I’m working on a
redesign of Morphic in Squeak. I named the project Morphic 3.0, because I consider
the Morphic in the Self project to be “Morphic 1.0” and the current in Squeak
“Morphic 2.0”.
Morphic is great. But
it can be enhanced. It also needs cleaning. The original design as it first
appeared in Squeak was pretty clean. But as time passed, more and more
functionality, applications, and so called “enhancements” were added. Morphic
became too big and complicated.
Besides, John Maloney
himself said each morph should define it’s own coordinate system. Read it in
the interview in issue 3 of SqueakNews.
BTW, SqueakNews is one of the coolest things ever in the Squeak community. If
you haven’t read them, download and enjoy all 5 issues.
Also Dan Ingalls when presenting Etoys spoke about “the
numerous temporary perturbations it has caused to an otherwise elegant Morphic
graphics system”. This was for Squeak 2.0! These perturbations became permanent…
I want complete independency of Display
properties such as size or resolution. That’s what we already have in our
printers, isn’t it? I’ve never seen warnings such as “best printed with 1200
dpi” or “minimum resolution 1200x600 dpi”. Postscript is a very old and widely
adopted technology. We need something alike for GUIs. Also, the programmer
should not need to worry about such details.
I want to separate the handling of
coordinate systems from the morphs themselves. A morph should only need to say
“I want to use a log scale”, instead of needing to convert every point it draws
to World coordinates himself.
The Morph hierarchy should not be a hierarchy
of shapes. The shapes of an object doesn’t’ need to be constant, and shapes are
not that important.
Class
Morph should not
include general concepts of color, border, etc. Each morph class decides which
are the relevant properties for its instances. The same goes for submorph
aligning.
There is no
concept of pixel. The GUI is thought at a higher level. Moving away from pixels
to general coordinate systems is like going from bits to objects. All the GUI
is independent of pixel resolution. All the rendering is antialiased.
Every Morph
defines a space and coordinate system. Its #drawOn: method and the location of
its submorphs are expressed in its own
coordinate system. This idea is from John Maloney, the designer of Morphic 1.0
and 2.0. Class Morph has an instance variable ‘coordinateSystem’ to hold an
instance of the MorphicCoordinateSystem hierarchy.
The coordinate
systems are 2D but are not restricted to Cartesian or linear. Useful nonlinear
coordinate systems include polar, logarithmic Cartesian, hyperbolic and
map-like projections.
A
Morph is placed somewhere in an owner. Class Morph has an instance variable
‘location’ to hold an instance of MorphicLocation. A MorphicLocation specifies a
position, extent, and rotation angle expressed in the owner’s coordinate
system. Separating them eases the moving, zooming and rotation of morphs. The
user can easily move, zoom and rotate morphs. Please note that we are talking
about zooming and not resizing.
In general, morphs are not
resizeable. The general operation available to the user is called zooming. The
zoom is defined by the extent (width/height) in the location of the morph. The user
can modify the location of any morph. However, the size of a morph is defined
by its own coordinate system and this is generally not modifiable by the user.
If some morph also wants to offer the user the possibility of modifying the
coordinate system (an hence the size), it is it’s own responsibility.
All coordinates
are Float numbers. This is good for allowing completely arbitrary scales
without significant rounding errors.
The Morph
hierarchy is not a shape hierarchy. Morphs don't have a concept of a border or
color. There is no general concept of submorph aligning.
Old Morphs and
new Morphs can live together in a World.
Suppose we have a music application. The relevant Morphs are the World,
a MusicSheetMorph and some NoteMorphs. The World contains the musicSheet. The
musicSheet has some notes.
The World coordinate system is that of the Display. The musicSheet
occupies some area in the world, defined by the user and stored in the
musicSheet’s location instance variable.
The musicSheet defines a coordinate system where the x axis is time in
milliseconds [0..2000] and the y axis is midi note [0..127].
The notes have a position in musical coordinates, such as 150mS@56. They also
define a coordinateSystem [0..1]x[0..1].
Let’s see how the rendering works. The #drawOn: method of the notes asks
a MorphicCanvas for drawing services. These calls use coordinates between 0 and
1 for drawing the shape of a musical figure. The canvas uses the note’s
coordinateSystem and location to translate them to musical coordinates. Then it
uses the musicSheet coordinateSystem and location to translate them from
musical coordinates to World coordinates. Then it draws as requested.
To do this, I
needed to start with Morphic 2.0. I took Squeak3.7-5989-basic. Then I removed
almost all applications. The result is my Cleaner Squeak image that’s good for
study (and doesn’t include any of Morphic 3.0). You can find it here.
Then I renamed
the Morphic 2.0 Morph hierarchy as OldMorph. Not much of it will remain.
However, I’m not redoing PluggableMorphs. This means that browsers and similar
applications don’t need to be rewritten.
We already have a
new Morph, MorphicLocation and CartesianCoordinateSystem classes. Not much of
the new design is done, but we can create instances of Morph and subclass
TestMorph. The hard work of knowing which OldMorph protocol is needed for a new
Morph class is already done. And this protocol is implemented in the new
design. This is not trivial: Morph and OldMorph are completely different.
You can see
TestMorph>>drawOn:. It draws in its own coordinate system, without a
mechanism for handling rotation (as in OldPolygonMorph) or an external
transformation (as in general flexed OldMorphs), even though both rotation and
zooming work ok.
Nested morphs
are not working correctly yet. But you can download my latest image to play with it.
I know there is
not much to look at, but If you'd like to think a bit on the way to model
locations and coordinate systems, and discuss about alternatives, etc., that
would be great. I want all this to work with any 2d coordinate systems:
Cartesian, Polar, various cartographic, logarithmic, hyperbolic, etc. But will
my ideas and design scale? Is there a better way?
Juan Vuletich