Example #1
0
    def __init__(self, main_window, *args, **kwargs):
        S = kwargs.pop("S")

        self.main_window = main_window

        self._states()

        self.interfaces = GuiInterfaces(self.main_window)

        if S is None:
            dimensions = kwargs.pop("dimensions")
        else:
            dimensions = S.shape
            kwargs.pop("dimensions")

        wx.grid.Grid.__init__(self, main_window, *args, **kwargs)

        self.SetDefaultCellBackgroundColour(wx.Colour(255, 255, 255, 255))

        # Cursor position on entering selection mode
        self.sel_mode_cursor = None

        # Set multi line editor
        self.SetDefaultEditor(GridCellEditor(main_window))

        # Create new grid
        if S is None:
            self.code_array = CodeArray(dimensions)
            post_command_event(self, self.GridActionNewMsg, shape=dimensions)
        else:
            self.code_array = S

        _grid_table = GridTable(self, self.code_array)
        self.SetTable(_grid_table, True)

        # Grid renderer draws the grid
        self.grid_renderer = GridRenderer(self.code_array)
        self.SetDefaultRenderer(self.grid_renderer)

        # Context menu for quick access of important functions
        self.contextmenu = ContextMenu(parent=self)

        # Handler classes contain event handler methods
        self.handlers = GridEventHandlers(self)
        self.cell_handlers = GridCellEventHandlers(self)

        # Grid actions
        self.actions = AllGridActions(self)

        # Layout and bindings
        self._layout()
        self._bind()

        # Update toolbars
        self.update_entry_line()
        self.update_attribute_toolbar()

        # Focus on grid so that typing can start immediately
        self.SetFocus()
Example #2
0
    def __init__(self, main_window, *args, **kwargs):
        S = kwargs.pop("S")

        self.main_window = main_window

        self._states()

        self.interfaces = GuiInterfaces(self.main_window)

        if S is None:
            dimensions = kwargs.pop("dimensions")
        else:
            dimensions = S.shape
            kwargs.pop("dimensions")

        wx.grid.Grid.__init__(self, main_window, *args, **kwargs)
        glr.GridWithLabelRenderersMixin.__init__(self)

        self.SetDefaultCellBackgroundColour(wx.Colour(255, 255, 255, 255))

        # Cursor position on entering selection mode
        self.sel_mode_cursor = None

        # Set multi line editor
        self.SetDefaultEditor(GridCellEditor(main_window))

        # Create new grid
        if S is None:
            self.code_array = CodeArray(dimensions)
            post_command_event(self, self.GridActionNewMsg, shape=dimensions)
        else:
            self.code_array = S

        _grid_table = GridTable(self, self.code_array)
        self.SetTable(_grid_table, True)

        # Grid renderer draws the grid
        self.grid_renderer = GridRenderer(self.code_array)
        self.SetDefaultRenderer(self.grid_renderer)

        self.SetDefaultRowLabelRenderer(RowLabelRenderer())
        self.SetDefaultColLabelRenderer(ColLabelRenderer())

        # Context menu for quick access of important functions
        self.contextmenu = ContextMenu(parent=self)

        # Handler classes contain event handler methods
        self.handlers = GridEventHandlers(self)
        self.cell_handlers = GridCellEventHandlers(self)

        # Grid actions
        self.actions = AllGridActions(self)

        # Layout and bindings
        self._layout()
        self._bind()

        # Update toolbars
        self.update_entry_line()
        self.update_attribute_toolbar()

        # Focus on grid so that typing can start immediately
        self.SetFocus()
Example #3
0
class Grid(wx.grid.Grid, glr.GridWithLabelRenderersMixin, EventMixin):
    """Pyspread's main grid"""

    def __init__(self, main_window, *args, **kwargs):
        S = kwargs.pop("S")

        self.main_window = main_window

        self._states()

        self.interfaces = GuiInterfaces(self.main_window)

        if S is None:
            dimensions = kwargs.pop("dimensions")
        else:
            dimensions = S.shape
            kwargs.pop("dimensions")

        wx.grid.Grid.__init__(self, main_window, *args, **kwargs)
        glr.GridWithLabelRenderersMixin.__init__(self)

        self.SetDefaultCellBackgroundColour(wx.Colour(255, 255, 255, 255))

        # Cursor position on entering selection mode
        self.sel_mode_cursor = None

        # Set multi line editor
        self.SetDefaultEditor(GridCellEditor(main_window))

        # Create new grid
        if S is None:
            self.code_array = CodeArray(dimensions)
            post_command_event(self, self.GridActionNewMsg, shape=dimensions)
        else:
            self.code_array = S

        _grid_table = GridTable(self, self.code_array)
        self.SetTable(_grid_table, True)

        # Grid renderer draws the grid
        self.grid_renderer = GridRenderer(self.code_array)
        self.SetDefaultRenderer(self.grid_renderer)

        self.SetDefaultRowLabelRenderer(RowLabelRenderer())
        self.SetDefaultColLabelRenderer(ColLabelRenderer())

        # Context menu for quick access of important functions
        self.contextmenu = ContextMenu(parent=self)

        # Handler classes contain event handler methods
        self.handlers = GridEventHandlers(self)
        self.cell_handlers = GridCellEventHandlers(self)

        # Grid actions
        self.actions = AllGridActions(self)

        # Layout and bindings
        self._layout()
        self._bind()

        # Update toolbars
        self.update_entry_line()
        self.update_attribute_toolbar()

        # Focus on grid so that typing can start immediately
        self.SetFocus()

    def _states(self):
        """Sets grid states"""

        # The currently visible table
        self.current_table = 0

        # The cell that has been selected before the latest selection
        self._last_selected_cell = 0, 0, 0

        # If we are viewing cells based on their frozen status or normally
        #  (When true, a cross-hatch is displayed for frozen cells)
        self._view_frozen = False

        # Timer for updating frozen cells
        self.timer_running = False

    def _layout(self):
        """Initial layout of grid"""

        self.EnableGridLines(False)

        # Standard row and col sizes for zooming
        default_cell_attributes = \
            self.code_array.cell_attributes.default_cell_attributes

        self.std_row_size = default_cell_attributes["row-height"]
        self.std_col_size = default_cell_attributes["column-width"]

        self.SetDefaultRowSize(self.std_row_size)
        self.SetDefaultColSize(self.std_col_size)

        # Standard row and col label sizes for zooming
        self.col_label_size = self.GetColLabelSize()
        self.row_label_size = self.GetRowLabelSize()

        self.SetRowMinimalAcceptableHeight(1)
        self.SetColMinimalAcceptableWidth(1)

        self.SetCellHighlightPenWidth(0)

    def _bind(self):
        """Bind events to handlers"""

        main_window = self.main_window

        handlers = self.handlers
        c_handlers = self.cell_handlers

        # Non wx.Grid events

        self.Bind(wx.EVT_MOUSEWHEEL, handlers.OnMouseWheel)
        self.Bind(wx.EVT_KEY_DOWN, handlers.OnKey)

        # Grid events

        self.GetGridWindow().Bind(wx.EVT_MOTION, handlers.OnMouseMotion)
        self.Bind(wx.grid.EVT_GRID_RANGE_SELECT, handlers.OnRangeSelected)

        # Context menu

        self.Bind(wx.grid.EVT_GRID_CELL_RIGHT_CLICK, handlers.OnContextMenu)

        # Cell code events

        main_window.Bind(self.EVT_CMD_CODE_ENTRY, c_handlers.OnCellText)

        main_window.Bind(self.EVT_CMD_INSERT_BMP, c_handlers.OnInsertBitmap)
        main_window.Bind(self.EVT_CMD_LINK_BMP, c_handlers.OnLinkBitmap)
        main_window.Bind(self.EVT_CMD_VIDEO_CELL, c_handlers.OnLinkVLCVideo)
        main_window.Bind(self.EVT_CMD_INSERT_CHART,
                         c_handlers.OnInsertChartDialog)

        # Cell attribute events

        main_window.Bind(self.EVT_CMD_COPY_FORMAT, c_handlers.OnCopyFormat)
        main_window.Bind(self.EVT_CMD_PASTE_FORMAT, c_handlers.OnPasteFormat)

        main_window.Bind(self.EVT_CMD_FONT, c_handlers.OnCellFont)
        main_window.Bind(self.EVT_CMD_FONTSIZE, c_handlers.OnCellFontSize)
        main_window.Bind(self.EVT_CMD_FONTBOLD, c_handlers.OnCellFontBold)
        main_window.Bind(self.EVT_CMD_FONTITALICS,
                         c_handlers.OnCellFontItalics)
        main_window.Bind(self.EVT_CMD_FONTUNDERLINE,
                         c_handlers.OnCellFontUnderline)
        main_window.Bind(self.EVT_CMD_FONTSTRIKETHROUGH,
                         c_handlers.OnCellFontStrikethrough)
        main_window.Bind(self.EVT_CMD_FROZEN, c_handlers.OnCellFrozen)
        main_window.Bind(self.EVT_CMD_LOCK, c_handlers.OnCellLocked)
        main_window.Bind(self.EVT_CMD_BUTTON_CELL, c_handlers.OnButtonCell)
        main_window.Bind(self.EVT_CMD_MARKUP, c_handlers.OnCellMarkup)
        main_window.Bind(self.EVT_CMD_MERGE, c_handlers.OnMerge)
        main_window.Bind(self.EVT_CMD_JUSTIFICATION,
                         c_handlers.OnCellJustification)
        main_window.Bind(self.EVT_CMD_ALIGNMENT, c_handlers.OnCellAlignment)
        main_window.Bind(self.EVT_CMD_BORDERWIDTH,
                         c_handlers.OnCellBorderWidth)
        main_window.Bind(self.EVT_CMD_BORDERCOLOR,
                         c_handlers.OnCellBorderColor)
        main_window.Bind(self.EVT_CMD_BACKGROUNDCOLOR,
                         c_handlers.OnCellBackgroundColor)
        main_window.Bind(self.EVT_CMD_TEXTCOLOR, c_handlers.OnCellTextColor)
        main_window.Bind(self.EVT_CMD_ROTATION0,
                         c_handlers.OnTextRotation0)
        main_window.Bind(self.EVT_CMD_ROTATION90,
                         c_handlers.OnTextRotation90)
        main_window.Bind(self.EVT_CMD_ROTATION180,
                         c_handlers.OnTextRotation180)
        main_window.Bind(self.EVT_CMD_ROTATION270,
                         c_handlers.OnTextRotation270)
        main_window.Bind(self.EVT_CMD_TEXTROTATATION,
                         c_handlers.OnCellTextRotation)

        # Cell selection events

        self.Bind(wx.grid.EVT_GRID_CMD_SELECT_CELL, c_handlers.OnCellSelected)

        # Grid edit mode events

        main_window.Bind(self.EVT_CMD_ENTER_SELECTION_MODE,
                         handlers.OnEnterSelectionMode)
        main_window.Bind(self.EVT_CMD_EXIT_SELECTION_MODE,
                         handlers.OnExitSelectionMode)

        # Grid view events

        main_window.Bind(self.EVT_CMD_VIEW_FROZEN, handlers.OnViewFrozen)
        main_window.Bind(self.EVT_CMD_REFRESH_SELECTION,
                         handlers.OnRefreshSelectedCells)
        main_window.Bind(self.EVT_CMD_TIMER_TOGGLE,
                         handlers.OnTimerToggle)
        self.Bind(wx.EVT_TIMER, handlers.OnTimer)
        main_window.Bind(self.EVT_CMD_DISPLAY_GOTO_CELL_DIALOG,
                         handlers.OnDisplayGoToCellDialog)
        main_window.Bind(self.EVT_CMD_GOTO_CELL, handlers.OnGoToCell)
        main_window.Bind(self.EVT_CMD_ZOOM_IN, handlers.OnZoomIn)
        main_window.Bind(self.EVT_CMD_ZOOM_OUT, handlers.OnZoomOut)
        main_window.Bind(self.EVT_CMD_ZOOM_STANDARD, handlers.OnZoomStandard)
        main_window.Bind(self.EVT_CMD_ZOOM_FIT, handlers.OnZoomFit)

        # Find events
        main_window.Bind(self.EVT_CMD_FIND, handlers.OnFind)
        main_window.Bind(self.EVT_CMD_REPLACE, handlers.OnShowFindReplace)
        main_window.Bind(wx.EVT_FIND, handlers.OnReplaceFind)
        main_window.Bind(wx.EVT_FIND_NEXT, handlers.OnReplaceFind)
        main_window.Bind(wx.EVT_FIND_REPLACE, handlers.OnReplace)
        main_window.Bind(wx.EVT_FIND_REPLACE_ALL, handlers.OnReplaceAll)
        main_window.Bind(wx.EVT_FIND_CLOSE, handlers.OnCloseFindReplace)

        # Grid change events

        main_window.Bind(self.EVT_CMD_INSERT_ROWS, handlers.OnInsertRows)
        main_window.Bind(self.EVT_CMD_INSERT_COLS, handlers.OnInsertCols)
        main_window.Bind(self.EVT_CMD_INSERT_TABS, handlers.OnInsertTabs)

        main_window.Bind(self.EVT_CMD_DELETE_ROWS, handlers.OnDeleteRows)
        main_window.Bind(self.EVT_CMD_DELETE_COLS, handlers.OnDeleteCols)
        main_window.Bind(self.EVT_CMD_DELETE_TABS, handlers.OnDeleteTabs)

        main_window.Bind(self.EVT_CMD_SHOW_RESIZE_GRID_DIALOG,
                         handlers.OnResizeGridDialog)
        main_window.Bind(self.EVT_CMD_QUOTE, handlers.OnQuote)

        main_window.Bind(wx.grid.EVT_GRID_ROW_SIZE, handlers.OnRowSize)
        main_window.Bind(wx.grid.EVT_GRID_COL_SIZE, handlers.OnColSize)

        main_window.Bind(self.EVT_CMD_SORT_ASCENDING, handlers.OnSortAscending)
        main_window.Bind(self.EVT_CMD_SORT_DESCENDING,
                         handlers.OnSortDescending)

        # Undo/Redo events

        main_window.Bind(self.EVT_CMD_UNDO, handlers.OnUndo)
        main_window.Bind(self.EVT_CMD_REDO, handlers.OnRedo)

    _get_selection = lambda self: self.actions.get_selection()
    selection = property(_get_selection, doc="Grid selection")

    # Collison helper functions for grid drawing
    # ------------------------------------------

    def is_merged_cell_drawn(self, key):
        """True if key in merged area shall be drawn

        This is the case if it is the top left most visible key of the merge
        area on the screen.

        """

        row, col, tab = key

        # Is key not merged? --> False
        cell_attributes = self.code_array.cell_attributes

        top, left, __ = cell_attributes.get_merging_cell(key)

        # Case 1: Top left cell of merge is visible
        # --> Only top left cell returns True
        top_left_drawn = \
            row == top and col == left and \
            self.IsVisible(row, col, wholeCellVisible=False)

        # Case 2: Leftmost column is visible
        # --> Only top visible leftmost cell returns True

        left_drawn = \
            col == left and \
            self.IsVisible(row, col, wholeCellVisible=False) and \
            not self.IsVisible(row-1, col, wholeCellVisible=False)

        # Case 3: Top row is visible
        # --> Only left visible top cell returns True

        top_drawn = \
            row == top and \
            self.IsVisible(row, col, wholeCellVisible=False) and \
            not self.IsVisible(row, col-1, wholeCellVisible=False)

        # Case 4: Top row and leftmost column are invisible
        # --> Only top left visible cell returns True

        middle_drawn = \
            self.IsVisible(row, col, wholeCellVisible=False) and \
            not self.IsVisible(row-1, col, wholeCellVisible=False) and \
            not self.IsVisible(row, col-1, wholeCellVisible=False)

        return top_left_drawn or left_drawn or top_drawn or middle_drawn

    def update_entry_line(self, key=None):
        """Updates the entry line

        Parameters
        ----------
        key: 3-tuple of Integer, defaults to current cell
        \tCell to which code the entry line is updated

        """

        if key is None:
            key = self.actions.cursor

        cell_code = self.GetTable().GetValue(*key)

        post_command_event(self, self.EntryLineMsg, text=cell_code)

    def lock_entry_line(self, lock):
        """Lock or unlock entry line

        Parameters
        ----------
        lock: Bool
        \tIf True then the entry line is locked if Falsse unlocked

        """

        post_command_event(self, self.LockEntryLineMsg, lock=lock)

    def update_attribute_toolbar(self, key=None):
        """Updates the attribute toolbar

        Parameters
        ----------
        key: 3-tuple of Integer, defaults to current cell
        \tCell to which attributes the attributes toolbar is updated

        """

        if key is None:
            key = self.actions.cursor

        post_command_event(self, self.ToolbarUpdateMsg, key=key,
                           attr=self.code_array.cell_attributes[key])

    def _update_video_volume_cell_attributes(self, key):
        """Updates the panel cell attrutes of a panel cell"""

        try:
            video_cell_panel = self.grid_renderer.video_cells[key]
        except KeyError:
            return

        old_video_volume = self.code_array.cell_attributes[key]["video_volume"]
        new_video_volume = video_cell_panel.volume

        if old_video_volume == new_video_volume:
            return

        selection = Selection([], [], [], [], [key])

        self.actions.set_attr("video_volume", new_video_volume, selection,
                              mark_unredo=False)

    def ForceRefresh(self, *args, **kwargs):
        """Refresh hook"""

        wx.grid.Grid.ForceRefresh(self, *args, **kwargs)

        for video_cell_key in self.grid_renderer.video_cells:
            if video_cell_key[2] == self.current_table:
                video_cell = self.grid_renderer.video_cells[video_cell_key]
                rect = self.CellToRect(video_cell_key[0], video_cell_key[1])
                drawn_rect = self.grid_renderer._get_drawn_rect(self,
                                                                video_cell_key,
                                                                rect)
                video_cell.SetClientRect(drawn_rect)
                self._update_video_volume_cell_attributes(video_cell_key)
Example #4
0
class Grid(wx.grid.Grid, glr.GridWithLabelRenderersMixin, EventMixin):
    """Pyspread's main grid"""
    def __init__(self, main_window, *args, **kwargs):
        S = kwargs.pop("S")

        self.main_window = main_window

        self._states()

        self.interfaces = GuiInterfaces(self.main_window)

        if S is None:
            dimensions = kwargs.pop("dimensions")
        else:
            dimensions = S.shape
            kwargs.pop("dimensions")

        wx.grid.Grid.__init__(self, main_window, *args, **kwargs)
        glr.GridWithLabelRenderersMixin.__init__(self)

        self.SetDefaultCellBackgroundColour(
            get_color(config["background_color"]))

        # Cursor position on entering selection mode
        self.sel_mode_cursor = None

        # Set multi line editor
        self.SetDefaultEditor(GridCellEditor(main_window))

        # Create new grid
        if S is None:
            self.code_array = CodeArray(dimensions)
            post_command_event(self, self.GridActionNewMsg, shape=dimensions)
        else:
            self.code_array = S

        _grid_table = GridTable(self, self.code_array)
        self.SetTable(_grid_table, True)

        # Grid renderer draws the grid
        self.grid_renderer = GridRenderer(self.code_array)
        self.SetDefaultRenderer(self.grid_renderer)

        self.SetDefaultRowLabelRenderer(RowLabelRenderer())
        self.SetDefaultColLabelRenderer(ColLabelRenderer())

        # Context menu for quick access of important functions
        self.contextmenu = ContextMenu(parent=self)

        # Handler classes contain event handler methods
        self.handlers = GridEventHandlers(self)
        self.cell_handlers = GridCellEventHandlers(self)

        # Grid actions
        self.actions = AllGridActions(self)

        # Layout and bindings
        self._layout()
        self._bind()

        # Update toolbars
        self.update_entry_line()
        self.update_attribute_toolbar()

        # Focus on grid so that typing can start immediately
        self.SetFocus()

    def _states(self):
        """Sets grid states"""

        # The currently visible table
        self.current_table = 0

        # The cell that has been selected before the latest selection
        self._last_selected_cell = 0, 0, 0

        # If we are viewing cells based on their frozen status or normally
        #  (When true, a cross-hatch is displayed for frozen cells)
        self._view_frozen = False

        # Timer for updating frozen cells
        self.timer_running = False

    def _layout(self):
        """Initial layout of grid"""

        self.EnableGridLines(False)

        # Standard row and col sizes for zooming
        default_cell_attributes = \
            self.code_array.cell_attributes.default_cell_attributes

        self.std_row_size = default_cell_attributes["row-height"]
        self.std_col_size = default_cell_attributes["column-width"]

        self.SetDefaultRowSize(self.std_row_size)
        self.SetDefaultColSize(self.std_col_size)

        # Standard row and col label sizes for zooming
        self.col_label_size = self.GetColLabelSize()
        self.row_label_size = self.GetRowLabelSize()

        self.SetRowMinimalAcceptableHeight(1)
        self.SetColMinimalAcceptableWidth(1)

        self.SetCellHighlightPenWidth(0)

    def _bind(self):
        """Bind events to handlers"""

        main_window = self.main_window

        handlers = self.handlers
        c_handlers = self.cell_handlers

        # Non wx.Grid events

        self.Bind(wx.EVT_MOUSEWHEEL, handlers.OnMouseWheel)
        self.Bind(wx.EVT_KEY_DOWN, handlers.OnKey)

        # Grid events

        self.GetGridWindow().Bind(wx.EVT_MOTION, handlers.OnMouseMotion)
        self.Bind(wx.grid.EVT_GRID_RANGE_SELECT, handlers.OnRangeSelected)

        # Context menu

        self.Bind(wx.grid.EVT_GRID_CELL_RIGHT_CLICK, handlers.OnContextMenu)

        # Cell code events

        main_window.Bind(self.EVT_CMD_CODE_ENTRY, c_handlers.OnCellText)

        main_window.Bind(self.EVT_CMD_INSERT_BMP, c_handlers.OnInsertBitmap)
        main_window.Bind(self.EVT_CMD_LINK_BMP, c_handlers.OnLinkBitmap)
        main_window.Bind(self.EVT_CMD_VIDEO_CELL, c_handlers.OnLinkVLCVideo)
        main_window.Bind(self.EVT_CMD_INSERT_CHART,
                         c_handlers.OnInsertChartDialog)

        # Cell attribute events

        main_window.Bind(self.EVT_CMD_COPY_FORMAT, c_handlers.OnCopyFormat)
        main_window.Bind(self.EVT_CMD_PASTE_FORMAT, c_handlers.OnPasteFormat)

        main_window.Bind(self.EVT_CMD_FONT, c_handlers.OnCellFont)
        main_window.Bind(self.EVT_CMD_FONTSIZE, c_handlers.OnCellFontSize)
        main_window.Bind(self.EVT_CMD_FONTBOLD, c_handlers.OnCellFontBold)
        main_window.Bind(self.EVT_CMD_FONTITALICS,
                         c_handlers.OnCellFontItalics)
        main_window.Bind(self.EVT_CMD_FONTUNDERLINE,
                         c_handlers.OnCellFontUnderline)
        main_window.Bind(self.EVT_CMD_FONTSTRIKETHROUGH,
                         c_handlers.OnCellFontStrikethrough)
        main_window.Bind(self.EVT_CMD_FROZEN, c_handlers.OnCellFrozen)
        main_window.Bind(self.EVT_CMD_LOCK, c_handlers.OnCellLocked)
        main_window.Bind(self.EVT_CMD_BUTTON_CELL, c_handlers.OnButtonCell)
        main_window.Bind(self.EVT_CMD_MARKUP, c_handlers.OnCellMarkup)
        main_window.Bind(self.EVT_CMD_MERGE, c_handlers.OnMerge)
        main_window.Bind(self.EVT_CMD_JUSTIFICATION,
                         c_handlers.OnCellJustification)
        main_window.Bind(self.EVT_CMD_ALIGNMENT, c_handlers.OnCellAlignment)
        main_window.Bind(self.EVT_CMD_BORDERWIDTH,
                         c_handlers.OnCellBorderWidth)
        main_window.Bind(self.EVT_CMD_BORDERCOLOR,
                         c_handlers.OnCellBorderColor)
        main_window.Bind(self.EVT_CMD_BACKGROUNDCOLOR,
                         c_handlers.OnCellBackgroundColor)
        main_window.Bind(self.EVT_CMD_TEXTCOLOR, c_handlers.OnCellTextColor)
        main_window.Bind(self.EVT_CMD_ROTATION0, c_handlers.OnTextRotation0)
        main_window.Bind(self.EVT_CMD_ROTATION90, c_handlers.OnTextRotation90)
        main_window.Bind(self.EVT_CMD_ROTATION180,
                         c_handlers.OnTextRotation180)
        main_window.Bind(self.EVT_CMD_ROTATION270,
                         c_handlers.OnTextRotation270)
        main_window.Bind(self.EVT_CMD_TEXTROTATATION,
                         c_handlers.OnCellTextRotation)

        # Cell selection events

        self.Bind(wx.grid.EVT_GRID_CMD_SELECT_CELL, c_handlers.OnCellSelected)

        # Grid edit mode events

        main_window.Bind(self.EVT_CMD_ENTER_SELECTION_MODE,
                         handlers.OnEnterSelectionMode)
        main_window.Bind(self.EVT_CMD_EXIT_SELECTION_MODE,
                         handlers.OnExitSelectionMode)

        # Grid view events

        main_window.Bind(self.EVT_CMD_VIEW_FROZEN, handlers.OnViewFrozen)
        main_window.Bind(self.EVT_CMD_REFRESH_SELECTION,
                         handlers.OnRefreshSelectedCells)
        main_window.Bind(self.EVT_CMD_TIMER_TOGGLE, handlers.OnTimerToggle)
        self.Bind(wx.EVT_TIMER, handlers.OnTimer)
        main_window.Bind(self.EVT_CMD_DISPLAY_GOTO_CELL_DIALOG,
                         handlers.OnDisplayGoToCellDialog)
        main_window.Bind(self.EVT_CMD_GOTO_CELL, handlers.OnGoToCell)
        main_window.Bind(self.EVT_CMD_ZOOM_IN, handlers.OnZoomIn)
        main_window.Bind(self.EVT_CMD_ZOOM_OUT, handlers.OnZoomOut)
        main_window.Bind(self.EVT_CMD_ZOOM_STANDARD, handlers.OnZoomStandard)
        main_window.Bind(self.EVT_CMD_ZOOM_FIT, handlers.OnZoomFit)

        # Find events
        main_window.Bind(self.EVT_CMD_FIND, handlers.OnFind)
        main_window.Bind(self.EVT_CMD_REPLACE, handlers.OnShowFindReplace)
        main_window.Bind(wx.EVT_FIND, handlers.OnReplaceFind)
        main_window.Bind(wx.EVT_FIND_NEXT, handlers.OnReplaceFind)
        main_window.Bind(wx.EVT_FIND_REPLACE, handlers.OnReplace)
        main_window.Bind(wx.EVT_FIND_REPLACE_ALL, handlers.OnReplaceAll)
        main_window.Bind(wx.EVT_FIND_CLOSE, handlers.OnCloseFindReplace)

        # Grid change events

        main_window.Bind(self.EVT_CMD_INSERT_ROWS, handlers.OnInsertRows)
        main_window.Bind(self.EVT_CMD_INSERT_COLS, handlers.OnInsertCols)
        main_window.Bind(self.EVT_CMD_INSERT_TABS, handlers.OnInsertTabs)

        main_window.Bind(self.EVT_CMD_DELETE_ROWS, handlers.OnDeleteRows)
        main_window.Bind(self.EVT_CMD_DELETE_COLS, handlers.OnDeleteCols)
        main_window.Bind(self.EVT_CMD_DELETE_TABS, handlers.OnDeleteTabs)

        main_window.Bind(self.EVT_CMD_SHOW_RESIZE_GRID_DIALOG,
                         handlers.OnResizeGridDialog)
        main_window.Bind(self.EVT_CMD_QUOTE, handlers.OnQuote)

        main_window.Bind(wx.grid.EVT_GRID_ROW_SIZE, handlers.OnRowSize)
        main_window.Bind(wx.grid.EVT_GRID_COL_SIZE, handlers.OnColSize)

        main_window.Bind(self.EVT_CMD_SORT_ASCENDING, handlers.OnSortAscending)
        main_window.Bind(self.EVT_CMD_SORT_DESCENDING,
                         handlers.OnSortDescending)

        # Undo/Redo events

        main_window.Bind(self.EVT_CMD_UNDO, handlers.OnUndo)
        main_window.Bind(self.EVT_CMD_REDO, handlers.OnRedo)

    _get_selection = lambda self: self.actions.get_selection()
    selection = property(_get_selection, doc="Grid selection")

    # Collison helper functions for grid drawing
    # ------------------------------------------

    def is_merged_cell_drawn(self, key):
        """True if key in merged area shall be drawn

        This is the case if it is the top left most visible key of the merge
        area on the screen.

        """

        row, col, tab = key

        # Is key not merged? --> False
        cell_attributes = self.code_array.cell_attributes

        top, left, __ = cell_attributes.get_merging_cell(key)

        # Case 1: Top left cell of merge is visible
        # --> Only top left cell returns True
        top_left_drawn = \
            row == top and col == left and \
            self.IsVisible(row, col, wholeCellVisible=False)

        # Case 2: Leftmost column is visible
        # --> Only top visible leftmost cell returns True

        left_drawn = \
            col == left and \
            self.IsVisible(row, col, wholeCellVisible=False) and \
            not self.IsVisible(row-1, col, wholeCellVisible=False)

        # Case 3: Top row is visible
        # --> Only left visible top cell returns True

        top_drawn = \
            row == top and \
            self.IsVisible(row, col, wholeCellVisible=False) and \
            not self.IsVisible(row, col-1, wholeCellVisible=False)

        # Case 4: Top row and leftmost column are invisible
        # --> Only top left visible cell returns True

        middle_drawn = \
            self.IsVisible(row, col, wholeCellVisible=False) and \
            not self.IsVisible(row-1, col, wholeCellVisible=False) and \
            not self.IsVisible(row, col-1, wholeCellVisible=False)

        return top_left_drawn or left_drawn or top_drawn or middle_drawn

    def update_entry_line(self, key=None):
        """Updates the entry line

        Parameters
        ----------
        key: 3-tuple of Integer, defaults to current cell
        \tCell to which code the entry line is updated

        """

        if key is None:
            key = self.actions.cursor

        cell_code = self.GetTable().GetValue(*key)

        post_command_event(self, self.EntryLineMsg, text=cell_code)

    def lock_entry_line(self, lock):
        """Lock or unlock entry line

        Parameters
        ----------
        lock: Bool
        \tIf True then the entry line is locked if Falsse unlocked

        """

        post_command_event(self, self.LockEntryLineMsg, lock=lock)

    def update_attribute_toolbar(self, key=None):
        """Updates the attribute toolbar

        Parameters
        ----------
        key: 3-tuple of Integer, defaults to current cell
        \tCell to which attributes the attributes toolbar is updated

        """

        if key is None:
            key = self.actions.cursor

        post_command_event(self,
                           self.ToolbarUpdateMsg,
                           key=key,
                           attr=self.code_array.cell_attributes[key])

    def _update_video_volume_cell_attributes(self, key):
        """Updates the panel cell attrutes of a panel cell"""

        try:
            video_cell_panel = self.grid_renderer.video_cells[key]
        except KeyError:
            return

        old_video_volume = self.code_array.cell_attributes[key]["video_volume"]
        new_video_volume = video_cell_panel.volume

        if old_video_volume == new_video_volume:
            return

        selection = Selection([], [], [], [], [key])

        self.actions.set_attr("video_volume",
                              new_video_volume,
                              selection,
                              mark_unredo=False)

    def ForceRefresh(self, *args, **kwargs):
        """Refresh hook"""

        wx.grid.Grid.ForceRefresh(self, *args, **kwargs)

        for video_cell_key in self.grid_renderer.video_cells:
            if video_cell_key[2] == self.current_table:
                video_cell = self.grid_renderer.video_cells[video_cell_key]
                rect = self.CellToRect(video_cell_key[0], video_cell_key[1])
                drawn_rect = self.grid_renderer._get_drawn_rect(
                    self, video_cell_key, rect)
                video_cell.SetClientRect(drawn_rect)
                self._update_video_volume_cell_attributes(video_cell_key)