diff options
author | Tomeu Vizoso <tomeu@sugarlabs.org> | 2009-01-20 16:58:45 (GMT) |
---|---|---|
committer | Tomeu Vizoso <tomeu@sugarlabs.org> | 2009-01-20 16:58:45 (GMT) |
commit | b3e2037e6b04890c427d5b69fa1bc6e265410c87 (patch) | |
tree | 25aaf8fee7f6a37ba9880138ee7498402f129f5d /view.py | |
parent | 8535ed6494b8ead86756c414ae9f305f35e25884 (diff) |
Refactor canvas stuff to another module
Diffstat (limited to 'view.py')
-rw-r--r-- | view.py | 253 |
1 files changed, 89 insertions, 164 deletions
@@ -23,41 +23,38 @@ import gtk # We'd rather not depend on sugar in this class from sugar.graphics import style -class MindMapView(gtk.DrawingArea): - +from canvas import Canvas, CanvasElement + +class MindMapView(Canvas): + + __gtype_name__ = 'MindMapView' + def __init__(self, model=None): self._model = None - self._row_changed_sid = None self._row_deleted_sid = None self._row_inserted_sid = None - self._thought_views = None - gobject.GObject.__init__(self) + Canvas.__init__(self) - self.connect('expose-event', self.__expose_event_cb) + self.dragging_started.connect(self.__dragging_started_cb) + self.dragging_finished.connect(self.__dragging_finished_cb) if model is not None: self.model = model - # DND stuff - self._pressed_button = None - self._press_start_x = None - self._press_start_y = None - self._last_clicked_thought = None - self.drag_source_set(0, [], 0) - self.add_events(gtk.gdk.BUTTON_PRESS_MASK | - gtk.gdk.POINTER_MOTION_HINT_MASK) - self.connect('motion-notify-event', self.__motion_notify_event_cb) - self.connect('button-press-event', self.__button_press_event_cb) - self.connect('drag-end', self.__drag_end_cb) - self.connect('drag-data-get', self.__drag_data_get_cb) - self.connect('drag-data-received', self.__drag_data_received_cb) - - self.drag_dest_set(gtk.DEST_DEFAULT_MOTION | - gtk.DEST_DEFAULT_HIGHLIGHT | - gtk.DEST_DEFAULT_DROP, - [('application/x-thought', 0, 0)], - gtk.gdk.ACTION_MOVE) + def __dragging_started_cb(self, **kwargs): + x, y = kwargs['position'] + logging.debug('__dragging_started_cb %r %r' % (x, y)) + thought = kwargs['element'] + thought.dragging = True + + def __dragging_finished_cb(self, **kwargs): + x, y = kwargs['position'] + thought = kwargs['element'] + logging.debug('__dragging_finished_cb %r %r' % (x, y)) + thought.dragging = False + thought.model.x = x + thought.model.y = y def set_model(self, new_model): logging.debug('set_model %r' % new_model) @@ -65,204 +62,132 @@ class MindMapView(gtk.DrawingArea): return if self._model is not None: - self._model.disconnect(self._row_changed_sid) self._model.disconnect(self._row_deleted_sid) self._model.disconnect(self._row_inserted_sid) self._model = new_model if self._model is not None: - self._row_changed_sid = \ - self._model.connect('row-changed', self.__row_changed_cb) self._row_deleted_sid = \ self._model.connect('row-deleted', self.__row_deleted_cb) self._row_inserted_sid = \ self._model.connect('row-inserted', self.__row_inserted_cb) - self._thought_views = [] + self.remove_all_elements() for thought_model in self._model.get_thoughts(): though_view = ThoughtView(thought_model) - self._thought_views.append(though_view) + self.add_element(though_view) def get_model(self): return self._model model = property(get_model, set_model) - def __expose_event_cb(self, widget, event): - logging.debug('expose %r' % self._model) - if self._model is None or not self._model: - return - - context = self.window.cairo_create() - - rect = self.get_allocation() - rect.x = 0 - rect.y = 0 - logging.debug('do_expose_event %r' % ((rect.x, rect.y, rect.width, rect.height),)) - - context.rectangle(event.area.x, event.area.y, - event.area.width, event.area.height) - context.clip() - - context.set_source_rgb(1.0, 1.0, 1.0) - context.paint() - - for thought_view in self._thought_views: - if thought_view.overlaps(event.area): - context.save() - thought_view.draw(context) - context.restore() - - return False - - def _invalidate_whole_area(self): - alloc = self.get_allocation() - rect = gtk.gdk.Rectangle(0, 0, alloc.width, alloc.height) - self.window.invalidate_rect(rect, True) - self.window.process_updates(True) - - def __row_changed_cb(self, model, path, iter): - logging.debug('__row_changed_cb %r' % path) - self._invalidate_whole_area() - def __row_inserted_cb(self, model, path, iter): logging.debug('__row_inserted_cb %r' % path) thought_model = model.get_thought(path[0]) though_view = ThoughtView(thought_model) - self._thought_views.append(though_view) - - self._invalidate_whole_area() + self.add_element(though_view) def __row_deleted_cb(self, model, path): logging.debug('__row_deleted_cb %r' % path) - for thought_view in self._thought_views: + though_view = self._get_though_by_id(path[0]) + self.remove_element(though_view) + + def _get_though_by_id(self, thought_id): + for thought_view in self.get_elements(): if thought_view.model.id == path[0]: - self._thought_views.remove(thought_view) - break + return thought_view + return None - self._invalidate_whole_area() +class ThoughtView(CanvasElement): - # DND methods - def __motion_notify_event_cb(self, widget, event): - if not self._pressed_button: - return True - - # if the mouse button is not pressed, no drag should occurr - if not event.state & gtk.gdk.BUTTON1_MASK: - self._pressed_button = None - return True + _PADDING = style.zoom(10) - logging.debug('motion_notify_event_cb') + def __init__(self, model): + CanvasElement.__init__(self) - if event.is_hint: - x, y, state_ = event.window.get_pointer() - else: - x = event.x - y = event.y - - if widget.drag_check_threshold(int(self._press_start_x), - int(self._press_start_y), - int(x), - int(y)): - context_ = widget.drag_begin([('application/x-thought', 0, 0)], - gtk.gdk.ACTION_MOVE, - 1, - event) - return True - - def __drag_end_cb(self, widget, drag_context): - logging.debug('drag_end_cb') - self._pressed_button = None - self._press_start_x = None - self._press_start_y = None - self._last_clicked_thought = None - - def __drag_data_get_cb(self, widget, context, selection, target_type, - event_time): - logging.debug('drag_data_get_cb: requested target ' + selection.target) - - thought_id = self._last_clicked_thought.model.id - selection.set(selection.target, 8, str(thought_id)) - - def __button_press_event_cb(self, widget, event): - logging.debug('button_press_event_cb') - - if event.button == 1 and event.type == gtk.gdk.BUTTON_PRESS: - self._last_clicked_thought = \ - self._get_thought_at_coords(event.x, event.y) - if self._last_clicked_thought is not None: - self._pressed_button = event.button - self._press_start_x = event.x - self._press_start_y = event.y - - return False - - def _get_thought_at_coords(self, x, y): - for thought in self._thought_views: - thought_x = thought.model.x - thought_y = thought.model.y - width, height = thought.get_size() - - if x >= thought_x and (x <= thought_x + width) and \ - y >= thought_y and (y <= thought_y + height): - return thought - return None + self.model = model + self._last_width = -1 + self._last_height = -1 + self._dragging = False + + self.model.changed.connect(self.__model_changed_cb) - def __drag_data_received_cb(self, widget, drag_context, x, y, - selection_data, info, time): - thought_id = int(selection_data.data) - for thought in self._thought_views: - if thought.model.id == thought_id: - thought.model.x = x - thought.model.y = y - break + def set_dragging(self, dragging): + if self._dragging != dragging: + self._dragging = dragging + self.invalidate() -class ThoughtView(object): + def get_dragging(self): + return self._dragging - _PADDING = style.zoom(10) + dragging = property(get_dragging, set_dragging) - def __init__(self, model): - self.model = model - self._last_width = 0 - self._last_height = 0 + def _get_name_layout(self, context=None): + if context is None: + visual = gtk.gdk.screen_get_default().get_system_visual() + pixmap = gtk.gdk.Pixmap(None, 1, 1, visual.depth) + context = pixmap.cairo_create() - def draw(self, context): if self.model.name is None or not self.model.name: name = _('Unnamed') else: name = self.model.name - context.save() - context.set_source_rgb(0, 0, 0) layout = context.create_layout() layout.set_text(name) + return layout + + def draw(self, context): + if self._dragging: + context.set_source_rgb(0.8, 0.8, 0.8) + else: + context.set_source_rgb(0, 0, 0) + + context.save() + layout = self._get_name_layout(context) + width, height = layout.get_pixel_size() + width += self._PADDING * 2 + height += self._PADDING * 2 - x, y = self.model.x + self._PADDING, self.model.y + self._PADDING + x = self.model.x + self._PADDING + y = self.model.y + self._PADDING context.translate(x, y) context.show_layout(layout) context.restore() - width += self._PADDING * 2 - height += self._PADDING * 2 - context.save() - context.set_line_width(1) - context.set_source_rgb(0.2, 0.2, 0.2) + context.set_line_width(4) + context.rectangle(self.model.x, self.model.y, width, height) context.stroke() context.restore() self._last_width = width self._last_height = height + + CanvasElement.draw(self, context) - def overlaps(self, rect): - return True - - def get_size(self, context=None): + def get_size(self): return self._last_width, self._last_height + def __model_changed_cb(self, **kwargs): + self.x = self.model.x + self.y = self.model.y + self.invalidate() + + def get_rect(self): + if -1 in (self._last_width, self._last_height): + layout = self._get_name_layout() + width, height = layout.get_pixel_size() + self._last_width = width + self._PADDING * 2 + self._last_height = height + self._PADDING * 2 + + return gtk.gdk.Rectangle(self.model.x, self.model.y, + self._last_width, self._last_height) + |