Precognition: A step beyond Intuition Release 1.06, December 1993 Precognition is an interface builder program for Intuition that allows you to create attractive, 3D-style interfaces like Workbench 2.0, but under AmigaDos 1.3! You use Precognition as if it were a structured drawing or paint program, i.e. simply drag the desired gadgets on to the window, size and move them using the mouse. When you're done, Precognition writes the C code to generate that window. Unlike other Amiga interface-building programs, Precognition not only writes the declarations for the gadgets, but also writes the code for opening and closing the window, and the event loop itself. (For any non-trivial interface, the event loop is usually the hardest part to write.) Precognition is also a set of programming utilities for use with Intuition that make manipulating gadgets easier. The code generated by the Precognition Interface builder relies heavily on the Precognition utilities. NITTY GRITTY DETAILS: Unlike Intuition, Precognition is not a separate process on the Amiga. It is merely a collection of functions which manipulate gadgets and windows. i.e. it's designed to extend Intuition, not replace it. Starting the Program from Workbench Simply double-click the "Builder" icon. Starting the Program from the CLI Type "Builder". Interlace vs. Non-Interlace Precognition normally opens a screen with the same resolution as the Workbench screen. You can force the screen to be (or not to be) interlaced via the tooltype "INTERLACE=". Use "INTERLACE=YES" for interlace, "INTERLACE=NO" for non-interlace. The Application Window Occupying most of the screen is a window titled "Application". This is the window which you are designing. You will add gadgets and graphics to this window by dragging them over from the "Gadgets" and "Graphics" windows. To change the properties of the application window, select "Window Properties" from the "Edit" menu. This will bring up the Window Properties requestor. Using this requester, you can change the window title, the variable name, and the window gadgets (close, drag, front/back, resize). The Gadget Window At the lower right side of the screen, there will be the "Gadgets" window which contains a set of buttons labelled with the different gadget types. To add one of these gadgets to the application window, simply move the mouse over the name of the gadget you wish, press and hold the left mousebutton. A gadget icon will be attached to your mouse pointer. Drag the gadget icon into the application window, and release the left mousebutton. The Graphics Window To the left of the "Gadgets" window is the "Graphics" window which contains a set of buttons labelled with the different window graphics which can be added to the window. Currently, there aren't very many graphics. You add these to the window the same way you add a gadget, i.e. drag them. Selecting Objects To move, resize, or edit an object in the application window, you must first select it. To select an object, move the mouse pointer over that object, and press and release the left mousebutton. The object should now be displayed in inverse video. Multiple objects can be selected at the same time by holding down either shift key while pressing the left mousebutton. Objects can be selected by lasso-ing them. Hold the left mousebutton down on an area of the window where there are no objects. Now move the mouse. A selection box will follow your mouse. When you release the mouse, any and all objects completely within the selection box will be selected. Changing the Size of an Object To change the size of an object, move the mouse pointer to the edge or corner of the object, press and hold the left mousebutton. The pointer image should change to a triangular arrow. Now drag the corner or edge of the object to its new size and release the left mousebutton. You can cancel a size-change by pressing the right mousebutton before releasing the left mousebutton. NOTE: The size of some objects cannot be changed, e.g. a CheckBox is a fixed size. The size of some objects can only be changed along one axis. e.g. a StringGadget can get wider, but not taller. If the pointer image becomes a hand you're not close enough to the edge of the object, or else this object does not size. NOTE: You can only change the size of one object at a time. If multiple objects are selected, dragging the mouse will always move rather than resize. Moving Objects You move objects on the application window the same way you move icons on the workbench screen. To move one or more objects, first select the objects, and then move the mouse pointer to the center of one of the objects, press and hold the left mousebutton. The pointer image will become a hand. Now drag the objects to their new location, and release the left mousebutton. You can cancel a size-change by pressing by pressing the right mousebutton before releasing the left mousebutton. If the pointer image becomes a triangular arrow instead of a hand you're too close to the edge of the object. Editing an Object To edit the properties of an object, select the object, and then select "Object Properties" from the Edit menu. This will bring up the object's property requestor. This requestor will allow you to change the variable name for this object, its displayable title (if any), its size and location, and any other property which is applicable. Aligning Objects You can align a set of objects by selecting those objects, and then selecting the appropriate option from the Align submenu of the Edit menu. Grid Snap You can also force alignment by turning on the Grid Snap. Selecting "Grid Snap » Grid Controls" from the Edit menu will display the Grid Snap requestor, which allows you to set the grid snap parameters. There are actually two separate grid snaps: "Location Snap" will force the upper-left corner of an object to be on a grid when you drag it. "Size Snap" will force the corner or edge of an object to be on a grid when you size it. Deleting Objects To delete one or more objects, select those objects, and then select Delete from the Edit menu. WARNING: Once you delete an object, its gone for good. Sooner or later I'll get around to adding Cut/Copy/Paste instead of Delete. (Sigh. So many improvements, so little time...) Generating Code To generate code for the application window, select "Write Code" from the "Project" menu. This will bring up a file requester for the C source code. Type or select a filename, and press the "OK" gadget. Precognition will then write the C source code declarations for your window. Precognition generates a 'struct' which defines your window, and 6 functions. (Where "" is the name you chose for the window.) _Init -- initializes all the objects in the window you designed. _CleanUp -- releases all the memory allocated to the objects in the window. _Respond -- Code which responds to a single -- IntuiMessage 'event' from Intuition. _EventLoop -- initializes and opens the window, gets events from Intuition, calls _Respond() until global variable 'Done' is set to TRUE. calls _CleanUp(). main -- main program. Opens libraries, calls _EventLoop, GracefulExit. GracefulExit -- closes libraries. The generated code should be compileable and linkable (with Precognition.lib) as generated. About the Generated Code... Precognition does not generate standard Intuition variables and function calls. (This is because 1.3 Intuition does not have built-in 3-D buttons and scrolling lists and such) Instead Precognition generates code which use special Precognition data types and functions. In order for your program to use these functions, you must link your code with the file "Precognition.lib", which contains all the special Precognition calls. Throughout the code you will say lines which say "/* YOUR CODE HERE */". These are the areas which you the programmer must fill in. Precognition inserts these statements to indicate that a User-interface event has occurred, and you should take the appropriate action. EXAMPLE: If you create a window with an "OK" button, Precognition will generate the following statements: if (Respond( (Interactor*) &OK_button, &event) & CHANGED_STATE) { /* OK_button was hit. */ ; /* YOUR CODE HERE */ } You, the programmer, need to supply the code to take the appropriate action when the OK button is pressed. (Precognition doesn't know what you want to happen when "OK" is hit.) The code as written should be compilable and linkable, although it won't do anything except have pretty buttons until you fill in the /* YOUR CODE HERE */ areas. Terminating the Event Loop The generated event loop runs until global variable 'Done' is set to TRUE. As generated, the only event in the code which does this is hitting the window's closebox. If you want to have other actions exit the window (e.g. an "OK" button), you need to add a line to set 'Done' to TRUE in the event code for the OK button. e.g. if (Respond( (Interactor*) &OK_button, &event) & CHANGED_STATE) { /* OK_button was hit. */ Done = TRUE; /* <-- YOUR CODE HERE */ } NOTE: If you do not include a closebox on your window, then the event loop is infinite until you modify the code. Precognition uses an OO paradigm via pointers-to-functions, which allows the same function to do different things to different objects ("polymorphism"). e.g. SetLocation(&BoolGadget, 10, 10 ); sets the location of a boolean gadget to be 10,10 in its window, while SetLocation( &pcgWindow, 10, 10 ); sets the location of the window to be 10, 10 on its screen. All header files have an 'object genealogy' at the top of the file which describes the parents of the object. e.g. PObject