2016-11-25 00:33:18 -07:00

1196 lines
53 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<title>How EuGTK Works</title>
<link rel="stylesheet" href="style.css" type="text/css">
</head>
<body>
<heading>
<img src="../thumbnails/mongoose.png" alt="mongoose" />
<img src="../thumbnails/gtk-logo-rgb.gif" alt="gtk logo align="left" height="100px" />
<img src="../thumbnails/gnome-run.png"alt="gnome-run" align="right" />
<h2> <hr />How EuGTK Works<hr /> </h2>
</heading>
<nav>
<div class="hdr">Quick Links:</div>
<a href="#create"><button>Create</button></a>
<a href="#keywords"><button>Key Words</button></a>
<a href="#properties"><button>Properties</button></a>
<a href="#set"><button>Set</button></a>
<a href="#get"><button>Get</button></a>
<a href="#connecting"><button>Linking to Eu Funcs</button></a>
<a href="#datapassing"><button>Passing Data</button></a>
<a href="#calendar"><button>Calendars</button></a>
<a href="#colors"><button>Colors</button></a>
<a href="#settings"><button>Settings</button></a>
<a href="#debugging"><button>Debugging</button></a>
<a href="#memory"><button>Memory Usage</button></a>
<br />
<div class="hdr">Other Files:</div>
<a href="README.html"><button>README</button></a>
<a href="guide_a.html"><button>Alphabetical Guide</button></a>
<a href="dialogs.html"><button>Built-in EuGTK Dialogs</button></a>
<a href="treeviews.html"><button>ListView/TreeView widgets</button></a>
<a href="pango_markup.html"><button>Markup</button></a>
<a href="printing.html"><button>Printing</button></a>
<a href="ServerHelp.html"><button>Web Server</button></a>
<a href="functions.html"><button>Quick Function List</button></a>
<a href="Glade.html"><button>Glade GUI Builder</button></a>
<a href="platforms.html"><button>Platforms</button></a>
<br />
</nav>
<h3><hr />Overview:<hr /></h3>
<div class="quote">
<blockquote cite="http://gtk.org">
From the GTK docs:
<p class="small">
"A GTK+ user interface is constructed by nesting widgets inside widgets.
Container widgets are the inner nodes in the resulting tree of widgets:
they contain other widgets. So, for example, you might have a GtkWindow
containing a GtkFrame containing a GtkLabel. If you wanted an image instead
of a textual label inside the frame, you might replace the GtkLabel widget
with a GtkImage widget.
</p>
<p class="small">
There are two major kinds of container widgets in GTK+. Both are subclasses of
the abstract GtkContainer base class.
The first type of container widget has a single child widget and derives from
GtkBin. These containers are decorators, which add some kind of functionality
to the child. For example, a GtkButton makes its child into a clickable button;
a GtkFrame draws a frame around its child and a GtkWindow places its child
widget inside a top-level window.
</p>
<p class="small">
The second type of container can have more than one child; its purpose is to
manage layout. This means that these containers assign sizes and positions to
their children. For example, a GtkBox arranges its children in a horizontal
[or vertical] row, and a GtkGrid arranges the widgets it contains in a
two-dimensional grid."
</p>
</div>
</blockquote>
<p>
To reiterate the last point: GTK does <i><b>not</b></i> expect the programmer to specify
position and size of each widget as is required when programming for Windows&trade;.
GTK handles these things automatically, adjusting things 'on-the-fly', as the user resizes
windows, changes fonts, etc... which makes your programs more user-friendly.
</p>
<div class="quote">
<blockquote cite="gtk.org">
Quote:
<p class="small">
"Note the inherent danger of setting any fixed size - themes, translations into other languages,
different fonts, and user action can all change the appropriate size for a given widget.
So, <u>it's basically impossible to hardcode a size that will always be correct.</u>
"
</p>
</blockquote>
</div>
<p>
If you are accustomed to writing programs for Windows&trade;, you'll wonder why there's not
a complex IDE to help lay out your GTK program interface. The answer is: because it's not necessary!
You don't need to specify sizes and positions for GTK controls, GTK takes care of that task for you.
Your main job will be writing Euphoria functions, for which a plain old text editor works
just fine! You do have the option to use Glade to design your program interface if you wish.
See <a href="Glade.html">Glade.html</a>.
</p>
<a name="keywords"></a>
<h3><hr />Keywords<hr /></h3>
<p>EuGTK allows you to program in an object-oriented style.</p>
<p>
There are only a handful of new keywords to know. You can create nice-looking, functional
programs with only the six shown here:
<ul>
<li><a href="#create">create</a>
<dd>declare a new instance of a given GTK object</dd>
</li>
<li><a href="#set">set</a>
<dd>modify a property of an object</dd>
</li>
<li><a href="#get">get</a>
<dd>retrieve a property of an object</dd>
</li>
<li><a href="#connecting">connect</a>
<dd>instructs an instance to respond to an event (a.k.a. signal)</dd>
</li>
<li><a href="functions.html#functions">show_all</a>
<dd>make a container and all objects contained therein visible</dd>
</li>
<li><a href="functions.html#functions">main</a>
<dd>start the GTK main event loop, waiting for user input</dd>
</li>
</ul>
</p>
<p>
You'll find a more complete list of keywords in <a href="functions.html">functions.html</a>
</p>
<a name="create"></a>
<h3><hr />Create<hr /></h3>
<p>
New instances of EuGTK containers and controls (collectively called <i>'widgets'</i> in GTK)
are created by calling the <i>create()</i> function with a class name.
These class names are enumerated in GtkEnums.e,
and they are the same as those used by the GTK
docs. These class names are the <i>ONLY</i> ones you can send to
the <i>create()</i> function. Never try numbers or strings. No quotes. Spelling counts!
</p>
<p>
The <i>create()</i> function returns a <i>'handle'</i> (a.k.a. pointer) to the newly created
instance.
That handle can (and usually should) be saved in a Euphoria constant for later access:
<pre>
<em class="kw">constant</em> win = <em class="gtk">create</em>(GtkWindow) <em>-- generally, a constant is best, because you won't be changing these;</em>
</pre>
Parameters, if any, which follow the class name vary, and are often optional.
Refer to the demo programs and the GTK docs for details. Also, explore the new, more compact <a href="README.html#syntax">syntax options</a> for the create() function <a href="README.html#syntax">here</a>, as well as <a href="#variants"> variants</a>, below.
</p>
<p>
GtkEngine.e maintains a list of currently created GTK containers and controls, and directs calls from your Euphoria program to the appropriate
'method' based on the type of widget and whether the call is to <a href="#set">
set</a> or to <a href="#get">get</a> one of that widget's <a href="#properties">properties</a>.
</p>
<a name="properties"></a>
<h3><hr />Properties<hr /></h3>
<p>
Every GTK widget has a list of <i>properties</i> which can be written to
or read from. For example, a window has a <i>title</i>, a <i>border width</i>,
a <i>default size</i>, etc.
</p>
<p>
Widgets which display information or accept input from users have properties such as
<i>text</i> for labels and text entries, <i>value</i> for numeric widgets, and <i>active</i>
for widgets such as checkboxes.
</p>
<p>
To find out what properties exist for a given widget, refer
to the GTK docs. Remember that widgets inherit properties from ancestor widgets, so if
you don't find a property for a given widget, follow the Object Hierarchy links in the GTK docs.
As an example, you can select the <i>font</i>, <i>background</i> or text <i>color</i> for a window,
but these properties are actually implemented by GtkWindow's ancestor the GtkWidget,
whereas <i>border width</i> is actually implemented by the GtkWindow's ancestor GtkContainer.
But you don't need to be concerned about this, all you need do is tell the window what to do, and it - or its parents or grandparents - will see that it gets done.</p>
</p>
<p>
EuGTK takes care of finding these ancestor properties for you, but if you don't
read the GTK docs, you won't be aware that these properties are available!
In many cases you can just use common sense: for example, if it seems reasonable that a window
should be able to have a blue background, just try it: <code>set(win,"background","blue")</code>.
If you try something that isn't possible, such as setting a window's <i>text</i>, for example,
you will get an error message on your terminal such as:
<br />
<div class="scrn"><tt>
object class 'GtkWindow' has no property named 'text'
</tt></div>
</p>
<div class="hint">
<img class="hint" src="../thumbnails/hint.png" alt="hint" width="100px" align="left" float="right" />
<p>Remember, when writing your EuGTK programs, you <i><u>must</u></i> run them from a terminal,
in order to see warnings such as the one above!</p>
</div>
<a name="set"></a>
<h3><hr />Set<hr /></h3>
<p>
The set() function takes a 'handle' to a control, plus a 'property' to
be set. Handle is <i>almost</i> always an atom (as assigned by the create() function),
except when you are using Glade to design your interfaces, when you often use the name of the control in string form, e.g. "button1"
or "help:window".
</p>
<p>
'property' is always a string! Following those are one or more parameters. The type and number of
parameters requred must be determined by looking at the GTK documentation
and the sample programs included here.
Some examples:
<pre>
<em class="gtk">set</em>(win,<em class="str">"title","My Program"</em>)
<em class="gtk">set</em>(win,<em class="str">"border_width"</em>,<em class="orange">10</em>)
<em class="gtk">set</em>(win,<em class="str">"default_size"</em>,<em class="orange">300,200</em>)
<em class="gtk">set</em>(<em class="str"><b>"help:window"</b>,"Title","Using EuGTK"</em>) <em>-- using widget name</em>
<em> -- the window directly above is created in an include file
-- which has the namespace "help"</em>
</pre>
</p>
<div class="hint">
<img class="hint" src="../thumbnails/hint.png" alt="hint" width="100px" align="left" float="right" />
<p>
Note that you can use <i>widget names</i> to refer to controls, rather than handles,
<i>if</i> you give the control its own individual name.
<br />(When using Glade, a name will be assigned automatically.)
</p>
</div>
<p>
For example: <code>win = <em class="gtk">create</em>(GtkWindow,<em class="str">"<b>name=Main Window</b>,size=400x300"</em>)</code>
<br /><br />In the above line, you have named this window, and so can refer to it as
"Main&nbsp;Window" in future set() or get() calls. Sometimes this can come in handy,
resulting in more-readable code.
</p>
<p>
If you supply too many parameters, like:
<pre>
<em class="gtk">set</em>(win,<em class="str">"title","My Program", "well isn't that swell?"</em>,<em class="orange">1,2,3</em>)
</pre>
That won't usually cause any problem; the excess parameters are just discarded.
You'll get an error message if you get carried away and try to send more than 10.
</p>
<p>
Too few parameters will usually cause problems, if not crashes, because unfilled values
default to zero:
<pre>
<em class="gtk">set</em>(win,<em class="str">"default_size"</em>)
</pre>
This will set the window size to 0x0 pixels, i.e: nothing, which will make it
kinda hard to see! No error message can help in this case, since such a
setting <i>could</i> - for some strange reason - be intentional.
</p>
<p>
Mismatched parameter types - sending a string where an atom or integer is expected, or vice-versa -
will usually give an error message, but
sometimes a crash (segfault) is unavoidable. Again, read the GTK docs!
</p>
<a name="get"></a>
<h3><hr />Get<hr /></h3>
<p>
The get() function takes a 'handle' to the control, plus a 'property' to
be looked up. Handle is always an atom, except when using Glade to design your
interface, in which case it is sometimes a string. And 'property' is always a string!
Some examples:
<pre>
<em class="gtk">get</em>(win,<em class="str">"title"</em>) <em>-- returns a string if a title was set, 0 otherwise</em>
<em class="gtk">get</em>(win,<em class="str">"border_width"</em>) <em>-- returns an integer (pixels), 0 if unset</em>
<em class="gtk">get</em>(win,<em class="str">"default_size"</em>) <em>-- returns a sequence {x,y} e.g: {300,200} or {-1,-1} if unset</em>
<em class="gtk">get</em>(<em class="str"><b>"prefs:spinbutton1"</b>,"value"</em>) <em> -- returns an atom or integer</em>
</pre>
Sending the wrong number of parameters to the get() function will
very likely cause problems! Sometimes a machine-level exception (signal 11).
Fortunately, this is easy to avoid, as there normally AREN'T ANY
parameters to 'get', other than the handle and the property name.
</p>
<a name="conveniences"></a>
<h3><hr />Conveniences<hr /></h3>
<p>
A few very frequently-used functions have simpler 'shorthand' ways to call them:
<table border="1">
<tr>
<th>Function</th><th>Parameters</th><th>Shorthand</th><th>Parameters</th>
</tr>
<tr>
<td>&nbsp;set(x,"add",z)&nbsp;</td>
<td rowspan="7">
<i>For functions on the left,<br /><hr /><b>&nbsp;x</b></i></i> and <i><b>z</b></i> must be atoms<br />
&nbsp;(widget handles)&nbsp;<br />
&nbsp;or widget names as strings</td>
<td>&nbsp;add(x,z)<em>*</em>&nbsp;</td>
<td rowspan="5"><i>For shorthand notation,<br /><hr />
<b>&nbsp;x</b></i> must be an atom&nbsp;<br /> &nbsp;(a widget handle)<br />or a widget name as a string<br />
<br />&nbsp;<em><big>*</big></em> <i><b>z</b></i> can be a handle<br />&nbsp;or a {list} of handles</td>
</tr>
<tr>
<td>&nbsp;set(x,"show")</td><td>&nbsp;show(z)<em>*</em>&nbsp;</td>
</tr>
<tr>
<td class="emphasis">&nbsp;set(x,"show_all")</td><td class="emphasis">&nbsp;show_all(z)&nbsp;</td>
</tr>
<tr>
<td>&nbsp;set(x,"hide")</td><td>&nbsp;hide(z)<em>*</em></td>
</tr>
<tr>
<td class="emphasis">&nbsp;set(x,"hide all")</td><td class="emphasis">&nbsp;hide_all(z)</td></tr>
</table>
</p>
<p>
These shortcut methods not only save a bit of typing, but more importantly, allow you to send <i>{lists}</i> of items, rather
than calling the routine over and over, once for each item. <i>{lists}</i> are simply sequences of one or more
handles to widgets. For example:
<pre>
<em class="gtk">add</em>(panel,{img1,btn1,btn2,btn3})
<em>-- or</em>
<em class="gtk">add</em>(panel,x) <em> -- where x can be a {list} of handles to any number of objects, of mixed types (don't all have to be buttons!)')</em>
<em>-- or</em>
<em class="gtk">add</em>(panel,x[1..5]) <em>-- you can send slices as well</em>
</pre>
</p>
<p>
GTK provides two 'pack' methods: pack_start and pack_end, which are identical except for direction.
The original calls are still there, but for added convenience, I've also provided <i>pack</i>, which uses the - (neg.) sign to indicate <i>pack at end</i>. This may be helpful when packing several items in one call.
<pre>
<em class="gtk">pack</em>(panel,btn1) <em>-- pack_start (top to bottom for vert. containers, left to right for horiz.)</em>
<em>-- or</em>
<em class="gtk">pack</em>(panel,-btn1) <em>-- pack_end (this item will go at the bottom / far right of the container)</em>
</pre>
</p>
<a name="variants"></a>
<h3><hr />Variants<hr /></h3>
<p>
There are some GTK widgets which have multiple ways to create
them. An image, for example, might be created from:
<ul>
<li>a file ~ *.jpg, .png, .gif, etc...</li>
<li>a stock item ~ "gtk-ok", "gtk-cancel", etc...</li>
<li>a pixbuf previously created or loaded from a file.</li>
<li>a themed icon ~ from one of the hundreds supplied: "face-cool", for example.</li>
<li>something else ~ a GIcon, perhaps.</li>
<li>or nothing at all</li>
</ul>
</p>
<p>
EuGTK tries to figure out which you want by examining the params (if any) you send
to the create() function:
<pre>
<em class="kw">constant</em> img = <em class="gtk">create</em>(GtkImage)
<em>--it seems you want an empty container which can hold an image to be set at a later time.</em>
<em class="kw">constant</em> img = <em class="gtk">create</em>(GtkImage,<em class="str">"~/demos/thumbnails/BabyTux.jpg"</em>)
<em>-- looks like you want to create this from the file named, if such file exists.
-- Note: cannonical_path() is automatically called to convert the filename/path to a usable form.</em>
<em class="kw">constant</em> img = <em class="gtk">create</em>(GtkImage,<em class="str">"gtk-ok"</em>,GTK_ICON_SIZE_DIALOG)
<em>-- looks like you want a stock image, in the size given.
-- Note: any name beginning with "gtk-" is considered to be a stock item</em>
<em class="kw">constant</em> img = <em class="gtk">create</em>(GtkImage,<em class="str">"face-smile"</em>,GTK_ICON_SIZE_DIALOG)
<em>-- you want an icon, as named, from the current icon theme, in the size specified.
-- size can be either one of the GTK_ICON_SIZE_ enums, or can be a pixel value,
-- usually between 16 and 256.</em>
<em class="kw">constant</em> pix = <em class="gtk">create</em>(GdkPixbuf,<em class="str">"~/demos/thumbnails/mongoose.png"</em>,<em class="orange">80,80</em>,TRUE)
<em class="kw">constant</em> img = <em class="gtk">create</em>(GtkImage,pix)
<em>-- by creating a pixbuf from the file, you can specify a size for the image,
-- plus, you have a static pixbuf object which can be re-used.
-- If you create an image directly from a file, you can't resize or re-use that image </em>
</pre>
</p>
<a name="connecting"></a>
<h3><hr />Connecting controls to functions<hr /></h3>
<p>
It should be obvious, but just to be clear, GTK programs, like Windows&trade; programs,
Apple&trade; programs, and almost every other computer program written in the last few decades,
are <i>event driven</i>. If you aren't sure what that means, find out before you begin designing your
nifty new program.
</p>
<p>
Your program will need to respond to user actions (events). The various
events emit signals, for example, a button click emits a "clicked" signal.
Your job is to connect a widget's signal to the appropriate function to handle the
event.
<pre>
<em class="gtk">connect</em>(win,<em class="str">"destroy","Quit"</em>) -- <em><u>Always</u> do this for the main window!</em>
</pre>
Where <i>win</i> is the handle, <i>"destroy"</i> [always a string] is a signal,
a.k.a. the name of an event. <i>"Quit"</i> is what to do in that event. The example above will
call the function Quit() when the program's main window is destroyed.
Quit() - a function exported by GtkEngine.e - then shuts down the GTK engine and frees memory it has allocated.
</p>
<p>
Quit() is one of very few <i>built-in</i> EuGTK functions you will need to connect to.
Most other connections will be made to Euphoria functions YOU write.
Any Euphoria function used for this purpose must be:
<ol>
<li>A function, not a procedure</li>
<li>Visible to the code doing the calling</li>
</ol>
</p>
<p>
You usually do not have to write a separate line of code to connect a widget to a function. The most commonly-used widgets have a convenient way to make that connection
at the time the widget is created, which leads to cleaner and easier to maintain code:
<pre>
<em>(A)</em> <em class="kw">constant</em> btn1 = <em class="gtk">create</em>(GtkButton,<em class="str">"gtk-ok","Foo"</em>,<i>42</i>)
<em>(B)</em> <em class="kw">constant</em> btn1 = <em class="gtk">create</em>(GtkButton,<em class="str">"gtk-ok","Foo","Hello World!"</em>)
<em>(C)</em> <em class="kw">constant</em> <b>foo</b> = call_back(routine_id(<em class="str">"Foo"</em>))
<em class="kw">constant</em> btn1 = <em class="gtk">create</em>(GtkButton,<em class="str">"gtk-ok"</em>,<b>foo</b>,<em class="str">"Hello World!"</em>)
</pre>
<div class="hint" style="width:100%">
<em>(D)</em> <b>New in 4.11.4!</b><pre>
<em class="kw">constant</em> btn1 = <em class="gtk">create</em>(GtkButton,"gtk-ok",<b><em>_("Foo")</em></b>,[...])
<em class="blue">The <b><em>_()</em></b> function allows linking to <i>local</i> functions, instead of global.
It works better than call_back(routine_id()), since it can
'look forward' to find functions which are defined
further down in your code, allowing cleaner program structure.
Thanks to Greg Haberek for this function.
</em></pre>
</div>
</p>
<p>
In any of the calls above, you are making a new button with the stock OK image, connecting its default signal (which is <i>'clicked'</i>, in the case of a button) to
call your Euphoria function Foo(), and optionally sending some object
as the data parameter to that function.
The data item is always optional, and can contain almost anything you
want.
</p>
<p>
See <a href='#datapassing'>Data passing</a> below for examples of how to pass
various data types to your Euphoria functions.
</p>
<p>
If you use method <em>(A)</em> or <em>(B)</em> then your Euphoria function declaration could look like this:
<pre>
<em>--------------------------------------------------------------</em>
<em class="kw"><b>global</b> function</em> Foo(<em class="kw">atom</em> <i>ctl</i>, <em class="kw">object</em> <i>data</i>) <em>-- must be global!</em>
<em>--------------------------------------------------------------</em>
</pre>
If you use method <em>(C)</em> or <em>(D)</em> then you can declare your Euphoria functions as local functions, not global:
<pre>
<em>-----------------------------------------------------------</em>
<em class="kw">function</em> Foo(<em class="kw">atom</em> <i>ctl</i>, <em class="kw">object</em> <i>data</i>)
<em>-----------------------------------------------------------</em>
</pre>
</p>
<p>
The parameter <i>ctl</i> will be filled in with the handle of the control which
dispatched the call, and <i>data</i> will be the data attached to that control,
or null if no data value was provided.
</p>
<p>
If you compile a program which uses method <em>(A)</em> or <em>(B)</em> to link to functions, it may compile
without error, but you will get a run-time error on the terminal like the following:
<br clear="all" />
<div class="scrn" width="80%"><pre>Error: function Foo is not in scope
****** (make it global or link via routine_id)</pre>
</p>
</div>
<br clear="all" />
<p>
Use the COMPILE flag for a way to quickly detect these errors in advance, before you go to the trouble of compiling.
<div class="scrn">
$ eui -d COMPILE myprogram.ex
</div>
</p>
<h4>Connections, alternate methods</h4>
<p>
You can also connect signals to controls by typing a separate line:
<pre>
<em>(1)</em><em class="gtk"> connect</em>(btn1,<em class="str">"clicked","Foo"</em>,[...]) <em>-- global function</em>
<em>(2)</em><em class="gtk"> connect</em>(btn1,<em class="str">"clicked"</em>,call_back(routine_id(<em class="str">"Foo"</em>)),[...])
<em>(3)</em><em class="gtk"> connect</em>(btn1,<em class="str">"clicked"</em>,_(<em class="str">"Foo"</em>),[...]) <em>-- local function</em>
<em>(4)</em> <em class="kw">constant</em> foo = <em class="kw">call_back(routine_id</em>(<em class="str">"Foo"</em>))
<em class="gtk">connect</em>(btn1,<em class="str">"clicked"</em>,foo,[...])
</pre>
You might use this method instead of the previous one
if you want to connect a signal other than the default, or if there is no default signal provided for
that control. See GTK docs for appropriate signal names, and GtkEngine.e for the implemented defaults
(around line 348 in the create() function). Again, if you plan to compile, use call_back(routine_id()) as shown in <em>(2)</em>, <em>(3)</em> or <em>(4)</em>.
</p>
<a name="caution"></a>
<p><h4>Function Parameters</h4>
<p>Different controls can pass different types and number of parameters to your Euphoria "handler" functions when activated, so be sure to check the GTK docs for the particular widget/signal you are using. The GTK docs usually show a prototype of an appropriate signal handler.</p>
Often, your Euphoria functions can ignore the parameters that GTK passes to them.
If you do not need to access these parameters, just don't bother to declare them!
</p>
<div class="hint">
<img class="hint" src="../thumbnails/hint.png" alt="hint" width="100px" align="left" float="right" />
<p>Note that you can connect <i>more than one signal</i> and/or <i>more than one function</i> to a control.
The calls will be executed in order.
To do this, use the alternate 'connect' syntax as shown in <em>(1,2,3)</em> above,
repeating the connect line for each different function or signal to be called.
</p>
<hr />
<p>
A practical application of this might be to trap your main window's "delete-event" signal first,
perhaps calling a routine that saves your work if necessary, then allowing (or not) the "destroy" event to call the "Quit" function to end the program.
</p>
<div class="quote">
<p>
<pre><code><em class="kw">constant</em> win = <em class="gtk">create</em>(GtkWindow)
<em class="gtk">connect</em>(win,<em class="str">"delete-event"</em>,_(<em class="str">"AreYouSure"</em>)) <em>--[1]</em>
<em class="gtk">connect</em>(win,<em class="str">"destroy","Quit"</em>) <em>--[2]</em>
<em>-- note 1: this will be called first</em>
<em>-- note 2: this may be called next, depending upon the</em>
<em>-- value returned by #1</em>
<em>-------------------------------------------------</em>
<em class="kw">function</em> AreYouSure()
<em>-------------------------------------------------</em>
<em class="kw">if</em> dirty <em class="kw">then</em>
<em>-- *save it* code goes here</em>
<em class="kw">end if</em>
<em class="kw">return</em><em class="gtk"> Question</em>(win,,<em class="str">"OK to Quit?"</em>) != MB_YES
<em class="kw">end function</em>
</code></pre>
</p>
</div>
<p>
The value returned by the first function will determine whether the succeeding function(s) will be called or skipped. Note that we use the syntax <i>not equal MB_YES</i>. This is so closing the popup Question dialog window without actually answering YES or NO will not kill the program.
</p>
<p>
If a 1 is returned from the first called function, then succeeding functions will <i>NOT</i> be called, and
a 0 will allow the succeeding function(s) to be called. One way to look at this so it makes sense is to think
of the return value as a report: A 1 or TRUE means "I've handled this myself, don't bother any further", while
a zero or FALSE means "I've done what I can, it's your turn now!".
</p>
</div>
<p>
If you find that you need to be able to <i>disconnect</i> a signal,
use this alternate method, and save the signal_id:
<pre><em class="kw"> integer</em> sigid = <em class="gtk">connect</em>(btn1,<em class="str">"clicked"</em>,....)
</pre>
so that later, you can disconnect that signal by calling:
<pre> <em class="gtk">disconnect</em>(btn1,sigid)
</pre>
Do not use this to disable a control, because it does not change the appearance
to indicate that the control is disabled. Instead, use
<pre> <em class="gtk">set</em>(btn1,<em class="str">"sensitive"</em>,<em class="kw">FALSE</em>)
</pre>
</p>
<h3><hr />How to figure out which control was activated<hr /></h3>
<p>
Since you can connect several controls to a single Eu function, your function may need to determine which
control is doing the calling.<br /><br />
As a rule, the first parameter passed to a called Eu function will be the
handle of the control that was activated.
The second parameter is usually the data attached
when the connection was made.<br /><br />
These 'rules' vary on occasion. See the GTK docs for a prototype of the respective callback routine.<br />
<br />Here are two ways to determine which control was activated:
<pre><code><em>--------------------------------------------</em>
<em class="kw">function</em> Foo(atom ctl, atom data)
<em>--------------------------------------------</em>
<em>-- within this function, you might choose to:</em>
</code></pre>
<ol>
<li>Match the ctl parameter to known control handles</li>
<small>
<ul><li><em class="kw">switch </em>ctl <em class="kw">do</em><br />
&nbsp;&nbsp;<em class="kw">case</em> btn1 <em class="kw">then</em> ...<br />
&nbsp;&nbsp;<em class="kw">case</em> btn2 <em class="kw">then</em> ...</li></ul><br />
</small>
<li>Use the data parameter to pass a unique identifier</li>
<small>
<ul><li><em class="kw">if</em> data = 42 <em class="kw">then</em> ...</li></ul>
</small></ul></small>
</ol>
<b>Note:</b> <br />
For control groups (such as RadioButtons), which send a 'toggled' signal,
there will be <b><i>two</i></b> controls responding to events,
and thus two calls to your Eu function!
<ul>
<li>One call being from the previously-selected button
as it is toggled to the de-activated state.</li>
<li>The other being
from the newly-selected button as it is toggled to the activated state.
</ul>
You must check the 'active' property
to see which of the two you should respond to. In some cases, you may want to respond to
<i>both </i>, deactivating or closing one thing, and activating or showing another, for example.
<ul><li><em class="kw">if</em> <em class="gtk">get</em>(ctl,<em class="str">"active"</em>) <em class="kw">then ...</em> <em>-- this is the one just clicked</em></li></ul>
</p>
<a name='datapassing'>
<h3><hr />Data passing<hr /></h3>
</a>
<p>
Frequently, it is convenient to be able to attach data items to an individual control,
which that control will pass to functions it calls when activated. One advantage of doing things this way
is that it allows you to write a single Eu function which can handle events from multiple controls.
Another advantage is that it makes your code easier to read and maintain.<br /><br />
Depending upon the method chosen, the data can be almost anything, from a simple integer to
a complex Euphoria sequence containing strings, pointers, routine_id's, and perhaps even images
or other GTK 'widgets'.
</p>
<h4>Method 1</h4>
<p>
Often it is enough to simply attach the data to a control's data space, as in the examples
below. This is also the cleanest and most readable method.
</p>
<p>
<pre>
<b class="x">(1) -- passing an integer</b>
<em class="kw">constant</em>
btn1 = <em class="gtk">create</em>(GtkButton,<em class="str">"Justin"</em>,_(<em class="str">"DisplayAge"</em>),<em class="brown">17</em>),
btn2 = <em class="gtk">create</em>(GtkButton,<em class="str">"Jamie"</em>,_(<em class="str">"DisplayAge"</em>),<em class="brown">15</em>)
<em>---------------------------------------------------------------</em>
<em class="kw">function</em> DisplayAge(<em class="kw">atom</em> ctl, <em class="kw">integer</em> age)
<em>---------------------------------------------------------------</em>
<em class="kw"> printf</em>(1,<em class="str">"Age = %d\n"</em>,age)
Integers are passed and used directly, with no conversion needed.
All other data types are passed as pointers,
and must be 'decoded' by using the unpack() function.
<b class="x">(2) -- passing a float</b>
<em class="kw">constant</em> btn1 = <em class="gtk">create</em>(GtkButton,<em class="str">"gtk-ok"</em>,_(<em class="str">"Foo"</em>),<em class="brown">123.456</em>)
<em>---------------------------------------------------------------</em>
<em class="kw">function</em> Foo(<em class="kw">atom</em> ctl, <em class="kw">object</em> data)
<em>---------------------------------------------------------------</em>
<em class="kw">atom</em> num = <em class="gtk">unpack</em>(data)
The unpack() function will return an atom
<b class="x">(3) -- passing a string</b>
<em class="kw">constant</em> btn1 = <em class="gtk">create</em>(GtkButton,<em class="str">"gtk-ok"</em>,_(<em class="str">"Foo"</em>),<em class="str">"James Brown"</em>)
<em>---------------------------------------------------------------</em>
<em class="kw">function</em> Foo(<em class="kw">atom</em> ctl, <em class="kw"><b>object</b></em> data) <em>-- must be object</em>
<em>---------------------------------------------------------------</em>
data = <em class="gtk">unpack</em>(data)
The unpack() function will return a string
<b class="x">(4) -- passing a Euphoria sequence {} containing almost any mix of data </b>
<em class="kw">constant</em>
btn1 = <em class="gtk">create</em>(GtkButton,<em class="str">"_Pie"</em>,_(<em class="str">"Foo"</em>),<b>{</b><em class="str">"Apple Pie"</em>,<em class="brown">1.95</em><b>}</b>),
btn2 = <em class="gtk">create</em>(GtkButton,<em class="str">"_Cake"</em>,_(<em class="str">"Foo"</em>),<b>{</b><em class="str">"Carrot Cake"</em>,<em class="brown">2.10</em><b>}</b>)
<em>---------------------------------------------------------------</em>
<em class="kw">function</em> Foo(<em class="kw">atom</em> ctl, <em class="kw">object</em> data) <em>-- must be object</em>
<em>---------------------------------------------------------------</em>
data = <em class="gtk">unpack</em>(data)
<em class="gtk">Info</em>(win,<em class="str">"Flo's Bakery"</em>,
<em class="kw">format</em>(<em class="str">"Two orders of [1]"</em>,data),
<em class="kw">format</em>(<em class="str">"$[2.2]"</em>,data*2))
The unpack() function will return a sequence
</pre>
</p>
</p>
<h4>Method 2</h4>
<p>
Sometimes, the best way to pass multiple data values of varying types might be with Euphoria's map functions.
One advantage of this method is that it allows you to access the values by
name, rather than by position, as shown in the method above. The disadvantage - verbosity.</p>
<img src="../screenshots/test84.jpg" alt="test84" align="right" />
<pre>
<em class="kw">object</em> jerry = <em class="kw">map:new()</em>
<em class="kw">map:put</em>(jerry,<em class="str">"Name","Jerry"</em>)
<em class="kw">map:put</em>(jerry,<em class="str">"School","Central High"</em>)
<em class="kw">map:put</em>(jerry,<em class="str">"Age"</em>,17)
<em class="kw">map:put</em>(jerry,<em class="str">"Pix"</em>,<em class="gtk">create</em>(GdkPixbuf,<em class="str">"~/demos/thumbnails/Jerry.jpg"</em>))
<em>-- above, we store a 'handle' to a picture of
-- Jerry in the map structure</em>
<em class="kw">constant </em>btn1 = <em class="gtk">create</em>(GtkButton,<em class="str">"Student 1"</em>,_(<em class="str">"ShowDetails"</em>),jerry)
<em>----------------------------------------------------------------</em>
<em class="kw">function</em> ShowDetails(<em class="str">atom</em> ctl, <em class="str">atom</em> data)
<em>----------------------------------------------------------------</em>
<em class="gtk">Info</em>(win,<em class="str">"Student"</em>,<em class="kw">map:get</em>(data,<em class="str">"Name"</em>),
<em class="kw">sprintf</em>(<em class="str">"<small><i>School:</i></small>\n %s\n<small><i>Age:</i></small>\n %d"</em>,
{<em class="kw">map:get</em>(data,<em class="str">"School"</em>),
<em class="kw">map:get</em>(data,<em class="str">"Age"</em>)}),,<em class="kw">map:get</em>(data,<em class="str">"Pix"</em>))
<em>-- above, we use the passed 'handle' to
-- display Jerry's photo in the Info pop-up</em>
</pre>
</p>
<br clear="all" />
<h4>Method 3</h4>
<p>
Another way is to use each control's "data" space to pass
<i>name/value</i> pairs. It is possible to combine this method with one of the
others listed above to pass even more data.
</p>
<p>
A drawback to this method is that you can only pass strings,
not numbers. You can either pass the numbers as strings, e.g. "$1.95",
or use one of the above methods
instead.
</p>
<img src="../screenshots/flo.jpg" alt="flo.jpg" width="300px" align="right" />
<pre>
<em class="kw">constant</em> pie = <em class="str">"~/demos/thumbnails/pie.png"</em>
<em class="kw">constant</em> cake = <em class="str">"~/demos/thumbnails/cake.png"</em>
<em class="kw">constant</em>
btn1 = <em class="gtk">create</em>(GtkButton,<em class="str">"gtk-quit","Quit"</em>),
btn2 = <em class="gtk">create</em>(GtkButton,pie & <em class="str">"#_Pie"</em>),
btn3 = <em class="gtk">create</em>(GtkButton,cake & <em class="str">"#_Cake"</em>)
<em class="gtk">connect</em>({btn2,btn3},<em class="str">"clicked"</em>,_(<em class="str">"Foo"</em>))
<em class="gtk">add</em>(box,{btn1,btn2,btn3})
<em class="gtk">set</em>(btn2,<em class="str">"data","dessert","Pumpkin Pie"</em>)
<em class="gtk">set</em>(btn2,<em class="str">"data","price","$1.95"</em>)
<em class="gtk">set</em>(btn2,<em class="str">"data","pix"</em>,pie)
<em class="gtk">set</em>(btn3,<em class="str">"data","dessert","Birthday Cake"</em>)
<em class="gtk">set</em>(btn3,<em class="str">"data","price","$2.10"</em>)
<em class="gtk">set</em>(btn3,<em class="str">"data","pix"</em>,cake)
<em class="gtk">show_all</em>(win)
<em class="gtk">main()</em>
<em>--------------------------------</em>
<em class="kw">function</em> Foo(<em class="kw">atom</em> ctl)
<em>--------------------------------</em>
<em class="gtk">Info</em>(win,<em class="str">"Flo's Bakery"</em>,
<em class="gtk">get</em>(ctl,<em class="str">"data","dessert"</em>),
<em class="gtk">get</em>(ctl,<em class="str">"data","price"</em>),,,
<em class="gtk">get</em>(ctl,<em class="str">"data","pix"</em>))
<em class="kw">return</em> 1
<em class="kw">end function</em>
</pre>
</p>
<h4>But Wait, There's More!</h4>
<p>
You can pass almost any type of Euphoria variable as data attached to
a control, which means that you can also pass Euphoria routine_id's -
so your connected function can execute whatever Eu function is attached as
its data item.<br />
If you combine this with the ability to store and pass other information in
name/value pairs as shown in Method 3 above, you can have a single
Eu function that provides a number of different 'services' with very little code.
</p>
<a name="calendar"></a>
<h3><hr />Calendars<img src="../thumbnails/cal.png" alt="calendar" height="30px" align="left" /></h3><hr />
<p>The GtkCalendar widget has a variety of ways to set and get the calendar date:</p>
<img src="../screenshots/test31.jpg" alt="calendar" width="300px" align="right" />
<pre>
<em class="gtk">get</em>(cal,<em class="str">"day"</em>) => 26 <em>-- as integers</em>
<em class="gtk">get</em>(cal,<em class="str">"month"</em>) => 4
<em class="gtk">get</em>(cal,<em class="str">"year"</em>) => 2015
<em class="gtk">set</em>(cal,<em class="str">"day"</em>,<em class="orange">23</em>) <em>-- changes day only</em>
<em class="gtk">set</em>(cal,<em class="str">"month"</em>,<em class="orange">3</em>) <em>-- changes month only</em>
<em class="gtk">set</em>(cal,<em class="str">"year"</em>,<em class="orange">1946</em>) <em>-- changes year only</em>
<em class="gtk">get</em>(cal,<em class="str">"eu_date"</em>) => {115,4,26} <em>-- Y in Eu format</em>
<em class="gtk">set</em>(cal,<em class="str">"eu_date"</em>,{<em class="orange">115,1,4</em>}) => Jan 4, 2015
<em class="gtk">set</em>(cal,<em class="str">"eu_date"</em>,date()) => current computer date
<em class="gtk">set</em>(cal,<em class="str">"date"</em>,{<em class="orange">1960,11,2</em>}) => Nov 2, 1960
<em class="gtk">set</em>(cal,<em class="str">"date"</em>,{<em class="orange">44,11,15</em>}) => Nov 15, 1944
<em class="gtk">set</em>(cal,<em class="str">"date","11/25/1940"</em>) => Nov 25, 1940
<em class="gtk">set</em>cal,<em class="str">"date","1924/4/25"</em>) => Apr 25, 1924
</pre>
<br clear="right">
<pre>
<em class="gtk">get</em>(cal,<em class="str">"datetime"</em>) => returns calendar date and current clock time in datetime format.
<em class="gtk">get</em>(cal,<em class="str">"datetime"</em>,0) => returns calendar date in datetime format with h,m,s = 0.
<em class="gtk">get</em>(cal,<em class="str">"date"</em>) => Tuesday, May 26, 2015 <em>-- if no format provided,returns a string in default format shown</em>
<em class="gtk">get</em>(cal,<em class="str">"date","%a on %A!"</em>) => "Sun on Sunday!" <em>-- this will be right as often as the weather bureau!</em>
Format string can include the following specifiers, along with other characters of your choice:
%% -- a literal %
%a -- locale's abbreviated weekday name (e.g., Sun)
%A -- locale's full weekday name (e.g., Sunday)
%b -- locale's abbreviated month name (e.g., Jan)
%B -- locale's full month name (e.g., January)
%C -- century; like %Y, except omit last two digits (e.g., 21)
%d -- day of month (e.g, 01)
%j -- day of year (001..366)
%m -- month (01..12)
%u -- day of week (1..7); 1 is Monday
%w -- day of week (0..6); 0 is Sunday
%y -- last two digits of year (00..99)
%Y -- year
For example, <em class="gtk">get</em>(cal,<em class="str">"date","Today is %A, day #%j of the year %Y"</em>)
<i><u>Results</u></i><br />
Today is Monday, day #126 of the year 2013
The calendar will normally open with the current computer date, if you don't tell it otherwise.
You may also use a datetime function, such as:
today = <em class="kw">datetime:now</em>()
<em class="gtk">gtk:set</em>(cal,<em class="str">"date"</em>,today)
or
<em class="gtk">gtk:set</em>(cal,<em class="str">"date"</em>,datetime:add(today,30,DAYS)) <em>-- shows date 30 days from now</em>
</pre>
</p>
<a name="colors"></a>
<h3><hr />RGBA Colors
<img src="../thumbnails/applications-graphics.png" alt="colors" height="30px" align="left" /></h3><hr />
<p>
GTK 3 uses a 32-bit RGBA color structure which can be a bit tricky to use, so EuGTK
implements some functions to make the process simpler. With EuGTK, you can specify colors by:
<ul>
<li>name: "red" <em><small>--this is the preferred way, using the xcolor names</small></em>
<small> Refer to <a href="../resources/xcolors.txt">xcolors.txt</a> for a list of names</small></li>
<li>hex value: #FF0000 <em><small>-- #RRGGBB </small></em></li>
<li>hex string: "#FF0000" <em><small>-- as above</small></em></li>
<li>decimal value: 16711680 <small><em>-- seldom useful, who can remember what color this is?</em></small>
<li>rgb string: "rgb(255,0,0)" <em><small>-- r,g, and b colors are 0 => 255</small></em></li>
<li>rgba string: "rgba(255,0,0,0.5)" <em><small>-- as above, plus alpha in the range from 0 => 1</small></em></li>
</ul>
</p>
<p>
To retrieve colors from, for example, the GtkColorChooserDialog, use:
<pre><code> <em class="kw">object</em> color = <em class="gtk">get</em>(ccd,<em class="str">"rgba"</em>) <em>-- returns rgb or rgba string</em></code></pre>
To make manipulating colors easier, there are several format options available for the above call:
<pre><code> <em class="kw">object</em> color = <em class="gtk">get</em>(ccd,<em class="str">"rgba"</em>,N) <em>-- see table below for N values</em></code></pre>
<ul>
<li>0 = Euphoria sequence: {"rgb",255,0,0} or {"rgba",255,0,0,0.51}</li>
<li>1 = hex string: "#FF0000" <dfn> -- this is a string, not a hex number</dfn></li>
<li>2 = decimal number: 16711680 <dfn> -- this is a number, not a string</dfn></li>
<li>3 = 3-element Eu sequence: {255,0,0} <dfn>-- {R,G,B}, colors are 0=>255<dfn></li>
<li>4 = 4-element Eu sequence: {255,0,0,0.51} <dfn>-- {R,G,B,A} where alpha is 0=>1</dfn></li>
<li>5 = 4-element Eu sequence: {255,0,0,130.5} <dfn>-- {R,G,B,A} where alpha is 0=>255</dfn></li>
<li>6 = rgb or rgba string: "rgb(255,0,0)" or "rgba(255,0,0,.51)" <dfn>-- rgba returned if alpha != 1, otherwise rgb returned</dfn></li>
</ul>
Note: there is no mapping back to a xcolor name from any of the above
color formats.
</p>
<a name="memory"></a>
<h3><hr />Memory Usage<img src="../thumbnails/mongoose.png" alt="goose" height="30px" align="left" /></h3><hr />
<p>
<em><b><u>eui</u></b></em><br />
A modest sized EuGTK program, when run in interpreted mode, may use a relatively large
amount of memory, (a minimum of 25 to 50 megs on my computer). This is because almost
<i>all</i> of the Euphoria std libraries are loaded by EuGTK.<br />The source code will,
however, run on both 32-bit and 64-bit machines, if they have Euphoria installed.
WEE editor, for example, uses 107 megs. when interpreted.
</p>
<p>
<em><b><u>eubind</u></b></em><br />
The same program, when bound, may only require 10 or 20 megs, and the bound source will
take up perhaps 4 or 5 megs of disk space, since the binder removes the unused routines.
Bound programs run almost instantly, compared with interpreted programs.<br />
In addition, binding takes only a moment - often less than a second. Remember that bound
programs must be distributed in two forms - 32-bit and 64-bit versions. WEE uses 35.6 megs.
</p>
<p>
<em><b><u>eushroud</u></b></em><br />
This also works nicely, producing an obfuscated .il file which loads and runs <i>very</i>
quickly. In addition, the .il file will be much smaller than a bound file - perhaps 1/2
to 1/5 the size. Like bound programs, there must be both a 32-bit version and a 64-bit
version. WEE uses 22.7 megs.
</p>
<p>
<em><b><u>euc</u></b></em><br />
When compiled, the program will use only 3 or 4 megs of memory, and the runtime will be
small, perhaps 1 or 2 megs, and will start even faster, but it takes quite a while to
compile. I only compile a program when I'm certain that all the bugs have been worked out.
You may prefer to distribute your program in compiled form. Just remember, you will need
to provide separate 32-bit and 64-bit versions. WEE uses only 8.3 megs!
</p>
<p>
<em><b><u>Conserving Memory</u></b></em><br />
In general, each widget you create will require some amount of memory, so you should
avoid creating (or re-creating) them in loops that might run for many iterations.
Instead, create them outside the loop, and simply
hide() and show() them as required. If widgets <i>must</i> be created within function
calls, try to <i>destroy()</i> them before
returning from the call to keep from wasting memory.
</p>
<a name="debugging"></a>
<h3><hr />Debugging<img src="../thumbnails/bug-buddy.png" alt="bug" height="30px" align="left" /></h3><hr />
<p>
In the table below are some command-line switches you may use to get into the inner
workings of EuGTK.
All but the first are generally only needed when maintaining EuGTK itself, but there
may be times when you can use them to help you find a programming error.
Of course, you must run your program from an x-terminal in order to see the output!
</p>
<table class="testing" border="1">
<th width="20%">Switch</th><th>Output</th><th>Comment</th>
<tr>
<td><b>-d COMPILE</b></td>
<td><code><pre><b>Caution: function Foo will not link when compiled!
********</b></pre></code>
</b></td>
<td><b>Use before compiling so you can fix links</b></td>
</tr>
<tr>
<td>-d CREATE</td>
<td><code><pre>Create
Call: GtkWindow->new
Params: Int
Return type: Ptr
Vector: 101
Args: {0}
GtkWindow=>37278096</pre></code>
</td>
<td>Vector is the routine_id assigned to the function "gtk_window_new"
by EuGTK's "init" procedure.<br /><br />The number following the =&gt;
is the 'handle' to the newly-created window.</td>
</tr>
<tr>
<td>-d SET</td>
<td><code><pre>Set
Call: GtkWindow->set_default_size
Params: Ptr Int Int
Return type: None
Vector: 107
Args: {37278096,300,80}</pre></code>
</td>
<td>Args are: 'handle' to the widget being 'set', and following that are
the parameters being passed, in this case, two integers, width and height.
</td>
</tr>
<tr>
<td>-d GET</td>
<td><code><pre>Get
Call: GtkComboBoxEntry->get_active_text
Params: Ptr
Return type: Str
Vector: 277
Args: {30175312}
Result: Banana</pre></code>
</td>
<td>Vectors > 0 are direct calls to GTK routines generated via define_c_func or define_c_proc.Vectors less than -1 mean that the call is to a function written in Euphoria, in which case the vector is the negated RID. </td>
</tr>
<tr>
<td>-d INIT</td>
<td><code><pre>Init class:GtkButton...
set_image_position 510
get_image_position 511
set_always_show_image -1
get_always_show_image -1</pre></code>
</td>
<td>The numbers represent the routine_id that Euphoria has assigned to the GTK calls.
<br />Use -d INITX for detailed listing.</td>
</tr>
<tr>
<td>-d INIT_ERR</td>
<td><code><pre>ERR:GtkWindow set_titlebar -1
ERR:GtkWindow close -1
ERR:GtkBox set_baseline_position -1
ERR:GtkBox get_baseline_position -1
ERR:GtkButton set_always_show_image -1
ERR:GtkButton get_always_show_image -1
ERR:GtkWidget get_frame_clock -1</pre></code></td>
<td>When the number is -1, that means the call is invalid, usually because the version
of GTK you are using does not implement that call.<br /><br />
'always_show_image' is only available in GTK 3.6+, for example.</td>
</tr>
<tr>
<td>-d INI</td><td>
<pre>-- Ini file for test173.ex
My Calendar={"date",{2015,4,5}}
ColorButton={"rgba","rgb(255,255,255)"}
MyCheckButton1={"active",1}
FontButton={"font name","Sans"}
</pre></td><td>Used to display data written to settings (ini) file on x-term</td>
</tr>
<tr>
<td>-d FUNC</td><td><pre>FUNC g_slist_nth_data 162
PARAMS {50331649,16777220}
Values {24122256,103}</pre></td>
<td>Debug calls to gtk_func() and gtk_str_func()</td>
</tr>
<tr>
<td>-d PROC</td>
<td><pre>PROC g_set_prgname 37
PARAMS {117440516}
Values widgets.ex</pre>
</td><td>Debug calls to gtk_proc</td>
</tr>
<tr>
<td>-d PIXBUF</td><td><pre>Pixbuf from file /home/irv/Pictures/IMG_0020.JPG
Scaled 300x300 1</pre>
</td><td>For debugging pixbuf creation</td>
</tr>
<tr>
<td>-d PIXBUF_ERR</td><td><pre>CAUTION: cannot create pixbuf from /home/irv/Pictures/map.pdf</pre>
</td><td>For debugging pixbuf errors</td>
</tr>
<tr>
<td><b>-d BUILDER</b></td>
<td><a href="../screenshots/hello.png">Screenshot</a></td>
<td>Used to display namespaced objects loaded from Glade</td>
</tr>
</table>
</p>
<a name="settings" />
<h3><hr />Settings<img src="../thumbnails/gnome-run.png" alt="gears" height="30px" align="left" /></h3><hr />
<p><u><em class="blue">Updated for EuGTK 4.11.10</em></u></p>
<p>
The ability to very easily save selected settings from one run to the next has been added in EuGTK 4.10.0.
This includes saving the 'state' of active controls, such as spin buttons, check buttons, color buttons,
font buttons, etc. as well as saving <i>selected</i> properties of any GtkWidget, such as the preferred background color,
font, position or size of windows, etc., from run to run.
</p>
<p>
IOW, your arrangement of things at the time the program was closed will be restored next time the program is run.
Refer to <a href="../test153.ex">test153.ex</a> and <a href="../resources/test153.ini">test153.ini</a> for some examples. Below is a sample
file, which can have any name and extension. <i>.ini</i> works fine, and is familiar. Note that it is plain text,
so it's easily edited, and comments are preserved when it's updated. It uses simple <i>name</i> <small>(dot)</small> <i>property</i> notation.
</p>
<p>
For commonly-used controls, there is a default property defined in GtkSettings.e,
which can be saved/loaded simply by adding the control's handle or name to a list of
controls to pass to settings:Save(). Note that controls to be saved MUST have a name!
These default states are restored when the ini file is loaded.
</p>
<p>
For saving other (non-default) properties, you must add one line of code to save
that property. No additional effort is required when loading the settings,
the property will be reset automatically to the saved value when the ini is loaded.
</p>
<p>
For saving bits of data which are NOT properties of a given widget, you can use the
widget's named <i>data</i> spaces (a.k.a. key/value pairs) to store almost
anything you want. For these, your program code must specifically read the
data item when it needs to use it:
<br /><code><em class="gtk">get</em>(<em class="str">"MainWindow","data","Foobar"</em>) => "Baz!"</code>
</p>
<p><pre><em>
----------------------------------------------------------------------------
-- Following items are 'persistent', only changed by editing this file:
----------------------------------------------------------------------------</em>
--!MainWindow.icon=face-smile
--!MainWindow.border width=20
--!Label1.text=Move, resize, change color, etc...
--!ColorChooserButton.tooltip text=Pick a color for the Main Window background
--!Font Button.tooltip text=Select font for calendar
<em>
------------------------------------------------------------
-- Following items are added by the settings:Save() command
-- using the default properties for the controls on the list
-- your program provides, or by the settings:Add() command,
-- using properties you specify.
------------------------------------------------------------
</em>
<em class="brown">MainWindow.data.Foobar</em>=Baz!
<em class="brown">MainWindow.data.Message</em>=Thanks a lot!
<em class="brown">MainWindow.background</em>=<em class="orange">#729FCF</em>
<em class="brown">MyCalendar.font</em>=Serif Bold Italic 12
<em class="brown">ColorChooserButton.rgba</em>=<em class="orange">#729FCF</em>
<em class="brown">FontButton.font</em> name=Serif Bold Italic 12
<em class="brown">MyCalendar.date</em>={<em class="gtk">2016,4,10</em>}
</pre>
</p>
<footer>
<div class="hint">
<img class="hint" src="../thumbnails/mongoose.png" alt="hint" align="left" float="right" />
<p>
This page edited by The <a href="README.html#bear">Bear</a>,
a web-page and programming editor
written in <a href="OpenEuphoria.org">Euphoria</a>.
</p>
<p>Updated for EuGTK version 4.12.0, Sept 15, 2016
<br />All code &copy; 2016 by Irv Mullins
</p>
</div>
</footer>
</body>
</html>