javafx - easiest way of changing the caret color - css

I would like to set the caret color for all JavaFX text inputs (e.g. TextField, TextArea, the ones in ComboBox:editable, DatePicker, etc...)
I found this Stackoverflow answer: How to change the caret color in JavaFX 2.0?
... and an example on GitHub.
The first one does change the text and the caret color which is not good. The second one extends the TextFieldSkin class, which is already better, but how can I use it in CSS?
Any help is appreciated.
UPDATE 1:
I found the following CSS style property for JavaFX controls: -fx-skin.
This would theoretically allow me to set a custom skin class (-fx-skin: "package.MySkin";), however, the skin class just isn't used!
The class looks like the following:
package gui;
…
public class MyTextFieldSkin extends TextFieldSkin
{
public MyTextFieldSkin(TextField tf) {
super(tf);
System.out.println("MyTextFieldSkin constructor called!");
ReadOnlyObjectWrapper<Color> farbe = new ReadOnlyObjectWrapper<>(Color.green);
caretPath.strokeProperty().bind(farbe);
caretPath.setStrokeWidth(1.5);
}
}
… and is set in CSS like that:
.text-field {
-fx-skin: "gui.MyTextFieldSkin";
}
What am I doing wrong? I looked at the source code of AquaFX, and they are doing it the same way as me!

After a bit of try & error, I solved the problem in the following way:
I gathered all TextFields and controls that have TextFields in them (like ComboBox, DatePicker and so on) inside a container recursively (in deference of TitledPane, ScrollPane, SplitPane and TabPane, because they don't publish their children in getChildren(), so one has to call the getContent() method of the individual classes and scan through it).
After I had all the TextField controls, I looped over them and changed their Skin with the following code:
public class MyTextFieldSkin extends TextFieldSkin {
public MyTextFieldSkin(TextField tf)
{
super(tf);
ReadOnlyObjectWrapper<Color> color = new ReadOnlyObjectWrapper<>(Color.RED);
caretPath.strokeProperty().bind(color);
}
}
Then I just had to call
textfield.setSkin(new MyTextFieldSkin(textfield));
and that was about it.
Cheers

Related

Xamarin.Forms: use SVG images as icons on a TabbedPage

I want to use SVG images as icons on a TabbedPage in Xamarin.Forms for iOS.
The documentation for the TabbedPage class provides the following tip:
The TabbedRenderer for iOS has an overridable GetIcon method that can be used to load tab icons from a specified source. This override makes it possible to use SVG images as icons on a TabbedPage. In addition, selected and unselected versions of an icon can be provided.
I created the following class to perform the override:
[assembly: ExportRenderer(typeof(TabsRoot), typeof(TabbedPageCustomRenderer))]
namespace MyProject.iOS.Renderers
{
public class TabbedPageCustomRenderer : TabbedRenderer
{
protected override Task<Tuple<UIImage, UIImage>> GetIcon(Page page)
{
var image = UIImage.FromFile(#"home-black-18dp.svg");
return Task.FromResult(new Tuple<UIImage, UIImage>(image, image));
}
}
}
The accepted answer in this thread recommends creating a UIImage from an SVG file by doing something like this: var myImage = UIImage.FromFile(<<file name>>) where <<filename>> is an SVG. This other thread contradicts the previous thread, saying that UIImages cannot be made from SVG files. Sure enough, when I provide an SVG file, UIImage.FromFile() returns null and no icon is shown at all, just as the latter thread predicted. When I provide a PNG file, the override works as expected.
Another way I've tried to square this circle is to use the SvgCachedImage provided by FFImageLoading.Svg.Forms, but I haven't figured out how to 'wrap' a UIImage around an SvgCachedImage or whether that is even appropriate in this case.
Thank you for your help!
Add Xamarin.FFImageLoading.Svg nuget package to your ios project.
then create the UImage in your GetIcon method like below :
UIImage img = await ImageService.Instance
.LoadFile("timer.svg")
.WithCustomDataResolver(new SvgDataResolver((int)(TabBar?.Bounds.Height / 2 ?? 30), (int)(TabBar?.Bounds.Height / 2 ?? 30), false))
.AsUIImageAsync();
UIImage newImg = img.ImageWithRenderingMode(UIImageRenderingMode.AlwaysOriginal);

Specify a background image via CSS in Vaadin 14 programmatically with Java

In Vaadin 14, we can set some CSS values programmatically in our Java code.
We can call getElement, then getStyle, and set the name of the CSS property along with a value.
For example, here we set the background color to green.
public class MainView extends VerticalLayout
{
public MainView ( )
{
this.getElement().getStyle().set( "background-color" , "Green" );
How do we do this for a CSS property like background-image that takes an argument of the CSS function named url?
Hard-coding the CSS path does not work.
public class MainView extends VerticalLayout
{
public MainView ( )
{
this.getElement().getStyle().set( "background-image" , "cat.jpg" );
➥ In Vaadin Flow, how to do we use Java to get CSS to find an image such as "cat.jpg"?
Furthermore, what should be the relative or absolute path to that image file be? I understand that the usual place for static images in Vaadin web app is in the src/main/resources folder.
In case of a "Plain Java Servlet" (non-Spring, non-CDI) Vaadin project, the file should go under /src/main/webapp
In case of Spring: /src/main/resources/META-INF/resources/img
Taken from official docs here: Resource Cheat Sheet
And, as #symlink has noticed in the comments, you should use a url('filename') syntax to reference an image in css : CSS background-image Property
For example, if I have a file named cat.jpg inside a /src/main/webapp/images, then this sets it getElement().getStyle().set("background-image","url('images/cat.jpg')");
Here is another example, with the picture file cat.jpg in src/main/webapp without nesting in an images folder. This is a Vaadin 14.0.10 web app, using the Plain Java Servlet technology stack option on the Start a new project with Vaadin page.
Below is the source code for an entire view using this image as a background.
Notice the first line of the constructor, where we pass "url('cat.jpg')" as an argument. See how we used single-quote marks around the file name to embed in a Java string without escaping. Fortunately the CSS specification allows for either single quotes (') or double quotes (") — quite convenient for Vaadin programmers embedding CSS within Java code.
package work.basil.example;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.notification.Notification;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.router.Route;
import com.vaadin.flow.server.PWA;
/**
* The main view contains a button and a click listener.
*/
#Route ( "" )
#PWA ( name = "Project Base for Vaadin", shortName = "Project Base" )
public class MainView extends VerticalLayout
{
public MainView ( )
{
this.getElement().getStyle().set( "background-image" , "url('cat.jpg')" );
Button button = new Button( "Click me" , event -> Notification.show( "Clicked!" ) );
add( button );
}
}
And a screenshot of this web app in action. The image is cropped because of the short height of the VerticalLayout. The layout is short because it contains only a button, whose label Click me can be seen faintly in blue text on the left edge. The cropped cat’s face is repeated across the page as is the default with CSS.

A border issue of suggestboxPopup in GWT

I am using a SuggestBox in GWT.I also inherit the Standard theme from SuggestionBox.gwt.xml as
<inherits name='com.google.gwt.user.theme.standard.Standard'/>
so this are using default standard css for widget Suggestbox and it is making border through image as hborder.png,vborder.png etc..I want to remove this but my css is not working.
.gwt-SuggestBoxPopup{
border : 1px solid #000000;
}
so how can i solve this issue.Please help me.
Thanks Rahul
The class used for the popup is a DefaultSuggestionDisplay for default SuggestBox. It uses a DecoratedPopupPanel as you can see in SuggestBox.java around line 392.
To avoid "heavy" border, you have to create/override a SuggestionDisplay that uses a non-decorated popupPanel and pass it to your SuggestBox trough constructor
public SuggestBox(SuggestOracle oracle, TextBoxBase box,SuggestionDisplay suggestDisplay);
Say, "border" is not sufficient, because DecoratedPopupPanel uses multiple cells to set borders, as you seen in the CSS. So you probably can update CSS directly but it will apply to all project, as SuggestBox does not seems to handle resource bundle directly.
Create a customSuggestionDisplay class
public static class CustomSuggestionDisplay extends SuggestBox.DefaultSuggestionDisplay {
private PopupPanel suggestionPopupRef;
public CustomSuggestionDisplay() {
suggestionPopupRef = getPopupPanel();
}
public void removeBorder() {
((Element)suggestionPopupRef.getElement().getChild(0)).getStyle().setBackgroundColor("white");
NodeList<com.google.gwt.dom.client.Element> tdList = suggestionPopupRef.getElement().getElementsByTagName("td");
for (int tdIndex = 0; tdIndex < tdList.getLength(); ++tdIndex) {
Element tdElement = (Element) tdList.getItem(tdIndex);
if (tdElement.getClassName().startsWith("suggestPopup"))
tdElement.removeClassName(tdElement.getClassName());
}
}
}
Create a suggestBox object
SuggestOracle oracle = new RestSuggestOracle();
CustomSuggestionDisplay suggestionDisplay = new CustomSuggestionDisplay();
TextBox textfield = new TextBox();
SuggestBox m_field = new SuggestBox(oracle, textfield, suggestionDisplay);
Call removeBorder when the suggestion is displaying
if (m_field.isSuggestionListShowing())
suggestionDisplay.removeBorder();

Flex: Label.addChild() not working?

I want to make a label that has a tiny title above it, for example so the label say $1,000 with a small retail price or our price above it. I am trying to add the title label to the display list of the main label. I get no error but the title does not show up. I also considered rawChildren but apparently Label has no rawChildren property.
Here is my code:
package
{
import mx.controls.Label;
public class PriceLabel extends StrikeThroughLabel //<-- exntension of label to add strike
{
private var _title:Label;
public function PriceLabel()
{
super();
}
[Bindable]
public function set title(s:String):void
{
if(_title == null)
{
_title = new Label();
addChild(_title);
this.alpha = .2;
}
_title.text = s;
}
public function get title():String
{
var s:String
if(_title != null)
{
s = _title.text;
}
return s;
}
}
}
If you add children to a Flex component that is not a container, then you have to manually manage sizing and positioning of those children. Containers do a lot of that work for you.
Here's what you should do:
Move the creation of your child Label into an override of the createChildren() function.
Set the text property of the child label in an override of the commitProperties() function. Your title getter and setter should save the value in a _title variable to be used later for the assignment in commitProperties(). This is actually important for performance.
Override the measure() function and update measuredWidth and measuredHeight to be the maximum width and height values of the main label and it's child.
Override updateDisplayList() and use setActualSize() on the child Label to set it to the required width and height.
That may seem like a lot of work, but in terms of best practices, that's the way you're supposed to build custom components. The Flex Team at Adobe spent a lot of time maximizing performance, and that's why things happen in several steps like that.
That's how to do it based on what you asked. Personally, I would make a subclass of UIComponent with two Labels or UITextFields as children, each with their own separate property.
By the way, the rawChildren property is only available on containers. It exists so that you can add "chrome" to a container that isn't part of the container's child layout algorithm. For example, Panel has a title bar and a border that aren't affected by the vertical/horizontal/absolute layout options.
Why not create a custom component that contains both labels as its children, instead of trying to throw a child on the Label? That feels cleaner to me, as adding children to build-in components like that doesn't seem right.

How can I change the size of icons in the Tree control in Flex?

I embed SVG graphics in my Flex application using
package MyUI
{
public class Assets
{
[Embed(source="/assets/pic.svg"]
[Bindable]
public static var svgPic:Class;
}
}
and then extending the Tree class with some of my own code, setting the icon upon adding a node to the data provider:
public class MyTree extends Tree
{
public function MyTree()
{
// ...
this.iconField = "svgIcon";
// ...
this.dataProvider = new ArrayCollection;
this.dataProvider.addItem({ /* ... */ svgIcon: MyUI.Assets.svgPic /* ... */ });
// ...
}
}
Now I have two things I want to do:
use the SVG graphics in multiple places in the app, scaling them to the appropriate size for each appearance, i. e. scale them to a proper icon size when using them in the tree
change the size of the icon at runtime, e. g. display a slightly larger icon for selected items or let an icon "pulse" as a response to some event
I read the Flex documentation on the 9-slice scaling properties in the Embed tag, but I think that's not what I want.
Edit:
I unsuccessfully checked the "similar questions" suggested by SO, among others this one:
Flex: Modify an embedded icon and use it in a button?
Subclass mx.controls.treeClasses.TreeItemRenderer and make it resize the icon to your desired dimensions, or create your own item renderer implementation by using the same interfaces as TreeItemRenderer. Set a custom item renderer with the itemRenderer property:
exampleTree.itemRenderer = new ClassFactory( ExampleCustomItemRendererClass );
The answer to this question might point you in the right direction, without knowing more about the trouble you're having:
Flex: Modify an embedded icon and use it in a button?
Hope it helps!

Resources