home *** CD-ROM | disk | FTP | other *** search
/ Crawly Crypt Collection 1 / crawlyvol1.bin / program / books / progem / windows.1 < prev    next >
Text File  |  1986-11-01  |  18KB  |  365 lines

  1.      Permission  to  reprint  or  excerpt is granted only if the following
  2.      line appears at the top of the article:
  3.  
  4.        ANTIC PUBLISHING INC., COPYRIGHT 1985. REPRINTED BY PERMISSION.
  5.  
  6.  
  7.      ANTIC  is proud to present the first of Tim Oren's bi-monthly columns
  8.      exploring  the  GEM programming environment.  These columns are aimed
  9.      at  professional  ST developers, but we encourage everyone to join in
  10.      and collect the columns for future reference.
  11.  
  12.  
  13.  
  14.      Professional GEM  by Tim Oren
  15.      Column #1 - Windows, part 1
  16.  
  17.  
  18.      HELLO, WORLD!
  19.  
  20.         For  those  whom  I  have  not met in person or electronically, an
  21.      introduction  is  in  order.   I  am  a  former  member  of  the  GEM
  22.      programming  team  at  Digital  Research,  Inc., where I designed and
  23.      implemented  the GEM Resource Construction Set and other parts of the
  24.      GEM  Programmer's  Toolkit.  I have since left DRI to become the user
  25.      interface  designer  for  Activenture,  a  startup  company  which is
  26.      developing  CD-ROM  technology  for  use  with the Atari ST and other
  27.      systems.
  28.  
  29.         The  purpose  of  Professional  GEM  is  to pass along some of the
  30.      information and tricks I have accumulated about GEM, and explore some
  31.      of  the user interface techniques which a powerful graphics processor
  32.      such as the ST makes possible.
  33.  
  34.  
  35.      GROUND RULES
  36.  
  37.         I am going to assume that you have both a working knowledge of the
  38.      C programming language and a copy of the ST Programmer's Toolkit with
  39.      documentation  (available  from  Atari).   If  you lack either, don't
  40.      panic.  You can read the columns to get the flavor of programming the
  41.      ST, and come back for a more serious visit later on.
  42.  
  43.         For  now,  I  will  be  using  code samples that will run with the
  44.      Atari-supplied  C  compiler,  also known as DR C-68K, or Alcyon C.  I
  45.      will  be  using  the portability macros supplied with the Toolkit, so
  46.      that the code will also be transferable to other GEM systems.
  47.  
  48.         Both  of  these  items  are subject to change, depending on reader
  49.      feedback and the availability of better products.
  50.  
  51.         If  you  do  not  have  a  copy  of the source to the DOODLE.C GEM
  52.      example   program,  you  should  consider  downloading  a  copy  from
  53.      SIG*ATARI.  Although  it  is  poorly  documented,  it shows real-life
  54.      examples of many of the techniques I will discuss.
  55.  
  56.         Getting  started  with a windowed graphics system seems to be like
  57.      getting into an ice-cold swimming pool: it's best done all at once.
  58.  
  59.         Anyone  who  has looked at "Inside Macintosh" has probably noticed
  60.      that  you  have to have read most of it to understand any of it.  GEM
  61.      isn't  really  much  different.  You have all the reference guides in
  62.      your hand, but nothing to show how it all works together.
  63.  
  64.         I  am  hoping  to help this situation by leading a series of short
  65.      tours  through  the  GEM  jungle.   Each  time  we'll  go  out with a
  66.      particular  goal in mind and follow the path that leads there.  We'll
  67.      look  at  the pitfalls and strange bugs that lurk for the unwary, and
  68.      show off a few tricks to amaze the natives.
  69.  
  70.         The  first trip leaves immediately; our mission is to get a window
  71.      onto the ST screen, with all of its parts properly initialized.
  72.  
  73.  
  74.      WE DO WINDOWS
  75.  
  76.         One  of  the  most  important  services which a graphics interface
  77.      system provides for the user and programmer is window management.
  78.  
  79.         Windows  allow  the  user to perform more than one activity on the
  80.      same  screen, to freely reallocate areas of the screen for each task,
  81.      and  even to pile the information up like pages of paper to make more
  82.      room.   The  price  for  this increased freedom is (as usual) paid by
  83.      you,  the  programmer,  who  must  master  a  more  complex method of
  84.      interacting with the "outside world".
  85.  
  86.         The   windowing   routines   provided  by  ST  GEM  are  the  most
  87.      comprehensive  yet  available  in  a  low-cost  microcomputer.   This
  88.      article is a guide to using these services in an effective manner.
  89.  
  90.  
  91.      IN THE BEGINNING
  92.  
  93.         In  GEM,  creating  a  window  and displaying it are two different
  94.      functions.   The  creation  function  is  called wind_create, and its
  95.      calling sequence is:
  96.  
  97.          handle = wind_create(parts, xfull, yfull, wfull, hfull);
  98.  
  99.      This  function  asks  GEM  to  reserve  space in its memory for a new
  100.      window  description,  and  to return a code or "handle" which you can
  101.      use  to  refer to the window in the future.  Valid window handles are
  102.      positive integers; they are not memory pointers.
  103.  
  104.         GEM  can  run  out  of  window  handles.  If it does so, the value
  105.      returned  is  negative.   Your  code  should  always  check  for this
  106.      situation  and ask the program's user to close some windows and retry
  107.      if  possible.   Handle  zero is special.  It refers to the "desktop",
  108.      which  is predefined as light green (or gray) on the ST.  Window zero
  109.      is  always  present  and  may  be  used,  but  never  deleted, by the
  110.      programmer.
  111.  
  112.         The  xfull,  yfull, wfull, and hfull parameters are integers which
  113.      determine the maximum size of the window.  Xfull and yfull define the
  114.      upper  left  corner  of  the  window, and wfull and hfull specify its
  115.      width  and  height. (Note that all of the window coordinates which we
  116.      use are in pixel units.)   GEM saves these values so that the program
  117.      can  get  them later when processing FULL requests.  Usually the best
  118.      maximum  size  for a window is the entire desktop area, excepting the
  119.      menu  bar.  You can find this by asking wind_get for the working area
  120.      of the desktop (handle zero, remember):
  121.  
  122.          wind_get(0, WF_WXYWH, &xfull, &yfull, &wfull, &hfull);
  123.  
  124.      Note  that  WF_WXYWH,  and  all  of  the other mnemonics used in this
  125.      article, are defined in the GEMDEFS.H file in the ST Toolkit.
  126.  
  127.         The  parts  parameter of wind_create defines what features will be
  128.      included  in the window when it is drawn.  It is a word of single bit
  129.      flags  which  indicate  the  presence/absence  of  each  feature.  To
  130.      request multiple features, the flags are "or-ed" together. The flags'
  131.      mnemonics and meanings are:
  132.  
  133.      NAME- A one character high title bar at the top of the window.
  134.  
  135.      INFO- A second character line below the NAME.
  136.  
  137.      MOVER- This lets the user move the window around by "dragging" in the
  138.      NAME area.  NAME also needs to be defined.
  139.  
  140.      CLOSER-  A square box at the upper left.  Clicking this control point
  141.      asks that the window be removed from the screen.
  142.  
  143.      FULLER-  A  diamond  at  upper  right.   Clicking  this control point
  144.      requests  that  the  window  grow to its maximum size, or shrink back
  145.      down if it is already big.
  146.  
  147.      SIZER-  An  arrow  at bottom right.  Dragging the SIZER lets the user
  148.      choose a new size for the window.
  149.  
  150.      VSLIDE-  defines  a  right-hand scroll box and bar for the window. By
  151.      dragging  the  scroll  bar,  the  user  requests  that  the  window's
  152.      "viewport"  into  the information be moved.  Clicking on the gray box
  153.      above  the  bar  requests  that  the  window  be moved up one "page".
  154.      Clicking  below  the  bar requests a down page movement.  You have to
  155.      define  what  constitutes  a  page  or  line  in  the context of your
  156.      application.
  157.  
  158.      UPARROW- An arrow above the right scroll bar.  Clicking here requests
  159.      that  the  window  be moved up one "line".  Sliders and arrows almost
  160.      always appear together.
  161.  
  162.      DNARROW-  An  arrow below the right scroll bar.  Requests that window
  163.      be moved down a line.
  164.  
  165.      HSLIDE-  These  features are the horizontal equivalent of the RTARROW
  166.      above.   They  appear  at  the  bottom of the window.  Arrows LFARROW
  167.      usually  indicate  "character" sized movement left and right.  "Page"
  168.      sized movement has to be defined by each application.
  169.  
  170.         It  is  important  to understand the correspondence between window
  171.      features  and event messages which are sent to the application by the
  172.      GEM  window  manager.   If  a  feature  is not included in a window's
  173.      creation,  the user cannot perform the corresponding action, and your
  174.      application  will  never  receive  the  matching  message  type.  For
  175.      example, a window without a MOVER may not be dragged by the user, and
  176.      your app will never get a WM_MOVED message for that window.
  177.  
  178.         Another  important  principle  is  that  the application itself is
  179.      responsible  for implementing the user's window action request when a
  180.      message  is received.  This gives the application a chance to accept,
  181.      modify, or reject the user's request.
  182.  
  183.         As  an  example,  if  a WM_MOVED message is received, it indicates
  184.      that the user has dragged the window.  You might want to byte or word
  185.      align  the  requested  position before proceeding to move the window.
  186.      The  wind_set  calls  used  to  perform  the actual movements will be
  187.      described in the next article.
  188.  
  189.  
  190.      OPEN, SESAME!
  191.  
  192.         The  wind_open  call is used to actually make the window appear on
  193.      the screen.  It animates a "zoom box" on the screen and then draws in
  194.      the window's frame.  The calling sequence is:
  195.  
  196.          wind_open(handle, x, y, w, h);
  197.  
  198.      The  handle  is the one returned by wind_create.  Parameters x, y, w,
  199.      and  h define the initial location and size of the window.  Note that
  200.      these  measurements  INCLUDE  all of the window frame parts which you
  201.      have  requested.  To  find out the size of the area inside the frame,
  202.      you can use:
  203.  
  204.          wind_get(handle, WF_WXYWH, &inner_x, &inner_y, &inner_w, &inner_h);
  205.  
  206.      Whatever  size  you  choose  for the window display, it cannot be any
  207.      larger than the full size declared in wind_create.
  208.  
  209.         Here  is  a  good  place  to  take  note  of  a useful utility for
  210.      calculating window sizes.  If you know the "parts list" for a window,
  211.      and  its  inner  or  outer size, you can find the other size with the
  212.      wind_calc call:
  213.  
  214.          wind_calc(parts, kind, input_x, input_y, input_w, input_h,
  215.                               &output_x, &output_y, &output_w, &output_h);
  216.  
  217.      Kind  is set to zero if the input coordinates are the inner area, and
  218.      you  are  calculating  the outer size.  Kind is one if the inputs are
  219.      the  outer  size  and  you want the equivalent inner size.  Parts are
  220.      just the same as in wind_create.
  221.  
  222.         There  is  one common bug in using wind_open.  If the NAME feature
  223.      is  specified,  then  the  window  title  must  be initialized BEFORE
  224.      opening the window:
  225.  
  226.          wind_set(handle, WF_NAME, ADDR(title), 0, 0);
  227.  
  228.      If  you  don't do this, you may get gibberish in the NAME area or the
  229.      system  may crash.  Likewise, if you have specified the INFO feature,
  230.      you must make a wind_set call for WF_INFO before opening the window.
  231.  
  232.         Note  that  ADDR()  specifies  the  32-bit address of title.  This
  233.      expression  is  portable  to other (Intel-based) GEM systems.  If you
  234.      don't  care  about  portability,  then &title[0], or just title alone
  235.      will work fine on the ST.
  236.  
  237.  
  238.      CLEANING UP
  239.  
  240.         When  you are done with a window, it should be closed and deleted.
  241.      The call:
  242.  
  243.          wind_close(handle);
  244.  
  245.      takes  the  window off the screen, redraws the desktop underneath it,
  246.      and  animates  a  "zoom  down"  box.   It doesn't delete the window's
  247.      definition, so you can reopen it later.
  248.  
  249.         Deleting  the  window  removes its definition from the system, and
  250.      makes  that  handle available for reuse.  Always close windows before
  251.      deleting,  or  you may leave a "dead" picture on the screen.  Also be
  252.      sure to delete all of your windows before ending the program, or your
  253.      app may "eat" window handles.  The syntax for deleting a window is:
  254.  
  255.          wind_delete(handle);
  256.  
  257.  
  258.      THOSE FAT SLIDERS
  259.  
  260.         One  of  ST GEM's unique features is the proportional slider bar.
  261.      Unlike  other  windowing  systems,  this  type  of  bar  gives visual
  262.      feedback on the fraction of a document which is being viewed, as well
  263.      as  the  position within the document.  The catch, of course, is that
  264.      you  have  two  variables  to  maintain for each scroll bar: size and
  265.      position.
  266.  
  267.         Both  bar  size  and position range from 1 to 1000.  A bar size of
  268.      1000  fills  the  slide  box, and a value of one gets the minimum bar
  269.      size. To compute the proper size, you can use the formula:
  270.  
  271.          size = min(1000, 1000 * seen_doc / total_doc)
  272.  
  273.      Seen_doc and total_doc are the visible and total size of the document
  274.      respectively,  in  whatever units are appropriate.  As an example, if
  275.      your  window  could show 20 lines of a 100 line text file, you should
  276.      set  a slider size of 200.  Since the window might be bigger than the
  277.      total document at some points, you need the maximum function.  If the
  278.      document  size  is  zero,  force the slider size to 1000.  (Note: You
  279.      will probably need to do the computation above with 32-bit arithmetic
  280.      to avoid overflow problems.)
  281.  
  282.         Once  you  have  computed  the  size, use the wind_set function to
  283.      configure the scroll bar:
  284.  
  285.          wind_set(handle, WF_VSLSIZE, size, 0, 0, 0);
  286.  
  287.      This  call sets the vertical (right hand) scroll bar.  Use WF_HSLSIZE
  288.      for  the horizontal scroller.  All of these examples are done for the
  289.      vertical  dimension,  but  the  principles are identical in the other
  290.      direction.
  291.  
  292.         Bar positioning is a little tougher.  The most confusing aspect is
  293.      that  the  1-1000  range does not set an absolute position of the bar
  294.      within  the  scroll  box.   Instead,  it positions the TOP of the bar
  295.      within its possible range of variation.
  296.  
  297.         Let's  look  at our text file example again to make this clearer.
  298.      If there are always 20 lines of a 100 line file visible, then the top
  299.      of the window must be always be somewhere between line 1 and line 81.
  300.      This  80  line range is the actual freedom of movement of the window.
  301.      So,  if  the window were actually positioned with its top at line 61,
  302.      it  would  be  at the three-quarter position within the range, and we
  303.      should  set  a  scroll  bar  position of 750.  The actual formula for
  304.      computing the position is:
  305.  
  306.          pos = 1000 * (top_wind - top_doc) / (total_doc - seen_doc)
  307.  
  308.      Top_wind  and  top_doc are the top line in the current window and the
  309.      whole  document,  respectively.  Obviously, if seen_doc is greater or
  310.      equal  to  total_doc,  you  need to force a zero value for pos.  This
  311.      calculation may seem rather convoluted the first time through, but is
  312.      easy  once  you  have  done  it. When you have computed the position,
  313.      wind_set configures the scroll bar:
  314.  
  315.          wind_set(handle, WF_VSLIDE, pos, 0, 0, 0);
  316.  
  317.      WF_HSLIDE is the equivalent for horizontal scrolling.
  318.  
  319.         It is a good practice to avoid setting the slider size or position
  320.      if  they  are  already  at  the value which you need.  This avoids an
  321.      annoying  redraw  flash  on the screen when it is not necessary.  You
  322.      can check on the current value of a slider parameter with wind_get:
  323.  
  324.          wind_get(handle, WF_VSLIDE, &curr_value, &foo, &foo, &foo);
  325.  
  326.         Foo  is a dummy variable which needs to be there, but is not used.
  327.      Substitute WF_VSLIDE with whatever parameter you are checking.
  328.  
  329.         One  philosophical note on the use of sliders: it is probably best
  330.      to  avoid  the  use  of  both  sliders  at  once unless it is clearly
  331.      appropriate to the type of data which is being viewed.
  332.  
  333.         Since  Write  and  Paint  programs  make use of the sheet-of-paper
  334.      metaphor,  moving the window around in both dimensions is reasonable.
  335.      However, if the data is more randomly organized, such as a tableau of
  336.      icons,  then  it  is  probably  better to only scroll in the vertical
  337.      dimension  and "reshuffle" if the window's width is changed. Then the
  338.      user  only  needs to manipulate one control to find information which
  339.      is  off-screen.   Anyone who has had trouble finding a file or folder
  340.      within a Desktop window will recognize this problem.
  341.  
  342.  
  343.      COMING UP NEXT
  344.  
  345.         In  my next column in Antic Online, we'll conclude the tour of the
  346.      ST's  windowing  system.   I'll  discuss  the correct way to redraw a
  347.      window's  contents,  and  how to handle the various messages which an
  348.      application receives from the window manager.  Finally, we'll look at
  349.      a way to redesign the desktop background to your own specifications.
  350.  
  351.  
  352.      FEEDBACK
  353.  
  354.         One of the beauties of an on-line column is that you can make your
  355.      comments  known  immediately.   To  register your opinions, select ST
  356.      FEEDBACK, enter your message, leave your name, and enter a blank line
  357.      to exit.
  358.  
  359.         I  am  interested in hearing proposals for topics, feedback on the
  360.      technical  level  of  the  column,  and  reports  on  bugs  and other
  361.      "features"  in both the column and the ST itself.  Your comments will
  362.      be read by the ANTIC staff and myself and, though we might not answer
  363.      individual questions, they will be used to steer the course of future
  364.      columns.
  365. əəəəəəəəəəəəəəəəəəəəəəə