Esempio n. 1
0
class Drawable(object):
    @staticmethod
    def get_default_bg_color():
        return Color(0.5, 0.5, 0.5, 1.0)

    def __init__(self, canvas, **properties):
        """
        @type canvas: drawing.canvas.Canvas
        """
        self.canvas = canvas

        self._position = self._parse_property(properties, "position",
                                              Vector(0, 0), Vector.vectorize)
        """@type _position: drawing.vector.Vector"""
        self._margin = self._parse_property(properties, "margin",
                                            Margin.all(0))
        """@type _margin: drawing.geometry.Margin"""
        self._padding = self._parse_property(properties, "padding",
                                             Padding.all(0))
        """@type _padding: drawing.geometry.Padding"""
        self._request_size = self._parse_property(properties, "size",
                                                  Size(-1, -1), Size.make_size)
        """@type _request_size: drawing.size.Size"""
        self._min_size = self._parse_property(properties, "min_size",
                                              Size(0, 0), Size.make_size)
        """@type _min_size: drawing.size.Size"""
        self._max_size = self._parse_property(properties, "max_size",
                                              Size(999, 999), Size.make_size)
        """@type _max_size: drawing.size.Size"""
        self.bg_color = self._parse_property(properties, "bg_color",
                                             Drawable.get_default_bg_color(),
                                             Color.make_color)
        """@type bg_color: drawing.drawable.Color"""
        self.name = self._parse_property(properties, "name", "")
        """@type name: str"""

        self.parent = None
        """@type parent: Drawable"""
        self.children = []
        self._visible = True

        self.click_handler = ClickHandler(self)

        self.on_mouse_click = EventBroadcaster()
        self.on_mouse_enter = EventBroadcaster()
        self.on_mouse_leave = EventBroadcaster()

        self.on_mouse_click.subscribe(self.handle_mouse_click)
        self.on_mouse_enter.subscribe(self.handle_mouse_enter)
        self.on_mouse_enter.subscribe(self.handle_tooltip_start)
        self.on_mouse_leave.subscribe(self.handle_mouse_leave)
        self.on_mouse_leave.subscribe(self.handle_tooltip_end)

        self.canvas.register_drawable(self)

        self.cached_rect = None

    @property
    def visible(self):
        return self._visible

    @visible.setter
    def visible(self, value):
        self._visible = value
        self.invalidate()

    @property
    def margin(self):
        """
        @rtype: drawing.geometry.Margin
        """
        return self._margin

    @margin.setter
    def margin(self, value):
        """
        @type value: drawing.geometry.Margin
        """
        self._margin = value
        self.invalidate()

    @property
    def padding(self):
        """
        @rtype: drawing.geometry.Padding
        """
        return self._padding

    @padding.setter
    def padding(self, value):
        """
        @type value: drawing.geometry.Padding
        """
        self._padding = value
        self.invalidate()

    @property
    def request_size(self):
        """
        @rtype: drawing.size.Size
        """
        return self._request_size

    @request_size.setter
    def request_size(self, value):
        """
        @type value: drawing.size.Size
        """
        self._request_size = value
        self.invalidate()

    @property
    def min_size(self):
        """
        @rtype: drawing.size.Size
        """
        return self._min_size

    @min_size.setter
    def min_size(self, value):
        """
        @type value: drawing.size.Size
        """
        self._min_size = value
        self.invalidate()

    @property
    def max_size(self):
        """
        @rtype: drawing.size.Size
        """
        return self._max_size

    @max_size.setter
    def max_size(self, value):
        """
        @type value: drawing.size.Size
        """
        self._max_size = value
        self.invalidate()

    @property
    def position(self):
        """
        @rtype: drawing.vector.Vector
        """
        return self._position

    @position.setter
    def position(self, value):
        """
        @type value: drawing.vector.Vector
        """
        self._position = value.copy()
        self.cached_rect = None
        self.place_children()

    def toggle(self):
        self.visible = not self.visible

    def hide(self):
        self.visible = False

    def show(self):
        self.visible = True

    def get_content_size(self):
        raise NotImplementedError()

    def get_computed_size(self):
        content_size = self.get_content_size()

        width = self.request_size.width
        if width < 0:
            width = content_size.width

        height = self.request_size.height
        if height < 0:
            height = content_size.height

        if self.min_size.width >= 0:
            width = max((width, self.min_size.width))
        if self.min_size.height >= 0:
            height = max((height, self.min_size.height))

        if self.max_size.width >= 0:
            width = min((width, self.max_size.width))
        if self.max_size.height >= 0:
            height = min((height, self.max_size.height))

        return Size(width, height)

    def add_child(self, child):
        """
        @type child: Drawable
        """
        self.children.append(child)
        child.parent = self
        self.click_handler.propagate_handler(child.click_handler)
        self.invalidate()

    def add_children(self, children):
        """
        @type children: list of Drawable | tuple of Drawable
        """
        self.children += children
        for child in children:
            child.parent = self
            self.click_handler.propagate_handler(child.click_handler)

        if len(children) > 0:
            self.invalidate()

    def get_child_at(self, position):
        """
        @type position: vector.Vector
        @rtype: Drawable
        """
        for child in self.children:
            drawable = child.get_child_at(position)
            if drawable:
                return drawable
        if self.get_rect().is_point_inside(position):
            return self
        else:
            return None

    def handle_mouse_event(self, mouse_data):
        """
        @type mouse_data: drawing.mouse.MouseData
        """
        self.click_handler.handle_mouse_event(mouse_data)

    def handle_mouse_click(self, mouse_data):
        """
        @type mouse_data: drawing.mouse.MouseData
        """
        pass

    def handle_mouse_enter(self, mouse_data):
        """
        @type mouse_data: drawing.mouse.MouseData
        """
        pass

    def handle_mouse_leave(self, mouse_data):
        """
        @type mouse_data: drawing.mouse.MouseData
        """
        pass

    def handle_tooltip_start(self, mouse_data):
        """
        @type mouse_data: mouse.MouseData
        """
        tooltip = self.get_tooltip()

        if tooltip is not None:
            self.canvas.set_drawable_tooltip(self, tooltip)

    def handle_tooltip_end(self, mouse_data):
        """
        @type mouse_data: mouse.MouseData
        """
        self.canvas.set_drawable_tooltip(self, None)

    def handle_drag_cancel(self):
        pass

    def handle_drag_start(self):
        pass

    def handle_drag_end(self, target):
        """
        @type target: Drawable
        """
        pass

    def on_child_changed(self, child):
        """
        @type child: Drawable
        """
        self.invalidate()

    def get_tooltip(self):
        """
        @rtype: str | None
        """
        return None

    def get_rect(self):
        if self.cached_rect:
            return self.cached_rect

        if not self.visible:
            return RectangleBBox(self.position)

        self.cached_rect = RectangleBBox(self.position,
                                         self.get_computed_size() +
                                         self.padding.to_size())
        return self.cached_rect

    def get_center(self):
        """
        Returns the center of the drawable.
        @rtype: canvas.vector.Vector
        """
        rect = self.get_rect()
        x = rect.x + rect.width / 2.0
        y = rect.y + rect.height / 2.0
        return Vector(x, y)

    def place_children(self):
        pass

    def draw(self):
        if self.visible:
            for child in self.children:
                child.draw()

    def invalidate(self):
        """
        Invalidates this drawable, placing it's children and sending it's
        parent a message that it has changd.
        """
        self.cached_rect = None
        if self.parent:
            self.parent.on_child_changed(self)
        self.place_children()

    def _parse_property(self, properties, key, default, modifier=None):
        """
        Parses property from property dictionary.
        Modifier modifies the resulting value.
        @type properties: dict
        @type key: str
        @type default: object
        @type modifier: function
        @rtype: object
        """
        if key in properties:
            if modifier:
                return modifier(properties[key])
            else:
                return properties[key]
        else:
            return default
Esempio n. 2
0
class SourceManager(Gtk.Notebook):
    def __init__(self, debugger):
        super(SourceManager, self).__init__()

        self.debugger = debugger

        self.popup_enable()

        self.on_breakpoint_changed = EventBroadcaster()
        self.on_symbol_hover = EventBroadcaster()
        self.on_symbol_hover.subscribe(self._handle_symbol_hover)
        self.on_breakpoint_changed.subscribe(self._handle_breakpoint_change)

        self.debugger.on_process_state_changed.subscribe(
            self._handle_process_state_change)
        self.debugger.on_frame_changed.subscribe(self._handle_frame_change)

    def _handle_symbol_hover(self, source_editor, symbol):
        if self.debugger.process_state == ProcessState.Stopped:
            variable = self.debugger.variable_manager.get_variable(symbol)
            if variable and variable.address:
                source_editor.set_tooltip_text(str(variable))

    def _handle_breakpoint_change(self, location, change_type):
        if change_type == BreakpointChangeType.Create:
            self.debugger.breakpoint_manager.add_breakpoint(*location)
        elif change_type == BreakpointChangeType.Delete:
            self.debugger.breakpoint_manager.remove_breakpoint(*location)

    def _handle_process_state_change(self, state, event_data):
        if state == ProcessState.Stopped:
            self._set_debugger_location()
        elif state == ProcessState.Exited:
            run_on_gui(self.unset_exec_line)

    def _handle_frame_change(self, frame):
        """
        @param frame: frame.Frame
        """
        self._set_debugger_location()

    def _set_debugger_location(self):
        location = self.debugger.file_manager.get_current_location()

        Logger.debug("Stop at {0}".format(location))

        if location and location[0]:
            run_on_gui(self.set_exec_line, location[0], location[1])

    @require_gui_thread
    def _create_label(self, path, widget):
        content = Gtk.Box.new(Gtk.Orientation.HORIZONTAL, 0)

        label = Gtk.Label(os.path.basename(path))

        button = Gtk.Button()
        button.add(Gtk.Image.new_from_stock(Gtk.STOCK_CLOSE,
                                            Gtk.IconSize.MENU))
        button.set_relief(Gtk.ReliefStyle.NONE)
        button.set_focus_on_click(False)
        button.connect("clicked", lambda *x: self._close_tab(widget))

        event_box = Gtk.EventBox.new()
        event_box.add(label)
        event_box.connect(
            "button-press-event",
            lambda source, event: self._handle_tab_label_press(event, widget))

        content.pack_start(event_box, True, True, 0)
        content.pack_start(button, False, False, 0)
        content.show_all()

        return content

    @require_gui_thread
    def _close_tab(self, widget):
        widget.editor.on_breakpoint_changed.clear()

        self.remove_page(self.get_tabs().index(widget))

    @require_gui_thread
    def _add_tab(self, file_path):
        editor = SourceEditor(self.debugger)
        editor.set_content_from_file(file_path)
        editor.set_hexpand(True)
        editor.set_vexpand(True)
        editor.show_all()

        window = SourceWindow(editor)

        label = self._create_label(file_path, window)

        menu_label = Gtk.Label(label=file_path)
        menu_label.set_alignment(0, 0)

        index = self.append_page_menu(window, label, menu_label)

        if index != -1:
            self.select_tab(index)
            self.set_tab_reorderable(window, True)
            editor.on_breakpoint_changed.redirect(self.on_breakpoint_changed)
            editor.on_symbol_hover.redirect(self.on_symbol_hover)
            return editor
        else:
            return None

    @require_gui_thread
    def _handle_tab_label_press(self, event, window):
        """
        @type event: Gdk.EventButton
        @type window: SourceWindow
        """
        if (event.type == Gdk.EventType.BUTTON_PRESS and event.button == 2):
            self._close_tab(window)

    @require_gui_thread
    def get_tabs(self):
        return [self.get_nth_page(i) for i in xrange(0, self.get_n_pages())]

    @require_gui_thread
    def open_file(self, file_path):
        for index, tab in enumerate(self.get_tabs()):
            if tab.editor.file == file_path:
                self.select_tab(index)
                return tab.editor

        return self._add_tab(file_path)

    @require_gui_thread
    def set_exec_line(self, file_path, line_number):
        self.unset_exec_line()

        tab = self.open_file(file_path)
        tab.set_exec_line(line_number - 1)

    @require_gui_thread
    def unset_exec_line(self):
        for tab in self.get_tabs():
            tab.editor.unset_exec_line()

    @require_gui_thread
    def get_selected_editor(self):
        selected = self.get_current_page()

        if selected != -1:
            return self.get_nth_page(selected).editor
        else:
            return None

    @require_gui_thread
    def select_tab(self, index):
        self.set_current_page(index)
Esempio n. 3
0
class Drawable(object):
    @staticmethod
    def get_default_bg_color():
        return Color(0.5, 0.5, 0.5, 1.0)

    def __init__(self, canvas, **properties):
        """
        @type canvas: drawing.canvas.Canvas
        """
        self.canvas = canvas

        self._position = self._parse_property(properties, "position",
                                              Vector(0, 0), Vector.vectorize)
        """@type _position: drawing.vector.Vector"""
        self._margin = self._parse_property(properties, "margin",
                                            Margin.all(0))
        """@type _margin: drawing.geometry.Margin"""
        self._padding = self._parse_property(properties, "padding",
                                             Padding.all(0))
        """@type _padding: drawing.geometry.Padding"""
        self._request_size = self._parse_property(properties, "size",
                                                  Size(-1, -1), Size.make_size)
        """@type _request_size: drawing.size.Size"""
        self._min_size = self._parse_property(properties, "min_size",
                                              Size(0, 0), Size.make_size)
        """@type _min_size: drawing.size.Size"""
        self._max_size = self._parse_property(properties, "max_size",
                                              Size(999, 999), Size.make_size)
        """@type _max_size: drawing.size.Size"""
        self.bg_color = self._parse_property(properties, "bg_color",
                                             Drawable.get_default_bg_color(),
                                             Color.make_color)
        """@type bg_color: drawing.drawable.Color"""
        self.name = self._parse_property(properties, "name", "")
        """@type name: str"""

        self.parent = None
        """@type parent: Drawable"""
        self.children = []
        self._visible = True

        self.click_handler = ClickHandler(self)

        self.on_mouse_click = EventBroadcaster()
        self.on_mouse_enter = EventBroadcaster()
        self.on_mouse_leave = EventBroadcaster()

        self.on_mouse_click.subscribe(self.handle_mouse_click)
        self.on_mouse_enter.subscribe(self.handle_mouse_enter)
        self.on_mouse_enter.subscribe(self.handle_tooltip_start)
        self.on_mouse_leave.subscribe(self.handle_mouse_leave)
        self.on_mouse_leave.subscribe(self.handle_tooltip_end)

        self.canvas.register_drawable(self)

        self.cached_rect = None

    @property
    def visible(self):
        return self._visible

    @visible.setter
    def visible(self, value):
        self._visible = value
        self.invalidate()

    @property
    def margin(self):
        """
        @rtype: drawing.geometry.Margin
        """
        return self._margin

    @margin.setter
    def margin(self, value):
        """
        @type value: drawing.geometry.Margin
        """
        self._margin = value
        self.invalidate()

    @property
    def padding(self):
        """
        @rtype: drawing.geometry.Padding
        """
        return self._padding

    @padding.setter
    def padding(self, value):
        """
        @type value: drawing.geometry.Padding
        """
        self._padding = value
        self.invalidate()

    @property
    def request_size(self):
        """
        @rtype: drawing.size.Size
        """
        return self._request_size

    @request_size.setter
    def request_size(self, value):
        """
        @type value: drawing.size.Size
        """
        self._request_size = value
        self.invalidate()

    @property
    def min_size(self):
        """
        @rtype: drawing.size.Size
        """
        return self._min_size

    @min_size.setter
    def min_size(self, value):
        """
        @type value: drawing.size.Size
        """
        self._min_size = value
        self.invalidate()

    @property
    def max_size(self):
        """
        @rtype: drawing.size.Size
        """
        return self._max_size

    @max_size.setter
    def max_size(self, value):
        """
        @type value: drawing.size.Size
        """
        self._max_size = value
        self.invalidate()

    @property
    def position(self):
        """
        @rtype: drawing.vector.Vector
        """
        return self._position

    @position.setter
    def position(self, value):
        """
        @type value: drawing.vector.Vector
        """
        self._position = value.copy()
        self.cached_rect = None
        self.place_children()

    def toggle(self):
        self.visible = not self.visible

    def hide(self):
        self.visible = False

    def show(self):
        self.visible = True

    def get_content_size(self):
        raise NotImplementedError()

    def get_computed_size(self):
        content_size = self.get_content_size()

        width = self.request_size.width
        if width < 0:
            width = content_size.width

        height = self.request_size.height
        if height < 0:
            height = content_size.height

        if self.min_size.width >= 0:
            width = max((width, self.min_size.width))
        if self.min_size.height >= 0:
            height = max((height, self.min_size.height))

        if self.max_size.width >= 0:
            width = min((width, self.max_size.width))
        if self.max_size.height >= 0:
            height = min((height, self.max_size.height))

        return Size(width, height)

    def add_child(self, child):
        """
        @type child: Drawable
        """
        self.children.append(child)
        child.parent = self
        self.click_handler.propagate_handler(child.click_handler)
        self.invalidate()

    def add_children(self, children):
        """
        @type children: list of Drawable | tuple of Drawable
        """
        self.children += children
        for child in children:
            child.parent = self
            self.click_handler.propagate_handler(child.click_handler)

        if len(children) > 0:
            self.invalidate()

    def get_child_at(self, position):
        """
        @type position: vector.Vector
        @rtype: Drawable
        """
        for child in self.children:
            drawable = child.get_child_at(position)
            if drawable:
                return drawable
        if self.get_rect().is_point_inside(position):
            return self
        else:
            return None

    def handle_mouse_event(self, mouse_data):
        """
        @type mouse_data: drawing.mouse.MouseData
        """
        self.click_handler.handle_mouse_event(mouse_data)

    def handle_mouse_click(self, mouse_data):
        """
        @type mouse_data: drawing.mouse.MouseData
        """
        pass

    def handle_mouse_enter(self, mouse_data):
        """
        @type mouse_data: drawing.mouse.MouseData
        """
        pass

    def handle_mouse_leave(self, mouse_data):
        """
        @type mouse_data: drawing.mouse.MouseData
        """
        pass

    def handle_tooltip_start(self, mouse_data):
        """
        @type mouse_data: mouse.MouseData
        """
        tooltip = self.get_tooltip()

        if tooltip is not None:
            self.canvas.set_drawable_tooltip(self, tooltip)

    def handle_tooltip_end(self, mouse_data):
        """
        @type mouse_data: mouse.MouseData
        """
        self.canvas.set_drawable_tooltip(self, None)

    def handle_drag_cancel(self):
        pass

    def handle_drag_start(self):
        pass

    def handle_drag_end(self, target):
        """
        @type target: Drawable
        """
        pass

    def on_child_changed(self, child):
        """
        @type child: Drawable
        """
        self.invalidate()

    def get_tooltip(self):
        """
        @rtype: str | None
        """
        return None

    def get_rect(self):
        if self.cached_rect:
            return self.cached_rect

        if not self.visible:
            return RectangleBBox(self.position)

        self.cached_rect = RectangleBBox(
            self.position,
            self.get_computed_size() + self.padding.to_size())
        return self.cached_rect

    def get_center(self):
        """
        Returns the center of the drawable.
        @rtype: canvas.vector.Vector
        """
        rect = self.get_rect()
        x = rect.x + rect.width / 2.0
        y = rect.y + rect.height / 2.0
        return Vector(x, y)

    def place_children(self):
        pass

    def draw(self):
        if self.visible:
            for child in self.children:
                child.draw()

    def invalidate(self):
        """
        Invalidates this drawable, placing it's children and sending it's
        parent a message that it has changd.
        """
        self.cached_rect = None
        if self.parent:
            self.parent.on_child_changed(self)
        self.place_children()

    def _parse_property(self, properties, key, default, modifier=None):
        """
        Parses property from property dictionary.
        Modifier modifies the resulting value.
        @type properties: dict
        @type key: str
        @type default: object
        @type modifier: function
        @rtype: object
        """
        if key in properties:
            if modifier:
                return modifier(properties[key])
            else:
                return properties[key]
        else:
            return default
Esempio n. 4
0
class SourceManager(Gtk.Notebook):
    def __init__(self, debugger):
        super(SourceManager, self).__init__()

        self.debugger = debugger

        self.popup_enable()

        self.on_breakpoint_changed = EventBroadcaster()
        self.on_symbol_hover = EventBroadcaster()
        self.on_symbol_hover.subscribe(self._handle_symbol_hover)
        self.on_breakpoint_changed.subscribe(self._handle_breakpoint_change)

        self.debugger.on_process_state_changed.subscribe(
            self._handle_process_state_change)
        self.debugger.on_frame_changed.subscribe(self._handle_frame_change)

    def _handle_symbol_hover(self, source_editor, symbol):
        if self.debugger.process_state == ProcessState.Stopped:
            variable = self.debugger.variable_manager.get_variable(symbol)
            if variable and variable.address:
                source_editor.set_tooltip_text(str(variable))

    def _handle_breakpoint_change(self, location, change_type):
        if change_type == BreakpointChangeType.Create:
            self.debugger.breakpoint_manager.add_breakpoint(*location)
        elif change_type == BreakpointChangeType.Delete:
            self.debugger.breakpoint_manager.remove_breakpoint(*location)

    def _handle_process_state_change(self, state, event_data):
        if state == ProcessState.Stopped:
            self._set_debugger_location()
        elif state == ProcessState.Exited:
            run_on_gui(self.unset_exec_line)

    def _handle_frame_change(self, frame):
        """
        @param frame: frame.Frame
        """
        self._set_debugger_location()

    def _set_debugger_location(self):
        location = self.debugger.file_manager.get_current_location()

        Logger.debug("Stop at {0}".format(location))

        if location and location[0]:
            run_on_gui(self.set_exec_line, location[0], location[1])

    @require_gui_thread
    def _create_label(self, path, widget):
        content = Gtk.Box.new(Gtk.Orientation.HORIZONTAL, 0)

        label = Gtk.Label(os.path.basename(path))

        button = Gtk.Button()
        button.add(Gtk.Image.new_from_stock(Gtk.STOCK_CLOSE,
                                            Gtk.IconSize.MENU))
        button.set_relief(Gtk.ReliefStyle.NONE)
        button.set_focus_on_click(False)
        button.connect("clicked", lambda *x: self._close_tab(widget))

        event_box = Gtk.EventBox.new()
        event_box.add(label)
        event_box.connect("button-press-event",
                          lambda source, event: self._handle_tab_label_press(
                              event, widget))

        content.pack_start(event_box, True, True, 0)
        content.pack_start(button, False, False, 0)
        content.show_all()

        return content

    @require_gui_thread
    def _close_tab(self, widget):
        widget.editor.on_breakpoint_changed.clear()

        self.remove_page(self.get_tabs().index(widget))

    @require_gui_thread
    def _add_tab(self, file_path):
        editor = SourceEditor(self.debugger)
        editor.set_content_from_file(file_path)
        editor.set_hexpand(True)
        editor.set_vexpand(True)
        editor.show_all()

        window = SourceWindow(editor)

        label = self._create_label(file_path, window)

        menu_label = Gtk.Label(label=file_path)
        menu_label.set_alignment(0, 0)

        index = self.append_page_menu(window, label, menu_label)

        if index != -1:
            self.select_tab(index)
            self.set_tab_reorderable(window, True)
            editor.on_breakpoint_changed.redirect(self.on_breakpoint_changed)
            editor.on_symbol_hover.redirect(self.on_symbol_hover)
            return editor
        else:
            return None

    @require_gui_thread
    def _handle_tab_label_press(self, event, window):
        """
        @type event: Gdk.EventButton
        @type window: SourceWindow
        """
        if (event.type == Gdk.EventType.BUTTON_PRESS and
                event.button == 2):
            self._close_tab(window)

    @require_gui_thread
    def get_tabs(self):
        return [self.get_nth_page(i) for i in xrange(0, self.get_n_pages())]

    @require_gui_thread
    def open_file(self, file_path):
        for index, tab in enumerate(self.get_tabs()):
            if tab.editor.file == file_path:
                self.select_tab(index)
                return tab.editor

        return self._add_tab(file_path)

    @require_gui_thread
    def set_exec_line(self, file_path, line_number):
        self.unset_exec_line()

        tab = self.open_file(file_path)
        tab.set_exec_line(line_number - 1)

    @require_gui_thread
    def unset_exec_line(self):
        for tab in self.get_tabs():
            tab.editor.unset_exec_line()

    @require_gui_thread
    def get_selected_editor(self):
        selected = self.get_current_page()

        if selected != -1:
            return self.get_nth_page(selected).editor
        else:
            return None

    @require_gui_thread
    def select_tab(self, index):
        self.set_current_page(index)