Policies/DrakXGui
From Mandriva
This topic describes some GUI tools, such as ugtk2 and mygtk2.
Contents |
New libraries, why?
Mandriva tools are written in Perl, why not using perl-Gtk2 directly?
ugtk2 has been written because it takes care of some HIG recommendations, and it encourages a more functional organization of the code to have a better idea of the interface. It isn't duplication of efforts, because it's only a layer on top of perl-Gtk2.
It is pretty straight-forward, most functions are only wrappers to Gtk2 functions. The interesting thing it that they returns the widget to be used again by other functions. This avoids code pollution with unneeded variables, and allows to organize the code closely to the interface look.
HIG concerns
ugtk2 and mygtk2 try to make easier to build "nice-looking" applications. They avoid to put general HIG concerns such as spacing in the interface code, this allows to write the interface much like the interface would be designed in Glade, except that there is no immediate graphical result.
Isn't glade already supposed to do that?
Glade is nice to create interface mock-ups, but it's not really handy to integrate user contributions in an existing project.
When a user wants to contribute and rework an existing program, if he only tweaks the interface, then the backend code will be broken because of removed/renamed/new properties. That would be a lot of work to reorganize this for the programmer: look for every property defined in the interface, and adapt current code for each modified property. That's quite an ingrate job.
With Glade, the C files are tighly coupled to the XML file so the interface/backend separation is not that enforced. While giving the feeling that the code can be graphically edited, Glade will make it wrong (renaming widgets can result in "lost" dead code).
So, is ugtk2 mandatory to contribute interfaces improvements?
Of course, it's easier for a creative user to use Glade, but it' still encouraged to submit interfaces proposals, even based on Glade. Programmers often prefer to have simple suggestions or screenshots, and then add theirself the widgets in the interface, instead of going back and forth in interface properties and code.
Programmers will still have to adapt the backend code, but writing an interface using ugtk/perl-gtk is pretty easy and fast.
It won't be possible for a user to edit an existing interface, but most screens should be quite simple, redesigning from scratch shouldn't be a lot of work.
Is it closed and Mandriva-centered?
These GUI libraries are open. Mainly collaboration with perl-Gtk2 developers. GuillaumeCottenceau and ThierryVignaud have been involved in the project, which isn't used only by Mandriva.
ugtk2
Introduction
ugtk2 is a simple perl-gtk2 extension: a set of wrappers and helpers to help building perl-Gtk2 apps. It basically allows to replace:
my $widget = Gtk2::SomeWidget->new; $widget->function(@args); do_something($widget);
with
do_something(gtkfunction(Gtk2::SomeWidget->new, @args));
gtkfunction() returns its widget argument, thus making functional programming and interface building a lot easier.
How to transcript from perl-Gtk2 syntax to ugtk2?
$variable->method(...) call became gtkmethod($variable, ...)
This is exactly the same code, but using ugtk then enables to oversimplify the code by getting rid of most temporary variables for widgets. The code is even more readable.
The following pseudo-code:
$win = Gtk2::Window->new; $win->set_title("My window"); $frame = Gtk2::Frame->new; $box = Gtk2::VBox->new; $label1 = Gtk2::Label->("option 1"); $label2 = Gtk2::Label->("option 2"); $frame->add($label1); $frame->add($label2); $box->add($frame); $button = Gtk2::Button->new; $button->set_label("Quit"); $button->signal_connect(clicked => sub { exit(0) }); $win->add($box); $win->show_all; Gtk2->main;
became:
$w = gtkpack(ugtk2->new("My window"), gtkpack(Gtk2::VBox->new, gtkpack(Gtk2->Frame->new("Options"), Gtk2::Label->new("option 1"), Gtk2::Label->new("option 2"), ), gtksignal_connect( gtk_create_button("Quit"), clicked => sub { exit(0) } ), ), ); $w->show_all; $w->main;
It is clearer than the first version despite being smaller. The code actually reflects the interface structure, it's somewhat comparable to the HTML -> HTML/CSS evolution.
Packing functions
- gtkpack() defaults to every widget growable
- gtkpack__() defaults to every widget NOT growable
- gtkpack_() enable to specify for each widget if it should grow if more space is allocated to its parent widget
mygtk2
Why a new layer?
Pixel has been trying to clean up some of the ugtk2 mess coming from backward compatibility by introducing mygtk2 (well re-introducing in fact), which would be further away from perl-Gtk2, cleaner, more declarative, more orthogonal and more powerful.
The biggest issue is that if you're used to gtk2, you're somewhat lost.
Features
- no backward compatibility needed, so cleaner
- get rid of most unnamed constants (e.g.: ->pack_start(..., 1, 1, 2) )
- adding more tuning doesn't imply new parentheses and/or indentation
- more orthogonal:
- ugtk2's create_packtable is the same as other widget creation
- gtkset_tip is ugly compared to: gtknew('Button', tip => N("the_tip"), ...) (N.B.: gtkset_tip could be simplified the way I've done in mygtk2, using a global Gtk2::Tooltips object)
- more tightly tied to perl variable
- simpler list/combo constructors (a la interactive)
- have a data structure instead of method calls, giving more flexibility (and allowing better backward compatibility for future changes...)
- hide some Gtk2 methods (e.g.: ->set_position is attribute _position_policy_)
- hide some Gtk2 weirdness (e.g.: fill vs expand in pack_start are unified)
Perl variables tying examples
my $depth_combo = gtknew('ComboBox', width => 220, text_ref => \$chosen_Depth, format => sub { translate($depth2text{$_[0]}) }, list => [ uniq(reverse map { $_->{Depth} } @resolutions) ], changed => sub { my @matching_Depth = $filter_on_Depth->(@matching_ratio); if (!$filter_on_res->(@matching_Depth)) { gtkval_modify(\$chosen_res, $matching_Depth[0]); } });
gtknew('CheckButton', text => N("Individual package selection"), active_ref => \$individual)
Examples
pure GTK2 version
use Gtk2; Gtk2->init; sub doit() { my $box = Gtk2::VBox->new; { my $frame = Gtk2::Frame->new("Options"); $frame->set_shadow_type('in'); my $sbox = Gtk2::VBox->new; $sbox->pack_start(Gtk2::Label->new("option 1"), 1, 1, 2); $sbox->pack_start(Gtk2::Label->new("option 2"), 1, 1, 2); $frame->add($sbox); $box->pack_start($frame, 1, 1, 0); } { my $button = Gtk2::Button->new; $button->set_label("Quit"); $button->signal_connect(clicked => sub { Gtk2->main_quit }); $box->pack_start($button, 0, 0, 0); } my $win = Gtk2::Window->new; $win->set_title("My window"); $win->set_default_size(100, -1); $win->add($box); $win->show_all; Gtk2->main; } doit();
ugtk2 version
use lib '/usr/lib/libDrakX'; use ugtk2 ':all'; sub doit() { my $w = ugtk2->new("My window"); gtkadd(gtkset_default_size($w->{window}, 100, -1), gtkpack_(Gtk2::VBox->new, 1, gtkadd(gtkset_shadow_type(Gtk2::Frame->new("Options"), 'in'), gtkpack(Gtk2::VBox->new, Gtk2::Label->new("option 1"), Gtk2::Label->new("option 2"), ), ), 0, gtksignal_connect( Gtk2::Button->new("Quit"), clicked => sub { exit(0) } ), ), ); $w->main; } doit(); sub gtkset_default_size { $_[0]->set_default_size($_[1], $_[2]); $_[0] }
A few remarks:
- set_default_size is missing from ugtk2. Is it bad practice or should we add it?
- access to pack_start "padding" argument is seldom used because gtkpack and the like don't give access to it. gtkpowerpack allows it, but is completly unused
mygtk2 version
use lib '/home/pixel/gi/perl-install'; use mygtk2; sub doit() { my $w = gtknew('MagicWindow', title => "My window", default_width => 100, child => gtknew('VBox', children => [ 1, gtknew('Frame', text => "Options", shadow_type => 'in', child => gtknew('VBox', padding => 2, children_loose => [ gtknew('Label', text => "option 1"), gtknew('Label', text => "option 2"), ]), ), 0, gtknew('Button', text => "Quit", clicked => sub { Gtk2->main_quit }), ]), ); $w->show; Gtk2->main; } doit();
Documentation
On the web
- http://gtk2-perl.sourceforge.net/doc/pod/
- http://developer.gnome.org/doc/API/2.0/gtk/index.html
- http://gtk2-perl.sf.net/doc/ or http://live.gnome.org/GTK2_2dPerl
Using perldoc
Install perl-doc
- perldoc Gtkt2
- perldoc Gtk2::Window
- perldoc Gtk2::Label
- ...
Using a Pod viewer GUI
Install perl-Gtk2-PodViewer
- podviewer Gtk2
- podviewer Gtk2::Label
- ...
References
perl-Gtk2
perl-MDK-Common tutorial
cooker mailing-list threads
- http://marc.theaimsgroup.com/?l=mandrake-cooker&m=111952076823705&w=2
- http://marc.theaimsgroup.com/?l=mandrake-cooker&m=112093056409934&w=2
Gtk2Fu, a ugtk2 fork on CPAN
Credits
- OlivierBlin (description, references)
- ThierryVignaud (ugtk2 code example)
- PascalRigaux (mygtk2 description code examples)