home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 5 / amigaformatcd05.iso / mui / developer / docs / muidev.guide (.txt) next >
Amigaguide Document  |  1996-08-13  |  63KB  |  1,364 lines

  1. @database MUI/Developer/Docs/MUIdev.guide
  2. @Master doc/MUIdev.texi
  3. @Width 72
  4. This is the AmigaGuide
  5.  file MUI/Developer/Docs/MUIdev.guide, produced by Makeinfo-1.55 from 
  6. the input file doc/MUIdev.texi.
  7. @Node Main "MUI/Developer/Docs/MUIdev.guide"
  8. @Next "GST_OOP"
  9.                        MUI - MagicUserInterface
  10.        A system to create and maintain graphical user interfaces
  11.                        Programmer Documentation
  12.                 (c) Copyright 1993/94 by Stefan Stuntz
  13. Getting Started...
  14.  @{" OOP Overview        " Link "GST_OOP"}                  Some words about Boopsi.
  15.  @{" Available Classes   " Link "GST_CLASSES"}                  List of available classes.
  16.  @{" Application Theory  " Link "GST_APPTHEORY"}                  The application tree.
  17.  @{" Object Handling     " Link "GST_OBJECTS"}                  General object handling.
  18.  @{" Macros              " Link "GST_MACROS"}                  Creating objects with macros.
  19. Layout...
  20.  @{" Basics              " Link "LAY_BASICS"}                  Automatic layout engine.
  21.  @{" Groups              " Link "LAY_GROUPS"}                  Grouping objects.
  22. Building An Application...
  23.  @{" Creation            " Link "APP_CREATE"}                  Object generation.
  24.  @{" Notification        " Link "APP_NOTIFY"}                  Object connections.
  25. Dynamic Object Linking...
  26.  @{" Overview            " Link "DYN_OVERVIEW"}                  OM_ADDMEMBER and OM_REMMEMBER.
  27.  @{" Windows             " Link "DYN_WINDOWS"}                  Dynamic creation of windows.
  28.  @{" Groups              " Link "DYN_GROUPS"}                  Dynamic creation of gadgets.
  29. Custom Classes...
  30.  @{" Introduction        " Link "CSC_INTRO"}                  General Infos.
  31.  @{" Overview            " Link "CSC_OVERVIEW"}                  Building the class.
  32.  @{" Methods             " Link "CSC_METHODS"}                  Methods in general.
  33.  @{" New & Dispose       " Link "CSC_NEWDISPOSE"}                  OM_NEW and OM_DISPOSE.
  34.  @{" Setup & Cleanup     " Link "CSC_SETUPCLEANUP"}                  MUIM_Setup and MUIM_Cleanup.
  35.  @{" AskMinMax           " Link "CSC_ASKMINMAX"}                  MUIM_AskMinMax
  36.  @{" Show & Hide         " Link "CSC_SHOWHIDE"}                  MUIM_Show and MUIM_Hide.
  37.  @{" Draw                " Link "CSC_DRAW"}                  MUIM_Draw.
  38.  @{" HandleInput         " Link "CSC_HANDLEINPUT"}                  MUIM_HandleInput.
  39.  @{" Set & Get           " Link "CSC_SETGET"}                  OM_SET and OM_GET.
  40.  @{" Distribution        " Link "CSC_DISTRIBUTE"}                  Distributing custom classes.
  41.  @{" Libraries           " Link "CSC_LIBRARIES"}                  External class libraries.
  42. Style Guide...
  43.  @{" Overview            " Link "STG_OVERVIEW"}               Rules for MUI programs.
  44. @EndNode
  45. @Node "GST_OOP" "MUIdev.guide/GST_OOP"
  46. @Next "GST_CLASSES"
  47. @Prev "Main"
  48. @Toc "Main"
  49. Getting Started
  50. ***************
  51.    Note: This documentation does not cover all concepts of MUI
  52. programming in detail. It's important that you also read the
  53. accompanying per class autodocs and have a look at the supplied demo
  54. programs!
  55. Object Oriented Programming
  56. ===========================
  57.    The MUI system is based on BOOPSI, the Basic Object Oriented
  58. Programming System for Intuition. Understanding MUI and understanding
  59. this documentation requires at least a little knowledge about the
  60. concepts of object oriented programming, about classes, objects,
  61. methods and attributes. An absolutely sufficient introduction to these
  62. topics can be found in the "Libraries" part of the "ROM Kernel
  63. Reference Manuals" or in several Amiga mail articles.
  64.    When talking about BOOPSI, most people automatically think of BOOPSI
  65. images and BOOPSI gadgets as part of the Amiga operating system.
  66. However, BOOPSI for itself is just a system for object oriented
  67. programming. One could e.g. have object oriented spread sheet software
  68. or object oriented file systems based on BOOPSI, intuition's builtin
  69. classes (gadgetclass, imageclass) are just two from thousands of
  70. possibilities.
  71.    The MUI system also uses BOOPSI only as a base for object oriented
  72. programming. Thus, MUI classes are all subclasses of BOOPSI's rootclass
  73. and have nothing in common with the system supplied gadget or image
  74. classes. Unfortunately, Commodore missed some very important topics
  75. when designing these classes, disabling them for use in automatic
  76. layout systems such as MUI. Anyway, MUI features an interface to
  77. BOOPSI's gadgetclass and allows using already available gadgets (e.g.
  78. the Kick 3.x colorwheel) in MUI applications.
  79. @EndNode
  80. @Node "GST_CLASSES" "MUIdev.guide/GST_CLASSES"
  81. @Next "GST_APPTHEORY"
  82. @Prev "GST_OOP"
  83. @Toc "Main"
  84. Available Classes
  85. =================
  86.    The MUI system comes with several classes, each of them available as
  87. seperate shared system library. These classes are organized in a tree.
  88. As usual in the OO programming model, objects inherit all methods and
  89. attributes from their true class as well as from all their
  90. superclasses. Here is a quick summary with some short notes what the
  91. classes are used for. More detailed information can be found later in
  92. this document and in the per class autodocs files coming with the
  93. developer archive.
  94.      rootclass               (BOOPSI's base class)
  95.      \--Notify               (implements notification mechanism)
  96.         +--Application       (main class for all applications)
  97.         +--Window            (handles intuition window related topics)
  98.         \--Area              (base class for all GUI elements)
  99.            +--Rectangle      (creates empty rectangles)
  100.            +--Image          (creates images)
  101.            +--Text           (creates some text)
  102.            +--String         (creates a string gadget)
  103.            +--Prop           (creates a proportional gadget)
  104.            +--Gauge          (creates a fule gauge)
  105.            +--Scale          (creates a percentage scale)
  106.            +--Boopsi         (interface to BOOPSI gadgets)
  107.            +--Colorfield     (creates a field with changeable color)
  108.            +--List           (creates a line-oriented list)
  109.            !  +--Floattext   (special list with floating text)
  110.            !  +--Volumelist  (special list with volumes)
  111.            !  +--Scrmodelist (special list with screen modes)
  112.            !  \--Dirlist     (special list with files)
  113.            \--Group          (groups other GUI elements - handles layout)
  114.               +--Virtgroup   (handles virtual groups)
  115.               +--Scrollgroup (handles virtual groups with scrollers)
  116.               +--Scrollbar   (creates a scrollbar)
  117.               +--Listview    (creates a listview)
  118.               +--Radio       (creates radio buttons)
  119.               +--Cycle       (creates cycle gadgets)
  120.               +--Slider      (creates slider gadgets)
  121.               +--Coloradjust (creates some RGB sliders)
  122.               \--Palette     (creates a complete palette gadget)
  123. @EndNode
  124. @Node "GST_APPTHEORY" "MUIdev.guide/GST_APPTHEORY"
  125. @Next "GST_OBJECTS"
  126. @Prev "GST_CLASSES"
  127. @Toc "Main"
  128. Application Theory
  129. ==================
  130.    A MUI application consists of a (sometimes very) big object tree
  131. (don't mix up with the class tree explained above).  The root of this
  132. tree is always an instance of application class, called application
  133. object. This application object handles the various communication
  134. channels such as user input through windows, ARexx commands or
  135. commodities messages.
  136.    An application object itself would be enough to create non-GUI
  137. programs with just ARexx and commodities capabilities. If you want to
  138. have windows with lots of nice gadgets and other user interface stuff,
  139. you will have to add window objects to your application. Since the
  140. application object is able to to handle any number of children, the
  141. number of windows is not limited.
  142.    Window objects are instances of window class and handle all the
  143. actions related with opening, closing, moving, resizing and refreshing
  144. of intuition windows. However, a window for itself is not of much use
  145. without having any contents to display.  That's why window objects
  146. always need a so called root object.
  147.    With this root object, we finally reach the gadget related classes
  148. of the MUI system. These gadget related classes are all subclasses of
  149. area class, they describe a rectangle region with some class dependant
  150. contents. Many different classes such as strings, buttons, checkmarks
  151. or listviews are available, but the most important subclass of area
  152. class is probably the group class. Instances of this class are able to
  153. handle any number of child objects and control the size and position of
  154. these children with various attributes. Of course these children can
  155. again be group objects with other sets of children.  Since you usually
  156. want your window to contain more than just one object, the root object
  157. of a window will be a group class object in almost all cases.
  158.    Because these first paragraphs are very important to understand how
  159. MUI works, here's a brief summary:
  160.    An application consists of exactly one application object. This
  161. application object may have any number of children, each of them being
  162. a window object. Every window object contains a root object, usually of
  163. type group class. This group object again handles any number of child
  164. objects, either other group objects or some user interface elements
  165. such as strings, sliders or buttons.
  166.    A little diagram might make things more clear:
  167.                                  +-------------+
  168.                                  ! Application !
  169.                                  +-------------+
  170.                                         !
  171.               ... ------+---------------+----------------+
  172.                         !               !                !
  173.                    +--------+       +--------+       +--------+
  174.                    ! Window !       ! Window !       ! Window !
  175.                    +--------+       +--------+       +--------+
  176.                         !               !                !
  177.                     +-------+
  178.                     ! Group !          ...              ...
  179.                     +-------+
  180.                         !
  181.          +------------+-+--------+-----------------+
  182.          !            !          !                 !
  183.      +--------+   +-------+   +------+         +-------+
  184.      ! String !   ! Group !   ! Text !         ! Group !
  185.      +--------+   +-------+   +------+         +-------+
  186.                       !                            !
  187.        ... -----+-----+-----+          +-----------+------- ...
  188.                 !           !          !           !
  189.              +------+   +-------+   +------+   +-------+
  190.              ! List !   ! Cycle !   ! List !   ! Group !
  191.              +------+   +-------+   +------+   +-------+
  192.                                                    !
  193.                                              +-----+-----+
  194.                                              !           !
  195.                                          +--------+  +--------+
  196.                                          ! Button !  ! Button !
  197.                                          +--------+  +--------+
  198.    As shown in this tree, only three types of objects are allowed to
  199. have children:
  200.      Application: zero or more children of window class.
  201.           Window: exactly one child of any subclass of area class.
  202.            Group: one or more children of any subclass of area class.
  203. @EndNode
  204. @Node "GST_OBJECTS" "MUIdev.guide/GST_OBJECTS"
  205. @Next "GST_MACROS"
  206. @Prev "GST_APPTHEORY"
  207. @Toc "Main"
  208. Object Handling
  209. ===============
  210.    Since MUI uses BOOPSI as object oriented programming system, objects
  211. could simply be created using intuition.library/NewObject().  However,
  212. `muimaster.library' also features a generation function called
  213.      Object * MUI_NewObjectA(STRPTR class, struct TagItem *taglist);
  214. with the varargs stub
  215.      Object * MUI_NewObject(STRPTR class, Tag tag1, ..., TAG_DONE);
  216.    That's the function you should use when creating objects of public
  217. MUI classes. The parameter `class' specifies the name of the object's
  218. class (e.g. `MUIC_Window', `MUIC_Slider', ...).  If the needed class
  219. isn't already in memory, it is automatically loaded from disk.
  220.    With `taglist', you specify initial create time attributes for your
  221. object. Every attribute from the objects true class or from one of its
  222. super classes is valid here, as long as it's marked with the letter `I'
  223. in the accompanying autodocs documentation.
  224.    To create a string object with a string-kind frame, a maximum length
  225. of 80 and the initial contents "foobar", you would have to use the
  226. following command:
  227.      MyString = MUI_NewObject(MUIC_String,
  228.                     MUIA_Frame          , MUIV_Frame_String,
  229.                     MUIA_String_Contents, "foobar",
  230.                     MUIA_String_MaxLen  , 80,
  231.                     TAG_DONE);
  232.    Once your object is ready, you can start talking to it by setting or
  233. getting one of its attributes or by sending it methods. The standard
  234. BOOPSI functions `SetAttrs()', `GetAttr()' and `DoMethod()' are used
  235. for these purposes:
  236.         char *contents;
  237.         SetAttrs(MyString,MUIA_String_Contents,"look",TAG_DONE);
  238.         GetAttr(MUIA_String_Contents,MyString,&contents);
  239.         printf("Always %s on the bright side of life.",contents);
  240.      
  241.         DoMethod(mylist,MUIM_List_Remove,42); /* remove entry nr 42 */
  242.    As already mentioned above, all attributes and methods are completely
  243. documented in the autodocs coming with this distribution. These
  244. autodocs follow the usual format, you can parse them with one of the
  245. various tools to create some hypertext online help for your favourite
  246. editor.
  247.    When you're done with an object, you should delete it with a call to
  248.      VOID MUI_DisposeObject(Object *obj);
  249. from `muimaster.library'. After doing so, the object pointer is invalid
  250. and must no longer be used.
  251.    When deleting objects, the parent-child connections mentioned above
  252. play an important role. If you dispose an object with children, not
  253. only the object itself but also all of its children (and their
  254. children, and the children of their children ...) get deleted. Since in
  255. a usual MUI application, the application object is the father of every
  256. window, the window is the father of it's contents and every group is
  257. the father of its sub objects, a single dispose of the application
  258. object will free the entire application.
  259.    Note well: you may *not* delete objects that are currently children
  260. of other objects. Thus, if you have a complete application tree, the
  261. only thing you can delete is the application object itself as this one
  262. has no father. You can, however, add and remove children dynamically.
  263. More information on that topic follows later in this document.
  264. @EndNode
  265. @Node "GST_MACROS" "MUIdev.guide/GST_MACROS"
  266. @Next "LAY_BASICS"
  267. @Prev "GST_OBJECTS"
  268. @Toc "Main"
  269. Macros
  270. ======
  271.    This chapter is only valid if you use C as your MUI programming
  272. language. Other language interfaces might feature other types of macros
  273. or support functions. Please have a look at the supplied interfaces to
  274. see how they work.
  275.    The tree structure that builds up an application also appears in the
  276. source code of a MUI program. Since adding child objects is always
  277. possible with a special attribute of the parent object, it is common to
  278. create the whole tree with one big function call.
  279.    To help making these calls more clear, the MUI header files contain
  280. several macros that simplify the task of object generation.
  281.    Instead of
  282.      MUI_NewObject(MUIC_Window, ..., TAG_DONE);
  283.      MUI_NewObject(MUIC_String, ..., TAG_DONE);
  284.      MUI_NewObject(MUIC_Slider, ..., TAG_DONE);
  285. you can simply use
  286.      WindowObject, ..., End;
  287.      StringObject, ..., End;
  288.      SliderObject, ..., End;
  289.    Please note that the `xxxObject' macros contain an opening bracket
  290. and thus must always be terminated with an `End' macro that contains
  291. the matching closing bracket.
  292.    Besides these "two way" macros, there are also some complete object
  293. definitions available which all create specific objects with certain
  294. types of attributes. The macro
  295.      SimpleButton("Cancel")
  296. would e.g. generate a complete button object with the correct frame,
  297. background and input capabilities. Though lots of these types of macros
  298. are available and can of course be used directly in your applications,
  299. they are mainly intended as some kind of example. Usually you will need
  300. some more sophisticated generation capabilities with a more specific
  301. set of macros.
  302.    Note: If your application needs lots of objects from a specific type
  303. (e.g. 200 buttons), you can save some memory by turning macros into
  304. functions.
  305. @EndNode
  306. @Node "LAY_BASICS" "MUIdev.guide/LAY_BASICS"
  307. @Next "LAY_GROUPS"
  308. @Prev "GST_MACROS"
  309. @Toc "Main"
  310. Layout Engine
  311. *************
  312. Overview
  313. ========
  314.    One of the most important and powerful features of MUI is its dynamic
  315. layout engine. As opposed to other available user interface tools, the
  316. programmer of a MUI application doesn't have to care about gadget sizes
  317. and positions. MUI handles all necessary calculations automatically,
  318. making every program completely screen, window size and font sensitive
  319. without the need for the slightest programmer interaction.
  320.    From a programmers point of view, all you have to do is to define
  321. some rectangle areas that shall contain the objects you want to see in
  322. your window. Objects of group class are used for this purpose. These
  323. objects are not visible themselves, but instead tell their children
  324. whether they should appear horizontally or vertically (there are more
  325. sophisticated layout possibilities, more on this later).
  326.    For automatic and dynamic layout, it's important that every single
  327. object knows about its minimum and maximum dimensions. Before opening a
  328. window, MUI asks all its gadgets about these values and uses them to
  329. calculate the windows extreme sizes.
  330.    Once the window is opened, layout takes place. Starting with the
  331. current window size, the root object and all its children are placed
  332. depending on the type of their father's group and on some additional
  333. attributes.  The algorithm ensures that objects will never become
  334. smaller as their minimum or larger as their maximum size.
  335.    The important thing with this mechanism is that object placement
  336. depends on window size. This allows very easy implementation of a
  337. sizing gadget: whenever the user resizes a window, MUI simply starts a
  338. new layout process and recalculates object positions and sizes
  339. automatically. No programmer interaction is needed.
  340. @EndNode
  341. @Node "LAY_GROUPS" "MUIdev.guide/LAY_GROUPS"
  342. @Next "APP_CREATE"
  343. @Prev "LAY_BASICS"
  344. @Toc "Main"
  345. Groups
  346. ======
  347.    As mentioned above, a programmer specifies a windows design by
  348. grouping objects either horizontally or vertically. As a little
  349. example, lets have a look at a simple file requester window:
  350.      +---------------------------------------+
  351.      !                                       !
  352.      !  +------------------------+ +------+  !
  353.      !  ! C                (dir) ! ! dh0: !  !
  354.      !  ! Classes          (dir) ! ! dh1: !  !
  355.      !  ! Devs             (dir) ! ! dh2: !  !
  356.      !  ! Expansion        (dir) ! ! df0: !  !
  357.      !  ! ...                    ! ! df1: !  !
  358.      !  ! Trashcan.info    1.172 ! ! df2: !  !
  359.      !  ! Utilities.info     632 ! ! ram: !  !
  360.      !  ! WBStartup.info     632 ! ! rad: !  !
  361.      !  +------------------------+ +------+  !
  362.      !                                       !
  363.      !  Path: _____________________________  !
  364.      !                                       !
  365.      !  File: _____________________________  !
  366.      !                                       !
  367.      !  +------+                 +--------+  !
  368.      !  ! Okay !                 ! Cancel !  !
  369.      !  +------+                 +--------+  !
  370.      !                                       !
  371.      +---------------------------------------+
  372.    This window consists of two listview objects, two string gadgets and
  373. two buttons. To tell MUI how these objects shall be placed, you need to
  374. define groups around them. Here, the window consists of a vertical group
  375. that contains a horizontal group with both lists as first child, the
  376. path gadget as second child, the file gadget as third child and again a
  377. horizontal group with both buttons as fourth child.
  378.    Using the previously defined macro language, the specification could
  379. look like this (in this example, `VGroup' creates a vertical group and
  380. `HGroup' creates a horizontal group):
  381.      VGroup,
  382.         Child, HGroup,
  383.            Child, FileListview(),
  384.            Child, DeviceListview(),
  385.            End,
  386.         Child, PathGadget(),
  387.         Child, FileGadget(),
  388.         Child, HGroup,
  389.            Child, OkayButton(),
  390.            Child, CancelButton(),
  391.            End,
  392.         End;
  393.    This tiny piece of source is completely enough to define the
  394. contents of our window, all necessary sizes and positions are
  395. automatically calculated by the MUI system.
  396.    To understand how these calculations work, it's important to know
  397. that all basic objects (e.g. strings, buttons, lists) have a fixed
  398. minimum and a maximum size. Group objects calculate their minimum and
  399. maximum sizes from their children, depending whether they are
  400. horizontal or vertical:
  401.    - Horizontal groups
  402.      The minimum width of a horizontal group is the sum of all minimum
  403.      widths of its children.
  404.      The maximum width of a horizontal group is the sum of all maximum
  405.      widths of its children.
  406.      The minimum height of a horizontal group is the biggest minimum
  407.      height of its children.
  408.      The maximum height of a horizontal group is the smallest maximum
  409.      height of its children.
  410.    - Vertical groups
  411.      The minimum height of a vertical group is the sum of all minimum
  412.      heights of its children.
  413.      The maximum height of a vertical group is the sum of all maximum
  414.      heights of its children.
  415.      The minimum width of a vertical group is the biggest minimum width
  416.      of its children.
  417.      The maximum width of a vertical group is the smallest maximum
  418.      width of its children.
  419.    Maybe this algorithm sounds a little complicated, but in fact it is
  420. really straight forward and ensures that objects will neither get
  421. smaller as their minimum nor bigger as their maximum size.
  422.    Before a window is opened, it asks its root object (usually a group
  423. object) to calculate minimum and maximum sizes. These sizes are used as
  424. the windows bounding dimensions, the smallest possible window size will
  425. result in all objects being display in their minimum size.
  426.    Once minimum and maximum sizes are calculated, layout process
  427. starts. The root object is told to place itself in the rectangle
  428. defined by the current window size. This window size is either
  429. specified by the programmer or results from a window resize operation
  430. by the user. When an object is told to layout itself, it simply sets
  431. its position and dimensions to the given rectangle.  In case of a group
  432. object, a more or less complicated algorithm distributes all available
  433. space between its children and tells them to layout too.
  434.    This "more or less complicated algorithm" is responsible for the
  435. object arrangement. Depending on some attributes of the group object
  436. (horizontal or vertical, ...) and on some attributes of the children
  437. (minimum and maximum dimensions, ...), space is distributed and
  438. children are placed.
  439.    A little example makes things more clear. Let's see what happens in
  440. a window that contains nothing but three horizontally grouped
  441. colorfield objects:
  442.      +---------------------------------+
  443.      !                                 !
  444.      !  +-------+ +-------+ +-------+  !
  445.      !  !       ! !       ! !       !  !
  446.      !  ! field ! ! field ! ! field !  !
  447.      !  !   1   ! !   2   ! !   3   !  !
  448.      !  !       ! !       ! !       !  !
  449.      !  +-------+ +-------+ +-------+  !
  450.      !                                 !
  451.      +---------------------------------+
  452.    Colorfield objects have a minimum width and height of one pixel and
  453. no (in fact a very big) maximum width and height. Since we have a
  454. horizontal group, the minmax calculation explained above yields to a
  455. minimum width of three pixels and a minimum height of one pixel for the
  456. windows root object (the horizontal group containing the colorfields).
  457. Maximum dimensions of the group are unlimited. Using these results, MUI
  458. is able to calculate the windows bounding dimensions by adding some
  459. spacing values and window border thicknesses.
  460.    Once min and max dimensions are calculated, the window can be opened
  461. with a programmer or user specified size. This size is the starting
  462. point for the following layout calculations. For our little example,
  463. let's imagine that the current window size is 100 pixels wide and 50
  464. pixels high.
  465.    MUI subtracts the window borders and some window inner spacing and
  466. tells the root object to layout itself into the rectangle left=5,
  467. top=20, width=90, height=74. Since our root object is a horizontal
  468. group in this case, it knows that each colorfield can get the full
  469. height of 74 pixels and that the available width of 90 pixels needs to
  470. be shared by all three fields.  Thus, the resulting fields will all get
  471. a width of 90/3=30 pixels.
  472.    That's the basic way MUI's layout system works. There are a lot more
  473. possibilities to influence layout, you can e.g.  assign different
  474. weights to objects, define some inter object spacing or even make
  475. two-dimensional groups. These sophisticated layout issues are discussed
  476. in the autodocs of group class.
  477. @EndNode
  478. @Node "APP_CREATE" "MUIdev.guide/APP_CREATE"
  479. @Next "APP_NOTIFY"
  480. @Prev "LAY_GROUPS"
  481. @Toc "Main"
  482. Building An Application
  483. ***********************
  484. Creation
  485. ========
  486.    Creating all the objects that make up an applications user interface
  487. is usually done with one big `MUI_NewObject()' call. This call returns
  488. a pointer to the application object as its result and contains lots of
  489. other object creation calls as parameter for its tag items. Using the
  490. previously defined macro language, a sample generation call could look
  491. like this:
  492.      app = ApplicationObject,
  493.         MUIA_Application_Title      , "Settings",
  494.         MUIA_Application_Version    , "$VER: Settings 6.16 (20.10.93)",
  495.         MUIA_Application_Copyright  , "
  496. 1992/93, Stefan Stuntz",
  497.         MUIA_Application_Author     , "Stefan Stuntz",
  498.         MUIA_Application_Description, "Just a silly demo",
  499.         MUIA_Application_Base       , "SETTINGS",
  500.      
  501.         SubWindow, window1 = WindowObject,
  502.            MUIA_Window_Title, "Save/use me and start me again!",
  503.            MUIA_Window_ID   , MAKE_ID('S','E','T','T'),
  504.      
  505.            WindowContents, VGroup,
  506.      
  507.               Child, ColGroup(2), GroupFrameT("User Identification"),
  508.                  Child, Label2("Name:"  ), Child, str1 = String(0,40),
  509.                  Child, Label2("Street:"), Child, str2 = String(0,40),
  510.                  Child, Label2("City:"  ), Child, str3 = String(0,40),
  511.                  Child, Label1("Passwd:"), Child, str4 = String(0,40),
  512.                  Child, Label1("Sex:"   ), Child, str5 = String(0,40),
  513.                  Child, Label("Age:"),
  514.                  Child, sl  = SliderObject, End,
  515.                  End,
  516.      
  517.               Child, VSpace(2),
  518.      
  519.               Child, HGroup,
  520.                  MUIA_Group_SameSize, TRUE,
  521.                  Child, btsave   = KeyButton("Save"  ,'s'),
  522.                  Child, btuse    = KeyButton("Use"   ,'u'),
  523.                  Child, btcancel = KeyButton("Cancel",'>'),
  524.                  End,
  525.      
  526.               End,
  527.            End,
  528.      
  529.         SubWindow, window2 = WindowObject,
  530.            MUIA_Window_Title, "Window 2",
  531.            ...,
  532.            ...,
  533.            End,
  534.      
  535.         SubWindow,
  536.            ...
  537.            End,
  538.      
  539.         End;
  540.      
  541.      if (!app) fail(app,"Failed to create Application.");
  542.    This big structure is indeed one single function call that builds a
  543. lot of other objects on the fly. Windows are created as children of the
  544. application object, a windows contents are created as child of the
  545. window and a groups contents are created as children of the group.
  546.    Though many single objects are created, error handling is very easy.
  547. When a parent object encounters a NULL pointer supplied as one of its
  548. children, it will automatically dispose all other supplied children and
  549. fail too. Thus, even errors occuring in a very deep level will cause
  550. the complete application object to fail.  On the other hand, if you
  551. receive a non NULL application pointer, you can be sure that all other
  552. objects have successfully been created.
  553.    Once you're done with your application, a single
  554.      MUI_DisposeObject(app);
  555. is enough to get rid of all previously created objects.
  556. @EndNode
  557. @Node "APP_NOTIFY" "MUIdev.guide/APP_NOTIFY"
  558. @Next "DYN_OVERVIEW"
  559. @Prev "APP_CREATE"
  560. @Toc "Main"
  561. Notificiation
  562. =============
  563.    The central element for controlling a MUI application is the
  564. notification mechanism. To understand how it works, its important to
  565. know that most objects feature lots of attributes that define their
  566. current state. Notification makes it possible to react on changes of
  567. these attributes.
  568.    Attributes are changed either directly by the programmer (with a
  569. call to SetAttrs()) or by the user manipulation some gadgets.  If he
  570. e.g. drags around the knob of a proportional gadget, the
  571. MUIA_Prop_First attribute will continously be updated and reflect the
  572. current position.
  573.    With notification, you could directly use this attribute change to
  574. set the MUIA_List_TopPixel attribute of a list object, building up a
  575. full featured listview:
  576.      DoMethod(sbar, MUIM_Notify, MUIA_Prop_First, MUIV_EveryTime,
  577.               list, 3, MUIM_Set, MUIA_List_TopPixel, MUIV_TriggerValue);
  578.    To make it clear: Every time, the scrollbar object changes its
  579. `MUIA_Prop_First' value, the list object shall change its
  580. `MUIA_List_TopPixel' attribute accordingly. The value 3 in the above
  581. function call identifies the number of the following parameters. Since
  582. you can call any method with any parameters here and MUI needs to save
  583. it somewhere, it's important to set it correctly.
  584.    From now on the list and the scrollbar are connected to each other.
  585. As soon as the proportional gadget is moved, the position of the list
  586. changes accordingly; the programmer doesn't have to care about.
  587.    Notification is mostly used together with either the
  588. `MUIM_Application_ReturnID' or with the `MUIM_CallHook' method. If you
  589. e.g. have a specific hook that should be called whenever the user
  590. presses a button, you could use the following notify method:
  591.      DoMethod(button, MUIM_Notify, MUIA_Pressed, FALSE,
  592.               button, 2, MUIM_CallHook, &ButtonHook);
  593.      
  594.      /* Whenever the button's pressed attribute is set to FALSE
  595.         (i.e. the user has released the button), the button object
  596.         itself will call ButtonHook. */
  597.    Futher information can be found in the autodocs of notify class.
  598. @EndNode
  599. @Node "DYN_OVERVIEW" "MUIdev.guide/DYN_OVERVIEW"
  600. @Next "DYN_WINDOWS"
  601. @Prev "APP_NOTIFY"
  602. @Toc "Main"
  603. Dynamic Object Linking
  604. **********************
  605. Overview
  606. ========
  607.    Usually, the complete user interface of an application is created
  608. with one single command. This makes error handling very easy and allows
  609. parallel usage of several windows. However, sometimes it makes sense to
  610. create certain windows only when they are actually needed: For example,
  611. if an application supplies many subwindows and would use too much
  612. memory, or if the number and contents of needed windows is not known at
  613. application startup time.
  614.    Therefore MUI supports the option of "late binding".  Using this
  615. mechanism, children can be added and removed after their parent object
  616. already has been created. MUI uses the methods `OM_ADDMEMBER' and
  617. `OM_REMMEMBER' for this purpose:
  618.      DoMethod(parent,OM_ADDMEMBER,child); /* add child object    */
  619.      DoMethod(parent,OM_REMMEMBER,child); /* remove child object */
  620.    Both methods are only supported by MUI's application and group
  621. class; these are the only classes that can manage several children.
  622. Dynamic object linking for window and group class is explained in
  623. detail in the following chapters.
  624.    Note: Objects that do not have parents, be it, because they are not
  625. yet connected using `OM_ADDMEMBER' or because they were disconnected
  626. using `OM_REMMEMBER', it's the programmer's task to delete them by
  627. calling `MUI_DisposeObject()'.  On the other side, objects that still
  628. are children of other objects must not be deleted!
  629. @EndNode
  630. @Node "DYN_WINDOWS" "MUIdev.guide/DYN_WINDOWS"
  631. @Next "DYN_GROUPS"
  632. @Prev "DYN_OVERVIEW"
  633. @Toc "Main"
  634. Dynamic Windows
  635. ===============
  636.    Let's say an application object is already set up and another (not
  637. yet existing) window has to be added. First, the window object needs to
  638. be created:
  639.      win = WindowObject,
  640.         MUIA_Window_Title, "New Window",
  641.            WindowContents, VGroup,
  642.               Child, ...,
  643.               Child, ...,
  644.               Child, ...,
  645.               End,
  646.            End,
  647.         End;
  648.      
  649.      if (!win) fail(); /* failure check */
  650. After the window object is created, it can be added to the application
  651. as one of its children:
  652.      DoMethod(app,OM_ADDMEMBER,win);
  653.    Now this window has become a part of the application, just as if it
  654. had been created as a subwindow together with the application object.
  655. It can be opened and closed by setting the according attributes and
  656. will be deleted automatically as soon as the application is ended.
  657.    Usually, however, you'll want to delete this window directly after
  658. usage, because the late binding wouldn't make much sense otherwise.
  659. After closing the window via
  660.      set(win,MUIA_Window_Open,FALSE);
  661. you can remove it by calling
  662.      DoMethod(app,OM_REMMEMBER,win);
  663.    After this you have to delete the window object "by hand", since the
  664. application no longer knows of it:
  665.      MUI_DisposeObject(win);
  666.    This method makes it possible to create subroutines that open their
  667. own window, wait for some imput events und return something.
  668. To illustrate this, here is a short example:
  669.      set(app,MUIA_Application_Sleep,TRUE);  // disable other windows
  670.      
  671.      win = WindowObject, ...., End;         // create new window
  672.      
  673.      if (win)                               // ok ?
  674.      {
  675.          DoMethod(app,OM_ADDMEMBER,win);    // add window...
  676.          set(win,MUIA_Window_Open,TRUE);    // and open it
  677.      
  678.          while (running)
  679.          {
  680.              switch (DoMethod(app,MUIM_Application_Input,&sigs))
  681.              {
  682.                  ... // Extra Input loop. For this window only.
  683.                  ... // Note: The special value
  684.                  ... // MUIV_Application_ReturnID_Quit should be recognized
  685.                  ... // as well
  686.              }
  687.          }
  688.      
  689.          set(win,MUIA_Window_Open,FALSE);   // Close window
  690.      
  691.          DoMethod(app,OM_REMMEMBER,win);    // remove
  692.      
  693.          MUI_DisposeObject(win);            // and kill it
  694.      }
  695.      
  696.      set(app,MUIA_Application_Sleep,FALSE); // wake up the application
  697. @EndNode
  698. @Node "DYN_GROUPS" "MUIdev.guide/DYN_GROUPS"
  699. @Next "CSC_INTRO"
  700. @Prev "DYN_WINDOWS"
  701. @Toc "Main"
  702. Dynamic Groups
  703. ==============
  704.    In the same way you can add windows to an application after its
  705. creation, you can add elements to already existing group objects. This
  706. may be useful if a group contains many similar children or if the
  707. number of children is not known in the beginning.
  708.    You can add new elements to groups or delete them again, but the
  709. window that contains this group must not be open!
  710. A small example:
  711.          app = ApplicationObject,
  712.              ...,
  713.              SubWindow, win = WindowObject,
  714.                  WindowContents, VGroup,
  715.                      ...,
  716.                      grp = VGroup,
  717.                  End,
  718.                  ...,
  719.              End,
  720.          End,
  721.      End;
  722.      
  723.      /* The group 'grp' has been created without any children. */
  724.      /* The window must not be opened now!                     */
  725.      
  726.      for (i=0; i<NumPlayers; i++)
  727.      {
  728.         Object *name = StringObject, MUIA_String_MaxLen, 30, End;
  729.         if (name)
  730.            DoMethod(grp,OM_ADDMEMBER,name); // add gadget to group.
  731.         else
  732.            fail();
  733.      }
  734.      
  735.      /* After we have at least one element in the group 'grp', */
  736.      /* the window can be opened...                            */
  737.    Of course you may (if the window is closed) remove elements from
  738. groups. Please note that window objects containing empty groups must
  739. not be opened.
  740. @EndNode
  741. @Node "CSC_INTRO" "MUIdev.guide/CSC_INTRO"
  742. @Next "CSC_OVERVIEW"
  743. @Prev "DYN_GROUPS"
  744. @Toc "Main"
  745. Custom Classes
  746. **************
  747. Introduction
  748. ============
  749.    MUI features a lot of builtin classes that already allow creation of
  750. powerful applications. However, a generic GUI system will never be able
  751. to satisfy all the requirements of all kinds of programs. A sound
  752. editor would e.g. need a class to display and edit sound data, a paint
  753. program would need a drawing area and a chess game would need a
  754. chess-board class.
  755.    Prior to MUI V2.0, programmers were stuck with the builtin classes.
  756. Except of the (sometimes problematic) BOOPSI interface, there was no
  757. way to include custom gadgets in a MUI window. This big disadvantage
  758. has finally disappeared, with MUI 2.0 it's posssible to write and use
  759. private classes just like one of the builtins.
  760.    Beneath the BOOPSI gadget interface, private classes are the only
  761. way to have custom gadgets in a MUI window. Drawing into windows
  762. directly from the applications task is illegal and will surely lead
  763. into lots of problems!
  764.    Note: Since this manual doesn't repeat the RKMs BOOPSI section, you
  765. should be familiar with the BOOPSI mechanisms of dispatchers, methods,
  766. attributes, instance data structures, etc. before going on.
  767. @EndNode
  768. @Node "CSC_OVERVIEW" "MUIdev.guide/CSC_OVERVIEW"
  769. @Next "CSC_METHODS"
  770. @Prev "CSC_INTRO"
  771. @Toc "Main"
  772. Overview
  773. ========
  774.    Building a class is rather simple. All you have to do is to write a
  775. class dispatcher function, setup a hook structure, call MUI_GetClass()
  776. to find the pointer to your superclass and use
  777. intuition.library/MakeClass() to create the class. If you already wrote
  778. BOOPSI classes, you should know whats going on here.
  779.    Objects from custom classes are created using intuition.library /
  780. NewObject(), not muimaster.library / MUI_NewObject(). Nevertheless, you
  781. can use these objects like every other MUI objects, e.g. as children of
  782. groups, in virtual groups or wherever you like.
  783.    All classes you create have to be subclasses of MUI's area class,
  784. most of them will probably be direct subclasses but you can also have
  785. subclasses of list class or even subclasses of your own classes if you
  786. want. Here's an example of how a custom class could be generated:
  787.         /* Get a pointer to the superclass. MUI will lock this */
  788.         /* and prevent it from being flushed during you hold   */
  789.         /* the pointer. When you're done, you have to call     */
  790.         /* MUI_FreeClass() to release this lock.               */
  791.      
  792.         if (!(SuperClass=MUI_GetClass(MUIC_Area)))
  793.            fail("Superclass for the new class not found.");
  794.      
  795.         /* Create the new class with the boopsi function call. */
  796.         /* You will need the sizeof your classes instance data */
  797.         /* here.                                               */
  798.      
  799.         if (!(MyClass = MakeClass(NULL,NULL,SuperClass,sizeof(struct MyData),0)))
  800.         {
  801.            MUI_FreeClass(SuperClass);
  802.            fail("Failed to create class.");
  803.         }
  804.      
  805.         /* Set the dispatcher for the new class. */
  806.      
  807.         MyClass->cl_Dispatcher.h_Entry    = (APTR)MyDispatcher;
  808.         MyClass->cl_Dispatcher.h_SubEntry = NULL;
  809.         MyClass->cl_Dispatcher.h_Data     = NULL;
  810.      
  811.         ...
  812.         ...
  813.      
  814.         app = ApplicationObject,
  815.            ...,
  816.      
  817.            SubWindow, window = WindowObject,
  818.               ...
  819.               WindowContents, VGroup,
  820.      
  821.                  Child, MyObj = NewObject(MyClass,NULL,
  822.                     TextFrame,
  823.                     MUIA_Background, MUII_BACKGROUND,
  824.                     TAG_DONE),
  825.      
  826.                  End,
  827.      
  828.               End,
  829.            End;
  830.      
  831.         ...
  832.         ...
  833.      
  834.         /* Shutdown. When the application is disposed,
  835.         /* MUI also deletes MyObj. */
  836.      
  837.         MUI_DisposeObject(app);     // dispose all objects.
  838.         FreeClass(MyClass);         // free our private class.
  839.         MUI_FreeClass(SuperClass);  // release super class pointer.
  840.    You're dispatcher will look like a traditional BOOPSI dispatcher:
  841.      SAVEDS ASM ULONG MyDispatcher(
  842.         REG(a0) struct IClass *cl,
  843.         REG(a2) Object *obj,
  844.         REG(a1) Msg msg)
  845.      {
  846.         switch (msg->MethodID)
  847.         {
  848.            case OM_NEW        : return(mNew      (cl,obj,(APTR)msg));
  849.            case OM_DISPOSE    : return(mDispose  (cl,obj,(APTR)msg));
  850.            case MUIM_AskMinMax: return(mAskMinMax(cl,obj,(APTR)msg));
  851.            case MUIM_Draw     : return(mDraw     (cl,obj,(APTR)msg));
  852.            ...
  853.         }
  854.      
  855.         return(DoSuperMethodA(cl,obj,msg));
  856.      }
  857.    What methods are available and need to be supported is discussed in
  858. the following chapter.
  859.    Note: Your dispatcher will also receive some undocumented methods.
  860. It's not a wise choice to make any assumptions here, the only thing you
  861. should do is pass them to your superclass immediately!
  862. @EndNode
  863. @Node "CSC_METHODS" "MUIdev.guide/CSC_METHODS"
  864. @Next "CSC_NEWDISPOSE"
  865. @Prev "CSC_OVERVIEW"
  866. @Toc "Main"
  867. Methods
  868. =======
  869.    The MUI system talks to its classes with a specific set of methods.
  870. Some of these methods need to be implemented by all MUI classes but
  871. most of them are optional.  This chapter gives a quick overview about
  872. the methods your class might receive.  All methods are discussed more
  873. detailed in the following sections.
  874.    As usual with BOOPSI objects, you will get an OM_NEW whenever a new
  875. object of your class shall be created. Since with MUI, the deepest
  876. nested objects are always created first, your object won't know anything
  877. about its display environment during OM_NEW.
  878.    After all objects are created, MUI finds out about the display
  879. environment (screen, drawinfo structure, fonts, etc.) and sends you a
  880. MUIM_Setup method with this information. You can calculate some
  881. internal data here that depends on the display enviroment (e.g. the
  882. line height in an editor class). Note that you still don't have a
  883. intuition window at this point.
  884.    The next method your class receives is called MUIM_AskMinMax. MUI
  885. wants to find out about your minimum, maximum and default sizes to
  886. prepare its window size calculation and layout algorithms. Since you
  887. already know about display environment, calculating these values should
  888. be easy at this point.
  889.    After asking all objects about their dimensions and adding the
  890. results depending on the type of group your object resides in, MUI is
  891. able to open the window. Once it is open, your object will receive a
  892. MUIM_Show method telling you that you are about to be added to the
  893. window.  MUIM_Show is mainly intended for use by intuition like
  894. gadgets, they will do an AddGadget() here (and a RemGadget() during
  895. MUIM_Hide). Usually, you won't need to implement these methods.
  896.    Since your class still didn't draw anything, its time for a
  897. MUIM_Draw method now. MUI sends this method whenever it feels that you
  898. should draw yourself.  This happens of course after a window has been
  899. opened but also when you reside in a simple refresh window and need to
  900. be refreshed. MUIM_Draw is the only place where you are actually
  901. allowed to draw something!
  902.    When the window is resized, MUI sends a MUIM_Hide (allowing some
  903. RemGadget() for intuition like gadgets), calculates new positions and
  904. sizes and sends a MUIM_Show and a MUIM_Draw again. However, if you
  905. correctly implement MUIM_Draw, you don't need to care about this in
  906. almost all cases.
  907.    When your window is about to be closed (either because your
  908. application no longer needs it or because the user iconified your
  909. program or changed the preferences settings), you will receive a
  910. MUIM_Cleanup. This allows you to free some display environment
  911. dependant things you allocated during MUIM_Setup.
  912.    The last thing your object will get is of course a OM_DISPOSE after
  913. it has hopefully done all the things you wanted it to do.
  914.    To sum it up again, look at the diagram below. Things between
  915. brackets might be called zero or more times for the same object.
  916.      OM_NEW; /* you dont know anything about display environment here */
  917.      {
  918.         MUIM_Setup;      /* information about display, still no window */
  919.         MUIM_AskMinMax;  /* tell me your min/max dimensions */
  920.         [ window is opened here ]
  921.         {
  922.            MUIM_Show;    /* add yourself to the window, don't yet draw */
  923.            {
  924.               MUIM_Draw;     /* draw yourself */
  925.            }
  926.            MUIM_Hide;    /* remove yourself from the window */
  927.         }
  928.         [ window is closed here ]
  929.         MUIM_Cleanup;    /* free any display dependant data */
  930.      }
  931.      OM_DISPOSE; /* kill yourself completely */
  932.    As you probably noticed, most methods are implemented as
  933. constructor/destructor pairs: OM_NEW & OM_DISPOSE, MUIM_Setup &
  934. MUIM_Cleanup, MUIM_Show & MUIM_Hide. For every constuctor call, you
  935. will receive exactly one destructor call. Usually, you will allocate
  936. some resources during OM_NEW, MUIM_Setup or MUIM_Show and free these
  937. resources during OM_DISPOSE, MUIM_Cleanup or MUIM_Hide respectively.
  938.    The three levels of constructor/destructor pairs feature different
  939. amount of available information about the display environment.
  940.    - OM_NEW (destructor OM_DISPOSE)
  941.      No information at all. All you can do is parse the initial
  942.      attribute list and store its contents in the instance data
  943.      structure of your object.
  944.    - MUIM_Setup (destructor MUIM_Cleanup)
  945.      MUI has figured out what screen and font to use. You can
  946.      allocate/calculate things that depend on this information.
  947.    - MUIM_Show (destructor MUIM_Hide)
  948.      MUI has finally opened an intuition window at this point. You are
  949.      able to allocate resources depending on a window context here.
  950.    You can rely on the fact that you receive OM_NEW before MUIM_Setup
  951. (of course, otherwise you wouldn't have a valid object pointer) and
  952. MUIM_Setup before MUIM_Show. But always keep in mind that you might get
  953. multiple MUIM_Show / MUIM_Hide pairs or MUIM_Setup / MUIM_Cleanup pairs
  954. or that you could receive a MUIM_Setup / MUIM_Cleanup pair without some
  955. MUIM_Show / MUIM_Hide between.
  956. @EndNode
  957. @Node "CSC_NEWDISPOSE" "MUIdev.guide/CSC_NEWDISPOSE"
  958. @Next "CSC_SETUPCLEANUP"
  959. @Prev "CSC_METHODS"
  960. @Toc "Main"
  961. OM_NEW & OM_DISPOSE
  962. ===================
  963.    Implementing these methods for MUI objects is mainly identical to
  964. traditional BOOPSI objects. The only thing important to remember is
  965. that MUI objects have really no idea about display environment or other
  966. configuration issues when receiving OM_NEW. The ops_GInfo member of the
  967. opSet parameter structure is always unused.  Typical new/dispose
  968. methods consist of some tag list parsing and instance data
  969. initialisation.
  970.      static ULONG mNew(struct IClass *cl,Object *obj,struct opSet *msg)
  971.      {
  972.         struct INST_DATA *data;
  973.      
  974.         if (!(obj = (Object *)DoSuperMethodA(cl,obj,msg)))
  975.            return(0);
  976.      
  977.         data = INST_DATA(cl,obj);
  978.      
  979.         data->min = GetTagData(MYATTR_Min,  0,msg->ops_AttrList);
  980.         data->max = GetTagData(MYATTR_Max,100,msg->ops_AttrList);
  981.         data->lvl = GetTagData(MYATTR_Lvl, 50,msg->ops_AttrList);
  982.      
  983.         data->count  = data->max - data->min + 1;
  984.         data->buffer = NULL;
  985.      
  986.         if (data->count > 0)
  987.         {
  988.            if (data->buffer = AllocVec(data->count * 4))
  989.            {
  990.               return((ULONG)obj);
  991.            }
  992.         }
  993.      
  994.         /* invoke OM_DISPOSE on *our* class! */
  995.         CoerceMethod(cl,obj,OM_DISPOSE);
  996.         return(0);
  997.      }
  998.      
  999.      
  1000.      static ULONG mDispose(struct IClass *cl,Object *obj,Msg msg)
  1001.      {
  1002.         struct Data *data = INST_DATA(cl,obj);
  1003.      
  1004.         if (data->buffer) FreeVec(data->buffer);
  1005.      
  1006.         return(DoSuperMethodA(cl,obj));
  1007.      }
  1008. @EndNode
  1009. @Node "CSC_SETUPCLEANUP" "MUIdev.guide/CSC_SETUPCLEANUP"
  1010. @Next "CSC_ASKMINMAX"
  1011. @Prev "CSC_NEWDISPOSE"
  1012. @Toc "Main"
  1013. MUIM_Setup & MUIM_Cleanup
  1014. =========================
  1015.    Since your object doesn't know anything about display environment
  1016. after it is created with OM_NEW, MUI will send you an MUIM_Setup when
  1017. it is about to open a window containing your object.
  1018.    The first thing you have to do is to pass MUIM_Setup to your super
  1019. class an return FALSE on failure. After this, you can calculate some
  1020. internal data or allocate some display buffers. Return TRUE if
  1021. everything went ok or FALSE when you discovered any errors. If you
  1022. return FALSE, you must also call MUIM_Cleanup on your superclasses to
  1023. give them the chance to free their setup stuff they allocated during
  1024. your DoSuperMethod(). See the example below on how to do this.
  1025.    If a MUIM_Setup returns FALSE, MUI will send a MUIM_Cleanup to all
  1026. objects that already received a MUIM_Setup (excluding the current one!)
  1027. and fail to open the window. Typical setup/cleanup pairs could look like
  1028. this:
  1029.      static ULONG mSetup(struct IClass *cl,Object *obj,Msg msg)
  1030.      {
  1031.         struct Data *data = INST_DATA(cl,obj);
  1032.      
  1033.         if (!(DoSuperMethodA(cl,obj,msg)))
  1034.            return(FALSE);
  1035.      
  1036.         data->lbuf = AllocVec(data->lsize);
  1037.         data->rbuf = AllocVec(data->rsize);
  1038.      
  1039.         if (!data->lbuf || !data->rbuf)
  1040.         
  1041.            CoerceMethod(cl,obj,MUIM_Cleanup);
  1042.            return(FALSE);
  1043.         
  1044.      
  1045.         data->lineheight = _font(obj)->tf_YSize;
  1046.      
  1047.         MUI_RequestIDCMP(obj,IDCMP_RAWKEY|IDCMP_MOUSEBUTTONS|IDCMP_INACTIVEWINDOW);
  1048.      
  1049.         return(TRUE);
  1050.      }
  1051.      
  1052.      
  1053.      static ULONG mCleanup(struct IClass *cl,Object *obj,Msg msg)
  1054.      {
  1055.         struct Data *data = INST_DATA(cl,obj);
  1056.      
  1057.         if (data->lbuf) FreeVec(data->lbuf);
  1058.         if (data->rbuf) FreeVec(data->rbuf);
  1059.      
  1060.         MUI_RejectIDCMP(obj,IDCMP_RAWKEY|IDCMP_MOUSEBUTTONS|IDCMP_INACTIVEWINDOW);
  1061.      
  1062.         return(DoSuperMethodA(cl,obj));
  1063.      }
  1064. @EndNode
  1065. @Node "CSC_ASKMINMAX" "MUIdev.guide/CSC_ASKMINMAX"
  1066. @Next "CSC_SHOWHIDE"
  1067. @Prev "CSC_SETUPCLEANUP"
  1068. @Toc "Main"
  1069. MUIM_AskMinMax
  1070. ==============
  1071.    With MUIM_AskMinMax, MUI wants to find out about the minimum,
  1072. maximum and default sizes of your object. These values are needed for
  1073. the correct layout, depending on the type of group that contains your
  1074. object.
  1075.      static ULONG mAskMinMax(
  1076.         struct IClass *cl,
  1077.         Object *obj,
  1078.         struct MUIP_AskMinMax *msg)
  1079.      {
  1080.         /*
  1081.         ** let our superclass first fill in what it thinks about sizes.
  1082.         ** this will e.g. add the size of frame and inner spacing.
  1083.         */
  1084.      
  1085.         DoSuperMethodA(cl,obj,msg);
  1086.      
  1087.         /*
  1088.         ** now add the values specific to our object. note that we
  1089.         ** indeed need to *add* these values, not just set them!
  1090.         */
  1091.      
  1092.         /* x-size depending on objects font */
  1093.         msg->MinMaxInfo->MinWidth  += _font(obj)->tf_XSize * 10;
  1094.         msg->MinMaxInfo->DefWidth  += _font(obj)->tf_XSize * 20;
  1095.         msg->MinMaxInfo->MaxWidth  += MAXMAX; /* unlimited */
  1096.      
  1097.         /* fixed y-size */
  1098.         msg->MinMaxInfo->MinHeight += _font(obj)->tf_YSize;
  1099.         msg->MinMaxInfo->DefHeight += _font(obj)->tf_YSize;
  1100.         msg->MinMaxInfo->MaxHeight += _font(obj)->tf_YSize;
  1101.      
  1102.         return(0);
  1103.      }
  1104. @EndNode
  1105. @Node "CSC_SHOWHIDE" "MUIdev.guide/CSC_SHOWHIDE"
  1106. @Next "CSC_DRAW"
  1107. @Prev "CSC_ASKMINMAX"
  1108. @Toc "Main"
  1109. MUIM_Show & MUIM_Hide
  1110. =====================
  1111.    Once the window is opened, your object will receive a MUIM_Show. If
  1112. you have some window/rastport environment dependant things to do,
  1113. MUIM_Show is the correct place. Intuition like gadgets would for
  1114. example do an AddGadget() here.
  1115.    Note that you should *not* render during MUIM_Show. Usually, MUI
  1116. classes won't need to implement this method.
  1117. @EndNode
  1118. @Node "CSC_DRAW" "MUIdev.guide/CSC_DRAW"
  1119. @Next "CSC_HANDLEINPUT"
  1120. @Prev "CSC_SHOWHIDE"
  1121. @Toc "Main"
  1122. MUIM_Draw
  1123. =========
  1124.    Whenever MUI feels that your object should render itself, it sends
  1125. you a MUIM_Draw method. This happens e.g. when a window is openend for
  1126. the first time, after a window was resized or when a simple refresh
  1127. window needs to be refreshed. In the latter case, MUI already set up a
  1128. clip region to restrict rendering to the necessary areas.
  1129.    Together with MUIM_Draw comes a flag value that indicates which
  1130. parts of the object are to be redrawn. The only interesting bits in
  1131. this flag value are MADF_DRAWOBJECT and MADF_UPDATE. When
  1132. MADF_DRAWOBJECT is set, MUI wants you to do a complete redraw of your
  1133. object. MADF_UPDATE is not used by the MUI system itself but is
  1134. reserved for your private requirements width the MUI_Redraw() function
  1135. call. See the example programs coming with the MUI distribution for
  1136. details.
  1137.    Information about rendering environment (screen, window, rastport,
  1138. pens, etc.) is saved in a structure called MUI_RenderInfo. Every
  1139. objects render info structure is accessable with the muiRenderInfo(obj)
  1140. macro. Parts of this structure are valid between MUIM_Setup and
  1141. MUIM_Cleanup, other parts like window and rastport pointer are valid
  1142. between MUIM_Show and MUIM_Hide. Please have a look at the supplied
  1143. compiler headers for more detailed information about the MUI_RenderInfo
  1144. structure.
  1145.    Note: MUIM_Draw is the only place where you are allowed to render!
  1146. @EndNode
  1147. @Node "CSC_HANDLEINPUT" "MUIdev.guide/CSC_HANDLEINPUT"
  1148. @Next "CSC_SETGET"
  1149. @Prev "CSC_DRAW"
  1150. @Toc "Main"
  1151. MUIM_HandleInput
  1152. ================
  1153.    Compared with BOOPSI, MUI uses a different input handling scheme. Not
  1154. only the "active" object but instead all objects may receive input
  1155. events at the same time. Since sending input events to every object in
  1156. a window would be an incredible overhead, you have to specify what
  1157. messages you really need. MUI offers the library calls
  1158. MUI_RequestIDCMP() and MUI_RejectIDCMP() for this purpose. Whenever an
  1159. arriving input event matches your request, your object will receive a
  1160. MUIM_HandleInput method.
  1161.    You can call MUI_RequestIDCMP() and MUI_RejectIDCMP() at every time.
  1162. Performance affecting critical events like INTUITICKS and MOUSEMOVEs
  1163. should only be requested when you really need them. The "Class3" for
  1164. example requests MOUSEBUTTONS and RAWKEY during MUIM_Setup. The critical
  1165. MOUSEMOVES are only requested when a button was pressed and immediately
  1166. rejected after it was released again.
  1167.    Beneath the struct IntuiMessage, MUIM_HandleInput receives a longword
  1168. describing a MUIKEY as second parameter. If this is set to some other
  1169. value as MUIKEY_NONE, your object is the actve object and the input
  1170. event translated to a user configured keyboard action.
  1171.    MUI will *not* translate input events to your objects coordinates.
  1172. This is up to you. A typical input implementation could look like this:
  1173.      static ULONG mHandleInput(
  1174.         struct IClass *cl,
  1175.         Object *obj,
  1176.         struct MUIP_HandleInput *msg)
  1177.      {
  1178.         #define _between(a,x,b) ((x)>=(a) && (x)<=(b))
  1179.         #define _isinobject(x,y) (_between(_mleft(obj),(x),_mright (obj))
  1180.                                && _between(_mtop(obj) ,(y),_mbottom(obj)))
  1181.      
  1182.         struct Data *data = INST_DATA(cl,obj);
  1183.      
  1184.         if (msg->muikey)
  1185.         {
  1186.            switch (msg->muikey)
  1187.            {
  1188.               case MUIKEY_LEFT :
  1189.                  data->sx=-1;
  1190.                  MUI_Redraw(obj,MADF_DRAWUPDATE);
  1191.                  break;
  1192.               case MUIKEY_RIGHT:
  1193.                  data->sx= 1;
  1194.                  MUI_Redraw(obj,MADF_DRAWUPDATE);
  1195.                  break;
  1196.               case MUIKEY_UP   :
  1197.                  data->sy=-1;
  1198.                  MUI_Redraw(obj,MADF_DRAWUPDATE);
  1199.                  break;
  1200.               case MUIKEY_DOWN :
  1201.                  data->sy= 1;
  1202.                  MUI_Redraw(obj,MADF_DRAWUPDATE);
  1203.                  break;
  1204.            }
  1205.         }
  1206.      
  1207.         if (msg->imsg)
  1208.         {
  1209.            switch (msg->imsg->Class)
  1210.            {
  1211.               case IDCMP_MOUSEBUTTONS:
  1212.               {
  1213.                  if (msg->imsg->Code==SELECTDOWN)
  1214.                  {
  1215.                     if (_isinobject(msg->imsg->MouseX,msg->imsg->MouseY))
  1216.                     {
  1217.                        data->x = msg->imsg->MouseX;
  1218.                        data->y = msg->imsg->MouseY;
  1219.                        MUI_Redraw(obj,MADF_DRAWUPDATE);
  1220.                        MUI_RequestIDCMP(obj,IDCMP_MOUSEMOVE);
  1221.                     }
  1222.                  }
  1223.                  else
  1224.                     MUI_RejectIDCMP(obj,IDCMP_MOUSEMOVE);
  1225.               }
  1226.               break;
  1227.      
  1228.               case IDCMP_MOUSEMOVE:
  1229.               {
  1230.                  if (_isinobject(msg->imsg->MouseX,msg->imsg->MouseY))
  1231.                  {
  1232.                     data->x = msg->imsg->MouseX;
  1233.                     data->y = msg->imsg->MouseY;
  1234.                     MUI_Redraw(obj,MADF_DRAWUPDATE);
  1235.                  }
  1236.               }
  1237.               break;
  1238.            }
  1239.         }
  1240.      
  1241.         /* passing MUIM_HandleInput to the super class is only necessary
  1242.            if you rely on area class input handling (MUIA_InputMode). */
  1243.      
  1244.         return(0);
  1245.      }
  1246. @EndNode
  1247. @Node "CSC_SETGET" "MUIdev.guide/CSC_SETGET"
  1248. @Next "CSC_DISTRIBUTE"
  1249. @Prev "CSC_HANDLEINPUT"
  1250. @Toc "Main"
  1251. OM_SETGET
  1252. =========
  1253.    Implementing OM_SET and OM_GET is similar to oldstyle BOOPSI gadgets.
  1254. The only important thing to know about is that you should *not* render
  1255. in a OM_SET (e.g. as a result of an attribute change). Instead, call
  1256. MUI_Redraw() with a MADF_DRAWOBJECT or a MADF_UPDATE flag, MUI will
  1257. then call your objects Draw method.
  1258.      static ULONG mSet(struct IClass *cl,Object *obj,Msg msg)
  1259.      {
  1260.         struct MyData *data = INST_DATA(cl,obj);
  1261.         struct TagItem *tags,*tag;
  1262.      
  1263.         for (tags=((struct opSet *)msg)->ops_AttrList;tag=NextTagItem(&tags);)
  1264.         {
  1265.            switch (tag->ti_Tag)
  1266.            {
  1267.               case MYATTR_PEN:
  1268.                  data->pen = tag->ti_Data;         /* set the new value */
  1269.                  MUI_Redraw(obj,MADF_DRAWOBJECT);  /* complete redraw */
  1270.                  break;
  1271.      
  1272.               case MYATTR_LEVEL:
  1273.                  data->level = tag->ti_Data;       /* set the new value */
  1274.                  MUI_Redraw(obj,MADF_DRAWUPDATE);  /* only update ourselves */
  1275.                  break;
  1276.            }
  1277.         }
  1278.      
  1279.         return(DoSuperMethodA(cl,obj,msg));
  1280.      }
  1281. @EndNode
  1282. @Node "CSC_DISTRIBUTE" "MUIdev.guide/CSC_DISTRIBUTE"
  1283. @Next "CSC_LIBRARIES"
  1284. @Prev "CSC_SETGET"
  1285. @Toc "Main"
  1286. CSC_DISTRIBUTE
  1287. ==============
  1288.    Usually, you will use custom classes only for your own applications.
  1289. In this case, you won't need to care about the tag values used for your
  1290. private attributes and methods. The only thing you should consider is
  1291. that all standard MUI classes use values betwenn 0x80420000 and
  1292. 0x8042ffff for their tags. To avoid conflicts, all you have to do is
  1293. make your tags start with anything but 0x8042.
  1294.    However, if you start distributing your classes to make other people
  1295. benefit from your work and help them in writing better MUI applications,
  1296. things get a bit more complicated. MUI will get confused if two or more
  1297. classes start using some equal tag values. To avoid these problems, I
  1298. suggest to use your MUI serial number together with the TAG_USER bit as
  1299. upper word for your tag items. Thus, if your serial number is e.g. 123,
  1300. all your tag items would look like
  1301.      #define MUIA_Myclass_Foobar     (TAG_USER | (123<<16) | 0x0000)
  1302.      #define MUIA_Myclass_Barfoo     (TAG_USER | (123<<16) | 0x0001)
  1303.      #define MUIA_Myclass_Deadbeaf   (TAG_USER | (123<<16) | 0x0002)
  1304.      #define MUIM_Myclass_Doit       (TAG_USER | (123<<16) | 0x0003)
  1305.      #define MUIM_Myclass_Doit2      (TAG_USER | (123<<16) | 0x0004)
  1306.      
  1307.      #define MUIA_Myotherclass_Attr1 (TAG_USER | (123<<16) | 0x0010)
  1308.      #define MUIA_Myotherclass_Attr2 (TAG_USER | (123<<16) | 0x0011)
  1309.      #define MUIA_Myotherclass_Attr3 (TAG_USER | (123<<16) | 0x0012)
  1310.      #define MUIA_Myotherclass_Attr4 (TAG_USER | (123<<16) | 0x0013)
  1311.    If you aren't registered and don't yet have a serial number, no
  1312. problem... just register *now*! ;-)
  1313. @EndNode
  1314. @Node "CSC_LIBRARIES" "MUIdev.guide/CSC_LIBRARIES"
  1315. @Next "STG_OVERVIEW"
  1316. @Prev "CSC_DISTRIBUTE"
  1317. @Toc "Main"
  1318. CSC_LIBRARIES
  1319. =============
  1320.    From version 2.0 on, MUI supports the creation of external custom
  1321. class libraries. See the autodocs of MUI_CreateCustomClass() and
  1322. MUI_DeleteCustomClass() and the supplied demo classes for details.
  1323. @EndNode
  1324. @Node "STG_OVERVIEW" "MUIdev.guide/STG_OVERVIEW"
  1325. @Prev "CSC_LIBRARIES"
  1326. @Toc "Main"
  1327. Style Guide
  1328. ***********
  1329. Overview
  1330. ========
  1331.    Note: These topics aren't discussed here just for fun. You will
  1332. annoy lots of users if you don't pay attention to them!
  1333.    - File Requester
  1334.      Even if MUI features a file list and a volume list object and
  1335.      makes building a private file requester very easy, you should
  1336.      always provide a possibility to pop up a standard asl requester
  1337.      for this purpose. Just add a little popup button right beneath
  1338.      your file string gadget and everything will be fine. MUI offers a
  1339.      file-popup object exactly for this purpose.  Note well: Many users
  1340.      (including myself) move programs with non-standard file requesters
  1341.      into the trashcan immediately.
  1342.    - Window Size
  1343.      With MUI, it's very easy to have lots of gadgets within a single
  1344.      window.  Since you as a programmer usually have a more powerful
  1345.      system with higher graphic resolutions as most of your users,
  1346.      windows tend to become too big. You should always make sure that
  1347.      everything you design fits on a standard 640x256 screen with a
  1348.      topaz/8 font. Otherwise, MUI will try to use very small fonts or
  1349.      virtual groups to make your window fit, making your application
  1350.      look and feel bad.
  1351.    - Keyboard Control
  1352.      Even if you're a "mouse-only" user, add keyboard cycle chains and
  1353.      gadget shortcuts to your application. It's very few work for you
  1354.      and helps lots of users.
  1355.    - Background
  1356.      MUI allows the user to adjust lots of different backgrounds for
  1357.      objects.  Even if you don't use this feature, you should always
  1358.      test your program with a fancy background pattern configuration
  1359.      and check whether all your buttons really have button backgrounds,
  1360.      all your framed texts really have text backgrounds, etc.
  1361.    - and last...
  1362.      Don't forget the traditional Amiga style guide!
  1363. @EndNode
  1364.