%% LyX 1.5.4 created this file.  For more info, see http://www.lyx.org/.
%% Do not edit unless you really know what you are doing.
\documentclass[twocolumn,ngerman]{article}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\setlength{\parskip}{\medskipamount}
\setlength{\parindent}{0pt}
\usepackage{url}
\usepackage{graphicx}

\makeatletter
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Textclass specific LaTeX commands.
\newenvironment{lyxcode}
{\begin{list}{}{
\setlength{\rightmargin}{\leftmargin}
\setlength{\listparindent}{0pt}% needed for AMS classes
\raggedright
\setlength{\itemsep}{0pt}
\setlength{\parsep}{0pt}
\normalfont\ttfamily}%
 \item[]}
{\end{list}}

\usepackage{babel}
\makeatother

\begin{document}

\title{GTK\texttt{+} mit Forth (1) - GTK Stock Viewer}
\ifx\shorttitle\undefined\else
\shorttitle{GTK Stock Viewer}
\fi

\author{Manfred Mahlow}

%
\begin{figure*}[b]
\begin{center}
\includegraphics[scale=0.78]{2008-03/Viewer}

\caption{\label{fig:Viewer} GTK Stock Viewer unter Ubuntu 6.06}
\end{center}
\end{figure*}


\maketitle
In der VD 02/2008 hatte ich eine GTK\texttt{+}-API für (csp)Forth
vorgestellt. Hier folgt nun ein erstes Anwendungsbeispiel mit einem
gewissen praktischen Nutzen, ein Viewer für den GTK Stock\emph{.}

\begin{multicols}{2}
\section*{Der GTK Stock}

Der GTK Stock ist eine Sammlung von vordefinierten graphischen Objekten,
\emph{GTK Stock Items} genannt. Die Stock Items sind Kombinationen
von Minibildern (Icons), Beschriftungen, Abkürzungsbuchstaben und
Tastenkombinationen, die bevorzugt für Menüeinträge, Dialoge und Knöpfe
verwendet werden sollen, um GTK\texttt{+}-Benutzerschnittstellen ein
einheitliches Aussehen zu geben. Auf die Stock Items kann man über
eindeutige Bezeichner, die \emph{Stock Ids}, zugreifen.

Will man ein bestimmtes GTK Stock Item verwenden, muß man seinen Bezeichner
kennen. Um dazu nicht immer wieder die GTK\texttt{+}-Dokumentation
wälzen zu müssen, bietet es sich an, ein kleines Tool zu schreiben,
mit dem man den Gtk Stock durchstöbern kann.


\section*{Ein GTK Stock Viewer}

In einer der GTK\texttt{+}-Bibliotheken, der \emph{libgtk}, gibt es
eine Funktion \emph{gtk\_stock\_list\_ids}, die einen Zeiger auf eine
Liste aller verfügbaren GTK Stock Items zurückgibt. Man könnte diese
Liste einer \emph{GtkComboBox} zuweisen. Mit dieser könnte man die
Liste anzeigen und ein Listenelement auswählen, das dann als \emph{GtkImage}
und als \emph{GtkButton} angezeigt werden könnte.

Das Ergebnis dieser Überlegungen ist der GTK Stock Viewer in Abbildung
\ref{fig:Viewer}. 



\section*{Der Code}

Der cspForth-Code, der den Viewer auf den Bildschirm zaubert, ist
im Listing 1 zu sehen.

Der Code in den Zeilen 3 bis 9 stellt sicher, dass alle benötigten
GTK\texttt{+}-Widget-Klassen geladen werden (einmaliges Laden der
Quelltextmodule). Außerdem wird die Klasse \emph{GSList} benötigt,
die einfach verknüpfte Listen der libglib zur Verfügung stellt (Zeile
11).

In Zeile 19 wird die bereits erwähnte Funktion \emph{gtk\_stocklist\_ids}
aus der \emph{libgtk} in das Vokabular \emph{gtk api} importiert.

Der Viewer ist ein Beispiel für die Verwendung der Klasse \emph{GtkComboBoxText}.
Für den Viewer legen wir deshalb ein privates Vokabular im Kontext
(in der Wortliste) dieser Klasse an (Zeile 22 u. 24). Privat bedeutet
hier, dass das Vokabular für Objekte der Klasse nicht sichtbar ist.

%
\begin{figure*}[th]
\begin{center}
\includegraphics[scale=0.45]{2008-03/Terminal}

\caption{\label{fig:Status} Status nach dem Laden von Listing 1}
\end{center}
\end{figure*}


In den Zeilen 26 bis 34 werden die für den Viewer benötigten Objekte
definiert:

\begin{description}
\item [{GtkToplevel}] Ein GtkWindow des Typs GTK\_WINDOW\_TOPLEVEL.
\item [{GtkTable}] Ein Container-Widget, in das andere Widgets in Zeilen
und Spalten gepackt werden können.
\item [{GtkLabel~Array}] Ein Array, dessen Elemente Objekte der Klasse
\emph{GtkLabel} (Beschriftungen) sind.
\item [{GtkAlignment~Array}] Ein Array, dessen Elemente Objekte der Klasse
\emph{GtkAlignment} sind. Ein Objekt der Klasse GtkAlignment ist ein
GtkContainer-Widget, in das man ein anderes Widget packen kann, das
horizontal und vertikal ausgerichtet werden kann.
\item [{GtkCombBoxText}] Ein \emph{GtkButton} (Knopf), der mit einer Liste
von Textelementen verbunden ist, die sich auf Knopfdruck öffnet und
aus der man genau ein Element auswählen kann. Das ausgewählte Element
wird als Knopfbeschriftung angezeigt.
\item [{GtkImage}] Ein GtkWidget zur Anzeige eines Bildes, dem das Icon
des ausgewählten GtkStockItems zugewiesen werden soll.
\item [{GtkButton}] Ein Knopf, der mit den Eigenschaften des ausgewählten
GtkStockItems dargestellt werden soll.
\item [{GSList}] Eine einfach verknüpfte Liste für die Handhabung der GTK
Stock Ids.
\end{description}
In Zeile 37 wird ein Signalhandler \emph{cb.quit} definiert, der aufgerufen
werden soll, wenn das Hauptfenster \emph{window} geschlossen wird.

In den Zeilen 39 bis 42 wird ein Signalhandler \emph{cb.changed} definiert,
der ausgeführt werden soll, wenn mit der GtkComboBox ein Listenelement
ausgewählt worden ist. Der Handler liest das ausgewählte Element aus
der GtkComboBox \emph{combo} (Zeile 40) aus und weist es dem GtkButton
\emph{button} und dem GtkLabel \emph{label} zu. 

Die Zeilen 44 u. 45 legen Optionen fest, mit denen die Elemente des
GtkLabel-Arrays und des GtkAlignment-Arrays in das GtkTable-Widget
gepackt werden sollen.

In Zeile 49 beginnt die Initialisierungsroutine des Viewers. Sie initialisiert
die in den Zeilen 26 bis 34 definierten Objekte, erzeugt die Widgets,
packt sie in ihre Container und zeigt dann das Hauptfenster an.

In Zeile 49 wird das Hauptfenster des Viewers initialisiert. Die \emph{init}-Methode
erzeugt ein GtkWindow vom Typ GTK\_TOPLEVEL\_WINDOW und weist diesem
den String, der auf dem Stack übergeben wird, als Titel zu.

In Zeile 50 erhält das Fenster einen inneren Rand von 12 Pixel und
es wird festgelegt, dass die Fenstergröße vom Anwender nicht geändert
werden kann.

In Zeile 51 werden das \emph{destroy}-Signal und der in Zeile 37 definierte
Callback-Handler \emph{cb.quit} an das Hauptfenster gebunden. Damit
wird festgelegt, dass \emph{cb.quit} ausgeführt wird, wenn das Fenster
vom Fenstermanager ein \emph{destroy}-Signal erhält.

In Zeile 53 wird das GtkTable-Widget \emph{table} initialisiert und
in das Hauptfenster \emph{window} gepackt. Anschließend wird in Zeile
54 der Spalten- und Zeilenabstand auf 8 Pixel festgelegt.

Die Tabellengröße muss nicht angegeben werden. Sie wird automatisch
angepasst, wenn Widgets in die Tabelle gepackt werden.

In den Zeilen 56 bis 60 werden die Beschriftungen (GtkLabels) initialisiert
und in die erste Spalte des GtkTable-Widgets gepackt. Die drei Beschriftungen
sind Elemente des Arrays \emph{labels,} das in Zeile 28 definiert
wurde.

Die Initialisierung des Arrays erfolgt in zwei Schritten. Zuerst wird
seine Größe festgelegt (Zeile 56), danach werden dann seine Elemente
initialisiert (Zeile 57-59). 

Die \emph{init}-Methode der Klasse GtkLabel erwartet den Text, der
als Beschriftung angezeigt werden soll, als String auf dem Stack.
Sie erzeugt ein GtkLabel-Widget und gibt dessen Adresse - in Forth
\emph{widget identifier (wid)} genannt - auf dem Stack zurück. Diese
Adresse wird von der \emph{attach}-Methode der Klasse GtkAlignment
verwendet, um das GtkLabel-Widget in die erste Spalte des GtkTable-Widgets
\emph{table} zu packen.

In Zeile 60 werden dann die Beschriftungen in der ersten Spalte des
GtkTable-Widgets \emph{table} rechtsbündig ausgerichtet.

In den Zeilen 62 u. 63 wird das in Zeile 29 definierte GtkAlignment-Array
initialisiert. Seine drei Elemente (GtkAlignment-Widgets) werden in
die zweite Spalte des GtkTable-Widgets \emph{table} gepackt. In die
GtkAlignment-Widgets werden dann das GtkComoBox-Widget \emph{combo},
das GtkImage-Widget \emph{imag}e und das GtkButton-Widget \emph{button}
gepackt (Zeile 64-67) und linksbündig ausgerichtet (Zeile 68).

In den Zeilen 70 bis 74 wird die von der Funktion gtk\_stock\_list\_ids
übergebene Liste der GTK Stock Ids in die GtkComboBox eingetragen.

Alle Widgets sind nun erzeugt, aber noch nicht zu sehen. Sie werden
durch den Code in Zeile 77 sichtbar gemacht.

In Zeile 84 wird der Viewer gestartet. Wurde der cspForth-Prozess,
der den Code ausführt, in einem Terminal gestartet, zeigt das Wort
\emph{??} den aktuellen Zustand des Forth-Systems an (Abbildung \ref{fig:Status}).
Mit cspForth kann dann interaktiv gearbeitet werden und man kann auf
die Widgets des Viewers zugreifen. Die Verarbeitung der Gtk-Ereignisse
erfolgt im Hintergrund, während auf die Eingabe einer Kommandozeile
gewartet wird.

Ist der cspForth-Prozess nicht mit einem Terminal verbunden, gibt
es keine Ereignisverarbeitung im Hintergrund. Es muss dann eine GTK\texttt{+}-Hauptschleife
gestartet werden ({[}ELSE]-Zweig in Zeile 84), die auf Ereignisse
wartet und dann den zugeordneten Code ausführt. Sie wird erst wieder
verlassen, wenn der Callback-Handler cb.quit beim Schließen des Hauptfensters
ausgeführt wird.



\begin{thebibliography}{1}
\bibitem{key-1}GTK+-Dokumentation. http://www.gtk.org

\bibitem{key-2}Matthias Warkus: GNOME 2.0 - Das Entwickler-Handbuch.
Galileo Press, 2003

\bibitem{key-3}Manfred Mahlow: Widgets zum Anfassen - GUI-Skripting
mit Forth und GTK+. Vierte Dimension 2/2008

\end{thebibliography}
%\appendix
%\onecolumn
\end{multicols}

\section*{Listing 1:}

\begin{lyxcode}
~~~1~~\textbackslash{}~GtkComboBoxText/example.2.4th

~~~2~~

~~~3~~~~needs~GtkToplevel

~~~4~~~~needs~GtkTable

~~~5~~~~needs~GtkLabel~Array

~~~6~~~~needs~GtkAlignment~Array

~~~7~~~~needs~GtkComboBoxText

~~~8~~~~needs~GtkImageFromStock

~~~9~~~~needs~GtkButton

~~10~~

~~11~~~~needs~GSList

~~12~~

~~13~~\textbackslash{}~-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-

~~14~~\textbackslash{}~~csp4th~:~~GtkComboBox~Example~2~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~MM-080311

~~15~~\textbackslash{}~-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-

~~16~~

~~17~~~~gtk~api~definitions

~~18~~

~~19~~~~libgtk~import~gtk\_stock\_list\_ids~(~-{}-~{*}list~)

~~20~~

~~21~~

~~22~~~~GtkComboBoxText~definitions

~~23~~

~~24~~~~private~vocabulary~example.2~~self~example.2~definitions~~also~gtk~api

~~25~~

~~26~~~~GtkToplevel~~~~~~~~new~window

~~27~~~~GtkTable~~~~~~~~~~~new~~table

~~28~~~~GtkLabel~Array~~~~~new~~~labels

~~29~~~~GtkAlignment~Array~new~~~alignments

~~30~~~~GtkComboBoxText~~~~new~~~~combo

~~31~~~~GtkImage~~~~~~~~~~~new~~~~image

~~32~~~~GtkButton~~~~~~~~~~new~~~~button

~~33~~

~~34~~~~GSList~new~list

~~35~~

~~36~~

~~37~~~~::~(~wid~data~-{}-~)~2drop~gtk~quit~;~~2~20~cb~cb.quit

~~38~~

~~39~~~~::~(~wid~data~-{}-~)

~~40~~~~~~~2drop~combo~@~dup~if

~~41~~~~~~~~~2dup~image~from-stock~button-size~!~~button~label~!

~~42~~~~~~~then~;~~2~20~cb~cb.changed

~~43~~

~~44~~~~:~\%label~(~-{}-~xopts~yopts~xpad~ypad~)~~~~~GTK\_FILL~0~~0~0~;

~~45~~~~:~\%alignment~(~-{}-~xopts~yopts~xpad~ypad~)~GTK\_FILL~0~12~0~;

~~46~~

~~47~~~~:~viewer~(~-{}-~)

~~48~~~

~~49~~~~~~~~\char`\"{}~Gtk~Stock~Item~Viewer\char`\"{}~window~init

~~50~~~~~~~~12~window~border-width~!~~~window~resizable~off

~~51~~~~~~~~\char`\"{}~destroy\char`\"{}~cb.quit~0~window~signal~connect~drop

~~52~~

~~53~~~~~~~~table~init~~window~add

~~54~~~~~~~~8~table~column-spacing~!~~8~table~row-spacing~!

~~55~~

~~56~~~~~~~~3~labels~init

~~57~~~~~~~~\char`\"{}~Stock~Item:\char`\"{}~0~labels~of~init~~0~1~0~1~\%label~table~attach

~~58~~~~~~~~\char`\"{}~Image:\char`\"{}~1~labels~of~init~~~~~~~0~1~1~2~\%label~table~attach

~~59~~~~~~~~\char`\"{}~Button:\char`\"{}~2~labels~of~init~~~~~~0~1~2~3~\%label~table~attach

~~60~~~~~~~~3~0~do~i~labels~of~xalign~right~loop

~~61~~

~~62~~~~~~~~3~alignments~init

~~63~~~~~~~~3~0~do~i~alignments~of~init~~1~2~i~dup~1+~\%alignment~table~attach~loop

~~64~~~~~~~~combo~init~~0~alignments~of~add

~~65~~~~~~~~\char`\"{}~changed\char`\"{}~cb.changed~0~combo~signal~connect~drop

~~66~~~~~~~~\char`\"{}~?\char`\"{}~image~from-stock~button-size~init~~1~alignments~of~add

~~67~~~~~~~~\char`\"{}~?\char`\"{}~button~init~~2~alignments~of~add

~~68~~~~~~~~3~0~do~i~alignments~of~xalign~left~loop

~~69~~

~~70~~~~~~~~gtk\_stock\_list\_ids~list~init

~~71~~~~~~~~~~list~size~dup~1-~swap~0~do

~~72~~~~~~~~~~~~dup~i~-~list~of~@~dup~zcount~combo~append~~free

~~73~~~~~~~~~~loop~drop

~~74~~~~~~~~list~free

~~75~~~~~~~~0~combo~activate

~~76~~

~~77~~~~~~~~window~show~all

~~78~~~~;

~~79~~

~~80~~~~hide~cb.quit~~hide~cb.changed

~~81~~

~~82~~~~previous

~~83~~

~~84~~~~viewer~term?~{[}IF]~??~{[}ELSE]~gtk~main~bye~{[}THEN]

~~85~~\textbackslash{}~-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-

~~86~~\textbackslash{}~Last~revision:~MM-080525

~

\end{lyxcode}
\vfill
\begin{center}
\includegraphics[height=7cm]{2008-03/profile-of-time}\\
Salvador Dali: \emph{Profil der Zeit}\\ Die Bronze ist im \emph{Arkady Wrocławskie} Einkaufszentrum in Breslau ausgestellt.\\
(Photo: Wikimedia/Julo, 4/2008)
\end{center}
\vfill

\end{document}

