DataGrid / CellTable styling frustration -- overriding row styles - css

I'm trying mightily to style my GWT 2.4 DataGrid, and hit roadblocks at every turn. I've added the following row styling to my DataGrid:
dataTable.setRowStyles(new RowStyles<IntegrityItem>() {
#Override
public String getStyleNames(IntegrityItem row, int rowIndex) {
if (row.getSomeValue() >= 100) {
return MyResources.INSTANCE.mystyles().alertRow();
} else {
return "";
}
}
});
The style alertRow is simply this:
.alertEntry {
font-weight: bold;
color: #00ff00;
background-color: #ff0000;
}
More information: I've made a local copy of DataGrid.css and removed ALL "background" elements from all the styles, and I've used this to construct a ClientBundle:
public interface MyDataGridResources extends DataGrid.Resources {
public static final FmeaDataGridResources INSTANCE = GWT.create(MyDataGridResources.class);
#Override
#Source({"../resources/styling/mydatagridstyles.css"})
Style dataGridStyle();
}
I've used this (MyDataGridResources.INSTANCE) in my DataGrid constructor.
When I try it out, the rows that meet the criteria contained green (#00ff00) text, but the background colour remains white or grey depending on whether it is an even row or an odd row. How is it that background-color is ignored the way it is? Where is it getting those colors in the first place?! I've removed background color information from the css file completely.

You can create a custom CSS file and provide this to the DataGrid through defining a new style resource. This is done by creating a type that extends DataGrid.Resources, which knows about your CSS file. You then pass this to the constructor of the datagrid.
To provide a fairly complete example, first create a new type for the DataGrid style. (Defining a new type like this just uniquely identifies your style within GWT).
public interface MyStyle extends DataGrid.Style {
}
Then, define an interface which overrides the dataGridStyle() method stub in DataGrid.Resources. The dataGridStyle method should return the previously defined MyStyle.
Note the two elements given to the #Source annotation - you can just override any of the class names in the default CSS (DataGrid.css) in the second file you provide ("DataGridOverride.css" here).
public interface DataGridResource extends DataGrid.Resources {
#Source({ DataGrid.Style.DEFAULT_CSS, "DataGridOverride.css" })
MyStyle dataGridStyle();
};
To construct your newly-styled datagrid all you need to do is:
DataGridResource resource = GWT.create(DataGridResource.class);
dataGrid = new DataGrid<T>(pageSize, resource)
One subtlety is as you're increasing the precedence of the overridden styles, you may need to override any other styles that require higher precedence, for example the row hover rules need to come after the row styling rules.

See http://code.google.com/p/google-web-toolkit/issues/detail?id=6144#c3 (which is not a bug!)
In short extend the DataGrid.Style (the goal is only to have a new type, you don't have to add anything to it) and have your dataGridStyle overridden method return your own subtype rather than DataGrid.Style (and it'll work because of return-type covariance)

Related

Which CSS selector is used when a DragOver event is detected?

I am creating a custom RowFactory for my TableView to accept drag-and-drop files. I want to update the style of the specific Row when an acceptable DragOver event is detected.
Using :hover obviously won't work because that would apply even if the user is not dragging anything.
The end goal is simply to make it visually clear which row the user is about to drop the items onto.
Is there a selector I can use in my stylesheet to handle this? I could not find anything in the JavaFX CSS Reference Guide.
I can currently work around this by defining my own StyleClass and adding it in the setOnDragOver() method:
setOnDragOver(event -> {
// Determine if the dragged items are files
if (!this.isEmpty() && event.getDragboard().hasFiles()) {
event.acceptTransferModes(TransferMode.LINK);
this.getStyleClass().add("dragging");
}
});
However, attempting to remove the class when exiting does not seem to work:
setOnDragExited(event -> this.getStyleClass().remove("dragging"));
Edit: I should also clarify that each row may have other styles applied to them (based on several factors) and would want to ADD a style to the row when being dragged over, not replace all the rest)
As mentioned by #kleopatra, working with custom PseudoClass can work for you.
/**
* Interface to keep all custom pseudo classes.
*/
public interface Styles{
/** Dragged pseudo class. */
public static final PseudoClass DRAGGED_PSEUDOCLASS = PseudoClass.getPseudoClass("dragged");
}
In your code:
setOnDragOver(event -> {
if (!this.isEmpty() && event.getDragboard().hasFiles()) {
event.acceptTransferModes(TransferMode.LINK);
this.pseudoClassStateChanged(Styles.DRAGGED_PSEUDOCLASS,true);
}
});
setOnDragExited(event -> this.pseudoClassStateChanged(Styles.DRAGGED_PSEUDOCLASS,false));
In CSS:
.table-row-cell:dragged{
-fx-background-color:$custom-color;
}

How to dynamically generate CSS class and/or set its property

The title is not really a question it is more like an idea, I don't know what approach is best for my situation.
So, the problem. I have some 3rd party component that have some complex structure and styling. Some part of it has some predefined CSS class that I can override with CSS in my surrounding component. Something like this:
my component:
<div class="my-cmp-container">
<some-3rd-party-cmp></some-3rd-party-cmp>
</div>
3rd party component:
<div class="3rd-party-css-class">
...
</div>
For example, 3rd-party-css-class has style background-color: #f00, I can override it with .my-cmp-container .3rd-party-css-class { background-color: #fff; } etc. But. What if I need to set color dynamically, it's stored in a DB for example and I can't predefine each case in my class' CSS. I just have the color in hex.
In theory I can generate unique string to set as CSS class for every instance of some-3rd-party-cmp and somehow generate CSS in my component? I'm lost a little, what is the best approach for this?
Edit: Code sample to illustrate the situation https://stackblitz.com/edit/angular-kxdatq
What you are trying to do is the subject of this open issue about stylesheet binding in Angular. Until that feature is available, you can get what you want with a custom directive. Here is a directive that retrieves the checkbox element generated by ng-zorro-antd and applies two color attributes to it. The two colors are #Input properties and the directive implements OnChanges which allows to react to property binding changes.
#Directive({
selector: "[nz-checkbox][nz-chk-style]"
})
export class CheckBoxStyleDirective implements OnInit, OnChanges {
#Input("nz-chk-bkgnd") chkBkgndColor: string;
#Input("nz-chk-border") chkBorderColor: string;
private checkbox: HTMLElement;
constructor(private renderer: Renderer2, private el: ElementRef) { }
ngOnInit() {
this.checkbox = this.el.nativeElement.querySelector(".ant-checkbox-inner");
this.updateBackgroundColor();
this.updateBorderColor();
}
ngOnChanges(changes: SimpleChanges) {
if (changes.chkBkgndColor) {
this.updateBackgroundColor();
}
if (changes.chkBorderColor) {
this.updateBorderColor();
}
}
updateBackgroundColor() {
if (this.checkbox) {
this.renderer.setStyle(this.checkbox, "background-color", this.chkBkgndColor);
}
}
updateBorderColor() {
if (this.checkbox) {
this.renderer.setStyle(this.checkbox, "border-color", this.chkBorderColor);
}
}
}
Once the directive attribute selector nz-chk-style is applied to the 3rd party element, you can set the checkbox background and border colors with property binding as follows:
<span nz-checkbox nz-chk-style [nz-chk-bkgnd]="bkgndColor" [nz-chk-border]="borderColor" >
See this interactive stackblitz for a demo.
Not sure if you are using Angular but you tagged it, so I guess you are.
If you want to change only the color and nothing more, instead of having a .3rd-party-css-class class, you could just have your with an ng-style like so:
<some-3rd-party-cmp ng-style="{ color: your_color_hex_variable }"></some-3rd-party-cmp>
You can also define a whole object if styles and pass it.
You can also use ng-class and pass one or an array of class names what you want to put additionally on your component:
<some-3rd-party-cmp ng-class="[cls1, cls2, cls3]"></some-3rd-party-cmp>
<some-3rd-party-cmp ng-class="[3rd-party-css-class, someCondition ? 'another-class-name' : '']"></some-3rd-party-cmp>
In the classes you can define the css rules you want to apply and thats it.
With this solutions you can avoid having extra wrapper elements for styling purposes which is a nice thing.

GWT override GSS style in another GSS file

Since my application got larger, I decided that each "module" of my application, will have its own resource file, style file and GSS file. Also styling of for example buttons will be in a different, global GSS file as it is more of an application style, used through the application.
This is not a problem, but when I wanted to do something like this:
.buttonGroup>.button.active{ background-color: red}
in one of the modules, it does not match anything.
Since the button style(buttonGroup, button, active) and behavior (add "active" class on click) is specified in different (global) GSS file, I am not able to change the style of the "active" class.
Here is a simplified example:
public interface AppResources extends ClientBundle {
public static AppResources INSTANCE = GWT.create(AppResources.class);
#Source({"style.gss"})
AppStyle appStyle();
}
Style file:
public interface AppStyle extends CssResource {
String buttonGroup();
String button();
String active();
}
Module:
public interface ModuleResources extends AppResources{
public static ModuleResources INSTANCE = GWT.create(ModuleResources.class);
#Source({"style.gss","module.gss"})
ModuleStyle moduleStyle();
}
Style file:
public interface ModuleStyle extends AppStyle {
}
In GSS files I tried to use #provide and #require (it would not compile without it as it would have missing identifiers or classes).
It then compiles fine, but the buttonGroup, button and even the active class is treated as it belongs to the AppStyle, therefore style.gss styles are used and the rule:
.buttonGroup>.button.active{ background-color: red}
in module.gss is not matching anything as it is probably looking for .hash-ModuleStyle-buttonGroup, .hash-ModuleStyle-button and .hash-ModuleStyle-active classes, whereas the actual styles on the button are .hash-AppStyle-buttonGroup etc.
In the end I solved it by using #external on the classes I wanted to use in different GSS stylesheets.
By using #external all the classes from widgets, which had their own stylesheets, keep their class names unobfuscated, so that they can be overridden in any module stylesheet.
I didn't want to do it before, but that was the only solution that I could think off.
This is actually exactly what #Import is meant to solve!

How to override GWT obfuscated style for DataGrid header

I'm trying to figure out how to override the dataGridHeader style defined in DataGrid.css! GWT core. The GWT style name is obfuscated with adler32 so I can't simply use .dataGridHeader in my css. In my case I wish a simple change of white-space:normal.
I've seen may articles here about injecting css but they all appear to be class level rather than a sub style used within a component like DataGrid.
How do I override a header style used within a component like DataGrid?
Just like with any ClientBundle and CssResource: create an interface that extends Datagrid.Resources and overrides the dataGridStyle method with a #Source annotation pointing to your own CSS file (or possibly to both the original file and your own file, so they'll be combined together).
Doing it that way will override the style for all DataGrids in your app though (it actually depends on which CssResource instance gets ensureInjected() first: the one from the original DataGrid.Resources or the one from your sub-interface): because you use the same return type (DataGrid.Style), the obfuscated class names will be the same.
If you want to change the style on a case-by-case basis then, in addition, declare an interface that extends DataGrid.Style and use that as the return type to your dataGridStyle override: because the obfuscated class name is based on both the interface fully-qualified name and the method name, your DataGrid.Style sub-interface will generate different obfuscated class names than the original DataGrid.Style interface.
Then of course, GWT.create() your DataGrid.Resources sub-interface and pass it as an argument to the DataGrid constructor.
See also http://code.google.com/p/google-web-toolkit/issues/detail?id=6144
Thanks Thomas.
Just to make it easier for the readers...
Create a new Interface
public interface GwtCssDataGridResources extends DataGrid.Resources {
#Source({Style.DEFAULT_CSS, "gwtDataGrid.css"})
Style dataGrid();
}
Use a static reference
public static final GwtCssDataGridResources gwtCssDataGridResources = GWT.create(GwtCssDataGridResources.class);
static {
gwtCssDataGridResources.dataGrid().ensureInjected();
}
Finally create a new CSS file gwtDataGrid.css. Note that if you need to override a style, you have to use !important on each definition.
.dataGridHeader {
color: #FF0000 !important;
}
.dataGridFirstColumnHeader {
-moz-border-radius-topleft: 5px;
-webkit-border-top-left-radius: 5px;
}
.dataGridLastColumnHeader {
-moz-border-radius-topright: 5px;
-webkit-border-top-right-radius: 5px;
}
That's it

Applying styles for custom TextArea in ActionScript 3

I have the following code to create and apply a few styles for a custom TextArea in ActionScript 3.
public class MyCustomTextArea extends TextArea
{
override protected function createChildren():void
{
super.createChildren();
this.styleSheet.setStyle("sup", { display: "inline", fontFamily: "ArialSup", fontSize:"12"});
this.styleSheet.setStyle("sub", { display: "inline", fontFamily: "ArialSub", fontSize:"12"});
this.setStyle("fontFamily", "Arial");
}
}
I have two problems with this code.
this.styleSheet is always null when I create an instance of the class. If this.styleSheet is initialized to new StyleSheet() to avoid this issue, then the TextArea instance does not seem to recognize any of the HTML tags that can be used with the htmlText property.
Can anyone help in fixing these two issues? Thanks.
First off - the styleSheet property of a TextArea component is null by default - what you're seeing is an expected behavior.
You're also creating your css stylesheet in an unusual way - perhaps this is where your problems are coming from? I'd try either loading, or defining inline, a stylesheet to apply to your text area. There's an example of loading and applying a stylesheet here: http://blog.flexexamples.com/2008/03/22/applying-a-cascading-style-sheet-to-a-textarea-control-in-flex/
Also, what are ArialSub and ArialSup? If these aren't valid font names flex won't recognize them and use them.

Resources