Re: Event Propagation problem



You could try overriding the event functions (for example: virtual
bool on_key_press_event (GdkEventKey* event)).


On Thu, Jan 12, 2012 at 7:15 PM, Carlos Lopez Gonzalez
<carloslopezgonzalez yahoo es> wrote:
> Hi!
> First of all I want to say sorry for the long post, but the existing code is
> long to explain.
> According to the Event Propagation lesson from the Grkmm Programming book,
> one even that happens in a widget can be handled by it by connecting the
> correspondent signal to the event handler. If the handler returns true, the
> event isn't propagated upstream to the parent containers of the widget.
>
> I'm having troubles obtaining the intended result:
>
> On one side, during the construction of the main instance of the application
> I define some shortcuts for certain actions:
>
> App::App(int *argc, char ***argv):
>     Gtk::Main(argc,argv)
> {
>     //
>     // Other stuff here
>     //
>     // Example: This accel key will map the 'home' key to the 'seek-begin'
> action
>     Gtk::AccelKey accel_key("Home", "<Actions>/canvasview/seek-begin");
>     Gtk::AccelMap::add_entry(accel_key.get_path(), accel_key.get_key(),
> accel_key.get_mod());
>     //
> }
>
>
> On the other hand I have the following related clases:
>
> A) A tree store:
> class CanvasTreeStore : virtual public Gtk::TreeStore
> This tree store has a member that adds a cell renderer value instance for a
> given column.
>
> CellRenderer_ValueBase*
> CanvasTreeStore::add_cell_renderer_value(Gtk::TreeView::Column* column)
>
> B) A cell renderer: class CellRenderer_ValueBase : public
> Gtk::CellRendererText
> The is a speialized renderer to render the Value Base on the cell.
> It has a pointer to a widget called ValueBase_Entry:
>
> ValueBase_Entry *value_entry;
>
> when the start_editing_vfunc is called a ValueBase_Entry is created, filled
> and returned as Gtk::CellEditable*
>
> Gtk::CellEditable*
> CellRenderer_ValueBase::start_editing_vfunc(
>     GdkEvent* event __attribute__ ((unused)),
>     Gtk::Widget& widget,
>     const Glib::ustring& path,
>     const Gdk::Rectangle& background_area __attribute__ ((unused)),
>     const Gdk::Rectangle& cell_area __attribute__ ((unused)),
>     Gtk::CellRendererState flags __attribute__ ((unused)))
> {
> // Other stuff here...
>     value_entry=manage(new ValueBase_Entry());
>     value_entry->set_path(path);
>     value_entry->set_parent(&widget);
>     value_entry->set_value(data);
>     value_entry->signal_editing_done().connect(sigc::mem_fun(*this,
> &CellRenderer_ValueBase::on_value_editing_done));
>     return value_entry;
> }
>
> c) A cell editable class:
>
> class studio::ValueBase_Entry : public Gtk::EventBox, public
> Gtk::CellEditable
>
> This class is also a EventBox (to handle events) since the CellEditable
> isn't a Gtk::Widget derived one.
> In this class there is a pointer to a specialized widget that is a HBox with
> many widgets to edit the value:
>
> Widget_ValueBase *valuewidget;
> this is created when the cell editable is created and added to it:
>
> valuewidget=manage(new class Widget_ValueBase());
> valuewidget->inside_cellrenderer();
> add(*valuewidget);
> valuewidget->show();
>
> D) A container with many widgets inside:
>
> class Widget_ValueBase : public Gtk::HBox
>
> This container has some editable widgets:
>
> Widget_Vector *vector_widget;
> Gtk::SpinButton *real_widget;
> Gtk::Adjustment real_adjustment;
> Gtk::SpinButton *integer_widget;
> Gtk::Adjustment integer_adjustment;
> Gtk::SpinButton *angle_widget;
> Gtk::Adjustment angle_adjustment;
> Gtk::CheckButton *bool_widget;
> Widget_ColorEdit *color_widget;
> Widget_CanvasChooser *canvas_widget;
> Widget_Enum *enum_widget;
> Widget_Filename *filename_widget;
> Widget_Time *time_widget;
> Gtk::Entry *string_widget;
> Widget_Distance *distance_widget;
>
> This is the constructor, where all the widgets are created and packed to the
> HBox.
>
> Widget_ValueBase::Widget_ValueBase():
>     Glib::ObjectBase    (typeid(Widget_ValueBase)),
>     Gtk::HBox(),
>     real_adjustment(0,-2000000000,2000000000,0.05,0.05,0),
>     integer_adjustment(0,-2000000000,2000000000,1,1,0),
>     angle_adjustment(0,-2000000000,2000000000,1,1,0)
> {
>     set_no_show_all();
>     label=manage(new class Gtk::Label("Unknown Datatype"));
>     pack_start(*label);
>     label->show();
>     vector_widget=manage(new class Widget_Vector());
>     pack_start(*vector_widget);
>     color_widget=manage(new class Widget_ColorEdit());
>     pack_start(*color_widget);
>     enum_widget=manage(new class Widget_Enum());
>     pack_start(*enum_widget);
>     real_widget=manage(new class
> Gtk::SpinButton(real_adjustment,0.05,DIGITS));
>     pack_start(*real_widget);
>     integer_widget=manage(new class
> Gtk::SpinButton(integer_adjustment,1,0));
>     pack_start(*integer_widget);
>     angle_widget=manage(new class Gtk::SpinButton(angle_adjustment,15,2));
>     pack_start(*angle_widget);
>     bool_widget=manage(new class Gtk::CheckButton());
>     pack_start(*bool_widget);
>     string_widget=manage(new class Gtk::Entry());
>     pack_start(*string_widget);
>     canvas_widget=manage(new class Widget_CanvasChooser());
>     pack_start(*canvas_widget);
>     filename_widget=manage(new class Widget_Filename());
>     pack_start(*filename_widget);
>     time_widget=manage(new class Widget_Time());
>     pack_start(*time_widget);
>     distance_widget=manage(new class Widget_Distance());
>     pack_start(*distance_widget);
>
>
>  vector_widget->signal_activate().connect(sigc::mem_fun(*this,&Widget_ValueBase::activate));
>
>  color_widget->signal_activate().connect(sigc::mem_fun(*this,&Widget_ValueBase::activate));
>
>  enum_widget->signal_changed().connect(sigc::mem_fun(*this,&Widget_ValueBase::activate));
>
>  real_widget->signal_activate().connect(sigc::mem_fun(*this,&Widget_ValueBase::activate));
>
>  integer_widget->signal_activate().connect(sigc::mem_fun(*this,&Widget_ValueBase::activate));
>
>  angle_widget->signal_activate().connect(sigc::mem_fun(*this,&Widget_ValueBase::activate));
>
>  string_widget->signal_activate().connect(sigc::mem_fun(*this,&Widget_ValueBase::activate));
>
>  canvas_widget->signal_activate().connect(sigc::mem_fun(*this,&Widget_ValueBase::activate));
>
>  filename_widget->signal_activate().connect(sigc::mem_fun(*this,&Widget_ValueBase::activate));
>
>  time_widget->signal_activate().connect(sigc::mem_fun(*this,&Widget_ValueBase::activate));
>
>  distance_widget->signal_activate().connect(sigc::mem_fun(*this,&Widget_ValueBase::activate));
> }
>
> initially all the widgets are hidden and the Widget_ValueBase shows nothing.
> When the cell renderer is starting to be edited, it pases the 'data' to the
> ValueBase_Entry using the set_value() member function:
>
> value_entry->set_value(data);
>
> which calls the set_value of the ValueBase_Entry
>
> void ValueBase_Entry::set_value(const synfig::ValueBase &data)
> {
>     if(valuewidget)
>         valuewidget->set_value(data);
> }
>
> which calls the set_value() of the Widget_ValueBase class:
>
> void
> Widget_ValueBase::set_value(const synfig::ValueBase &data)
> {
>     label->hide();
>     vector_widget->hide();
>     real_widget->hide();
>     integer_widget->hide();
>     bool_widget->hide();
>     color_widget->hide();
>     string_widget->hide();
>     canvas_widget->hide();
>     enum_widget->hide();
>     angle_widget->hide();
>     filename_widget->hide();
>     time_widget->hide();
>     distance_widget->hide();
>     value=data;
>     try{
>     switch(value.get_type())
>     {
>     case ValueBase::TYPE_VECTOR:
>         vector_widget->set_canvas(canvas);
>         vector_widget->set_value(value.get(Vector()));
>         vector_widget->show();
>         break;
>     case ValueBase::TYPE_REAL:
>         if(( child_param_desc.get_is_distance() ||
> param_desc.get_is_distance() )&& canvas)
>         {
>             Distance dist(value.get(Real()),Distance::SYSTEM_UNITS);
>             dist.convert(App::distance_system,canvas->rend_desc());
>             distance_widget->set_value(dist);
>             distance_widget->show();
>         }
>         else
>         {
>             real_widget->set_value(value.get(Real()));
>             real_widget->show();
>         }
>         break;
>     case ValueBase::TYPE_TIME:
>
>  if(canvas)time_widget->set_fps(canvas->rend_desc().get_frame_rate());
>         time_widget->set_value(value.get(Time()));
>         time_widget->show();
>         break;
>     case ValueBase::TYPE_ANGLE:
>         angle_widget->set_value(Angle::deg(value.get(Angle())).get());
>         angle_widget->show();
>         break;
>     case ValueBase::TYPE_INTEGER:
>         {
>             String child_param_hint(child_param_desc.get_hint());
>             String param_hint(param_desc.get_hint());
>             if(child_param_hint!="enum" && param_hint!="enum")
>             {
>                 integer_widget->set_value(value.get(int()));
>                 integer_widget->show();
>             }
>             else
>             {
>                 if(child_param_hint=="enum")
>                     enum_widget->set_param_desc(child_param_desc);
>                 else
>                     enum_widget->set_param_desc(param_desc);
>                 enum_widget->set_value(value.get(int()));
>                 enum_widget->show();
>             }
>         }
>         break;
>     case ValueBase::TYPE_CANVAS:
>         assert(canvas);
>         canvas_widget->set_parent_canvas(canvas);
>
>  canvas_widget->set_value(value.get(etl::loose_handle<synfig::Canvas>()));
>         canvas_widget->show();
>         break;
>     case ValueBase::TYPE_BOOL:
>         bool_widget->set_active(value.get(bool()));
>         bool_widget->show();
>         break;
>     case ValueBase::TYPE_STRING:
>         if(child_param_desc.get_hint()!="filename" &&
> param_desc.get_hint()!="filename")
>         {
>             string_widget->set_text(value.get(string()));
>             string_widget->show();
>         }
>         else
>         {
>             filename_widget->set_value(value.get(string()));
>             filename_widget->show();
>         }
>         break;
>     case ValueBase::TYPE_COLOR:
>             {
>         color_widget->set_value(value.get(synfig::Color()));
>         color_widget->show();
>         }
>         break;
>     default:
>         label->show();
>         break;
>     }
>     }catch(...) { synfig::error(__FILE__":%d: Caught something that was
> thrown",__LINE__); }
> }
>
> Notice that all the widgets are hidden except the one given by the type.
>
> And now my problem:
>
> When I'm editing the Widget_ValueBase (an of the widgets contained by the
> HBox) the shorcuts of the applications are applied.
> I've tried to use the techniques of the event propagation of the keyboard
> and mouse buttons events but the action is ejecuted always.
> For example I tried:
> Add to ValueBaseEntry constructor this code:
>
> ValueBase_Entry::ValueBase_Entry():
>     Glib::ObjectBase  (typeid(ValueBase_Entry)),
>     Gtk::EventBox     (),
>     Gtk::CellEditable ()
> {
>     parent=0;
>     edit_done_called=false;
>     valuewidget=manage(new class Widget_ValueBase());
>     valuewidget->inside_cellrenderer();
>     add(*valuewidget);
>     valuewidget->show();
>     // ADDED LINES/////////////
>     add_events(
>           Gdk::KEY_PRESS_MASK
>         | Gdk::KEY_RELEASE_MASK
>         | Gdk::BUTTON_PRESS_MASK
>         | Gdk::BUTTON_RELEASE_MASK
>         | Gdk::SCROLL_MASK
>         );
>     valuewidget->signal_key_press_event().connect(sigc::mem_fun(*this,
> &studio::ValueBase_Entry::on_key_event));
>     valuewidget->signal_key_release_event().connect(sigc::mem_fun(*this,
> &studio::ValueBase_Entry::on_key_event));
>     valuewidget->signal_button_press_event().connect(sigc::mem_fun(*this,
> &studio::ValueBase_Entry::on_button_event));
>     valuewidget->signal_button_release_event().connect(sigc::mem_fun(*this,
> &studio::ValueBase_Entry::on_button_event));
>     valuewidget->signal_scroll_event().connect(sigc::mem_fun(*this,
> &studio::ValueBase_Entry::on_scroll_event));
>     signal_key_press_event().connect(sigc::mem_fun(*this,
> &studio::ValueBase_Entry::on_key_event));
>     signal_key_release_event().connect(sigc::mem_fun(*this,
> &studio::ValueBase_Entry::on_key_event));
>     signal_button_press_event().connect(sigc::mem_fun(*this,
> &studio::ValueBase_Entry::on_button_event));
>     signal_button_release_event().connect(sigc::mem_fun(*this,
> &studio::ValueBase_Entry::on_button_event));
>     signal_scroll_event().connect(sigc::mem_fun(*this,
> &studio::ValueBase_Entry::on_scroll_event));
>     /////////////////////////
>     show_all_children();
> }
>
>
> And the corresponding new event handlers:
>
> bool ValueBase_Entry::on_key_event(GdkEventKey* /*event*/)
> {
>     synfig::info("key event handled");
>     return true;
> }
> bool ValueBase_Entry::on_button_event(GdkEventButton* /*event*/)
> {
>     synfig::info("button event handled");
>     return true;
> }
> bool ValueBase_Entry::on_scroll_event(GdkEventScroll* /*event*/)
> {
>     synfig::info("scroll event handled");
>     return true;
> }
>
>
> Without success.
>
> In theory the key event that is not processed by the Widget_ValueBase is
> passed to the parent, the HBox which would pass to the ValueBase_Entry which
> would stop the event propagation.
> Why the shortcuts still begin done?
> Is there a way to avoid them during the edition of the widget?
>
> Using the same Widget_ValueBase on a pop up dialog doesn't trigger the
> actions when the shortcuts are pressed.
>
> Any idea is welcome.
>
> Thanks for reading.
>
>
>
>
>
> _______________________________________________
> gtkmm-list mailing list
> gtkmm-list gnome org
> http://mail.gnome.org/mailman/listinfo/gtkmm-list
>


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