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 18:48:35 +0200
User-agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040616

Abdelrazak Younes wrote:

Henri Lesourd wrote:

Abdelrazak Younes wrote:

There are a lot of different kind of widget.

Not that much. From the point of view we are
most of the time interested in, the real situation
is just the opposite: most of the time (i.e.: 99%),
the programs you will write only need to use *GENERIC*
operations on widgets like moving, dimensioning,
catching the submit event.

Thus I simply disagree with you here, and I have
the feeling that common sense is on my side: you
are left to provide me an example which doesn't
fits my API, and still is realistic given the
context of our discussion (i.e., the set of
components you need for an editor like TeXmacs
or LyX).


It's even possible possible to have non-rectangular widget :-)

Fine. If you are interested in those ones, it's
great. As for me, I do not take those in consideration,
because my feeling is that in the context of TeXmacs
GUI, I will not need those soon (although evolving
my simple API to manage such cases is probably
possible: but if not, I don't care).


By keeping the control of such things as widget placement and size you are limiting yourself to widget with windows.

Absolutely not: in case I would need a widget which
cannot be moved and/or resized, then the methods move()
and resize() will do nothing, and that's all.

A too much extreme use of object-oriented programming
blinds you, here.


For example Qt provides dock widgets and drawer on Mac. You ought to let Qt manage these widget, there is no other way around.

If it's only on the Mac, I don't want such widgets. Otherwise,
as I said, if there are some parameters that need to be out
of my control in such particular cases, then let it be.

I now realize that my whole point since the very beginning
in fact is that the need for handling such cases does NOT
imply a need to change/extend the API.

That's the difference between polymorphic encapsulation and
encapsulation by means of inheritance.


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.


See above. IIUC your architecture, you are limiting the frontend capabilities to the one you are defining.

What you say is trivial: it's what happens with any API.

On the other hand, you do not answer the question of why
my API would be platform-dependent. As far as I understand
the meaning of the word, it is not.


In essence, you are forcing the frontend API to a common denominator

Exactly.

In fact, I follow the sanity rules of UNIX, which is able
to implement filesystems by means of only four main API
calls: open, read, write, and close.


Do you think that a filesystem is a much simpler beast
than a GUI toolkit ? I don't.

The fact remains that if you look a little bit in
the history of computing, you will see that many
early operating systems implemented horrid APIs
for filesystems, giving control on unnecessary
things, and not giving control on other important
things, without much coherence.

Finally, Multics came and they wiped all this trash
away: since now, filesystem's APIs are minimalistic
APIs a la UNIX.


while I think the core typesetting engine is the one which should define a clear and limited API.

As I said before, this is very tempting, but if
you do this, you have to implement the components
by yourself, and then it is extremely hard to have
a native look on all platforms.

Still, I agree that this is the alternative design
for what we are discussing.


The frontend will just provide a canvas where the core can draw onto. A virtual interface to the painting operations will of course be needed.

You should not forget to mention that there will
also be an awful *LOT* of detailed design work
for cloning the native look for each one of
the platforms. Much more difficult to maintain,
in my opinion.


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


By platform-dependant I meant the "Texmacs platform" because that what you are creating ;-)

Then we dont discuss the same thing: by "platform-dependent",
I meant "the very same code works identically under UNIX and
under Windows, on top of the Qt implementation of the GUI
API or on top of the GTK implementation of the GUI API".


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.


And what I am saying that the toolkit designer (Qt in our example) have done a lot of thinking about the API.

It's quite good, but not sufficiently good for allowing
you to define new components without the need of
using C++ inheritance.

Wnat we want, rather, is a 100% dynamic mechanism which
provides a way to turn widgets to *real* components,
i.e., composite objects which are dynamically built
and use signals to speak to one each other.

By the way, this is because the Qt API is of high quality
that it is easy to fold it into a scheme like mine.


Of course, the code that you are creating using the object defined with your API components will be usable by all frontends but, in most cases, programming directly using Qt component will mean much less code to begin with.

Certainly not. With my API components, basically
you need only two instructions: one for creating
the component, the other one for inserting the
component inside his parent component. Then you
can need some other instructions for setting things
like the position and the title, but not very much.

It's really difficult to see how one could do
substantially shorter.


I mean, unless you are a GUI toolkit expert yourself and you think you can do better... In this case you should simply say that you are implementing a simple GUI toolkit limited to dialogs and buttons on top of Qt :-)

That's *exactly* what I am doing !

The only supplementary (but important) point is
that I claim that with my simple API, I can in
fact wrap most of the existing Qt components.

This latter is not a matter of opinion, it is
a matter of fact: and I don't need more than
this (and neither LyX, I'm pretty sure).


That's how we do it in LyX, the only thing that the core knows about is the text canvas that we call the Work Area. the core doesn't know anymore about menubars, toolbars and dialogs. We are not 100% clean yet but coming close.

This is exactly the same in TeXmacs: the core
rendering engine only knows the drawing API
and the canvas.

But the core has nothing to do with the GUI,
anyway: in fact, the core, i.e., the "editor"
is one of the GUI components.


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,


Wrong! These are predefined ideas, things can be much more complex than buttons and dialogs.

If you start from the predefined idea that things
are complex, no wonder you end up with complex
concepts in the end.


That's precisely my point from the beginning: break
the mental barriers in your head, and stop thinking
by means of this insane object-oriented approach
which leads you to think *HIERARCHICAL*, by means
of "specializing" and adding more and more methods
for the purpose of implementing a more specific
component.


Rather, a much more powerful approach is to
think *POLYMORPHIC*, by means of always trying
to find what is *universal* in the set of classes
you are modelling.

To state it otherwise: the hierarchical approach
is pre-scientific, while the polymorphic one
is the only authentically scientific one.


We are doing software, which is design, not
science: thus these things would not matter
if the second approach were not so *MUCH*
more powerful than the first one.


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.


As a said, if your goal is to have limited support for GUI components, that's fine.

No: my goal is to have a simple API which can be used
to easily wrap most of the existing Qt GUI components.

And that's what I do.


Qt provides signal and slots for the typical needs for user interaction with button, by handling this kind of events you are not simplifying things.

I had a look at what a button really is, and I concluded
that I need only *ONE* event, the one which arises
when the button is clicked: that's this one I wrap
behind my "submit" event handler.

Difficult to do simpler. Once again: the point is that
in fact, lots of components are like the button, you
only need one event in the API to be able to use them.


Well, we have a virtual interface for the event handler (QApplication). So we just intanciate that class and call QApplication::exec() from main(), that's all. But even that kind of stuff should be transferred to the frontend, I'll do that later for LyX.

Then you will end up calling the API of your frontend to
start the loop, which is exactly what I do. No difference,
here.



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).


I don't get it, why do you want to keep control of the loop?

Because TeXmacs is monothreaded, it enters a main loop,
which looks like that:

while (!finished) {
 polling sockets
 polling alarms
 polling GUI events
}


If you need to call QApplication::exec() from this
main loop and cannot exit, then you have a problem...


I also implemented a multithread version of this,
but it turns out that I cannot avoid losing time
in synchronizing the two loops.

Thus it turns out that the monothreaded design
enables a interaction of a better quality.


And as I said before, putting the pollings in
a Qt handler forces to rewrite other parts of
the code, and especially removes our previous
control on the timings and on many other vital
things.


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).


You can use a timer do that kind of polling, no need to mess with the event loop.

I know that lots of people think they can poll sockets,
keyboard, etc. with a timer, but in doing so, you turn
what should remain a genuine interruption to a polling,
which is bad style, to say the least.



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.


What problems? Again, are you in the business of a typesetting application or in the toolkit business?

You are in the business of designing an interactive application
with the best possible look & feel. In this respect, controlling
such details of how interlacing I/O events is of chief importance.

GUI tookits are relatively poor at that, they are designed for
the most usual cases (i.e.: not for very sophisticated applications
like interactive editors), and they do not give you all the
control you usually enjoy when programming directly on top
of X11 or of Win32.


You are not forced to use Qt's solution for socket (we don't either) but there's nothing that forbids that.

If I don't (e.g. because I want to use select()), then I need
to put the polling in another thread, which I will need to
synchronize.

And if I use Qt's solution, I need to trust them to do the
right thing, which is not sure at all, because Qt people
are good at designing GUI components, but perhaps not as
good for other kinds of things: the problem is that they
tend to force you into their scheme.


Regarding the event loop and timers, I don't understand what is the benefit of not using them.

If it were the only kinds of events, it would be OK: but
there are other kinds of events which are often available
only by means of the OS (e.g.: file changed).


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*.


Well, if the thing is already defined what is the need to redefine it? ;-)

The need is in defining a less verbose, and less
static (as far as the C++-based spirit of Qt is
concerned) way.


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 ;


You can put in place a communication protocol for that kind of stuff. No need to encapsulate the GUI API. In LyX we just use what we call a function request which is an object that is understood by the core and the frontend.

Then it's more complex and tedious to maintain, for
no real benefit besides the hypothetic possibility
of augmenting the API later.

Much better to know what you need in the first place.


But you could also really split the application in two process and use socket or pipe based communication between the two if you truly want to be Qt independent.

That's the first solution I tried, and by the way, you
can use my toolkit in such a multithreaded mode. But
there is an overhead due to messaging and synchronization,
and btw, this issue is quite orthogonal.

Another point is that you still need a fine-grained
control of the Qt event loop, because in order to
be able to modify dynamically the widgets, you can
only do it from inside a handler, thus in practice,
because the function calls come from the other
thread, you somehow need to stop the Qt event
loop first (that's the kind of little b!@@#$t
which is not explicitely said in the Qt documentation,
but that's the way it is).


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


Well, if you replace 'you don't' by 'I don't', I would agree :-)

Now we finally agree :-)


As I said above:

int main(int argc,char **argv) {
   MyApplication app(argc, argv);
   return app.exec();
}

MyApplication would of course derives from QApplication in my world. But I know that isn't the answer you were expecting.

No, because:

1. I don't want to be forced to use C++ inheritance
  in my code, and especially not directly from
  a Qt class ;

2. I don't want to be forced to put all the code of
  my event handlers into Qt handlers: what I want
  is clean, Qt-independent messages that I can
  simply read from my C code ;


Well, in a C world maybe. Having the core lib in C is maybe desirable (that's not my personal taste) but the GUI should be implemented in C++ IMHO, especially if you make use of C++ toolkit.

No.

C++ raises lots of problems which will prove
to be impossible to solve later, e.g., dynamically
reloading a component: given how current linkers
work, you are anyway forced to implement a C
wrapper around any C++ API, if you want to use
dynamic loading.

Thus there are *very sound* reasons why sticking
to C is mandatory if you want to implement
extendible software.


Of course, I don't know if it will finally be
done in TeXmacs, but the possibility of implementing
and compiling a Qt component independently, and
then loading it into TeXmacs without the need
for recompiling TeXmacs is one of the important
reasons which lead to this choice of wrapping Qt
behind a C API.

But perhaps you don't want to do this. In any
case, this little thought experiment reveals
the limits of C++-based designs: if you use
C++ without specific care, such designs are
usually very static.


No wonder, since Mr. Stroulstrup once said:
[[
I also maintain what I consider a
healthy suspicion of all kinds of
run-time code modification (self
modifying code, dynamic linking,
plug-ins, run-time patches) because
they too often bypasses careful analysis
and whole-system testing.
]]
 B. Stroustrup (interview): C++: past,
 present, and future. Frontier Channels,
 September 2006.


As for me, as you probably guessed, I of course
strongly disagree with such an (irresponsible,
because wildly irrealistic) statement.


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


Maybe the question is "what else could other developers want?"

I'm implementing a wrapper for the purpose
of solving TeXmacs GUI toolkit's portability
problems, I am not implementing an OS.




reply via email to

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