DockNode should support bringToFront/Focus
jasons2000 opened this issue · 16 comments
I think DockNode should support a method which brings it the Front and gives it Focus, regardless on whether it is Floating, Docked or in a Tabbed Pane.
This should be possible with a floating DockNode through getStage() and then using the equivalent method for bringing a stage to the front. I also understand the importance of having it for docked and tabbed nodes as well.
Yeah, I've basically done this, I'm using the Tabbed branch by @hkmoon too, so I've got a bit of code like follows:-
final Parent parent = dockNode.getParent();
if (parent != null) {
Parent x = parent.getParent();
if (x instanceof ContentTabPane) {
List<Node> childrenList = ((ContentTabPane) x).getChildrenList();
for (int i = 0; i < childrenList.size(); i++) {
if (childrenList.get(i) == dockNode) {
((ContentTabPane) x).getSelectionModel().select(i);
}
}
}
else {
((Stage) dockNode.getScene().getWindow()).toFront();
}
}
Essentially, in my application code, I maintain a reference to each DockNode and use this reference to locate the ContentPane.
It would probably be nice if DockNode, just had a method toFront()
I agree, but I think it should be implemented differently perhaps.
In Qt Framework every QWidget has a raise() method to bring it to the top of its parents child stack. This can be used with a tabbed QDockWidget in Qt to quickly bring it to the front. But to have this for JavaFX, the raise method would be best placed on the Node class itself in the official Java API.
So I am not sure what the best course of action is, obviously just adding a toFront() to DockNode is a possibility that acts like raise() in Qt and augments the behavior of Stage.toFront().
However, it does seem that JavaFX already has toFront() for Node because of z-order with different layouts. So try using toFront() with the tab as well and see what it does, because TabPane also inherits it.
http://stackoverflow.com/questions/2988196/z-order-in-javaffx
https://docs.oracle.com/javase/8/javafx/api/javafx/scene/Node.html#toFront--
Node.toFront() doesn't work with the tabs. I cant see how it can avoid going through the Tab SelectionModel
Darn, I feel as though that's how it should behave, given that would be the behavior in Qt Framework as well. I think there is a similar option in Swing too. It would be practical to file a feature request/enhancement at Oracle's site explaining why that should be the behavior, and I think I will do so later today.
However, DockNode will still need to augment toFront() so it knows whether to come to the front of its parent or delegate to its stage's toFront(). Would you find it acceptable to have DockNode.toFront() that can bring the node to the top like you want in all contexts?
On a slightly related note, its also annoying that JavaFX doesn't have a simple method to determine if a node is visible to the user. Its quite important for a framework like DockFX, whereby you don't necessarily want every DockNode wasting compute resources on rendering if its not visible. Swing has this feature.
Yes, and they've also denied requests for a public scene traversal API. However, JavaFX uses a retained mode scene graph, so I believe all of that culling and everything should be getting done by JavaFX behind the scenes because of the CSS parsing and everything.
ah, I see, that's interesting. In my application a DockNode essentially causes intermittent server request for new information. So its not just the rendering that I want to avoid if the DockNode is not visible.
Can you elaborate? Is there something you would like DockFX to do to prevent/mitigate that?
Essentially, in my application a user can dynamically create DockNodes that have a view on realtime data on a server. The more DockNodes the more load on the server.
Ideally, you'd have a method on a Node (or on a DockNode) which indicates if the node is actually visible to the user, ie is it minimized, an unselected tab, or even a totally obscured Window.
As as workaround , given what you said about the "retained mode scene graph", I guess if I capture a timestamp on rendering, then I can determine if its actually visible and thus stop an unnecessary server polling.
@jasons2000 Actually, I have a much better solution for you.
Use getStage() on DockNode and add a listener to the focused property. This will allow you to determine when each DockNode is focused and unfocused.
https://docs.oracle.com/javase/8/javafx/api/javafx/stage/Window.html#focusedProperty
You can actually use this with all Node's in JavaFX too. So you could just set it on the DockNode itself which should allow it to work when docked and when floating without much code at all.
http://stackoverflow.com/questions/16549296/how-perform-task-on-javafx-textfield-at-onfocus-and-outfocus
If the control doesn't have focus, there is no need for it to poll the server.
Hmm, my suggestion wouldn't work anyway.
Wrt to your suggestion, not having focus would not mean I wouldn't want to update the screen. I could have two views side by side, and user would be focused on one of them, but they would want to see both of them get updated if data changed on the server.
Right, I understand. I bet the scene graph does do some occlusion culling behind the scenes (pun intended?), obviously Windows Explorer does at the OS level. I do see why focus won't work for you. It would be nice for more of the internal JavaFX API to be exposed publicly. I assume you are also sleeping any threads doing the background polling somewhat though, correct? The visible property may still work for when the stage is minimized to the taskbar. I would also try using the visible property of DockNode directly, because that may still get set by JavaFX behind the scenes. Something to try anyway, and if not I would consider filing a feature request/enhancement on that as well.
My original implementation was in Swing, so there was one Thread which would poll for the selected Tab in a TabPane. Each Set of Views was always managed by a Swing Tabbed Pane, so it wasn't so much of a problem determining if something was viewable, it only existed in a Tabbed Pane.
Because DockFX is more flexible, which is obviously a good thing, non viewable DockNodes are more of a problem with causing unnecessary load on my servers.
If you read the javadoc for the visibility property, its quite clear that you cant use it for the things I've described. (https://docs.oracle.com/javase/8/javafx/api/javafx/scene/Node.html#visibleProperty)
I may raise request/enhancement with oracle if I remember how to do it.
Thanks for you help anyway, I realise most of my issues are with JavaFX rather than DockFX. However still love working with JavaFX, its so much better than Swing.
I have a bit of an update on all of this.
My feature request for toFront()/toBack() to work on tabs was denied by OpenJDK;
https://bugs.openjdk.java.net/browse/JDK-8153373
I also filed a ticket for the other requested feature, checking if the DockNode is actually visible. It still remains open but has not been evaluated. Either way, I do not think we will address this in DockFX because it's a broad problem that applies to many JavaFX apps.
https://bugs.openjdk.java.net/browse/JDK-8153374
This issue here however could be addressed when we get tab support in the master branch. One way to do it would be to override setFocused on DockNode and make that select it if it's a tab. The solution would also have to address #17 if it's not addressed first.