[Gambas-user] A Gambas odissey

Doriano Blengino doriano.blengino at ...1909...
Mon Aug 11 10:09:21 CEST 2008


Hello all...

I am writing a file manager, hybrid between FileRunner and a more
modern one.

I started with a DirView, and soon discovered that it doesn't raise the
KeyPress event (but the IDE makes you think that). There were other
things missing in DirView, so I wrote my MyDirView the way I wanted. It
was easy at first, but then I discovered that it is difficult, or at
least not clear, how to move the "Current" cursor. I am not sure why,
but it does work by setting the Selected property of an item. 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.

Writing MyDirView revealed another problem. If in a custom control I
receive the KeyPress event, I can not re-raise it (stack overflow). So I
have to raise another event with a different name. This breaks the
consistency of naming - in a row of four controls, each derived from the
other, the same event must be called with four different names. I took a
look at the FileView control to see what has been done in there. It
receives Click events, and raises Click events. What inside? It does not
inherit from ListView or similar. Now I understand why it works, but I
don't like it.

Anyway, I went ahead. I put two FileView on the form. They don't raise
KeyPress event. It's getting tiring. 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 which has the
Backspace key as its shortcut. Now the backspace works, but... how the
hell can I tell which control is focused? The only way I found was to
catch the GotFocus and LostFocus events, and track the focus by hand. I
have only three controls, but what about if I had dozens of them?
Grouping them would group all their events, while I am interested in
grouping only GotFocus/LostFocus events.

To make it short, I succeded in make it work, and passed to the
Enter key. The Enter key should invoke the selected file in one of the
two FileView's. A menu voice has only one shortcut, but the Enter keys
are two (Gambas calls them Enter and Return). Uhm... no way. Then I try
to use the Form_Keypress event, but it does not fire - the controls are
stealing the keys. So, there is no way to do this thing. If a FileView
does not "activate" a file when the user presses Enter, then you can not:

    1: inherit a new control which does, because you must rename all its
events
    2: use a menu voice to do it, because a menu voice has only one
shortcut; if you want use more keys, no way
    3: use the form KeyPress, which does not fire

The only way left is to create a new control, and then instantiate a
FileView inside it. This is not inheritance, because you have to
replicate all the things you need: events, properties, methods.

Coming from Delphi, I must say the following:

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.

Delphi containers have an ActiveControl property which tells which
control has the focus. Moreover, every control has a Focused property
which tells if a specific control has the focus or not. The list of
things Delphi has and Gambas doesn't is long, but I don't want to
criticize. I am really missing keyboard and focus control. It seems that
VisualBasic programmers use the mouse a lot, and neglect keyboards, and
so do many users, so this could be the reason why Gambas seems to do the
same.

I don't know Gambas very well, and I could have missed a lot of things.
But it is easy to miss things - in the documentation a "See also"
section in every topic could really help.

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. Probably Gambas is too developed to
change things at this point but, for who cares or is courious, I will
explain how events work in Delphi. An event in delphi has an associated
property which contains the address of a routine to launch. For example,
if a control has a Click event, then it has a OnClick property. That
property contains the address of the routine to invoke when the control
wants to "raise" the Click event. The OnClick property is a procedural
type, a thing that does not exist in Gambas. But being a property, the
main program can disable that event by setting that property to NIL
(NULL), or change the handler by setting the property to another value.
It is possible to associate many controls to the same handler, but only
the events we want, not *all* the events of *all* the selected controls.
In fact, events do not exist in delphi, they are simply procedure calls.
Instead of writing:

    raise KeyPress   ' Gambas code

which, I suppose, unleashes a textual search for a public subroutine
named in some correct way, in Delphi one would write:

    if OnKeypress<>NIL then OnKeypress();   // procedural call


This paradigm is faster, more sure, more flexible, more easy to
understand. When deriving controls, the derived one can override the
methods of the ancestor, and still call the inherited one. Gambas has an
interesting feature which does the opposite: instead of calling the
ancestor method on demand, it can stop it on demand. It is quite the
same, I think.


Happy holidays to everyone.







More information about the User mailing list