Vibrant User Interface Tools Introduction VIBRANT is a high-level, multi-platform user interface development library designed and implemented by Jonathan Kans at NCBI. Due to popular demand it is now being distributed as part of the NCBI Software Development Kit, but should not be considered a "supported product" the way tools more closely tied to the NCBI databases are. Vibrant is designed to act as an intermediary between an application program and the underlying windowing system toolkit. The philosophy behind Vibrant is that everything in the published user interface guidelines for the various windowing systems (i.e., the generic behavior of windows, menus, buttons, etc., to which all programs should conform) is taken care of automatically, without needing attention from the programmer. The programmer can concentrate on the specific behavior of the application in response to manipulation of control objects without worrying about unexpected and undesired interaction between objects. Vibrant frees the programmer from maintaining resource files, explicitly specifying the positions of objects, and writing an event loop. A program written with Vibrant calls functions that create windows, menus, and the various graphical control objects that reside in them. Typically, the first parameter to the function that creates a control is the parent object for that control. The programmer may also write a "callback" function for a given object. The name of the callback is typically passed as the last parameter to the object creation procedure. When the user manipulates the object (and thus changes its "value"), the callback function is automatically executed. In addition to such standard interface objects as windows, menus, buttons, lists, and text boxes, Vibrant provides a universal drawing object called a "slate." A slate can contain one or more "panels." Each panel can have instance-specific callbacks for click, drag, hold, release, and draw functions. By using Vibrant's portable drawing functions in panels, an application can present arbitrarily complex drawings in a completely portable manner. Modern graphical windowing interfaces have been largely responsible for the recent popularity of personal computers and workstations among the general public and in the business community. In contrast to traditional command- line- or prompt-driven programs, applications that run on a contemporary personal computer allow the user to decide the order of execution of computational tasks. The commands that are available under a given application are frequently displayed in a visible menu, so that the user does not need to remember esoteric acronyms or abbreviations or special function key codes. Graphical objects that represent relevant physical or mathematical entities appear in windows on the display screen, and these objects can respond to the movements of a pointing device (a "mouse") in a manner analogous to physical manipulation of material objects in the real world. The ease-of-use of these interfaces, in which learning a few skills allows the user to control many programs in a consistent manner, is especially important in molecular biology, where a given researcher may need to use many different programs on an occasional basis. While windowing interfaces have made the user's job much easier, they have made the programmer's job much more difficult. Because the user is placed in charge of the work flow, the program must continually check to see what the user is doing, and must respond appropriately. Traditional programming for these interfaces requires the application developer to keep track of many interface implementation details. The programmer needs to place each object at a specific position, must draw each object correctly upon request, and must make sure that objects in general do not interfere with each other while allowing certain desired interactions to occur. This means that the cycle time for program development is long, and that even simple changes can require a lot of effort. In addition, programs written for one operating environment need to be extensively rewritten to run on another platform. Finally, the programmer must make the effort to become an expert in the use of the interface toolkits. VIBRANT (Virtual Interface for Biological Research ANd Technology) is a portable user interface development library that has been written to allow new algorithms created by NCBI scientists to be quickly implemented and deployed to laboratory researchers as user-friendly computer programs. As part of the NCBI Software Development Kit, it is written in the C language, and can be built on a variety of computers with their most popular compilers. Programs written using the Vibrant interface will run on the graphically-oriented personal computers and workstations that are commonly found in many molecular biology laboratories. In addition, an interface written with Vibrant can be created quickly and changed easily. These features are particularly important in computer tools for molecular biology, since new problems suitable for computer solution and better algorithms for older problems appear rapidly as our understanding of the science progresses. Vibrant is distinct from the native windowing systems or portable development toolkits in that it does not support the infinite variety of interface objects that could be created using those packages. Instead, control objects are created by function call from a small repertoire of standard objects that are in common use. Because of this compromise, Vibrant can internally handle all of the details necessary to fully implement its graphical control objects. For example, creating a push button, and completely specifying its appearance and behavior, is done with the following function call and parameters: button = PushButton (parent, title, action); The benefit of using Vibrant for building a program is that you can concentrate on writing code for the application functions, and need not worry about low-level interface messages or events. A choice group in a sub menu could be replaced by a set of radio buttons or a scrolling list simply by calling different functions to create the objects. With other packages such a program change would entail completely rewriting the code used to create the objects and detect and respond to user actions. The limitation in using Vibrant is that you must be satisfied with "standard" behavior for all of your graphical control objects. Some of the fancier interface techniques available only on one platform would generally not be available under Vibrant. Since Vibrant is a functional interface, the programmer is no longer forced to pay attention to many low-level implementation details of visual interface objects (e.g., what radio button is set), and can simply be concerned with the values of the parameters these objects represent (e.g., what choice was made). From the user's point of view, objects appear to have a logical, hierarchical relationship to one another (e.g., radio buttons always "belong" to a particular group in a particular window), and Vibrant takes advantage of this functional hierarchy by having the programmer explicitly specify the relationships to be created. Objects are created with a single procedure call, and the call and its parameters are sufficient to make an object exist and define its generic behavior. Vibrant also automatically positions and sizes visual objects. Adding new objects to a program's interface imposes no extra burden in terms of code complexity. This means that the cycle time for program development is short, and it encourages a programmer to make even major changes to the look and feel of a program in order to make it as ergonomic and useful as possible, since such changes are substantially less difficult to implement using Vibrant. A program written with Vibrant is designed around functional subunits that can be called upon user request. The programmer attaches such a "callback" function to a particular interface object, usually when the object is first created, and the callback is executed automatically when the user performs some appropriate action. Programs are thus divided into the procedure calls to create objects and the callback functions to give objects their specific behaviors. The callback structure of the interface is especially suited to user-driven programs. The callback functions in a program may also need to change the appearance and responsiveness of various interface objects (or create new ones). Several high-level procedures are available to manipulate objects, and include such self-explanatory functions as Show, Hide, Enable, Disable, Reset, SetTitle, and GetValue. Because of the object-oriented internal design of the interface, these procedures can be applied to any object, including text boxes, push buttons, and menu choices. Since Vibrant is a portable interface, the programmer no longer needs to master the complicated underlying toolkits for each interface. Vibrant acts as a bridge between the high-level concepts of parameters (e.g., strings, numbers, choices, toggles) and the toolbox commands for the appropriate visual object on a particular machine. Portable memory, string and file manipulation procedures are provided by the NCBI Software Development Kit core library. Application programs using Vibrant currently run unchanged on the Macintosh, under Microsoft Windows on the PC, and on UNIX and VMS machines under OSF/Motif. In addition to the standard interface objects (windows, menus, buttons, lists, and text boxes), Vibrant also supplies a universal drawing environment called a "slate." A slate allows an application to present arbitrarily complex drawings in a completely portable manner. Messages or events that are treated by other objects at the generic level (including drawing requests and mouse clicks) are converted by slates to application callback function calls in a platform-independent manner. A slate can have one or more panels, and each panel can have instance-specific callbacks for click, drag, hold, release, and draw functions. (The simplest version of a slate merges a slate and a panel in one object instance.) Vibrant provides a variety of drawing procedures that can be used inside slates regardless of the machine that is actually being used. A panel can be used to create a new object that solves a general problem (such as display of tabular text, or display of bitmap icons). Since the slate allows multiple panels, you can combine these general building blocks (even superimpose them) to create a complex slate from simpler components. This can be much more efficient than having to modify (and thus understand) a copy of the code for each component in order to make a custom object. Programming Example The simple application in this section illustrates programming techniques for Vibrant. Commentary on the use of Vibrant is interspersed with the code. For the purposes of illustration, the callbacks, which are referenced in the setup portion, are declared at the end of the program. Vibrant is built on top of the NCBI Software Development Kit core library. The main application procedure in a Vibrant program is called Main. Vibrant itself contains the C main function, which initializes the windowing system before calling the application Main. The Main procedure should create the object hierarchy to be used for the program's interface, and should assign callback functions to appropriate objects. Once Vibrant objects are created they persist until explicitly removed or until program termination. A call to ProcessEvents should be at the end of Main, just before any cleanup and the return statement. ProcessEvents will handle all events or messages from the underlying windowing system, and will trigger the execution of application callback functions when appropriate. One callback function should call QuitProgram to allow the user to terminate the program. The remaining callbacks should respond by performing computational services that the user has requested. Object Specification The only header file that needs to be included is . This will automatically include , which in turn includes the header specific for the current platform: #include Interface object data types are variants of Handle types. Although these may be indirect pointers on the personal computers, they should only be used as parameters to Vibrant procedures, and should not be used with * or -> notation. The last letter of each Vibrant object type is capitalized for easy identification. The names of many Vibrant object types are self explanatory. WindoW objects have no parents. GrouP objects go inside windows or other groups. Their main purpose is to automatically position their child objects, but they also allow a set of radio buttons to be referenced by an integer value (as are LisT, ChoicE and PopuP sets). ButtoN, IcoN, LisT, PopuP, PrompT, RepeaT, SlatE, SwitcH, and TexT objects can go inside of groups or windows. MenU objects belong to particular windows (or NULL on the Macintosh, in which case they are placed on the "desktop window"), and can contain IteM and ChoicE objects (as well as sub menus). There are also portable types for FonT, PoinT, RecT, and RegioN: static ButtoN accept; static GrouP category; static PaneL drawing; static GrouP features; static TexT species; static ButtoN check [4]; static PoinT lastPt; Functions that are referenced before they are declared in a program must be prototyped by copying the function declaration and adding a semicolon to the end of the line. Vibrant uses the ANSI style of C, in which the parameter list includes the type of each parameter: static void QuitProc (IteM i); static void EnableProc (GraphiC g); static void DrawProc (PaneL p); static void ClickProc (PaneL p, PoinT pt); static void DragProc (PaneL p, PoinT pt); static void AcceptProc (ButtoN b); The Main procedure returns an Int2, which is defined in as a 16- bit signed integer: extern Int2 Main (void) { GrouP g; IteM i; MenU m; PrompT p; WindoW w; Menus are installed on the desktop (on the Macintosh) or inside a given window (under Windows or Motif) by determining whether the platform symbols WIN_MAC, WIN_MSWIN or WIN_MOTIF are defined. The first parameter to any object creation procedure (except for a window) is the parent object. Thus, the File menu is created first (with the NULL parent specifying the desktop window in the case of the Macintosh), and its child items are created later. The CommandItem procedure has its parent menu as its first parameter. Note that CommandItem objects take an item action procedure callback (typedef void (*ItmActnProc) (IteM)) as an explicit parameter. An action procedure is used to notify the program when the value of an object has changed, i.e., when the user has chosen the command item from the menu: #ifdef WIN_MAC m = AppleMenu (NULL); DeskAccGroup (m); m = PulldownMenu (NULL, "File"); i = CommandItem (m, "Quit/Q", QuitProc); #endif For the FixedWindow procedure, the "-50, -33" for left and top means that the window will be centered horizontally on the screen and one third of the way down the screen. The "-10, -10" for width and height mean that 10 pixels will separate objects on the window. The string parameter is the window title, and the NULL is the close callback. Whereas a DocumentWindow can be resized and dragged, a FixedWindow can only be dragged: w = FixedWindow (-50, -33, -10, -10, "Observed Organisms", NULL); For non-Macintosh platforms, the menus go in a particular window, not on the desktop: #ifndef WIN_MAC m = PulldownMenu (w, "File"); i = CommandItem (m, "Quit/Q", QuitProc); #endif A StaticPrompt is a label that takes parameters for the parent group or window, text of the label, pixel width (0 will calculate the width of the string), pixel height (prompts are centered vertically if the height is greater than the line height), font, and justification ('l', 'c', or 'r' for left, centered, or right): p = StaticPrompt (w, "Species", 0, dialogTextHeight, systemFont, 'l'); The Advance function forces the next object to appear at the top of the next available column on the window. (A hidden group (discussed below) could also be used to arrange objects.) Objects are otherwise placed by default below the previous object: Advance (w); A DialogText takes as parameters its parent group or window, the initial value of the edit text, the minimum number of character spaces to reserve, and a callback to be called whenever the text value of the edit box changes. (Objects that take "character space" parameters also usually add a border of 8 pixels. These functions will likely be changed to take pixel parameters, perhaps without automatically including additional border pixels.) Select makes species the active (highlighted) text object: species = DialogText (w, "", 15, (TxtActnProc) EnableProc); Select (species); Advance (w); The DefaultButton triggers the callback when it is pressed, or when the Return key is hit, but Disable prevents this action from occurring for the present by graying out the button title: accept = DefaultButton (w, "Accept", AcceptProc); Disable (accept); The Break function forces the next object to appear at the left on the next available row of the window, below all previously placed objects, and resets the new "top" used by Advance: Break (w); A hidden group is created in order to nicely position the category and features groups and the drawing panel. The "0, 3" means that objects in the hidden group should be laid out vertically (Y axis comes after X axis in these layout specifications), and that after every third object the next position should advance to the top of the next available column. SetGroupMargins sets the horizontal and vertical pixel distances between the group boundary and its internal objects, and SetGroupSpacing sets the pixel distances between objects within a group: g = HiddenGroup (w, 0, 3, NULL); SetGroupMargins (g, 3, 3); SetGroupSpacing (g, 3, 2); The RadioButton choices go into a group. The radio buttons must be inside of a group for them to behave as a mutually exclusive set of choices, and the current choice is an integer property of the group. The callback for the first group is the same as that for the dialog text box. The initial value of the group is 0, meaning that no radio buttons are set. The "5, 0" means that objects are laid out horizontally (X axis), and up to five objects may be placed on each line. The RadioButton function does return a handle to the button, but only so that individual buttons in a group can be disabled or hidden. The GetValue function should be used to determine which group member is set, rather than calling GetStatus for each button: category = NormalGroup (g, 5, 0, "Category", (GrpActnProc) EnableProc); RadioButton (category, "Amphibian"); RadioButton (category, "Bird"); RadioButton (category, "Fish"); RadioButton (category, "Fungus"); RadioButton (category, "Lichen"); RadioButton (category, "Mammal"); RadioButton (category, "Mold"); RadioButton (category, "Plant"); RadioButton (category, "Reptile"); The check boxes are inside of a group merely so that they will line up nicely by virtue of the group's automatic positioning of its children, and do not behave in a mutually exclusive manner. The check boxes are initially off. The SetStatus function can change the settings of check boxes: features = NormalGroup (g, 4, 0, "Features", NULL); check [0] = CheckBox (features, "Camouflaged", NULL); check [1] = CheckBox (features, "Motile", NULL); check [2] = CheckBox (features, "Nocturnal", NULL); check [3] = CheckBox (features, "Poisonous", NULL); A simple panel is created to allow the user to sketch the organism, although this information will not be saved to a file. Since the panel is in the hidden group, its width will be adjusted to be the same as that of its sibling objects (i.e., the category and features groups, overriding the width specification). The simple panel contains a slate and a single panel in one object instance. The SimplePanel callback parameter specifies the draw function for that panel. Vibrant will call this application function whenever the drawing in the panel needs to be refreshed. The SetPanelClick function assigns callbacks for responding to click, drag, hold, and release mouse actions: drawing = SimplePanel (g, 100, 100, DrawProc); SetPanelClick (drawing, ClickProc, DragProc, NULL, NULL); Finally, Main calls Show to make the window visible (and size it to its child objects if the window width and height parameters were negative), and calls ProcessEvents to give control to the user: Show (w); ProcessEvents (); return 0; } Callback Functions The setup portion of this sample program referenced six callback procedures, QuitProc, EnableProc, AcceptProc, DrawProc, ClickProc, and DragProc, and then called ProcessEvents as its final act. The remainder of the life span of the program consists of these callbacks automatically being executed in response to particular actions by the user: The QuitProc callback calls the Vibrant QuitProgram function, which terminates Vibrant execution and exits the ProcessEvents loop to return to the program's Main function. After Main returns, Vibrant will clean up its memory structures before returning to the operating system: static void QuitProc (IteM i) { QuitProgram (); } The EnableProc (used as the action procedure of the species text and the category group) enables the accept button only if the species text is not blank and if a category has been chosen. Since the procedure can be called with either a GrouP or a TexT parameter, the parameter is declared as a GraphiC, and the EnableProc name was cast to a GrpActnProc or a TxtActnProc when referenced: static void EnableProc (GraphiC g) { Char str [32]; GetTitle (species, str, sizeof (str)); if (StringLen (str) == 0 || GetValue (category) == 0) { Disable (accept); } else { Enable (accept); } } The panel draw callback is called whenever the drawing in the panel needs to be refreshed. The DrawProc example callback frames a border around the drawing panel and draws a text label. Since the draw callback may be triggered many times, the text label is drawn with DrawString rather than by creating a StaticPrompt object. Unless a new font is selected, DrawString will use the pre-defined systemFont. ObjectRect returns the bounding rectangle for any Vibrant object. The current implementation does not save and refresh the drawing: static void DrawProc (PaneL p) { RecT r; ObjectRect (p, &r); if (RectInRgn (&r, updateRgn)) { r.top += 6; FrameRect (&r); r.top -= 6; r.left += 4; r.right = r.left + StringWidth ("Picture") + 2; r.bottom = r.top + stdLineHeight; DrawString (&r, "Picture", 'l', FALSE); } } The ClickProc responds to double clicking on the panel by using EraseRect to erase the current drawing. The coordinates for the mouse position (pt parameter) is always relative to the parent window, with (0, 0) at the upper left of the window. ObjectRect will return the rectangle of the panel in the same window-based coordinate system: static void ClickProc (PaneL p, PoinT pt) { RecT r; if (dblClick) { ObjectRect (p, &r); r.top += stdLineHeight; InsetRect (&r, 2, 2); EraseRect (&r); } lastPt = pt; } The DragProc tracks the mouse on the panel, allowing the user to sketch an organism. Checking for PtInRect is necessary on some platforms that do not automatically clip to restrict drawing to be within a given panel (all platforms now perform this clipping): static void DragProc (PaneL p, PoinT pt) { RecT r; ObjectRect (p, &r); r.top += stdLineHeight; InsetRect (&r, 4, 4); if (PtInRect (lastPt, &r) && PtInRect (pt, &r)) { DrawLine (lastPt, pt); } lastPt = pt; } The AcceptProc callback, triggered by pressing the accept button once it has been enabled, opens a file using the core library FileOpen function: static void AcceptProc (ButtoN b) { FILE *f; Int2 i; RecT r; Char str [32]; Int2 val; f = FileOpen ("Organism", "a"); if (f != NULL) { It then prints the species and category to the file. (The Motif version of Vibrant is not able to get the titles of buttons, list elements, or menu items.) Note that for a group, the value is 0 if no choice has been made, and is 1 through n if a choice item is currently selected: GetTitle (species, str, sizeof (str)); StringNCat (str, "\t", sizeof (str) - 1); WriteString (f, str); val = GetValue (category); GetItemTitle (category, val, str, sizeof (str)); WriteString (f, str);); Finally, it prints the chosen features to the file, and closes the file: for (i = 0; i < CountItems (features); i++) { if (GetStatus (check [i])) { WriteChar (f, '\t'); GetTitle (check [i], str, sizeof (str)); WriteString (f, str); } } WriteLn (f); FileClose (f); } To reset for the next entry, it disables the accept button, clears and resets the species text, category group, and features check boxes, erases the drawing, and sets the input focus to the species text object: Disable (accept); SetValue (category, 0); for (i = 0; i < CountItems (features); i++) { SetStatus (check [i], FALSE); } Select (drawing); ObjectRect (drawing, &r); r.top += stdLineHeight; InsetRect (&r, 2, 2); EraseRect (&r); SetTitle (species, ""); Select (species); } The actual dialog window, with the species, category and feature objects filled in, appears below: Reference This section presents the various Vibrant graphic interface functions in some detail. Although there are quite a few procedures, a number of them are variants of one another. For example, all of the window creation functions are similar, differing only in the kinds of window controls generated (drag bars, grow regions, close boxes) and in their behavior (normal, modal dialog, or floating palette windows). Buttons also differ in their behavior, with push buttons used to trigger commands, check boxes used as Boolean toggles, and radio buttons used to select from a mutually exclusive set of choices. The visibility and functionality modifying functions (e.g., Show, Hide, Enable, Disable, Select) can be applied to any Vibrant graphic object. Some procedures are menu item equivalents of similar button procedures. For example, a PushButton and CommandItem are equivalent, as are a CheckBox and a StatusItem. RadioButtons in a group are equivalent to ChoiceItems in a ChoiceGroup. The "value" of a given object is manipulated by certain functions. SetValue and GetValue use an integer value, and are appropriate for radio button groups, single choice lists, menu choice groups, and popup menu groups. (The value 0 means no choice is selected, and the choices are numbered 1 through n.) SetStatus and GetStatus use a Boolean value, and are appropriate for check boxes and status items. SetItemStatus and GetItemStatus are used for the item values of multiple choice lists, which do not have individual Vibrant object handles. SetTitle and GetTitle are used to manipulate the titles of windows, buttons, prompts, etc., and SetItemTitle and GetItemTitle are used to access list item titles. (Changing or obtaining the title of an item is not always possible for certain objects on certain platforms.) In situations where a user is expected to make a choice among a small number of items, it is frequently appropriate either to implement the choice as a group of radio buttons, as a menu choice group, or as a popup menu group. If the number of choices can be quite large, or if the names of the actual choices can change each time the program is run, it may be wiser to implement the choice as a single choice list. Certain design decisions will seem unnecessarily complex to people who are familiar with only one of the underlying windowing interfaces. A case in point is the description of fonts. On the Macintosh, selection of a font name, size, and style are independent operations. Under Windows, a different font descriptor must be created for each combination of name, size, and style. The portable solution in Vibrant was to create a FonT object that specifies one unique combination of name, size, and style, and to change fonts on each machine by calling SelectFont with the desired font object. In addition, Windows and Motif do not perform garbage collection among allocated fonts, whereas Vibrant will do so. Other design decisions will seem impossibly simple. For example, by assigning one device context to each parent window in Windows, by having child windows use the parent's device context, and by keeping track of the "current" window and device context in static variables, the device context becomes the functional equivalent of the Macintosh port. This allows the creation of the slate, the universal drawing environment, on otherwise very different graphics systems. Vibrant's drawing functions do not need the current window as an explicit parameter, even though the underlying Windows toolbox calls do need to be told which device context to use. Under Motif, each slate is a separate DrawingArea, and the current Xlib-level Window is also a hidden context variable. Vibrant will perform garbage collection on Windows pens and brushes. Be sure to read the appropriate declarations in , or to get a complete list of types, variables, functions and parameters when you are actually working with a particular section of the Vibrant library. Also, you should become familiar with the types defined in the header, such as Int2, CharPtr, VoidPtr, and NULL. Object Data Types All Vibrant objects are referenced, as far as the compiler is concerned, by pointers to hidden data structures. (In fact, on both the Macintosh and Microsoft Windows, these are in reality handles, which are pointers to pointers to data ("near" pointers to pointers on Windows). When accessing the data structures, Vibrant internally "locks" the handles to get a pointer to the data and "unlocks" the handles when done.) The base type is GraphiC, whose definition appears below: typedef struct Nlm_graphic { Nlm_VoidPtr dummy; } HNDL Nlm_GraphiC; The standard object types are BaR, ButtoN, ChoicE, GrouP, IcoN, IteM, LisT, MenU, PaneL, PopuP, PrompT, RepeaT, SlatE, SwitcH, TexT and WindoW. There are several important points to note. First, in order to avoid conflicts with type or function names in the various windowing systems, all NCBI core library and Vibrant symbols are prefixed with "Nlm_". For application programs, includes defines that add the prefix to every common symbol prior to compilation: #define GraphiC Nlm_GraphiC Second, note that for Vibrant objects, the last letter of each data type is capitalized. This is the evolutionary remnant of a less general attempt at collision avoidance that was ultimately superseded by the Nlm_ prefix. However, it does allow Vibrant objects to be identified at a glance. Third, the HNDL symbol indicates that the object is a handle. This symbol is defined in the file specific for each platform. On the Macintosh it is simply "*", the general pointer definition. Under Windows it is "_near *", indicating that it is a 16 bit pointer, which is size compatible with the 16 bit int currently used for a handle. (The related symbol, PNTR, defines a 32 bit far pointer, which is returned by the core library MemNew memory allocation function. Under Win32 and Windows NT, both pointers and handles are 32 bits, but PNTR and HNDL should still be used at this time.) Although it is not safe practice to access the data to which the handle points by double indirection (or even single indirection), the definition of Vibrant object handles as (near) pointers to different dummy structures allows the compiler to distinguish, for example, a ButtoN from a ChoicE. This means that the compiler can prevent an attempt to place a ButtoN in a MenU, but will allow a ChoicE group to be placed in a MenU. Fourth, note that WindoW and GrouP are (handle-sized) pointers to the same dummy structure: typedef struct Nlm_window { Nlm_VoidPtr dummy; } HNDL Nlm_GrouP, HNDL Nlm_WindoW; This allows ButtoN, GrouP, IcoN, LisT, PopuP, PrompT, RepeaT, SlatE, SwitcH and TexT objects to be placed either at the main level of a window, or in a group within a window (or within another group), without having the compiler complain. (A group has two major functions. One is that it is the parent object for a group of radio buttons, and gives the set of buttons mutual exclusivity. The other is that it automatically positions its child objects. The application rarely has to worry about object layout.) A WindoW is a top level object, and has no parent. A MenU is placed inside a window (Vibrant considers the Macintosh desktop to be a window). IteM and ChoicE objects can only go inside menus. All other objects can go inside a window or inside a group within a window. There are also other definitions for types that are not Vibrant graphic interface objects, but which may be used as parameters when creating such objects or when drawing using slates and panels. These include FonT, PoinT, RecT and RegioN, which are needed because the equivalent underlying concepts are incompatible between different windowing systems. FonT is defined as a handle to another dummy structure, and the other definitions are shown below: typedef struct Nlm_point { Nlm_Int2 x; Nlm_Int2 y; } Nlm_PoinT, PNTR Nlm_PointPtr; typedef struct Nlm_rect { Nlm_Int2 left; Nlm_Int2 top; Nlm_Int2 right; Nlm_Int2 bottom; } Nlm_RecT, PNTR Nlm_RectPtr; typedef Nlm_Handle Nlm_RegioN; The remainder of this document will omit the Nlm_ prefix. Function definitions will also omit the PROTO macro, which is used to allow compatibility with compilers that cannot accept parameter lists in prototypes. Callback Types The callback functions for various objects are strictly typed. The most used class, the action proc, has the handle to the calling object as the only parameter. (There are separate callback function type definitions for each kind of object, since some compilers check types of function parameters, so only the "generic" typedefs are shown.) The click proc is used by panels for the click, drag, hold and release callbacks, and includes the x and y coordinates of the mouse at the time of the call: typedef void (*VoidProc) (void); typedef void (*KeyProc) (Char); typedef void (*ActnProc) (GraphiC); typedef void (*ClckProc) (GraphiC, PoinT); typedef void (*ScrlProc) (BaR, GraphiC, Int2, Int2); typedef void (*ChngProc) (GraphiC, Int2, Int2); The button action proc and panel click proc illustrate the actual specific callback types: typedef void (*BtnActnProc) (ButtoN); typedef void (*PnlClckProc) (PaneL, PoinT); General Global Variables There are a number of useful global variables that are available in Vibrant. screenRect holds the rectangular coordinates of the computer screen. systemFont and programFont are predefined font variables. stdAscent, stdDescent, stdLeading, stdFontHeight, stdLineHeight, and stdCharWidth are constants determined by applying the equivalent (capitalized) function to systemFont. dblClick and shftKey may be set during list and panel clicks. updateRgn and updateRect are set in response to panel draw (expose) events. Window Objects Windows are the top level objects in Vibrant. Document windows may be dragged and resized by the user. Fixed and Round windows may be dragged but not resized. Modal windows force the user to enter immediately needed information. The first two parameters of all of the window creation functions determine the x and y position of the window on the screen. If these parameter are negative, then the absolute value is used as the percentage of desktop space to be at the left of the window or above it. The next two parameters specify the width and height of the window. If these are negative, then the window form fits around its child objects when it is first shown, and the absolute value is the number of pixels to use as the border around and the spacing between the children. Remaining possible parameters include the window title, a callback for responding to clicking in the close box, and a callback for responding to resizing of the window. The full prototype for the FixedWindow function is shown below: extern WindoW FixedWindow (Int2 left, Int2 top, Int2 width, Int2 height CharPtr title, WndActnProc close); The remaining sections will omit the types of parameters except for the parent object. The full prototype declarations may be found in the header. Other windows are: WindoW DocumentWindow (left, top, width, height, title, close, resize); WindoW FixedWindow (left, top, width, height, title, close); WindoW FrozenWindow (left, top, width, height, title, close); WindoW RoundWindow (left, top, width, height, title, close); WindoW AlertWindow (left, top, width, height, close); WindoW ModalWindow (left, top, width, height, close); WindoW FloatingWindow (left, top, width, height, close); WindoW ShadowWindow (left, top, width, height, close); WindoW PlainWindow (left, top, width, height, close); On some platforms a window becomes "active" and available for manipulation when it is moved to the front of the other windows. The SetActivate procedure assigns to a window a callback that is triggered when the window is activated, though this parameter may be added to the window creation functions: void SetActivate (WindoW w, act); Context Functions Vibrant remembers the current window context of an application. The following functions can be used to get and set the current context. On Motif, setting the context for a panel in addition requires calling Select for that panel: WindoW CurrentWindow (void); void UseWindow (WindoW w); WindoW ParentWindow (Handle obj); WindoW SavePort (Handle obj); void RestorePort (WindoW w); Grouping Objects Groups are used to control the positioning of objects within a window. Groups can be placed in windows, or can be nested inside other groups. In addition to positioning most classes of Vibrant interface objects, groups are used to reference a set of radio buttons and implement mutual exclusivity. The width and height parameters determine the layout of child objects. If the width parameter is positive and the height parameter is 0, objects are laid out horizontally, and the position Breaks to the next row after each set of n objects. If the height parameter is positive, objects are laid out vertically, and the position Advances to the next column after n objects. If width or height are negative, objects are laid out as above, but their borders are not aligned with one another. If both width and height are 0, successive objects are placed at the same position. In this case, you would typically hide all but one of the superimposed child objects at any given time, or you could call Advance or Break between objects, which would just give up the automatic alignment of items that the group would otherwise provide: GrouP NormalGroup (GrouP prnt, width, height, title, actn); GrouP HiddenGroup (GrouP prnt, width, height, actn); SetGroupMargins and SetGroupSpacing specify the borders between a group and its objects and the spacing between internal objects. Measurements are in pixels: void SetGroupMargins (GrouP g, xMargin, yMargin); void SetGroupSpacing (GrouP g, xSpacing, ySpacing); Button Objects Buttons are created by PushButton, DefaultButton, CheckBox, or RadioButton. A default button is a push button with a visible border that also responds to the return key. The check box implements a Boolean toggle. Changing the radio button selection turns off the previously-selected radio button and triggers the action callback of the parent group: ButtoN PushButton (GrouP prnt, title, actn); ButtoN DefaultButton (GrouP prnt, title, actn); ButtoN CheckBox (GrouP prnt, title, actn); ButtoN RadioButton (GrouP prnt, title); The CheckBox setting is manipulated with the GetStatus and SetStatus functions. Radio buttons should not be accessed in this manner, but instead with the GetValue and SetValue functions applied to the parent group, which guarantee mutual exclusivity. List Objects Scrolling lists may be single choice or multiple choice: LisT SingleList (GrouP prnt, width, height, actn); LisT MultiList (GrouP prnt, width, height, actn); List elements are appended to the end of a list with the ListItem function: void ListItem (LisT prnt, title); The single choice list has an integer value accessed by GetValue and SetValue, and is the functional equivalent of a group of radio buttons. A multiple choice list is similar to a group of check boxes, but since each list item does not have its own handle, the settings are accessed with the GetItemStatus and SetItemStatus functions. Menu Objects Menus can reside in a window menu bar, in the Macintosh desktop menu bar, or as a sub menu in another menu. The Apple menu can be created on the Macintosh. A parent window parameter of NULL specifies the desktop menu bar on the Macintosh. SubMenu creates a menu item that controls a cascading sub menu, and takes a menu as its parent: MenU PulldownMenu (WindoW prnt, title); MenU AppleMenu (WindoW prnt); MenU SubMenu (MenU prnt, title); Menus can contain items or choice groups. The CommandItem is the equivalent of a push button, and the StatusItem is the equivalent of a check box: IteM CommandItem (MenU prnt, title, actn); IteM StatusItem (MenU prnt, title, actn); Separator bars can be used to make the menu easier to read: void SeparatorItem (MenU prnt); A choice group acts like a group of radio buttons or a single choice list. As such, the value of the choice group should be accessed with GetValue and SetValue: ChoicE ChoiceGroup (MenU prnt, actn); Choice group items are appended to the end of a choice group with the ChoiceItem function. The return value can be used to disable a choice item, but should not be used to access the status of the choice item: IteM ChoiceItem (ChoicE prnt, title); Popup Object The PopupList is a choice group that can appear anywhere in a window. On the Macintosh, the macLike parameter determines if the list drops down or pops up around the current selection, but this parameter may be eliminated in the future. As with other choice groups, the popup list value should be accessed with GetValue and SetValue: PopuP PopupList (GrouP prnt, macLike, actn); Popup menu items are appended to the end of a popup list with the PopupItem function. There is no return value, so the individual elements of a popup menu cannot be disabled: void PopupItem (PopuP prnt, title); Prompt Object The StaticPrompt is generally used as a label for a dialog text or a popup menu. It can also be used to display a changing value on a window. If the pixwidth parameter is 0, the width of the title string (plus two pixels) is used. If the pixheight parameter is 0, the stdLineHeight value is used. If the font specification is NULL, systemFont is used. The just parameter is either 'l', 'c', or 'r', specifying the horizontal justification: PrompT StaticPrompt (GrouP prnt, title, pixwidth, pixheight, font, just); The prompt is centered vertically around the pixheight value. Passing the standard variables dialogTextHeight or popupMenuHeight ensures proper placement of the prompt next to these objects. SetTitle can be used to change the string displayed by the prompt. Text Objects DialogText and PasswordText procedures accept a single line of text, while ScrollText is used for entering multiple lines of text. The width, height, and charWidth parameters currently use stdCharWidth as their metric, but this may be changed to pixel values in the future: TexT DialogText (GrouP prnt, dfault, charWidth, actn); TexT HiddenText (GrouP prnt, dfault, charWidth, actn, tabProc); TexT PasswordText (GrouP prnt, dfault, charWidth, actn); TexT ScrollText (GrouP prnt, width, height, font, actn); SetTextSelect assigns callbacks to notify the application of changes in the selection range or focus, though these parameter may be added to the text creation functions in the future: void SetTextSelect (TexT t, slct, dslct); TextLength returns the number of characters currently in the text object: Int2 TextLength (TexT t); SelectText allows a specific range of characters to be selected: Int2 SelectText (TexT t, begin, end); Knowledge of the active text and the selection range are useful for cutting and pasting: TexT CurrentText (void); void TextSelectionRange (TexT t, begin, end); The cut, copy, paste and clear functions require the text object to be specified as a parameter: void CutText (TexT t); void CopyText (TexT t); void PasteText (TexT t); void ClearText (TexT t); Scroll Bar Object A scroll bar unconnected with a text or slate object can be placed on a window with the ScrollBar function. Vibrant does not currently create scroll bars in a document window, though this may be implemented in the future. If width is positive, the scroll bar is horizontal, and if height is positive, it is vertical. The width and height parameters currently use stdCharWidth as the metric, though this will likely be changed to use pixels: BaR ScrollBar (GrouP prnt, width, height, actn); Scroll bar values are manipulated with GetValue and SetValue, which access the actual scroll bar thumb position. In addition, a scroll bar must first be activated by calling the SetRange function, passing it the maximum value as well as the page up and page down values: void SetRange (Handle obj, pgUp, pgDn, max); The scroll bar callback is triggered when the application program calls SetValue. All other Vibrant objects call their callback only when the user, not the application, changes the value. This is because the scroll bar is assumed to be controlling some non-standard object, whose appearance is changed in an application-specific manner. In order to adjust the value of the scroll bar without triggering the callback, the CorrectBarValue function is provided. The CorrectBarMax function changes the maximum value without needing to specify the page up and page down values, and CorrectBarPage changes the page up and down values: void CorrectBarValue (BaR b, val); void CorrectBarMax (BaR b, max); void CorrectBarPage (BaR b, pgUp, pgDn); The application also gets the scroll bar callbacks for the AutonomousPanel and GeneralSlate objects. The scroll callback for a panel will generally be written to call ScrollRect (to move lines that will remain visible, albeit in a different location in the panel), InvalRect (to flag as invalid any areas that need to be redrawn), and Update (to force the invalid areas to be immediately redrawn). The application should take care that the scroll bar value is never greater than the maximum. Slate and Panel Objects The slate is a universal drawing object. A slate can contain one or more panels. Each panel has an instance-specific callback for drawing, and can be assigned instance-specific callbacks for responding to mouse click, drag, hold, and release events. A slate comes in two flavors. One is a combination of a slate and a panel in a single object instance. These panels are created with the following commands: PaneL SimplePanel (GrouP prnt, pixwidth, pixheight, draw); PaneL AutonomousPanel (GrouP prnt, pixwidth, pixheight, draw, vscrl, hscrl, extra, reset, classPtr); The mouse response callbacks are assigned by SetPanelClick: void SetPanelClick (PaneL p, click, drag, hold, release); For the autonomous panel, extra instance data can be appended to the object. For example, the repeat button is implemented as an autonomous panel, and stores the button title and repeat action callback as extra data specific to each instance of a repeat button. The extra data is retrieved and set by the GetPanelExtra and SetPanelExtra functions: void GetPanelExtra (PaneL p, VoidPtr sptr); void SetPanelExtra (PaneL p, VoidPtr sptr); The other flavor of a slate has (usually multiple) panels as the children of a slate: SlatE ScrollSlate (GrouP prnt, width, height); SlatE NormalSlate (GrouP prnt, width, height); SlatE HiddenSlate (GrouP prnt, width, height); SlatE GeneralSlate (GrouP prnt, width, height, scrl, extra, classPtr); The VirtualSlate function fools the vertical scroll bar into acting as if it has a large range: void VirtualSlate (SlatE s, before, after, actn); Panels inside these slates are created with CustomPanel or GeneralPanel: PaneL CustomPanel (SlatE prnt, draw, extra, reset); PaneL GeneralPanel (SlatE prnt, draw, extra, reset, classPtr); Panels must register their rectangles to let the parent slate know their dimensions: void RegisterRect (PaneL p, r); Panels should also register rows and columns to the parent slate scroll bars. The slate remembers the line offsets and line heights, calls SetRange to the slate scroll bars, and the default slate scroll callback issues ScrollRect and InvalRect commands as appropriate when the user scrolls: void RegisterRow (SlatE s, position, height, count); void RegisterColumn (SlatE s, position, width, count); Slates may obtain the first line shown by calling GetOffset to the slate. Panels may obtain the current pixel offset by calling GetOffset to the child panel: void GetOffset (Handle obj, horiz, vert); Finally, the vertical and horizontal scroll bars may be obtained from the slate. The slate passes SetRange commands to its vertical scroll bar, but this became insufficient when horizontal scroll bars were added: BaR GetSlateVScrollBar (SlatE s); BaR GetSlateHScrollBar (SlatE s); Child panels (CustomPanel or GeneralPanel) can be used to build higher level reusable objects. (TablE and PalettE objects have been built to allow text and pictures to be easily displayed inside a slate.) The panels can be superimposed to build complex behaviors out of simpler panels, without disrupting the code of the individual panels. Panels are drawn first to last, so that the first one added to a slate appears at the rear of the slate. Panels are checked for click responsiveness from last to first, so that the last one added behaves as if it were in front. Repeat Object RepeatButton takes a click proc as its callback, which is called for click and hold. Even though it is implemented as a panel, and its callback has a mouse location parameter, it is otherwise close to a button in behavior. The title can be changed with SetTitle: RepeaT RepeatButton (GrouP prnt, title, actn); Switch Object The switch object is used as a miniature scroll bar, with up and down arrows but no thumb or page areas. It can optionally display a (non-editable) text representation of the value (e.g., "5/15"): SwitcH UpDownSwitch (GrouP prnt, text, actn); SwitcH LeftRightSwitch (GrouP prnt, text, actn); The value is manipulated with SetValue and GetValue. The arrows will allow the user to set values from 1 through max. SetSwitchParams will set both the max and the value at once, to avoid flickering by multiple redraws: void SetSwitchMax (SwitcH s, Int2 max); Int2 GetSwitchMax (SwitcH s); void SetSwitchParams (SwitcH s, Int2 value, Int2 max); Icon Object The IconButton is used to display arbitrary bitmap and drawing controls. The draw callback should get the value of the icon button (with GetValue) to determine what to display, and should call ObjectRect to determine the rectangle of the icon object (in which it should draw). The click, drag, hold and release mouse callbacks may use SetValue to change the appearance: IcoN IconButton (GrouP prnt, pixwidth, pixheight, draw, inval, click, drag, hold, release); Whenever SetValue is called, the inval callback is triggered. If this parameter is NULL, the default invalidation procedure is called. This obtains the object rectangle, insets it by one pixel, and invalidates the resulting rectangle. The inval parameter is provided to allow the application to invalidate a different region, or to scroll the drawing, if that is more appropriate. After the inval procedure is called, an Update is forced, calling the draw procedure if any part of the icon has been marked as invalid. Graphical Viewer Object This is a high level object written with an autonomous panel. There are two header files that contain the typedefs and function prototypes for this package: #include #include You should read these header files to see the typedefs for the various callbacks. The mouse responsiveness callbacks, in particular, take an extra parameter from those used directly with panels. A picture is created as a tree of segment objects. Picture segments are not Vibrant graphical objects, in that they cannot be placed into windows, groups, menus, etc., though their philosophy is very similar to the Vibrant group. A segment can be given an integer ID that can refer to the program object which it represents. It can also be told the maximum scale factor at which it will be visible (0 means always visible). Given any segment, you can find its parent segment, and traverse up the hierarchy to the parent picture. SegmenT CreatePicture (void); SegmenT DeletePicture (SegmenT picture); SegmenT CreateSegment (SegmenT parent, segID, maxScale); SegmenT ResetSegment (SegmenT segment); SegmenT ParentSegment (SegmenT segment); Int2 SegmentID (SegmenT segment); Boolean SegmentVisible (SegmenT segment); Int1 SegmentStyle (SegmenT segment); void SegmentBox (SegmenT segment, box, mrg); Picture items of various types (rectangles, lines, annotation objects such as symbols and labels, and attribute items that change color, shading, line width and style) are added to segments. (Segments can also be added to other segments.) Items are placed in a picture in "world coordinates", which are integer numbers that make sense to the domain being modeled. The primitive items can contain an integer ID to be returned by FindSegment. Rectangles and lines have must specify their full dimensions in world coordinates. These items will change size when the picture is scaled in a viewer: void AddRectangle (SegmenT parent, left, top, right, bottom, arrow, fill, primID); void AddLine (SegmenT parent, pnt1X, pnt1Y, pnt2X, pnt2Y, arrow, primID); Annotation objects are attached to a particular point in world coordinates. They do not change size when the picture is scaled in a viewer, but their position changes depending upon where the point is mapped. This means that label text will remain a constant font size even when the picture is scaled: void AddSymbol (SegmenT parent, pntX, pntY, symbol, fill, align, primID); void AddBitmap (SegmenT parent, pntX, pntY, width, height, data, align,primID); void AddCustom (SegmenT parent, pntX, pntY, width, height, proc, align, primID); void AddMarker (SegmenT parent, pntX, pntY, length, orient, primID); void AddLabel (SegmenT parent, pntX, pntY, string, size, offset, align, primID); The attribute item changes the color, line style, shading, pen width and drawing mode for subsequent items within a given segment. The attributes do not effect subsequent items in any parent segments: void AddAttribute (SegmenT parent, flags, color, linestyle, shading, penwidth, mode); A viewer is created on a window or in a group. A picture is then attached to the viewer. The viewer is responsible for scaling (zooming) and panning (scrolling) the picture on the screen. It converts from world coordinates to screen coordinates. It also responds to mouse events, and can return the deepest segment that contains the item upon which the mouse was clicked. The viewer width and height parameters are in pixels: VieweR CreateViewer (GrouP prnt, width, height, vscroll, hscroll); void ResetViewer (VieweR viewer); VieweR DeleteViewer (VieweR viewer) A picture is connected to a viewer by AttachPicture. This function also specifies where a particular point in world coordinates should initially go on the screen, the scale factors (what number to divide a world coordinate by to get a pixel coordinate), and a draw procedure (for drawing on top of the viewer picture). A scale parameter of 0 will cause the viewer to calculate the scale needed to show the entire picture at once. You can also set the click, drag, release, and scrolling pan procedures, and attach extra instance data to the viewer: void AttachPicture (VieweR viewer, picture, pntX, pntY, align, scaleX, scaleY, draw); void SetViewerProcs (VieweR viewer, click, drag, release, pan); void SetViewerData (VieweR viewer, data, cleanup); VoidPtr GetViewerData (VieweR viewer); If you wish to respond to the user's scrolling, you should set the pan parameter to a callback in your program. You can then call ViewerBox to get the current view parameters, including the world boundaries, the port boundaries, the view rectangle, and the X and Y scaling factors. The port is the view rectangle (pixel rectangle in the viewer) mapped up onto world coordinates, and is always contained within the world boundaries: void ViewerBox (VieweR viewer, world, port, view, scaleX, scaleY); Printing the picture associated with a viewer is only partially implemented at this time: void PrintViewer (VieweR viewer); During a click, drag, or release callback, FindSegment will return the deepest segment containing an object in which the mouse resides, and can return the integer segment ID and primitive ID assigned when the segment and its primitive item were created. You can also show, hide, or highlight a segment, or highlight a rectangle or line primitive: SegmenT FindSegment (VieweR viewer, pt, segID, primID); void ShowSegment (VieweR viewer, segment); void HideSegment (VieweR viewer, segment); void HighlightSegment (VieweR viewer, segment, highlight); void HighlightPrimitive (VieweR viewer, segment, primitive, highlight); World and viewer coordinates can be interconverted with the following functions: void MapWorldToViewer (VieweR viewer, pnt, pt); void MapViewerToWorld (VieweR viewer, pt, pnt); When you want to zoom, you call AttachPicture, passing the old viewer and picture, but giving new values for scaleX and scaleY. This will recalculate boundary and scaling information, and display the picture at a new level of magnification. Doc Object This is a high level object written with an autonomous panel. It is meant as a (partial) general solution to the problems of displaying text and graphics. You should read the header to see the callback typedefs and the column and paragraph data structures: #include When a document is created you give it the width and height in pixels. This does not include the vertical scroll bar that is automatically created: DoC DocumentPanel (GrouP prnt, pixwidth, pixheight); void PrintDocument (DoC d); void SaveDocument (DoC d, f); Paragraph items are appended to the document with AppendItem or AppendText. AppendText is a special case that takes a pre-formatted text pointer. AppendItem is a more general function that takes a data pointer and a print procedure. The print procedure is called when the given paragraph needs to be displayed, printed, or saved: void AppendItem (DoC d, proc, data, docOwnsData, lines, parFmt, colFmt, font, adjust); void AppendText (DoC, text, parFmt, colFmt, font); Existing paragraph items can be replaced in a similar manner: void ReplaceItem (DoC d, item, proc, data, docOwnsData, lines, parFmt, colFmt, font, adjust); void ReplaceText (DoC, item, text, parFmt, colFmt, font); Document callback procedures are set in a similar manner to the graphical viewer object: void SetDocProcs (DoC d, click, drag, release, pan); void SetDocShade (DoC d, draw, gray, invert, color); void SetDocData (DoC d, data, cleanup); VoidPtr GetDocData (DoC d); The mouse point can be mapped to a paragraph item, row, and column, and parameters can be returned that apply to the document, item, or column levels. The text in a document can be retrieved, with 0 for item, row or column specifying all items, rows or columns: void MapDocPoint (DoC d, pt, item, row, col); void GetDocParams (DoC d, numItems, numLines); void GetItemParams (DoC d, item, startsAt, numRows, numCols, lineHeight); void GetColParams (DoC d, item, col, pixPos, pixWidth, pixInset, just); CharPtr GetDocText (DoC d, item, row, col); Boolean ItemIsVisible (DoC d, item, top, bottom, firstLine); If an item is appended or replaced with the adjust parameter FALSE, the document will need to be updated, and its scrolling may need to be adjusted: void UpdateDocument (DoC d, from, to); void AdjustDocScroll (DoC); Two simple functions can be used to display a text file in a document object: void DisplayFile (DoC d, file, font); void DisplayFancy (DoC d, file, parFmt, colFmt, font, tabStops); Class Functions Class functions can be applied to any Vibrant graphical object. (This does not include the FonT or SegmenT objects. Even though each FonT or SegmenT refers to an element of a linked list maintained by Vibrant, the structures of these elements is different than Vibrant graphic control objects. Class functions also cannot be applied to PoinT, RecT, or RegioN, which are simply descriptions of areas in a window.) Several functions are used to control visibility and responsiveness of an object. All objects except windows are set to be visible and enabled at the time of their creation. A window must be explicitly shown in order for it and its children to become visible: void Show (Handle obj); void Hide (Handle obj); void Enable (Handle obj); void Disable (Handle obj); void Select (Handle obj); The program parameters that objects represent can have string, integer, or Boolean values: void SetTitle (Handle obj, title); void GetTitle (Handle obj, title, maxsize); void SetValue (Handle obj, value); Int2 GetValue (Handle obj); void SetStatus (Handle obj, status); Boolean GetStatus (Handle obj); SetRange controls a scroll bar (or slate vertical scroll bar) range. SetValue and GetValue will access the actual scroll bar thumb position: void SetRange (Handle obj, pgUp, pgDn, max); SetOffset and GetOffset of a slate, list, or scrolling text access the scroll bar values. GetOffset of a slate returns the integer setting of the scroll bar (generally representing the number of the first line in view). GetOffset of a panel child of a slate returns the pixel offset of the line, which is maintained by the slate: void SetOffset (Handle obj, horiz, vert); void GetOffset (Handle obj, horiz, vert); Reset and Remove reinitialize and delete objects. These functions are automatically called for all objects at the end of the program: void Reset (Handle obj); void Remove (Handle obj); Miscellaneous Functions Positioning of objects can be influenced with Advance and Break. These are called automatically by the group layout function: void Advance (Handle obj); void Break (Handle obj); The position in which the next object will be placed can be explicitly set and obtained controlled with the following commands: void GetNextPosition (Handle obj, pt); void SetNextPosition (Handle obj, pt); The bounding rectangle of any Vibrant graphical object is obtained with ObjectRect: void ObjectRect (Handle obj, rct); The number of items in a list or menu choice group can be obtained with CountItems: Int2 CountItems (Handle obj); Whether an object is enabled or visible can be determined with Enabled or Visible. An object will be unresponsive or invisible if it or any of its parent objects are disabled or hidden, even if it is flagged as visible and enabled: Boolean Enabled (Handle obj); Boolean Visible (Handle obj); The cursor can be set with the following commands: void ArrowCursor (void); void CrossCursor (void); void IBeamCursor (void); void PlusCursor (void); void WatchCursor (void); An application timer can be set with the Metronome function: void Metronome (actn); The parent of an object can be traversed up the hierarchy. The parent of a window is NULL: Handle Parent (Handle obj); ProcessEvents calls the main Vibrant event loop, and Update forces immediate redrawing: void ProcessEvents (void); void Update (void); AlignObjects may be used for objects within a window (or within a group that does not do automatic repositioning). Objects should be cast to (HANDLE) (which is different than Handle), and the list must be terminated with NULL. Alignment will adjust the margins of the target objects so that they line up vertically, by moving the appropriate margins to the maximum value of all margins. ALIGN_LEFT will move the left margins, ALIGN_RIGHT will move the right margins, ALIGN_JUSTIFY will move both margins, and ALIGN_CENTER will center all objects: void AlignObjects (Int2 align, ...); Vibrant adds the following functions for file path manipulation. These display file open and file save dialogs: Boolean GetInputFileName (fileName, maxsize, extType, macType); Boolean GetOutputFileName (fileName, maxsize, dfault); Graphical Drawing Functions Drawing functions are provided for displaying graphics in a Vibrant panel. (These may now also be used to draw on top of a viewer object.) Most of these functions simply front-end for the equivalent procedures in the underlying toolkits. However, some (e.g., CopyBits and ScrollRect) are quite complicated internally, doing much more than the toolkits provide. Procedures for specifying the drawing mode, the color, the pen and brush patterns, and for framing or painting objects, are all independent, even if some of the underlying toolkits combine functions. Drawing parameters are reset prior to each call to the panel drawing callback. Coordinates are in pixels, with (0, 0) being the upper left corner of the parent window (not including the window border or frame). There are four modes for drawing. CopyMode and MergeMode are implemented on all platforms. Copy mode will overwrite a destination area with the source data. Drawing text in copy mode will show the text in foreground color on top of a rectangle in background color, regardless of what color had been there before. MergeMode can be used to superimpose bitmaps of different colors (using CopyBits) to form a multicolored iconic picture. Drawing text in merge mode will show the text in foreground color but won't change the background. InvertMode can be used along with a Dotted pen for drawing "rubber band" lines: void CopyMode (void); void MergeMode (void); void InvertMode (void); void EraseMode (void); Standard colors for drawing can be set, or an arbitrary color can be selected with one-byte values for red, green, and blue intensity. InvertColors swaps foreground and background colors, to allow predictable highlighting to occur under various color models: void Black (void); void Red (void); void Green (void); void Blue (void); void Cyan (void); void Magenta (void); void Yellow (void); void White (void); void Gray (void); void LtGray (void); void DkGray (void); void SelectColor (red, green, blue); Int4 GetColor (void); void SetColor (color); void InvertColors (void); The drawing pattern or dithering can be specified for brushes (painting functions), as can the width and style of a pen (framing functions). Solid will restore the pen and brush patterns: void Solid (void); void Dark (void); void Medium (void); void Light (void); void Empty (void); void Dotted (void); void Dashed (void); void WidePen (width); Fonts are created with GetFont (passing individual parameters) or with ParseFont (passing a string that is parsed and then sent to GetFont). This returns a handle to an element of a font list maintained by Vibrant. SelectFont sets that font for use in drawing text. Vibrant will clean up the memory used for fonts after the application Main exits: FonT GetFont (name, size, bld, itlc, undrln, fmly); FonT ParseFont (spec); void SelectFont (font); Available fonts differ between different windowing systems. Typically, #ifdefs are used to specify fonts within the program code. The string sent to ParseFont has the font name, the font size, and any of the characters 'b', 'i', or 'u', for bold, italic, or underline: #ifdef WIN_MAC headingFont = ParseFont ("Monaco,9,b"); sequenceFont = ParseFont ("Monaco,9"); #endif #ifdef WIN_MSWIN headingFont = ParseFont ("Arial,11,b"); sequenceFont = ParseFont ("Courier,9"); #endif #ifdef WIN_MOTIF headingFont = ParseFont ("Helvetica,14,b"); sequenceFont = ParseFont ("Courier,12"); #endif Points and rectangles can be loaded, compared, and manipulated. OffsetRect will add dx to the left and right coordinates, and add dy to the top and bottom coordinates. InsetRect will add dx to the left, subtract dx from the right, add dy to the top, and subtract dy from the bottom. SectRect and UnionRect return the intersection and union, respectively, between two source rectangles. Drawing functions may want to check RectInRgn against the updateRgn to determine if an object needs to be redrawn: void LoadPt (pt, x, y); void AddPt (src, dst); void SubPt (src, dst); Boolean EqualPt (pt1, pt2); void LoadRect (rct, lf, tp, rt, bt); void OffsetRect (rct, dx, dy); void InsetRect (rct, dx, dy); Boolean SectRect (src1, src2, dst); Boolean UnionRect (src1, src2, dst); Boolean EqualRect (r1, r2); Boolean EmptyRect (rct); Boolean PtInRect (pt, rct); Boolean PtInRgn (pt, rgn); Boolean RectInRect (r1, r2); Boolean RectInRgn (rct, rgn); Text metrics are returned for the currently selected font by the following functions: Int2 CharWidth (ch); Int2 StringWidth (text); Int2 TextWidth (text, len); Int2 Ascent (void); Int2 Descent (void); Int2 Leading (void); Int2 FontHeight (void); Int2 LineHeight (void); Int2 MaxCharWidth (void); The pen position can be set and lines can be drawn with the following functions: void SetPen (pt); void GetPen (pt); void MoveTo (x, y); void LineTo (x, y); void DrawLine (pt1, pt2); Text strings may be painted (at the current pen location) or drawn (in a specified rectangle). The minimum width of the rectangle should be StringWidth (text) + 2 pixels. The justification parameter is 'l', 'c' or 'r' for left, centered, or right: void PaintChar (ch); void PaintString (text); void PaintText (format, ...); void DrawString (rct, text, jst, gray); void DrawText (rct, text, len, jst, gray); Rectangles, ovals, round rectangles, arcs, and polygons may generally be framed (drawn in outline) and painted (filled in), and on some platforms can also be erased and inverted. Rectangles are drawn with the following functions: void EraseRect (rct); void FrameRect (rct); void PaintRect (rct); void InvertRect (rct); Ovals or ellipses are fitted to the bounding rectangle: void EraseOval (rct); void FrameOval (rct); void PaintOval (rct); void InvertOval (rct); Round rectangles are not implemented on all systems: void EraseRoundRect (rct, ovlWid, ovlHgt); void FrameRoundRect (rct, ovlWid, ovlHgt); void PaintRoundRect (rct, ovlWid, ovlHgt); void InvertRoundRect (rct, ovlWid, ovlHgt); Arcs take a rectangle and draw counter clockwise from the line between the starting point and the center to the line between the ending point and the center: void EraseArc (rct, start, end); void FrameArc (rct, start, end); void PaintArc (rct, start, end); void InvertArc (rct, start, end); Polygons take a pointer to an array of PoinTs, and will always form a closed polygon. Painting is done using the Even-Odd Rule (as opposed to the Winding Rule, which is not available on all platforms). This means that if the lines connecting the points cross, some areas will be painted and other adjacent areas will not be painted: void ErasePoly (num, pts); void FramePoly (num, pts); void PaintPoly (num, pts); void InvertPoly (num, pts); Regions, lists of rectangular areas treated as a group, are manipulated and drawn with the following functions. Functions that take a destination region (e.g., SectRgn, UnionRgn) must be passed an existing region, and will not create one if NULL is supplied. Most programs will not need to be concerned with regions, other than to check RectInRgn against the updateRgn: RegioN CreateRgn (void); RegioN DestroyRgn (rgn); void ClearRgn (rgn); void LoadRectRgn (rgn, lf, tp, rt, bt); void OffsetRgn (rgn, dx, dy); void SectRgn (src1, src2, dst); void UnionRgn (src1, src2, dst); void DiffRgn (src1, src2, dst); void XorRgn (src1, src2, dst); Boolean EqualRgn (rgn1, rgn2); Boolean EmptyRgn (rgn); void EraseRgn (rgn); void FrameRgn (rgn); void PaintRgn (rgn); void InvertRgn (rgn); Clipping restricts the area on the window in which drawing commands will be honored. Invalidation marks areas of the window to be erased and redrawn at the next update: void ClipRect (rct); void ClipRgn (rgn); void ResetClip (void); void ValidRect (rct); void InvalRect (rct); void ValidRgn (rgn); void InvalRgn (rgn); A rectangular area can be scrolled with the ScrollRect function. The area of the rectangle that will need to be updated is automatically invalidated, but if an application does not draw objects that would be partially visible, it may need to invalidate the (scrolled) areas that would have contained parts of objects when the objects in those areas become fully visible: void ScrollRect (rct, dx, dy); Bitmaps (icons) can be displayed with the CopyBits function (which performs a toolbox BitBlt operation). The source is a VoidPtr to an array of bits in memory, where 1 means foreground color and 0 means background color. Under Windows, a copy is made, and the bits are inverted. Under Motif, a copy is made, and the bytes are rotated so that the last significant and most significant bits are reversed: void CopyBits (rct, source); The following bitmap represents a 16-bit-wide downward arrow. The 1 bits specify foreground color, the 0 bits background color, and the most significant bit in a byte is drawn at the left. Bitmaps should be declared as Uint1s (to avoid byte order problems between different machines), and the width should be in multiples of 2 bytes, even though the CopyBits rectangle can clip to less than 8 bits. Bitmaps should be declared outside of functions, since some compilers hang when trying to initialize large internal arrays: static Uint1 downArrow [] = { 0x1C, 0x00, 0x1C, 0x00, 0x1C, 0x00, 0x1C, 0x00, 0x1C, 0x00, 0x1C, 0x00, 0x7F, 0x00, 0x3E, 0x00, 0x1C, 0x00, 0x08, 0x00 }; The following function will draw the downward arrow in the center of a panel. The arrow will be drawn in the currently selected foreground color, and using the current mode: static void DrawDownArrow (PaneL p) { RecT r; ObjectRect (p, &r); r.left = (r.left + r.right) / 2 - 8; r.right = r.left + 16; r.top = (r.top + r.bottom) / 2 - 5; r.bottom = r.top + 10; CopyBits (&r, downArrow); } Complex iconic pictures can be drawn by repeated calls to CopyBits using the same target rectangle and using MergeMode to superimpose different bitmaps in different colors. Index Vibrant types are listed below: typedef struct point { Int2 x; Int2 y; } PoinT, PNTR PointPtr; typedef struct rect { Int2 left; Int2 top; Int2 right; Int2 bottom; } RecT, PNTR RectPtr; typedef Handle RegioN; typedef struct font {} HNDL FonT; Types of Vibrant graphic objects that can be created are as follows: BaR ButtoN ChoicE DoC GrouP IcoN IteM LisT MenU PaneL PopuP PrompT RepeaT SlatE SwitcH TexT VieweR WindoW Generic callback types are shown below: typedef void (*VoidProc) (void); typedef void (*KeyProc) (Char); typedef void (*ActnProc) (GraphiC); typedef void (*ClckProc) (GraphiC, PoinT); typedef void (*ScrlProc) (BaR, GraphiC, Int2, Int2); typedef void (*ChngProc) (GraphiC, Int2, Int2); typedef void (*FreeProc) (GraphiC, VoidPtr); The section lists all of the functions presented above in alphabetical order: void AddAttribute (SegmenT parent, flags, color, linestyle, shading, penwidth, mode); void AddBitmap (SegmenT parent, pntX, pntY, width, height, data, align, primID); void AddCustom (SegmenT parent, pntX, pntY, width, height, proc, align, primID); void AdjustDocScroll (DoC d); void AddLabel (SegmenT parent, pntX, pntY, string, size, offset, align, primID); void AddLine (SegmenT parent, pnt1X, pnt1Y, pnt2X, pnt2Y, arrow, primID); void AddMarker (SegmenT parent, pntX, pntY, length, orient, primID); void AddPt (src, dst); void AddRectangle (SegmenT parent, left, top, right, bottom, arrow, fill, primID); void AddSymbol (SegmenT parent, pntX, pntY, symbol, fill, align, primID); void Advance (Handle obj); WindoW AlertWindow (left, top, width, height, close); void AlignObjects (Int2 align, ...); void AppendItem (DoC d, proc, data, docOwnsData, lines, parFmt, colFmt, font, adjust); void AppendText (DoC, text, parFmt, colFmt, font); MenU AppleMenu (WindoW prnt); void ArrowCursor (void); Int2 Ascent (void); void AttachPicture (VieweR viewer, picture, pntX, pntY, align, scaleX, scaleY, draw); PaneL AutonomousPanel (GrouP prnt, pixwidth, pixheight, draw, vscrl, hscrl, extra, reset, classPtr); void Black (void); void Blue (void); void Break (Handle obj); Int2 CharWidth (ch); ButtoN CheckBox (GrouP prnt, title, actn); ChoicE ChoiceGroup (MenU prnt, actn); IteM ChoiceItem (ChoicE prnt, title); void ClearRgn (rgn); void ClearText (TexT t); void ClipRect (rct); void ClipRgn (rgn); IteM CommandItem (MenU prnt, title, actn); void CopyBits (rct, source); void CopyMode (void); void CopyText (TexT t); void CorrectBarMax (BaR b, max); void CorrectBarPage (BaR b, pgUp, pgDn); void CorrectBarValue (BaR b, val); Int2 CountItems (Handle obj); SegmenT CreatePicture (void); RegioN CreateRgn (void); SegmenT CreateSegment (SegmenT parent, segID, maxScale); VieweR CreateViewer (GrouP prnt, width, height, vscroll, hscroll); void CrossCursor (void); TexT CurrentText (void); WindoW CurrentWindow (void); PaneL CustomPanel (SlatE prnt, draw, extra, reset); void CutText (TexT t); void Cyan (void); void Dark (void); void Dashed (void); ButtoN DefaultButton (GrouP prnt, title, actn); SegmenT DeletePicture (SegmenT picture); VieweR DeleteViewer (VieweR viewer) Int2 Descent (void); RegioN DestroyRgn (rgn); TexT DialogText (GrouP prnt, dfault, charWidth, actn); void DiffRgn (src1, src2, dst); void Disable (Handle obj); void DisplayFancy (DoC d, file, parFmt, colFmt, font, tabStops); void DisplayFile (DoC d, file, font); void DkGray (void); DoC DocumentPanel (GrouP prnt, pixwidth, pixheight); WindoW DocumentWindow (left, top, width, height, title, close, resize); void Dotted (void); void DrawLine (pt1, pt2); void DrawString (rct, text, jst, gray); void DrawText (rct, text, len, jst, gray); void Empty (void); Boolean EmptyRect (rct); Boolean EmptyRgn (rgn); void Enable (Handle obj); Boolean Enabled (Handle obj); Boolean EqualPt (pt1, pt2); Boolean EqualRect (r1, r2); Boolean EqualRgn (rgn1, rgn2); void EraseArc (rct, start, end); void EraseMode (void); void EraseOval (rct); void ErasePoly (num, pts); void EraseRect (rct); void EraseRgn (rgn); void EraseRoundRect (rct, ovlWid, ovlHgt); SegmenT FindSegment (VieweR viewer, pt, segID, primID); WindoW FixedWindow (left, top, width, height, title, close); WindoW FloatingWindow (left, top, width, height, close); Int2 FontHeight (void); void FrameArc (rct, start, end); void FrameOval (rct); void FramePoly (num, pts); void FrameRect (rct); void FrameRgn (rgn); void FrameRoundRect (rct, ovlWid, ovlHgt); WindoW FrozenWindow (left, top, width, height, title, close); PaneL GeneralPanel (SlatE prnt, draw, extra, reset, classPtr); SlatE GeneralSlate (GrouP prnt, width, height, scrl, extra, classPtr); FonT GetFont (name, size, bld, itlc, undrln, fmly); Int4 GetColor (void); void GetColParams (DoC d, item, col, pixPos, pixWidth, pixInset, just); VoidPtr GetDocData (DoC d); void GetDocParams (DoC d, numItems, numLines); CharPtr GetDocText (DoC d, item, row, col); void GetItemParams (DoC d, item, startsAt, numRows, numCols, lineHeight); Boolean GetInputFileName (fileName, maxsize, extType, macType); void GetNextPosition (Handle obj, pt); void GetOffset (Handle obj, horiz, vert); Boolean GetOutputFileName (fileName, maxsize, dfault); void GetPanelExtra (PaneL p, VoidPtr sptr); void GetPen (pt); BaR GetSlateHScrollBar (SlatE s); BaR GetSlateVScrollBar (SlatE s); Boolean GetStatus (Handle obj); Int2 GetSwitchMax (SwitcH s); void GetTitle (Handle obj, title, maxsize); Int2 GetValue (Handle obj); VoidPtr GetViewerData (VieweR viewer); VoidPtr GetWindowExtra (WindoW w); void Gray (void); void Green (void); GrouP HiddenGroup (GrouP prnt, width, height, actn); SlatE HiddenSlate (GrouP prnt, width, height); TexT HiddenText (GrouP prnt, dfault, charWidth, actn, tabProc); void Hide (Handle obj); void HideSegment (VieweR viewer, segment); void HighlightSegment (VieweR viewer, segment, highlight); void HighlightPrimitive (VieweR viewer, segment, primitive, highlight); void IBeamCursor (void); IcoN IconButton (GrouP prnt, pixwidth, pixheight, draw, inval, click, drag, hold, release); void InsetRect (rct, dx, dy); void InvalObject (Handle obj); void InvalRect (rct); void InvalRgn (rgn); void InvertArc (rct, start, end); void InvertColors (void); void InvertMode (void); void InvertOval (rct); void InvertPoly (num, pts); void InvertRect (rct); void InvertRgn (rgn); void InvertRoundRect (rct, ovlWid, ovlHgt); Boolean ItemIsVisible (DoC d, item, top, bottom, firstLine); Int2 Leading (void); SwitcH LeftRightSwitch (GrouP prnt, text, acrn); void Light (void); Int2 LineHeight (void); void LineTo (x, y); void ListItem (LisT prnt, title); void LoadPt (pt, x, y); void LoadRect (rct, lf, tp, rt, bt); void LoadRectRgn (rgn, lf, tp, rt, bt); void LtGray (void); void Magenta (void); void MapDocPoint (DoC d, pt, item, row, col); void MapViewerToWorld (VieweR viewer, pt, pnt); void MapWorldToViewer (VieweR viewer, pnt, pt); Int2 MaxCharWidth (void); void Medium (void); void MergeMode (void); void Metronome (actn); WindoW ModalWindow (left, top, width, height, close); void MoveTo (x, y); LisT MultiList (GrouP prnt, width, height, actn); GrouP NormalGroup (GrouP prnt, width, height, title, actn); SlatE NormalSlate (GrouP prnt, width, height); void ObjectRect (Handle obj, rct); void OffsetRect (rct, dx, dy); void OffsetRgn (rgn, dx, dy); void PaintArc (rct, start, end); void PaintChar (ch); void PaintOval (rct); void PaintPoly (num, pts); void PaintRect (rct); void PaintRgn (rgn); void PaintRoundRect (rct, ovlWid, ovlHgt); void PaintString (text); void PaintText (format, ...); Handle Parent (Handle obj); SegmenT ParentSegment (SegmenT segment); WindoW ParentWindow (Handle obj); FonT ParseFont (spec); TexT PasswordText (GrouP prnt, dfault, charWidth, actn); void PasteText (TexT t); WindoW PlainWindow (left, top, width, height, close); void PlusCursor (void); void PopupItem (PopuP prnt, title); PopuP PopupList (GrouP prnt, macLike, actn); void PrintDocument (DoC d); void PrintViewer (VieweR viewer); void ProcessEvents (void); Boolean PtInRect (pt, rct); Boolean PtInRgn (pt, rgn); MenU PulldownMenu (WindoW prnt, title); ButtoN PushButton (GrouP prnt, title, actn); ButtoN RadioButton (GrouP prnt, title); Boolean RectInRect (r1, r2); Boolean RectInRgn (rct, rgn); void Red (void); void RegisterColumn (SlatE s, position, width, count); void RegisterRect (PaneL p, r); void RegisterRow (SlatE s, position, height, count); void Remove (Handle obj); RepeaT RepeatButton (GrouP prnt, title, actn); void ReplaceItem (DoC d, item, proc, data, docOwnsData, lines, parFmt, colFmt, font, adjust); void ReplaceText (DoC, item, text, parFmt, colFmt, font); void Reset (Handle obj); void ResetClip (void); SegmenT ResetSegment (SegmenT segment); void ResetViewer (VieweR viewer); void RestorePort (WindoW w); WindoW RoundWindow (left, top, width, height, title, close); void SaveDocument (DoC d, f); WindoW SavePort (Handle obj); BaR ScrollBar (GrouP prnt, width, height, actn); void ScrollRect (rct, dx, dy); SlatE ScrollSlate (GrouP prnt, width, height); TexT ScrollText (GrouP prnt, width, height, font, actn); Boolean SectRect (src1, src2, dst); void SectRgn (src1, src2, dst); void SegmentBox (SegmenT segment, box, mrg); Int2 SegmentID (SegmenT segment); Int1 SegmentStyle (SegmenT segment); Boolean SegmentVisible (SegmenT segment); void Select (Handle obj); void SelectColor (red, green, blue); void SelectFont (font); Int2 SelectText (TexT t, begin, end); void SeparatorItem (MenU prnt); void SetActivate (WindoW w, act); void SetColor (color); void SetDocData (DoC d, data, cleanup); void SetDocProcs (DoC d, click, drag, release, pan); void SetDocShade (DoC d, draw, gray, invert, color); void SetGroupMargins (GrouP g, xMargin, yMargin); void SetGroupSpacing (GrouP g, xSpacing, ySpacing); void SetNextPosition (Handle obj, pt); void SetOffset (Handle obj, horiz, vert); void SetPanelClick (PaneL p, click, drag, hold, release); void SetPanelExtra (PaneL p, VoidPtr sptr); void SetPen (pt); void SetRange (Handle obj, pgUp, pgDn, max); void SetStatus (Handle obj, status); void SetSwitchMax (SwitcH s, max); void SetSwitchParams (SwitcH s, value, max); void SetTextSelect (TexT t, slct, dslct); void SetTitle (Handle obj, title); void SetValue (Handle obj, value); void SetViewerData (VieweR viewer, data, cleanup); void SetViewerProcs (VieweR viewer, click, drag, release, pan); void SetWindowExtra (WindoW w, data, cleanup); WindoW ShadowWindow (left, top, width, height, close); void Show (Handle obj); void ShowSegment (VieweR viewer, segment); PaneL SimplePanel (GrouP prnt, pixwidth, pixheight, draw); LisT SingleList (GrouP prnt, width, height, actn); void Solid (void); PrompT StaticPrompt (GrouP prnt, title, pixwidth, pixheight, font, just); IteM StatusItem (MenU prnt, title, actn); Int2 StringWidth (text); MenU SubMenu (MenU prnt, title); void SubPt (src, dst); Int2 TextLength (TexT t); void TextSelectionRange (TexT t, begin, end); Int2 TextWidth (text, len); Boolean UnionRect (src1, src2, dst); void UnionRgn (src1, src2, dst); void Update (void); void UpdateDocument (DoC d, from, to); SwitcH UpDownSwitch (GrouP prnt, text, acrn); void UseWindow (WindoW w); void ValidRect (rct); void ValidRgn (rgn); void ViewerBox (VieweR viewer, world, port, view, scaleX, scaleY); void VirtualSlate (SlatE s, before, after, actn); Boolean Visible (Handle obj); void WatchCursor (void); void White (void); void WidePen (width); void XorRgn (src1, src2, dst); void Yellow (void); Acknowledgments I wish to thank a number of colleagues at the National Center for Biotechnology Information who have contributed critical ideas to this interface. Jim Ostell proposed the ideas of portability and of dealing with objects at a high level, as close to the level of the desired parameters as is possible. He also made suggestions that led to the concept of automatically positioning objects on the window and within groups. Warren Gish, Greg Schuler, Tim Clark, Peter Karp, and several others also made numerous useful suggestions and constructive criticisms. Early applications in Vibrant, written by or for John Spouge, Jill Shermer, Charlie Beatty, Jonathan Epstein and Kenn Rudd, uncovered design limitations that were quickly remedied. Jill Shermer assisted in porting Vibrant to Motif. Vibrant will be published separately in the near future. You should reference J. Kans (manuscript in preparation). Details on the internal organization of Vibrant will be published as an NCBI technical report in the future. Vibrant is supplied as-is, and is currently not being supported. Questions or comments can be directed to toolbox@ncbi.nlm.nih.gov. Trademarks The mention of trade names, commercial products, or organizations does not imply endorsement by the NCBI or the U.S. Government. Apple and Macintosh are registered trademarks of Apple Computer, Inc. Microsoft is a registered trademark and Windows is a trademark of Microsoft Corporation. Motif is a registered trademark of the Open Software Foundation.