home *** CD-ROM | disk | FTP | other *** search
- ** Professional GEM **
- by Tim Oren
-
- Topic: WINDOWS, part I
- 10/7/85
-
- ANTIC is proud to present the first of Tim Oren's bi-monthly columns
- exploring the GEM programming environment. These columns are aimed
- at professional ST developers, but we encourage everyone to join in
- and collect the columns for future reference.
-
- HELLO, WORLD!
-
- For those whom I have not met in person or electronically, an
- introduction is in order.
-
- I am a former member of the GEM programming team at Digital Research,
- Inc., where I designed and implemented the GEM Resource Construction
- Set and other parts of the GEM Programmer's Toolkit. I have since
- left DRI to become the user interface designer for Activenture, a
- startup company which is developing CD-ROM technology for use with
- the Atari ST and other systems.
-
- The purpose of Professional GEM is to pass along some of the
- information and tricks I have accumulated about GEM, and explore some
- of the user interface techniques which a powerful graphics processor
- such as the ST makes possible.
-
- GROUND RULES
-
- I am going to assume that you have both a working knowledge of the C
- programming language and a copy of the ST Programmer's Toolkit with
- documentation (available from Atari). If you lack either, don't
- panic. You can read the columns to get the flavor of programming the
- ST, and come back for a more serious visit later on.
-
- For now, I will be using code samples that will run with the
- Atari-supplied C compiler, also known as DR C-68K, or Alcyon C. I
- will be using the portability macros supplied with the Toolkit, so
- that the code will also be transferable to other GEM systems.
-
- Both of these items are subject to change, depending on reader
- feedback and the availability of better products.
-
- If you do not have a copy of the source to the DOODLE.C GEM example
- program, you should consider downloading a copy from SIG*ATARI.
- Although it is poorly documented, it shows real-life examples of many
- of the techniques I will discuss.
-
- Getting started with a windowed graphics system seems to be like
- getting into an ice-cold swimming pool: it's best done all at once.
-
- Anyone who has looked at "Inside Macintosh" has probably noticed that
- you have to have read most of it to understand any of it. GEM isn't
- really much different. You have all the reference guides in your
- hand, but nothing to show how it all works together.
-
- I am hoping to help this situation by leading a series of short tours
- through the GEM jungle. Each time we'll go out with a particular
- goal in mind and follow the path that leads there. We'll look at the
- pitfalls and strange bugs that lurk for the unwary, and show off a
- few tricks to amaze the natives. The first trip leaves immediately;
- our mission is to get a window onto the ST screen, with all of its
- parts properly initialized.
-
- WE DO WINDOWS
-
- One of the most important services which a graphics interface system
- provides for the user and programmer is window management.
-
- Windows allow the user to perform more than one activity on the same
- screen, to freely reallocate areas of the screen for each task, and
- even to pile the information up like pages of paper to make more
- room. The price for this increased freedom is (as usual) paid by
- you, the programmer, who must master a more complex method of
- interacting with the "outside world".
-
- The windowing routines provided by ST GEM are the most comprehensive
- yet available in a low-cost microcomputer. This article is a guide
- to using these services in an effective manner.
-
- IN THE BEGINNING
-
- In GEM, creating a window and displaying it are two different
- functions. The creation function is called wind_create, and its
- calling sequence is:
-
- handle = wind_create(parts, xfull, yfull, wfull, hfull);
-
- This function asks GEM to reserve space in its memory for a new
- window description, and to return a code or "handle" which you can
- use to refer to the window in the future. Valid window handles are
- positive integers; they are not memory pointers.
-
- GEM can run out of window handles. If it does so, the value returned
- is negative. Your code should always check for this situation and
- ask the program's user to close some windows and retry if possible.
- Handle zero is special. It refers to the "desktop", which is
- predefined as light green (or gray) on the ST. Window zero is always
- present and may be used, but never deleted, by the programmer.
-
- The xfull, yfull, wfull, and hfull parameters are integers which
- determine the maximum size of the window. Xfull and yfull define the
- upper left corner of the window, and wfull and hfull specify its
- width and height. (Note that all of the window coordinates which we
- use are in pixel units.)
-
- GEM saves these values so that the program can get them later when
- processing FULL requests. Usually the best maximum size for a
- window is the entire desktop area, excepting the menu bar. You can
- find this by asking wind_get for the working area of the desktop
- (handle zero, remember):
-
- wind_get(0, WF_WXYWH, &xfull, &yfull, &wfull, &hfull);
-
- Note that WF_WXYWH, and all of the other mnemonics used in this
- article, are defined in the GEMDEFS.H file in the ST Toolkit.
-
- The parts parameter of wind_create defines what features will be
- included in the window when it is drawn. It is a word of single bit
- flags which indicate the presence/absence of each feature. To
- request multiple features, the flags are "or-ed" together. The flags'
- mnemonics and meanings are:
-
- NAME- A one character high title bar at the top of the window.
-
- INFO- A second character line below the NAME.
-
- MOVER- This lets the user move the window around by "dragging" in
- the NAME area. NAME also needs to be defined.
-
- CLOSER - A square box at the upper left. Clicking this control
- point asks that the window be removed from the screen.
-
- FULLER - A diamond at upper right. Clicking this control point
- requests that the window grow to its maximum size, or shrink back
- down if it is already big.
-
- SIZER - An arrow at bottom right. Dragging the SIZER lets the
- user choose a new size for the window.
-
- VSLIDE - defines a right-hand scroll box and bar for the window.
- By dragging the scroll bar, the user requests that the window's
- "viewport" into the information be moved. Clicking on the gray box
- above the bar requests that the window be moved up one "page".
- Clicking below the bar requests a down page movement. You have to
- define what constitutes a page or line in the context of your
- application.
-
- UPARROW - An arrow above the right scroll bar. Clicking here
- requests that the window be moved up one "line". Sliders and arrows
- almost always appear together.
-
- DNARROW - An arrow below the right scroll bar. Requests that window
- be moved down a line.
-
- HSLIDE - These features are the horizontal equivalent of the
- RTARROW above. They appear at the bottom of the window. Arrows
- LFARROW usually indicate "character" sized movement left and right.
- "Page" sized movement has to be defined by each application.
-
- It is important to understand the correspondence between window
- features and event messages which are sent to the application by the
- GEM window manager. If a feature is not included in a window's
- creation, the user cannot perform the corresponding action, and your
- application will never receive the matching message type. For
- example, a window without a MOVER may not be dragged by the user,
- and your app will never get a WM_MOVED message for that window.
-
- Another important principle is that the application itself is
- responsible for implementing the user's window action request when a
- message is received. This gives the application a chance to accept,
- modify, or reject the user's request.
-
- As an example, if a WM_MOVED message is received, it indicates that
- the user has dragged the window. You might want to byte or word
- align the requested position before proceeding to move the window.
- The wind_set calls used to perform the actual movements will be
- described in the next article.
-
- OPEN, SESAME! The wind_open call is used to actually make the window
- appear on the screen. It animates a "zoom box" on the screen and
- then draws in the window's frame. The calling sequence is:
-
- wind_open(handle, x, y, w, h);
-
- The handle is the one returned by wind_create. Parameters x, y, w,
- and h define the initial location and size of the window. Note that
- these measurements INCLUDE all of the window frame parts which you
- have requested. To find out the size of the area inside the frame,
- you can use
-
- wind_get(handle, WF_WXYWH, &inner_x, &inner_y, &inner_w, &inner_h);
-
- Whatever size you choose for the window display, it cannot be any
- larger than the full size declared in wind_create.
-
- Here is a good place to take note of a useful utility for calculating
- window sizes. If you know the "parts list" for a window, and its
- inner or outer size, you can find the other size with the wind_calc
- call:
-
- wind_calc(parts, kind, input_x, input_y, input_w, input_h, &output_x,
- &output_y, &output_w, &output_h);
-
- Kind is set to zero if the input coordinates are the inner area, and
- you are calculating the outer size. Kind is one if the inputs are
- the outer size and you want the equivalent inner size. Parts are
- just the same as in wind_create.
-
- There is one common bug in using wind_open. If the NAME feature is
- specified, then the window title must be initialized BEFORE opening
- the window:
-
- wind_set(handle, WF_NAME, ADDR(title), 0, 0);
- If you don't do this, you may get gibberish in the NAME area or the
- system may crash. Likewise, if you have specified the INFO feature,
- you must make a wind_set call for WF_INFO before opening the window.
-
- Note that ADDR() specifies the 32-bit address of title. This
- expression is portable to other (Intel-based) GEM systems. If you
- don't care about portability, then &title[0], or just title alone
- will work fine on the ST.
-
- CLEANING UP. When you are done with a window, it should be closed
- and deleted. The call
-
- wind_close(handle);
-
- takes the window off the screen, redraws the desktop underneath it,
- and animates a "zoom down" box. It doesn't delete the window's
- definition, so you can reopen it later.
-
- Deleting the window removes its definition from the system, and makes
- that handle available for reuse. Always close windows before
- deleting, or you may leave a "dead" picture on the screen. Also be
- sure to delete all of your windows before ending the program, or
- your app may "eat" window handles. The syntax for deleting a window
- is:
-
- wind_delete(handle);
-
- THOSE FAT SLIDERS. One of ST GEM's unique features is the
- proportional slider bar. Unlike other windowing systems, this type
- of bar gives visual feedback on the fraction of a document which is
- being viewed, as well as the position within the document. The
- catch, of course, is that you have two variables to maintain for each
- scroll bar: size and position.
-
- Both bar size and position range from 1 to 1000. A bar size of 1000
- fills the slide box, and a value of one gets the minimum bar size.
- To compute the proper size, you can use the formula:
-
- size = min(1000, 1000 * seen_doc / total_doc)
-
- Seen_doc and total_doc are the visible and total size of the document
- respectively, in whatever units are appropriate. As an example, if
- your window could show 20 lines of a 100 line text file, you should
- set a slider size of 200. Since the window might be bigger than the
- total document at some points, you need the maximum function. If
- the document size is zero, force the slider size to 1000. (Note: You
- will probably need to do the computation above with 32-bit
- arithmetic to avoid overflow problems.)
-
- Once you have computed the size, use the wind_set function to
- configure the scroll bar:
-
- wind_set(handle, WF_VSLSIZE, size, 0, 0, 0);
-
- This call sets the vertical (right hand) scroll bar. Use WF_HSLSIZE
- for the horizontal scroller. All of these examples are done for the
- vertical dimension, but the principles are identical in the other
- direction.
-
- Bar positioning is a little tougher. The most confusing aspect is
- that the 1-1000 range does not set an absolute position of the bar
- within the scroll box. Instead, it positions the TOP of the bar
- within its possible range of variation.
-
- Let's look at our text file example again to make this clearer. If
- there are always 20 lines of a 100 line file visible, then the top of
- the window must be always be somewhere between line 1 and line 81.
- This 80 line range is the actual freedom of movement of the window.
- So, if the window were actually positioned with its top at line 61,
- it would be at the three-quarter position within the range, and we
- should set a scroll bar position of 750. The actual formula for
- computing the position is:
-
- pos = 1000 * (top_wind - top_doc) / (total_doc - seen_doc)
-
- Top_wind and top_doc are the top line in the current window and the
- whole document, respectively. Obviously, if seen_doc is greater or
- equal to total_doc, you need to force a zero value for pos. This
- calculation may seem rather convoluted the first time through, but is
- easy once you have done it. When you have computed the position,
- wind_set configures the scroll bar:
-
- wind_set(handle, WF_VSLIDE, pos, 0, 0, 0);
-
- WF_HSLIDE is the equivalent for horizontal scrolling.
-
- It is a good practice to avoid setting the slider size or position if
- they are already at the value which you need. This avoids an
- annoying redraw flash on the screen when it is not necessary. You
- can check on the current value of a slider parameter with wind_get:
-
- wind_get(handle, WF_VSLIDE, &curr_value, &foo, &foo, &foo);
-
- Foo is a dummy variable which needs to be there, but is not used.
- Substitute WF_VSLIDE with whatever parameter you are checking.
-
- One philosophical note on the use of sliders: It is probably best to
- avoid the use of both sliders at once unless it is clearly
- appropriate to the type of data which is being viewed.
-
- Since Write and Paint programs make use of the sheet-of-paper
- metaphor, moving the window around in both dimensions is reasonable.
- However, if the data is more randomly organized, such as a tableau of
- icons, then it is probably better to only scroll in the vertical
- dimension and "reshuffle" if the window's width is changed. Then the
- user only needs to manipulate one control to find information which
- is off-screen. Anyone who has had trouble finding a file or folder
- within a Desktop window will recognize this problem.
- COMING UP NEXT
-
- In my next column in Antic Online, we'll conclude the tour of the
- ST's windowing system. I'll discuss the correct way to redraw a
- window's contents, and how to handle the various messages which an
- application receives from the window manager. Finally, we'll look at
- a way to redesign the desktop background to your own specifications.
-
- FEEDBACK
-
- One of the beauties of an on-line column is that you can make your
- comments known immediately. To register your opinions, select ST
- FEEDBACK, enter your message, leave your name, and enter a blank line
- to exit.
-
- I am interested in hearing proposals for topics, feedback on the
- technical level of the column, and reports on bugs and other
- "features" in both the column and the ST itself. Your comments will
- be read by the ANTIC staff and myself and, though we might not answer
- individual questions, they will be used to steer the course of future
- columns.
-
-
-