#!/usr/bin/perl -w # Be warned, this thing is slightly out of whack... #TITLE: Packer #REQUIRES: Gtk #use strict; use Gtk; sub destroy { my($widget) = @_; Gtk->main_quit; } sub main { my($info) = {}; init Gtk; my($window) = new Gtk::Window -toplevel; $window->signal_connect( "destroy" => \&destroy); my($window_pack) = new Gtk::Packer; $window->add($window_pack); $window->border_width(4); my($top_pack) = new Gtk::Packer; $window_pack->add_defaults($top_pack, -top, -center, [-fill_x, -fill_y, -expand]); my($frame) = new Gtk::Frame("Packing Area"); $frame->set_usize(400,400); $top_pack->add($frame, -left, -center, [-fill_x, -fill_y, -expand], 0, 8, 8, 0, 0); my($packer) = new Gtk::Packer; $frame->add($packer); my($button_pack) = new Gtk::Packer; $top_pack->add($button_pack, -left, -north, [], 0, 0, 0, 0, 0); my($button_add) = new Gtk::Button "Add Button"; $top_pack->add($button_add, -top, -center, -fill_x, 0, 8, 8, 8, 0); $button_add->signal_connect(clicked => \&add_widget, $info); my($button_quit) = new Gtk::Button "Quit"; $top_pack->add($button_quit, -top, -center, -fill_x, 0, 8, 8, 0, 0); $button_quit->signal_connect(clicked => sub { destroy $window }); my($bottom_pack) = new Gtk::Packer; $window_pack->add_defaults($bottom_pack, -top, -center, -fill_x); my($side_frame) = new Gtk::Frame "Side"; $window_pack->add($side_frame, -left, -west, -fill_y, 0, 10, 10, 0, 0); my($side_pack) = new Gtk::Packer; $side_frame->add($side_pack); my($button_top) = new Gtk::ToggleButton "Top"; my($button_bottom) = new Gtk::ToggleButton "Bottom"; my($button_left) = new Gtk::ToggleButton "Left"; my($button_right) = new Gtk::ToggleButton "Rght"; $button_top->{side} = -top; $button_bottom->{side} = -bottom; $button_left->{side} = -left; $button_right->{side} = -right; $button_top->set_usize(50, -1); $button_bottom->set_usize(50, -1); $button_left->set_usize(50, -1); $button_right->set_usize(50, -1); $side_pack->add($button_top, -top, -center, [], 0, 5, 5, 0, 0); $side_pack->add($button_bottom, -bottom, -center, [], 0, 5, 5, 0, 0); $side_pack->add($button_left, -left, -center, [], 0, 10, 5, 0, 0); $side_pack->add($button_right, -right, -center, [], 0, 10, 5, 0, 0); $button_top->signal_connect(toggled => \&toggle_side, $info); $button_bottom->signal_connect(toggled => \&toggle_side, $info); $button_left->signal_connect(toggled => \&toggle_side, $info); $button_right->signal_connect(toggled => \&toggle_side, $info); my($anchor_frame) = new Gtk::Frame "Anchor"; $window_pack->add($anchor_frame, -left, -west, -fill_y, 0, 10, 10, 0, 0); my($anchor_pack) = new Gtk::Packer; $anchor_frame->add($anchor_pack); my($anchor_table) = new Gtk::Table(3, 3, 1); $anchor_pack->add($anchor_table, -top, -center, [-fill_y, -fill_x, -expand], 0, 10, 5, 0, 0); my($button_n) = new Gtk::ToggleButton "N"; my($button_ne) = new Gtk::ToggleButton "NE"; my($button_e) = new Gtk::ToggleButton "E"; my($button_se) = new Gtk::ToggleButton "SE"; my($button_s) = new Gtk::ToggleButton "S"; my($button_sw) = new Gtk::ToggleButton "SW"; my($button_w) = new Gtk::ToggleButton "W"; my($button_nw) = new Gtk::ToggleButton "NW"; my($button_center) = new Gtk::ToggleButton ""; $button_n->{anchor} = "north"; $button_ne->{anchor} = "ne"; $button_e->{anchor} = "east"; $button_se->{anchor} = "se"; $button_s->{anchor} = "south"; $button_sw->{anchor} = "sw"; $button_w->{anchor} = "west"; $button_nw->{anchor} = "nw"; $button_center->{anchor} = "center"; $button_n->signal_connect(toggled => \&toggle_anchor, $info); $button_ne->signal_connect(toggled => \&toggle_anchor, $info); $button_e->signal_connect(toggled => \&toggle_anchor, $info); $button_se->signal_connect(toggled => \&toggle_anchor, $info); $button_s->signal_connect(toggled => \&toggle_anchor, $info); $button_sw->signal_connect(toggled => \&toggle_anchor, $info); $button_w->signal_connect(toggled => \&toggle_anchor, $info); $button_nw->signal_connect(toggled => \&toggle_anchor, $info); $button_center->signal_connect(toggled => \&toggle_anchor, $info); $anchor_table->attach_defaults($button_nw, 0, 1, 0, 1); $anchor_table->attach_defaults($button_n, 1, 2, 0, 1); $anchor_table->attach_defaults($button_ne, 2, 3, 0, 1); $anchor_table->attach_defaults($button_w, 0, 1, 1, 2); $anchor_table->attach_defaults($button_center, 1, 2, 1, 2); $anchor_table->attach_defaults($button_e, 2, 3, 1, 2); $anchor_table->attach_defaults($button_sw, 0, 1, 2, 3); $anchor_table->attach_defaults($button_s, 1, 2, 2, 3); $anchor_table->attach_defaults($button_se, 2, 3, 2, 3); my($options_frame) = new Gtk::Frame "Options"; $window_pack->add($options_frame, -left, -west, -fill_y, 0, 10, 10, 0, 0); my($options_pack) = new Gtk::Packer; $options_frame->add($options_pack); my($button_fillx) = new Gtk::ToggleButton "Fill X"; my($button_filly) = new Gtk::ToggleButton "Fill Y"; my($button_expand) = new Gtk::ToggleButton "Expand"; $options_pack->add($button_fillx, -top, -north, [-fill_x, -expand], 0, 10, 5, 0, 0); $options_pack->add($button_filly, -top, -center, [-fill_x, -expand], 0, 10, 5, 0, 0); $options_pack->add($button_expand, -top, -south, [-fill_x, -expand], 0, 10, 5, 0, 0); $button_fillx->{option} = -fill_x; $button_filly->{option} = -fill_y; $button_expand->{option} = -expand; $button_fillx->signal_connect(toggled => \&toggle_options, $info); $button_filly->signal_connect(toggled => \&toggle_options, $info); $button_expand->signal_connect(toggled => \&toggle_options, $info); $info->{widgets} = []; $info->{packer} = $packer; $info->{button_top} = $button_top; $info->{button_bottom} = $button_bottom; $info->{button_left} = $button_left; $info->{button_right} = $button_right; $info->{button_n} = $button_n; $info->{button_ne} = $button_ne; $info->{button_e} = $button_e; $info->{button_se} = $button_se; $info->{button_s} = $button_s; $info->{button_sw} = $button_sw; $info->{button_w} = $button_w; $info->{button_nw} = $button_nw; $info->{button_center} = $button_center; $info->{button_fillx} = $button_fillx; $info->{button_filly} = $button_filly; $info->{button_expand} = $button_expand; add_widget(undef, $info); $window->show_all; Gtk->main; return 0; } main; sub toggle_options { my($widget, $info) = @_; my($option, $fillx, $filly, $expand, $pchild, @options); $option = $widget->{option}; if (not defined $info->{pchild}) { die; } $pchild = $info->{pchild}; push @options, -fill_x if $info->{button_fillx}->active; push @options, -fill_y if $info->{button_filly}->active; push @options, -expand if $info->{button_expand}->active; $info->{packer}->configure($info->{current}, $pchild->side, $pchild->anchor, \@options, $pchild->border_width, $pchild->pad_x, $pchild->pad_y, $pchild->ipad_x, $pchild->ipad_y); } sub toggle_anchor { my($widget,$info) = @_; if ($widget->active) { my($anchor) = $widget->{anchor}; my($pchild) = $info->{pchild}; if (not defined $pchild) { die; } $info->{packer}->configure($info->{current}, $pchild->side, $anchor, $pchild->options, $pchild->border_width, $pchild->pad_x, $pchild->pad_y, $pchild->ipad_x, $pchild->ipad_y); foreach ( $info->{button_n}, $info->{button_ne}, $info->{button_e}, $info->{button_se}, $info->{button_s}, $info->{button_sw}, $info->{button_w}, $info->{button_nw}, $info->{button_center} ) { if ($_ != $widget) { $_->set_state(0); $_->set_sensitive(1); } } $widget->set_sensitive(0); } } sub toggle_side { my($widget,$info) = @_; if ($widget->active) { my($side) = $widget->{side}; my($pchild) = $info->{pchild}; if (not defined $pchild) { die; } $info->{packer}->configure($info->{current}, $side, $pchild->anchor, $pchild->options, $pchild->border_width, $pchild->pad_x, $pchild->pad_y, $pchild->ipad_x, $pchild->ipad_y); foreach ( $info->{button_top}, $info->{button_bottom}, $info->{button_left}, $info->{button_right} ) { if ($_ != $widget) { $_->set_state(0); $_->set_sensitive(1); } } $widget->set_sensitive(0); } } sub set_widget { my($w,$info) = @_; my($pchild); if ($w->active) { $info->{current} = $w; $pchild = undef; foreach ($info->{packer}->children) { if ($_->widget eq $info->{current}) { $pchild = $_; last; } } $info->{pchild} = $pchild; $info->{button_top}->set_state(1) if $pchild->side eq "top"; $info->{button_bottom}->set_state(1) if $pchild->side eq "bottom"; $info->{button_left}->set_state(1) if $pchild->side eq "left"; $info->{button_right}->set_state(1) if $pchild->side eq "right"; $info->{button_north}->set_state(1) if $pchild->anchor eq "north"; $info->{button_ne}->set_state(1) if $pchild->anchor eq "ne"; $info->{button_east}->set_state(1) if $pchild->anchor eq "east"; $info->{button_se}->set_state(1) if $pchild->anchor eq "se"; $info->{button_south}->set_state(1) if $pchild->anchor eq "south"; $info->{button_sw}->set_state(1) if $pchild->anchor eq "sw"; $info->{button_west}->set_state(1) if $pchild->anchor eq "west"; $info->{button_nw}->set_state(1) if $pchild->anchor eq "nw"; $info->{button_center}->set_state(1) if $pchild->anchor eq "center"; $info->{button_expand}->set_state($pchild->options->{expand} || 0); $info->{button_fillx}->set_state($pchild->options->{fill_x} || 0); $info->{button_filly}->set_state($pchild->options->{fill_y} || 0); $w->set_sensitive(0); foreach (@{$info->{widgets}}) { next if $_ eq $info->{current}; $_->set_state(0); $_->set_sensitive(1); } } } use vars '$add_widget_n'; sub add_widget { my($w, $info) = @_; my($packer) = $info->{packer}; $main::add_widget_n ||= 0; my($widget) = new Gtk::ToggleButton "$main::add_widget_n"; $widget->set_usize(50, 50); $packer->Gtk::Container::add($widget); $widget->show; $widget->signal_connect(toggled => \&set_widget, $info); push @{$info->{widgets}}, $widget; $widget->set_state(1); set_widget($widget, $info); $main::add_widget_n++; }