How to construct Windows::UI::Xaml::Style class programmatically - winrt-xaml

I'm trying to programmatically construct a winrt::Windows::UI::Xaml::Style object for all buttons. But, some of the style Setter doesn't work I expect.
In summary, Setters for BorderThickness, BorderBrush, Foreground and Margin properties doesn't work. On the other hand, Setters for FontSize and Background properties work right. How can I correct this matter.
a Style object is constructed like this code.
void MainPage::SetStylePropertySetters()
{
coloredButtonStyle.Setters().Append(Setter{ // doesn't work
Control::BorderThicknessProperty(),
box_value(ThicknessHelper::FromUniformLength(10.5)) });
coloredButtonStyle.Setters().Append(Setter{ // doesn't work
Control::BorderBrushProperty(),
box_value(Colors::Black()) });
coloredButtonStyle.Setters().Append(Setter{ // works right
Control::FontSizeProperty(),
box_value(50) });
coloredButtonStyle.Setters().Append(Setter{ // doesn't work
Control::ForegroundProperty(),
box_value(Colors::White()) });
coloredButtonStyle.Setters().Append(Setter{ // doesn't work
FrameworkElement::MarginProperty(),
box_value(ThicknessHelper::FromLengths(10, 10, 0, 0)) });
coloredButtonStyle.Setters().Append(Setter{ // works right
Control::BackgroundProperty(),
GenerateGradient() });
}
LinearGradientBrush MainPage::GenerateGradient()
{
GradientStopCollection gradientStopCollection{};
GradientStop gs1;
gs1.Color(Colors::Yellow());
gs1.Offset(0);
gradientStopCollection.Append(gs1);
GradientStop gs2;
gs2.Color(Colors::Orange());
gs2.Offset(0.5);
gradientStopCollection.Append(gs2);
GradientStop gs3;
gs3.Color(Colors::Red());
gs3.Offset(1.0);
gradientStopCollection.Append(gs3);
return LinearGradientBrush(gradientStopCollection, 0.0);
}
Then the style is applied to a button in the constructor of the MainPage.
MainPage::MainPage() :
coloredButtonStyle{ xaml_typename<Button>() }
{
InitializeComponent();
// Apply a style to a button named DefaultButton
SetStylePropertySetters();
DefaultButton().Style(coloredButtonStyle);
}
The main page has one button named DefaultButton.
<Page
x:Class="HeadedAppDesign.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:HeadedAppDesign"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<StackPanel>
<Button x:Name="DefaultButton" Content="Button"/>
</StackPanel>
</Page>
This produces the following result:

For Thickness type properties, pass string object as the same
format in XAML markup. And for Brush type properties, pass one of the derived class object of Brush class.
void MainPage::SetStylePropertySetters()
{
coloredButtonStyle.Setters().Append(Setter{
Control::BorderThicknessProperty(),
box_value(L"10.5") });
coloredButtonStyle.Setters().Append(Setter{
Control::BorderBrushProperty(),
SolidColorBrush(Colors::Black()) });
coloredButtonStyle.Setters().Append(Setter{
Control::FontSizeProperty(),
box_value(50) });
coloredButtonStyle.Setters().Append(Setter{
Control::ForegroundProperty(),
SolidColorBrush(Colors::White()) });
coloredButtonStyle.Setters().Append(Setter{
FrameworkElement::MarginProperty(),
box_value(L"10, 10, 0, 0") });
coloredButtonStyle.Setters().Append(Setter{
Control::BackgroundProperty(),
GenerateGradient() });
}
The margin, border width and color, font size and color and background gradient of the button all applied as I expected.

Related

Chrome extension tooltip over text(one word)

I'd like to implement a tooltip dictionary chrome extension. When the user hover the mouse over a chunk or a word in text, It should show the block selection or change its background color and show the tooltip under the word.
How can I implement it?
I just did similar thing with background like this:
core.js
// Unique ID for the className.
var MOUSE_VISITED_CLASSNAME = 'crx_mouse_visited';
// Previous dom, that we want to track, so we can remove the previous styling.
var prevDOM = null;
// Mouse listener for any move event on the current document.
document.addEventListener('mousemove', function (e) {
var srcElement = e.srcElement;
// Lets check if our underlying element is a DIV.
if (srcElement.nodeName == 'DIV' || srcElement.nodeName == 'SPAN') {
// For NPE checking, we check safely. We need to remove the class name
// Since we will be styling the new one after.
if (prevDOM != null) {
prevDOM.classList.remove(MOUSE_VISITED_CLASSNAME);
}
// Add a visited class name to the element. So we can style it.
srcElement.classList.add(MOUSE_VISITED_CLASSNAME);
// The current element is now the previous. So we can remove the class
// during the next iteration.
prevDOM = srcElement;
}
}, false);
core.css
.crx_mouse_visited {
background-color: #bcd5eb !important;
outline: 1px solid #5166bb !important;
}

Modal View Popover: Always full screen?

I've created a view. and show from bottom with height 200
I'm using the following code to present it (in a touch event):
var pvc = Storyboard.InstantiateViewController("demoStoryboard") as ModalViewController;
pvc.View.Frame = new CGRect(0, this.View.Frame.Height - 200, this.View.Frame.Width, 200);
pvc.ModalPresentationStyle = UIModalPresentationStyle.Custom;
pvc.ModalTransitionStyle = UIModalTransitionStyle.CoverVertical;
this.PresentViewController(pvc, true, null);
When it's presented, though, it always fills the screen, instead of having a height of just 200.
I've tried changing the ModalPresentationStyle property, but it makes no difference.
how can i fix it?
Even you set the Frame for the View of ModalViewController as,
pvc.View.Frame = new CGRect(0, this.View.Frame.Height - 200, this.View.Frame.Width, 200);
Inside ModalViewController, between ViewWillAppear and ViewDidAppear methods, the Frame property value is changing. It's because ViewWillLayoutSubviews method is called in between ViewWillAppear and ViewDidAppear methods. This method, ViewWillLayoutSubviews is where the Frame property is actually been set. It sets the default value for the Frame property, that is the full screen size. So this is the method where you should set your custom Frame property value so that the default value is overridden.
That is, inside ModalViewController,
public override void ViewWillLayoutSubviews()
{
base.ViewWillLayoutSubviews();
View.Frame = new CGRect(0, View.Frame.Height - 200, View.Frame.Width, 200);
}
And you can avoid setting the Frame property value in the parent view controller. That is,
pvc.View.Frame = new CGRect(0, this.View.Frame.Height - 200, this.View.Frame.Width, 200);
can be removed.

Xamarin iOS : Center UILabel inside UICollectionView Header created programmatically

The solution for centering any subview within a parent is usually simple, however, it doesn't seem to work in my case.
I'm working with a UICollectionView and have added a Header class programmatically. I have this constructor, where I also try to center the label within the screen:
[Export("initWithFrame:")]
public Header(System.Drawing.RectangleF frame) : base(frame)
{
label = new UILabel
{
Frame = new System.Drawing.RectangleF(frame.Size.Width / 2, 50, 200, 50),
BackgroundColor = UIColor.Clear,
TextColor = UIColor.White,
Font = UIFont.FromName("HelveticaNeueLTStd-ThCn", 35f),
Text = DateTime.Now.ToString("Y")
};
AddSubview(label);
}
And I initialize the class inside the UICollectionViewSource 's constructor like this:
public MyCollectionViewDataSource(MainController mainController, DateTime currentDate)
{
try
{
controller = mainController;
new Header(new RectangleF(0, 0, (float)mainController.View.Frame.Size.Width, 200));
}
catch (Exception ex)
{
Console.WriteLine(ex.Message + ex.StackTrace);
}
}
What exactly am I missing because this usually works in other instances but seems to fail here?
This is what it looks like :
I found an explanation here iOS Layout Gotchas by Adam Kemp which helped me resolve this issue.
The first solution
One very common mistake I made was adding the layout definition code in the constructor, instead of doing it in the rightful place : the LayoutSubviews override in this case.
Giving the label the frame size in the constructor assumes a static size set at the time of construction, which may later change depending on the screen size.
The second solution
He explains that :
Frame sets the position of a view within its parent while Bounds is in the coordinate system of the view itself (not its parent).
So, to center the UILabel, I used bounds and center together and this worked for me.
[Export("initWithFrame:")]
public Header(CGRect bounds) : base(bounds)
{
label = new UILabel
{
BackgroundColor = UIColor.Clear,
TextColor = UIColor.White,
Font = UIFont.FromName("HelveticaNeueLTStd-ThCn", 35f),
Text = DateTime.Now.ToString("Y"),
TextAlignment = UITextAlignment.Center
};
rectangle = bounds;
AddSubview(label);
}
public override void LayoutSubviews()
{
base.LayoutSubviews();
label.Bounds = new CGRect (rectangle.Size.Width / 2, 50, 200, 50);
label.Center = new PointF((float)rectangle.Size.Width/2,50);
}

Color of texture skybox unity

I'm working with google cardboard in unity.
In my main scene I have a skybox with an image as texture.
How can I get the color of the pixel I'm looking?
The skybox is an element of mainCamera, that is child of "Head".
I put also GvrReticle as child of head; is it useful for my purpose?
Thanks
Basically you wait for the end of the frame so that the camera has rendered. Then you read the rendered data into a texture and get the center pixel.
edit Be aware that if you have a UI element rendered in the center it will show the UI element color not the color behind.
private Texture2D tex;
public Color center;
void Awake()
{
StartCoroutine(GetCenterPixel());
}
private void CreateTexture()
{
tex = new Texture2D(1, 1, TextureFormat.RGB24, false);
}
private IEnumerator GetCenterPixel()
{
CreateTexture();
while (true)
{
yield return new WaitForEndOfFrame();
tex.ReadPixels(new Rect(Screen.width / 2f, Screen.height / 2f, 1, 1), 0, 0);
tex.Apply();
center = tex.GetPixel(0,0);
}
}

JavaFX 2.0 - How to change legend color of a LineChart dynamically?

I am trying to style my JavaFX linechart but I have some trouble with the legend.
I know how to change the legend color of a line chart in the css file:
.default-color0.chart-series-line { -fx-stroke: #FF0000, white; }
.default-color1.chart-series-line { -fx-stroke: #00FF00, white; }
.default-color2.chart-series-line { -fx-stroke: #0000FF, white; }
.default-color0.chart-line-symbol { -fx-background-color: #FF0000, white; }
.default-color1.chart-line-symbol { -fx-background-color: #00FF00, white; }
.default-color2.chart-line-symbol { -fx-background-color: #0000FF, white; }
But this is not enough for my purposes. I have three or more colored toggle buttons and a series of data for every button. The data should be displayed in the same color the button has after I have selected the button. This should be possible with a multiselection of the buttons, so that more than one series of data can be displayed simultaneously.
For the chart lines I have managed it by changing the style after I clicked the button:
..
dataList.add(series);
..
series.getNode().setStyle("-fx-stroke: rgba(" + rgba + ")");
If I deselect the button I remove the data from the list.
dataList.remove(series);
That is working fine for the strokes, but how can I do the same for the legend?
You can see an example below. First I clicked the red button, thus the stroke and the legend is red (default-color0). After that I clicked the blue button. Here you can see the problem. The stroke is blue but the legend is green, because default color1 is used and I do not know how to change the legend color.
I ran into this issue as well. The issue seems to be that when data series are added to the chart, the legend isn't updated at the same time, so when you lookup components with that seriesN style class they don't exist yet. Came up with a work-around that detects when the legend items are created so that dynamic styling can be added to them.
I added a ListChangeListener to the chart legend's "getChildrenUnmodifiable()" ObservableList, which in turn adds a ListChangeListener to each of the legend's children as they get added. From within this listener, we can tell when new items are being added to the legend (or removed). This allow us to then make the dynamic style changes.
for (Node n : lineChart.getChildrenUnmodifiable())
{
if (n instanceof Legend)
{
final Legend legend = (Legend) n;
// remove the legend
legend.getChildrenUnmodifiable().addListener(new ListChangeListener<Object>()
{
#Override
public void onChanged(Change<?> arg0)
{
for (Node node : legend.getChildrenUnmodifiable())
{
if (node instanceof Label)
{
final Label label = (Label) node;
label.getChildrenUnmodifiable().addListener(new ListChangeListener<Object>()
{
#Override
public void onChanged(Change<?> arg0)
{
//make style changes here
}
});
}
}
}
});
}
}
For future reference, this problem can be solved by wrapping your relevant code in a call to Platform.runLater(). For example:
LineChart<Number, Number> plot;
....
Platform.runLater(() -> {
Node nl = plot.lookup(".default-color0.chart-series-line");
Node ns = plot.lookup(".default-color0.chart-line-symbol");
nl.setStyle("-fx-stroke: #333;");
ns.setStyle("-fx-background-color: #333, white;");
});
It seems that this guy is able to lookup the nodes used for legend using their class, and then calling setStyle() on those nodes. (I don't think his problem is relevant for yours)
This solution is based on #Chris' solution
if (checkCombo.getCheckModel().isChecked(0)) {
lineChart.getData().add(seriesTest1);
changeColorSeries(lineChart.getData().size() - 1, "darkgreen");
}
if (checkCombo.getCheckModel().isChecked(3)) {
lineChart.getData().add(seriesTest2);
changeColorSeries(lineChart.getData().size() - 1, "darkred");
}
private void changeColor(int position, String color) {
Platform.runLater(() -> {
Node nl = lineChart.lookup(".default-color" + position + ".chart-series-line");
Node ns = lineChart.lookup(".default-color" + position + ".chart-line-symbol");
Node nsl = lineChart.lookup(".default-color" + position + ".chart-legend-item-symbol");
nl.setStyle("-fx-stroke: " + color + ";");
ns.setStyle("-fx-background-color: " + color + ", white;");
nsl.setStyle("-fx-background-color: " + color + ", white;");
});
}
After digging a lot through google with no success I finally found a lean way to update the legend colors according line color through this method:
private void setLegendItemColor(String shop, String color, Legend lg) {
for (Node n : lg.getChildren()) {
Label lb = (Label) n;
if (lb.getText().contains(shop)) {
lb.getGraphic().setStyle("-fx-background-color:" + color + ";");
}
}
}
So you just need to call the method setLegendItemColor() when you´re going to update the chart lines to update the legend label symbols to the correspondent color.

Resources