EventGhost/EventGhost

View on GitHub
eg/Classes/ConfigPanel.py

Summary

Maintainability
A
1 hr
Test Coverage
# -*- coding: utf-8 -*-
#
# This file is part of EventGhost.
# Copyright © 2005-2020 EventGhost Project <http://www.eventghost.net/>
#
# EventGhost is free software: you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free
# Software Foundation, either version 2 of the License, or (at your option)
# any later version.
#
# EventGhost is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
# more details.
#
# You should have received a copy of the GNU General Public License along
# with EventGhost. If not, see <http://www.gnu.org/licenses/>.

import types
import wx
from inspect import currentframe, getargvalues, getouterframes

# Local imports
import eg

class ConfigPanel(wx.PyPanel, eg.ControlProviderMixin):
    """
    A panel with some magic.
    """
    def __init__(
        self,
        executable=None,
        resizable=True,
        showLine=True
    ):
        #if resizable is None:
        #    resizable = bool(eg.debugLevel)
        dialog = eg.ConfigDialog.currentDialog
        dialog.panel = self
        dialog.__init__(resizable, showLine)
        self.dialog = dialog
        wx.PyPanel.__init__(self, dialog.notebook)
        dialog.notebook.AddPage(self, "Settings")
        self.lines = []
        dialog.sizer.Add(self, 1, wx.EXPAND)
        self.sizerProps = (6, 5)
        self.rowFlags = {}
        self.colFlags = {}
        self.shown = False
        self.maxRowNum = 0
        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.isDirty = False
        self.resultCode = None
        self.buttonsEnabled = True
        outer = getouterframes(currentframe())
        has_args = len(getargvalues(outer[1][0]).args) > 1
        self.dialog.buttonRow.applyButton.Enable(
            has_args and self.dialog.treeItem.isFirstConfigure
        )
        self.dialog.buttonRow.okButton.Enable(
            not has_args or
            not (has_args and self.dialog.treeItem.isFirstConfigure)
        )

    def AddCtrl(self, ctrl):
        self.sizer.Add(ctrl, 0, wx.BOTTOM, 10)

    def AddGrid(self, grid, vgap=6, hgap=5):
        columns = self.maxRowNum
        sizer = wx.GridBagSizer(vgap, hgap)
        sizer.SetFlexibleDirection(wx.HORIZONTAL)
        rowFlagsGet = self.rowFlags.get
        colFlagsGet = self.colFlags.get
        for rowNum, (row, kwargs) in enumerate(grid):
            if kwargs.get("growable", False):
                sizer.AddGrowableRow(rowNum)
            for colNum, ctrl in enumerate(row):
                if ctrl is None:
                    ctrl = (1, 1)
                elif type(ctrl) in types.StringTypes:
                    ctrl = wx.StaticText(self, -1, ctrl)

                flags = rowFlagsGet(rowNum, 0) | colFlagsGet(colNum, 0)
                flags |= (wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_LEFT)
                sizer.Add(ctrl, (rowNum, colNum), (1, 1), flags)

            if colNum < columns - 1:
                sizer.SetItemSpan(ctrl, (1, columns - colNum + 1))
        self.sizer.Add(sizer, 1, wx.EXPAND)

    def AddLabel(self, label):
        self.sizer.Add(self.StaticText(label), 0, wx.BOTTOM, 2)

    def AddLine(self, *items, **kwargs):
        self.maxRowNum = max(self.maxRowNum, len(items))
        self.lines.append((items, kwargs))

    def Affirmed(self):
        """
        Returns the user request.

        If called the first time, it will also finish creation of the panel
        and show it to the user, before returning the user request.

        The return value depends on the button the user has pressed in the
        panel:

            | Cancel button => :const:`False`
            | Ok button => :const:`wx.ID_OK`
            | Apply button => :const:`wx.ID_APPLY`
            | Test button => :const:`eg.ID_TEST`
        """
        self.resultCode = self.dialog.Affirmed()
        return self.resultCode

    def EnableButtons(self, flag=True):
        """
        Enables/Disables the OK, Apply and Test buttons.

        Useful if you want to temporarily disable them, because the current
        settings have no valid state and later re-enable them.
        """
        self.buttonsEnabled = flag
        buttonRow = self.dialog.buttonRow
        buttonRow.okButton.Enable(flag)
        if buttonRow.testButton:
            buttonRow.testButton.Enable(flag)
        if flag and self.isDirty:
            buttonRow.applyButton.Enable(True)
        else:
            buttonRow.applyButton.Enable(False)

    def FinishSetup(self):
        self.shown = True
        if self.lines:
            self.AddGrid(self.lines, *self.sizerProps)
        spaceSizer = wx.BoxSizer(wx.HORIZONTAL)
        spaceSizer.Add((2, 2))
        spaceSizer.Add(self.sizer, 1, wx.EXPAND | wx.TOP | wx.BOTTOM, 3)
        spaceSizer.Add((4, 4))
        self.SetSizerAndFit(spaceSizer)

        #self.dialog.FinishSetup()
        def OnEvent(dummyEvent):
            self.SetIsDirty()
        self.Bind(wx.EVT_CHECKBOX, OnEvent)
        self.Bind(wx.EVT_BUTTON, OnEvent)
        self.Bind(wx.EVT_CHOICE, OnEvent)
        self.Bind(wx.EVT_TOGGLEBUTTON, OnEvent)
        self.Bind(wx.EVT_TEXT, OnEvent)
        self.Bind(wx.EVT_RADIOBOX, OnEvent)
        self.Bind(wx.EVT_RADIOBUTTON, OnEvent)
        self.Bind(wx.EVT_TREE_SEL_CHANGED, OnEvent)
        self.Bind(wx.EVT_DATE_CHANGED, OnEvent)
        self.Bind(eg.EVT_VALUE_CHANGED, OnEvent)
        self.Bind(wx.EVT_CHECKLISTBOX, OnEvent)
        self.Bind(wx.EVT_SCROLL, OnEvent)
        self.Bind(wx.EVT_LISTBOX, OnEvent)

    def SetColumnFlags(self, colNum, flags):
        self.colFlags[colNum] = flags

    @eg.LogIt
    def SetIsDirty(self, flag=True):
        self.isDirty = flag
        if flag and self.dialog.treeItem.isFirstConfigure:
            self.dialog.buttonRow.okButton.Enable(True)
        elif self.dialog.treeItem.isFirstConfigure:
            self.dialog.buttonRow.okButton.Enable(False)

        if flag and self.buttonsEnabled:
            self.dialog.buttonRow.applyButton.Enable(True)

    def SetResult(self, *args):
        """
        Notifies the program of the current values of the configuration
        controls.
        """
        if self.resultCode != eg.ID_TEST:
            self.dialog.buttonRow.applyButton.Enable(False)
            self.isDirty = False
        self.dialog.SetResult(*args)

    def SetRowFlags(self, rowNum, flags):
        self.rowFlags[rowNum] = flags

    def SetSizerProperty(self, vgap=6, hgap=5):
        self.sizerProps = (vgap, hgap)