Copyright (c) Hyperion Entertainment and contributors.
Programming AmigaOS 4: GUI Toolkit ReAction
This article was adapted from Amiga Future magazine's series on developing for AmigaOS....
We mainly worked with shell programs or simple windows in the previous parts of this workshop. However, today's topic will be how to create a completely interactive GUI.
For this purpose we will use ReAction, which provides great flexibility for defined windows and controls that lay themselves out automatically. But before we dive into this subject, let us take a look at the past and see how interface development on the Amiga has changed over the years.
Contents
History
With Kickstart 1.x you had to create gadgets (the controls, which were back then - a button, a panel and a slide bar) directly as a structure and connect them with each other as well as calculate their positions. This procedure was very time consuming and a different font or another window size could sometimes cause significant trouble. Therefore, the gadtools.library, which was supplied with Kickstart 2.x, greatly simplified the creation of gadgets and menus. Additionally, a great number of new gadget types (e.g. ListView, Checkbox, Cycle) was launched. However, there was still a problem with the fixed positions. In this step the BOOPSI (Basic Object Oriented Programming System for Intuition) was also created. It offered an object-orientated approach, that could readily be used with Workbench 3.5 in the form of ReAction gadgets. This made it possible for windows to lay themselves out correctly automatically. That means that the gadgets automatically re-position themselves and their size is adjusted, if needed, when the window size is changed. The calculation of the minimized window size when opening a window is handled automatically by the system.
The end of Gadtools
By introducing ReAction all gadget types from the gadtools.library became superfluous. The same procedure is still used with AmigaOS 4, but this time it is used to create menus. All the functions required to create and layout menus are now available in the window class and no longer need to be made automatically. In other words, gadtools.library no longer has this role to perform!
A side note: the MUI (Magic User Interface) is used as a second GUI library and it is provided with the Operating System since AmigaOS 4. However, it remains an external toolkit. Its standard appearance has been made in the style of AmigaOS 4 so it would not look like an 'alien element'. In principle, it applies the same approach as for ReAction, but it is programmed differently.
ReAction step by step
After that brief introduction it is now time for our first example, a window with a gadget and a menu. What used to take a long time, is now done in just a few steps. These necessary steps will be explained here in detail, because you can create big applications with them as well.
All ReAction objects (gadgets, window and Requester) are set up with IIntuition->NewObject(). The result is a generic 'Object' pointer. However, most of the old functions still expect a pointer on a gadget structure (or a window structure), so that you must decide whether you want to cast the return value immediately, or once you activate the respective functions. There is no standard notation in SDK at the moment. Right now, casting the result pointer is the best option. This way you can immediately see what it is about, in case you have selected an unfavourable name for the variable. You can create a button as follows:
struct Gadget *gb_ButtonGad; #define GAD_ID_Quit 2 if((gb_ButtonGad = (struct Gadget *) IIntuition->NewObject(IButton->BUTTON_GetClass(),NULL, GA_ID, GAD_ID_Quit, GA_RelVerify, TRUE, GA_Text, "_end", TAG_DONE)))
There is an example for various gadget classes at the end of this article. The GA_xxx tags are general and applicable to all kinds of gadgets. A specific gadget for a button would be, for instance, BUTTON_BevelStyle, which you can find under "gadgets/...". With the underscore in the button text the shortcut is defined, which can start the button without a mouse.
You can also use the same procedure to create a window, but this time you must use the WINDOW_xxx Defines from "classes/window.h". In addition, you can also use a great number of old WA tags.
Object *gb_WindowObj; if((gb_WindowObj = (Object *) IIntuition->NewObject(IWindow->WINDOW_GetClass(),NULL, WA_IDCMP, IDCMP_GADGETUP | IDCMP_CLOSEWINDOW | IDCMP_MENUPICK, WA_SizeGadget, TRUE, WA_DepthGadget, TRUE, WA_DragBar, TRUE, WA_CloseGadget, TRUE, WA_Activate, TRUE, WA_Title, "Example with reaction gadgets and window class", WINDOW_Position, WPOS_CENTERSCREEN,
A ReAction window requires implicitly a layout object, which automatically handles the size adjustment and distribution of the individual gadgets. In our example with only one gadget we need a central layout method. The layout object serves the horizontal and vertical arrangement of several gadgets within the window. This way, you can also realise very complex layouts by dividing them into horizontal and vertical groups.
struct Gadget *gb_MainLayout; WINDOW_ParentGroup, gb_MainLayout = (struct Gadget *) IIntuition->NewObject(ILayout->LAYOUT_GetClass(),NULL, LAYOUT_Orientation, LAYOUT_ORIENT_VERT, LAYOUT_SpaceOuter, TRUE, LAYOUT_SpaceInner, TRUE, LAYOUT_AddChild, gb_ButtonGad, TAG_DONE), TAG_DONE)))
As already mentioned, creating menus has become a very simple task in the meantime. All you need to do is create the NewMenu structure (from "libraries/gadtools.h") dating from gadtools times, which describes the individual menu points. This structure is given then when you create the window object. You no longer need to take care of deleting the menu structure; this happens automatically when the window object is released.
struct NewMenu gb_MenuDescribe[] = { { NM_TITLE, "Project", NULL, 0, 0, NULL }, { NM_ITEM, "Quit", NULL, 0, 0, NULL }, { NM_END, NULL, NULL, 0, 0, NULL } }; #define MENU_ID_Quit FULLMENUNUM(0,0,NOSUB) IIntuition->NewObject(IWindow->WINDOW_GetClass(), WINDOW_NewMenu, gb_MenuDescribe,
Since AmigaOS 4's release the ReAction gadgets have been included in the BubbleHelp. If you move the mouse cursor over such an element, a bubble with help text will be displayed soon afterwards. You need to do just a little bit of programming for this. Mainly, you must fill out the HintInfo structure from "classes/window.h":
struct HintInfo gb_HintInfo[] = { { GAD_ID_Help, -1, "activate/deactivate the BubbleHelp hints", 0 }, { GAD_ID_Quit, -1, "quit program", 0 }, { -1, -1, NULL, 0 } };
The fourth value is reserved for the future flags and a 0 is assigned to it at the moment. The structure must be indicated when you create the window object.
IIntuition->NewObject(IWindow->WINDOW_GetClass(), WINDOW_HintInfo, gb_HintInfo, WINDOW_GadgetHelp, TRUE,
With the WINDOW_GadgetHelp you can turn on/off the help. With 'WINDOW_GadgetHelp, FALSE' you can deactivate it, so it will not be displayed again. With TRUE you can re-activate it. You can change this tag during runtime. Other settings such as influencing the waiting time until the display, the display duration, the colour, etc. are still not possible, but users should be able to change them by using a global Prefs adjuster in the future.
IIntuition->SetAttrs(gb_WindowObj, WINDOW_GadgetHelp, FALSE, TAG_DONE);
We will add a checkbox to the sample program in order to put this possibility to use. We can turn on and off the help any time with it. In reality, you will set this option on a menu point or in the program settings, if there are any. A tooltype in the icon information is also an alternative.
struct Gadget *gb_CheckboxGad; #define GAD_ID_Help 1 if((gb_CheckboxGad = (struct Gadget *) IIntuition->NewObject(ICheckBox->CHECKBOX_GetClass(),NULL, GA_ID, GAD_ID_Help, GA_RelVerify, TRUE, GA_Text, "Bubble_Help active", TAG_DONE))) WINDOW_ParentGroup, LAYOUT_AddChild, gb_CheckboxGad,
All GUI elements are now created, but they are still not visible. You should certainly check, whether the window pointer is present. If not, a gadget could probably not be created. To display the window you can use the RA_OpenWindow() macros from "reaction/reaction_macros.h", to close it RA_CloseWindow() and to edit news RA_HandleInput().
Since these are macros, you cannot use the typical interface notation. The news editing loop looks in practice as follows:
if((gb_Win = RA_OpenWindow(gb_WindowObj))) { ULONG winsig; IIntuition->GetAttr(WINDOW_SigMask,gb_WindowObj,&winsig); BOOL run = TRUE; while(run) { ULONG result, code, val; const ULONG sigs = IExec->Wait(winsig | SIGBREAKF_CTRL_C); while((result = RA_HandleInput(gb_WindowObj,&code)) != WMHI_LASTMSG) { switch(result & WMHI_CLASSMASK) { case WMHI_GADGETUP: switch(result & WMHI_GADGETMASK) { case GAD_ID_Help: IIntuition->GetAttr(CHECKBOX_Checked,gb_CheckboxGad,(ULONG*)&val); IIntuition->SetAttrs(gb_WindowObj, WINDOW_GadgetHelp, val, TAG_DONE); break; case GAD_ID_Quit: run = FALSE; break; } break; case WMHI_CLOSEWINDOW: run = FALSE; break; case WMHI_MENUPICK: switch(result & WMHI_MENUMASK) { case MENU_ID_Quit: run = FALSE; break; } break; } } if(sigs & SIGBREAKF_CTRL_C) run = FALSE; } RA_CloseWindow(gb_WindowObj); }
You can see the various news types like press gadget (WMHI_GADGETUP), select menu (WMHI_MENUPICK) and the closing symbol for the window (WMHI_CLOSEWINDOW). But you can only get news, which has been defined explicitly as IDCMP_xxx Bits when creating the window.
To close the program, that is, to release all created objects all you need to do is activate IIntuition->DisposeObject(). It automatically makes sure that all elements included in the object are also released. If you specify the window pointer here, all included gadgets, menus and helptexts will be also deleted and can no longer be used!
IIntuition->DisposeObject(gb_WindowObj);
What is missing now are only the Includes and a main function. Then the program is complete and can be found as an example below.
ReAction Example
/* Michael Christoph * ReActionEx.c * * gcc ReActionEx.c -o ReActionEx -l auto */ /******************************* INCLUDES *************************************/ #include <intuition/gadgetclass.h> #include <classes/window.h> #include <reaction/reaction_macros.h> #include <libraries/gadtools.h> #include <gadgets/checkbox.h> #include <proto/exec.h> #include <proto/dos.h> #include <proto/intuition.h> #include <proto/window.h> #include <proto/layout.h> #include <proto/button.h> #include <proto/checkbox.h> #define MENU_ID_Quit FULLMENUNUM(0,0,NOSUB) #define GAD_ID_Help 1 #define GAD_ID_Quit 2 /******************************************************************************/ static const char *version USED = "\0$VER: ReActionEx 1.00 (16.12.2004) - (c) Dez.2004 by Meicky-Soft\n"; /******************************************************************************/ Object *gb_WindowObj; struct Window *gb_Win; struct Gadget *gb_MainLayout; struct Gadget *gb_ButtonGad; struct Gadget *gb_CheckboxGad; struct NewMenu gb_MenuDescribe[] = { { NM_TITLE, "Project", NULL, 0, 0, NULL }, { NM_ITEM, "Quit", NULL, 0, 0, NULL }, { NM_END, NULL, NULL, 0, 0, NULL } }; struct HintInfo gb_HintInfo[] = { { GAD_ID_Help, -1, "Activate/Deactive BubbleHelp Tips", 0 }, { GAD_ID_Quit, -1, "Quit Program", 0 }, { -1, -1, NULL, 0 } }; /******************************************************************************/ int main() { /* ein Checkbox-Gadget erzeugen */ if((gb_CheckboxGad = (struct Gadget *) IIntuition->NewObject(ICheckBox->CHECKBOX_GetClass(),NULL, GA_ID, GAD_ID_Help, GA_RelVerify, TRUE, GA_Text, "Bubble_Help Active", TAG_DONE))) { /* den Button erzeugen */ if((gb_ButtonGad = (struct Gadget *) IIntuition->NewObject(IButton->BUTTON_GetClass(),NULL, GA_ID, GAD_ID_Quit, GA_RelVerify, TRUE, GA_Text, "_Quit", TAG_DONE))) { /* das Fenster-Objekt erzeugen */ if((gb_WindowObj = (Object *) IIntuition->NewObject(IWindow->WINDOW_GetClass(),NULL, WA_IDCMP, IDCMP_GADGETUP | IDCMP_CLOSEWINDOW | IDCMP_MENUPICK, WA_SizeGadget, TRUE, WA_DepthGadget, TRUE, WA_DragBar, TRUE, WA_CloseGadget, TRUE, WA_Activate, TRUE, WA_Title, "Example with ReAction gadgets and window class", WINDOW_Position, WPOS_CENTERSCREEN, WINDOW_NewMenu, gb_MenuDescribe, WINDOW_HintInfo, gb_HintInfo, WINDOW_GadgetHelp, FALSE, /* das Layout-Object erzeugen und im Fenster einhâ°ngen */ WINDOW_ParentGroup, gb_MainLayout = (struct Gadget *) IIntuition->NewObject(ILayout->LAYOUT_GetClass(),NULL, LAYOUT_Orientation, LAYOUT_ORIENT_VERT, LAYOUT_SpaceOuter, TRUE, LAYOUT_SpaceInner, TRUE, LAYOUT_AddChild, gb_CheckboxGad, LAYOUT_AddChild, gb_ButtonGad, TAG_DONE), TAG_DONE))) { /* das Fenster Ëffnen */ if((gb_Win = RA_OpenWindow(gb_WindowObj))) { /* Signalbit des Fensters erfragen */ ULONG winsig; IIntuition->GetAttr(WINDOW_SigMask,gb_WindowObj,&winsig); BOOL laufen = TRUE; while(laufen) { ULONG result, code, val; /* warten bis der Button oder das Schlieï¬symbol geklickt wird */ const ULONG sigs = IExec->Wait(winsig | SIGBREAKF_CTRL_C); /* die eingetroffenen Nachrichten verarbeiten */ while((result = RA_HandleInput(gb_WindowObj,&code)) != WMHI_LASTMSG) { /* den Nachrichtenanteil ausmaskieren ! */ switch(result & WMHI_CLASSMASK) { /* Gadget-Nachrichten auswerten */ case WMHI_GADGETUP: switch(result & WMHI_GADGETMASK) { case GAD_ID_Help: IIntuition->GetAttr(CHECKBOX_Checked, (Object*)gb_CheckboxGad, (ULONG*)&val); IIntuition->SetAttrs(gb_WindowObj, WINDOW_GadgetHelp, val, TAG_DONE); break; case GAD_ID_Quit: laufen = FALSE; break; } break; /* Fenster-Schlieï¬symbol auswerten */ case WMHI_CLOSEWINDOW: laufen = FALSE; break; /* Men¸auswahl auswerten */ case WMHI_MENUPICK: switch(result & WMHI_MENUMASK) { case MENU_ID_Quit: laufen = FALSE; break; } break; } } /* CTRL-C von der Shell erhalten ? */ if(sigs & SIGBREAKF_CTRL_C) laufen = FALSE; } /* Fenster schlieï¬en */ RA_CloseWindow(gb_WindowObj); } } } /* Window-Object freigeben, entsorgt auch Layout und Gadget-Objekte */ IIntuition->DisposeObject(gb_WindowObj); } return 0; }
AllReActionGadgets Example
We can deal with programming with ReAction here only in theory. But for this purpose we have put "AllReActionGadgets.c" as a bonus. Here all available gadgets are used and you can see how they can be created and queried. The use of page gadgets is also shown. In conjunction with the Clicktab gadget you can also realise tabs, which always show another 'page' with gadgets. For instance, you can divide comprehensive setting windows into individual pages.
/* Michael Christoph - Musterbeispiel */ /* AllGadgets - Programm mit allen Reaction-Gadgets unter OS4 */ /* ** gcc AllGadgets.c -o AllGadgets -l auto */ /************************** PROGRAMM-PARAMETER ********************************/ static const char *version = "\0$VER: AllGadgets 1.01 (14.04.2014) - (c) Apr.2014 by Meicky-Soft\n"; /******************************* INCLUDES *************************************/ #include <exec/types.h> #include <intuition/gadgetclass.h> #include <intuition/icclass.h> #include <classes/window.h> #include <classes/requester.h> #include <reaction/reaction_macros.h> #include <libraries/gadtools.h> #include <clib/macros.h> #include <gadgets/button.h> #include <gadgets/space.h> #include <gadgets/checkbox.h> #include <gadgets/listbrowser.h> #include <gadgets/string.h> #include <gadgets/integer.h> #include <gadgets/radiobutton.h> #include <gadgets/scroller.h> #include <gadgets/slider.h> #include <gadgets/getfile.h> #include <gadgets/getfont.h> #include <gadgets/getscreenmode.h> #include <gadgets/getcolor.h> #include <gadgets/chooser.h> #include <gadgets/texteditor.h> #include <gadgets/colorwheel.h> #include <gadgets/gradientslider.h> #include <gadgets/datebrowser.h> #include <gadgets/fuelgauge.h> #include <gadgets/listview.h> #include <gadgets/layout.h> #include <gadgets/clicktab.h> #include <gadgets/page.h> #include <gadgets/palette.h> #include <gadgets/virtual.h> #include <images/label.h> #include <images/bevel.h> #include <images/bitmap.h> #include <images/drawlist.h> #include <images/filler.h> #include <images/glyph.h> #include <images/penmap.h> #include <proto/exec.h> #include <proto/dos.h> #include <proto/intuition.h> #include <proto/graphics.h> #include <proto/utility.h> #include <proto/asl.h> #include <proto/locale.h> #include <proto/application.h> #include <proto/timer.h> #include <proto/window.h> #include <proto/layout.h> #include <proto/button.h> #include <proto/slider.h> #include <proto/scroller.h> #include <proto/space.h> #include <proto/label.h> #include <proto/integer.h> #include <proto/string.h> #include <proto/listbrowser.h> #include <proto/clicktab.h> #include <proto/chooser.h> #include <proto/radiobutton.h> #include <proto/checkbox.h> #include <proto/palette.h> #include <proto/datebrowser.h> #include <proto/fuelgauge.h> #include <proto/getfile.h> #include <proto/getfont.h> #include <proto/getscreenmode.h> #include <proto/getcolor.h> #include <proto/texteditor.h> #include <proto/colorwheel.h> #include <proto/label.h> #include <proto/bevel.h> #include <proto/bitmap.h> #include <proto/drawlist.h> #include <proto/filler.h> #include <proto/glyph.h> #include <proto/penmap.h> #include <string.h> /******************************************************************************/ enum GADIDs { GAD_ID_ButtonV, GAD_ID_Button, GAD_ID_String, GAD_ID_Integer, GAD_ID_Slider, GAD_ID_Scroller, GAD_ID_Chooser, GAD_ID_Chooser2, GAD_ID_Chooser3, GAD_ID_Checkbox, GAD_ID_Radio, GAD_ID_Listbrowser, GAD_ID_Palette, GAD_ID_File, GAD_ID_Font, GAD_ID_Screenmode, GAD_ID_Color, GAD_ID_Fuelgauge, GAD_ID_Colorwheel, GAD_ID_Gradientslider, GAD_ID_Texteditor, GAD_ID_Datebrowser, GAD_ID_Space, GAD_ID_Page, GAD_ID_Clicktab, GAD_ID_Pages, GAD_ID_PagesClicktab, }; /******************************************************************************/ struct List gb_List; struct ColumnInfo gb_ListbrowserColumn[] = { { 30, "Nummer", 0 }, { 170, "Eintrag", 0 }, { -1, (STRPTR)~0, (ULONG)-1 } }; struct Hook gb_RenderHook; struct Hook gb_IDCMPHook; STRPTR gb_ChooserLabels[] = { "Amiga 1000", "Amiga 1200", "AmigaOne", NULL }; STRPTR gb_Chooser2Labels[] = { "Amiga 1000", "Amiga 1200", "AmigaOne", NULL }; STRPTR gb_Chooser3Labels[] = { "Amiga 1000", "Amiga 1200", "AmigaOne", NULL }; STRPTR gb_RadioLabels[] = { "Amiga 1000", "Amiga 1200", "AmigaOne", NULL }; STRPTR gb_ClicktabLabels[] = { "Amiga 1000", "Amiga 1200", "AmigaOne", NULL }; STRPTR gb_PagesLabels[] = { "_Grundtypen","_Auswahllisten","ASL-Aus_wahl","Sonstige _Typen","_Seitengestalltung","_Images", NULL }; UWORD gb_GradientArray[] = { ~0, ~0, ~0, ~0, ~0, ~0, ~0 }; /******************************************************************************/ struct Gadget *gb_ButtonVGad; struct Gadget *gb_ButtonGad; struct Gadget *gb_StringGad; struct Gadget *gb_IntegerGad; struct Gadget *gb_SliderGad; struct Gadget *gb_ScrollerGad; struct Gadget *gb_ChooserGad; struct Gadget *gb_Chooser2Gad; struct Gadget *gb_Chooser3Gad; struct Gadget *gb_CheckboxGad; struct Gadget *gb_RadioGad; struct Gadget *gb_ListbrowserGad; struct Gadget *gb_PaletteGad; struct Gadget *gb_FileGad; struct Gadget *gb_FontGad; struct Gadget *gb_ScreenmodeGad; struct Gadget *gb_ColorGad; struct Gadget *gb_FuelgaugeGad; struct Gadget *gb_GradientsliderGad; struct Gadget *gb_ColorwheelGad; struct Gadget *gb_TexteditorGad; struct Gadget *gb_DatebrowserGad; struct Gadget *gb_SpaceGad; struct Gadget *gb_PageGad; struct Gadget *gb_ClicktabGad; struct Image *gb_LabelImg; struct Image *gb_BevelImg; struct Image *gb_BitmapImg; struct Image *gb_BitmapSImg; struct Image *gb_BitmapDImg; struct Image *gb_DrawlistImg; struct Image *gb_FillerImg; struct Image *gb_GlyphImg[27]; struct Image *gb_PenmapImg; struct Gadget *gb_MainLayout; struct Gadget *gb_Page1Layout; struct Gadget *gb_Page2Layout; struct Gadget *gb_Page3Layout; struct Gadget *gb_Page4Layout; struct Gadget *gb_Page5Layout; struct Gadget *gb_Page6Layout; struct Gadget *gb_PagesLayout; struct Gadget *gb_PagesClicktab; Object *gb_WindowObj; struct Window *gb_Win; struct Screen *gb_Scr; ULONG image_object_palette[] = { 2, 0x00000000, 0x00000000, 0x00000000, 0xEEEEEEEE, 0xDDDDDDDD, 0x00000000 }; UBYTE happy_data[] = { 0,16, 0,14, 0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0, 0,0,0,1,1,2,2,2,2,2,2,1,1,0,0,0, 0,0,1,2,2,2,2,2,2,2,2,2,2,1,0,0, 0,1,2,2,2,2,2,2,2,2,2,2,2,2,1,0, 0,1,2,2,2,1,1,2,2,1,1,2,2,2,1,0, 1,2,2,2,2,1,1,2,2,1,1,2,2,2,2,1, 1,2,2,2,2,1,1,2,2,1,1,2,2,2,2,1, 1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1, 1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1, 0,1,2,2,2,1,2,2,2,2,1,2,2,2,1,0, 0,1,2,2,2,2,1,1,1,1,2,2,2,2,1,0, 0,0,1,2,2,2,2,2,2,2,2,2,2,1,0,0, 0,0,0,1,1,2,2,2,2,2,2,1,1,0,0,0, 0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0 }; UBYTE scared_data[] = { 0,16, 0,14, 0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0, 0,0,0,1,1,2,2,2,2,2,2,1,1,0,0,0, 0,0,1,2,2,2,2,2,2,2,2,2,2,1,0,0, 0,1,2,2,2,1,1,2,2,1,1,2,2,2,1,0, 0,1,2,2,1,2,2,2,2,2,2,1,2,2,1,0, 1,2,2,2,2,1,1,2,2,1,1,2,2,2,2,1, 1,2,2,2,2,1,1,2,2,1,1,2,2,2,2,1, 1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1, 1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1, 0,1,2,2,2,2,1,1,1,1,2,2,2,2,1,0, 0,1,2,2,2,1,1,1,1,1,1,2,2,2,1,0, 0,0,1,2,2,2,2,2,2,2,2,2,2,1,0,0, 0,0,0,1,1,2,2,2,2,2,2,1,1,0,0,0, 0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0 }; struct DrawList gb_DrawList[] = { { DLST_LINE, 0,30,15,0, 1}, { DLST_LINE, 30,30,15,0, 1}, { DLST_LINE, 9,15,23,15, 1}, { DLST_END } }; /******************************************************************************/ BOOL CreateEntry(ULONG num, CONST_STRPTR number, CONST_STRPTR text) { /* einen Listeneintrag erzeugen */ /* ACHTUNG: ** diese Funktion darf nur verwendet werden, wenn die Liste *nicht* ** dem ListView zugewiesen ist ! Ggf. mittels ** SetGadgetAttrs(gad,win,NULL, LISTBROWSER_Labels,~0, TAG_DONE); ** aush‰ngen, dann die Liste bearbeiten und mittels ** SetGadgetAttrs(gad,win,NULL, LISTBROWSER_Labels,liste, TAG_DONE); ** die Liste wieder dem ListView zuweisen. */ struct Node *node; if((node = IListBrowser->AllocListBrowserNode(2, LBNA_Column, 0, LBNCA_Text, number, LBNCA_Justification, LCJ_LEFT, LBNCA_Editable, FALSE, LBNCA_CopyText, TRUE, LBNCA_MaxChars, 4, LBNA_Column, 1, LBNCA_Text, text, LBNCA_Justification, LCJ_LEFT, LBNCA_Editable, FALSE, LBNCA_CopyText, TRUE, LBNCA_MaxChars, 100, TAG_DONE))) { node->ln_Pri = num; IExec->AddTail(&gb_List,node); } else { IDOS->Printf("Speichermangel beim Erstellen von Listeneintrag\n"); } return( node ? TRUE : FALSE ); } /******************************************************************************/ void FreigebenList() { /* die Liste mit allen Daten freigeben */ /* ACHTUNG: ** diese Funktion darf nur verwendet werden, wenn die Liste *nicht* ** dem ListView zugewiesen ist ! Ggf. mittels ** SetGadgetAttrs(gad,win,NULL, LISTBROWSER_Labels,~0, TAG_DONE); ** aush‰ngen, dann die Liste bearbeiten und mittels ** SetGadgetAttrs(gad,win,NULL, LISTBROWSER_Labels,liste, TAG_DONE); ** die (leere) Liste wieder dem ListView zuweisen. */ struct Node *node, *nextnode; node = gb_List.lh_Head; while((nextnode = node->ln_Succ)) { IExec->Remove(node); IListBrowser->FreeListBrowserNode(node); node = nextnode; } } /******************************************************************************/ void RenderHookFunc(struct Hook *hook, Object *obj, struct gpRender *gpr) { /* ** Hook-Funktion zum Refreshen des Space-Gadgets */ /* nur wenn das Fenster sichtbar ist, d¸rfen wir hineinzeichnen */ if(gb_Win) { /* die Grˆfle unseres Ausgabebereiches ermitteln */ struct IBox *gb_DrawArea; IIntuition->GetAttr(SPACE_AreaBox,(Object*)gb_SpaceGad,(ULONG *)&gb_DrawArea); /* die komplette Fl‰che leeren mit der Hintergrundfarbe */ IGraphics->SetAPen(gpr->gpr_RPort,0); IGraphics->RectFill(gpr->gpr_RPort,gb_DrawArea->Left,gb_DrawArea->Top,gb_DrawArea->Left+gb_DrawArea->Width-1,gb_DrawArea->Top+gb_DrawArea->Height-1); } } /******************************************************************************/ void IDCMPHookFunc(struct Hook *hook, Object *winobj, struct IntuiMessage *msg) { /* ** Hook-Funktion zum Abhˆren der IDCMP_UPDATE-Nachrichten */ struct TagItem *taglist = (struct TagItem *) msg->IAddress; const LONG gadid = IUtility->GetTagData(GA_ID,-1,taglist); if(msg->Class == IDCMP_GADGETDOWN) { /* Maus gedr¸ckt: Startposition setzen ohne zu zeichnen */ IGraphics->SetAPen(gb_Win->RPort,4); IGraphics->Move(gb_Win->RPort,msg->MouseX,msg->MouseY); } if(msg->Class == IDCMP_IDCMPUPDATE && gadid == GAD_ID_Space) { //ULONG mx, my; //IIntuition->GetAttr(SPACE_MouseX,gb_SpaceGad,(ULONG*)&mx); //IIntuition->GetAttr(SPACE_MouseY,gb_SpaceGad,(ULONG*)&my); /* die Grˆfle unseres Ausgabebereiches ermitteln */ /* damit wird nicht aus diesem Bereich hinaus zeichnen */ struct IBox *gb_DrawArea; IIntuition->GetAttr(SPACE_AreaBox,(Object*)gb_SpaceGad,(ULONG *)&gb_DrawArea); const LONG mx = msg->MouseX; const LONG my = msg->MouseY; if(mx >= gb_DrawArea->Left && my >= gb_DrawArea->Top && mx <= gb_DrawArea->Left+gb_DrawArea->Width-1 && my <= gb_DrawArea->Top+gb_DrawArea->Height-1) { IGraphics->Draw(gb_Win->RPort,msg->MouseX,msg->MouseY); } } } /******************************************************************************/ BOOL CreateAll() { int i; /* Bildschim-Zeiger wird f¸r einzelne Gadgets benˆtigt */ gb_Scr = IIntuition->LockPubScreen(NULL); if(gb_Scr) { /* Zeichenstifte f¸r den Gradientslider anfordern und setzen */ struct ColorMap *cm = gb_Scr->ViewPort.ColorMap; gb_GradientArray[0] = IGraphics->ObtainPen(cm,~0,0xFF,0xFF,0xFF,PENF_EXCLUSIVE); gb_GradientArray[1] = IGraphics->ObtainPen(cm,~0,0xCC,0xCC,0xCC,PENF_EXCLUSIVE); gb_GradientArray[2] = IGraphics->ObtainPen(cm,~0,0x99,0x99,0x99,PENF_EXCLUSIVE); gb_GradientArray[3] = IGraphics->ObtainPen(cm,~0,0x66,0x66,0x66,PENF_EXCLUSIVE); gb_GradientArray[4] = IGraphics->ObtainPen(cm,~0,0x33,0x33,0x33,PENF_EXCLUSIVE); gb_GradientArray[5] = IGraphics->ObtainPen(cm,~0,0x00,0x00,0x00,PENF_EXCLUSIVE); struct ViewPort *vp = &gb_Scr->ViewPort; if((WORD)gb_GradientArray[0] != ~0) IGraphics->SetRGB4(vp,gb_GradientArray[0],0xFF,0xFF,0xFF); if((WORD)gb_GradientArray[1] != ~0) IGraphics->SetRGB4(vp,gb_GradientArray[1],0xCC,0xCC,0xCC); if((WORD)gb_GradientArray[2] != ~0) IGraphics->SetRGB4(vp,gb_GradientArray[2],0x99,0x99,0x99); if((WORD)gb_GradientArray[3] != ~0) IGraphics->SetRGB4(vp,gb_GradientArray[3],0x66,0x66,0x66); if((WORD)gb_GradientArray[4] != ~0) IGraphics->SetRGB4(vp,gb_GradientArray[4],0x33,0x33,0x33); if((WORD)gb_GradientArray[5] != ~0) IGraphics->SetRGB4(vp,gb_GradientArray[5],0x00,0x00,0x00); } /* Listbrowser-Eintr‰ge erzeugen */ IExec->NewList(&gb_List); CreateEntry(0,"1","Amiga 1000"); CreateEntry(1,"2","Amiga 1200"); CreateEntry(2,"3","AmigaOne"); /* RenderHook initialisieren */ gb_RenderHook.h_Entry = (ULONG (*)())RenderHookFunc; gb_RenderHook.h_SubEntry = NULL; /* IDCMPHook initialisieren zum Abhˆren der IDCMP_UPDATE-Nachrichten */ gb_IDCMPHook.h_Entry = (ULONG (*)())IDCMPHookFunc; gb_IDCMPHook.h_SubEntry = NULL; /* Gadget-Objekt erzeugen */ gb_ButtonVGad = (struct Gadget *) IIntuition->NewObject(IButton->BUTTON_GetClass(),NULL, BUTTON_BevelStyle, BVS_THIN, BUTTON_Justification, BCJ_LEFT, GA_ID, GAD_ID_ButtonV, GA_Text, "Info-Anzeige", GA_ReadOnly, TRUE, TAG_DONE); gb_ButtonGad = (struct Gadget *) IIntuition->NewObject(IButton->BUTTON_GetClass(),NULL, GA_ID, GAD_ID_Button, GA_Text, "Button", TAG_DONE); gb_StringGad = (struct Gadget *) IIntuition->NewObject(IString->STRING_GetClass(),NULL, GA_ID, GAD_ID_String, GA_RelVerify, TRUE, GA_TabCycle, TRUE, STRINGA_MaxChars, 30+1, STRINGA_MinVisible, 30, STRINGA_TextVal, "Amiga 1000", TAG_DONE); gb_IntegerGad = (struct Gadget *) IIntuition->NewObject(IInteger->INTEGER_GetClass(),NULL, GA_ID, GAD_ID_Integer, GA_RelVerify, TRUE, GA_TabCycle, TRUE, INTEGER_MaxChars, 4, INTEGER_Arrows, TRUE, INTEGER_MinVisible, 3, INTEGER_Minimum, 1, INTEGER_Maximum, 100, TAG_DONE); gb_SliderGad = (struct Gadget *) IIntuition->NewObject(ISlider->SLIDER_GetClass(),NULL, GA_ID, GAD_ID_Slider, GA_Immediate, TRUE, GA_RelVerify, TRUE, SLIDER_Min, 0, SLIDER_Max, 100, SLIDER_Level, 10, SLIDER_Orientation, SLIDER_HORIZONTAL, SLIDER_Ticks, 11, SLIDER_KnobDelta, 50, SLIDER_LevelFormat, "%3ld", SLIDER_LevelMaxLen, 3+1, SLIDER_LevelPlace, PLACETEXT_IN, TAG_DONE); gb_ScrollerGad = (struct Gadget *) IIntuition->NewObject(IScroller->SCROLLER_GetClass(),NULL, GA_ID, GAD_ID_Scroller, GA_Immediate, TRUE, GA_RelVerify, TRUE, SCROLLER_Top, 1, SCROLLER_Visible, 5, SCROLLER_Total, 105, SCROLLER_Orientation, SCROLLER_HORIZONTAL, SCROLLER_Arrows, TRUE, SCROLLER_Stretch, TRUE, SCROLLER_ArrowDelta, 10, TAG_DONE); gb_ChooserGad = (struct Gadget *) IIntuition->NewObject(IChooser->CHOOSER_GetClass(),NULL, GA_ID, GAD_ID_Chooser, GA_RelVerify, TRUE, GA_Underscore, '#', CHOOSER_PopUp, TRUE, CHOOSER_DropDown, FALSE, CHOOSER_LabelArray, gb_ChooserLabels, CHOOSER_Selected, 0, CHOOSER_MaxLabels, 10, TAG_DONE); gb_Chooser2Gad = (struct Gadget *) IIntuition->NewObject(IChooser->CHOOSER_GetClass(),NULL, GA_ID, GAD_ID_Chooser2, GA_RelVerify, TRUE, GA_Underscore, '#', CHOOSER_PopUp, FALSE, CHOOSER_DropDown, TRUE, CHOOSER_Title, "Eintr‰ge", CHOOSER_LabelArray, gb_Chooser2Labels, CHOOSER_Selected, 0, CHOOSER_MaxLabels, 10, TAG_DONE); gb_Chooser3Gad = (struct Gadget *) IIntuition->NewObject(IChooser->CHOOSER_GetClass(),NULL, GA_ID, GAD_ID_Chooser3, GA_RelVerify, TRUE, GA_Underscore, '#', CHOOSER_PopUp, FALSE, CHOOSER_DropDown, TRUE, CHOOSER_LabelArray, gb_Chooser3Labels, CHOOSER_Selected, 0, CHOOSER_MaxLabels, 10, TAG_DONE); gb_CheckboxGad = (struct Gadget *) IIntuition->NewObject(ICheckBox->CHECKBOX_GetClass(),NULL, GA_ID, GAD_ID_Checkbox, GA_Text, "Anwahl", CHECKBOX_TextPlace, PLACETEXT_RIGHT, CHECKBOX_Checked, TRUE, TAG_DONE); gb_RadioGad = (struct Gadget *) IIntuition->NewObject(IRadioButton->RADIOBUTTON_GetClass(),NULL, GA_ID, GAD_ID_Radio, GA_RelVerify, TRUE, GA_Text, gb_RadioLabels, //RADIOBUTTON_LabelArray, gb_RadioLabels, RADIOBUTTON_Selected, 2, RADIOBUTTON_LabelPlace, PLACETEXT_RIGHT, RADIOBUTTON_Spacing, 4, TAG_DONE); gb_ListbrowserGad = (struct Gadget *) IIntuition->NewObject(IListBrowser->LISTBROWSER_GetClass(),NULL, GA_ReadOnly, FALSE, GA_ID, GAD_ID_Listbrowser, GA_RelVerify, TRUE, LISTBROWSER_ColumnInfo, &gb_ListbrowserColumn, LISTBROWSER_ColumnTitles, TRUE, LISTBROWSER_Labels, &gb_List, LISTBROWSER_VertSeparators, TRUE, LISTBROWSER_Spacing, 1, LISTBROWSER_ShowSelected, TRUE, LISTBROWSER_AutoFit, TRUE, LISTBROWSER_Editable, FALSE, LISTBROWSER_MinVisible, 2, TAG_DONE); gb_PaletteGad = (struct Gadget *) IIntuition->NewObject(IPalette->PALETTE_GetClass(),NULL, GA_ReadOnly, FALSE, GA_ID, GAD_ID_Palette, GA_RelVerify, TRUE, PALETTE_Colour, 1, PALETTE_ColourOffset, 0, PALETTE_NumColours, 8, TAG_DONE); gb_FileGad = (struct Gadget *) IIntuition->NewObject(IGetFile->GETFILE_GetClass(),NULL, GA_ID, GAD_ID_File, GA_RelVerify, TRUE, GA_TabCycle, TRUE, GETFILE_TitleText, "Datei ausw‰hlen ...", GETFILE_Pattern, "#?", GETFILE_DoSaveMode, FALSE, GETFILE_RejectIcons, TRUE, GETFILE_ReadOnly, TRUE, GETFILE_DrawersOnly, FALSE, TAG_DONE); gb_FontGad = (struct Gadget *) IIntuition->NewObject(IGetFont->GETFONT_GetClass(),NULL, GA_ID, GAD_ID_Font, GA_RelVerify, TRUE, GETFONT_TitleText, "Zeichensatz ausw‰hlen ...", GETFONT_MinHeight, 6, GETFONT_MaxHeight, 30, TAG_DONE); gb_ScreenmodeGad = (struct Gadget *) IIntuition->NewObject(IGetScreenMode->GETSCREENMODE_GetClass(),NULL, GA_ID, GAD_ID_Screenmode, GA_RelVerify, TRUE, GETSCREENMODE_TitleText, "Bildschirmmodus ausw‰hlen ...", GETSCREENMODE_MinDepth, 2, GETSCREENMODE_MaxDepth, 8, TAG_DONE); gb_ColorGad = (struct Gadget *) IIntuition->NewObject(IGetColor->GETCOLOR_GetClass(),NULL, GA_ID, GAD_ID_Color, GA_RelVerify, TRUE, GETCOLOR_TitleText, "Farbe ausw‰hlen ...", GETCOLOR_Screen, gb_Scr, GETCOLOR_Color, 0x00aaccee, GETCOLOR_ColorWheel, TRUE, GETCOLOR_RGBSliders, TRUE, GETCOLOR_ShowRGB, TRUE, TAG_DONE); gb_FuelgaugeGad = (struct Gadget *) IIntuition->NewObject(IFuelGauge->FUELGAUGE_GetClass(),NULL, GA_ReadOnly, FALSE, GA_ID, GAD_ID_Fuelgauge, GA_RelVerify, TRUE, FUELGAUGE_Min, 0, FUELGAUGE_Max, 100, FUELGAUGE_Level, 10, FUELGAUGE_Orientation, FGORIENT_HORIZ, FUELGAUGE_Percent, TRUE, FUELGAUGE_Ticks, 10, FUELGAUGE_ShortTicks, 10, FUELGAUGE_Justification, FGJ_CENTER, TAG_DONE); gb_GradientsliderGad = (struct Gadget *) IIntuition->NewObject(NULL,"gradientslider.gadget", GA_ID, GAD_ID_Gradientslider, GA_RelVerify, TRUE, GA_TabCycle, TRUE, GRAD_PenArray, gb_GradientArray, PGA_Freedom, LORIENT_VERT, TAG_DONE); /* Colorwheel auf diesen RGB-Wert setzen */ struct ColorWheelRGB rgbval = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF }; gb_ColorwheelGad = (struct Gadget *) IIntuition->NewObject(NULL,"colorwheel.gadget", GA_ID, GAD_ID_Colorwheel, GA_RelVerify, TRUE, GA_TabCycle, TRUE, WHEEL_Screen, gb_Scr, //WHEEL_GradientSlider, gb_GradientsliderGad, WHEEL_BevelBox, FALSE, WHEEL_RGB, rgbval, TAG_DONE); gb_TexteditorGad = (struct Gadget *) IIntuition->NewObject(ITextEditor->TEXTEDITOR_GetClass(),NULL, GA_ID, GAD_ID_Texteditor, GA_RelVerify, TRUE, GA_TabCycle, TRUE, GA_TEXTEDITOR_FixedFont, FALSE, TAG_DONE); gb_DatebrowserGad = (struct Gadget *) IIntuition->NewObject(IDateBrowser->DATEBROWSER_GetClass(),NULL, GA_ID, GAD_ID_Datebrowser, GA_RelVerify, TRUE, GA_TabCycle, TRUE, DATEBROWSER_Day, 27, DATEBROWSER_Month, 10, DATEBROWSER_Year, 2007, DATEBROWSER_ShowTitle, TRUE, DATEBROWSER_ShowWeek, TRUE, DATEBROWSER_MultiSelect, FALSE, TAG_DONE); gb_SpaceGad = (struct Gadget *) IIntuition->NewObject(ISpace->SPACE_GetClass(),NULL, GA_ID, GAD_ID_Space, GA_RelVerify, TRUE, /* Gadget Up senden */ GA_Immediate, TRUE, /* Gadget Down senden */ GA_ReadOnly, FALSE, SPACE_Transparent, TRUE, /* Hintergrund nicht automatisch lˆschen */ SPACE_MinWidth, 10, SPACE_MinHeight, 10, SPACE_BevelStyle, BVS_DROPBOX, SPACE_RenderHook, &gb_RenderHook, ICA_TARGET, ICTARGET_IDCMP, /* eine Nachricht an das Programm senden */ TAG_DONE); gb_PageGad = (struct Gadget *) IIntuition->NewObject(ILayout->PAGE_GetClass(),NULL, GA_ID, GAD_ID_Page, LAYOUT_Orientation, LAYOUT_VERTICAL, LAYOUT_FixedHoriz, FALSE, LAYOUT_FixedVert, FALSE, LAYOUT_SpaceInner, TRUE, PAGE_Add, IIntuition->NewObject(ILayout->LAYOUT_GetClass(),NULL, LAYOUT_AddChild, IIntuition->NewObject(IButton->BUTTON_GetClass(),NULL, BUTTON_BevelStyle, BVS_NONE, BUTTON_Transparent, TRUE, GA_Text, "Amiga 1000", GA_ReadOnly, TRUE, TAG_DONE), TAG_DONE), PAGE_Add, IIntuition->NewObject(ILayout->LAYOUT_GetClass(),NULL, LAYOUT_AddChild, IIntuition->NewObject(IButton->BUTTON_GetClass(),NULL, BUTTON_BevelStyle, BVS_NONE, BUTTON_Transparent, TRUE, GA_Text, "Amiga 1200", GA_ReadOnly, TRUE, TAG_DONE), TAG_DONE), PAGE_Add, IIntuition->NewObject(ILayout->LAYOUT_GetClass(),NULL, LAYOUT_AddChild, IIntuition->NewObject(IButton->BUTTON_GetClass(),NULL, BUTTON_BevelStyle, BVS_NONE, BUTTON_Transparent, TRUE, GA_Text, "AmigaOne", GA_ReadOnly, TRUE, TAG_DONE), TAG_DONE), TAG_DONE); gb_ClicktabGad = (struct Gadget *) IIntuition->NewObject(IClickTab->CLICKTAB_GetClass(),NULL, GA_ID, GAD_ID_Clicktab, GA_Text, &gb_ClicktabLabels, GA_RelVerify, TRUE, CLICKTAB_PageGroup, gb_PageGad, TAG_DONE); gb_LabelImg = (struct Image *) IIntuition->NewObject(ILabel->LABEL_GetClass(),NULL, LABEL_Text, "Beschriftung", //LABEL_SoftStyle, FSF_BOLD, //LABEL_Justification, LJ_LEFT, TAG_DONE); gb_BevelImg = (struct Image *) IIntuition->NewObject(IBevel->BEVEL_GetClass(),NULL, BEVEL_Style, BVS_BOX, TAG_DONE); gb_BitmapImg = (struct Image *) IIntuition->NewObject(IBitMap->BITMAP_GetClass(),NULL, BITMAP_Screen, gb_Scr, BITMAP_Masking, FALSE, BITMAP_SourceFile, "amiga1000-normal.iff", BITMAP_SelectSourceFile, "amiga1000-selected.iff", BITMAP_DisabledSourceFile, "amiga1000-disabled.iff", IA_SupportsDisable, TRUE, TAG_DONE); gb_BitmapSImg = (struct Image *) IIntuition->NewObject(IBitMap->BITMAP_GetClass(),NULL, BITMAP_Screen, gb_Scr, BITMAP_Masking, FALSE, BITMAP_SourceFile, "amiga1000-selected.iff", IA_SupportsDisable, TRUE, TAG_DONE); gb_BitmapDImg = (struct Image *) IIntuition->NewObject(IBitMap->BITMAP_GetClass(),NULL, BITMAP_Screen, gb_Scr, BITMAP_Masking, FALSE, BITMAP_SourceFile, "amiga1000-disabled.iff", TAG_DONE); gb_DrawlistImg = (struct Image *) IIntuition->NewObject(IDrawList->DRAWLIST_GetClass(),NULL, DRAWLIST_Directives, gb_DrawList, TAG_DONE); gb_FillerImg = (struct Image *) IIntuition->NewObject(IFiller->FILLER_GetClass(),NULL, FILLER_Screen, gb_Scr, FILLER_BackgroundColor, 0xffaaaaaa, FILLER_ImageFilename, "amigaball.iff", FILLER_ImageMode, FILLER_MODE_TILED, IA_Width, 30, IA_Height, 30, TAG_DONE); gb_PenmapImg = (struct Image *) IIntuition->NewObject(IPenMap->PENMAP_GetClass(),NULL, PENMAP_RenderData, happy_data, PENMAP_Palette, image_object_palette, PENMAP_Screen, gb_Scr, PENMAP_Transparent, TRUE, TAG_DONE); for(i=1; i<=26; i++) { /* 13-17 und 19 gibt es nicht */ gb_GlyphImg[i] = (struct Image *) IIntuition->NewObject(IGlyph->GLYPH_GetClass(),NULL, GLYPH_Glyph, i, /*GLYPH_xxx */ IA_Width, 20, IA_Height, 20, TAG_DONE); } /* die einzelnen Seiten der Dragbar anlegen */ gb_Page1Layout = (struct Gadget *) IIntuition->NewObject(ILayout->LAYOUT_GetClass(),NULL, LAYOUT_Orientation, LAYOUT_ORIENT_VERT, LAYOUT_SpaceOuter, TRUE, LAYOUT_SpaceInner, TRUE, LAYOUT_BevelStyle, BVS_GROUP, LAYOUT_Label, "Grundtypen", LAYOUT_LabelPlace, BVJ_TOP_CENTER, LAYOUT_AddChild, gb_ButtonVGad, CHILD_WeightedHeight, 80, LAYOUT_AddChild, gb_ButtonGad, CHILD_WeightedHeight, 10, LAYOUT_AddChild, gb_StringGad, LAYOUT_AddChild, gb_IntegerGad, LAYOUT_AddChild, gb_SliderGad, CHILD_WeightedHeight, 10, LAYOUT_AddChild, gb_ScrollerGad, TAG_DONE); gb_Page2Layout = (struct Gadget *) IIntuition->NewObject(ILayout->LAYOUT_GetClass(),NULL, LAYOUT_Orientation, LAYOUT_ORIENT_VERT, LAYOUT_SpaceOuter, TRUE, LAYOUT_SpaceInner, TRUE, LAYOUT_BevelStyle, BVS_GROUP, LAYOUT_Label, "Auswahllisten", LAYOUT_LabelPlace, BVJ_TOP_CENTER, LAYOUT_AddChild, IIntuition->NewObject(ILayout->LAYOUT_GetClass(),NULL, LAYOUT_Orientation, LAYOUT_ORIENT_HORIZ, LAYOUT_AddChild, gb_ChooserGad, LAYOUT_AddChild, gb_Chooser2Gad, LAYOUT_AddChild, gb_Chooser3Gad, TAG_DONE), CHILD_WeightedHeight, 0, LAYOUT_AddChild, gb_CheckboxGad, CHILD_WeightedHeight, 0, LAYOUT_AddChild, gb_RadioGad, CHILD_WeightedHeight, 0, LAYOUT_AddChild, gb_ListbrowserGad, CHILD_WeightedHeight, 90, LAYOUT_AddChild, gb_PaletteGad, CHILD_WeightedHeight, 10, TAG_DONE); gb_Page3Layout = (struct Gadget *) IIntuition->NewObject(ILayout->LAYOUT_GetClass(),NULL, LAYOUT_Orientation, LAYOUT_ORIENT_VERT, LAYOUT_SpaceOuter, TRUE, LAYOUT_SpaceInner, TRUE, LAYOUT_BevelStyle, BVS_GROUP, LAYOUT_Label, "ASL-Auswahl", LAYOUT_LabelPlace, BVJ_TOP_CENTER, LAYOUT_AddChild, gb_FileGad, CHILD_WeightedHeight, 0, LAYOUT_AddChild, gb_FontGad, CHILD_WeightedHeight, 0, LAYOUT_AddChild, gb_ScreenmodeGad, CHILD_WeightedHeight, 0, LAYOUT_AddChild, gb_ColorGad, CHILD_WeightedHeight, 0, TAG_DONE); gb_Page4Layout = (struct Gadget *) IIntuition->NewObject(ILayout->LAYOUT_GetClass(),NULL, LAYOUT_Orientation, LAYOUT_ORIENT_VERT, LAYOUT_SpaceOuter, TRUE, LAYOUT_SpaceInner, TRUE, LAYOUT_BevelStyle, BVS_GROUP, LAYOUT_Label, "Sonstige Typen", LAYOUT_LabelPlace, BVJ_TOP_CENTER, LAYOUT_AddChild, gb_FuelgaugeGad, CHILD_WeightedHeight, 10, LAYOUT_AddChild, IIntuition->NewObject(ILayout->LAYOUT_GetClass(),NULL, LAYOUT_Orientation, LAYOUT_ORIENT_HORIZ, LAYOUT_AddChild, gb_ColorwheelGad, //CHILD_WeightedWidth, 0, //CHILD_WeightedHeight, 0, LAYOUT_AddChild, gb_GradientsliderGad, LAYOUT_AddChild, IIntuition->NewObject(ISpace->SPACE_GetClass(),NULL, SPACE_Transparent, FALSE, SPACE_MinWidth, 10, SPACE_MinHeight, 10, TAG_DONE), TAG_DONE), CHILD_WeightedHeight, 70, LAYOUT_AddChild, gb_TexteditorGad, CHILD_WeightedHeight, 10, LAYOUT_AddChild, gb_DatebrowserGad, CHILD_WeightedHeight, 10, TAG_DONE); gb_Page5Layout = (struct Gadget *) IIntuition->NewObject(ILayout->LAYOUT_GetClass(),NULL, LAYOUT_Orientation, LAYOUT_ORIENT_VERT, LAYOUT_SpaceOuter, TRUE, LAYOUT_SpaceInner, TRUE, LAYOUT_BevelStyle, BVS_GROUP, LAYOUT_Label, "Seitengestalltung", LAYOUT_LabelPlace, BVJ_TOP_CENTER, LAYOUT_AddChild, gb_SpaceGad, LAYOUT_AddChild, gb_ClicktabGad, TAG_DONE); gb_Page6Layout = (struct Gadget *) IIntuition->NewObject(ILayout->LAYOUT_GetClass(),NULL, LAYOUT_Orientation, LAYOUT_ORIENT_VERT, LAYOUT_SpaceOuter, TRUE, LAYOUT_SpaceInner, TRUE, LAYOUT_BevelStyle, BVS_GROUP, LAYOUT_Label, "Images", LAYOUT_LabelPlace, BVJ_TOP_CENTER, LAYOUT_AddImage, gb_LabelImg, LAYOUT_AddImage, gb_BevelImg, CHILD_MinHeight, 10, LAYOUT_AddChild, IIntuition->NewObject(ILayout->LAYOUT_GetClass(),NULL, LAYOUT_Orientation, LAYOUT_ORIENT_HORIZ, LAYOUT_AddImage, gb_BitmapImg, LAYOUT_AddImage, gb_BitmapSImg, LAYOUT_AddImage, gb_BitmapDImg, TAG_DONE), CHILD_WeightedHeight, 0, LAYOUT_AddImage, gb_DrawlistImg, CHILD_MinWidth, 30, CHILD_MinHeight, 30, CHILD_WeightedWidth, 0, CHILD_WeightedHeight, 0, LAYOUT_AddImage, gb_FillerImg, CHILD_MinWidth, 30, CHILD_MinHeight, 30, CHILD_MaxWidth, 200, CHILD_MaxHeight, 60, LAYOUT_AddImage, gb_PenmapImg, CHILD_WeightedWidth, 0, CHILD_WeightedHeight, 0, LAYOUT_AddChild, IIntuition->NewObject(ILayout->LAYOUT_GetClass(),NULL, LAYOUT_Orientation, LAYOUT_ORIENT_HORIZ, LAYOUT_AddImage, gb_GlyphImg[ 1], CHILD_MinWidth, 20, LAYOUT_AddImage, gb_GlyphImg[ 2], CHILD_MinWidth, 20, LAYOUT_AddImage, gb_GlyphImg[ 3], CHILD_MinWidth, 20, LAYOUT_AddImage, gb_GlyphImg[ 4], CHILD_MinWidth, 20, LAYOUT_AddImage, gb_GlyphImg[ 5], CHILD_MinWidth, 20, LAYOUT_AddImage, gb_GlyphImg[ 6], CHILD_MinWidth, 20, LAYOUT_AddImage, gb_GlyphImg[ 7], CHILD_MinWidth, 20, LAYOUT_AddImage, gb_GlyphImg[ 8], CHILD_MinWidth, 20, LAYOUT_AddImage, gb_GlyphImg[ 9], CHILD_MinWidth, 20, LAYOUT_AddImage, gb_GlyphImg[10], CHILD_MinWidth, 20, LAYOUT_AddImage, gb_GlyphImg[11], CHILD_MinWidth, 20, LAYOUT_AddImage, gb_GlyphImg[12], CHILD_MinWidth, 20, LAYOUT_AddImage, gb_GlyphImg[18], CHILD_MinWidth, 20, LAYOUT_AddImage, gb_GlyphImg[20], CHILD_MinWidth, 20, LAYOUT_AddImage, gb_GlyphImg[21], CHILD_MinWidth, 20, LAYOUT_AddImage, gb_GlyphImg[22], CHILD_MinWidth, 20, LAYOUT_AddImage, gb_GlyphImg[23], CHILD_MinWidth, 20, LAYOUT_AddImage, gb_GlyphImg[24], CHILD_MinWidth, 20, LAYOUT_AddImage, gb_GlyphImg[25], CHILD_MinWidth, 20, LAYOUT_AddImage, gb_GlyphImg[26], CHILD_MinWidth, 20, TAG_DONE), CHILD_MinHeight, 20, CHILD_WeightedHeight, 10, TAG_DONE); gb_PagesLayout = (struct Gadget *) IIntuition->NewObject(ILayout->PAGE_GetClass(),NULL, GA_ID, GAD_ID_Pages, LAYOUT_Orientation, LAYOUT_VERTICAL, LAYOUT_FixedHoriz, FALSE, LAYOUT_FixedVert, FALSE, LAYOUT_SpaceInner, TRUE, PAGE_Add, gb_Page1Layout, PAGE_Add, gb_Page2Layout, PAGE_Add, gb_Page3Layout, PAGE_Add, gb_Page4Layout, PAGE_Add, gb_Page5Layout, PAGE_Add, gb_Page6Layout, TAG_DONE); gb_PagesClicktab = (struct Gadget *) IIntuition->NewObject(IClickTab->CLICKTAB_GetClass(),NULL, GA_ID, GAD_ID_PagesClicktab, GA_Text, &gb_PagesLabels, CLICKTAB_PageGroup, gb_PagesLayout, TAG_DONE); IIntuition->UnlockPubScreen(NULL,gb_Scr); /* Layout-Objekt erzeugen */ gb_MainLayout = (struct Gadget *) IIntuition->NewObject(ILayout->LAYOUT_GetClass(),NULL, LAYOUT_Orientation, LAYOUT_ORIENT_VERT, LAYOUT_SpaceOuter, TRUE, LAYOUT_SpaceInner, TRUE, LAYOUT_AddChild, gb_PagesClicktab, TAG_DONE); if(gb_MainLayout) { /* das Fenster-Objekt erzeugen */ if((gb_WindowObj = (Object *) IIntuition->NewObject(IWindow->WINDOW_GetClass(),NULL, WA_IDCMP, IDCMP_GADGETUP | IDCMP_GADGETDOWN | IDCMP_MOUSEMOVE | IDCMP_VANILLAKEY | IDCMP_RAWKEY | IDCMP_CLOSEWINDOW, WA_SizeGadget, TRUE, WA_DepthGadget, TRUE, WA_DragBar, TRUE, WA_Activate, TRUE, WA_Title, "Alle Reaction Gadgets", WA_InnerWidth, 100, WA_InnerHeight, 100, WA_AutoAdjust, TRUE, WA_CloseGadget, TRUE, WA_RMBTrap, TRUE, WINDOW_ParentGroup, gb_MainLayout, WINDOW_IDCMPHook, &gb_IDCMPHook, WINDOW_IDCMPHookBits, IDCMP_IDCMPUPDATE | IDCMP_GADGETDOWN, TAG_DONE))) { /* alles korrekt erzeugt */ /* das Fenster kann jetzt angezeigt werden */ gb_Win = RA_OpenWindow(gb_WindowObj); } } return ( gb_WindowObj ? TRUE : FALSE ); } /******************************************************************************/ void DestroyAll() { /* Fenster schlieflen und enthaltene Objekte freigeben */ RA_CloseWindow(gb_WindowObj); IIntuition->DisposeObject(gb_WindowObj); /* die Listview-Eintr‰ge freigeben */ FreigebenList(); /* die reservierten Zeichenstifte freigeben */ struct ColorMap *cm = (gb_Scr ? gb_Scr->ViewPort.ColorMap : NULL); if((WORD)gb_GradientArray[0] != ~0) IGraphics->ReleasePen(cm,gb_GradientArray[0]); if((WORD)gb_GradientArray[1] != ~0) IGraphics->ReleasePen(cm,gb_GradientArray[1]); if((WORD)gb_GradientArray[2] != ~0) IGraphics->ReleasePen(cm,gb_GradientArray[2]); if((WORD)gb_GradientArray[3] != ~0) IGraphics->ReleasePen(cm,gb_GradientArray[3]); if((WORD)gb_GradientArray[4] != ~0) IGraphics->ReleasePen(cm,gb_GradientArray[4]); if((WORD)gb_GradientArray[5] != ~0) IGraphics->ReleasePen(cm,gb_GradientArray[5]); } /******************************************************************************/ void MsgLoop() { ULONG winsig; ULONG result, code; BOOL laufen = TRUE; /* Signalbits des Fensters vermerken */ IIntuition->GetAttr(WINDOW_SigMask,gb_WindowObj,&winsig); while(laufen) { /* warten auf Benutzeraktionen */ const ULONG sigs = IExec->Wait(winsig | SIGBREAKF_CTRL_C); /* die eingetroffenen Nachrichten verarbeiten */ while((result = RA_HandleInput(gb_WindowObj,&code)) != WMHI_LASTMSG) { /* den Nachrichtenanteil ausmaskieren ! */ switch(result & WMHI_CLASSMASK) { /* Gadget-Nachrichten auswerten */ case WMHI_GADGETUP: switch(result & WMHI_GADGETMASK) { case GAD_ID_ButtonV: { } break; case GAD_ID_Button: { IDOS->Printf("Button: [released]\n"); } break; case GAD_ID_String: { STRPTR val; IIntuition->GetAttr(STRINGA_TextVal,(Object*)gb_StringGad,(ULONG*)&val); IDOS->Printf("String: [%s]\n",val); } break; case GAD_ID_Integer: { ULONG val; IIntuition->GetAttr(INTEGER_Number,(Object*)gb_IntegerGad,(ULONG*)&val); IDOS->Printf("Integer: [%ld]\n",val); } break; case GAD_ID_Slider: { ULONG val; IIntuition->GetAttr(SLIDER_Level,(Object*)gb_SliderGad,(ULONG*)&val); IDOS->Printf("Slieder: [%ld]\n",val); } break; case GAD_ID_Scroller: { ULONG val; IIntuition->GetAttr(SCROLLER_Top,(Object*)gb_ScrollerGad,(ULONG*)&val); IDOS->Printf("Scroller: [%ld]\n",val); } break; case GAD_ID_Chooser: { ULONG val; IIntuition->GetAttr(CHOOSER_Selected,(Object*)gb_ChooserGad,(ULONG*)&val); IDOS->Printf("Chooser: [%ld]\n",val); } break; case GAD_ID_Chooser2: { ULONG val; IIntuition->GetAttr(CHOOSER_Selected,(Object*)gb_Chooser2Gad,(ULONG*)&val); IDOS->Printf("Chooser2: [%ld]\n",val); } break; case GAD_ID_Chooser3: { ULONG val; IIntuition->GetAttr(CHOOSER_Selected,(Object*)gb_Chooser3Gad,(ULONG*)&val); IDOS->Printf("Chooser3: [%ld]\n",val); } break; case GAD_ID_Checkbox: { ULONG val; IIntuition->GetAttr(GA_Selected,(Object*)gb_CheckboxGad,(ULONG*)&val); IDOS->Printf("Checkbox: [%s]\n",(val ? "selectet" : "not selected")); } break; case GAD_ID_Radio: { ULONG val; IIntuition->GetAttr(RADIOBUTTON_Selected,(Object*)gb_RadioGad,(ULONG*)&val); IDOS->Printf("Radio: [%ld]\n",val); } break; case GAD_ID_Listbrowser: { //ULONG action, column; struct Node *node; //IIntuition->GetAttr(LISTBROWSER_RelEvent,(Object*)gb_WordlistGad,(ULONG*)&action); //IIntuition->GetAttr(LISTBROWSER_RelColumn,(Object*)gb_WordlistGad,(ULONG*)&column); IIntuition->GetAttr(LISTBROWSER_SelectedNode,(Object*)gb_ListbrowserGad,(ULONG*)&node); //struct UserDictEntry *ude = LBNode2UserDictNode(node); IDOS->Printf("Listview: [%ld]\n",node->ln_Pri); } break; case GAD_ID_Palette: { ULONG val; IIntuition->GetAttr(PALETTE_Colour,(Object*)gb_PaletteGad,(ULONG*)&val); IDOS->Printf("Palette: [%ld]\n",val); } break; case GAD_ID_File: { STRPTR val; ULONG res = gfRequestFile((Object *)gb_FileGad,gb_Win); IIntuition->GetAttr(GETFILE_FullFile,(Object*)gb_FileGad,(ULONG*)&val); if(res) IDOS->Printf("File: [%s]\n",val); } break; case GAD_ID_Font: { struct TextAttr *val; ULONG res = gfRequestFont((Object *)gb_FontGad,gb_Win); IIntuition->GetAttr(GETFONT_TextAttr,(Object*)gb_FontGad,(ULONG*)&val); if(res) IDOS->Printf("Font: [%s %ld]\n",val->ta_Name,val->ta_YSize); } break; case GAD_ID_Screenmode: { ULONG id, width, height, depth; ULONG res = RequestScreenMode((Object *)gb_ScreenmodeGad,gb_Win); IIntuition->GetAttr(GETSCREENMODE_DisplayID,(Object*)gb_ScreenmodeGad,(ULONG*)&id); IIntuition->GetAttr(GETSCREENMODE_DisplayWidth,(Object*)gb_ScreenmodeGad,(ULONG*)&width); IIntuition->GetAttr(GETSCREENMODE_DisplayHeight,(Object*)gb_ScreenmodeGad,(ULONG*)&height); IIntuition->GetAttr(GETSCREENMODE_DisplayDepth,(Object*)gb_ScreenmodeGad,(ULONG*)&depth); if(res) IDOS->Printf("Screenmode: [$%lx %ld x %ld x %ld]\n",id,width,height,depth); } break; case GAD_ID_Color: { ULONG val; ULONG res = RequestColor((Object *)gb_ColorGad,gb_Win); IIntuition->GetAttr(GETCOLOR_Color,(Object*)gb_ColorGad,(ULONG*)&val); if(res) IDOS->Printf("Color: [$%08lx]\n",val); } break; case GAD_ID_Fuelgauge: { ULONG val; IIntuition->GetAttr(FUELGAUGE_Level,(Object*)gb_FuelgaugeGad,(ULONG*)&val); IDOS->Printf("Fuelgauge: [%ld]\n",val); } break; case GAD_ID_Colorwheel: { struct ColorWheelRGB val; IIntuition->GetAttr(WHEEL_RGB,(Object*)gb_ColorwheelGad,(ULONG*)&val); IDOS->Printf("Colorwheel: [red=%08lx green=%08lx blue=%08lx]\n",val.cw_Red,val.cw_Green,val.cw_Blue); /* anhand der neuen Farbauswahl den Gradientslieder anpassen */ struct ViewPort *vp = &gb_Scr->ViewPort; if((WORD)gb_GradientArray[0] != ~0) IGraphics->SetRGB32(vp,gb_GradientArray[0],val.cw_Red,val.cw_Green,val.cw_Blue); if((WORD)gb_GradientArray[1] != ~0) IGraphics->SetRGB32(vp,gb_GradientArray[1],val.cw_Red/15*12,val.cw_Green/15*12,val.cw_Blue/15*12); if((WORD)gb_GradientArray[2] != ~0) IGraphics->SetRGB32(vp,gb_GradientArray[2],val.cw_Red/15*9,val.cw_Green/15*9,val.cw_Blue/15*9); if((WORD)gb_GradientArray[3] != ~0) IGraphics->SetRGB32(vp,gb_GradientArray[3],val.cw_Red/15*6,val.cw_Green/15*6,val.cw_Blue/15*6); if((WORD)gb_GradientArray[4] != ~0) IGraphics->SetRGB32(vp,gb_GradientArray[4],val.cw_Red/15*3,val.cw_Green/15*3,val.cw_Blue/15*3); IIntuition->RefreshGadgets(gb_GradientsliderGad,gb_Win,NULL); } break; case GAD_ID_Gradientslider: { ULONG val; IIntuition->GetAttr(GRAD_CurVal,(Object*)gb_GradientsliderGad,(ULONG*)&val); IDOS->Printf("Gradientslieder: [%ld]\n",val); } break; case GAD_ID_Texteditor: { STRPTR val; val = (STRPTR) IIntuition->DoGadgetMethod(gb_TexteditorGad,gb_Win,NULL,GM_TEXTEDITOR_ExportText,NULL); if(val) IDOS->Printf("Texteditor: [%s]\n",val); } break; case GAD_ID_Datebrowser: { ULONG day, month, year; IIntuition->GetAttr(DATEBROWSER_Day,(Object*)gb_DatebrowserGad,(ULONG*)&day); IIntuition->GetAttr(DATEBROWSER_Month,(Object*)gb_DatebrowserGad,(ULONG*)&month); IIntuition->GetAttr(DATEBROWSER_Year,(Object*)gb_DatebrowserGad,(ULONG*)&year); IDOS->Printf("Datebrowser: [%ld.%ld.%ld]\n",day,month,year); } break; case GAD_ID_Space: { // ULONG mx, my; // IIntuition->GetAttr(SPACE_MouseX,(Object*)gb_SpaceGad,(ULONG*)&mx); // IIntuition->GetAttr(SPACE_MouseY,(Object*)gb_SpaceGad,(ULONG*)&my); // IDOS->Printf("Space: [%ld : %ld]\n",mx,my); } break; case GAD_ID_Page: { ULONG val; IIntuition->GetAttr(PAGE_Current,(Object*)gb_PageGad,(ULONG*)&val); IDOS->Printf("Page: [%ld]\n",val); } break; case GAD_ID_Clicktab: { ULONG val; IIntuition->GetAttr(CLICKTAB_Current,(Object*)gb_ClicktabGad,(ULONG*)&val); IDOS->Printf("Clicktab: [%ld]\n",val); } break; } break; /* RawKey der gedr¸ckten Taste */ case WMHI_RAWKEY: { //struct InputEvent *ie; //IIntuition->GetAttr(WINDOW_InputEvent,gb_WindowObj,(ULONG *)&ie); // code = result & WMHI_KEYMASK // qualifier = ie->ie_Qualifier } break; /* ASCII-Zeichencode der gedr¸ckten Taste */ case WMHI_MENUPICK: switch(result & WMHI_MENUMASK) { //case MENU_ID_xxx: // break; } break; /* Fenster-Schlieflsymbol angeklickt */ case WMHI_CLOSEWINDOW: { /* Fenster Schlieflsymbol bet‰tigt */ laufen = FALSE; } break; } } /* CTRL-C in der Shell gedr¸ckt oder als Signal erhalten */ if(sigs & SIGBREAKF_CTRL_C) laufen = FALSE; } } /******************************************************************************/ int main(int argc, char *argv[]) { if( CreateAll() ) { MsgLoop(); DestroyAll(); } else IDOS->Printf("Createing GUI failed !\n"); return( 0 ); }
Here are the support graphics files to go with it: allgadgets-gfx.lha
Reactor's approach, which you could use to 'click together' graphically a GUI under the Workbench 3.5 and 3.9, hasn't been developed any further. However, as shown in the previous example, you can basically copy the required GUI elements in your own sources with copy & paste.
ClickTab-Test Example
Another bonus is "ClickTab-Test" which deals exclusively with the Clicktab gadget. As I already mentioned, you can use it to create tabs. The tabs can in the meantime be dynamically added and deleted again. Moreover, you can use both tags, so all tags have the same width and the tab labeling is not shortened.
/* Michael Christoph - Musterbeispiel */ /* ClickTab-Test.c : Einfaches Beispielprogramm mit variablen ClickTabs */ /* ** gcc ClickTab-Test.c -o ClickTab-Test -l auto */ /************************** PROGRAMM-PARAMETER ********************************/ static const char *version = "\0$VER: ClickTab-Test 1.0 (13.02.2009) - (c) Feb.2009 by Meicky-Soft\n"; /******************************* INCLUDES *************************************/ #include <exec/types.h> #include <intuition/gadgetclass.h> #include <classes/window.h> #include <classes/requester.h> #include <reaction/reaction_macros.h> #include <libraries/gadtools.h> #include <gadgets/button.h> #include <gadgets/checkbox.h> #include <gadgets/string.h> #include <gadgets/clicktab.h> #include <gadgets/layout.h> #include <gadgets/page.h> #include <images/label.h> #include <proto/exec.h> #include <proto/dos.h> #include <proto/intuition.h> #include <proto/utility.h> #include <proto/window.h> #include <proto/layout.h> #include <proto/button.h> #include <proto/label.h> #include <proto/string.h> #include <proto/clicktab.h> #include <proto/checkbox.h> #include <proto/label.h> /******************************************************************************/ enum GADID { GAD_ID_Name = 1, GAD_ID_Add, GAD_ID_Del, GAD_ID_Evensize, GAD_ID_Labeltruncate, GAD_ID_Clicktab, }; struct Gadget *gb_NameGad; struct Gadget *gb_AddGad; struct Gadget *gb_DelGad; struct Gadget *gb_EvensizeGad; struct Gadget *gb_LabeltruncateGad; struct Gadget *gb_ClicktabGad; struct Gadget *gb_MainLayout; #define MAX_CLICKTABS 15 STRPTR gb_ClicktabLabels[MAX_CLICKTABS + 1] = { NULL }; Object *gb_WindowObj; struct Window *gb_Win; struct Screen *gb_Scr; /******************************************************************************/ BOOL CreateGUI() { if((gb_ClicktabLabels[0] = (STRPTR) IExec->AllocVecTags(31,AVT_Type,MEMF_SHARED,TAG_DONE))) { IUtility->Strlcpy(gb_ClicktabLabels[0],"_Muster",30); } gb_NameGad = (struct Gadget *) IIntuition->NewObject(IString->STRING_GetClass(),NULL, GA_ID, GAD_ID_Name, GA_RelVerify, TRUE, GA_TabCycle, TRUE, STRINGA_MaxChars, 30+1, STRINGA_MinVisible, 30, TAG_DONE); gb_AddGad = (struct Gadget *) IIntuition->NewObject(IButton->BUTTON_GetClass(),NULL, GA_ID, GAD_ID_Add, GA_RelVerify, TRUE, GA_Text, "_Add", TAG_DONE); gb_DelGad = (struct Gadget *) IIntuition->NewObject(IButton->BUTTON_GetClass(),NULL, GA_ID, GAD_ID_Del, GA_RelVerify, TRUE, GA_Text, "_Del", TAG_DONE); gb_EvensizeGad = (struct Gadget *) IIntuition->NewObject(ICheckBox->CHECKBOX_GetClass(),NULL, GA_ID, GAD_ID_Evensize, GA_Text, "EvenSize", GA_RelVerify, TRUE, CHECKBOX_TextPlace, PLACETEXT_RIGHT, CHECKBOX_Checked, FALSE, TAG_DONE); gb_LabeltruncateGad = (struct Gadget *) IIntuition->NewObject(ICheckBox->CHECKBOX_GetClass(),NULL, GA_ID, GAD_ID_Labeltruncate, GA_Text, "LabelTruncate", GA_RelVerify, TRUE, CHECKBOX_TextPlace, PLACETEXT_RIGHT, CHECKBOX_Checked, TRUE, TAG_DONE); gb_ClicktabGad = (struct Gadget *) IIntuition->NewObject(IClickTab->CLICKTAB_GetClass(),NULL, GA_ID, GAD_ID_Clicktab, GA_Text, &gb_ClicktabLabels, GA_RelVerify, TRUE, CLICKTAB_EvenSize, FALSE, CLICKTAB_LabelTruncate, TRUE, //CLICKTAB_PageGroup, gb_PagesLayout, TAG_DONE); gb_MainLayout = (struct Gadget *) IIntuition->NewObject(ILayout->LAYOUT_GetClass(),NULL, LAYOUT_Orientation, LAYOUT_VERTICAL, LAYOUT_SpaceOuter, TRUE, LAYOUT_SpaceInner, TRUE, LAYOUT_AddChild, gb_NameGad, LAYOUT_AddChild, gb_AddGad, LAYOUT_AddChild, gb_DelGad, LAYOUT_AddChild, gb_EvensizeGad, LAYOUT_AddChild, gb_LabeltruncateGad, LAYOUT_AddChild, gb_ClicktabGad, TAG_DONE); if(gb_MainLayout) { /* das Fenster-Objekt erzeugen */ if((gb_WindowObj = (Object *) IIntuition->NewObject(IWindow->WINDOW_GetClass(),NULL, WA_IDCMP, IDCMP_GADGETUP | IDCMP_VANILLAKEY | IDCMP_CLOSEWINDOW, WA_SizeGadget, TRUE, WA_DepthGadget, TRUE, WA_DragBar, TRUE, WA_Activate, TRUE, WA_Title, "Variable Anzahl Tabs", WA_InnerWidth, 150, WA_InnerHeight, 100, WA_AutoAdjust, TRUE, WA_CloseGadget, TRUE, WINDOW_ParentGroup, gb_MainLayout, TAG_DONE))) { /* alles korrekt erzeugt */ /* das Fenster kann jetzt angezeigt werden */ gb_Win = RA_OpenWindow(gb_WindowObj); } } return ( gb_Win ? TRUE : FALSE ); } /******************************************************************************/ void FreeGUI() { RA_CloseWindow(gb_WindowObj); IIntuition->DisposeObject(gb_WindowObj); ULONG i; for(i=0; i<MAX_CLICKTABS; i++) { if(gb_ClicktabLabels[i]) IExec->FreeVec(gb_ClicktabLabels[i]); } } /******************************************************************************/ void MsgLoop() { ULONG winsig; ULONG result, code; BOOL laufen = TRUE; /* Signalbits des Fensters vermerken */ IIntuition->GetAttr(WINDOW_SigMask,gb_WindowObj,&winsig); while(laufen) { /* warten auf Benutzeraktionen */ const ULONG sigs = IExec->Wait(winsig | SIGBREAKF_CTRL_C); /* die eingetroffenen Nachrichten verarbeiten */ while((result = RA_HandleInput(gb_WindowObj,&code)) != WMHI_LASTMSG) { /* den Nachrichtenanteil ausmaskieren ! */ switch(result & WMHI_CLASSMASK) { /* Gadget-Nachrichten auswerten */ case WMHI_GADGETUP: switch(result & WMHI_GADGETMASK) { case GAD_ID_Name: { /* die Beschriftung aktualisieren */ ULONG val; IIntuition->GetAttr(CLICKTAB_Current,(Object*)gb_ClicktabGad,(ULONG*)&val); STRPTR name; IIntuition->GetAttr(STRINGA_TextVal,(Object*)gb_NameGad,(ULONG*)&name); IUtility->Strlcpy(gb_ClicktabLabels[val],name,30); IDOS->Printf("Update CT [%ld] <%s>\n",val,name); IIntuition->RefreshSetGadgetAttrs(gb_ClicktabGad,gb_Win,NULL, GA_Text,gb_ClicktabLabels, TAG_DONE); } break; case GAD_ID_Add: { /* einen neuen Tab hinzuf¸gen */ ULONG max; IIntuition->GetAttr(CLICKTAB_Total,(Object*)gb_ClicktabGad,(ULONG*)&max); if(max < MAX_CLICKTABS-1) { STRPTR name; IIntuition->GetAttr(STRINGA_TextVal,(Object*)gb_NameGad,(ULONG*)&name); if(name[0]) { IDOS->Printf("Add CT [%ld] <%s>\n",max,name); if((gb_ClicktabLabels[max] = (STRPTR) IExec->AllocVecTags(31,AVT_Type,MEMF_SHARED,TAG_DONE))) { IUtility->Strlcpy(gb_ClicktabLabels[max],name,30); } else IDOS->Printf("out of memory\n"); IIntuition->RefreshSetGadgetAttrs(gb_ClicktabGad,gb_Win,NULL, GA_Text,gb_ClicktabLabels, TAG_DONE); } else IDOS->Printf("Name for tab required\n"); } else IDOS->Printf("No more tabs possible\n"); } break; case GAD_ID_Del: { /* den aktuellen Tab lˆschen */ ULONG val, i; IIntuition->GetAttr(CLICKTAB_Current,(Object*)gb_ClicktabGad,(ULONG*)&val); IDOS->Printf("Del CT [%ld] <%s>\n",val,gb_ClicktabLabels[val]); IExec->FreeVec(gb_ClicktabLabels[val]); for(i=val; i<MAX_CLICKTABS; i++) { gb_ClicktabLabels[i] = gb_ClicktabLabels[i + 1]; } IIntuition->RefreshSetGadgetAttrs(gb_ClicktabGad,gb_Win,NULL, GA_Text,gb_ClicktabLabels, TAG_DONE); } break; case GAD_ID_Evensize: { /* alle Tabs mit selber Breite */ /* V53: FUNKTIONIERT IM MOMENT NUR BEI INITIALISIERUNG ! */ ULONG val; IIntuition->GetAttr(GA_Selected,(Object*)gb_EvensizeGad,(ULONG*)&val); IIntuition->RefreshSetGadgetAttrs(gb_ClicktabGad,gb_Win,NULL, CLICKTAB_EvenSize,val, TAG_DONE); /* !!! MUST DO to layout the changed tag !!! */ IIntuition->RefreshSetGadgetAttrs(gb_ClicktabGad,gb_Win,NULL, GA_Text,gb_ClicktabLabels, TAG_DONE); } break; case GAD_ID_Labeltruncate: { /* bei Bedarf Tabbeschriftung k¸rzen */ /* V53: FUNKTIONIERT IM MOMENT NUR BEI INITIALISIERUNG ! */ ULONG val; IIntuition->GetAttr(GA_Selected,(Object*)gb_LabeltruncateGad,(ULONG*)&val); IIntuition->RefreshSetGadgetAttrs(gb_ClicktabGad,gb_Win,NULL, CLICKTAB_LabelTruncate,val, TAG_DONE); /* !!! MUST DO to layout the changed tag !!! */ IIntuition->RefreshSetGadgetAttrs(gb_ClicktabGad,gb_Win,NULL, GA_Text,gb_ClicktabLabels, TAG_DONE); } break; case GAD_ID_Clicktab: { /* Tabbezeichnung ¸bernehmen zur Bearbeitung */ ULONG val; IIntuition->GetAttr(CLICKTAB_Current,(Object*)gb_ClicktabGad,(ULONG*)&val); IDOS->Printf("Update STR [%ld] <%s>\n",val,gb_ClicktabLabels[val]); IIntuition->SetGadgetAttrs(gb_NameGad,gb_Win,NULL, STRINGA_TextVal,gb_ClicktabLabels[val], TAG_DONE); } break; } break; case WMHI_VANILLAKEY: { const LONG code = result & WMHI_KEYMASK; if(code == ' ') { IDOS->Printf("---- Label List:\n"); ULONG i; for(i=0; i<MAX_CLICKTABS; i++) { if(gb_ClicktabLabels[i]) IDOS->Printf("[%ld] <%s> $%lx\n",i,gb_ClicktabLabels[i],gb_ClicktabLabels[i]); } IDOS->Printf("----------------\n"); } } break; /* Fenster-Schlieflsymbol angeklickt */ case WMHI_CLOSEWINDOW: { /* Fenster Schlieflsymbol bet‰tigt */ laufen = FALSE; } break; } } /* CTRL-C in der Shell gedr¸ckt oder als Signal erhalten */ if(sigs & SIGBREAKF_CTRL_C) laufen = FALSE; } } /******************************************************************************/ int main(int argc, char *argv[]) { /* AmigaOS 4.1 ist erforderlich */ if(SysBase->lib_Version < 53) { IDOS->Printf("program required AmigaOS 4.1\n"); return( 20 ); } if( CreateGUI() ) { MsgLoop(); FreeGUI(); } else IDOS->Printf("Createing GUI failed !\n"); return( 0 ); }
Irrespective of the programing side, the user can influence the appearance and partly the behaviour of gadgets and windows system-wide using the Prefs options. Angular or rounded edges, the thickness of the window frame, and also the complex colour scheme are all widely configurable. There are ready-made styles so everything works perfectly in the visual sense.
Authors
Written by Michael Christoph and Aleksandra Schmidt-Pendarovska
Copyright (c) 2013 Michael Christoph