Re: Event Propagation problem
- From: lecas malecas <darkiiiiii gmail com>
- To: Carlos Lopez Gonzalez <carloslopezgonzalez yahoo es>
- Cc: "gtkmm-list gnome org" <gtkmm-list gnome org>
- Subject: Re: Event Propagation problem
- Date: Fri, 13 Jan 2012 01:17:46 +0000
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]