1Gtk2::Ex::FormFactory::UIsnetrroC(o3n)tributed Perl DocuGmtekn2t:a:tEixo:n:FormFactory::Intro(3)
2
3
4

NAME

6       Gtk2::Ex::FormFactory::Intro - Introduction into the FormFactory
7       framework
8

DESCRIPTION

10       The Gtk2::Ex::FormFactory framework is for Perl Gtk2 developers who (at
11       least partially ;) agree with these statements:
12
13       •  GUI programming is fun but often boring
14
15       •  A lot of tasks in GUI programming are similar and misleads the lazy
16          programmer to do too much Copy'n Paste
17
18       •  RAD tools like Glade are fine for small applications but not if you
19          want to have a consistent look and feel in bigger and modular
20          applications
21
22       Gtk2::Ex::FormFactory tries to help you with these issues by
23
24       •  Strictly separating GUI design, application logic and data
25          structures
26
27       •  Giving the developer a more declarative style of defining the
28          structure of your GUI
29
30       •  Giving the developer the possibility of definiting the design of the
31          GUI at a single spot in your program
32
33       •  Being lightweight and easy to learn.
34
35   Enough buzzwords
36       Imagine you want to build a configuration dialog for your application,
37       which consists of a notebook, to distinguish several topics, each
38       containing a bunch of simpler widgets (in the following example a
39       single text entry). Also it should have the usual Ok and Cancel
40       buttons.
41
42       The straight approach often is to code all the stuff by hand or "draw"
43       all widgets using Glade. At any rate you need to take care of:
44
45       •  Consistent look and feel, e.g. labels should be bold and properly
46          aligned to the widgets; the widgets iteslf should have some space
47          around them, buttons should always be aligned to the form above etc.
48
49       •  Initializing the widgets with the actual content of your
50          configuration data
51
52       •  Either connecting a lot of signals to track the changes the user
53          made. This would apply all changes straight to your internal data
54          structure, which may make implementing the Cancel button difficult
55          or impossible
56
57       •  Or grabbing all (changed) data from the widgets, when the user hit
58          the Ok button resp. simply close the window, when the user hit the
59          Cancel button
60
61       That's a lot of stuff, which needs to be repeated for every single
62       dialog in your application. No fun anymore.
63
64       Gtk2::Ex::FormFactory will do the boring stuff for you.  That's how it
65       works:
66
67   Register your objects to the Context
68       Create a Gtk2::Ex::FormFactory::Context object and register all your
69       objects, which should be presented/changed by the GUI, here:
70
71         my $context = Gtk2::Ex::FormFactory::Context->new;
72         $context->add_object (
73           name   => "config",
74           object => $config_object
75         );
76
77       $config_object has at least the following methods in our example below:
78
79         - get_data_dir()
80         - get_selected_page()
81         - set_data_dir()
82         - set_selected_page()
83
84       The Context is a layer which encapsulates the methods of accessing your
85       object's attributes. Also the Context knows about relationships between
86       objects and/or their attributes, so it's able to handle correspondent
87       updates on the GUI side automatically. We will discuss more details of
88       Gtk2::Ex::FormFactory::Context later in this document.
89
90   Define the structure of your GUI
91       Create Gtk2::Ex::FormFactory object and define the structure of your
92       GUI. E.g, you want to have window which contains a notebook, which
93       consists of a few pages with a bunch of text entries in them. This will
94       look this way: [ very compressed and evil nesting for this document -
95       for bigger dialogs you will break this into several pieces ]
96
97         my $ff = Gtk2::Ex::FormFactory->new (
98           context => $context,
99           content => [
100             Gtk2::Ex::FormFactory::Window->new(
101               title   => "Preferences",
102               content => [
103                 Gtk2::Ex::FormFactory::Notebook->new (
104                   attr    => "config.selected_page",
105                   content => [
106                     Gtk2::Ex::FormFactory::VBox->new (
107                       title   => "Filesystem",
108                       content => [
109                         Gtk2::Ex::FormFactory::Form->new (
110                           content => [
111                             Gtk2::Ex::FormFactory::Entry->new (
112                               attr   => "config.data_dir",
113                               label  => "Data Directory",
114                               tip    => "This directory takes all your files.",
115                               rules  => "writable-directory",
116                             ),
117                           ],
118                         ),
119                       ],
120                     ),
121                   ],
122                 );
123                 Gtk2::Ex::FormFactory::DialogButtons->new
124               ],
125             ),
126           ],
127         );
128
129         $ff->open;    # actually build the GUI and open the window
130         $ff->update;  # fill in the values from $config_object
131
132       So now you defined that you want to have a text entry, which contains a
133       valid writable directory name, which should be inside a form on a
134       notebook page. No details about the exact layout yet, this is just the
135       strucure of your dialog
136
137   But how is this rendered?
138       For this task Gtk2::Ex::FormFactory creates a
139       Gtk2::Ex::FormFactory::Layout object which takes care of all the
140       rendering details. Gtk2::Ex::FormFactory has a default implementation
141       of this, but you can easily inherit from this module to define your own
142       layout (that's mainly for what all this is good for!) and pass it to
143       the FormFactory as the layouter.
144
145       The Layout module mainly consists of two types of methods
146
147       Methods for building a widget
148           build_TYPE() methods for each FormFactory widget type (Entry,
149           SelectList, Popup, Foo etc.) you use in your dialog.  These have
150           the Gtk2 code actually necessary to create the corresponding Gtk2
151           widgets.
152
153       Methods for adding a widget to a container
154           These are the so called add_WIDGET_to_CONTAINER() methods, which
155           specify how a particular widget type is added to a particular
156           container type. E.g. they're responsible for consistent looking
157           labels beside widgets etc.
158
159           Because the details of adding a widget mainly depend on the
160           container the widget is added to, there are generic methods for
161           adding arbitrary widgets to a container. If there is no specific
162           method for a widget type this generic method is called instead.
163
164   Layout methods for our example
165       The Layout implementation needs the following methods, to be able to
166       generate a layout for our FormFactory defined above:
167
168         build_window           => creates a Gtk2::VBox in a Gtk2::Window
169         build_notebook         => creates a Gtk2::Notebook
170         build_form             => creates a Gtk2::Table (2 columns)
171         build_entry            => creates a Gtk2::Entry
172         build_dialog_buttons   => creates a ButtonBox with Ok/Apply/Cancel
173
174         add_widget_to_form     => adds entry to table, label in 1st column
175         add_widget_to_notebook => adds form to notebook with tab title
176         add_widget_to_window   => adds notebook and buttonbox to the window
177
178       If you regularly code applications with Gtk2 you know, that none of
179       this tasks is rocket science. But you have a lot of parameters for each
180       widget in question to take care of (simply think of the border_width
181       property which may lead to an ugly misaligned mess, if you don't handle
182       it really consistently)
183
184       Because you define this tasks at a single point in your program, it's
185       really easy to create a consistently looking application. Or to change
186       the look quickly. E.g. you decide to put a frame around all your forms?
187       Just change one method - build_form() - and you're done!
188
189   Huh, a lot of new Widget classes to learn!
190       Not really. The FormFactory Widget classes are very simple and mainly
191       wrap correspondent Gtk2 widgets, so you don't need to learn much more.
192
193       Using the builtin widgets is really easy. They all ship with a manual
194       page describing their specific attributes, which usualy isn't much.
195
196       Also Gtk2::Ex::FormFactory has some nifty wrappers for really
197       inconvenient Gtk2 widgets, like Gtk2::Table. Take a look at
198       Gtk2::Ex::FormFactory::Table to learn how easy programming complex
199       table layouts can be. Or look at Gtk2::Ex::FormFactory::Image which is
200       a nice image widget which resizes the image automatically in
201       configurable ranges.
202
203   Building your own FormFactory widgets
204       If you need more widgets: implement them on your own.
205       Gtk2::Ex::FormFactory widget classes don't have much Gtk2 code in them,
206       they just define the properties, which represent this particular form
207       item and implement mainly the following methods:
208
209       •  Define a short name for the type (e.g. "entry" for a Gtk2::Entry -
210          the Layout->add_X_to_Y() methods are derived from the short name)
211
212       •  Transfer the object's attribute value to the widget
213
214       •  Transfer the widget's value to the object's attribute
215
216       •  Connect the 'changed' signal for a synchronized dialog, e.g. if you
217          want to react immedately on user input
218
219       What the widget and object "value" actually is (a scalar, hash, array
220       or complex structure) may be arbitrarly defined. How object attributes
221       are accessed, is defined in the Context module. Our example uses the
222       default set_foo(), get_foo() style accessors, but there are more
223       methods up to defining callbacks, which can do very complex lookups.
224
225   Data consistency
226       Now we know that the FormFactory suite solve layout issues very well.
227       Another important feature is automatic data consistency resp. keeping
228       the GUI and your application data in sync.
229
230       Change an object attribute: the correspondent GUI widgets will update
231       automatically. The user entered data to a text entry: the object
232       attribute associated with this entry will automatically get the new
233       text.
234
235       Gtk2::Ex::FormFactory must know your application's objects very well to
236       do such a magic. That's what the Gtk2::Ex::FormFactory::Context module
237       is good for, mentioned shortly at the top of our example.
238
239   Abstraction from your application's objects
240       All your application objects are registered with a unique name to the
241       Context module. Each FormFactory has a reference to this Context, so it
242       know the objects which are registered.
243
244       When you register your object to the Context, you may specify how
245       attributes are accessed by setting prefixes for read/write accessors.
246
247       You may even override methods inside the Context by specifying
248       correspondent closures, which are called instead of the original
249       method.
250
251       Also objects in terms of the Context module may be abstract things like
252       "The currently selected disc from the currently selected artist", not
253       only a simply hardwired object reference. This is done by calling a
254       closure returning the actual object instead of using a hardwired
255       object.
256
257       This way dependend widgets update automaticly, as soon as the
258       correspondent selection changes, e.g. updating a list of CD titles when
259       switching to another disc in an imaginary CD database program.
260
261   Widget consistency
262       Another challenge in a good GUI program is to make your widgets
263       consistent in terms of graying out widgets, which are not useful in a
264       particular state of your program.
265
266       Gtk2::Ex::FormFactory manages visibility and sensivity of your widgets
267       automatically for you once you registered the correspondent
268       dependencies at the Context. E.g. if there currently is no CD album
269       selected, the corresponding fields are greyed out automatically,
270       including the field labels.
271
272   Data validity
273       Gtk2::Ex::FormFactory specifies Gtk2::Ex::FormFactory::Rules, which are
274       checked against the values the user entered. These conditions must
275       apply, otherwise the old values are restored automatically. A bunch of
276       rules are shipped, but you can define your own set by specifying a
277       correspondent rule object or closures.
278
279   Extensibility
280       This framework was designed with extensibility in mind. You can
281
282       •  Define your own FormFactory widgets, by simply using the base class
283          Gtk2::Ex::FormFactory::Widget resp.
284          Gtk2::Ex::FormFactory::Container. No matter how complex your widget
285          is as long as you provide correspondent object attribute accessors,
286          which transfer the widget's state to the object and vice versa.
287
288       •  Define your own FormFactory Layout module, by deriving from the
289          default Layout implementation and passing a correspondent object to
290          the FormFactory constructor.
291
292       •  All items in your FormFactory have a name, which will be set by
293          default or to a value, you pass to the item's constructor.  This way
294          your Layout implementation can even do very special things for very
295          special widgets, without the need of creating an extra Widget module
296          for this.
297
298       •  You can request any Gtk widget from a FormFactory widget by name to
299          do further manipulation, although you should consider doing this
300          inside your Layout implementation, to keep the "single point of
301          layout" rule.
302

AUTHORS

304        Jörn Reder <joern at zyn dot de>
305
307       Copyright 2004-2006 by Jörn Reder.
308
309       This library is free software; you can redistribute it and/or modify it
310       under the terms of the GNU Library General Public License as published
311       by the Free Software Foundation; either version 2.1 of the License, or
312       (at your option) any later version.
313
314       This library is distributed in the hope that it will be useful, but
315       WITHOUT ANY WARRANTY; without even the implied warranty of
316       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
317       Library General Public License for more details.
318
319       You should have received a copy of the GNU Library General Public
320       License along with this library; if not, write to the Free Software
321       Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307
322       USA.
323

POD ERRORS

325       Hey! The above document had some coding errors, which are explained
326       below:
327
328       Around line 399:
329           Non-ASCII character seen before =encoding in 'Jörn'. Assuming UTF-8
330
331
332
333perl v5.34.0                      2022-01-21   Gtk2::Ex::FormFactory::Intro(3)
Impressum