[Gambas-user] A Gambas odissey

Benoit Minisini gambas at ...1...
Wed Aug 13 18:11:13 CEST 2008


On mercredi 13 août 2008, Doriano Blengino wrote:
> Benoit Minisini ha scritto:
> >> I failed,
> >> instead, in removing all the children of an item, one by one (there is a
> >> clear() method, but I need to delete them one by one). The "for each ...
> >> in item.children" does not work; it is not the first time I see similar
> >> anomalies, especially while stepping the source.
> >
> > Items are not enumerable, because they are not true objects.
> >
> > Instead, you must use the Move* methods that move an internal cursor. Use
> > the TreeView.Item property to get the item pointed by that internal
> > cursor.
>
> Sorry - it was my mistake. Actually I didn't use "for each", but this:
>
>   ME.MoveTo(path)
>   DO
>     IF ME.movechild() THEN BREAK
>     ME.Item.Delete
>     ME.MoveTo(path)
>   LOOP
>
> The idea is to delete children of Path, one by one. It is this example
> that does not work, it even dirties the string variable Path. I noticed
> that stepping the source sometimes has unwanted side effects, which
> disappear when the program is run normally. 

You should elaborate, as these are clearly bugs: stepping the source should 
always have no side effects (effect for things that depends on time or window 
activation/deactivation).

> And, I see now that it can 
> be written as:
>
>   DO
>     ME.MoveTo(path)
>     IF ME.movechild() THEN BREAK
>     ME.Item.Delete
>   LOOP
>
> >> Writing MyDirView revealed another problem. If in a custom control I
> >> receive the KeyPress event, I can not re-raise it (stack overflow).
> >
> > If "you" (I think "you" mean "an object A") receives an event from an
> > object "B", raising it "again" does not mean anything. Only the object
> > "B" can raise the event again.
> >
> > If you mean that the object A is its own event observer, why would it
> > need to send itself an event?
>
> When writing code, I project myself into the code and think as I was the
> CPU... :-))
> So, "I raise an event" should mean "the object we are talking of raises
> an event"...
>
> And about sending events to itself... why not? Often I set up a timer
> only to posticipate an action (note: *not* to delay it, only to get out
> the event handler). For example, I had a problem with deleting a
> TabStrip from a Button inside it. The TabStrip refused to Delete()
> because it was not empty; so in the event handler of the Button I set up
> a timer which, in the next event loop, deletes the TabStrip.
> The purpose of the timer is not to delay things, but to posticipate
> them. It is a mean to send an event to itself.

OK, but "you" are not sending event to "yourself". The event is sent by the 
timer.

>
> > FileView and DirView are compound controls, they do not inherit TreeView
> > or whatever directly. This is mandatory for the FileView control, as it
> > has actually two different views inside: a ListView and an IconView.
> >
> > You don't see KeyPress event sent by the inside views, for the same
> > reason a Container does not see the KeyPress events sent by its children.
> >
> > I admit this seems a bit stupid from the outside.
>
> I don't understand why DirView does not inherit from TreeView. I looked
> at the source, and there is nothing that prevents that.

No. But when DirView was created, (a few years ago!), Observer didn't exist, 
and it was one of the first control written in Gambas, and was used for 
debugging the UserControl control.

> A DirView is no less than a TreeView; simply, its items are directory
> names. A routine to read directory names from file system and put them
> in the tree could be the only different thing.
> Look at my file manager application, in the MyDirView class. The only
> routine which has to do with files is populate(). All the rest is there
> because of missing things in TreeView, or because I am not a good
> programmer, or because I am not a good documentation reader.
>
> >> I don't want to rewrite MyFileView
> >> just now (I will do, because I need more functionalities). I only need
> >> to catch Backspace and Enter, so I make a menu voice
> >
> > A menu "voice"? What's that?
>
> A menu item, an object of type Menu, which has a Name, a Caption, a
> Shortcut.
> Sorry for my naming confusion.
>
> > Application.ActiveControl will tell you.
>
> Aaahhhh! Look at http://gambasdoc.org/help/comp/gb/application

Application.ActiveControl is implemented in gb.qt, so you are not looking at 
the right page.

A component can reimplement an already existing class by adding methods, 
properties... This is like inheritance, but by keeping the same name.

>
> Just speaking of Delphi, the Oracle of Delphi would help in such
> cases... if you can not find something in the docs, ask the Oracle...
> Just joking...
>
> >> Delphi forms have a KeyPreview property. If you set it, then *all* the
> >> keypresses are first passed to the form. The form then decides wether to
> >> ignore the key, or make additional things, to let the key pass, or to
> >> stop it.
> >
> > I think this is possible to implement.
>
> There are situations where it can help.
>
> >> Moreover, every control has a Focused property
> >> which tells if a specific control has the focus or not.
> >
> > I can implement that too. Maybe I will call it "HasFocus" instead.
>
> To avoid to write duplicates, could be better think twice. Having
> Application.ActiveControl already covers this case, perhaps:
>
>   if Application.ActiveControl = ControlToTestForFocus then ...
>
> >> Finally, I must say that I think, and *repeat*, I think, the event
> >> management is wrong or, at least, it is not as flexible as it could be.
> >> Once a control raises event, you can not make it stop. If you group
> >> controls, you group all their events. Once you assign a handler to an
> >> event, you can no more change it.
> >
> > Mmm. Not really. Maybe you should first understand that it works
> > differently in Gambas than in Delphi.
> >
> > http://gambasdoc.org/help/doc/object-model
> > http://gambasdoc.org/help/cat/event
> > http://gambasdoc.org/help/comp/gb/observer
>
> Ok, I read them. The docs do not go deep enough for the speaking we are
> making now.
> I learned that, with Object.lock(), you can stop a control to send
> events. I did not know. Problem is, you disable *all* its events.
> With Object.Attach() you can change the event names of a control (all
> the events), not a single event handler.
> A group of controls can share events - yes: all the events or none of them.
> You see, and please take this with friendship, this is not what I call
> "flexible".

It is less flexible than the Delphi way, but I yet think it is enough.

> Looking at DirView source, I see:
>
>   $bNoEvent = TRUE
>   $hTreeView.Clear
>   ...
>   TreeView_Expand
>   $bNoEvent = FALSE
>
> This is a clear symptom of lack of flexibility. You have to circumvent
> the normal event processing, because it is not flexible enough.
> To solve this problem, you had:
>
>     - to declare a variable ($bNoEvent) somewhere in the outer scope
>     - to set/reset that variable (and this is required, because in some
> point you want to stop the events)
>     - to modify the relevant event handler and make it test $bNoEvent
>
> In delphi, the same thing would have reduced to set/reset the
> TreeView.OnSelect property, i.e., exactly the only thing we wanted.

OK. But implementing events the same way as Delphi has a cost that is higher 
than the management of these specific case that are not very common.

> Anyway, this particular case is not important - I solved already similar
> cases as you did in DirView.
> But, please, don't tell me I say this because I am used to delphi and
> not to Gambas. This is true only in part...
>
> > You are mixing again the object that raises the event with the object
> > that receives it. Apparently, this concept does not exist in Delphi, or
> > it is not clearly visible. Not really object-oriented... :-)
>
> Ah ah ah...
> Please, please, please... give delphi a try, so you will speak knowing
> what you are saying.

I didn't say that Delphi is not object-oriented. I just said that the concept 
of event observer is more object-oriented. :-)

> In this discussion, I win 1,5 to 1, because I know delphi and a little
> gambas, you keep saying you don't know delphi. It is true that you know
> gambas better than me (and better than everyone else, right?), so may be
> I win only 1,5 to 1,4...
> Objects and events are two concepts totally unrelated. Tcl/Tk has event
> management, and it is not an object language. Turbo pascal was a true
> object language, and had no events.
> You say half the truth in saying that the event concept is not clearly
> visible in delphi. This comes from the fact that delphi is strictly
> bound to the windows world, where events are called "messages". Delphi
> manages them perfectly, but they are not the best. The power of delphi
> is such it can hide this awful thing behind "standard", strong-type
> checked, parametrized function calls. Excuse me if this is not enough.
> Messages in windows are records (structs in C), having 4 integers in
> them. The first integer says what kind of message is, all the rest
> depends on what type of message you look at. Those integers can contain
> coordinates, key codes, or be pointers to some string in memory, or even
> point to some complicated structure (which possibly you have to free,
> once used...). These integers sometime are break in words, just for fun.
> These messages are sent to the main procedure of a program, directed to
> a window handle (in windows, everything is a window). This "WindowProc"
> parses that record, and dispatches them to the appropriate window. So,
> for a MouseDown event you receive a wonderful:
>
> procedure TForm1.ListBox1MouseDown(Sender: TObject; Button:
> TMouseButton; Shift: TShiftState; X, Y: Integer);
>
> which has in the header all the information you need, without going to
> see key.xxx, mouse.xxx (external, unrelated variables).
> You can not get the "no event data error", in delphi.
> The LAST variable used in gambas, here is named Sender (the name is more
> appropriate).
> Beside the fact that this method is cleaner than in gambas, there is
> another advantage: you can call/invoke event handlers as they were
> normal subroutines (and they are in fact). You can not do it in gambas,
> because the global variables LAST, Key, Mouse are undefined.
> This also means that you don't need to raise events - you can invoke
> directly the event handler, if you want. 

This is true for these special events that use static values only. Otherwise 
event handlers are public methods like any other public methods, and you can 
call them from anywhere.

> But, for the sake of 
> completeness, I must say that, if you want, you can send messages, and
> you can send them in two different ways - normal way, or "post" them,
> which means they are queued and processed in the next event loop. There
> is also an Idle event, which is missing in gambas (apropos: how about to
> implement it?). This event is raised when the application is idle -
> useful for background processing.

GTK+ has that, but not QT, so I don't think I can do that.

> Delphi is a true object/class language. Gambas is not. How about method
> overriding, virtual methods, protected methods, default properties,
> published properties, and the list could continue... but probably this
> things are unknown for a visual basic programmer (fortunately you know
> also C++. How events work in C++?).

Maybe you should *really* read the documentation pages I told you. Especially 
this one: http://gambasdoc.org/help/doc/object-model

Gambas has method / property overriding, virtual methods. There is no 
protected method (what for?), and no default property. 

But there is a default method, enumerators, array accessors...

And class overriding: a Gambas component can reimplement and/or extend an 
already existing class declared in another component. You can even do that in 
your own project, by using the EXPORT keyword. For example, if you add a 
class named TextBox in your project, adds the EXPORT keyword to it, this 
TextBox class will extend and replace the TextBox control.

> Back on your half truth. Events, as known in gambas, do not exist in
> delphi. They are simply not needed but, if you want to interface
> directly with that monster called windows, then you can use messages
> (which are events).

Gambas events have nothing to do with X11 events, QT events, GTK+ events or 
Windows events. There are Gambas events. Some of the Gambas events are raised 
from a internal GUI event (keyboard, mouse, focus), but not all.

> Want to know? Gambas events could be better if they had an associated
> property to set. Grouping, disabling, intercepting, all this things
> could be done. Gambas events could be better if they carried event
> informations along: the pressed key for a keypress, the coordinates,
> button and shift state for mousedown, and so on. Why gambas does it not?
> Please tell me.

I admit that Keyboard and Mouse events accessing global structures is not very 
beautiful. I did that because it was simpler for the programmer, and because 
I never meet the need for explicitely calling a mouse or keyboard event 
handler, unless for doing bad things. :-)

>
> Ok, I am making all the people waste time.
>
> I love gambas, and could love it more. This is all I have to say.
>
> Nice day to everybody.
>

Regards,

-- 
Benoit Minisini




More information about the User mailing list