LESS CSS - interpolation on mapped variables - less

I'm trying to automate a nested map scenario using LESS CSS.
Consider the following single level map:
.map(#keys) {
each(#keys, {
#{value} : #index;
});
}
Called something like this:
.render-maps() {
#arr: child1, child2, child3;
#text-colors: {
#map(#arr);
}
}
This works fine for single level maps where the output is a simple key and value, however I want to create a second level map - like below - but I can't get it to compile:
.nested-map(#arr1, #arr2) {
each(#arr1, {
// I cannot get the compiler to output with a prefix '#' on parent!!!
#parent#{index} : {
each(#arr2, {
#{value} : #index;
});
}
});
}
Can it be done? If so, any advice appreciated.
UPDATE
Here's what I'm trying to achieve, just in case there's a better solution:
I have a number of base colors, these are held as variables in themes.
#primary: #000000;
For each base color, there may be a contrasting "on" color - representing text etc.
#on-primary: #ffffff;
For each "on" color, there maybe a number of categories - text, icons, borders.
... and for each category, there could be multiple states and each state uses a different opacity.
For instance,
icons have 3 states - active, inactive, disabled - each with a different opacity but using the same "on" color.
You could choose to place icons on the background or on a colored surface, so there are multiple themes as well.
To summarise, there could be hundreds of different permutations - which I don't want to maintain individually as variables.
Instead, I create a number of key variables/lists and mixins so that I can generate all of the variations.
#primary: #000000; // 10 of these
#on-primary: #ffffff;
#icon-variants: active, inactive, disabled;
#icon-opacity-on-primary: 70, 50, 38;
Once, I have all my variants, I retrieve colors via a mixin. Here's an example of a single level map for colors.
.get-color(#color) {
#colors: {
.map-colors();
}
#return: color(#colors[$#color]);
}
This type of approach means that I can only need to know a theme "primary", from which I can get the correct, "on" colors and any variants for text, icons, borders, and any state of any variant suing just a handful of mixins.
For example: .get-text-color(high-emphasis, on-primary)[];
Here's how I have to map 2 level maps because I can't do it automatically:
.get-text-color(#theme; #type: high) {
#text-colors: {
#on-primary: { .map-text-color(on-primary); }
#on-primary-dark: { .map-text-color(on-primary-dark); }
#on-primary-light: { .map-text-color(on-primary-light); }
#on-secondary: { .map-text-color(on-secondary); }
#on-error: { .map-text-color(on-error); }
#on-surface: { .map-text-color(on-surface); }
#on-background: { .map-text-color(on-background); }
#on-light: { .map-text-color(on-light); }
#on-dark: { .map-text-color(on-dark); }
}
#return: color(#text-colors[##theme][$#type]);
}
Which results in 30 colors - 10 x 3 states.

Related

listview in TornadoFX displaying duplicated items when using cache-form

I'm loading JSON data from internet, capturing data about items, like name, author and imageurl. Then I want to load them one under the other so I put them into the listview. I only add them once as a custom class, that only holds those variables.
I'm having a problem with those values duplicating and not appearing as they should. For example, it would load first 5 items(out of 20) and it would repeat them over the remaining 15. I don't understand why that's happening, also tried with looping over listview's items array and printing them out and they are all different, also tried doing refresh() on them, but it doesn't seem to change anything at all.
I'm adding a code that I use to create the listview and the piece that I'm using to fill it in.
val lv = listview<Item>{
anchorpaneConstraints {
topAnchor = 0.0
bottomAnchor = 0.0
leftAnchor = 0.0
rightAnchor = 0.0
}
cellFormat {
graphic = cache {
form {
fieldset {
hbox {
spacing = 10.0
println(it.name)
println(it.author)
println(it.imgurl)
println(it.desc)
imageview {
image = Image(it.imgurl)
prefWidth(256.0)
prefHeight(256.0)
}
vbox {
field("Name") {
label(it.name)
}
field("Author") {
label(it.author)
}
field("Description") {
label {
text = it.desc
wrapWidth = 150
}
}
}
}
}
}
}
}
}
val tmpItems = items.clone() as ArrayList<JsonObject>()
val arr = ArrayList<Item>()
for (m in tmpItems) {
arr.add(
Item(
m["name"].toString(),
m["author"].toString(),
m["desc"].toString(),
m["imgUrl"].toString()
)
)
}
lv.items.addAll(arr)
I expected the output to be 20 unique items, as that's what's in the lv.items, but the shown result is 5 unique items repeated over 20 lines.
When using cache you need to specify a unique id for each item, so the framework knows how to retrieve the cached ui elements for the currently displayed item in a given table cell. This is explained in detail in the javadoc for the cache function.
If you have an id field in your item, you can use that for example:
cache(rowItem.id) { }
You could even use the value for the cell, if that's unique:
cache(it) { }

LESS: how to convert a list of called mixins to a for loop with a unique call

I crated many mixins to generate different kinds of classes for various purposes. Specifically I have to use a unique colorizer set using the standard bootstrap variable name, such as (only an example):
#type-primary: #fff;
#type-success: #f00;
#type-info: #ff0;
#type-default: #000;
#type-warning: #0f0;
#type-danger: #0ff;
Actually I created my mixins in the following form, with a "mother" as prefix to which I attached various suffixes
.text
{
&-primary { .color_text(#type-primary); }
&-success { .color_text(#type-success); }
&-info { .color_text(#type-info); }
&-default { .color_text(#type-default); }
&-warning { .color_text(#type-warning); }
&-danger { .color_text(#type-danger); }
}
After this, I can then create the final called mixin such as (so simple because it's only an example)
.color_text (#color)
{
color:#color;
}
I woud like to automate and optimize .text mixin to avoid many repeated rows, I think with a for loop. How could be possible?
Final results should be (in this case)
.text-primary {
color: #fff;
}
.text-success {
color: #f00;
}
.text-info {
color: #ff0;
}
.text-default {
color: #000;
}
.text-warning {
color: #0f0;
}
.text-danger {
color: #0ff;
}
In PSEUDO-CODE something like this could be ideal
#type-primary: #fff;
#type-success: #f00;
#type-info: #ff0;
.createContextClass("classNamePrefix",{#type-primary,#type-success,#type-info},mixinToBeCalled);
// Another call could be
.createContextClass("otherClassNamePrefix",{#type-primary,#type-success},otherMixinToBeCalled);
where, in relation to my original code, classNamePrefix should be the name of first part of final CSS class, then is passed an array with all kind of suffix that I wish in final CSS code, and mixinToBeCalled is the mixin that creates all css rules for final .text-primary, .text-success, .text-info.
For the moment, following Seven-Phases-Max' suggestion, I improved his solution in the following way

Is ~'' really the best way to pass a null parameter to a LESS mixin?

I am creating a series of mixins for LESS css where I use a mixin like this with media queries:
.animal(#color: ~'', #imgWidth: ~'')
{
& when not (#color = ~'')
{
color: #color;
}
& when not (#imageMargin = ~'')
{
img
{
width: #imgWidth;
}
}
}
As you can see the parameters default to ~'' and then I only output the property if a real value is passed in. This allows me to 'inherit' from the previous media query when nothing is passed in :
#media screen and (min-width: 20em)
{
.cat(#color: red, #imgWidth: 3em);
.tiger(#color: blue, #imgWidth: 5em);
}
#media screen and (min-width: 20em)
{
.cat(#imgWidth: 5em);
.tiger(#imgWidth: 7em);
}
The color doesn't need to be re-set for the second media query, only the #imgWidth parameter. So in the output CSS it isn't included.
This works fine, but its very cumbersome. It this really the only way to do optional parameters that should be ignored if not provided. Why does LESS even output parameters when they're empty? Is there a setting to disable this?

dynamically change the model used as base for a qml item

Im starting to work with qtquick 1.1. And i have designed a component consisting mainly out of a pathview.
Rectangle {
id: pathViewElement
PathView {
id: pathView
pathItemCount: 4
preferredHighlightBegin: 0.5
preferredHighlightEnd: 0.5
highlightRangeMode: PathView.StrictlyEnforceRange
model: myModel
delegate: Item {
width: valueText.width
height: 50
scale: 1.0-2*Math.abs(pathViewElement.width/2-(x+width/2)) / pathViewElement.width
opacity: scale
smooth: true
Text {
id: valueText
anchors.centerIn: parent
text: myModel.value
font.pointSize: 35
}
}
path: Path {
startX: 0; startY: 25
PathLine { x: pathViewElement.width; y: 25;}
}
}
}
This PathView is using a model called myModel. Which might be located in any other file.
The question now is the following:
I'm using the same component to be able to change different values. Each of these values is coming with another QML ListModel.
So how can i dynamically change the model used in the PathView (myModel)?
Also, while creating the PathView i can statically set the model using
model: MyListModel{}
where MyListModel is a qmlFile consisting only of a ListModel {} declaration. But when i dynamically create the PathView from within a third file, say MyApplication.qml I cannot set pathViewElement.model: MyListModel{} as the compiler is expecting a ";" instead of {}. Why is this?
So how can i dynamically change the model used in the PathView
(myModel)?
On the occurrence of respective event, you can directly change the model assigned for your view.
eg. Assuming you want this change to be done on click of some mouse button:
onClicked:
{
pathView.model = myNewModel
}
Here, myNewModel is the id for your new model to replace with.
But when i dynamically create the PathView from within a third file,
say MyApplication.qml I cannot set pathViewElement.model:
MyListModel{} as the compiler is expecting a ";" instead of {}. Why is
this?
Can you state this part more clearly ?

Displaying Custom Images in 'tools' config options of ext.grid.panel

I am only a month old with extjs and still experimenting. My question is: I have a grid panel and within it the 'tools' config options. I am using this to enable/disable a Ext.grid.feature.Grouping variable. The 2 handler functions have the logic to disable/enable the 2 views by clicking on the 2 'cross' buttons that appear on the right side of the header. The logic is fine. However, I would like to display my set of custom images in place of the 'cross' buttons. Can this be done? If yes, how? Do I need to make some changes in the css code for that?
I have looked into the documentation and also done a good search but nothing seems to answer my question.
Specify a custom type config on your tools:
Ext.create('Ext.grid.Panel', {
...
tools: [
{
type: 'enable-grouping',
handler: function() {
...
}
},
{
type: 'disable-grouping',
handler: function() {
...
}
}
]
});
Then define the following classes in a stylesheet to style your new tools:
.x-tool-enable-grouping {
background-image: url('path/to/tool/image/enable-grouping.png');
}
.x-tool-disable-grouping {
background-image: url('path/to/tool/image/disable-grouping.png');
}
The size of a tool image should be 15 x 15 px