How to make a frame/dialog/window always on top?
-
I want a small frame/dialog/window (showing a color gradient scale) to show in a corner in front of the model. I can't use a Web Dialog because it disappears to the background when I click on the model outside the dialog, and I can't use show_modal because in Windows that would mean (as far as I understand) that no interaction with the model is possible until the dialog is closed.
I considered wxSU, but then when I tried installing it it didn't work for a while. I realised the problem was that the plugin files had been mysteriously placed inside the newly created folder 'Google Sketchup 7' instead of 8. This is on a Mac.
This is for a commercial plugin, and I need it to be user friendly. I do not want to have to have installation instructions that say 'download and install wxSU, then maybe move some files from one folder to another.'
Any suggestions please?
-
"Always above" is an (optional) window manager feature, on Windows and probably OS X it's mainly exposed to developers but not end users.
It's correct what you found that SketchUp's webdialogs are bugged: in the OS X version,
webdialog.show_modal()
is not modal at all, but it's always on top (whatshow()
should be). It hasn't been fixed yet, so we commonly just use a simple conditional:if OSX webdialog.show_modal() else # (elsif WIN) webdialog.show() end
using boolean constants (in your namespace) for the operating systems, as described in FAQ: Detect if plugin is running in the OSX vs Windows version of SketchUp ?
-
So are you saying that in Windows, show() keeps the dialog always on top? I wasn't expecting that, since it certainly doesn't in Mac, and the API didn't seem to suggest that. Or the name of the function. Or just common sense. I thought that it shows it but then it can be hidden again when it goes out of focus.
-
@alexmojaki said:
So are you saying that in Windows,
show()
keeps the dialog always on top?
YES ... because on MS Windows child window objects have a Z order higher than the owner window object. (UI speaking, everything on the screen, is a child window object. This includes menus, editboxes, buttons, ... all controls, .. everything is a window object; or some subclass of the base window class.)@alexmojaki said:
I wasn't expecting that, since it certainly doesn't in Mac, ...
The concept of what "modal" means differs between the Mac and Win development world.@alexmojaki said:
... and the API didn't seem to suggest that.
The API dictionary is long overdue for an overhaul !Get ThomThom's WebDialogs - The Lost Manual β R1 09 November 2009 in PDF
... or read a condensed edition in forum topic:
WebDialogs - The Lost Manual@alexmojaki said:
Or the name of the function. Or just common sense.
Yea... the previous example method could be wrapped in a cross-platform method named:
.show_atop()
(I think I'll enter an API Request for it.)It is frustrating to have methods with the same name, that have differing behavior on Mac vs Windows !! Your not the first to complain ... and likely not the last.
@alexmojaki said:
I thought that it shows it but then it can be hidden again when it goes out of focus.
Sometimes things get "out of whack" on Windows.. and we need to call thebring_to_front()
method, but it's rare. That method is of more use on the Mac.We can actually also force a hidden child window on MS Windows, but it requires making system calls the change the Z-order of the child window to less than that of the owner window, or hide it in some way.
But that's a pain-in-the-butt, and not necessary anyway, because theUI::WebDialog
class has a means to hide the window, via theclose()
method.This does not destroy the
UI::WebDialog
instance! It can be opened again later by calling either one of the show methods. However, the HTML will be re-loaded, so in order to restore any information or control selections, it is up to YOU to save them on the Ruby side into instance variables, before the dialog closes.Likewise, it is YOUR responsibility to restore any dialog information and control selections after the dialog opens / re-opens.
-
Awesome, thanks a lot to both of you!
-
OK, it's not working as I had hoped.
What I wanted was for the dialog to show when a particular object was selected. It does, but then I want the user to be able ton continue to interact with the model, e.g. orbit the camera, while the scale is still showing, just out of focus. But when the object is selected, and the dialog appears, it of course starts out by being in focus. While I'd like this to not happen, it's acceptable. But when I click on the same object again,
onSelectionBulkChange
gets called again, even though nothing has changed, and so before it would 'reshow' the dialog, thus keeping it in focus no matter what, and making it impossible to use Sketchup. I tried inserting a conditional to avoid this so that the dialog is only shown when the selection is genuinely changed, but now when I re-click the same selection to try and bring Sketchup into focus, the dialog disappears completely. It's not even in the background, and it's certainly not on top as I thoughtshow_modal
would make it. I know from theputs
statements that the conditionals are working as expected: only 'b' is output, so the dialog isn't being closed. It's just not staying on top.class ScaleSelectionObserver < Sketchup;;SelectionObserver def initialize() @dialog = UI;;WebDialog.new("Color scale", false, "Color scale", 70,160,5,100, true) path = Sketchup.find_support_file("scale.html",#...#) @dialog.set_file(path) @prevSelection = nil end def onSelectionBulkChange(sel) if #the selection is appropriate# and sel.length>0 puts 'b' if not sel.to_a==@prevSelection puts 'a' @dialog.show_modal @prevSelection = sel.to_a end else puts 'hi' @dialog.close end end def onSelectionCleared(sel) @dialog.close end end # Attach the observer. Sketchup.active_model.selection.add_observer(ScaleSelectionObserver.new)
-
Being able to change the focus from a dialog or toolwindow, back to the main SketchUp window, (and visa-versa) is a current problem we have discussed before.
We have entered API request for this.
-
Sigh. OK, thanks. You should probably also note that neither show nor show_modal keeps the window on top in Mac. I've even checked with another case.
-
@alexmojaki said:
Sigh. OK, thanks. You should probably also note that neither show nor show_modal keeps the window on top in Mac. I've even checked with another case.
show_modal
will keep the WebDialog on top of the SketchUp window under OSX. But not on top of all other child windows of SketchUp. -
Your test
if #the selection is appropriate# and sel.length>0
???
Presumably you have some 'real code' in there... otherwise the line is
if
as everything after the first # is ignored ?
Then you'll always get 'b'...
Also [incidentally] the
path = Sketchup.find_support_file("scale.html",#...#)
would be better as
path = File.join(File.dirname(__FILE__), "scale.html")
assuming it's in the same folder as the ruby script itself... -
So, returning to my original question, since WebDialogs won't work, how do you suggest that I make the scale always show on top? Is wxSU my only option?
-
No, you can draw it to the screen if you make your own 'tool'. Use the view.draw method of your tool class and you can do some pretty interesting things.
BUT, that requires the user to be using your tool so they can see the info you've written to the screen. Once they switch to rotate or pan or select, move, etc the data disappears. So it is also flawed.
-
@thomthom said:
show_modal
will keep the WebDialog on top of the SketchUp window under OSX. But not on top of all other child windows of SketchUp.Well, for me it's not even showing on top of the main Sketchup window. I have no other dialogs open, the only other window is Sketchup itself. And when I click on it, the dialog disappears right behind it.
@tig said:
Your test
if #the selection is appropriate# and sel.length>0
???
Presumably you have some 'real code' in there... otherwise the line is
if
as everything after the first # is ignored ?
Then you'll always get 'b'...Yes, I replaced the real code with the comment.
@tig said:
Also [incidentally] the
path = Sketchup.find_support_file("scale.html",#...#)
would be better as
path = File.join(File.dirname(__FILE__), "scale.html")
assuming it's in the same folder as the ruby script itself...Thanks, I'll give that a try.
@chris fullmer said:
No, you can draw it to the screen if you make your own 'tool'. Use the view.draw method of your tool class and you can do some pretty interesting things.
BUT, that requires the user to be using your tool so they can see the info you've written to the screen. Once they switch to rotate or pan or select, move, etc the data disappears. So it is also flawed.
Thanks, I'll consider that. But still not ideal, of course. Is that all then?
-
@alexmojaki said:
Well, for me it's not even showing on top of the main Sketchup window. I have no other dialogs open, the only other window is Sketchup itself. And when I click on it, the dialog disappears right behind it.
hm... you sure you didn't use
show()
?If you try this base bone example:
w=UI::WebDialog.new('test').show_modal
If that doesn't produce a WebDialog that keep on top of SketchUp; what OSX do you have?
Btw, while on topic of Webdialogs, have you seen this thread: http://sketchucation.com/forums/viewtopic.php?f=180&t=23445#p198883
? -
Yes, I've seen the lost manual. What was critical to me at the beginning of the thread was that
show
in Windows kept the dialog on top (which isn't obvious), maybe add that to the manual.OK, I edited the wrong file when I was testing show_modal. So it works correctly. Then I discovered that the problem with my code is that for some reason when I reclick on the object to put Sketchup in focus, for some reason
onSelectionCleared
gets called, and then immediately afteronSelectionBulkChange
. I have no idea why: as far as I can see the selection never gets cleared. So the dialog was actually being closed, and then it wasn't opened again because I didn't edit@prevSelection
when the selection was cleared. But now that I've done that, I'm back to the original problem: each time I click on the object to try and put Sketchup in focus, the dialog is closed and reopened and so regains focus.So now it seems my main problem is that the selection is momentarily cleared unnecessarily. In fact, I tested a bit more and found that it seems to get cleared pretty much all the time. It hasn't even got anything to do with the dialog or reclicking,
onSelectionCleared
gets called whenever I change my selection at all. I need to keep the definition becauseonSelectionBulkChange
doesn't react to clicking an empty space. So I need a way to distinguish between the selection being genuinely cleared and this quirk. I considered InputPoint, but I've never used that before and I don't see how it can be used from the context of a SelectionObserver. -
hm... I've noticed that the Selection observers misbehaves: http://www.thomthom.net/software/sketchup/observers/
(Btw - I have other observations I've not published yet. Available in the BitBucket repo: https://bitbucket.org/thomthom/sketchup-observers/issues?status=new&status=open)
-
on the mac
show_modal
andbring_to_front
appears on top of everything, so they're really the same except one returns 'true' and the other returns the object.> webdialog=UI;;WebDialog.new('blur_focus') #<UI;;WebDialog;0x110e2a48> > webdialog.show true > webdialog.show_modal true > webdialog.bring_to_front #<UI;;WebDialog;0x110e2a48> > webdialog.execute_script('window.focus()') true > webdialog.show_modal webdialog.execute_script('window.blur()') true > webdialog.close nil
'window.focus()' and 'window.blur()' work with 'show', 'show_modal' or 'bring_to_front', so you can do stuff like
> webdialog.set_html("Hi!") webdialog.execute_script('window.blur()') true > webdialog.set_html("Bye!") webdialog.execute_script('window.blur()') true > webdialog.set_html("Hi!") webdialog.bring_to_front webdialog.execute_script('window.blur()') true > webdialog.set_html("I'm going to hide!") webdialog.close webdialog.execute_script('window.blur()') true > webdialog.show true
just say if I'm 'barking up the wrong tree'
john -
@alexmojaki said:
OK, I edited the wrong file when I was testing
show_modal
. So it works correctly.
Yup! Been there, done that, just yesterday, in fact (edited the wrong Js function and wondered why things did not change.)@alexmojaki said:
Then I discovered that the problem with my code is that for some reason when I reclick on the object to put Sketchup in focus, for some reason
onSelectionCleared
gets called, and then immediately afteronSelectionBulkChange
. I have no idea why ... So now it seems my main problem is that the selection is momentarily cleared unnecessarily. ...onSelectionCleared
gets called whenever I change my selection at all.
This is expected. The selection must be cleared in order to receive the elements for the new selection, regardless of whether they are the same as the old selection.@alexmojaki said:
So I need a way to distinguish between the selection being genuinely cleared and this quirk.
Sketchup::ToolsObserver
The SelectionTool is tool id #21022
You might get some benefit from watching the tool state (integer) changes.Also the Sketchup::Tools collection, might help.
But be sure you always check thatactive_tool_id != 0
before attempting to accessactive_tool_name()
(if active tool is undefined, trying to get a name string can BugSplat! SketchUp.)@alexmojaki said:
Is
wxSU
my only option?
Not for Mac, which is where you had the Z-order problem. AFAIK, it is still MS Windows only. (Unless they've gotten it working on the Mac now?) -
@driven said:
on the mac
show_modal
andbring_to_front
appears on top of everything, so they're really the same except one returns 'true' and the other returns the object.Not the same. If you have a dialog opened with
show
then callbring_to_front
then it will put the window at the top of the stack. But if you click the SketchUp window it'll appear above the WebDialog.
If you useshow_modal
then the webdialog will never drop behind the sketchup window. -
@thomthom said:
Not the same. If you have a dialog opened with
show
then callbring_to_front
then it will put the window at the top of the stack. But if you click the SketchUp window it'll appear above the WebDialog.I stand corrected... if acting on a previously
show_modal
, thenbring_to_front
will stay on top.` > webdialog=UI::WebDialog.new('blur_focus')
webdialog.set_html("You'll only see me flash!
but I'll exist in a 'show_modal' state")
webdialog.show_modal
webdialog.close
nilwebdialog.set_html("You'll see me, and because I was 'show_modal' to start with, I'll behave like a 'show_modal' dialog!
However, I won't have focus, because 'window.blur()' has been called")
webdialog.bring_to_front
webdialog.execute_script('window.blur()')
true`My main point was that blur and focus can be set independently of the show-status.
john
Advertisement