texmacs-dev
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Texmacs-dev] Re: Compiling TexMacs on OSX


From: Henri Lesourd
Subject: [Texmacs-dev] Re: Compiling TexMacs on OSX
Date: Tue, 17 Jun 2008 15:54:40 +0200
User-agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040616

Abdelrazak Younes wrote:

Henri Lesourd wrote:

It looks like one of the root causes of why you feel
it's difficult to support multiple toolkits is that
you are trying to design *too much fine-grained* APIs.


Hum well, the API you are describing below is *very fine-grained* :-), more details below.

It captures the essence of what widgets are, namely,
rectangular areas of the screen which can be recursively
embedded inside one each other.

As soon as you know that these aspects of widgets are
universal, of course you provide detailed control over
that.


The fact remains that I agree with you that supporting
multiplatform software is hard. But there are ways
to turn this easier by means of designing the APIs
carefully, especially: thru your API, you should
*not* try to give control on details which, as a
matter of fact, are platform-dependent.


Much of the API I see below is platform-dependent IMO.

You would need to point me exactly why, because
it seems to me that my API contains no detail
related to any particular platform or environment.

But perhaps we have different definitions
for "platform-independent", in such a case
we should agree on a definition of this word
first.


Otherwise, you end up having to support the whole
functionality on multiple platforms, rather than
having to support only a wrapper on the many platforms
you want to target (which *is* feasible and not
too hard, if you do it well).


You seem to miss my point: those indirections caused by your encapsulation is not worth it.

Yes it is worth, because the code written on top of the
first low-level API (the "hardware abstraction layer" if
you want) is completely reuseable, you don't maintain a
different version of this code for each platform.


Maybe you think that you'll be able to factorize some code between frontend because a dialog is a dialog and a button is a button.

No: I think that I will be able to factorize lots of code
because the API for a dialog and the API for a button have
a lots of common points, e.g., dialog and buttons are rectangular areas of the screen, they can be moved, they can send you back a "submit" event with the appropriate meaning in each one of
the cases, etc.

In the end, it turns out that when you want to wrap Qt
buttons behind my API, 80% of the code is pure wrapping,
e.g. something like that:

button::move(widgel *w,int x,int y) {
 ((QWidget*)w->wdg)->move(x,y);
}

, and the rest is wrapping the specific Qt events (e.g.,
the "clicked" event) behind one of the few handlers for
the generic events (e.g. "submit").


And THAT'S ALL ! Thus once the API is defined, wrapping
a new Qt component behind it is a matter of less than
one hour.


But I am forecasting that the glue code necessary to fit into your defined API will be bigger than the toolkit code to define the dialog and the buttons.

It is definitely not the case.


Still, there remain hard cases, especially for
features you absolutely need, but are not well
standardized across toolkits, and thus are platform
dependent. A chief example of such features is
how to encapsulate the main loop of the underlying
GUI toolkit in a portable way.


And that's exactly why you should try to avoid it. We had a lot of problem managing the event loop in LyX; I cleaned up that so that the core doesn't know about the event loop, literally.

It has to be somewhere, anyway, and there are well-known
techniques to abstract such a thing (i.e., by means of
a queue).

The only problem is that it's never sure that the GUI
will provide us with the control we need on the main
loop (specifically: the ability to stop the loop from
outside, or either to run the loop for only one event,
or either to run the loop till it becomes idle).

In any case, this thing has to be implemented somewhere,
all the more because the pure X11 TeXmacs loop was
performing some important polling (e.g., listening
to the incoming socket).

And NO, it is not an option to turn this polling loop
to a Qt event handler, that's exactly what has to be
avoided, because then you need to use *their* implementation of sockets, timers, etc., which would raise other problems.


But we make it easy for the advanced user to modify his menubar at will. So a Mac menubar is possible without any compromission.

In my opinion, trying to give too much control to
the user is a mistake, or at least, it is something
which will easily cost you a lot of (neverending)
effort. I would rather advocate sketching the basics
of what you really need as precisely as possible,
then *stop* the work in providing more and more
details in your API.


I was only talking about a menu description file. This is not something you want to hard-code.

OK, but for this, no detailed control is necessary,
you only provide the information to fill the menu,
which is something which *HAS* to be possible in
any (coherent) implementation of menus.

This thing is on top of the wrapping of the GUI
toolkit, anyway, thus it's not directly related
to the current discussion, in fact.


No: the reality is that designing a portable API (i.e., what
you call the "virtual interface") is *hard*. But if you do
it well, i.e., if you capture the real nature of what a widget
is, then you can succeed.


And your locking yourself in your portable API.

As soon as I know I will not need to change it in
the future, it's OK.

YES, it means that I define in the first
place what a "widget" is, and that in the
future, I stick to that definition. But as
a matter of fact, in computer science, defining
what you want to implement is *necessary*.

If you want to implement an other concept
later on top of this one, then it should
be *another* API.

Most of this portable API will need to be reimplemented by the frontend.

No, no, and no !

Most of the implementation of this portable API is
pure wrapping: look at the code, really it is !


This is what I called glue code, at application level, we are not (IMHO) in the toolkit API business.

For me, a toolkit API should provide you with
the basics, namely:

1. being able to move and redim, to hide and
  unhide widgets ;

2. being able to move a widget inside another
  (composite) widget, and to detach a widget ;

3. Being able to program events. For high-level
  widgets like buttons, filechoosers, etc., only
  a "submit" event is necessary. For lower-level,
  programmable widgets, you need input events,
  i.e., mouse and keyboard events, and the repaint,
  plus an API to draw on the widget (the high-level
  widget draw themselves, and there is a priori no
  way to change this behaviour) ;

4. Being able to start and stop the main loop, and
  provide you with an event queue to poll the incoming
  events ;


That's exactly what my API provides, and what I claim
is that you don't, and will never need more in the
future.

You can disagree with me, but then it means that your
goal is not the same as mine, which is to provide a
simple, limited API for encapsulating all the usual
widgets.


void widglib_finish();


Sorry but this looks to me like a lot of work for basically not much gain.

Are you sure we speak about the same thing ? You need
routines to start the main loop and routines to stop
it, how could you do without ?


A typical C program creating a window with only a
button looks like this:

int main(int argc,char **argv) {
 widgel *win=NULL;
 widglib_start(argc,argv,0,0);
 win=new_widgel(WidgetGrid,NULL);
 widgel *b1=new_widgel(Button,win);
 widgel_setTitle(b1,"Hello");
 widgel_setRemoteHandling(b1,WevSubmit,1);
 widgel_setTitle(win,"The window");
 widgel_show(win);
 while (!widglib_finished()) {
   widglib_step(); // We are running in synchronous mode
   if (widglib_event_pending()) {
     widgel *w;
     widgev *e;
     widglib_read_event(&w,&e);
     if (e->type==WevSubmit) {
       if (w==b1) {
         widglib_finish();
       }
     }
   }
 }
 return 0;
}


Although it's perhaps possible to make shorter,
it seems to me that the API provides you with
a *very* easy way to implement interactive
applications.

And as I said before, the API is completely
cross-platform, you should be able to run
the program above on any platform on top
of which the API has been implemented.


I just wanted to warn you of the possible consequence, that's all.

I know that it can raise problems later
if one misses the point in the beginning.


But you seem to be pretty convinced of your case so I won't insist :-)

It's just that it seems to me difficult to do
simpler, and that this API is easy to implement,
and easy to use as well.

What else could I want ?, this is really the question.





reply via email to

[Prev in Thread] Current Thread [Next in Thread]