> It has strange windows management.
The windows in Morphic are not really the primary objects like they are in
most UI systems. As far as I can tell, they were made so that the existing
tools in the MVC environment could be ported quickly to Morphic. That's
the origin of all the Pluggable* components; you will see that there are
pairs of them with similar APIs for MVC and Morphic.
> Inactive windows disable all its components (look at Zurgle to see it).
Zurgle has, as I recall, its own idea of focus and window activity.
> You can't switch
> between submorphs using Tab key etc.
We have had this working from time to time.
> One of the most strange features of Morphic and MVC is the single world
> cycle. One long computation can make whole GUI unusable.
How is this different from what was done in Mac OS 7 or Windows 3.1? I
recall many applications that would make the whole GUI unusable by doing
just what you describe in response to a UI action.
Later operating systems tended to assign a separate thread per
application; they could easily maintain the behavior of the rest of the
system by using message queues.
In fact, if you look at Squeak as a single application (which it is,
despite the windows) ours is a fairly typical architecture. Events come up
from the VM and are dispatched in a single loop.
There is enough shared state in Squeak that having multiple GUI processes
would require quite a bit of work for little benefit if you wanted
anything more interesting than a "windowing system". I want to have live
objects in my world, and I don't particularly want them confined
exclusively to windows. As soon as morphs need to talk to each other
(which is not generally the case with windows but is essential for pretty
much everything else we do with Morphic) you wouldn't be able to call the
methods of other morphs directly any more, which would require a number of
changes. You'd probably have to distinguish between top-level morphs and
other morphs; the top-level ones would have their own message queue, etc.
But then there would be a difference between (say) a RectangleMorph loose
in the World and one that was embedded in a window or other top-level
container: the one in the window could have its methods called directly
and would be a "second class citizen" intended only for embedding, and the
one loose in the World would not be able to have its methods called
directly. This would be like the distinction between "widgets" and
"windows" in many windowing systems.
I agree that mixing models has led to strangeness; the attempts to make
the SystemWindows behave more and more like operating-system windows
despite their existence alongside other non-window morphs have not always
resulted in consistent behavior. But at least it got the MVC tools working
in Morphic. One example of this strangeness is the "topmost window"
concept which is completely at odds with the existing Morphic layering;
another is the concept of "window focus". Morphic itself doesn't have
focus other than the halos, but the concept was added to the windows. So
if you have a mixture of windows and non-windows in the world, you will
sometimes see situations where the Z-ordering will suddenly be reorganized
(for instance, after you enter a new project or save the image).
As it is now, it's quite simple to put long-running computations in
background threads; you just don't let the background threads call methods
directly on Morphs. We have addDeferredUIMessage: to queue up action from
the background threads for later execution in the UI thread during the
next window cycle.
> It's not a feature
> of Squeak's process scheduler. I have created an experimental window
> manager with separated message passing cycles, all GUI messages were sent
> through shared queues and it has worked perfectly.
But Squeak isn't a window manager (despite the things that look somewhat
like UI windows), and the things in the World (windows or other morphs)
aren't separate applications. Or, looked at another way, every morph is a
separate application whether or not it is a top-level morph (they each
have their own step methods), but then there is still no distinction
between top-level morphs (well, other than the World itself) and embedded
morphs. Top-level morphs are just submorphs of the World, and a lowly
StringMorph or RectangleMorph deep in a construction somewhere inside a
window is no less live than the window itself.
If you wanted to make a UI in the style you describe -- merely concerned
with standard kinds of windows and UI elements inside them -- many of the
issues around intra-Morph communication would not be a problem. But you're
missing the point, I think; Morphic was not intended (as far as I know) as
a windowing system. As you point out, the MVC system is much closer to
this model, with its controllers that are associated with things that look
like windows on the desktop.
Whether Morphic is the right design for the kinds of things *you* want to
build, I don't know. Maybe it isn't a good fit.
However, there is nothing that I can think of in Squeak that would prevent
you from writing a completely different UI system fairly easily. In fact,
there have been several of these already: the Parks PDA that John Maloney
did had one, his Scratch system has another, Andreas' Tweak system has
another, Croquet has another, and so on.
The co-existence of MVC and Morphic shows that it is possible to make a
completely different UI model and still re-use the basic UI system
(events, canvases, invalidation, etc.). We could probably make the work
required to add different kinds of Projects/Worlds a bit easier, though;
there's a fair amount of code at the project level that assumes that
projects are either MVC or Morphic.
> That's a very interesting statement. How do you imagine this working?
> Do you mean getting rid of all the UI that currently uses SystemWindow
> (Browsers, Debuggers, etc), replacing them with Self-style outliners?
> Or do you just mean making SystemWindows be morphs like any others and
> getting rid of all the special cases around them?
I meant that as soon as developers see things that look like windows (and
menus, I suppose):
- they have certain expectations as to how they should act and feel, which
is not unreasonable since they look familiar.
- they associate their previous concepts of "window", "widget", "event
loop", etc. with the Morphic artifacts that appear to correspond to
those concepts.
- they then get frustrated when they run into differences between how
these familiar user interface elements act (and look) in Squeak and how
they act and look in the operating system with which they're most
familiar.
- they also miss the design philosophy which doesn't differentiate between
submorphs of the World and submorphs of those morphs. There is no
distinction in Morphic between a "widget" and a "top level Morph".
I'm not saying that the tools that we have in Morphic that happen to live
in windows aren't useful. It's just that there's this disconnect between
things that want to be their own mini-worlds with an idea of focus and
locality (i.e. windows and their embedded morphs) and things that don't.
I'm also not arguing that Morphic has the best solutions to the problems
of event routing, layout, drawing, etc.. As someone who has done a fair
amount of Morphic programming, I feel strongly that we can make Morphic
better than it is now. However, I'm not sure that a wholesale refactoring
of Morphic would be worth the time at this point, as there are a couple of
important new UI systems in the works (Tweak and Croquet), and I also
think that the desire for a cleaner, more "standard" user interface that
includes the elements that people are used to is not necessarily best met
by Morphic.
As you know, there's lots of stuff in Morphic (and Squeak in general) that
is a result of its focus on being the platform for EToys. I think that
much of the current complexity of Morphic is due to design decisions (made
under time pressure, of course) from EToys (and Alan's various demos)
creeping into what started out as a much simpler system.
For example, looking at different historical versions we see:
v 1.31 (before EToys): Morph selectors size 231 Morph withAllSubclasses
size 101
v 2.0 (the dawn of EToys): Morph selectors size 347 Morph
withAllSubclasses size 129
v 2.1 Morph selectors size 357 Morph withAllSubclasses size 138
v 2.8 Morph selectors size 540 Morph withAllSubclasses size 269
v 3.0 Morph selectors size 924 Morph withAllSubclasses size 343
v 3.6 full Morph selectors size 1090 Morph withAllSubclasses size 394
the Squeakland developer's image that I'm working on right now, with m17n
and Connectors in it: Morph selectors size 1258 Morph withAllSubclasses
size 444
An example of this effect is that there are two different and conflicting
idioms (well, three if you count my work in Connectors) for associating
behavior with UI events:
* You can override #mouseDown:, etc. to get the behavior you want
* You can plug the EventHandler by using #on:send:to: (I think that this
may have been added for triggering EToys scripts from UI events)
* You can override #processEvent:using: for more control over how things
are handled (I do this in my QHSMMorph which is the basis for my new
Connectors)
And there's also one-off variations on this, like (some of the) buttons
that give you a different way to plug the behavior.
> It would be nice to see some kind of proof of concept of a
> Morphic-without-windows, even a very rough one...
We have one. It's called EToys.
I use Morphic all the time with Connectors and its various morphs and
menus without ever having to see windows.
> It would be nice to see some kind of proof of concept of a
> Morphic-without-windows, even a very rough one...
If you think about what windows do for us, you'll see that there have to
be other ways to do what they do.
What overlapping windows do (off the top of my head):
* they provide single grabbable object that acts as a container and may be
moved or overlapped with others to save pixels and limit what you have
to look at at any instant
* they bundle several related UI elements together and often let you
resize the areas that those elements occupy
This isn't really very much.
We've seen many environments that don't use overlapping windows at all,
ranging from the very task specific (CAD programs, etc.) to different user
interface models (like the visual languages) to all-text environments like
some versions of Emacs.
If the problem is just being able to re-use pixels and organize what you
see at any instant, then all we need is some facile way to remember the
various arrangements of things that we've constructed, rearranged, or had
pre-constructed.
Instead of having to stick things in windows (or other containers), if
there was a more general way to specify the arrangement constraints of UI
elements (along with wiring up the events, etc.) then that could be used
both to glue UI elements together into tools and to glue those tools into
task-oriented snapshots of a workbench or desktop configuration. Windows
themselves aren't needed for this purpose, though it is nice to have
common UI elements for resizing and grabbing.
The ownership relationship in Morphic is an example of a global policy for
such constraints that mostly seems to work well but can be limiting
sometimes. I just added the ability for Connectors to attach to submorphs;
this introduced the necessity to add new accessors to EToys so that the
embedded pins and their owners could talk with each other.
-- Ned Konz