Triton





Release 1.4





Developer Documentation





© 1993-1995 by Stefan Zeiger.

All rights reserved.


\input texinfo

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1 Introduction


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.1 Overview

The Triton GUI creation system offers an easy way to create good looking GUIs for your applications. It can be used with a variety of programming languages. Currently supported are the following languages and development systems:

(If you create a Triton support system for any other language or development system and are willing to maintain it for future updates, please contact me for inclusion into the main Triton Developer distribution.)

This document describes how to use Triton in your own applications by providing you with some overview topics and a step by step introduction. It does not describe in detail the functions, structures, tags, etc. which are used, so you should always look them up in the autodocs file (see Introduction - Autodocs) and the C header file ‘Developer/Include/libraries/triton.h’.

The examples in this document assume that you’re using the C support files with the SAS/C compiler. There may be differences in other languages or even with other C development systems.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.2 OOP Internals

Although Triton offers a mostly procedural API, it is based on an object-oriented system. As a Triton user you will never see Triton objects directly, but instead reference them through IDs.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.3 Class Tree

The following classes are available in Triton:

    Object                  Abstract root class
    `-- DisplayObject       Abstract class for window contents
        +-- Button          BOOPSI button gadget
        +-- CheckBox        GadTools CheckBox
        +-- Cycle           GadTools Cycle and MX gadget
        +-- DropBox         AppIcon dropping box
        +-- FrameBox        Framing or grouping box
        +-- Group           Triton's layout engine
        +-- Image           Image
        +-- Line            3D line
        +-- Listview        GadTools Listview
        +-- Palette         GadTools Palette gadget
        +-- Progress        Progress indicator
        +-- Scroller        GadTools Scroller
        +-- Slider          GadTools Slider
        +-- Space           Empty space
        +-- String          GadTools String gadget
        `-- Text            Text

Descriptions for all classes can be found in the Triton autodocs (see Introduction - Autodocs) under triton.library/class_<classname>.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.4 Autodocs

Documentation on all Triton classes and ‘triton.library’ functions can be found in the Triton autodocs file ‘Developer/Autodocs/triton.doc’. The function descriptions follow the usual syntax as used in the AmigaOS autodocs. The Triton classes are listed with the prefix triton.library/class_ and are described using the following keywords:


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2 Tutorial


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.1 Applications

In order to use ‘triton.library’ you must first of all open it, like any other shared library, as described in the Amiga ROM Kernel Reference Manual, volume Libraries. Before quitting, you have to close it again. Since release 1.1 ‘triton.library’ is a single-base library, so you can share one instance of ‘triton.library’ between several tasks. The following code makes sure that you can use functions from ‘triton.library’ release 1.2 or higher:

    #include <libraries/triton.h>
    #include <clib/triton_protos.h>
    #include <pragmas/triton_pragmas.h>

    struct Library *TritonBase;

    int main(void)
    {
      if(TritonBase=OpenLibrary(TRITONNAME,TRITON12VERSION))
      {
        /* Use functions from triton.library... */
        CloseLibrary(TritonBase);
      }
      else
      {
        /* React on the error... */
      }
      return 0;
    }

All Triton programs are based on a Triton application structure (struct TR_App). This structure is the connection which keeps all Triton parts of your application together. Before using any other Triton functions, you have to create a Triton application, and you must delete it again before your program quits (and before you close ‘triton.library’ of course). Any Triton application must have at least a short name, which is used by Triton to identify the application. All other tags are optional. A typical code segment could look like this:

    struct TR_App *myApp;

    if(myApp=TR_CreateAppTags(
      TRCA_Name,    "MyApp",
      TRCA_Release, "1.0",
      TRCA_Version, "42.113",
      TRCA_Date,    "3.11.94",
      TAG_END))
    {
      /* Use myApp for other Triton functions... */
      TR_DeleteApp(myApp);
    }
    else
    {
      /* React on the error... */
    }

The linker library ‘triton.lib’ offers an easier way to open ‘triton.library’ and create a Triton application structure. The two examples from above can be combined into the following short version:

    #include <libraries/triton.h>
    #include <proto/triton.h>

    int main(void)
    {
      if(TR_OpenTriton(TRITON12VERSION,
        TRCA_Name,    "MyApp",
        TRCA_Release, "1.0",
        TRCA_Version, "42.113",
        TRCA_Date,    "3.11.94",
        TAG_END))
      {
        /* The opened application is called 'Application' */
        TR_CloseTriton();
      }
      else
      {
        /* React on the error... */
      }
      return 0;
    }

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.2 Projects

A Triton Project is the next smaller entity of a Triton GUI. Currently a project contains exactly one Intuition window, but in future versions of Triton it could be possible to attach more windows to a project. Upon opening a project, you have to specify all objects which are to be displayed in the window, the window’s menu and some tags describing window properties.

At first you have to specify the window properties, then the menus and finally one (!) object. Normally this object will be a group which contains other objects or groups.

Note that all tags are optional. You may just as well open a window without any tags. This will result in a small window, consisting only of the close and depth gadget and a small dragging bar, being opened on the default public screen’s title bar.

As with naming Triton applications, you should give each project at least a unique ID which is used by Triton e.g. for remembering the window dimensions.

Opening and closing a project without any objects and menus could look like this:

    struct TagItem dummyTags=
    {
      TRWI_Title, (ULONG) "A dummy window",
      TRWI_ID,            42,
      TAG_END
    };

    void dummyFunction(void)
    {
      struct TR_Project *dummyProject;

      if(dummyProject=TR_OpenProject(Application,dummyTags))
      {
        /* Opened successfully */
        TR_CloseProject(dummyProject);
      }
      else
      {
        /* React on the error... */
      }
    }

Of course this way of opening a project via a static TagItem list doesn’t allow to insert object parameters or localized strings. Since you need these features most times, you should instead use a dynamical TagList which is built on the stack at runtime. Be sure to set a large enough stack! Some development systems offer an automatic stack setting in their startup code, which comes handy in those situations. Please do not rely on the user to set the stack!

And now back to our code, this time with a dynamic list. Imagine a function STRPTR GetLocStr(int num) which gives you a localized string.

    void dummyFunction(void)
    {
      struct TR_Project *dummyProject;

      if(dummyProject=TR_OpenProjectTags(Application,
        TRWI_Title, (ULONG) GetLocStr(MSG_WINTITLE_DUMMY),
        TRWI_ID,            42,
        TAG_END))
      {
        /* Opened successfully */
        TR_CloseProject(dummyProject);
      }
      else
      {
        /* React on the error... */
      }
    }

The ID 42 in the above examples has been chosen randomly. This is no problem as long as you stick to this ID in future updates of your application. Otherwise the window dimensions would be wrong and the user would have to adjust them again.

In order to not use IDs twice, it can be useful to enumerate them:

    enum windowIDs {WINID_DUMMY=1, WINID_FOO, WINID_BAR};

Note that window IDs must be different from 0. 0 is equal to no ID at all.

See the autodoc clip triton.library/TR_OpenProject() for details about the supported tags.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.3 Menus

Any project definiton may contain menus. The menu tags must follow the window tags immediately, before the object tags. If a menu has got an object ID, the TRAT_ID tag must be the last one in the menu definition. Object IDs are more than Project IDs. Project IDs are used only internally by Triton. As an application programmer, you have to reference Projects by a pointer to their struct TR_Project. Objects instead are not referenced through pointers, but only through object IDs. The same is true for menus, which use ordinary object IDs.

A typical menu defintion could look like this:

    TR_OpenProjectTags(...
      TRMN_Title,   (ULONG) "Project",
        TRMN_Item,  (ULONG) "?_About",       TRAT_ID, 1,
        TRMN_Item,  (ULONG) TRMN_BARLABEL,   TRAT_ID, 2,
        TRMN_Item,  (ULONG) "Q_Quit",        TRAT_ID, 3,
      ...);

The title of a menu item or sub-item can be TRMS_BARLABEL to insert a standard separator bar. Keyboard shortcuts can be specified by beginning the menu label with the shortcut key followed by an underscore character and the real menu label. These simple shortcuts (with the right Amiga key) are processed automatically. You can create a so-called ’extended shortcut’ by starting a label with an underscore character, then the text for the shortcut, another underscore and the menu label. These extended shortcuts are only displayed with AmigaOS 3.0 or higher and they are not managed automatically. You have to listen to incoming keyboard events in order to handle these shortcuts yourself.

See the Menus window of the Triton demo application for a more detailed example on menus.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.4 Objects

The heart of every Triton GUI are the objects. Currently only instances of subclasses of the DisplayObject class can be created. See section Introduction - Class Tree, for a short list of all classes. Detailed descriptions can be found in the autodocs.

Objects are created by inserting an object tag into a project definition. For example, a checked CheckBox object with an ID of 99 can be created the following way:

    TROB_CheckBox,   NULL,
      TRAT_Value,    (ULONG) TRUE,
      TRAT_ID,       99,

All available tags are listed in the autodocs. The <Default> tag’s value has to be inserted directly in the TROB_<Class> tag as its data. All other tags are inserted normally after the initial class tag.

Note: It is useful to enumerate object IDs just like project IDs. But in contrast to project IDs, object IDs may be used more than once. If you use an object ID several times within the same project, the objects with that ID will be linked together and whenever an attribute (only selected attributes, notably TRAT_Value!) of one object changes, this change will be broadcast to all other objects with that ID as if you had notified them yourself with TR_SetAttribute(). This is particularly useful to link a CheckBox gadget and a checkable menu item together.

See the Connections window of the Triton demo application for a more detailed example on attribute broadcasting.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.5 Layout

One of the most important classes is Group. It implements Triton’s layout engine.

Group objects offer two kinds of directions:

  1. Horizontal (primary direction; secondary direction is vertical). Created with TRGR_Horiz.
  2. Vertical (primary direction; secondary direction is horizontal) Created with TRGR_Vert.

3 different layout types are available for each instance of Group (adjustable with the group flags). They affect the primary direction only:

  1. TRGR_PROPSHARE: Divides all objects proportionally to their minimum size. All spaces retain their minimum size and are not resizable. Non-resizable non-space objects do also stick to their minimum sizes (well, they don’t really have a choice, do they? ;).
  2. TRGR_EQUALSHARE: Same as TRGR_PROPSHARE except that all non-space objects have the same size. Their minimum size equals the biggest minimum size of the individual objects.
  3. TRGR_PROPSPACES: All non-space objects retain their minimum sizes all the time and do not get stretched. Instead the spaces are stretched proportionally to their minimum sizes.
  4. TRGR_ARRAY: This group builds the top group of an array. In order to create an array, you have to set up an outer TRGR_ARRAY group (horizontal for a column array, vertical for a line array) and fill it with single objects (notably spaces) or TRGR_PROPSHARE groups in the opposite direction. All elements of the inner groups will be aligned to build an array. Inner groups which have the flag TRGR_INDEP set will not be aligned. They are mainly used to insert named separator bars (created with TROB_Line and TROB_Text) into an array.

Currently the only objects which are treated as spaces in the above scheme are instances of class Space.

The behaviour of the group in its secondary direction can be changed, too. Two additional flags are available for that purpose. In most cases you may want to set both of them:

  1. TRGR_ALIGN: All resizable objects (i.e. resizable in the secondary dimension of the group) are strechted to fit the full space occupied by the group.
  2. TRGR_CENTER: All non-resizable objects are centered in the group. Without this flag they get aligned to the left or top border.

It is also possible to keep a group at its minimum size and don’t allow it to be stretched in either or both directions. This can be accomplished with the TRGR_FIXHORIZ and TRGR_FIXVERT flags.

A group can be created like any other object. It takes other objects as its arguments. Every group has to be terminated with a TRGR_End tag. A typical horizontal group, which contains a CheckBox, a space and again a CheckBox, would look like this:

    TRGR_Horiz,      TRGR_PROPSHARE|TRGR_ALIGN|TRGR_CENTER,

      TROB_CheckBox, 0,
        TRAT_ID,     1,

      TROB_Space,    TRST_NORMAL,

      TROB_CheckBox, 0,
        TRAT_Value,  TRUE,
        TRAT_ID,     2,

      TRGR_End,      0

See the Groups window of the Triton demo application for a more detailed example on groups and arrays.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.6 Macros

The C header file ‘Developer/Include/libraries/triton.h’ contains quite a lot of macro definitions which make creating a Triton GUI much easier. With the help of the preprocessor Mac2E these macros are also available in AmigaE. Other languages or compilers may support similar or different macros or none at all. If no macros are available in your development system, you have to do it the traditional way. If you can use macros, use them.

The static taglist definition can be written a bit simpler with macros:

    ProjectDefinition(dummyTags)
    {
      /* Insert project tags here */
    };

But the main use for macros are the tags themselves. For example, the tags from the dummy window example (see Tutorial - Projects) would look like this:

      WindowTitle("A dummy window"),
      WindowID(42),
      EndProject

Have a look at the macro definitions and the supplied demo applications for more detailed information about the macros.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.7 Polling Loop

After creating a GUI you have to handle user input. In order to accomplish this task, Triton offers a polling system which resembles the Intuition IDCMP polling system very much. A basic polling loop looks like this:

    void handleDummyWindow(void)
    {
      BOOL closeMe=FALSE;
      struct TR_Message *trMsg;

      /* Open the window... */

      while(!closeMe)
      {
        TR_Wait(Application,NULL);
        while(trMsg=TR_GetMsg(Application))
        {
          switch(trMsg->trm_Class)
          {
            case TRMS_CLOSEWINDOW:
              closeMe=TRUE;
              break;

            case TRMS_ACTION:
              switch(trmsg->trm_ID)
              {
                case ID_FOO:
                  /* Do something... */
                  break;
                case ID_BAR:
                  /* Do something... */
                  break;
              }
              break;

            case TRMS_NEWVALUE:
              switch(trMsg->trm_ID)
              {
                /* New value is in trMsg->trm_Data */

                case ID_MYCHECKBOX:
                  /* Do something... */
                  break;
                case ID_MYSLIDER:
                  /* Do something... */
                  break;
              }
              break;

            case TRMS_ERROR:
              puts(TR_GetErrorString(trMsg->trm_Data));
              break;
          }
          TR_ReplyMsg(trMsg);
        }
      }

      /* Close the window... */
    }

Note: Don’t forget to reply all messages!

You could add a switch() for the project which sent the message if you have more than one project opened, but a better way is to use unique object IDs. This does also yield the advantage that moving an object from one window to another does not require any change in the message handling.

It is currently not very well documented which messages are sent by the different objects. As a general rule, activatable objects send TRMS_ACTION and objects which have a TRAT_Value or a similar modifiable tag, send TRMS_NEWVALUE.

Here is a more detailed description of the message types:

A description of all fields of the TR_Message structure can be found in the C header file ‘Developer/Include/libraries/triton.h’.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.8 Messages

Sometimes you may wish to query an object’s attribute directly without waiting in a polling loop and then putting it down somewhere else. This is especially useful for string gadgets. You should not read their contents when you receive a TRMS_NEWVALUE message, because it is possible to exit a string gadget without triggering such a message. Instead you have to read the contents directly before you need them.

Attributes can be read with the TR_GetAttribute() function, which will return the value of an object’s or project’s attribute. Specify the object’s ID or 0 for a project attribute. You can get the default attribute of an object by setting Attribute to 0. Otherwise set it to an attribute tag.

Setting a new attribute works just the same way with the function TR_SetAttribute(). Again you may also modify project attributes. See the autodoc clip for a list of them. After setting a new attribute the on-screen representation of it will be updated if necessary.

If you want to send custom object messages (TR_SetAttribute() and TR_GetAttribute() invoke the messages TRDM_SETATTRIBUTE and TRDM_GETATTRIBUTE), you have to use TR_SendMessage(). The autodocs will tell you which classes accept which messages.

Note: Do not confuse Object Messages (TROM_...) which are sent to Triton objects with Triton messages (TRMS_...) which you receive in your polling loop.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.9 Help

Triton offers two ways of providing help for the user of a Triton application:


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.10 Requesters

Triton offers two requester functions:

Please consult the autodocs for more detailed information about these functions. The main demo application contains examples for both types of requesters.

If you need a more sophisticated requester (e.g. a string requester), you have to use your own message polling loop (see Tutorial - Polling Loop). You may still use the requester macros though.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3 Style Guide


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.1 Guidelines

Please keep the following general rules in mind when designing and implementing a GUI with Triton:


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4 Odds & Ends


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.1 FAQ

Here are some frequesntly asked questions and their answers:

  1. Q: Why shouldn’t I use a simple TR_Wait() for dummy windows?

    A: Triton has to process inputs from Intuition. This is done in TR_GetMsg(). But of course you have to call this functions so that Triton can process its input. After TR_Wait() returns, you have to run though a while(TR_GetMsg()) loop as usual. An easier way to create a dummy window is using TR_AutoRequest().

  2. Q: How do I handle a progress indicator?

    A: As already explained in answer 1, you have to call TR_GetMsg() regularly. When a progress indicator is displayed, you should update it regularly and run through a while(TR_GetMsg()) loop every time. See the supplied Progress Indicator demo application for details.

  3. Q: How do I activate a string gadget?

    A: Beginning with Triton 1.3 (V4) you can use TR_SendMessage(Project,ID,TROM_ACTIVATE,NULL).


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

Index

Jump to:   A   C   F   G   H   I   L   M   N   O   P   Q   R   S   T  
Index Entry  Section

A
Answers 4.1 FAQ
Applications 2.1 Applications
Attribute 2.8 Messages
Autodocs 1.4 Autodocs

C
Class Tree 1.3 Class Tree

F
FAQ 4.1 FAQ
Frequently Asked Questions 4.1 FAQ

G
Get 2.8 Messages
Guide, Style 3.1 Guidelines
Guidelines 3.1 Guidelines

H
Help 2.9 Help

I
Introduction 1 Introduction

L
Layout 2.5 Layout
Linking 2.4 Objects
Loop, Polling 2.7 Polling Loop

M
Macros 2.6 Macros
Menus 2.3 Menus
Message 2.8 Messages
Modify 2.8 Messages

N
Notification 2.4 Objects

O
Objects 2.4 Objects
OOP Internals 1.2 OOP Internals
Overview 1.1 Overview

P
Polling Loop 2.7 Polling Loop
Projects 2.2 Projects

Q
Query 2.8 Messages
Questions 4.1 FAQ
QuickHelp 2.9 Help

R
Requesters 2.10 Requesters

S
Set 2.8 Messages
Style Guide 3.1 Guidelines

T
Tutorial 2 Tutorial

Jump to:   A   C   F   G   H   I   L   M   N   O   P   Q   R   S   T  

[Top] [Contents] [Index] [ ? ]

Table of Contents


[Top] [Contents] [Index] [ ? ]

About This Document

This document was generated on August 25, 2024 using texi2html 5.0.

The buttons in the navigation panels have the following meaning:

Button Name Go to From 1.2.3 go to
[ << ] FastBack Beginning of this chapter or previous chapter 1
[ < ] Back Previous section in reading order 1.2.2
[ Up ] Up Up section 1.2
[ > ] Forward Next section in reading order 1.2.4
[ >> ] FastForward Next chapter 2
[Top] Top Cover (top) of document  
[Contents] Contents Table of contents  
[Index] Index Index  
[ ? ] About About (help)  

where the Example assumes that the current position is at Subsubsection One-Two-Three of a document of the following structure:


This document was generated on August 25, 2024 using texi2html 5.0.