[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

Re: the proper way to do inheritance



Quoting muppet <scott asofyet org>:
<snip>
> not just the type system, but features that rely on the type system.
> if you want to have your main widget be a GtkNotebook but also have 
> a signal like "config_changed" or "doohickey_frobnicated", or if you 
> want to have new object properties that could be seen and used by other
> code, you need to register your subtype.
</snip>

<snip>
> [1] there are many situations in which there are perfectly easy and
> equivalent ways to do things with normal perl techniques and using
> the signal/callback mechanism.  it's down to preference, really.  
> i've found that signals/callbacks and object properties are really
> sweet once you figure out how to use them effectively, and they take
> care of a whole slew of OO abstraction scope issues that used to plague
> me (if you can hook a signal to this event, then class A never needs to
> know anything about class B, which needs to hook into that interaction;
> listable, typesafe properties allow you to save object configuration 
> without knowing anything about that object).  using Glib for the signals 
> makes a lot of sense because it already handles the callback queuing 
> you'd have to reimplement in perl.  all that said, i use the subclasses 
> more for specialized non-widgets than i do for widgets.
</snip>

Thanks, that was what I was looking for.  But just to make certain I understand
let me give an example of how using Glib could help me.  First a little
background: I have a main window that holds a Gtk2::Notebook that holds
(possibly) many GnomeSQLEditor::Editor objects.  Each tab in this notebook holds
a label with the name of the file being edited.  When the user changes the file
I want to mark the tab with an asterisk (*) and enable the save button.  When
the user saves I want to remove the asterisk and disable the save button. 
Currently I am registering an idle function everytime I create a new
GnomeSQLEditor::Editor object to check if the object->is_dirty and adding the
asterisk (and enabling the save button) if it is.  But if I were to use Glib to
do the inheritance I could create a signal "dirty" or "has_changed" that would
be caught (instead of using the Idle function).

pacakge GnomeSQLEditor;

	sub new_editor {
		my ($self, $tab, $text) = @_;
		my $editor = GnomeSQLEditor::Editor->new($text);
		$editor->show_all;

		$tab = "new file" unless defined $tab;

		$self->{nb}->append_page(
			$editor, Gtk2::Label->new($tab)
		);

		my $idle = Glib::Idle->add(
			sub {
				if ($editor->is_dirty) {
					my $nb   = $self->{nb};
					my $tab  = $nb->get_tab_label($editor);
					my $file = $tab->get_text;
					#FIXME: what if the filename ends with *
					#FIXME: '*' should be replaced with 
					#       user defined text so that 
					#       users who have a hard time
					#       seeing can use the string
					#       ' has changed' instead.
					if ($file !~ /\*$/) {
						$tab->set_text("$file*");
					}
				}
				return 1;
			}
		);
		$self->{nb}->get_nth_page(
			$self->{nb}->page_num($editor)
		)->{idle} = $idle;
		$self->{nb}->show_all;
	}

could become

pacakge GnomeSQLEditor;

	sub new_editor {
		my ($self, $tab, $text) = @_;
		my $editor = GnomeSQLEditor::Editor->new($text);
		$editor->show_all;

		$tab = "new file" unless defined $tab;

		$self->{nb}->append_page(
			$editor, Gtk2::Label->new($tab)
		);

		$editor->signal_connect(
			'dirty',
			sub {
				my $nb   = $self->{nb};
				my $tab  = $nb->get_tab_label($editor);
				my $file = $tab->get_text;
				#FIXME: what if the filename ends with *
				#FIXME: '*' should be replaced with 
				#       user defined text so that 
				#       users who have a hard time
				#       seeing can use the string
				#       ' has changed' instead.
				if ($file !~ /\*$/) {
					$tab->set_text("$file*");
				}
				$self->{save}->set_sensitive;
				return 1;
			}
		);
		$self->{nb}->show_all;
	}

A savings of 7 lines[1] and it is more efficient than have tons of idle
functions being called.

[1]
Later in the code there are two more lines in the close_tab() method that are no
longer needed:
my $page    = $nb->get_nth_page($pagenum);
G::Source->remove($page->{idle}); 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]