Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding support for borders to UILabel and UIButton (via CALayer and t… #1956

Merged
merged 1 commit into from
Feb 14, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 22 additions & 32 deletions Frameworks/QuartzCore/CALayer.mm
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,6 @@ static void DoDisplayList(CALayer* layer) {
_undefinedKeys = nil;
_actions = nil;
CGColorRelease(_backgroundColor);
CGColorRelease(_borderColor);
_name = nil;
if (_animations) {
[_animations release];
Expand Down Expand Up @@ -1582,64 +1581,55 @@ - (CGColorRef)backgroundColor {
return priv->_backgroundColor;
}

- (void)_setContentColor:(CGColorRef)newColor {
UNIMPLEMENTED();
}

/**
@Status Stub
@Status Interoperable
*/
- (void)setBorderColor:(CGColorRef)color {
UNIMPLEMENTED();
if (color != nil) {
priv->borderColor = *[static_cast<UIColor*>(color) _getColors];
} else {
_ClearColorQuad(priv->borderColor);
}

CGColorRef old = priv->_borderColor;
priv->_borderColor = CGColorRetain(color);
CGColorRelease(old);
// Set the border color via CATransaction
[CATransaction _setPropertyForLayer:self name:@"borderColor" value:(NSObject*)color];
[self setNeedsDisplay];
}

/**
@Status Stub
@Status Interoperable
*/
- (CGColorRef)borderColor {
UNIMPLEMENTED();
return priv->_borderColor;
// Grab the current border color directly off of the layer proxy
return [(UIColor*)priv->_layerProxy->GetPropertyValue("borderColor") CGColor];
}

/**
@Status Stub
@Status Interoperable
*/
- (void)setBorderWidth:(float)width {
UNIMPLEMENTED();
priv->borderWidth = width;
// Set the border width via CATransaction
[CATransaction _setPropertyForLayer:self name:@"borderWidth" value:[NSNumber numberWithFloat:width]];
[self setNeedsDisplay];
}

/**
@Status Stub
@Status Interoperable
*/
- (float)borderWidth {
UNIMPLEMENTED();
return priv->borderWidth;
// Grab the current border width directly off of the layer proxy
return [(NSNumber*)priv->_layerProxy->GetPropertyValue("borderWidth") floatValue];
}

/**
@Status Stub
@Status NotInPlan
@Notes Rounded corners with clipped children are not currently achievable in Xaml.
*/
- (void)setCornerRadius:(float)radius {
UNIMPLEMENTED();
priv->cornerRadius = radius;
UNIMPLEMENTED_WITH_MSG("Rounded corners with clipped children are not achievable in Xaml.");
}

/**
@Status Stub
@Status NotInPlan
@Notes Rounded corners with clipped children are not currently achievable in Xaml.
*/
- (float)cornerRadius {
UNIMPLEMENTED();
return priv->cornerRadius;
UNIMPLEMENTED_WITH_MSG("Rounded corners with clipped children are not achievable in Xaml.");
return StubReturn();
}

/**
Expand Down Expand Up @@ -2518,7 +2508,7 @@ + (CGRect)convertRect:(CGRect)pos fromLayer:(CALayer*)fromLayer toLayer:(CALayer
return ret;
}

- (NSObject*)presentationValueForKey:(NSString*)key {
- (NSObject*)_presentationValueForKey:(NSString*)key {
return reinterpret_cast<NSObject*>(priv->_layerProxy->GetPropertyValue([key UTF8String]));
}

Expand Down
10 changes: 10 additions & 0 deletions Frameworks/UIKit.Xaml/Button.xaml.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,16 @@ Canvas^ Button::SublayerCanvas::get() {
return _contentCanvas;
}

// Accessor for the LayerProperty that manages the BorderBrush of this button
Private::CoreAnimation::LayerProperty^ Button::GetBorderBrushProperty() {
return ref new Private::CoreAnimation::LayerProperty(_border, _border->BorderBrushProperty);
}

// Accessor for the LayerProperty that manages the BorderThickness of this button
Private::CoreAnimation::LayerProperty^ Button::GetBorderThicknessProperty() {
return ref new Private::CoreAnimation::LayerProperty(_border, _border->BorderThicknessProperty);
}

void Button::OnPointerPressed(PointerRoutedEventArgs^ e) {
// Call the pointer hook if it exists
if (_pointerPressedHook) {
Expand Down
6 changes: 6 additions & 0 deletions Frameworks/UIKit.Xaml/Button.xaml.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,12 @@ public ref class Button sealed : public Private::CoreAnimation::ILayer {
Windows::UI::Xaml::Controls::Canvas^ get();
}

// Accessor for the LayerProperty that manages the BorderBrush of this button
virtual Private::CoreAnimation::LayerProperty^ GetBorderBrushProperty();

// Accessor for the LayerProperty that manages the BorderThickness of this button
virtual Private::CoreAnimation::LayerProperty^ GetBorderThicknessProperty();

internal:
void HookPointerEvents(
const Microsoft::WRL::ComPtr<ABI::Windows::UI::Xaml::Input::IPointerEventHandler>& pointerPressedHook,
Expand Down
35 changes: 34 additions & 1 deletion Frameworks/UIKit.Xaml/Label.xaml.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,45 @@ Canvas^ Label::SublayerCanvas::get() {
if (!_sublayerCanvas) {
_sublayerCanvas = ref new Canvas();
_sublayerCanvas->Name = "Sublayers";
Children->Append(_sublayerCanvas);

// If we have a border make sure the sublayer canvas is inserted before it
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this to make sure that border's zindex is bigger than sublayer thus display on top?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes

if (_border) {
unsigned int insertIndex = 0;
Children->IndexOf(_border, &insertIndex);
Children->InsertAt(insertIndex, _sublayerCanvas);
} else {
// Just add the sublayer canvas to the end because we don't yet have a border on this element
Children->Append(_sublayerCanvas);
}
}

return _sublayerCanvas;
}

Border^ Label::_GetBorder() {
if (!_border) {
// We always want the border added to the end of the Children collection
_border = ref new Border();
Children->Append(_border);
}

return _border;
}

// Accessor for the LayerProperty that manages the BorderBrush of this label
Private::CoreAnimation::LayerProperty^ Label::GetBorderBrushProperty() {
// Make sure we have a border element, and return it along with its associated border property
Border^ border = _GetBorder();
return ref new Private::CoreAnimation::LayerProperty(border, border->BorderBrushProperty);
}

// Accessor for the LayerProperty that manages the BorderThickness of this label
Private::CoreAnimation::LayerProperty^ Label::GetBorderThicknessProperty() {
// Make sure we have a border element, and return it along with its associated border property
Border^ border = _GetBorder();
return ref new Private::CoreAnimation::LayerProperty(border, border->BorderThicknessProperty);
}

Windows::Foundation::Size Label::ArrangeOverride(Windows::Foundation::Size finalSize) {
// Make sure we render vertically-centered text if possible, else cap at the containing layer's height.
// TODO: Issue #1946: Do we actually need this call to Measure?
Expand Down
9 changes: 9 additions & 0 deletions Frameworks/UIKit.Xaml/Label.xaml.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,15 +44,24 @@ public ref class Label sealed : public Private::CoreAnimation::ILayer {
Windows::UI::Xaml::Controls::Canvas^ get();
}

// Accessor for the LayerProperty that manages the BorderBrush of this label
virtual Private::CoreAnimation::LayerProperty^ GetBorderBrushProperty();

// Accessor for the LayerProperty that manages the BorderThickness of this label
virtual Private::CoreAnimation::LayerProperty^ GetBorderThicknessProperty();

internal:
property Windows::UI::Xaml::Controls::TextBlock^ TextBlock {
Windows::UI::Xaml::Controls::TextBlock^ get();
}

private:
Windows::UI::Xaml::Controls::Border^ _GetBorder();

// Layer elements; created on demand
Windows::UI::Xaml::Controls::Image^ _content;
Windows::UI::Xaml::Controls::Canvas^ _sublayerCanvas;
Windows::UI::Xaml::Controls::Border^ _border;
};

} /* Xaml*/
Expand Down
25 changes: 25 additions & 0 deletions Frameworks/UIKit.Xaml/Layer.xaml.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,19 @@ DependencyProperty^ Layer::s_layerContentProperty = nullptr;
DependencyProperty^ Layer::s_sublayerCanvasProperty = nullptr;
bool Layer::s_dependencyPropertiesRegistered = false;

LayerProperty::LayerProperty(DependencyObject^ target, DependencyProperty^ property) : _target(target), _property(property) {
}

void LayerProperty::SetValue(Platform::Object^ value) {
// Set the specified value on our underlying target/property pair
_target->SetValue(_property, value);
}

Platform::Object^ LayerProperty::GetValue() {
// Retrieve the current value from our underlying target/property pair
return _target->GetValue(_property);
}

Layer::Layer() {
InitializeComponent();

Expand Down Expand Up @@ -72,6 +85,18 @@ Canvas^ Layer::SublayerCanvas::get() {
return this;
}

// Accessor for the LayerProperty that manages the BorderBrush of this layer
LayerProperty^ Layer::GetBorderBrushProperty() {
// We don't support borders on basic layers yet, because Canvas doesn't support one intrinsically
return nullptr;
}

// Accessor for the LayerProperty that manages the BorderThickness of this layer
LayerProperty^ Layer::GetBorderThicknessProperty() {
// We don't support borders on basic layers yet, because Canvas doesn't support one intrinsically
return nullptr;
}

DependencyProperty^ Layer::LayerContentProperty::get() {
return s_layerContentProperty;
}
Expand Down
27 changes: 27 additions & 0 deletions Frameworks/UIKit.Xaml/Layer.xaml.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,21 @@ namespace Xaml {
namespace Private {
namespace CoreAnimation {

// Pairs a DependencyProperty and its associated DependencyObject for setting/getting values on objects within an ILayer instance.
// For example, can wrap an internal FrameworkElement and its associated BorderBrushProperty.
[Windows::Foundation::Metadata::WebHostHidden]
public ref class LayerProperty sealed {
public:
LayerProperty(Windows::UI::Xaml::DependencyObject^ target, Windows::UI::Xaml::DependencyProperty^ property);

void SetValue(Platform::Object^ value);
Platform::Object^ GetValue();

private:
Windows::UI::Xaml::DependencyObject^ _target;
Windows::UI::Xaml::DependencyProperty^ _property;
};

[Windows::Foundation::Metadata::WebHostHidden]
public interface class ILayer {
public:
Expand All @@ -41,6 +56,12 @@ public interface class ILayer {
property Windows::UI::Xaml::Controls::Canvas^ SublayerCanvas {
Windows::UI::Xaml::Controls::Canvas^ get();
}

// Accessor for the LayerProperty that manages the BorderBrush of this layer
LayerProperty^ GetBorderBrushProperty();

// Accessor for the LayerProperty that manages the BorderThickness of this layer
LayerProperty^ GetBorderThicknessProperty();
};

[Windows::Foundation::Metadata::WebHostHidden]
Expand All @@ -63,6 +84,12 @@ public ref class Layer sealed : public ILayer {
Windows::UI::Xaml::Controls::Canvas^ get();
}

// Accessor for the LayerProperty that manages the BorderBrush of this layer
virtual LayerProperty^ GetBorderBrushProperty();

// Accessor for the LayerProperty that manages the BorderThickness of this layer
virtual LayerProperty^ GetBorderThicknessProperty();

// Allows arbitrary framework elements to opt-into hosting layer content
static property Windows::UI::Xaml::DependencyProperty^ LayerContentProperty {
Windows::UI::Xaml::DependencyProperty^ get();
Expand Down
Loading