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
|