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) Dec.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() { /* create a Checkbox Gadget */ 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))) { /* create the Button */ if((gb_ButtonGad = (struct Gadget *) IIntuition->NewObject(IButton->BUTTON_GetClass(),NULL, GA_ID, GAD_ID_Quit, GA_RelVerify, TRUE, GA_Text, "_Quit", TAG_DONE))) { /* create the Window Object */ 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, /* create the Layout Object and include it into the Window */ 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))) { /* open the Window */ if((gb_Win = RA_OpenWindow(gb_WindowObj))) { /* query the Signal Bit of the Window */ ULONG winsig; IIntuition->GetAttr(WINDOW_SigMask,gb_WindowObj,&winsig); BOOL laufen = TRUE; while(laufen) { ULONG result, code, val; /* wait till either Button or Close Icon are clicked */ const ULONG sigs = IExec->Wait(winsig | SIGBREAKF_CTRL_C); /* process the received Messages */ while((result = RA_HandleInput(gb_WindowObj,&code)) != WMHI_LASTMSG) { /* mask out the Messages part */ switch(result & WMHI_CLASSMASK) { /* process the Gadget Messages */ 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; /* query the Window Close Icon */ case WMHI_CLOSEWINDOW: laufen = FALSE; break; /* query the Menu Selection */ case WMHI_MENUPICK: switch(result & WMHI_MENUMASK) { case MENU_ID_Quit: laufen = FALSE; break; } break; } } /* query if CTRL-C received from the Shell */ if(sigs & SIGBREAKF_CTRL_C) laufen = FALSE; } /* close the Window */ RA_CloseWindow(gb_WindowObj); } } } /* release Window Object, dump also Layout and Gadget Objects */ IIntuition->DisposeObject(gb_WindowObj); } return 0; }
AllGadgets Example
We can deal with programming with ReAction here only in theory. But for this purpose we have put "AllGadgets.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 * AllGadgets.c * * gcc AllGadgets.c -o AllGadgets -l auto */ /******************************* 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> /******************************************************************************/ static const char *version USED = "\0$VER: AllGadgets 1.01 (14.04.2014) - (c) Apr.2014 by Meicky-Soft\n"; /******************************************************************************/ 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) { /* create a List entry */ /* ATTENTION: ** Use this function only if the List is *not* assigned to the ListView! ** If applicable, deselect via ** SetGadgetAttrs(gad,win,NULL, LISTBROWSER_Labels,~0, TAG_END); ** then modify the List, then assign the List via ** SetGadgetAttrs(gad,win,NULL, LISTBROWSER_Labels,liste, TAG_END); ** back to the ListView. 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_END))) { node->ln_Pri = num; IExec->AddTail(&gb_List,node); } else { IDOS->Printf("Out of memory while creating list entry\n"); } return( node ? TRUE : FALSE ); } /******************************************************************************/ void FreigebenList() { /* release the List with all its data */ /* ATTENTION: ** Use this function only if the List is *not* assigned to the ListView! ** If applicable, deselect via ** SetGadgetAttrs(gad,win,NULL, LISTBROWSER_Labels,~0, TAG_END); ** then modify the List, then assign the (empty) List via ** SetGadgetAttrs(gad,win,NULL, LISTBROWSER_Labels,liste, TAG_END); ** back to the ListView. */ 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 Function to refresh the Space Gadgets */ /* only if the Window is visible we can draw into it */ if(gb_Win) { /* determine the size of our Output Area */ struct IBox *gb_DrawArea; IIntuition->GetAttr(SPACE_AreaBox,(Object*)gb_SpaceGad,(ULONG *)&gb_DrawArea); /* empty the complete Area with Background Color */ 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 Function for listening to IDCMP_UPDATE Messages */ struct TagItem *taglist = (struct TagItem *) msg->IAddress; const LONG gadid = IUtility->GetTagData(GA_ID,-1,taglist); if(msg->Class == IDCMP_GADGETDOWN) { /* Press Mouse Button: Set start position without drawing */ 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); /* determine the size of our Output Area */ /* so we don't draw outside of this area */ 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; /* Screen Pointer is needed for single Gadgets */ gb_Scr = IIntuition->LockPubScreen(NULL); if(gb_Scr) { /* request and set pens for the Gradient Slider */ 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); } /* create Listbrowser entries */ IExec->NewList(&gb_List); CreateEntry(0,"1","Amiga 1000"); CreateEntry(1,"2","Amiga 1200"); CreateEntry(2,"3","AmigaOne"); /* initialize RenderHook */ gb_RenderHook.h_Entry = (ULONG (*)())RenderHookFunc; gb_RenderHook.h_SubEntry = NULL; /* initialize IDCMPHook for listening to IDCMP_UPDATE Messages */ gb_IDCMPHook.h_Entry = (ULONG (*)())IDCMPHookFunc; gb_IDCMPHook.h_SubEntry = NULL; /* create Gadget Object */ 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_END); gb_ButtonGad = (struct Gadget *) IIntuition->NewObject(IButton->BUTTON_GetClass(),NULL, GA_ID, GAD_ID_Button, GA_Text, "Button", TAG_END); 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_END); 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_END); 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_END); 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_END); 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_END); 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_END); 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_END); 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_END); 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_END); 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_END); 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_END); gb_FileGad = (struct Gadget *) IIntuition->NewObject(IGetFile->GETFILE_GetClass(),NULL, GA_ID, GAD_ID_File, GA_RelVerify, TRUE, GA_TabCycle, TRUE, GETFILE_TitleText, ""Select File ...", GETFILE_Pattern, "#?", GETFILE_DoSaveMode, FALSE, GETFILE_RejectIcons, TRUE, GETFILE_ReadOnly, TRUE, GETFILE_DrawersOnly, FALSE, TAG_END); gb_FontGad = (struct Gadget *) IIntuition->NewObject(IGetFont->GETFONT_GetClass(),NULL, GA_ID, GAD_ID_Font, GA_RelVerify, TRUE, GETFONT_TitleText, "Select Font ...", GETFONT_MinHeight, 6, GETFONT_MaxHeight, 30, TAG_END); gb_ScreenmodeGad = (struct Gadget *) IIntuition->NewObject(IGetScreenMode->GETSCREENMODE_GetClass(),NULL, GA_ID, GAD_ID_Screenmode, GA_RelVerify, TRUE, GETSCREENMODE_TitleText, "Select Screen Mode ...", GETSCREENMODE_MinDepth, 2, GETSCREENMODE_MaxDepth, 8, TAG_END); gb_ColorGad = (struct Gadget *) IIntuition->NewObject(IGetColor->GETCOLOR_GetClass(),NULL, GA_ID, GAD_ID_Color, GA_RelVerify, TRUE, GETCOLOR_TitleText, "Choose Color ...", GETCOLOR_Screen, gb_Scr, GETCOLOR_Color, 0x00aaccee, GETCOLOR_ColorWheel, TRUE, GETCOLOR_RGBSliders, TRUE, GETCOLOR_ShowRGB, TRUE, TAG_END); 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_END); 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_END); /* set Color Wheel to this RGB value */ 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_END); 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_END); 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_END); gb_SpaceGad = (struct Gadget *) IIntuition->NewObject(ISpace->SPACE_GetClass(),NULL, GA_ID, GAD_ID_Space, GA_RelVerify, TRUE, /* send Gadget Up */ GA_Immediate, TRUE, /* send Gadget Down */ GA_ReadOnly, FALSE, SPACE_Transparent, TRUE, /* Background not deleted automatically */ SPACE_MinWidth, 10, SPACE_MinHeight, 10, SPACE_BevelStyle, BVS_DROPBOX, SPACE_RenderHook, &gb_RenderHook, ICA_TARGET, ICTARGET_IDCMP, /* send a Message to the Program */ TAG_END); 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_END), TAG_END), 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_END), TAG_END), 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_END), TAG_END), TAG_END); 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_END); gb_LabelImg = (struct Image *) IIntuition->NewObject(ILabel->LABEL_GetClass(),NULL, LABEL_Text, "Beschriftung", //LABEL_SoftStyle, FSF_BOLD, //LABEL_Justification, LJ_LEFT, TAG_END); gb_BevelImg = (struct Image *) IIntuition->NewObject(IBevel->BEVEL_GetClass(),NULL, BEVEL_Style, BVS_BOX, TAG_END); 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_END); 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_END); gb_BitmapDImg = (struct Image *) IIntuition->NewObject(IBitMap->BITMAP_GetClass(),NULL, BITMAP_Screen, gb_Scr, BITMAP_Masking, FALSE, BITMAP_SourceFile, "amiga1000-disabled.iff", TAG_END); gb_DrawlistImg = (struct Image *) IIntuition->NewObject(IDrawList->DRAWLIST_GetClass(),NULL, DRAWLIST_Directives, gb_DrawList, TAG_END); 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_END); 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_END); for(i=1; i<=26; i++) { /* 13-17 and 19 do not exist */ gb_GlyphImg[i] = (struct Image *) IIntuition->NewObject(IGlyph->GLYPH_GetClass(),NULL, GLYPH_Glyph, i, /*GLYPH_xxx */ IA_Width, 20, IA_Height, 20, TAG_END); } /* create the single pages of the Drag Bar */ 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_END); 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_END), 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_END); 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_END); 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_END), TAG_END), CHILD_WeightedHeight, 70, LAYOUT_AddChild, gb_TexteditorGad, CHILD_WeightedHeight, 10, LAYOUT_AddChild, gb_DatebrowserGad, CHILD_WeightedHeight, 10, TAG_END); 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_END); 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_END), 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_END), CHILD_MinHeight, 20, CHILD_WeightedHeight, 10, TAG_END); 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_END); gb_PagesClicktab = (struct Gadget *) IIntuition->NewObject(IClickTab->CLICKTAB_GetClass(),NULL, GA_ID, GAD_ID_PagesClicktab, GA_Text, &gb_PagesLabels, CLICKTAB_PageGroup, gb_PagesLayout, TAG_END); IIntuition->UnlockPubScreen(NULL,gb_Scr); /* create Layout Object */ 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_END); if(gb_MainLayout) { /* create the Window Object */ 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, "All 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_END))) { /* everything created correctly */ /* the Window can be shown now */ gb_Win = RA_OpenWindow(gb_WindowObj); } } return gb_WindowObj ? TRUE : FALSE; } /******************************************************************************/ void DestroyAll() { /* close Window and release included Objects */ RA_CloseWindow(gb_WindowObj); IIntuition->DisposeObject(gb_WindowObj); /* release Listview entries */ FreigebenList(); /* release the reserved pens */ 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; /* save Signal Bits of the Window */ IIntuition->GetAttr(WINDOW_SigMask,gb_WindowObj,&winsig); while(laufen) { /* wait for user actions */ const ULONG sigs = IExec->Wait(winsig | SIGBREAKF_CTRL_C); /* process the received Messages */ while((result = RA_HandleInput(gb_WindowObj,&code)) != WMHI_LASTMSG) { /* mask out the Messages part */ switch(result & WMHI_CLASSMASK) { /* process Gadget Messages */ 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); /* reset the Gradient Slider depending on the new color selection */ 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 of pressed key */ case WMHI_RAWKEY: { //struct InputEvent *ie; //IIntuition->GetAttr(WINDOW_InputEvent,gb_WindowObj,(ULONG *)&ie); // code = result & WMHI_KEYMASK // qualifier = ie->ie_Qualifier } break; /* ASCII code of pressed key */ case WMHI_MENUPICK: switch(result & WMHI_MENUMASK) { //case MENU_ID_xxx: // break; } break; /* Window Close Icon clicked */ case WMHI_CLOSEWINDOW: { /* Window Close Icon executed */ laufen = FALSE; } break; } } /* CTRL-C typed into the Shell or received as signal */ 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 * ClickTab-Test.c * * gcc ClickTab-Test.c -o ClickTab-Test -l auto */ /******************************* 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> /******************************************************************************/ static const char *version USED = "\0$VER: ClickTab-Test 1.0 (13.02.2009) - (c) Feb.2009 by Meicky-Soft\n"; /******************************************************************************/ 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_END))) { 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_END); gb_AddGad = (struct Gadget *) IIntuition->NewObject(IButton->BUTTON_GetClass(),NULL, GA_ID, GAD_ID_Add, GA_RelVerify, TRUE, GA_Text, "_Add", TAG_END); gb_DelGad = (struct Gadget *) IIntuition->NewObject(IButton->BUTTON_GetClass(),NULL, GA_ID, GAD_ID_Del, GA_RelVerify, TRUE, GA_Text, "_Del", TAG_END); 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_END); 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_END); 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_END); 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_END); if(gb_MainLayout) { /* Create the window object */ 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 Number of Tabs", WA_InnerWidth, 150, WA_InnerHeight, 100, WA_AutoAdjust, TRUE, WA_CloseGadget, TRUE, WINDOW_ParentGroup, gb_MainLayout, TAG_END))) { /* Everything created successfully */ /* The window can be opened now */ 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 running = TRUE; /* Get the window signal bit mask */ IIntuition->GetAttr(WINDOW_SigMask, gb_WindowObj, &winsig); while(running) { /* Wait for user actions */ const ULONG sigs = IExec->Wait(winsig | SIGBREAKF_CTRL_C); /* Process all messages */ while((result = RA_HandleInput(gb_WindowObj, &code)) != WMHI_LASTMSG) { /* Mask out the message class ! */ switch(result & WMHI_CLASSMASK) { /* Handle gadget message */ case WMHI_GADGETUP: switch(result & WMHI_GADGETMASK) { case GAD_ID_Name: { /* Update caption */ 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_END); } break; case GAD_ID_Add: { /* Add a new tab */ 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_END))) { 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_END); } else IDOS->Printf("Name for tab required\n"); } else IDOS->Printf("No more tabs possible\n"); } break; case GAD_ID_Del: { /* Erase the current tab */ 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_END); } break; case GAD_ID_Evensize: { /* All tabs have the same width */ /* V53: WORKS ONLY DURING INITIALIZATION ! */ ULONG val; IIntuition->GetAttr(GA_Selected,(Object*)gb_EvensizeGad,(ULONG*)&val); IIntuition->RefreshSetGadgetAttrs(gb_ClicktabGad,gb_Win,NULL, CLICKTAB_EvenSize,val, TAG_END); /* !!! MUST DO to layout the changed tag !!! */ IIntuition->RefreshSetGadgetAttrs(gb_ClicktabGad,gb_Win,NULL, GA_Text,gb_ClicktabLabels, TAG_END); } break; case GAD_ID_Labeltruncate: { /* Truncates label if necessary */ /* V53: WORKS ONLY DURING INITIALIZATION ! */ ULONG val; IIntuition->GetAttr(GA_Selected,(Object*)gb_LabeltruncateGad,(ULONG*)&val); IIntuition->RefreshSetGadgetAttrs(gb_ClicktabGad,gb_Win,NULL, CLICKTAB_LabelTruncate,val, TAG_END); /* !!! MUST DO to layout the changed tag !!! */ IIntuition->RefreshSetGadgetAttrs(gb_ClicktabGad,gb_Win,NULL, GA_Text,gb_ClicktabLabels, TAG_END); } break; case GAD_ID_Clicktab: { /* Use tab name for editing */ 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_END); } 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; /* Window close gadget clicked */ case WMHI_CLOSEWINDOW: { running = FALSE; } break; } } /* CTRL-C typed in the shell or via a signal */ if(sigs & SIGBREAKF_CTRL_C) laufen = FALSE; } } /******************************************************************************/ int main(int argc, char *argv[]) { /* AmigaOS 4.1 is required */ if(SysBase->lib_Version < 53) { IDOS->Printf("Program requires AmigaOS 4.1\n"); return( 20 ); } if( CreateGUI() ) { MsgLoop(); FreeGUI(); } else IDOS->Printf("GUI creation 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