Die Programmierung mit Gadtools- oder 1.3-Gadget-Strukturen liegt weit in der Vergangenheit � aktuell ist die objektorientierte Programmierung, die auch bei p.OS-Gadgets zur Anwendung kommt. Wer das BOOPSI-Konzept von Kickstart 2.0 kennt oder mit der Programmierung unter MUI vertraut ist, wird auch unter p.OS keine Schwierigkeiten haben. Die Gadgets, wie auch andere Objekte, werden per pOS_NewIObject() erzeugt und mit pOS_DisposeIObject() wieder freigegeben. Auf die Freigabe der Gadgets �von Hand� k�nnen Sie aber normalerweise verzichten, da Ihnen diese Arbeit vom OS abgenommen wird. Dazu ist nur der Tag ICLTAG_AutoDelete auf TRUE zu setzen. Falls Sie mehrere Gadgets zu einer Gruppe zusammenf�gen (dazu sp�ter mehr), gen�gt es, wenn diese den Tag bekommt. Alle Members (Gruppenangeh�rige) werden dann automatisch mitgel�scht � das macht die Funktion pOS_DisposeIObject() ebenfalls.
Kurs�bersicht | |||
|
Der Screenshot zeigt die Gadgetgruppierung des Intui-Demoprogramms
(zu finden auf der CD-ROM 9-10/97)
Alle Gadgets brauchen zwingend die DrawInfo-Daten des Screens (per ICLTAG_DrawInfo). Abgeleitete Gadgets ben�tigen teilweise unbedingt noch weitere Tags. Die m�glichen Tags entnehmen Sie der Datei "p:pIntui/Tags.h". Dabei ist zu beachten, da� die abgeleiteten Gadgets alle Tags ihres Basis-Gadgets verstehen.
Wenn Sie alle Gadgets erzeugt haben, die Sie f�r die Oberfl�che ben�tigen, m�ssen die Gadgets noch plaziert werden. Unter AmigaOS war es sehr aufwendig, die Gadgets fontsensitiv zu programmieren. Je nach Fontgr��e �ndert sich die der Gadgets. Aber auch hier nimmt Ihnen p.OS die komplette Gr��enberechnung und Plazierung ab. Sie k�nnen Ihre Gadgets dadurch zwar nicht mehr auf eine feste Koordinate setzen, sondern �beschreiben� nur noch die Seite, die Vorteile der automatischen Fontsensivit�t �berwiegen aber.
Zur Anordnung der Gadgets existieren horizontale und vertikale Gruppen. Eine �Speichern/Benutzen/Abbrechen�-Gadgetgruppe wird durch eine horizontale Gruppe zusammengefa�t und nebeneinander angezeigt. Durch die Kombination mehrerer vertikaler und horizontaler Gruppen (auch gemischt mit einfachen Gadgets) k�nnen Sie das Aussehen des Fensterinneren komplett bestimmen. Soll nur einfacher Text gezeigt werden, l��t sich dies direkt mit pOS_DrawText() ausgeben. Dabei m�ssen Sie aber noch die korrekte Position berechnen und evtl. ist auch nicht genug Platz f�r den kompletten String. Da sich die Gadgets, je nach Fenstergr��e auch ausdehnen k�nnen, ist diese Positionsberechnung sehr aufwendig. Es empfiehlt sich daher, da� Sie auch dazu auf Gadgets zur�ckgreifen (SCRNAM_ GTxtBoxClass). Sie lassen sich wahlweise mit Rahmen anzeigen. Auch Textfarbe und Hintergrundverhalten k�nnen Sie festlegen. Dabei ergibt sich noch ein weiterer Vorteil: L��t sich der Text durch einen gro�en Font nicht mehr vollst�ndig sichtbar zeigen, wird der Ausgabebereich automatisch geclippt. D.h. alle p.OS-Systemgadgets zeigen sich nur so gro�, wie Platz vorhanden ist.
F�r das Abtrennen von Gadgets(gruppen) kann man statt pOS_SetPosition()/pOS_DrawLine() auf ein Trennlinien-Gadget zur�ckgreifen; z.B.
pOS_NewIObject(NULL, dri->dri_Names[SCRNAM_GBarClass], 0, ICLTAG_DrawInfo, dri, TAG_DONE);Die Trennlinie richtet sich, je nach der Gruppe, automatisch horizontal oder vertikal aus. Wollen Sie die Zusammengeh�rigkeit mehrerer Gadgets einer Gruppe hervorheben, gen�gt es, wenn Sie in der Gruppe den Tag ICLTAG_GadBorderType (z.B. mit GADBORTYP_XBox) angeben. Die verschiedenen m�glichen Rahmentypen finden Sie in der Datei �p:pGadget/ Gadget.h�.
Werden Fenster vergr��ert oder verkleinert, pa�t p.OS automatisch (ohne jede zus�tzliche Programmzeile!) alle Gadgets der neuen Fenstergr��e an. Damit Sie nun bestimmen k�nnen, wieviel Platz ein Gadget haben darf, gibt es �Gewichte�. Ohne Gewicht (ICLTAG_Gwk = 0) wird das Gadget immer in seiner Nominalgr��e gezeichnet. Gewichte gr��er Null m�ssen immer als Ganzes in der Gruppe betrachtet werden. Nehmen wir wieder die "Speichern/Benutzen/Abbrechen"-Gruppe:
Speichern => ICLTAG_Gwk 1 Benutzen => ICLTAG_Gwk 2 Abbrechen => ICLTAG_Gwk 3Die Gruppe hat somit eine Gesamtgewichtanzahl von �6�. Ist das Fenster nun 600 Pixel breit, wird
Speichern => ICLTAG_Gwk 1 => 100 Pixel Benutzen => ICLTAG_Gwk 2 => 200 Pixel Abbrechen => ICLTAG_Gwk 3 => 300 Pixelbreit gezeichnet, was insgesamt zur Fensterbreite von 600 Pixel f�hrt. In diesem Rechenbeispiel wird die �Luft� zwischen den Gadgets nicht ber�cksichtigt. Auch dieser Abstand l��t sich vorgeben: GRPGADTAG_SpaceVert oder GRPGADTAG_SpaceHorz, je nach Gruppe. Auch die Mindestgr��e ist zu definieren; bei Button-Gadgets z.B. mit BUTGADTAG_MinStdWidth und BUTGADTAG_MinStdHeight. Dabei beziehen sich die Zahlenwerte auf den verwendeten Font und entsprechen etwa einem Zeichen.
Soll ein Button nur etwas gr��er als normal sein, gibt es dazu die Tags ICLTAG_AddWidth und ICLTAG_AddHeight. Die Angaben erfolgen hier als Pixelanzahl. F�r die Verbreitung von Buttons k�nnen Sie auch zus�tzliche Leerzeichen im Schaltertext angeben. Dadurch pa�t sich die Gadgetgr��e dynamisch dem Font an. Beachten Sie aber, da� bei Proportionalfonts das Leerzeichen sehr schmal sein kann und dadurch nicht immer das gew�nschte Ergebnis erreicht wird. In unserem Beispielprogramm wollen wir die verwendeten Gadgettypen kurz vorstellen:
Gadget-Typen in p.OS | ||||||||||
|
Weitere m�gliche Tags und ihre Beschreibung entdeckt man in der Datei �p:pInclude/Tags.h�. Hier finden Sie auch die Ableitungen der Gadgets wieder. Beachten Sie, da� einige Gadgets auch die Tags anderer Gadgets verstehen. So k�nnen Sie f�r ein Popup-Gadget die Basis-(LVGADTAG_xxx-)Tags des ListView-Gadgets verwenden. Dadurch kann ein Listview bei Bedarf sehr einfach in ein Popup umgewandelt werden.
Andere Gadgets verstehen durch �Ableitung� die Tags ihrer Basis-Klasse. So verwendet das Textdisplay-Gadget die Tags des Button-Gadget (BUTGADTAG_xxx), das sich wiederum von gadget.class ableitet und die ICLTAG_xxx-Tags versteht. Im Beispielquellcode sehen Sie die korrekte Erzeugung all dieser Gadgettypen, teilweise mit n�tzlichen Informationen.
Wenn der Anwender mit der Maus �ber ein Gadget f�hrt, stellt p.OS nach einer (einstellbaren) Wartezeit einen Suchpfad f�r den Hilfetext zusammen. Dieser generiert sich aus der Fenster-ID, �/� und der Gadget-ID (mehrere getrennt durch �/� m�glich). Danach kann, ebenfalls durch den Schr�gstrich getrennt, der Gadgetzustand folgen (z.B. ON, OFF, DISABLED). Wollen Sie hier keine Unterscheidung machen, k�nnen Sie in der Beschreibung den Joker �*� einsetzen. Auch Default-Texte sind so m�glich, indem z.B. �*ButtonGad� angegeben wird. F�r alle Gadgets mit der ID �ButtonGad�, auch in unterschiedlichen Fenstern, wird derselbe Text erscheinen. Ausnahmef�lle k�nnen Sie zuvor durch den ausgeschriebenen Pfad bearbeiten. Deshalb empfiehlt es sich, die Default-Texte zum Schlu� anzugeben. Der eigentliche Aufbau der Hilfetext-Datei ist recht simpel:
#Hilfe-Suchpfad (mehrzeiliger) Hilfetext #Per Rautenzeichen �#� mit dem Hilfe-Suchpfad wird der Anfang des Hilfetextes markiert, durch ein alleinstehendes �#� das Ende. Dazwischen k�nnen Sie den Hilfetext plazieren, der maximal zehn Zeilen zu je maximal 77 Zeichen haben darf. Es soll sich hier lediglich um eine kurze Hilfebeschreibung zur gew�hlten Funktion handeln (z.B. Auswirkung der Einstellung, auszul�sende Aktion, ...) und nicht um einen Ersatz des Handbuchs.
F�r unser Beispiel eignet sich aber auch das Inline-Hilfetext-Verfahren. Dabei k�nnen Sie auf die beiden Help-IDs im Fenster verzichten und den Hilfetext direkt im Gadget mit angeben. Dabei wird statt einem Suchpfad direkt ein Rautenzeichen, gefolgt vom Hilfetext, angegeben. Mehrzeilige Texte sind ebenfalls m�glich, wobei �*n� als Zeilentrenner zu verwenden ist. Sie k�nnen auch interne und externe Hilfetexte kombiniert einsetzen. Bei den internen Hilfetexten wird nicht zwischen den Gadgetzust�nden unterschieden, da sich nur ein String definieren l��t. Der String kann zur Laufzeit per pOS_SetGadget-Attrs() �ber ICLTAG_HelpID neu festgelegt werden. Der String mu� aber w�hrend der kompletten Laufzeit bestehen bleiben.
Nachdem Sie jetzt alles �ber die Erzeugung der Gadgets wissen, mu� unser Beispielprogramm des ersten Kursteils noch im Message-Loop erweitert werden. Gadgets k�nnen folgende Meldungen verursachen:
Gadget-Meldungen in p.OS | ||||||||
|
Da normalerweise nicht zwischen den einzelnen Ursachen unterschieden werden mu�, k�nnen Sie die komplette Gadgetauswertung in einem Block zusammenfassen. Bei Gadget-Messages steht in �msg->im_IAddress� die Adresse des ausl�senden Gadgets. Es ist zwar auch weiterhin m�glich, per ICLTAG_ID, beim Erzeugen eine Gadget-ID f�r jedes Gadget zu vergeben und sie so zu unterscheiden, empfehlenswerter ist aber die Unterscheidung per Gadget-Adresse.
M�chten Sie feststellen, ob das Gadget zu einer bestimmten Gruppe geh�rt, k�nnen Sie das �ber die Funktion pOS_IsGadgetMember() aus der pGadget.library erfahren. Dazu ist die Gadget-Adresse und die Gruppen-Adresse zu �bergeben. Bedenken Sie, da� bei Benutzung dieser Funktion unbedingt auch die pGadget.library ge�ffnet und am Programmende wieder geschlossen werden mu�!
Im Code-Feld der Message (pOS_IntuiMessage->im_Code) steht unter p.OS ein GUI-Code, der die Aktion genauer beschreibt. Die m�glichen Aktionen sind im �p:pDevice/IEvent.h� nachzulesen (IEGUCODE_xxx). Mit pOS_GetGadgetAttrs() k�nnen Sie dann die aktuellen Daten des ver�nderten Gadgets abfragen. Von direktem Auslesen der Daten aus der Gadget-Struktur ist dringend abzuraten, da nur die Schnittstellen �ber pOS_SetGadget-Attrs() und pOS_GetGadget-Attrs() genormt und einheitlich sind. Ein Gadget kann auch private, unsichtbare Daten enthalten, die somit nicht zug�nglich w�ren. Das Auslesen des aktuellen Gadgetzustands �ber gad->gad_Flags (z.B. GFLG_Selected oder GFLG_Disabled) ist aber m�glich und erlaubt.
Die Kommunikation mit den Gadgets erfolgt �ber die bekannten Tags. Es lassen sich jedoch nicht alle Tags f�r jede Aktion verwenden. Die Verwendbarkeit der Tags wird mit �I� (Init/Create), �S� (Set) und �G� (Get) in den Includes gekennzeichnet. Die aktuellen Daten werden im Messageloop lediglich ermittelt und dann an SetDatas() zur Aktualisierung aller Gadgets weitergegeben. Dabei mu� jedoch beachtet werden, da� die Daten f�r das ausl�sende Gadget nicht gesetzt werden d�rfen! Der Grund ist recht simpel: Fahren Sie z.B. per Maus schnell durch das ListView, ist m�glicherweise bereits ein neuer Eintrag gew�hlt (Multitasking!). Setzen Sie jetzt aber den aktuellen Eintrag wieder auf den alten Wert zur�ck, dann springt der aktuelle Eintrag. M�glichweise wird dadurch auch die letzte Ver�nderung nicht mehr erfa�t.
Damit ist der zweite Kursteil beendet. Die angesprochenen Punkte finden Sie wieder im dokumentieren Sourcecode (�IntuiDemo_2.c�). Ein Beispiel f�r die externe Hilfetextdatei (�IntuiDemo.hlp�) gibt's ebenfalls hier. Im n�chsten Kursteil werden wir unser Beispielprogramm noch um Men�s erweitern.
� Copyright by MagnaMedia Verlag AG, Haar bei M�nchen
Ver�ffentlichung und Vervielf�ltigung nur mit schriftlicher Genehmigung des Verlags