Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / customdrawn / 2012-04

Replace some widgets

7 messages · 2 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Michael Schnell

I understand that CustomDrawn provides code for rendering the visual "Components" (Widgets) used by the user code to pixel-images. Same are then sent to one of the attachable backends to have them displayed.

Now these Components not only need to be visualized, but they also provide information to the user code (events, readable properties, ...) .

I understand that there are "basic" Components (supposedly something similar to Panel and Label) that in fact need to be rendered and "higher level" Components that use the basic ones to have themselves be displayed.

If I decide that some or all of these "basic" components should not be rendered to pixels but still the user code needs the functionality it sees: does the CustomDrawn code provide a "hook" that allows for replacing the pixel-rendering code by something provided by a "3rd-party" ? (E.g. to create a "remote" GUI or to switch off the visibility altogether.)

This of course not only asks for appropriately intercepting the information flow direction towards the visualization, but also needs allowing to implement the appropriate events (such as those generated by Timers and Threads and - if doing a remote GUI - the remote user).

Thanks,
-Michael

Giuliano Colla
to Michael Schnell

Il 03/04/2012 11:40, Michael Schnell ha scritto:

Show quoted text 24 lines
I understand that CustomDrawn provides code for rendering the visual "Components" (Widgets) used by the user code to pixel-images. Same are then sent to one of the attachable backends to have them displayed. Now these Components not only need to be visualized, but they also provide information to the user code (events, readable properties, ...) . I understand that there are "basic" Components (supposedly something similar to Panel and Label) that in fact need to be rendered and "higher level" Components that use the basic ones to have themselves be displayed. If I decide that some or all of these "basic" components should not be rendered to pixels but still the user code needs the functionality it sees: does the CustomDrawn code provide a "hook" that allows for replacing the pixel-rendering code by something provided by a "3rd-party" ? (E.g. to create a "remote" GUI or to switch off the visibility altogether.) This of course not only asks for appropriately intercepting the information flow direction towards the visualization, but also needs allowing to implement the appropriate events (such as those generated by Timers and Threads and - if doing a remote GUI - the remote user).

CustomDrawn is actually divided in a common section, and one dedicated section for each backend supported.
The common section performs only abstract operations, such as painting the widget image in the widget's canvas, dispatching messages, etc.

Then each backend takes care of implementing the actual physical drawing, detecting mouse and keyboard actions, implementing Timers, etc.

Splitting at backend level is, in principle straightforward: you insert a new backend, which does whatever you have in mind and it takes the place of existing backends. Instead of {$define CD_cocoa} you'll put {$define CD_Michael} in the main defines (customdrawndefines.inc), and you'll have to write your own version of all _Something files (such as customdrawnwinapi_Michael.inc).

Splitting at widget level on the contrary is very difficult, because they follow the inheritance rules.

Almost all visible LCL components are descendants of TControl, and therefore on Widgetset side you find in customdrawn a TCDWSControl class, which implements the basic methods, common to all controls.

So if you create your own backend, you may decide that if the control it's supposed to deal with is a TEdit, you'll send it via TCP/IP to a remote server, if it's a TButton you'll paint it on screen 1, if it's a TLabel you'll output the text to a console, if it's a TTimer you'll ask a CallBack from your Time Server, etc.

I don't know if this answers to your question.

Giuliano

Michael Schnell
to Giuliano Colla
Giuliano Colla wrote
I don't know if this answers to your question.

Yep. I think it does.

IIUC:

The code in the common section provides the near-user stuff such as storing the readable properties for the programmer's interface.

The code in the common section does not do the very time consuming stuff like rendering the graphics to pixels.

Thus it seems to be a quite straight forward (though maybe not at all effortless) task to (e.g.) do a backend that creates a "remote GUI" interface talking to the real GUI via a byte stream (for real "other box" remoting or to remote-control a daemon ow Windows Service) and similar stuff.

I understand that there have been some effort to do a kind of remote GUI to hook to a remote control program done in Java for use on Android. Maybe part of that (code and/or design ideas) can be re-used to do a bytestream based remote backend (of cause not before the realization of current plans for CustomDrwan is more advanced).

Sounds great !

Thanks !

-Michael

Giuliano Colla
to Michael Schnell

Il 03/04/2012 13:10, Michael Schnell ha scritto:

Show quoted text 26 lines
On 04/03/2012 12:28 PM, Giuliano Colla wrote: > I don't know if this answers to your question. Yep. I think it does. IIUC: The code in the common section provides the near-user stuff such as storing the readable properties for the programmer's interface. The code in the common section does not do the very time consuming stuff like rendering the graphics to pixels. Thus it seems to be a quite straight forward (though maybe not at all effortless) task to (e.g.) do a backend that creates a "remote GUI" interface talking to the real GUI via a byte stream (for real "other box" remoting or to remote-control a daemon ow Windows Service) and similar stuff. I understand that there have been some effort to do a kind of remote GUI to hook to a remote control program done in Java for use on Android. Maybe part of that (code and/or design ideas) can be re-used to do a bytestream based remote backend (of cause not before the realization of current plans for CustomDrwan is more advanced). Sounds great !

Depending on what are your needs you have at least three ways to go:

1) If you just want a remote GUI, i.e. your application running on computer A and display, keyboard and mouse on computer B, you don't have to change a bit, because Linux and X11 already provide all the facilities to do that: just use a remote X server, and you're done.

If you on the contrary you want a mix of local and remote functions (one window in computer A, one window in computer B, and such)

2) you can start a full new widgetset, maybe taking the nogui widgetset as a starting point

3) create your branch among the backends of CustomDrawn, and implement what you need.

Giuliano

Michael Schnell
to Giuliano Colla
Giuliano Colla wrote 7 lines
Depending on what are your needs you have at least three ways to go: 1) If you just want a remote GUI, i.e. your application running on computer A and display, keyboard and mouse on computer B, you don't have to change a bit, because Linux and X11 already provide all the facilities to do that: just use a remote X server, and you're done.

During the last four years I did a lot of research on this issue, and so I of course do know how X11 works (VNC is another option). But here, the Widget Set, Window Manager etc needs to run on the non-local-GUI device, which might be a very limited embedded thingy. This is why I searched for possibilities that move the memory and CPU hungry stuff to the remote control unit.

2) you can start a full new widgetset, maybe taking the nogui widgetset as a starting point

At that point in time, I did this. But this asks for implementing an event queue (e.g. for handling Timer- and Thread- generated events). And here I decided that it is very inappropriate to do yet another new event queue implementation, while all other Widget Types already do have this code. I also considered to drop Lazarus and use mseGUI. Same does provide a decent Event Queue enabled "Widget Type" that has no GUI binding. And based on this all GUI enabled "Widget Types" are implemented.

3) create your branch among the backends of CustomDrawn, and implement what you need.

I still do hope, that CustomDraw might have (or get) such a hook. I understand that (similar to fpGUI) there are multiple "backends" (such as X11, Android, ...) that implement the low level stuff, based on what facilities each backend might provide. So it should be possible to add a new backend without forking the project. Here I feel, that the way fpGUI works (using a compiler define to select the backend when compiling), is very appropriate.

Of course some backends will need an event queue done in Pascal code (e.g. if it is not possible to feed events (e.g. generated by threads) to the event queue that might be provided by the GUI API, an Event queue needs to be implemented in Pascal, that needs to be synchronized (i.e. fed by or alternately fetched from) with the event queue the GUI API might provide. As this is an ubiquitous issue, it does make sense to implement the event queue outside of the backend code, and thus make it usable for all current and upcoming backends.

Michael

Giuliano Colla
to Michael Schnell

Michael Schnell ha scritto:

Show quoted text 8 lines
Of course some backends will need an event queue done in Pascal code (e.g. if it is not possible to feed events (e.g. generated by threads) to the event queue that might be provided by the GUI API, an Event queue needs to be implemented in Pascal, that needs to be synchronized (i.e. fed by or alternately fetched from) with the event queue the GUI API might provide. As this is an ubiquitous issue, it does make sense to implement the event queue outside of the backend code, and thus make it usable for all current and upcoming backends.

This is just one of the fields which needs development in Customdrawn, at least for some backends, like X11. Momentarily I've simply taken advantage of X11 message queue, but I'm also considering other possibilities, such as using Glib's GLoop, or implement one using fpc TThreads, just to mention two possible candidates. It would be preferable to have an event queue common for all backends, and therefore this implies taking into account many factors.
However, it that's what you need, I think you'll get it. Sooner or later :-)

Giuliano Colla Whenever people agree with me, I always feel I must be wrong (O. Wilde)
Michael Schnell
to Giuliano Colla
Giuliano Colla wrote
Momentarily I've simply taken advantage of X11 message queue, but I'm also considering other possibilities,

After many discussions during some years, I have been convinced, that for performance issues, an event queue provided by the backend API should be used whenever possible.

For a "Windows" backend, this is strictly always, because you can always send "Messages" to the mainthread that get queued together with the GUI and the Timer events generated by the API itself. Of course waiting on an event is done in the GUI API.

For GTK and similar backends, I understand that you can't feed events to the queue provided by the API, and that is why you need to implement a queue in user code and in the main loop you need to somehow mix the events that are fetched from both queue. Waiting might get complicated, as if you do waiting just in the GUI API, you don't wake up for events that are not generated by the GUI API itself, but are scheduled via your own queue (this problem has only quite recently be solved <on my request> for GTK2).

For a "native" backend done in Pascal code, you of course need to provide an event queue for all events (generated by Timers, Threads and possibly incoming messages from the remote GUI). Of course waiting and waking up needs to be done using directly the means of the underlying OS'es API.

It would be preferable to have an event queue common for all backends, and therefore this implies taking into account many factors.

It might be worth testing whether it is preferable to pass all events through this queue or to use the GUI API's queue in parallel for events generated by the GUI itself. I suppose a non-trivial problem is the waiting and waking up whenever the queue (any of the queues) gets from empty to not empty. If all events are passed through the queue implemented in Pascal, waiting should be done by means of an OS Library (in Linux pthreads_mutex_...() calls is the obvious choice)

However, it that's what you need, I think you'll get it. Sooner or later :-)

Yep !

Thanks a lot for listening !
-Michael