home *** CD-ROM | disk | FTP | other *** search
- Dreamscape: notes to users
- ============================
-
- Contents
- --------
- - Dreamscape pseudo exception handling
- - Creating gadgets
- - Using SaveAs windows
- - Returning menus from pop up gadgets
- - ColourDBox problems
- - Showing and hidden handlers
- - Multi-clicking/dragging
- - Graphics renderers
- - Errors during redrawing
- - Pane handling
- - Document and view classes
- - Accessing low-level features
- - Graphics and font handling
- - The iconise() method
- - Using Dreamscape from C
- - Deferred delete templates
-
-
- Dreamscape pseudo exception handling
- ------------------------------------
- Since Acorn's CFront-based C++ compiler doesn't support exception handling,
- I've had to write a pseudo exception handler for Dreamscape. Note that this
- is by no means a proper exception handling system. It doesn't free up stack
- chunks that are no longer needed after an exception, and it doesn't call the
- destructors of objects in the stack. It also only handles RISC OS errors.
-
- The main purpose of this exception handling system is to stop an error from
- causing the program to die with a postmortem message. It will also catch the
- 'illegal address' and 'illegal instruction' exceptions and allow the program
- to continue running. (Remember that these errors might be caused by the
- program corrupting its data, in which case carrying on might not be a good
- idea, although the user still has a choice and it may be safe to carry on
- anyway).
-
- To use the exception handler, use a #include "x.h" line at the beginning of
- the file. To catch an error from a non-x-form SWI or from x_throw(), use a
- structure like this:
-
- x_try {
- ... // errors occurring in this block will be caught
- }
- x_catch(error) {
- ... // handling code here
- }
-
- The x_try block must always be followed by an x_catch block. To throw an
- exception, you use the x_throw() function. This comes in three forms:
-
- void x_throw(RISCOSError *error);
- void x_throw(const char *message);
- void x_throw();
-
- The first version throws an exception from an actual RISC OS error block. The
- class RISCOSError is a RISC OS error block and can be cast from or to OSLib's
- os_error struct if necessary. The difference between the two is that
- RISCOSError is a C++ class and provides extra functions and constructors:
-
- class RISCOSError {
- public:
- RISCOSError();
- RISCOSError(const char *m);
- RISCOSError(const char *m, unsigned n);
-
- operator const char*() const;
- operator char*();
-
- unsigned number;
- char message[252];
- };
-
- The second version throws an error created from the given textual message,
- using an error number of 0. The last version of x_throw() throws the last
- error that occurred; useful for nested exception handlers.
-
- Two functions in x.h provide standard error messages. x_msg_memory() returns
- a string with the message "Not enough memory". x_msg_internal() is passed a
- string and returns it converted into the form "Internal error (...)".
-
- Lastly, if you create an error block without using new, and the block's scope
- is only in the function that created it, use x_buffer_error to copy it into
- an internal block and use the block returned.
-
-
- Creating gadgets
- ----------------
- If you create a gadget by using Window's get_gadget method, you must be
- careful that a gadget of the type you want is created, and not an object of
- the base Gadget type. For example, you might use the following in a
- constructor to make a reference to an action button gadget:
-
- button(*(ActionButton *) window->get_gadget(0))
-
- Then you might use the following to assign a handler that is executed when
- the button is clicked:
-
- button->click_handler = &my_command;
-
- If the action button code does not get linked with your program, an object
- the type ActionButton will not be created, but the program will quite happily
- cast the object to that type, and then assign the handler to somewhere
- outside the object, possibly corrupting something important.
-
- You've just got to make sure that the action button code *does* get linked.
- If you call an action button method that isn't inlined, you'll be okay.
- Otherwise, you need to add "Dreamscape:gadgets.o.actionbutton" into the list
- of files to link.
-
- The same also goes for Toolbox objects, although you will get an error if you
- try to create an object from a Toolbox class that is not recognised.
-
-
- Using SaveAs windows
- --------------------
- The SaveAs code in Dreamscape will happily support RAM transfers, so you can
- enable "Supports RAM transfers" in the objects in the Resource file. You
- should always select "Client participates".
-
- However, if the handler you attach to the SaveAs object is a FileSaver not
- just a Saver, "Supports RAM transfers" should not be selected. FileSavers are
- there so you can save directories (as MakeApp does) or, for example, so you
- can call an external program to do the saving. Most of the time you should
- use a Saver object to do the saving.
-
- Dreamscape also has a small patch that allows you to type spaces in the
- filename field of SaveAs windows. These spaces will be converted to hard
- spaces when you save the file - the patch is completely transparent.
-
-
- Returning menus from pop up gadgets
- -----------------------------------
- The get_menu() method in the PopUp class doesn't work - I think this might be
- a flaw in OSLib or the Window module, although I haven't had a chance to
- investigate this. A workaround is to create the menu manually and use
- set_menu() to assign it to the PopUp object.
-
-
- ColourDBox problems
- -------------------
- get_colour() doesn't appear to work (Toolbox bug I think). I doubt
- get_colour_model() works either. From what others have said on
- comp.sys.acorn.programmer, the ColourDBox module seems to be extremely buggy.
-
-
- Showing and hidden handlers
- ---------------------------
- The showing and hidden handlers are only called if the object is not already
- showing or hidden respectively. Unlike some handlers, you can only register
- one of each - this is for simplicity. If you want to register more, you can
- attach a MultiCommand object and add handlers to that.
-
-
- Multi-clicking/dragging
- -----------------------
- Dreamscape will handle triple-clicks and other numbers of clicks for you. It
- will also handle 'double-drag's, where the user clicks once and then drags on
- the second click (Zap and Edit use this to drag a selection of whole words).
-
- You will have to set the click type of the button gadget or window work area
- appropriately for this to work. Some times you will not want triple clicks to
- be detected. Also, for double-dragging to work, the button type used must not
- have its own double-click handling, and so the double-pointer will not
- appear.
-
- This list shows how some button types are handled:
-
- 6 Click/drag Multi-click and multi-drag handling
- 10 Double/click/drag Multi-click handling
-
-
- Graphics renderers
- ------------------
- These will auto-load the relevant modules in the graphic class's constructor,
- so you don't need to bother loading them in the app's !Run file.
-
- You can change the quality for graphic objects. This is how different
- graphics respond to quality settings:
-
- DrawFile This ignores the quality setting, as the DrawFile module only
- displays draw files one way.
-
- JPEGImage Below 0x700000 (normal), no dithering is used. From 0x7000000
- and below 0x9000000 (anti-aliased), fast inaccurate dithering
- is used. From 0x9000000 upwards, slow accurate dithering is
- used.
-
- Graphics object files must be explicitly linked into programs before they
- will automatically recognise graphics files for you.
-
-
- Errors during redrawing
- -----------------------
- If an error occurs while a window is being redrawn, the redraw will stop and
- the error will be reported. If the error box disappearing causes another
- redraw request, the library will not attempt to redraw the window the second
- time.
-
-
- Pane handling
- -------------
- For Dreamscape-based pane handling to work (as opposed to Toolbox-based pane
- handling), the auto-open and auto-close options of the window must not be
- selected.
-
- Dreamscape will open and close windows for you anyway if these are not set,
- but it would probably be slightly more efficient to leave them selected if
- you are not using panes, as the library's handler code would not have to be
- called.
-
- Dreamscape also provides a transparent fix for the problem that multi-tasking
- stops when dragging windows with panes with Select. However, it will not fix
- this for panes that are handled by the Toolbox.
-
-
- Document and view classes
- -------------------------
- Note that these classes (in the document.h header) aren't tested at all - I
- haven't actually used them yet. They also aren't intended to be used for
- absolutely all cases of documents with multiple views, just for documents
- with multiple scalable views. You wouldn't use them for a plain text editor
- like Edit, for example.
-
- Don't use the Document and Views classes yet, because they are going to have
- a complete redesign in a future version of Dreamscape.
-
-
- Accessing low-level features
- ----------------------------
- Dreamscape provides various hooks to allow the programmer to access things at
- a lower level. For example, you can find out the underlying Toolbox object of
- a window with get_toolbox_object(). This returns a ToolboxObject object which
- converts to OSLib's toolbox_o type.
-
- You can also intercept Wimp messages and Wimp events that are already claimed
- by other classes. By registering a handler after the other class does so, you
- are guaranteed to receive the message first. You can use Dreamscape's
- low-level implementation of the data transfer protocol within other
- protocols.
-
- Intercepting Toolbox events is harder as Dreamscape's handling system for
- these events is simplified to make it more efficient. If you need to patch
- something it is best to do it by modifying Dreamscape itself.
-
- The Wimp event, Wimp message and Toolbox event handlers can now be used from
- C as well as C++. The Wimp event handler has been re-written to be more
- efficient, so it might be worthwhile using that in your programs even if you
- don't use any other features of Dreamscape! All the handlers have been
- written to be safe - the dispatchers can be called while they are threaded
- and handlers can be deregistered while the dispatcher is threaded.
-
-
- Graphics and font handling
- --------------------------
- Dreamscape does not yet provide any handling for graphics primitives such as
- line drawing with the Draw module or plot commands, nor does it provide any
- font plotting facilities. For now you will have to write code for this
- yourself by calling SWIs using OSLib.
-
- Another thing about font rendering is that when I implement it I am
- definitely going to add support for other alphabets. If that means rewriting
- FontMenu and FontDBox to do it, then so be it!
-
-
- The iconise() method
- --------------------
- BaseWindow's iconise() method only half works at the moment. When it iconises
- a window, it doesn't give the icon the correct name. In the future, this
- will be fixed, and I will add methods that allow you to set a window's
- iconised title and icon.
-
-
- Using Dreamscape from C
- -----------------------
- Dreamscape's event handling routines and other routines can be used from C.
- However, some C 'features' complicate things. Unlike with C++, structures in
- C occupy their own namespace and types can't be re-typedef'd. This makes
- using OSLib structures without first #including the appropriate header a real
- pain - the OSLib headers are too large to #include them from Dreamscape
- unnecessarily.
-
- If you want to access the contents of OSLib structures you must #include the
- relevant OSLib header yourself (in both C and C++). However, in C you must
- #include the OSLib headers *before* you #include the Dreamscape headers, or C
- will start giving nonsensical errors and will start getting confused about
- whether structure types match.
-
-
- Deferred delete templates
- -------------------------
- Sometimes you have to delete an object from within one of that object's
- member functions (usually a handler function). This can be done with "delete
- this", which is perfectly legal, although it can be dangerous - the object
- might be accessed after it has been deleted.
-
- A safer way of doing this is to mark the object as deleted and delete it
- later. This is what the defdelete.h header does - it will delete objects on
- the next null Wimp event.
-
- This header provides two template functions:
-
- template<class Type> void deferred_delete(Type *object);
- template<class Type> void deferred_delete_a(Type *objects);
-
- The first function will delete a single object (equivalent to "delete
- object"), whereas the second will delete an array of objects (equivalent to
- "delete [] objects"), although in practise the two do the same thing (the
- second type of delete is specified by C++).
-