Re: [sigc] conditions in libsigc
- From: Paul Pogonyshev <pogonyshev gmx net>
- To: Chris Vine <chris cvine freeserve co uk>
- Cc: libsigc-list gnome org, Roel Vanhout <roel riks nl>
- Subject: Re: [sigc] conditions in libsigc
- Date: Tue, 4 Jul 2006 20:10:11 +0300
I wrote:
> > This is getting pretty pointless. Lets end it here, as an ounce of code is
> > worth a pound of words.
>
> OK. I'll try to write something.
Here is `something'.
I didn't write anything complete, therefore things are not properly optimized,
application doesn't terminate when both windows are closed etc.
Condition creation is ugly because there is no support from Gtkmm.
Probably there should be functions like `Gtk::Widget::set_sensitive (sigc::condition)'
instead of all this `SensitivityController' stuff.
Compile like this:
g++ -g conditions.cpp -o conditions `pkg-config --cflags --libs sigc++-2.0` `pkg-config --cflags --libs gtkmm-2.4`
Paul
#include <sigc++/signal.h>
#include <gtkmm.h>
// sigc++ part.
class condition;
class condition_impl : public sigc::trackable
{
friend class condition;
bool state;
int reference_counter;
sigc::signal <void, condition> state_changed;
void
reference ()
{
++reference_counter;
}
bool
unreference ()
{
if (!--reference_counter)
delete this;
}
protected:
explicit
condition_impl (bool initial_state)
: state (initial_state),
reference_counter (0)
{ }
virtual
~condition_impl ()
{ }
void set_state (bool new_state);
};
class condition
{
condition_impl* implementation;
public:
explicit
condition (condition_impl* implementation)
: implementation (implementation)
{
implementation->reference ();
}
condition (const condition& other_condition)
: implementation (other_condition.implementation)
{
implementation->reference ();
}
~condition ()
{
implementation->unreference ();
}
operator bool () const
{
return implementation->state;
}
sigc::signal <void, condition>&
signal_state_changed ()
{
return implementation->state_changed;
}
};
class conjunction : public condition_impl
{
const condition first;
const condition second;
public:
conjunction (condition first, condition second);
private:
void update (condition condition);
};
void
condition_impl::set_state (bool new_state)
{
if (state != new_state)
{
state = new_state;
state_changed (condition (this));
}
}
conjunction::conjunction (condition first, condition second)
: condition_impl (first && second),
first (first),
second (second)
{
first.signal_state_changed ().connect (sigc::mem_fun (*this, &conjunction::update));
second.signal_state_changed ().connect (sigc::mem_fun (*this, &conjunction::update));
}
inline condition
operator& (condition first, condition second)
{
return condition (new conjunction (first, second));
}
void
conjunction::update (condition condition)
{
set_state (first && second);
}
// Gtkmm part.
class EntryNotEmptyCondition : public condition_impl
{
const Glib::RefPtr <Gtk::Entry> entry;
public:
explicit
EntryNotEmptyCondition (Gtk::Entry* entry)
: condition_impl (entry->get_text_length () > 0),
entry (entry)
{
entry->signal_changed ().connect (sigc::mem_fun (*this, &EntryNotEmptyCondition::update_condition));
}
void
update_condition ()
{
set_state (entry->get_text_length () > 0);
}
};
class ToggleButtonActiveCondition : public condition_impl
{
const Glib::RefPtr <Gtk::ToggleButton> toggle_button;
public:
explicit
ToggleButtonActiveCondition (Gtk::ToggleButton* toggle_button)
: condition_impl (toggle_button->get_active ()),
toggle_button (toggle_button)
{
toggle_button->signal_toggled ().connect (sigc::mem_fun (*this, &ToggleButtonActiveCondition::update_condition));
}
void
update_condition ()
{
set_state (toggle_button->get_active ());
}
};
class SensivityController
{
Glib::RefPtr <Gtk::Widget> widget;
condition sensitivity;
public:
SensivityController (Gtk::Widget* widget, condition sensitivity)
: widget (widget),
sensitivity (sensitivity)
{
sensitivity.signal_state_changed ().connect
(sigc::mem_fun (*this, &SensivityController::update_sensivity));
update_sensivity (sensitivity);
}
void
update_sensivity (condition condition)
{
widget->set_sensitive (condition);
}
};
// Program part.
class Windows
{
Gtk::Window* window;
Gtk::VBox* vbox;
Gtk::Entry* entry;
Gtk::CheckButton* check_button;
Gtk::Button* button;
SensivityController* controller;
public:
Windows ()
{
window = new Gtk::Window ();
vbox = manage (new Gtk::VBox (false, 12));
entry = manage (new Gtk::Entry ());
check_button = manage (new Gtk::CheckButton ("Check me"));
button = manage (new Gtk::Button (Gtk::Stock::CLOSE));
window->add (*vbox);
vbox->add (*entry);
vbox->add (*check_button);
vbox->add (*button);
window->set_title ("With Conditions");
controller = new SensivityController (button,
(condition (new EntryNotEmptyCondition (entry))
& condition (new ToggleButtonActiveCondition (check_button))));
window->show_all ();
window = new Gtk::Window ();
vbox = manage (new Gtk::VBox (false, 12));
entry = manage (new Gtk::Entry ());
check_button = manage (new Gtk::CheckButton ("Check me"));
button = manage (new Gtk::Button (Gtk::Stock::CLOSE));
window->add (*vbox);
vbox->add (*entry);
vbox->add (*check_button);
vbox->add (*button);
window->set_title ("Without Conditions");
entry->signal_changed ().connect (sigc::mem_fun (*this, &Windows::update_sensitivity));
check_button->signal_toggled ().connect (sigc::mem_fun (*this, &Windows::update_sensitivity));
// Set initial state.
update_sensitivity ();
window->show_all ();
}
private:
void
update_sensitivity ()
{
button->set_sensitive (entry->get_text_length () > 0 && check_button->get_active ());
}
};
int
main (int argc, char** argv)
{
Gtk::Main main_loop (argc, argv);
Windows windows;
main_loop.run ();
return 0;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]