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; }
_______________________________________________ libsigc-list mailing list libsigc-list@gnome.org http://mail.gnome.org/mailman/listinfo/libsigc-list