Professional GEM - Part I - Windows

From Atari Wiki
Revision as of 13:02, 13 September 2006 by Zorro 2 (talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search
        Professional GEM                                                1


                                    P�PA�AR�RT�T -�- I�I

                                 W�Wi�in�nd�do�ow�ws�s       



        I�IN�N T�TH�HE�E B�BE�EG�GI�IN�NN�NI�IN�NG�G       

             In GEM,   creating  a  window  and  displaying  it  are  two
        different   functions.    The   creation   function   is   called
        windcreate, and its calling sequence is: 

             handle = windcreate(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 windget  for the working area
        of the desktop (handle zero, remember): 

              windget(0, WFWXYWH, &xfull, &yfull, &wfull, &hfull);

        Note  that  WFWXYWH,  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  windcreate  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.  


        
�

        Professional GEM             Part I                             2


            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 WMMOVED  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.  


        
�

        Professional GEM             Part I                             3



             As an   example,  if  a  WMMOVED  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 windset calls used to perform the actual
        movements will be described in the next article.  


        O�OP�PE�EN�N S�SE�ES�SA�AM�ME�E!�!        

             The windopen  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: 

                          windopen(handle, x, y, w, h);

        The  handle  is the one returned by windcreate.  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 

          windget(handle, WFWXYWH, &innerx, &innery, &innerw, &innerh);

        Whatever  size  you  choose  for the window display, it cannot be
        any larger than the full size declared in windcreate.  

             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 windcalc call: 

         windcalc(parts, kind, inputx, inputy, inputw, inputh, &outputx,
                         &outputy, &outputw, &outputh);

        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 windcreate.  

             There is  one  common  bug  in  using windopen.  If the NAME
        feature   is specified, then the window title must be initialized
        BEFORE opening the window: 

                   windset(handle, WFNAME, 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 windset call for WFINFO before opening
        the window.  




        
�

        Professional GEM             Part I                             4



             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.  


        C�CL�LE�EA�AN�NI�IN�NG�G U�UP�P        

             When you  are  done  with  a window, it should be closed and
        deleted.  The call 

                               windclose(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: 

                               winddelete(handle);



        T�TH�HO�OS�SE�E F�FA�AT�T S�SL�LI�ID�DE�ER�RS�S       

             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 * seendoc / totaldoc)

        Seendoc  and  totaldoc  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


        
�

        Professional GEM             Part I                             5


        the  computation  above  with 32-bit arithmetic to avoid overflow
        problems).  

             Once you  have  computed  the size, use the windset function
        to configure the scroll bar: 

                   windset(handle, WFVSLSIZE, size, 0, 0, 0);

        This  call  sets  the  vertical  (right  hand)  scroll  bar.  Use
        WFHSLSIZE  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 * (topwind - topdoc) / (totaldoc - seendoc)

        Topwind  and  topdoc  are  the top line in the current window and
        the  whole  document,  respectively.   Obviously,  if  seendoc is
        greater  or equal to totaldoc, 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, windset configures the scroll bar: 

                    windset(handle, WFVSLIDE, pos, 0, 0, 0);


              WFHSLIDE 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 windget: 

            windget(handle, WFVSLIDE, &currvalue, &foo, &foo, &foo);

        Foo  is  a  dummy  variable  which  needs to be there, but is not


        
�

        Professional GEM             Part I                             6


        used.   Substitute  WFVSLIDE  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.  


        C�CO�OM�MI�IN�NG�G U�UP�P N�NE�EX�XT�T       

             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.  


        F�FE�EE�ED�DB�BA�AC�CK�K         

             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.