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