[Ekiga-devel-list] Parenting the forms



Hi,

the problem with the current organization to display forms in ekiga is
that they appear as separate windows, ie: they don't depend on another
window.

(I) A solution: wide scale

The obvious solution is to make the forms find their way to the ui not
directly like this : Some::Component -> Ekiga::UI, but more like :
Some::Component -> Some::Hub -> Ekiga::WhateverCore -> Ekiga::WhateverView.

What I propose is the following scheme, which hopefully will do what we
want : use a "chain of responsibility". It is a sort of signal where callbacks are run each in turn, and return a boolean, until one of them returns true, in which case the others isn't called.

This means that only one callback will really do something, and hence we won't get hit by the "I have several views and all of them have proposed the form to the user, (s)he is pretty unhappy!!" problem.

This also means we get rid of the Ekiga::UI class for now (but of course the rest of the ui code will still run happily!).

(II) A solution: details

When the dialog for the forms will be created by the code responsible for a window, correct parenting will require :
- adding a set_parent_window method to the Gtk::FormDialog class ;
- use said method like this :

Gtk::FormDialog dialog(request);
dialog.set_parent_window (window);
dialog.run ();


Using the code from a chain of responsibility should look something like:
* declaring a chain of responsibility dealing with form requests :
Ekiga::ChainOfResponsibility<Ekiga::FormRequest> my_chain;

* sample debug handler for this chain :
static bool
debug_handler (Ekiga::FormRequest &request)
{
  Ekiga::FormDumper printer(std::cout);
#ifdef __GNUC__
  std::cout << __PRETTY_FUNCTION__ << std::endl;
#endif
  printer.dump (request);

  return false; // means we only peeked and decided not to really handle
}

* using the debug handler :
In the class which declares the chain, do the following in the constructor, so it's the first handler to be run :
my_chain.add_handler (sigc::ptr_fun (debug_handler));

* gtk+ handler for the form :
This is more a reminder, I quoted the possible code above :
bool
addressbook_window_run_form_request (Ekiga::FormRequest &request,
                                     AddressBookWindow *window)
{
  Gtk::FormDialog dialog(request);

  dialog.set_parent_window (window);
  dialog.run ();
}

* sending a form to the user :
my_chain.handle_request (request);

* code for the chain of responsibility :
This is simply a one-parameter bool-returning signal with a special return value accumulator, and some method-renaming to make it look better ; notice that the fact it returns a bool allows doing 'if' tests on the handle_request call, and if it's false, dump an error message on the console to notify us about the problem!

struct responsibility_accumulator
{
  typedef bool result_type;

  template <typename T_slot_iterator>
  bool operator() (T_slot_iterator begin, T_slot_iterator end)
  {
    bool result = false;

    for (T_slot_iterator iter = begin ;
	 iter != end && !result;
	 iter++)
      result = *iter;

    return result;
  }
};

template<typename T_request>
struct ChainOfResponsibility:
  public sigc::signal1<bool,
		       T_request,
		       responsibility_accumulator>
{
  typedef typename sigc::signal1<bool,
				 T_request,
				 responsibility_accumulator>::iterator iterator;
  typedef typename sigc::signal1<bool,
				 T_request,
				 responsibility_accumulator>::slot_type slot_type;

  iterator add_handler (const slot_type& slot_)
  { return connect (slot_); }

  bool handle_request (typename sigc::type_trait<T_request>::take request)
  { return emit (request); }

};


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