Commit 1193c3dd authored by sumpfralle's avatar sumpfralle

implemented handling of registered events and gtk actions with additional parameters

proper gtk action disconnect during teardown


git-svn-id: https://pycam.svn.sourceforge.net/svnroot/pycam/trunk@1172 bbaffbd6-741e-11dd-a85d-61de82d9cad9
parent 2f6fbc1e
...@@ -50,6 +50,7 @@ class Bounds(pycam.Plugins.ListPluginBase): ...@@ -50,6 +50,7 @@ class Bounds(pycam.Plugins.ListPluginBase):
CONTROL_SET = ("set_active", "set_value") CONTROL_SET = ("set_active", "set_value")
def setup(self): def setup(self):
self._event_handlers = []
if self.gui: if self.gui:
import gtk import gtk
bounds_box = self.gui.get_object("BoundsBox") bounds_box = self.gui.get_object("BoundsBox")
...@@ -59,13 +60,11 @@ class Bounds(pycam.Plugins.ListPluginBase): ...@@ -59,13 +60,11 @@ class Bounds(pycam.Plugins.ListPluginBase):
self._modelview = self.gui.get_object("BoundsModelsTable") self._modelview = self.gui.get_object("BoundsModelsTable")
model_selection = self._modelview.get_selection() model_selection = self._modelview.get_selection()
model_selection.set_mode(gtk.SELECTION_MULTIPLE) model_selection.set_mode(gtk.SELECTION_MULTIPLE)
self._detail_handlers = [] self._gtk_handlers = []
handler = model_selection.connect("changed", self._gtk_handlers.append((model_selection, "changed",
lambda widget: self.core.emit_event("bounds-changed")) "bounds-changed"))
self._detail_handlers.append((model_selection, handler)) self._gtk_handlers.append((self._boundsview.get_selection(),
selection = self._boundsview.get_selection() "changed", "bounds-selection-changed"))
selection.connect("changed",
lambda widget: self.core.emit_event("bounds-selection-changed"))
self._treemodel = self._boundsview.get_model() self._treemodel = self._boundsview.get_model()
self._treemodel.clear() self._treemodel.clear()
def update_model(): def update_model():
...@@ -86,8 +85,8 @@ class Bounds(pycam.Plugins.ListPluginBase): ...@@ -86,8 +85,8 @@ class Bounds(pycam.Plugins.ListPluginBase):
(self.ACTION_DELETE, "BoundsDelete")): (self.ACTION_DELETE, "BoundsDelete")):
self.register_list_action_button(action, self._boundsview, self.register_list_action_button(action, self._boundsview,
self.gui.get_object(obj_name)) self.gui.get_object(obj_name))
self.gui.get_object("BoundsNew").connect("clicked", self._gtk_handlers.append((self.gui.get_object("BoundsNew"),
self._bounds_new) "clicked", self._bounds_new))
# quickly adjust the bounds via buttons # quickly adjust the bounds via buttons
for obj_name in ("MarginIncreaseX", "MarginIncreaseY", for obj_name in ("MarginIncreaseX", "MarginIncreaseY",
"MarginIncreaseZ", "MarginDecreaseX", "MarginDecreaseY", "MarginIncreaseZ", "MarginDecreaseX", "MarginDecreaseY",
...@@ -100,61 +99,61 @@ class Bounds(pycam.Plugins.ListPluginBase): ...@@ -100,61 +99,61 @@ class Bounds(pycam.Plugins.ListPluginBase):
args = "-" args = "-"
else: else:
args = "0" args = "0"
self.gui.get_object(obj_name).connect("clicked", self._gtk_handlers.append((self.gui.get_object(obj_name),
self._adjust_bounds, axis, args) "clicked", self._adjust_bounds, axis, args))
# connect change handler for boundary settings # connect change handler for boundary settings
for axis in "XYZ": for axis in "XYZ":
for value in ("Low", "High"): for value in ("Low", "High"):
obj_name = "Boundary%s%s" % (value, axis) obj_name = "Boundary%s%s" % (value, axis)
obj = self.gui.get_object(obj_name) self._gtk_handlers.append((self.gui.get_object(obj_name),
handler = obj.connect("value-changed", "value-changed", "bounds-changed"))
lambda widget: self.core.emit_event("bounds-changed"))
self._detail_handlers.append((obj, handler))
# register all controls # register all controls
for obj_name in self.CONTROL_BUTTONS: for obj_name in self.CONTROL_BUTTONS:
obj = self.gui.get_object(obj_name) obj = self.gui.get_object(obj_name)
if obj_name == "TypeRelativeMargin": if obj_name == "TypeRelativeMargin":
handler = obj.connect("toggled", self._gtk_handlers.append((obj, "toggled",
self._switch_relative_custom) self._switch_relative_custom))
elif obj_name == "RelativeUnit": elif obj_name == "RelativeUnit":
handler = obj.connect("changed", self._gtk_handlers.append((obj, "changed",
self._switch_percent_absolute) self._switch_percent_absolute))
else: else:
for signal in self.CONTROL_SIGNALS: for signal in self.CONTROL_SIGNALS:
try: try:
handler = obj.connect(signal, lambda *args: \ handler = obj.connect(signal, lambda *args: None)
self.core.emit_event(args[-1]), obj.disconnect(handler)
"bounds-changed") self._gtk_handlers.append((obj, signal,
"bounds-changed"))
break break
except TypeError: except TypeError:
continue continue
else: else:
self.log.info("Failed to connect to widget '%s'" % str(obj_name)) self.log.info("Failed to connect to widget '%s'" % \
str(obj_name))
continue continue
self._detail_handlers.append((obj, handler)) self._gtk_handlers.append((self.gui.get_object("NameCell"),
self.gui.get_object("NameCell").connect("edited", "edited", self._edit_bounds_name))
self._edit_bounds_name)
self.gui.get_object("ModelDescriptionColumn").set_cell_data_func( self.gui.get_object("ModelDescriptionColumn").set_cell_data_func(
self.gui.get_object("ModelNameCell"), self._render_model_name) self.gui.get_object("ModelNameCell"), self._render_model_name)
self._event_handlers = (("bounds-selection-changed", self._switch_bounds), self._event_handlers.extend((
("bounds-selection-changed", self._switch_bounds),
("bounds-changed", self._store_bounds_settings), ("bounds-changed", self._store_bounds_settings),
("bounds-changed", self._trigger_table_update), ("bounds-changed", self._trigger_table_update),
("model-list-changed", self._update_model_list)) ("model-list-changed", self._update_model_list)))
self.register_event_handlers(self._event_handlers) self.register_gtk_handlers(self._gtk_handlers)
self._trigger_table_update() self._trigger_table_update()
self._switch_bounds() self._switch_bounds()
self._update_model_list() self._update_model_list()
self.core.set("bounds", self) self.core.set("bounds", self)
self.core.register_event("bounds-changed", self._event_handlers.append(("bounds-changed", "visual-item-updated"))
lambda: self.core.emit_event("visual-item-updated")) self.register_event_handlers(self._event_handlers)
return True return True
def teardown(self): def teardown(self):
if self.gui: if self.gui:
self.core.unregister_ui("main", self.gui.get_object("BoundsBox")) self.core.unregister_ui("main", self.gui.get_object("BoundsBox"))
self.unregister_event_handlers(self._event_handlers) self.unregister_gtk_handlers(self._gtk_handlers)
self.unregister_event_handlers(self._event_handlers)
self.core.set("bounds", None) self.core.set("bounds", None)
return True
def get_selected(self, index=False): def get_selected(self, index=False):
return self._get_selected(self._boundsview, index=index) return self._get_selected(self._boundsview, index=index)
...@@ -380,8 +379,7 @@ class Bounds(pycam.Plugins.ListPluginBase): ...@@ -380,8 +379,7 @@ class Bounds(pycam.Plugins.ListPluginBase):
if not bounds: if not bounds:
control_box.hide() control_box.hide()
else: else:
for obj, handler in self._detail_handlers: self.unregister_gtk_handlers(self._gtk_handlers)
obj.handler_block(handler)
for obj_name, value in bounds.iteritems(): for obj_name, value in bounds.iteritems():
if obj_name == "Models": if obj_name == "Models":
self.select_models(value) self.select_models(value)
...@@ -397,8 +395,7 @@ class Bounds(pycam.Plugins.ListPluginBase): ...@@ -397,8 +395,7 @@ class Bounds(pycam.Plugins.ListPluginBase):
break break
else: else:
self.log.info("Failed to set value of control %s" % obj_name) self.log.info("Failed to set value of control %s" % obj_name)
for obj, handler in self._detail_handlers: self.register_gtk_handlers(self._gtk_handlers)
obj.handler_unblock(handler)
self._hide_and_show_controls() self._hide_and_show_controls()
control_box.show() control_box.show()
......
...@@ -52,7 +52,7 @@ class EMCToolExport(pycam.Plugins.PluginBase): ...@@ -52,7 +52,7 @@ class EMCToolExport(pycam.Plugins.PluginBase):
def teardown(self): def teardown(self):
if self.gui: if self.gui:
self.core.unregister_ui("export_menu", self.export_emc_tools) self.core.unregister_ui("export_menu", self.export_emc_tools)
self.unregister_gtk_accelerator("fonts", self.export_emc_tools) self.unregister_gtk_accelerator("fonts", self.export_action)
self.unregister_gtk_handlers(self._gtk_handlers) self.unregister_gtk_handlers(self._gtk_handlers)
self.unregister_event_handlers(self._event_handlers) self.unregister_event_handlers(self._event_handlers)
......
...@@ -65,9 +65,8 @@ class Models(pycam.Plugins.ListPluginBase): ...@@ -65,9 +65,8 @@ class Models(pycam.Plugins.ListPluginBase):
self._gtk_handlers.extend(( self._gtk_handlers.extend((
(self.gui.get_object("ModelColorButton"), "color-set", (self.gui.get_object("ModelColorButton"), "color-set",
self._set_colors_of_selected_models), self._set_colors_of_selected_models),
(self._modelview, "row-activated", lambda *args: (self._modelview, "row-activated",
self._list_action_toggle_custom( self._list_action_toggle_custom, self.COLUMN_VISIBLE),
*(args + [self.COLUMN_VISIBLE]))),
(self.gui.get_object("ModelNameColumn"), "edited", (self.gui.get_object("ModelNameColumn"), "edited",
self._edit_model_name))) self._edit_model_name)))
self.gui.get_object("ModelVisibleColumn").set_cell_data_func( self.gui.get_object("ModelVisibleColumn").set_cell_data_func(
......
...@@ -92,8 +92,9 @@ class OpenGLWindow(pycam.Plugins.PluginBase): ...@@ -92,8 +92,9 @@ class OpenGLWindow(pycam.Plugins.PluginBase):
self._last_view = VIEWS["reset"] self._last_view = VIEWS["reset"]
self._position = [200, 200] self._position = [200, 200]
toggle_3d = self.gui.get_object("Toggle3DView") toggle_3d = self.gui.get_object("Toggle3DView")
handler = toggle_3d.connect("toggled", self.toggle_3d_view) self._gtk_handlers = []
self._toggle_action_handler = (toggle_3d, handler) self._gtk_handlers.append((toggle_3d, "toggled",
self.toggle_3d_view))
self.register_gtk_accelerator("opengl", toggle_3d, self.register_gtk_accelerator("opengl", toggle_3d,
"<Control><Shift>v", "ToggleOpenGLView") "<Control><Shift>v", "ToggleOpenGLView")
self.core.register_ui("view_menu", "ViewOpenGL", toggle_3d, -20) self.core.register_ui("view_menu", "ViewOpenGL", toggle_3d, -20)
...@@ -108,29 +109,33 @@ class OpenGLWindow(pycam.Plugins.PluginBase): ...@@ -108,29 +109,33 @@ class OpenGLWindow(pycam.Plugins.PluginBase):
("LeftView", "left"), ("RightView", "right"), ("LeftView", "left"), ("RightView", "right"),
("FrontView", "front"), ("BackView", "back"), ("FrontView", "front"), ("BackView", "back"),
("TopView", "top"), ("BottomView", "bottom")): ("TopView", "top"), ("BottomView", "bottom")):
self.gui.get_object(obj_name).connect("clicked", kwargs = {"view": view}
self.rotate_view, VIEWS[view]) self._gtk_handlers.append((self.gui.get_object(obj_name),
"clicked", self.rotate_view, VIEWS[view]))
# key binding # key binding
self.window.connect("key-press-event", self.key_handler) self._gtk_handlers.append((self.window, "key-press-event",
self.key_handler))
# OpenGL stuff # OpenGL stuff
glconfig = gtk.gdkgl.Config(mode=gtk.gdkgl.MODE_RGBA \ glconfig = gtk.gdkgl.Config(mode=gtk.gdkgl.MODE_RGBA \
| gtk.gdkgl.MODE_DEPTH | gtk.gdkgl.MODE_DOUBLE) | gtk.gdkgl.MODE_DEPTH | gtk.gdkgl.MODE_DOUBLE)
self.area = gtk.gtkgl.DrawingArea(glconfig) self.area = gtk.gtkgl.DrawingArea(glconfig)
# first run; might also be important when doing other fancy # first run; might also be important when doing other fancy
# gtk/gdk stuff # gtk/gdk stuff
self.area.connect_after('realize', self.paint) #self.area.connect_after('realize', self.paint)
# called when a part of the screen is uncovered # called when a part of the screen is uncovered
self.area.connect('expose-event', self.paint) self._gtk_handlers.append((self.area, 'expose-event', self.paint))
# resize window # resize window
self.area.connect('configure-event', self._resize_window) self._gtk_handlers.append((self.area, 'configure-event',
self._resize_window))
# catch mouse events # catch mouse events
self.area.set_events(gtk.gdk.MOUSE | gtk.gdk.POINTER_MOTION_HINT_MASK \ self.area.set_events(gtk.gdk.MOUSE | gtk.gdk.POINTER_MOTION_HINT_MASK \
| gtk.gdk.BUTTON_PRESS_MASK | gtk.gdk.BUTTON_RELEASE_MASK \ | gtk.gdk.BUTTON_PRESS_MASK | gtk.gdk.BUTTON_RELEASE_MASK \
| gtk.gdk.SCROLL_MASK) | gtk.gdk.SCROLL_MASK)
self.area.connect("button-press-event", self.mouse_press_handler) self._gtk_handlers.extend((
self.area.connect('motion-notify-event', self.mouse_handler) (self.area, "button-press-event", self.mouse_press_handler),
self.area.connect("button-release-event", self.context_menu_handler) (self.area, "motion-notify-event", self.mouse_handler),
self.area.connect("scroll-event", self.scroll_handler) (self.area, "button-release-event", self.context_menu_handler),
(self.area, "scroll-event", self.scroll_handler)))
self.container.pack_end(self.area) self.container.pack_end(self.area)
self.camera = Camera(self.core, lambda: (self.area.allocation.width, self.camera = Camera(self.core, lambda: (self.area.allocation.width,
self.area.allocation.height)) self.area.allocation.height))
...@@ -192,19 +197,20 @@ class OpenGLWindow(pycam.Plugins.PluginBase): ...@@ -192,19 +197,20 @@ class OpenGLWindow(pycam.Plugins.PluginBase):
self.context_menu.show_all() self.context_menu.show_all()
else: else:
self.context_menu = None self.context_menu = None
self.core.register_event("model-change-after", self._event_handlers = (
self.update_model_dimensions) ("model-change-after", self.update_model_dimensions),
self.core.register_event("visual-item-updated", ("visual-item-updated", self.update_model_dimensions),
self.update_model_dimensions) ("visual-item-updated", self.update_view),
self.core.register_event("visual-item-updated", self.update_view) ("visualization-state-changed", self._update_widgets),
self.core.register_event("visualization-state-changed", ("model-list-changed", self._restore_latest_view))
self._update_widgets) # handlers
self.core.register_event("model-list-changed", self.register_gtk_handlers(self._gtk_handlers)
self._restore_latest_view) self.register_event_handlers(self._event_handlers)
# show the window # show the window - the handlers _must_ be registered before "show"
self.area.show() self.area.show()
self.container.show() self.container.show()
toggle_3d.set_active(True) toggle_3d.set_active(True)
# refresh display
self.core.emit_event("visual-item-updated") self.core.emit_event("visual-item-updated")
return True return True
...@@ -215,15 +221,8 @@ class OpenGLWindow(pycam.Plugins.PluginBase): ...@@ -215,15 +221,8 @@ class OpenGLWindow(pycam.Plugins.PluginBase):
self.core.unregister_ui("view_menu", toggle_3d) self.core.unregister_ui("view_menu", toggle_3d)
self.unregister_gtk_accelerator("opengl", toggle_3d) self.unregister_gtk_accelerator("opengl", toggle_3d)
self.core.unregister_ui("view_menu", toggle_3d) self.core.unregister_ui("view_menu", toggle_3d)
self.core.unregister_event("model-change-after", self.unregister_gtk_handlers(self._gtk_handlers)
self.update_model_dimensions) self.unregister_event_handlers(self._event_handlers)
self.core.unregister_event("visual-item-updated",
self.update_model_dimensions)
self.core.unregister_event("visual-item-updated", self.update_view)
self.core.unregister_event("visualization-state-changed",
self._update_widgets)
self.core.unregister_event("model-list-changed",
self._restore_latest_view)
# the area will be created during setup again # the area will be created during setup again
self.container.remove(self.area) self.container.remove(self.area)
self.area = None self.area = None
...@@ -233,10 +232,9 @@ class OpenGLWindow(pycam.Plugins.PluginBase): ...@@ -233,10 +232,9 @@ class OpenGLWindow(pycam.Plugins.PluginBase):
self.paint() self.paint()
def _update_widgets(self): def _update_widgets(self):
obj, handler = self._toggle_action_handler self.unregister_gtk_handlers(self._gtk_handlers)
obj.handler_block(handler) self.gui.get_object("Toggle3DView").set_active(self.is_visible)
obj.set_active(self.is_visible) self.register_gtk_handlers(self._gtk_handlers)
obj.handler_unblock(handler)
def update_model_dimensions(self, widget=None): def update_model_dimensions(self, widget=None):
models = self.core.get("models").get_visible() models = self.core.get("models").get_visible()
......
...@@ -73,33 +73,66 @@ class PluginBase(object): ...@@ -73,33 +73,66 @@ class PluginBase(object):
else: else:
self.log.debug("Failed to locate icon: %s" % self.ICONS[key]) self.log.debug("Failed to locate icon: %s" % self.ICONS[key])
self.ICONS[key] = None self.ICONS[key] = None
self._lambda_handlers = {} self._func_cache = {}
self._gtk_handler_id_cache = []
self.enabled = True self.enabled = True
def __get_handler_func(self, func): def __get_handler_func(self, func, params=None):
if isinstance(func, basestring): if params is None:
if not func in self._lambda_handlers: params = []
self._lambda_handlers[func] = lambda *args: \ params = tuple(params)
self.core.emit_event(func) try:
return self._lambda_handlers[func] key = (hash(func), repr(params))
else: except TypeError:
return func key = (id(func), repr(params))
if not key in self._func_cache:
if isinstance(func, basestring):
result = lambda *args: \
self.core.emit_event(func, *params)
else:
if not params:
result = func
else:
result = lambda *args, **kwargs: \
func(*(args + params), **kwargs)
self._func_cache[key] = result
return self._func_cache[key]
def register_event_handlers(self, event_handlers): def register_event_handlers(self, event_handlers):
for name, func in event_handlers: for data in event_handlers:
self.core.register_event(name, self.__get_handler_func(func)) name, func = data[:2]
if len(data) > 2:
params = data[2:]
else:
params = []
self.core.register_event(name,
self.__get_handler_func(func, params))
def register_gtk_handlers(self, gtk_widget_handlers): def register_gtk_handlers(self, gtk_widget_handlers):
for obj, signal, func in gtk_widget_handlers: for data in gtk_widget_handlers:
obj.connect(signal, self.__get_handler_func(func)) obj, signal, func = data[:3]
if len(data) > 3:
params = data[3:]
else:
params = []
handler_id = obj.connect(signal,
self.__get_handler_func(func, params))
self._gtk_handler_id_cache.append((obj, handler_id))
def unregister_event_handlers(self, event_handlers): def unregister_event_handlers(self, event_handlers):
for name, func in event_handlers: for data in event_handlers:
self.core.unregister_event(name, self.__get_handler_func(func)) name, func = data[:2]
if len(data) > 2:
params = data[2:]
else:
params = []
self.core.unregister_event(name,
self.__get_handler_func(func, params))
def unregister_gtk_handlers(self, gtk_widget_handlers): def unregister_gtk_handlers(self, gtk_widget_handlers):
for obj, signal, func in gtk_widget_handlers: while self._gtk_handler_id_cache:
obj.connect(signal, self.__get_handler_func(func)) obj, handler_id = self._gtk_handler_id_cache.pop()
obj.disconnect(handler_id)
def setup(self): def setup(self):
raise NotImplementedError(("Module %s (%s) does not implement " + \ raise NotImplementedError(("Module %s (%s) does not implement " + \
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment