the ProWesS window manager
The ProWesS window manager currently has a few limitations which can be very annoying when writing certain types of programs. There are a few things which are currently not supported, but which could make life much easier, or could make ProWesS more
attractive and/or user friendly.
One of the things which can be improved is the efficiency and power of object types, and better handling of messages and events.
Difference between an event and a message :
An object can react both to messages and events. In principle events
are generated by ProWesS itself and messages can also be sent by the user (using the PWChange command).
The difference on the implementation level is that an event is handled at the object level - thus may be different for each object - while a message is handled by the type.
Also messages are forwarded to the parent object when on object doesn't handle it itself. This passing of unhandled messages to the parent object was not done in ProWesS v1.
For queries the query is normally passed on to the parent object when not answered, but it can also be flagged that only the designated object can get a chance to answer the query.
Message handling :
When handling messages using the PWChange keyword, the system should first ask the recipient object to handle the message and if this object does not wish to handle the
event, the message is passed to the parent object to allow that to handle it. This continues to the grandparent object etc. To make this process slightly more efficient, the object type can indicate mask of messages it may accept. This can allow the PWChange routine to know in advance if it can skip an object as it will never accept the message. The messages will be handled by separate routines for each message. This allows the compiler to do more and better optimizations.
Each message routine gets two objects as parameter : the object which receives the message, and the object to which the message was passed.
Event handling :
It would be better to have specific event handling routines for each possible event. This is more efficient, and gives cleaner code. To reduce the memory consequences, there are general handlers for the type and
handlers for the specific object. The object is searched for the event handler before the type.
These indicate some changes in the internal mechanisms which are used in ProWesS and which are important when writing ProWesS types. Most of the improvements are direct consequences of the limitations of the current system.
When positioning objects in ProWesS v1, objects are positioned in rows and columns. The design is flawed as rows can actually change to columns and vice versa, so this will be fixed. Also the current version allows objects in a container to have the same height (in a row) or identical width (in a column). More powerful constructs are currently not possible. This is now remedied by having containers which actually determine the
size and position of the objects in it (though the object can tell its preferred size). This means it will be possible to have objects in a grid all with identical size. Another feature which is not possible in ProWesS v1 is a "multiple document interface". This means that the objects in it can overlap. It will also be possible to have a container which is smaller than the contained object. Using this kind of object, you can introduce an object to include some other object to make
them smaller and scrollable.
Improved positioning :
All the objects which can be created should be positioned in an object tree. Each system contains one object tree, and this tree represents all the menu objects in window which can represent that system.
The object types can be of two types : branch objects or leaf objects. A branch object can have both branches
and leaves connected to it, but a leaf object can not have any children in the tree.
Visibly speaking, all objects are always fully contained within the parent objects area. Though the virtual area may be bigger, the visible part can't be.
Objects which are at the same level in the object tree are contained in the same parent objects and may (partly) overlap. The objects are ordered from front to back.
Size of an object :
The size can be determined by each object individually. The object can determine its preferred minimum size.
Normally speaking an object will make sure that the contained objects are completely visible (except for things like a "multiple document interface").
Each object has to assume that it's size can be changed later on. It can be notified of this (to allow resizing of
child objects or making sure the internal state remains correct). This is because the parent may resize the objects to conform to some kind of rule (e.g. all equal width).
In principle, a window has a fixed size (which may be scaled), but some objects may tell the system that they want to resize depending on the amount of information in them and the amount of screen space. These objects can then resize ("autosize") their contents (they should know the possible increase amount).
When there is room left, the next object which allows autosize will get a chance.
Key presses will be handled similar to ProWesS v1. There will be some differences. Normally key presses are handled by the system, only if there is no action for the keypress, then it is passed on to the "current catch object". Switching between catch objects was quite cumbersome to set up, you had to tell
each object what the next and previous one is, which is easily bugged, and very unpractical. This will be improved. For the key presses which are directly defined, it will be possible to check which keys are already in use. This allows automatic assignment of key presses by the objects !
Keypress handling :
All key presses should be handled by the system (this is
also true in v1, although this was not stated as clearly). It should be possible to query whether a keypress is already "in use". Each keypress can be connected to an object. When the keypress is activated, a user defined (e.g. "keystroke") event is sent to that object. Obviously several key presses can be attached to one object. However, each keypress can only be linked to one object.
Key presses are case sensitive. However, when a key is pressed
which is not linked to an object, then the case is changed and a matching object is searched again.
Switching catch objects :
All objects (or their type) have to contain a flag which indicates whether it is possible to catch keypress. This doesn't mean this is always the case, but just that it could be possible. Objects could then be stored in a linked list of
"possible catch objects" when they are added to the system. The order in this list is then the default order for switching catch object with <tab> or <shift tab>.
Of course you have to be able to explicitly change the order of objects in the list.
When moving through the list, it should still be checked whether the object is effectively willing to accept catch events.
When objects are deleted in the old ProWesS, all the child objects are also deleted. In ProWesS v2, it will also be possible to delete an object, while keeping the children in the menu. This can be useful when an object has reduced its size so that you no longer need a parent object which makes it scrollable.
Deleting objects :
To make sure that objects can contain links to other objects and make sure their internal state remains consistent, all objects in a systems need to be notified when an object is removed from the system.
Some other important changes are the handling of move and resize of a window. In the current version, each window automatically get a scale border to allow this. In
ProWesS v2, there will be no default handling, all move and scale events have to be performed by an object (normally as a result of a user action).
Creating a system :
The handling of move and rescale should be initialized by the types. The system should not incorporate how this is interfaced to the user. There should be a type which is intended to be the top level.
When this is done compatible with v1, the type will implement the scale border.
When a type is created in a new system, then the system has to include the top level itself (if the object was not of that type).
In principle this should not be necessary, but it is done for extra user friendliness and for compatibility with v1. This option can be disabled by passing a creation tag.
Window scaling :
It will be possible for a window to be bigger than the area which is used on screen. This can be because the window is larger than the screen, but may also be forced otherwise. As a result, you could allow the user to shrink the window.
There are some smaller changes. The window will be redrawn more
often to inform the user more quickly. This means that you no longer have to do that in your types (in fact, you aren't allowed to redraw in your types, if you want your object to be (partly) redrawn, you have to inform the system to do that, only redraw events may actually redraw). Redraw is handled quite differently, as objects in the window may overlap. So it will be possible to have a floating window. An object is only allowed to draw the bits were it is on top. Portions of the screen
which are covered by other (probably child) objects, are no longer modifiable. This will make some nice affects possible (like very fancy backgrounds).
Redraw of objects :
The system should redraw more often. In particular, the window should redraw at the end of each access to the system if the system is active and does not need resize. Redrawing will be done with
clipping. This makes sure that contained objects do not need redraw when the parent is redrawn. This can also have visible advantages, e.g. when having a parent object with a fancy background. More importantly, this also allows windows which float on top of the rest.
There are some important changes in data hiding. The internal structures will be better hidden from the types. This means that in the
future, the system could very easily be modified to allow sending messages to objects in a different job, without the need to change the interface for the user or the types. Actually it is quite likely that it will immediately be possible. That way, you could have interacting windows. Object identifiers will also really be that, and not pointers to unknown structures. This gives better data debugging as most invalid object ids will be caught before doing damage.
Data abstraction :
All the internal data structures should be hidden. Each routine should get at least two parameters : the object identifier (used to interface with the ProWesS system and the ObjectData structure. This structure can be defined by the type.
Multitasking options :
The ProWesS interface should be defined in such a way that it would be possible to access a ProWesS object from a different job then where it was created. This means that there should be no direct access to memory except in some well defined cases (e.g. the ObjectData). Definitely no access via object id's which happen to be pointers (very deadly).
Some implementation related changes are
the deprecated PWAddType call (I don't think anybody used it up until now, a dummy will be implemented which just returns an error). The handling of unknown messages is also handled. It can be annoying to return an error for an unrecognized message (e.g. because the type is not the very latest version), as the added functionality may not be vital for the programs functioning.
Unknown messages :
The handling of unknown messages has changed. In v1 you would get an ERR_IPAR after handling the remaining messages. This is now different. If a message in not recognized by the object, its parents or the system, then the tag is just skipped. For debugging purposes however, you can query the system to know how many messages in the last PWCreate or PWChange were not handled.
Of course, when
there are going to be so many changes, there is always the problem of backward compatibility. I realize this is very important (I would prefer not having to bother, but well). Everything possible will be done to make sure that applications which work in ProWesS v1 also work in ProWesS v2. The types however will not be compatible. The internal workings are so different that it would not be wise to try and support the same structures. As an aside, the new structure for the types will be easier
to use, so writing new types will be more straightforward. What's more reuse of types will also be much easier.