JavaFX Text styling for dynamic objects - css

I'm using a ListView in my program with many, many styled Text's. Currently, I'm doing something like this
case COMMENT:
t = new Text(lexer.comment.toString());
t.setStyle(BASE_STYLE + COMMENT_STYLE);
where the style is stored as java string. I do have a global.css in my application which is used to style some static nodes of the scene, but for the programatically created texts I don't know how to access this. I tried using t.setId(..) and put a style definition in the css file but this doesn't work.
Is there a way that I can store all styles for my different text types in one css and access them easily? Note that I'm creating many of those text objects.

There are three ways to apply CSS styling to a JavaFX Node (or a combination of them):
As Tom mentioned, a Nodes css style classes are accessed via Node.getStyleClass(). This returns an ObservableList where you can add and remove your style classes.
If you change a Nodes style rather often, it is better to use pseudo selectors, like :hover or :active with Node.pseudoClassStateChanged().
The third option you already discovered (setStyle()), but I dislike this option because moving the CSS parts into a seperate file offers many advantages.
For #1 and #2 you need to attach a Stylesheet to the Scene/Node, with Scene.getStylesheets() or Parent.getStylesheets(), where your CSS definitions are stored. For example:
listView.getStylesheets().add(getClass().getResource("myStyles.css").toExternalForm());
Addtional info for #1:
If you want to add the style-class my-node to a JavaFX Node:
node.getStyleClass().add("my-node");
now you can style that node in your CSS file:
.my-node {}
Addtional info for #2:
You can declare and use your own pseudo-class with
PseudoClass comment = PseudoClass.getPseudoClass("comment");
node.pseudoClassStateChanged(comment, true);
node.pseudoClassStateChanged(comment, false);
And in your css file:
.my-node:comment {}

Related

Using existing CSS selectors to apply styles across the Shadow DOM to custom elements

This question likely has no single direct answer, but hopefully will lead to some best practices or common patterns to use when adapting an existing styles framework to new web component development.
For my case, I have a component <custom-avatar>, and it's all set up properly with self-contained styles and functionality, everything is just peachy.
In certain use cases, the application display needs to stack avatars, just one slightly overtop one other at a diagonal, and the pattern I'm following is using a simple component <custom-composite-avatar>. All this does is wrap the slotted content in a <div> with the correct styling class, but key aspect is retaining the composability for flexible re-use, like so:
<custom-composite-avatar>
<custom-avatar title="first"></custom-avatar>
<custom-avatar title="second"></custom-avatar>
</custom-composite-avatar>
The tricky bit lies in the styles, which are imported from a monorepo that provides the same BEM-ish CSS and component CSS modules to other flavors of the component library like React, Vue, etc. I have the avatar and composite-avatar styles imported just fine, but forcing the intended overlap display is defined with the hierarchical selector .my-composite-avatar.my-composite-avatar--medium .my-avatar {}
So with .my-composite-avatar class applied to the div wrapper within <custom-composite-avatar> and the .my-avatar class applied to the wrapper within the <custom-avatar> and it's own Shadow DOM, that parent/child CSS selector is no good.
I doubt there is a silver bullet for this, but this seems like it will be a rather common scenario as more people migrate to Web Components while using existing styling systems. What approach makes the most sense to ensure that the composite component remains composable, and adaptation of existing selectors pain-free (or at least easy to communicate to other devs)? can this be solved with ::host or ::slotted, or will these cases require significant re-work?
Thanks for reading, your ideas are appreciated!
I would advice to become good friends with CSS properties
because they trickle down into shadowDOMs following CSS selectors.
CSS Custom Properties(variables)
and getPropertyValue
and setProperty if you want to be brutal and make Custom Elements change the outside world.
example
I have an <SVG-ICON> element taking configuration from attributes OR CSS properties
with my favorite lines of code:
let val = this.getAttribute(attr)
||
getComputedStyle(this)
.getPropertyValue("--svg-icon-" + attr)
.replace(/"/g, "")
.trim();
Allows for your standard attribute configuration:
<svg-icon name="configuration" fill="grey"></svg-icon>
But more powerful (simplified example):
<style>
body {
--svg-icon-fill: "grey";
}
svg-icon[selected] {
--svg-icon-fill: "green";
}
</style>
<svg-icon name="messages" selected></svg-icon>
<svg-icon name="configuration"></svg-icon>
CSS = Custom String Scripting
It doesn't often happen, but sometimes the simplest code makes me very happy.
There is no Styling restriction!
These 2 lines allow any String you want in CSS properties:
.replace(/"/g, "")
.trim();
Example
<style>
[name*="globe"] {
--svg-icon-tile: "rect:0,0,24,24,0,fill='blue'";
--svg-icon-stroke: white;
}
</style>
<svg-icon name="feather-icons-globe"></svg-icon>
The --svg-icon-tile has nothing to do with CSS, it is read (and parsed) by the <SVG-ICON> connectedCallback() code to generate a SVG background/tile for all icons named globe.
The double-quotes aren't required, but without them your IDE will complain about invalid CSS.
Have fun coding... you will pull some hairs when you start with calc() in your CSS properties...
But you can take 'CSS' to another level.
PS.
And monitor the future of ConstructAble StyleSheets aka ConstructIble StyleSheets aka Constructed Sheets aka AdoptedStyleSheets:
https://developers.google.com/web/updates/2019/02/constructable-stylesheets
https://chromestatus.com/feature/5394843094220800
iconmeister

Same style class for different components in Angular 6

I have css class which needs to be added to three different component(for example) which might not require for other components of our application.
which one would be the best approach.
add that css class to style.css (global css)and use it or
add it to three different component specific style sheet as it is not used anywhere in the application(is this considered as code duplicate ?)
Thanks!
I would say that adding it to the global styles is just fine for this purpose. View encapsulation is cool, but the cascading part of CSS is still something that we're supposed to take advantage of...just as long as you're still cognizant of keeping styles organized and not too high of specificity.
Conversely, if you knew all three components would share parent component, you could turn off view encapsulation for that component and add the class there, which is essentially the same as adding to global styles with the difference being the style would only be loaded when the component is loaded.
You could also use ::ng-deepon a parent component to target its children. Sass brings other solutions, but it doesn't look like you're using .scss files.

How to handle cq component with same html structure and different css?

I have 2 jsps for 2 cq components that have the same html structure but the css is different.
What are the best practices for refactoring in this case?
One scenario would be to have a single component and set the css classes based on some input provided by the author in the dialog (component type 1, component type 2), but this gets messy cause I need to do the if checks and set different values for the css classes. It becomes even more complicated if I add a 3rd component with the same html structure and different css.
I would suggest to use one of next approaches:
Create base component with html structure and for each design create components which have sling:resourceSuperType of base component. And in child components you can override css file with specific one.
Base component should be made of (at least) 2 jsp files:
container with some class (unique among different designs) which contains include of actual component content. This class then should be used in you selectors in css file. Like .container-design-1 .title {}. This container also can be overwritten in child components.
jsp with content.
Also you can still use component dialogue, but populate dropdown menu with available designs dynamically. For example, you can have some servlet+service which looks into repository and collects available clientlib categories for this component. And during rendering you will include selected clientlib category, set unique class for your container and use it in css selectors (like in previous approach).
Also in both cases html and id/class names of elements should be the same, and only styles implementation is different.

How to to customize GWT components style?

I'm developing a multi-module application using GWT 2.5.1. I'm not using any GWT theme. I want to customize the style for some of the GWT widgets, for example Button and CheckBox.
I see two solutions:
Write a CSS file loaded in the application (link in the HTML page). The CSS will contain CSS rules using GWT defined names, like .gwt-Button for buttons and .gwt-CheckBox, .gwt-CheckBox-disabled for checkboxes. This solution don't takes the advantage of CSS optimizations made by the GWT compiler.
Use a CssResource and set the style name each time I use a Button or a Checkbox. This solution will take advantage of CSS optimizations but it requires to set the style name every time I create a new Widget.
There are other solutions? Which is the correct one?
You can put those styles in a CssResource as well.
Just put #external on top of those styles in your css file, and you are good to go.
For example:
#external gwt-DatePicker;
.gwt-DatePicker {
...
}
Hope it helps.
Other solution: Button is html element button and Checkbox an html element input[type=checkbox]. So you could set styles on those elements and use css selectors for specific states. i.e. button:disabled. That way you won't have to set style names, or don't have lots of extra style names and use cleaner css.
You could subclass whatever widgets you want to style (e.g. MyButton), and have your subclass either just add a style name to each widget that gets created, or do the styling inline using calls to this.setWidth(), this.getElement().getStyle.setXXX.
Also, what optimizations does the GWT compiler perform on CSS? I know that it will obfuscate style names to avoid collisions, but I'm not sure CSS is even able to be optimized?
I would personally use emanuele's solution, but just to offer an alternative: you can use a widget's getElement() method to access style names directly, so if you really want to, you can override the style names with ones you created. This gets rather difficult, however, with larger widgets and panels that have multiple styles.

gwt how to use setStyleName(String style, boolean add) - for a gwt standard widget

I want to style/mark a MenuItem in GWT MenuBar. So i have some logic that adds a style name to a menu item (the logic is working properly).
mItem.setStyleName("menuItemMarked", true);
with this set getStyleName yields "gwt-MenuItem menuItemMarked" as expected.
But how to use/apply this style in css (at the moment i put css in uibinder.xml)? (as you may see i am not a css expert)
update: what i tried is that.
.menuItemMarked{background-color: yellow}
this is not working. if i call "inspect element"(chrome) i can see "class="gwt-MenuItem menuItemMarked" but i can not find the style "menuItemMarked" in the list of applied styles?!
Where are you specifying your CSS?
If your code is located within your code packages, it is likely being obfuscated by the GWT compiler. This applies to <ui:style> blocks in .ui.xml files, and .css files included in ClientBundles.
In this case, you will want to check out Programmatic Access to Inline Styles from the GWT docs. This will allow you to change your code to:
mItem.setStyleName(style.menuItemMarked(), true);
Alternatively, you can tell GWT to not obfuscate certain CSS classes. Here is a detailed answer to a similar question
Finally, if GWT does not touch your CSS file (it is being served from your server like other files), then you will need to make sure that your file is being included in your page properly. Your browser's dev tools should be able to help with that.
Make sure you specify correct selector name in your css. In this case you need to have following:
.gwt-MenuItem.menuItemMarked {
background-color: yellow;
}
Since gwt-MenuItem remains the first class name in the list it takes precedence over any styles (incl. background-color) defined in the subsequent classes. The only way to overrule this is to define styles with more specific selector like above. Check this link out for more detailed explanation.

Resources