Re: Event when CSS is applied
On 18-2-2015 08:34, Tomas Mikula wrote: Hope this helps. I'll give it a try! Maybe it will solve some of the TBEERNOT (TODO) tags further down the code. Tom
Re: Event when CSS is applied
On 18-2-2015 08:34, Tomas Mikula wrote: What I think should be done is, instead of trying to hack around Pane, create class NeedlePane that extends Region and overrides layoutChildren. It would create its children in the constructor (or take them as constructor parameters), add them to its children list right in the constructor and never clear them, and position them on the layout pass (i.e. in layoutChildren). Creating a DialPane is not such a problem, but creating a path only once and the only layout it turns out to be more of a challenge: the constructed but not yet correctly initialized path elements do not behave well with the rotate. It is an approach with merrit though, especially in resizing. Tom
Re: Event when CSS is applied
I like the improvements to the code. Thanks! Tom
Re: Event when CSS is applied
On 18-2-2015 21:49, Tomas Mikula wrote: So back to your original question: Basically I would like to be informed when the styling of a node has been applied or changed. Is there some place that can provide this information? Turns out you don't actually need this information ;) Indeed. Pattern learned. What does surprise me is that JavaFX aims at doing things via composition, that is why almost everything is final, and where the structure in my original code comes from. This turns out is best solved with inheritance. Tom
Re: Event when CSS is applied
Hmm, my view is rather reverse to yours: The fact that the implementation of layout is best solved with inheritance is a sign that JavaFX does _not_ aim enough at doing things via composition. Tomas On Wed, Feb 18, 2015 at 4:37 PM, Tom Eugelink t...@tbee.org wrote: On 18-2-2015 21:49, Tomas Mikula wrote: So back to your original question: Basically I would like to be informed when the styling of a node has been applied or changed. Is there some place that can provide this information? Turns out you don't actually need this information ;) Indeed. Pattern learned. What does surprise me is that JavaFX aims at doing things via composition, that is why almost everything is final, and where the structure in my original code comes from. This turns out is best solved with inheritance. Tom
Re: Event when CSS is applied
So back to your original question: Basically I would like to be informed when the styling of a node has been applied or changed. Is there some place that can provide this information? Turns out you don't actually need this information ;) Regards, Tomas On Wed, Feb 18, 2015 at 3:20 PM, Tom Eugelink t...@tbee.org wrote: I like the improvements to the code. Thanks! Tom
Re: Event when CSS is applied
(after a night's sleep) Well... I was trying to do things by composition and it did not work. My implemention worked, but it had to depend on a layoutChildren, only at the top level (Skin), which was not fine grained enough. Interesting is that for JFXtras Agenda I used the inherit pattern, but because Agenda has a lot of nested layout (week - day - appointment - time, title, ...). Inheritance was used there out of a need for encapsulation; the composition code got very complex. But it probably saved me from a lot of CSS and layout woos. Now, back to the gauge, I just tried to see if I could hammer a composition pattern onto NeedlePane. The separation between construction and layout is a good thing, so I ended up doing this: - Removing the whole NeedlePane class and replace it with a Pane needlePane = new Pane(); since we're doing absolute layout. - Convert the constructor to a method private void constructNeedlePane() - Convert the layoutChildren to a method private void layoutNeedlePane() - Then I tried to wire it up by listening to needlePane.needsLayoutProperty() That did not work... It worked partially, which was weird. What of course did work was hooking into layoutChildren(): final private Pane needlePane = new Pane() { @Override protected void layoutChildren() { super.layoutChildren(); layoutNeedlePane(); } }; So, now I have composed the layout with a smallish hack. But, getting back to my remark on Agenda... Encapsulation was a good thing there, and actually I like using extends (I always complain when things are final, and I cannot override). So I'm not too displeased with what we ended up with. ;-) Tom On 18-2-2015 22:50, Tomas Mikula wrote: Hmm, my view is rather reverse to yours: The fact that the implementation of layout is best solved with inheritance is a sign that JavaFX does _not_ aim enough at doing things via composition. Tomas On Wed, Feb 18, 2015 at 4:37 PM, Tom Eugelink t...@tbee.org wrote: On 18-2-2015 21:49, Tomas Mikula wrote: So back to your original question: Basically I would like to be informed when the styling of a node has been applied or changed. Is there some place that can provide this information? Turns out you don't actually need this information ;) Indeed. Pattern learned. What does surprise me is that JavaFX aims at doing things via composition, that is why almost everything is final, and where the structure in my original code comes from. This turns out is best solved with inheritance. Tom
Re: Event when CSS is applied
OK, so the major problem I see is that a lot of layout is done outside layoutChildren, using code like this: needlePane = new Pane(); needlePane.widthProperty().addListener( (observable) - { drawNeedlePane(); }); What I think should be done is, instead of trying to hack around Pane, create class NeedlePane that extends Region and overrides layoutChildren. It would create its children in the constructor (or take them as constructor parameters), add them to its children list right in the constructor and never clear them, and position them on the layout pass (i.e. in layoutChildren). The problem you have (or one of the problems) is that in the layout pass, when lStackPane sets the size of needlePane, drawNeedlePane() is triggered which clears needlePane's children (this is shortly after the CSS was applied to them, just before the layout pass that is currently in progress), then adds them quickly back, but without CSS applied. Another problem is that in Skin's layoutChilren, you are trying to layout grand-grand-children. You should only be laying out direct children. The code reads protected void layoutChildren(double arg0, double arg1, double arg2, double arg3) { super.layoutChildren(arg0, arg1, arg2, arg3); setValueText(); scaleValueText(); positionValueText(); } This is what it does: super.layoutChildren() resizes and positions lStackPane. It does not call layout() on it yet. The rest of the methods are positioning grand-children of that lStackPane. When the layoutChildren call returns, layout() will be called on all children, i.e. on lStackPane. Within lStackPane.layout(), lStackPane.layoutChildren() is called, which sets the width and height of needlePane, which triggers drawNeedlePane() (if size changed), which clears the children and adds them back. When lStackPane.layoutChildren() returns, needlePane.layout() is called, within which needlePane.layoutChildren() is called. This is where you should do the layout for valueText. Hope this helps. Tomas On Wed, Feb 18, 2015 at 1:46 AM, Tom Eugelink t...@tbee.org wrote: Sure! I'm very curious what can be done better. https://github.com/JFXtras/jfxtras-labs/blob/8.0/src/main/java/jfxtras/labs/internal/scene/control/skin/gauge/linear/SimpleMetroArcGaugeSkin.java You can also checkout the sources, you should be able to run SimpleMetroArcGaugeTrial1.java without any other dependencies. Some of the other classes will have compilation errors, but the gauge should run. Tom On 17-2-2015 23:15, Tomas Mikula wrote: Maybe if you can post the relevant part of your layoutChildren method so that others can look if they can suggest an improvement. Tomas On Tue, Feb 17, 2015 at 5:05 PM, Tom Eugelink t...@tbee.org wrote: On 17-2-2015 20:01, David Grieve wrote: On 2/17/15 1:30 PM, Tom Eugelink wrote: The control is a codewise polish up one of Gerrit's gauges (with permission!) and pulled into JFXtras (with tests and all). For an idea on what we are talking about: https://www.youtube.com/watch?v=RH5X1uBu1d8 The process of centering the Text in that circle is a bit more complex. 1. The value may vary between a min and max value. 2. I want the Text to automatically utilize the maximum available space, but not change size when a longer or shorter text is shown. To do this I have two additional Text nodes that have the same styling as the Text node (so these are on the scene, but not visible, otherwise CSS is not applied). These two text nodes get the maximum and minimum possible value set. Then on these two some pythagoras is applied and in that way one can determine the scale factor so that the value will never be rendered outside of the circle. Then the actual to-be-rendered value can be placed into the Text node and positioned in the centre of the circle. The problem is that a lot of these calculations depend on the CSS styling. What font is set? Bold or not? So I can only do these calculcation after the CSS has been applied. This unfortunately is not yet the case when the skin is instantiated. This means that if I do not used the layoutChildren, the initial presentation is totally off, untill the first min/max/value is set. Have you looked at the javadoc for Node#applyCss()? I did just now and tried calling that and layout when the skin is being instantiated, but apparently things are not setup right yet. Maybe layoutChildren with bound checking is the way to go.
Re: Event when CSS is applied
On 2/17/15 8:02 AM, Tom Eugelink wrote: I have a skin (of a control) that centers a Text node. This Text node can be styled via CSS, so this styling is a factor when centering. because larger font means wider text. The centering works perfectly, the only problem is figuring out when to center the node. At the moment I'm centering the node on every layoutChildren call of the skin, but this is way to often, because after applying the CSS chances are very low that the node will need to be repositioned. Basically I would like to be informed when the styling of a node has been applied or changed. Is there some place that can provide this information? Not in general, no. But you can add a listener to a property that is styled by CSS and react to the change. You might add a listener to the Text node's fontProperty, for example. Clearly this isn't an all-purpose solution. Another approach is to hold onto the bounds (or maybe just the pref width and height) of the child node. If the old bounds doesn't equal the new bounds, then recenter.
Re: Event when CSS is applied
needsLayoutProperty() is not available on Text, and I figure that on the container it in the end will call layoutChildren, which I'm using already. On 17-2-2015 14:24, Benjamin Gudehus wrote: Basically I would like to be informed when the styling of a node has been applied or changed. There are isNeedsLayout() and needsLayoutProperty() and they might give Node-based information whether the the layout and thus the styling was applied. I guess this might be true, since doCSSPass() is called before doLayoutPass() in the JavaFX thread, but could be wrong on this regard. As another (more fuzzy) option you could place a custom Logger into PulseLogger and handle calls to the newPhase() method. The problem is, that it only gives Scene-based information, i.e. you don't see which Node was processed, so it might be unreliable information. I use a custom PulseLogger for performance tests. --Benjamin On 2/17/15, Tom Eugelink t...@tbee.org wrote: I have a skin (of a control) that centers a Text node. This Text node can be styled via CSS, so this styling is a factor when centering. because larger font means wider text. The centering works perfectly, the only problem is figuring out when to center the node. At the moment I'm centering the node on every layoutChildren call of the skin, but this is way to often, because after applying the CSS chances are very low that the node will need to be repositioned. Basically I would like to be informed when the styling of a node has been applied or changed. Is there some place that can provide this information? Tom
Re: Event when CSS is applied
Basically I would like to be informed when the styling of a node has been applied or changed. There are isNeedsLayout() and needsLayoutProperty() and they might give Node-based information whether the the layout and thus the styling was applied. I guess this might be true, since doCSSPass() is called before doLayoutPass() in the JavaFX thread, but could be wrong on this regard. As another (more fuzzy) option you could place a custom Logger into PulseLogger and handle calls to the newPhase() method. The problem is, that it only gives Scene-based information, i.e. you don't see which Node was processed, so it might be unreliable information. I use a custom PulseLogger for performance tests. --Benjamin On 2/17/15, Tom Eugelink t...@tbee.org wrote: I have a skin (of a control) that centers a Text node. This Text node can be styled via CSS, so this styling is a factor when centering. because larger font means wider text. The centering works perfectly, the only problem is figuring out when to center the node. At the moment I'm centering the node on every layoutChildren call of the skin, but this is way to often, because after applying the CSS chances are very low that the node will need to be repositioned. Basically I would like to be informed when the styling of a node has been applied or changed. Is there some place that can provide this information? Tom
Re: Event when CSS is applied
Registering to fontProperty works, but potentially requires a lot of listeners on every property that may affect the size, like effect, scale, etc. So I'm leaving it in layoutChildren for now; better once to many than not often enough. Would adding such an event be a big change? On 17-2-2015 14:50, David Grieve wrote: On 2/17/15 8:02 AM, Tom Eugelink wrote: I have a skin (of a control) that centers a Text node. This Text node can be styled via CSS, so this styling is a factor when centering. because larger font means wider text. The centering works perfectly, the only problem is figuring out when to center the node. At the moment I'm centering the node on every layoutChildren call of the skin, but this is way to often, because after applying the CSS chances are very low that the node will need to be repositioned. Basically I would like to be informed when the styling of a node has been applied or changed. Is there some place that can provide this information? Not in general, no. But you can add a listener to a property that is styled by CSS and react to the change. You might add a listener to the Text node's fontProperty, for example. Clearly this isn't an all-purpose solution. Another approach is to hold onto the bounds (or maybe just the pref width and height) of the child node. If the old bounds doesn't equal the new bounds, then recenter.
Re: Event when CSS is applied
Hi Tom, suppose you have such an event and can tell whether CSS of your Text has changed. But is changed CSS the only time you want to re-position the Text? I guess you also need to re-position it when the size of the parent changes. I imagine the logic for determining whether you need to re-position the Text or not can get quite complicated. Why is it a problem that you reposition the Text too often? I imagine, and someone please correct me if I'm wrong, that when you ask for text.prefWidth(-1), you get a cached prefWidth from the last call, if no properties of Text have changed since the last call to prefWidth. I also suppose, and again correct me if I'm wrong, that if you resizeRelocate the Text to the exact same position and size as it already has, it does not incur any additional operations down the road compared to not calling resizeRelocate at all. So my conclusion is that repositioning the Text to the same place is not more expensive than checking whether the Text needs to be repositioned. Regards, Tomas On Tue, Feb 17, 2015 at 10:14 AM, Tom Eugelink t...@tbee.org wrote: Registering to fontProperty works, but potentially requires a lot of listeners on every property that may affect the size, like effect, scale, etc. So I'm leaving it in layoutChildren for now; better once to many than not often enough. Would adding such an event be a big change? On 17-2-2015 14:50, David Grieve wrote: On 2/17/15 8:02 AM, Tom Eugelink wrote: I have a skin (of a control) that centers a Text node. This Text node can be styled via CSS, so this styling is a factor when centering. because larger font means wider text. The centering works perfectly, the only problem is figuring out when to center the node. At the moment I'm centering the node on every layoutChildren call of the skin, but this is way to often, because after applying the CSS chances are very low that the node will need to be repositioned. Basically I would like to be informed when the styling of a node has been applied or changed. Is there some place that can provide this information? Not in general, no. But you can add a listener to a property that is styled by CSS and react to the change. You might add a listener to the Text node's fontProperty, for example. Clearly this isn't an all-purpose solution. Another approach is to hold onto the bounds (or maybe just the pref width and height) of the child node. If the old bounds doesn't equal the new bounds, then recenter.
Re: Event when CSS is applied
On 2/17/15 1:30 PM, Tom Eugelink wrote: The control is a codewise polish up one of Gerrit's gauges (with permission!) and pulled into JFXtras (with tests and all). For an idea on what we are talking about: https://www.youtube.com/watch?v=RH5X1uBu1d8 The process of centering the Text in that circle is a bit more complex. 1. The value may vary between a min and max value. 2. I want the Text to automatically utilize the maximum available space, but not change size when a longer or shorter text is shown. To do this I have two additional Text nodes that have the same styling as the Text node (so these are on the scene, but not visible, otherwise CSS is not applied). These two text nodes get the maximum and minimum possible value set. Then on these two some pythagoras is applied and in that way one can determine the scale factor so that the value will never be rendered outside of the circle. Then the actual to-be-rendered value can be placed into the Text node and positioned in the centre of the circle. The problem is that a lot of these calculations depend on the CSS styling. What font is set? Bold or not? So I can only do these calculcation after the CSS has been applied. This unfortunately is not yet the case when the skin is instantiated. This means that if I do not used the layoutChildren, the initial presentation is totally off, untill the first min/max/value is set. Have you looked at the javadoc for Node#applyCss()? So I would like to know when the CSS is applied to do the initial calculations. After that only when CSS, min or max changes is a recalculation required. Tom On 17-2-2015 19:05, Tomas Mikula wrote: Hi Tom, suppose you have such an event and can tell whether CSS of your Text has changed. But is changed CSS the only time you want to re-position the Text? I guess you also need to re-position it when the size of the parent changes. I imagine the logic for determining whether you need to re-position the Text or not can get quite complicated. Why is it a problem that you reposition the Text too often? I imagine, and someone please correct me if I'm wrong, that when you ask for text.prefWidth(-1), you get a cached prefWidth from the last call, if no properties of Text have changed since the last call to prefWidth. I also suppose, and again correct me if I'm wrong, that if you resizeRelocate the Text to the exact same position and size as it already has, it does not incur any additional operations down the road compared to not calling resizeRelocate at all. So my conclusion is that repositioning the Text to the same place is not more expensive than checking whether the Text needs to be repositioned. Regards, Tomas On Tue, Feb 17, 2015 at 10:14 AM, Tom Eugelink t...@tbee.org wrote: Registering to fontProperty works, but potentially requires a lot of listeners on every property that may affect the size, like effect, scale, etc. So I'm leaving it in layoutChildren for now; better once to many than not often enough. Would adding such an event be a big change? On 17-2-2015 14:50, David Grieve wrote: On 2/17/15 8:02 AM, Tom Eugelink wrote: I have a skin (of a control) that centers a Text node. This Text node can be styled via CSS, so this styling is a factor when centering. because larger font means wider text. The centering works perfectly, the only problem is figuring out when to center the node. At the moment I'm centering the node on every layoutChildren call of the skin, but this is way to often, because after applying the CSS chances are very low that the node will need to be repositioned. Basically I would like to be informed when the styling of a node has been applied or changed. Is there some place that can provide this information? Not in general, no. But you can add a listener to a property that is styled by CSS and react to the change. You might add a listener to the Text node's fontProperty, for example. Clearly this isn't an all-purpose solution. Another approach is to hold onto the bounds (or maybe just the pref width and height) of the child node. If the old bounds doesn't equal the new bounds, then recenter.
Re: Event when CSS is applied
On Tue, Feb 17, 2015 at 1:30 PM, Tom Eugelink t...@tbee.org wrote: The control is a codewise polish up one of Gerrit's gauges (with permission!) and pulled into JFXtras (with tests and all). For an idea on what we are talking about: https://www.youtube.com/watch?v=RH5X1uBu1d8 The process of centering the Text in that circle is a bit more complex. 1. The value may vary between a min and max value. 2. I want the Text to automatically utilize the maximum available space, but not change size when a longer or shorter text is shown. To do this I have two additional Text nodes that have the same styling as the Text node (so these are on the scene, but not visible, otherwise CSS is not applied). These two text nodes get the maximum and minimum possible value set. Then on these two some pythagoras is applied and in that way one can determine the scale factor so that the value will never be rendered outside of the circle. Then the actual to-be-rendered value can be placed into the Text node and positioned in the centre of the circle. The problem is that a lot of these calculations depend on the CSS styling. What font is set? Bold or not? So I can only do these calculcation after the CSS has been applied. This unfortunately is not yet the case when the skin is instantiated. This means that if I do not used the layoutChildren, the initial presentation is totally off, untill the first min/max/value is set. Maybe I was misunderstood. I didn't suggest not doing it in layoutChildren. My conclusion was to keep doing it in layoutChildren and not worry about repositioning the text too often. Tomas So I would like to know when the CSS is applied to do the initial calculations. After that only when CSS, min or max changes is a recalculation required. Tom On 17-2-2015 19:05, Tomas Mikula wrote: Hi Tom, suppose you have such an event and can tell whether CSS of your Text has changed. But is changed CSS the only time you want to re-position the Text? I guess you also need to re-position it when the size of the parent changes. I imagine the logic for determining whether you need to re-position the Text or not can get quite complicated. Why is it a problem that you reposition the Text too often? I imagine, and someone please correct me if I'm wrong, that when you ask for text.prefWidth(-1), you get a cached prefWidth from the last call, if no properties of Text have changed since the last call to prefWidth. I also suppose, and again correct me if I'm wrong, that if you resizeRelocate the Text to the exact same position and size as it already has, it does not incur any additional operations down the road compared to not calling resizeRelocate at all. So my conclusion is that repositioning the Text to the same place is not more expensive than checking whether the Text needs to be repositioned. Regards, Tomas On Tue, Feb 17, 2015 at 10:14 AM, Tom Eugelink t...@tbee.org wrote: Registering to fontProperty works, but potentially requires a lot of listeners on every property that may affect the size, like effect, scale, etc. So I'm leaving it in layoutChildren for now; better once to many than not often enough. Would adding such an event be a big change? On 17-2-2015 14:50, David Grieve wrote: On 2/17/15 8:02 AM, Tom Eugelink wrote: I have a skin (of a control) that centers a Text node. This Text node can be styled via CSS, so this styling is a factor when centering. because larger font means wider text. The centering works perfectly, the only problem is figuring out when to center the node. At the moment I'm centering the node on every layoutChildren call of the skin, but this is way to often, because after applying the CSS chances are very low that the node will need to be repositioned. Basically I would like to be informed when the styling of a node has been applied or changed. Is there some place that can provide this information? Not in general, no. But you can add a listener to a property that is styled by CSS and react to the change. You might add a listener to the Text node's fontProperty, for example. Clearly this isn't an all-purpose solution. Another approach is to hold onto the bounds (or maybe just the pref width and height) of the child node. If the old bounds doesn't equal the new bounds, then recenter.
Re: Event when CSS is applied
On 17-2-2015 20:01, David Grieve wrote: On 2/17/15 1:30 PM, Tom Eugelink wrote: The control is a codewise polish up one of Gerrit's gauges (with permission!) and pulled into JFXtras (with tests and all). For an idea on what we are talking about: https://www.youtube.com/watch?v=RH5X1uBu1d8 The process of centering the Text in that circle is a bit more complex. 1. The value may vary between a min and max value. 2. I want the Text to automatically utilize the maximum available space, but not change size when a longer or shorter text is shown. To do this I have two additional Text nodes that have the same styling as the Text node (so these are on the scene, but not visible, otherwise CSS is not applied). These two text nodes get the maximum and minimum possible value set. Then on these two some pythagoras is applied and in that way one can determine the scale factor so that the value will never be rendered outside of the circle. Then the actual to-be-rendered value can be placed into the Text node and positioned in the centre of the circle. The problem is that a lot of these calculations depend on the CSS styling. What font is set? Bold or not? So I can only do these calculcation after the CSS has been applied. This unfortunately is not yet the case when the skin is instantiated. This means that if I do not used the layoutChildren, the initial presentation is totally off, untill the first min/max/value is set. Have you looked at the javadoc for Node#applyCss()? I did just now and tried calling that and layout when the skin is being instantiated, but apparently things are not setup right yet. Maybe layoutChildren with bound checking is the way to go.
Re: Event when CSS is applied
Maybe if you can post the relevant part of your layoutChildren method so that others can look if they can suggest an improvement. Tomas On Tue, Feb 17, 2015 at 5:05 PM, Tom Eugelink t...@tbee.org wrote: On 17-2-2015 20:01, David Grieve wrote: On 2/17/15 1:30 PM, Tom Eugelink wrote: The control is a codewise polish up one of Gerrit's gauges (with permission!) and pulled into JFXtras (with tests and all). For an idea on what we are talking about: https://www.youtube.com/watch?v=RH5X1uBu1d8 The process of centering the Text in that circle is a bit more complex. 1. The value may vary between a min and max value. 2. I want the Text to automatically utilize the maximum available space, but not change size when a longer or shorter text is shown. To do this I have two additional Text nodes that have the same styling as the Text node (so these are on the scene, but not visible, otherwise CSS is not applied). These two text nodes get the maximum and minimum possible value set. Then on these two some pythagoras is applied and in that way one can determine the scale factor so that the value will never be rendered outside of the circle. Then the actual to-be-rendered value can be placed into the Text node and positioned in the centre of the circle. The problem is that a lot of these calculations depend on the CSS styling. What font is set? Bold or not? So I can only do these calculcation after the CSS has been applied. This unfortunately is not yet the case when the skin is instantiated. This means that if I do not used the layoutChildren, the initial presentation is totally off, untill the first min/max/value is set. Have you looked at the javadoc for Node#applyCss()? I did just now and tried calling that and layout when the skin is being instantiated, but apparently things are not setup right yet. Maybe layoutChildren with bound checking is the way to go.
Event when CSS is applied
I have a skin (of a control) that centers a Text node. This Text node can be styled via CSS, so this styling is a factor when centering. because larger font means wider text. The centering works perfectly, the only problem is figuring out when to center the node. At the moment I'm centering the node on every layoutChildren call of the skin, but this is way to often, because after applying the CSS chances are very low that the node will need to be repositioned. Basically I would like to be informed when the styling of a node has been applied or changed. Is there some place that can provide this information? Tom