Thread: [Fxruby-users] Dialogues, and create.
Status: Inactive
Brought to you by:
lyle
From: Hugh S. S. E. E. <hg...@dm...> - 2003-07-01 13:44:56
|
I have learned the heuristic that for a widget hierarchy to be operative it must be constructed and created, and the create() calls must be done on the child widgets before the parent widget. So now I have been looking at dialog.rb from the examples. application is an FXApp, and application.create is called, but FXTestDialog's create method never seems to be called, nor does DialogTester's. The child widgets (buttons, menus) don't seem to be create()d either. What have I missed? Thank you Hugh |
From: Joel V. <vj...@PA...> - 2003-07-01 16:15:03
|
Hugh Sasse Staff Elec Eng wrote: > I have learned the heuristic that for a widget hierarchy to be > operative it must be constructed and created, and the create() calls > must be done on the child widgets before the parent widget. > > So now I have been looking at dialog.rb from the examples. > application is an FXApp, and application.create is called, but > FXTestDialog's create method never seems to be called, nor does > DialogTester's. The child widgets (buttons, menus) don't seem to be > create()d either. Isn't the create() call propagated from parent to child? In fact, if I add some debugging code to DialogTester#create: def create super puts "FOO" show(PLACEMENT_SCREEN) end end then I see FOO on stdout when the main window appears. I'll bet you could verify that FXTestDialog#create is being called, too. |
From: Hugh S. S. E. E. <hg...@dm...> - 2003-07-01 16:40:51
|
On Tue, 1 Jul 2003, Joel VanderWerf wrote: > Hugh Sasse Staff Elec Eng wrote: > > I have learned the heuristic that for a widget hierarchy to be > > operative it must be constructed and created, and the create() calls > > must be done on the child widgets before the parent widget. > > > > So now I have been looking at dialog.rb from the examples. > > application is an FXApp, and application.create is called, but > > FXTestDialog's create method never seems to be called, nor does > > DialogTester's. The child widgets (buttons, menus) don't seem to be > > create()d either. > > Isn't the create() call propagated from parent to child? Then why isn't it always? I have found that I have to call create on the children before the parent, in the few cases I have done this so far. > > In fact, if I add some debugging code to DialogTester#create: > [...] > puts "FOO" [...] > > then I see FOO on stdout when the main window appears. > > I'll bet you could verify that FXTestDialog#create is being called, too. > OK, but how do I use this? I mean, I realise my heuristic was wrong, because the code works, but how do I revise it to fit with reality? :-) Are there whole families of widgets and windows for which I can forget about the create() calls? How do I look this information up? Hugh |
From: Lyle J. <jl...@cf...> - 2003-07-02 14:16:29
|
Hugh Sasse Staff Elec Eng wrote: >> Isn't the create() call propagated from parent to child? > > Then why isn't it always? I have found that I have to call create on > the children before the parent, in the few cases I have done this so > far. Hugh, Sorry for the delayed response. Joel was correct in his response that when you call create() on a parent window, it recursively calls create() on all of its child windows that exist at that time. Also, even though FXApp is not itself a "window", calling FXApp#create will call create() on all of the top-level windows (e.g. main windows and dialog boxes) that exist at the time create() is called. So for the dialog.rb example program, the call to FXApp#create triggers calls to both DialogTester#create and FXTestDialog#create, since they are top-level windows and they have been instantiated before the call to FXApp#create. In turn those calls to DialogTester#create and FXTestDialog#create trigger recursive calls to create() for all of those windows' child windows. > OK, but how do I use this? I mean, I realise my heuristic was > wrong, because the code works, but how do I revise it to fit with > reality? :-) Are there whole families of widgets and windows for > which I can forget about the create() calls? How do I look this > information up? I'm trying to think of any exceptions to the rule and I don't know that there are any. What may be tripping you up, and what frequently throws people, is that create() only realizes widgets that exist at the time that create() is called. In other words, say you construct a dialog box: dialog = FXTestDialog.new(...) and then create it: dialog.create Now if you were to add a new button to the dialog box immediately after you called FXDialogBox#create: button = FXButton.new(dialog, ...) That button doesn't automatically get "created", because it didn't exist when you previously called create. You must go back and either call create() on the button itself: button.create or, since calls to create() are recursive, you could call create() on the dialog again: dialog.create Calling create() repeatedly on the same object is safe, at least for the built-in FOX classes. They will still recurse through the list of child windows, but only actually create the windows that haven't been realized yet. Hope this helps, Lyle |
From: Hugh S. S. E. E. <hg...@dm...> - 2003-07-02 15:17:09
|
On Wed, 2 Jul 2003, Lyle Johnson wrote: > Hugh Sasse Staff Elec Eng wrote: > > >> Isn't the create() call propagated from parent to child? > > > > Then why isn't it always? I have found that I have to call create on > > the children before the parent, in the few cases I have done this so > > far. > > Hugh, > > Sorry for the delayed response. Joel was correct in his response that > when you call create() on a parent window, it recursively calls create() > on all of its child windows that exist at that time. Also, even though > FXApp is not itself a "window", calling FXApp#create will call create() > on all of the top-level windows (e.g. main windows and dialog boxes) > that exist at the time create() is called. OK, that is clear now.... > [...] > I'm trying to think of any exceptions to the rule and I don't know that > there are any. What may be tripping you up, and what frequently throws > people, is that create() only realizes widgets that exist at the time > that create() is called. In other words, say you construct a dialog box: This could be what happened to me. I will have another look at my code to see if that is true. Thank you. The next thing I'll need to know is: Where can I generalize this behaviour: are there other calls that propagate like this? > > or, since calls to create() are recursive, you could call create() on > the dialog again: > > dialog.create Could I call it on FXApp again? Hmm, what about class Class alias_method :old_new, :new def new(*args) result = old_new(*args) $fxapp.create if self.ancestors.include?(FXObjectt) return result end end or something? > > Calling create() repeatedly on the same object is safe, at least for the > built-in FOX classes. They will still recurse through the list of child > windows, but only actually create the windows that haven't been realized > yet. > > Hope this helps, Yes, this is clear now. thnak you. > > Lyle > |
From: Lyle J. <jl...@cf...> - 2003-07-03 14:09:39
|
Hugh Sasse Staff Elec Eng wrote: > The next thing I'll need to know is: Where can I generalize this > behaviour: are there other calls that propagate like this? The other two that immediately come to mind are the detach() and destroy() methods. You may already understand that the purpose of calling create() is to create and then bind a native windowing-system entity (e.g. a X window, or a Win32 GDI font) to an already-existing FOX object (like an FXWindow or FXFont instance). Calling detach() on a FOX object reverses part of the effect of create(); it breaks this binding between the FOX object and its window-system entity, but it doesn't actually destroy either of them. And like create(), detach() does its thing recursively, from parent to child windows. Calling destroy() goes one step further (if you want to think of it that way) and actually destroys the window-system entity. Note that it doesn't destroy (garbage-collect) the FOX object, just the X window or whatever that was backing it up. An important distinction, though, is that destroy() is not as aggressive as create() and detach() in terms of its recursive behavior. Specifically, calling destroy() on a widget will not destroy any of its shared resources, like fonts or icons. Suppose you create an icon: anIcon = FXPNGIcon.new(getApp(), ...) and then associate it with two different widgets (a label and a button): aLabel.icon = anIcon aButton.icon = anIcon Now suppose that at some point later you call destroy() on the button: aButton.destroy It is clear that you want to blow away the X window (or Win32 window) underlying that FXButton instance, but you don't want to destroy the icon too since someone else may still be using that resource. And in this case, of course, that "someone else" is the label. There are other behaviors in FOX that are recursive, e.g. the manner in which the layout algorithm works, but right offhand I can't think of any other APIs that you'd deal with directly that have a recursive nature. I am sure that as soon as I send this post, someone will point out some cases I forgot about, though ;) Hope this helps, Lyle |
From: Hugh S. S. E. E. <hg...@dm...> - 2003-07-03 14:53:11
|
On Thu, 3 Jul 2003, Lyle Johnson wrote: > Hugh Sasse Staff Elec Eng wrote: > > > The next thing I'll need to know is: Where can I generalize this > > behaviour: are there other calls that propagate like this? > > The other two that immediately come to mind are the detach() and > destroy() methods. > > You may already understand that the purpose of calling create() is to > create and then bind a native windowing-system entity (e.g. a X window, > or a Win32 GDI font) to an already-existing FOX object (like an FXWindow > or FXFont instance). Yes, I have an idea about that, but am not au fait with the details. I don't think I need to be yet! > > Calling detach() on a FOX object reverses part of the effect of > create(); it breaks this binding between the FOX object and its > window-system entity, but it doesn't actually destroy either of them. When would you want to do that, then? > And like create(), detach() does its thing recursively, from parent to > child windows. > > Calling destroy() goes one step further (if you want to think of it that > way) and actually destroys the window-system entity. Note that it > doesn't destroy (garbage-collect) the FOX object, just the X window or So you can call create on the FXObject to get it back again if you wish? Is this common practice to reduce memory usage whilst keeping performance high, or something? I'm thinking in my current application I will have many possible dialogues, and am wondering about when to new()...GC or create()...destroy() or show()...hide() them, and what [de]merits there are of each strategy. I think I've just listed them in increasing order of memory usage. I'm not sure if I should worry about that at all, I expect the windowing systems are pretty efficient in terms of memory nowadays[?]. > whatever that was backing it up. An important distinction, though, is > that destroy() is not as aggressive as create() and detach() in terms of > its recursive behavior. Specifically, calling destroy() on a widget will > not destroy any of its shared resources, like fonts or icons. Suppose > you create an icon: > > anIcon = FXPNGIcon.new(getApp(), ...) Ah, just "clicked" about getApp(), avoids repeoting a ref to the application object. getApp doesn't seem to appear in the methods pane of http://www.fxruby.org/doc/api/ > > and then associate it with two different widgets (a label and a button): [...] > Now suppose that at some point later you call destroy() on the button: [...] > It is clear that you want to blow away the X window (or Win32 window) > underlying that FXButton instance, but you don't want to destroy the > icon too since someone else may still be using that resource. And in that flexibility is useful. > > There are other behaviors in FOX that are recursive, e.g. the manner in > which the layout algorithm works, but right offhand I can't think of any > other APIs that you'd deal with directly that have a recursive nature. I OK, thanks, this is probably enough for now. :-) > am sure that as soon as I send this post, someone will point out some > cases I forgot about, though ;) > > Hope this helps, Yes, thank you again. > > Lyle > Hugh |
From: Lyle J. <jl...@cf...> - 2003-07-03 15:22:28
|
Hugh Sasse Staff Elec Eng wrote: >> Calling detach() on a FOX object reverses part of the effect of >> create(); it breaks this binding between the FOX object and its >> window-system entity, but it doesn't actually destroy either of them. > > When would you want to do that, then? Please see the FAQ "What's the difference between detach and delete?": http://www.fox-toolkit.org/faq.html#DETACH >> Calling destroy() goes one step further (if you want to think of it that >> way) and actually destroys the window-system entity. Note that it >> doesn't destroy (garbage-collect) the FOX object, just the X window or > > So you can call create on the FXObject to get it back again if you > wish? Is this common practice to reduce memory usage whilst keeping > performance high, or something? I'm thinking in my current > application I will have many possible dialogues, and am wondering > about when to new()...GC or create()...destroy() or show()...hide() > them, and what [de]merits there are of each strategy. I think I've > just listed them in increasing order of memory usage. I'm not sure > if I should worry about that at all, I expect the windowing systems > are pretty efficient in terms of memory nowadays[?]. Yes, you can call create on the object to get it back again, but no, it isn't common practice to create and tear down windows to reduce memory use. I cannot think of a single time when I have called destroy() explicitly in one of my FOX applications. [As the previously referenced FAQ notes, destroy() gets called as a side effect when the FOX object is garbage-collected, but I'm excluding those cases.] I would not worry about using this as a memory management technique. One way it might be useful (and I think some people have used it for this) is to build an application that runs continuously but doesn't always need to display a GUI. For example, maybe at first it does display a GUI and allow the user to interact, set some parameters. At some point, the user clicks the "Go" button and we call FXApp#destroy to tear down all of the GUI parts, so that the program can continue to run in the background even if the X server is killed or something like that. Again, I've never needed to do this, so I'm just going from memory here. >> its recursive behavior. Specifically, calling destroy() on a widget will >> not destroy any of its shared resources, like fonts or icons. Suppose >> you create an icon: >> >> anIcon = FXPNGIcon.new(getApp(), ...) > > Ah, just "clicked" about getApp(), avoids repeoting a ref to the > application object. getApp doesn't seem to appear in the methods > pane of http://www.fxruby.org/doc/api/ It *is* listed as a "readable" attribute of FXId: http://www.fxruby.org/doc/api/classes/Fox/FXId.html which means that there's also a getApp() method that returns the same value. But that's a separate discussion, whether we should be listing both the "getter" and "setter" methods as well as the "attr_reader" and "attr_writer" methods in the API docs ;) -- Lyle |
From: Hugh S. S. E. E. <hg...@dm...> - 2003-07-03 15:45:31
|
On Thu, 3 Jul 2003, Lyle Johnson wrote: > Hugh Sasse Staff Elec Eng wrote: > > > When would you want to do [detach], then? > > Please see the FAQ "What's the difference between detach and delete?": > > http://www.fox-toolkit.org/faq.html#DETACH Thanks, I'll do that. > > > So you can call create on the FXObject to get it back again if you > > wish? Is this common practice to reduce memory usage whilst keeping > > performance high, or something? I'm thinking in my current [...] > Yes, you can call create on the object to get it back again, but no, it > isn't common practice to create and tear down windows to reduce memory > use. I cannot think of a single time when I have called destroy() [...] So these GUIs are pretty efficient then. So do people tend to just use show and hide then, and just let normal garbage collection take its course? Maybe the effort isn't worth it now, and I should forget habits about tight memory budgets picked up in the 1980's! [...] > need to display a GUI. For example, maybe at first it does display a GUI > and allow the user to interact, set some parameters. At some point, the > user clicks the "Go" button and we call FXApp#destroy to tear down all > of the GUI parts, so that the program can continue to run in the > background even if the X server is killed or something like that. Again, > I've never needed to do this, so I'm just going from memory here. Thanks, that is an interesting idea. > [...] > >> anIcon = FXPNGIcon.new(getApp(), ...) > > > > Ah, just "clicked" about getApp(), avoids repeoting a ref to the > > application object. getApp doesn't seem to appear in the methods > > pane of http://www.fxruby.org/doc/api/ > > It *is* listed as a "readable" attribute of FXId: Oh! it's one of those! :-) > value. But that's a separate discussion, whether we should be listing > both the "getter" and "setter" methods as well as the "attr_reader" and > "attr_writer" methods in the API docs ;) yes, this may really fall into the "who is RDoc's audience?" area: -- I was feeling frustrated earlier trying to find out where show() came from, because it is used by FXDialogueBox, but comes from FXTopWindow, but FXTopWindow.methods doesn't reveal it, only FXTopWindow.instance_methods does. I'm beginning to think that there maybe needs to ba another template for RDoc for behaviour discovery. This leads into the dark and twisty passages about respond_to?() being insufficient to specify type because it doesn't cover semantics. So I can't think about adding this to Rdoc myeslf when it is probably not the solution. > > -- Lyle > > Hugh |
From: Lyle J. <jl...@cf...> - 2003-07-03 15:53:59
|
Hugh Sasse Staff Elec Eng wrote: > So these GUIs are pretty efficient then. So do people tend to just > use show and hide then, and just let normal garbage collection take > its course? Maybe the effort isn't worth it now, and I should > forget habits about tight memory budgets picked up in the 1980's! Yes, the GUIs are quite efficient (IMO). One of the pathological cases that we had for awhile here at work was an application that built up its GUI dynamically (based on the contents of a configuration file) and for some cases was constructing thousands and thousands of widgets. Despite that unusually large size, it was still pretty responsive and so forth. Widgets are very quick to construct and destroy, and don't seem to use that much memory. In C++-based FOX applications it's standard practice to just construct dialog boxes (e.g. file dialogs) as temporary objects, on the stack. We never used to do that in older Motif applications because it was so slow. As you noted, times (and memory constraints) have changed a lot since the 80's ;) |
From: Hugh S. S. E. E. <hg...@dm...> - 2003-07-03 16:01:17
|
On Thu, 3 Jul 2003, Lyle Johnson wrote: > Yes, the GUIs are quite efficient (IMO). One of the pathological cases > that we had for awhile here at work was an application that built up its > GUI dynamically (based on the contents of a configuration file) and for > some cases was constructing thousands and thousands of widgets. Despite > that unusually large size, it was still pretty responsive and so forth. Thank you, that is reassuring. > > Widgets are very quick to construct and destroy, and don't seem to use > that much memory. In C++-based FOX applications it's standard practice > to just construct dialog boxes (e.g. file dialogs) as temporary objects, That seems reasonable, and better than what I was considering: constructing them all at the start, doing the one create() call, and hiding most of them. > on the stack. We never used to do that in older Motif applications > because it was so slow. As you noted, times (and memory constraints) > have changed a lot since the 80's ;) Yes :-) I still admire what people did with 32K though! > > Thank you, Hugh |
From: Lyle J. <jl...@cf...> - 2003-07-03 16:14:24
|
Hugh Sasse Staff Elec Eng wrote: >> > Ah, just "clicked" about getApp(), avoids repeoting a ref to the >> > application object. getApp doesn't seem to appear in the methods >> > pane of http://www.fxruby.org/doc/api/ >> >> It *is* listed as a "readable" attribute of FXId: > > Oh! it's one of those! :-) > >> value. But that's a separate discussion, whether we should be listing >> both the "getter" and "setter" methods as well as the "attr_reader" and >> "attr_writer" methods in the API docs ;) > > yes, this may really fall into the "who is RDoc's audience?" area: > -- I was feeling frustrated earlier trying to find out where show() > came from, because it is used by FXDialogueBox, but comes from > FXTopWindow, but FXTopWindow.methods doesn't reveal it, only > FXTopWindow.instance_methods does. Right, but this is just a Ruby thing. Object#methods returns a list of methods available for the object. Since FXTopWindow is itself an object (it is an instance of class "Class"), you can call methods on it to get a list of its methods: FXTopWindow.methods but of course this isn't very useful. What you *really* want to know is, if you have my hands on an FXTopWindow object (an instance of class "FXTopWindow"), what methods can you call on that? So then your choices are: aTopWindow = FXTopWindow.new(...) aTopWindow.methods or the more convenient: FXTopWindow.instance_methods > I'm beginning to think that there maybe needs to be another template > for RDoc for behaviour discovery. This leads into the dark and > twisty passages about respond_to?() being insufficient to specify > type because it doesn't cover semantics. So I can't think about adding > this to RDoc myself when it is probably not the solution. Sure. Good automated documentation tools like RDoc are great to have, but they can't write the meat of the text for you. As you say, they cannot divine the semantics of a particular method given its name, or its argument list; some human being has to fill in those blanks ;) |
From: Hugh S. S. E. E. <hg...@dm...> - 2003-07-03 16:59:33
|
On Thu, 3 Jul 2003, Lyle Johnson wrote: > > -- I was feeling frustrated earlier trying to find out where show() > > came from, because it is used by FXDialogueBox, but comes from > > FXTopWindow, but FXTopWindow.methods doesn't reveal it, only > > FXTopWindow.instance_methods does. > > Right, but this is just a Ruby thing. Object#methods returns a list of Yes, and may be wider, for OO languages in general. > but of course this isn't very useful. What you *really* want to know is, > if you have my hands on an FXTopWindow object (an instance of class or a descendent of it, > "FXTopWindow"), what methods can you call on that? So then your choices are: > > aTopWindow = FXTopWindow.new(...) > aTopWindow.methods > > or the more convenient: > > FXTopWindow.instance_methods Yes, did both of those. > > Sure. Good automated documentation tools like RDoc are great to have, > but they can't write the meat of the text for you. As you say, they > cannot divine the semantics of a particular method given its name, or > its argument list; some human being has to fill in those blanks ;) I wonder if that can be facilitated in some way? Objects are supposed to be re-useable, but without docs they won't be. Maybe common usage "patterns" might be helpful. For example, with a teaspoon you can stir tea with it, or eat with it, and you want to wash it afterwards. This doesn't mean you can't use it as a tyre lever when mending a puncture on a bicycle, but at least the common things inherited from spoon and cutlery are to hand in the docs. I'd hope that the tool could search the usual inheritance paths to find thes methods and link to them, which would save on duplication, and cope with some ancestor overriding its parent's methods later. This would be too naive in the case of singletons, but is it worth consideration, in the general case? It would not be perfert, but would it be enough of an improvement to try? Hugh |