mirror of
https://github.com/Sneed-Group/Poodletooth-iLand
synced 2024-12-27 21:52:25 -06:00
540 lines
18 KiB
Python
540 lines
18 KiB
Python
#----------------------------------------------------------------------------
|
|
# Name: fmcustomizeddlg.py
|
|
# Purpose:
|
|
#
|
|
# Author:
|
|
#
|
|
# Created:
|
|
# Version:
|
|
# Date:
|
|
# Licence: wxWindows license
|
|
# Tags: phoenix-port, py3-port
|
|
#----------------------------------------------------------------------------
|
|
"""
|
|
This module contains a custom dialog class used to personalize the appearance of a
|
|
:class:`~lib.agw.flatmenu.FlatMenu` on the fly, allowing also the user of your application to do the same.
|
|
"""
|
|
|
|
import wx
|
|
import wx.lib.six as six
|
|
|
|
if six.PY2:
|
|
from UserDict import UserDict
|
|
else:
|
|
from collections import UserDict
|
|
|
|
from .artmanager import ArtManager
|
|
from .fmresources import *
|
|
from .labelbook import LabelBook
|
|
|
|
_ = wx.GetTranslation
|
|
|
|
# ---------------------------------------------------------------------------- #
|
|
# Class OrderedDict
|
|
# ---------------------------------------------------------------------------- #
|
|
|
|
class OrderedDict(UserDict):
|
|
"""
|
|
An ordered dictionary implementation.
|
|
"""
|
|
|
|
def __init__(self, dict = None):
|
|
self._keys = []
|
|
UserDict.__init__(self, dict)
|
|
|
|
def __delitem__(self, key):
|
|
UserDict.__delitem__(self, key)
|
|
self._keys.remove(key)
|
|
|
|
def __setitem__(self, key, item):
|
|
UserDict.__setitem__(self, key, item)
|
|
if key not in self._keys: self._keys.append(key)
|
|
|
|
def clear(self):
|
|
UserDict.clear(self)
|
|
self._keys = []
|
|
|
|
def copy(self):
|
|
dict = UserDict.copy(self)
|
|
dict._keys = self._keys[:]
|
|
return dict
|
|
|
|
def items(self):
|
|
return list(zip(self._keys, list(self.values())))
|
|
|
|
def keys(self):
|
|
return self._keys
|
|
|
|
def popitem(self):
|
|
try:
|
|
key = self._keys[-1]
|
|
except IndexError:
|
|
raise KeyError('dictionary is empty')
|
|
|
|
val = self[key]
|
|
del self[key]
|
|
|
|
return (key, val)
|
|
|
|
def setdefault(self, key, failobj = None):
|
|
UserDict.setdefault(self, key, failobj)
|
|
if key not in self._keys: self._keys.append(key)
|
|
|
|
def update(self, dict):
|
|
UserDict.update(self, dict)
|
|
for key in list(dict.keys()):
|
|
if key not in self._keys: self._keys.append(key)
|
|
|
|
def values(self):
|
|
return list(map(self.get, self._keys))
|
|
|
|
|
|
# ---------------------------------------------------------------------------- #
|
|
# Class FMTitlePanel
|
|
# ---------------------------------------------------------------------------- #
|
|
|
|
class FMTitlePanel(wx.Panel):
|
|
"""
|
|
Helper class to draw gradient shadings on the dialog.
|
|
"""
|
|
|
|
def __init__(self, parent, title):
|
|
"""
|
|
Default class constructor.
|
|
|
|
:param `parent`: the :class:`FMTitlePanel` parent;
|
|
:param `title`: the string to use as a dialog title.
|
|
"""
|
|
|
|
wx.Panel.__init__(self, parent)
|
|
self._title = title
|
|
|
|
# Set the panel size
|
|
dc = wx.MemoryDC()
|
|
dc.SelectObject(wx.Bitmap(1, 1))
|
|
dc.SetFont(wx.SystemSettings.GetFont( wx.SYS_DEFAULT_GUI_FONT ))
|
|
|
|
ww, hh = dc.GetTextExtent("Tp")
|
|
dc.SelectObject(wx.NullBitmap)
|
|
|
|
# Set minimum panel size
|
|
if ww < 250:
|
|
ww = 250
|
|
|
|
self.SetSize(wx.Size(ww, hh + 10))
|
|
|
|
self.Bind(wx.EVT_PAINT, self.OnPaint)
|
|
self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
|
|
|
|
|
|
def OnEraseBackground(self, event):
|
|
"""
|
|
Handles the ``wx.EVT_ERASE_BACKGROUND`` event for :class:`FMTitlePanel`.
|
|
|
|
:param `event`: a :class:`EraseEvent` event to be processed.
|
|
|
|
:note: This method is intentionally empty to reduce flicker.
|
|
"""
|
|
|
|
pass
|
|
|
|
|
|
def OnPaint(self, event):
|
|
"""
|
|
Handles the ``wx.EVT_PAINT`` event for :class:`FMTitlePanel`.
|
|
|
|
:param `event`: a :class:`PaintEvent` event to be processed.
|
|
"""
|
|
|
|
dc = wx.BufferedPaintDC(self)
|
|
|
|
# Draw the background
|
|
colour1 = wx.SystemSettings.GetColour(wx.SYS_COLOUR_3DFACE)
|
|
colour2 = ArtManager.Get().LightColour(colour1, 70)
|
|
ArtManager.Get().PaintStraightGradientBox(dc, self.GetClientRect(), colour1, colour2, False)
|
|
|
|
# Draw the text
|
|
font = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT)
|
|
font.SetWeight(wx.FONTWEIGHT_BOLD)
|
|
dc.SetFont(font)
|
|
dc.SetTextForeground(wx.BLACK)
|
|
dc.DrawText(self._title, 5, 5)
|
|
|
|
|
|
# ---------------------------------------------------------------------------- #
|
|
# Class FMCustomizeDlg
|
|
# ---------------------------------------------------------------------------- #
|
|
|
|
class FMCustomizeDlg(wx.Dialog):
|
|
"""
|
|
Class used to customize the appearance of :class:`~lib.agw.flatmenu.FlatMenu`
|
|
and :class:`~lib.agw.flatmenu.FlatMenuBar`.
|
|
"""
|
|
|
|
def __init__(self, parent=None):
|
|
"""
|
|
Default class constructor.
|
|
|
|
:param `parent`: the :class:`FMCustomizeDlg` parent window.
|
|
"""
|
|
|
|
self._book = None
|
|
|
|
if not parent:
|
|
wx.Dialog.__init__(self)
|
|
return
|
|
|
|
wx.Dialog.__init__(self, parent, wx.ID_ANY, _("Customize"), wx.DefaultPosition,
|
|
wx.DefaultSize, wx.DEFAULT_DIALOG_STYLE)
|
|
|
|
self._visibleMenus = OrderedDict()
|
|
self._hiddenMenus = OrderedDict()
|
|
|
|
self.CreateDialog()
|
|
self.ConnectEvents()
|
|
self.GetSizer().Fit(self)
|
|
self.GetSizer().SetSizeHints(self)
|
|
self.GetSizer().Layout()
|
|
self.Centre()
|
|
|
|
|
|
def CreateDialog(self):
|
|
""" Actually creates the dialog. """
|
|
|
|
sz = wx.BoxSizer(wx.VERTICAL)
|
|
self.SetSizer(sz)
|
|
|
|
# Create the main book and add some pages into it
|
|
style = INB_NO_RESIZE | INB_LEFT | INB_DRAW_SHADOW | INB_BORDER
|
|
self._book = LabelBook(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, style)
|
|
sz.Add(self._book, 1, wx.EXPAND)
|
|
|
|
self._book.SetColour(INB_TAB_AREA_BACKGROUND_COLOUR, ArtManager.Get().GetMenuFaceColour())
|
|
|
|
colour = wx.SystemSettings.GetColour(wx.SYS_COLOUR_3DFACE)
|
|
self._book.SetColour(INB_ACTIVE_TAB_COLOUR, colour)
|
|
|
|
self.created = False
|
|
self.Initialise()
|
|
hsizer = wx.BoxSizer(wx.HORIZONTAL)
|
|
|
|
# add a separator between the book & the buttons area
|
|
hsizer.Add(wx.Button(self, wx.ID_OK, _("&Close")), 0, wx.EXPAND | wx.ALIGN_RIGHT)
|
|
sz.Add(wx.StaticLine(self), 0, wx.EXPAND | wx.TOP | wx.BOTTOM, 3)
|
|
sz.Add(hsizer, 0, wx.ALIGN_RIGHT | wx.ALL, 2)
|
|
|
|
|
|
def Initialise(self):
|
|
""" Initialzes the :class:`~lib.agw.labelbook.LabelBook` pages. """
|
|
|
|
self._book.DeleteAllPages()
|
|
self._book.AddPage(self.CreateMenusPage(), _("Menus"), True)
|
|
self._book.AddPage(self.CreateOptionsPage(), _("Options"), False)
|
|
|
|
|
|
def CloseDialog(self):
|
|
""" Closes the dialog. """
|
|
|
|
self.EndModal(wx.ID_OK)
|
|
|
|
|
|
def ConnectEvents(self):
|
|
""" Does nothing at the moment. """
|
|
|
|
pass
|
|
|
|
|
|
def CreateMenusPage(self):
|
|
""" Creates the :class:`~lib.agw.labelbook.LabelBook` pages with :class:`~lib.agw.flatmenu.FlatMenu` information. """
|
|
|
|
menus = wx.Panel(self._book, wx.ID_ANY, wx.DefaultPosition, wx.Size(300, 300))
|
|
sz = wx.BoxSizer(wx.VERTICAL)
|
|
menus.SetSizer(sz)
|
|
|
|
choices = []
|
|
|
|
mb = self.GetParent()
|
|
|
|
if not self.created:
|
|
self.order = []
|
|
|
|
# Add all the menu items that are currently visible to the list
|
|
for i in range(len(mb._items)):
|
|
|
|
dummy, lableOnly = ArtManager.Get().GetAccelIndex(mb._items[i].GetTitle())
|
|
choices.append(lableOnly)
|
|
|
|
# Add the menu to the visible menus map
|
|
self._visibleMenus.update({lableOnly: mb._items[i].GetMenu()})
|
|
if not self.created:
|
|
self.order.append(lableOnly)
|
|
|
|
# Add all hidden menus to the menu bar
|
|
|
|
for key in list(self._hiddenMenus.keys()):
|
|
choices.append(key)
|
|
|
|
if self.created:
|
|
visible = OrderedDict()
|
|
hidden = OrderedDict()
|
|
for items in self.order:
|
|
if items in self._visibleMenus:
|
|
visible[items] = self._visibleMenus[items]
|
|
elif items in self._hiddenMenus:
|
|
hidden[items] = self._hiddenMenus[items]
|
|
|
|
self._visibleMenus = visible
|
|
self._hiddenMenus = hidden
|
|
|
|
self._menuListId = wx.NewId()
|
|
self._checkListMenus = wx.CheckListBox(menus, self._menuListId, pos=wx.DefaultPosition, size=wx.Size(250, 250),
|
|
choices=self.order, style=wx.BORDER_SIMPLE)
|
|
self._checkListMenus.Bind(wx.EVT_CHECKLISTBOX, self.OnMenuChecked)
|
|
|
|
# check all visible items
|
|
for indx, item in enumerate(self.order):
|
|
if item in self._visibleMenus:
|
|
self._checkListMenus.Check(indx)
|
|
|
|
# Add title panel
|
|
title = FMTitlePanel(menus, _("Select Menu To Add/Remove:"))
|
|
sz.Add(title, 0, wx.EXPAND | wx.ALL, 2)
|
|
sz.Add(self._checkListMenus, 1, wx.EXPAND | wx.TOP | wx.RIGHT | wx.LEFT, 2)
|
|
|
|
self.created = True
|
|
|
|
return menus
|
|
|
|
|
|
def CreateShortcutsPage(self):
|
|
""" Creates the :class:`~lib.agw.labelbook.LabelBook` shorcuts page. """
|
|
|
|
shorcuts = wx.Panel(self._book, wx.ID_ANY, wx.DefaultPosition, wx.Size(300, 300))
|
|
return shorcuts
|
|
|
|
|
|
def CreateOptionsPage(self):
|
|
"""
|
|
Creates the :class:`~lib.agw.labelbook.LabelBook` option page which holds the
|
|
:class:`~lib.agw.flatmenu.FlatMenu` styles.
|
|
"""
|
|
|
|
options = wx.Panel(self._book, wx.ID_ANY, wx.DefaultPosition, wx.Size(300, 300))
|
|
|
|
# Create some options here
|
|
vsizer = wx.BoxSizer(wx.VERTICAL)
|
|
options.SetSizer(vsizer)
|
|
|
|
#-----------------------------------------------------------
|
|
# options page layout
|
|
# - Menu Style: Default or 2007 (radio group)
|
|
#
|
|
# - Default Style Settings: (static box)
|
|
# + Draw vertical gradient (check box)
|
|
# + Draw border (check box)
|
|
# + Drop toolbar shadow (check box)
|
|
#
|
|
# - Colour Scheme (static box)
|
|
# + Menu bar background colour (combo button)
|
|
#-----------------------------------------------------------
|
|
|
|
self._menuStyleID = wx.NewId()
|
|
choices = [_("Default Style"), _("Metallic")]
|
|
self._menuStyle = wx.RadioBox(options, self._menuStyleID, _("Menu bar style"),
|
|
wx.DefaultPosition, wx.DefaultSize, choices)
|
|
|
|
# update the selection
|
|
theme = ArtManager.Get().GetMenuTheme()
|
|
|
|
if theme == Style2007:
|
|
self._menuStyle.SetSelection(1)
|
|
else:
|
|
self._menuStyle.SetSelection(0)
|
|
|
|
# connect event to the control
|
|
self._menuStyle.Bind(wx.EVT_RADIOBOX, self.OnChangeStyle)
|
|
|
|
vsizer.Add(self._menuStyle, 0, wx.EXPAND | wx.ALL, 5)
|
|
|
|
self._sbStyle = wx.StaticBoxSizer(wx.StaticBox(options, -1, _("Default style settings")), wx.VERTICAL)
|
|
self._drawVertGradID = wx.NewId()
|
|
self._verticalGradient = wx.CheckBox(options, self._drawVertGradID, _("Draw vertical gradient"))
|
|
self._verticalGradient.Bind(wx.EVT_CHECKBOX, self.OnChangeStyle)
|
|
self._sbStyle.Add(self._verticalGradient, 0, wx.EXPAND | wx.ALL, 3)
|
|
self._verticalGradient.SetValue(ArtManager.Get().GetMBVerticalGradient())
|
|
|
|
self._drawBorderID = wx.NewId()
|
|
self._drawBorder = wx.CheckBox(options, self._drawBorderID, _("Draw border around menu bar"))
|
|
self._drawBorder.Bind(wx.EVT_CHECKBOX, self.OnChangeStyle)
|
|
self._sbStyle.Add(self._drawBorder, 0, wx.EXPAND | wx.ALL, 3)
|
|
self._drawBorder.SetValue(ArtManager.Get().GetMenuBarBorder())
|
|
|
|
self._shadowUnderTBID = wx.NewId()
|
|
self._shadowUnderTB = wx.CheckBox(options, self._shadowUnderTBID, _("Toolbar float over menu bar"))
|
|
self._shadowUnderTB.Bind(wx.EVT_CHECKBOX, self.OnChangeStyle)
|
|
self._sbStyle.Add(self._shadowUnderTB, 0, wx.EXPAND | wx.ALL, 3)
|
|
self._shadowUnderTB.SetValue(ArtManager.Get().GetRaiseToolbar())
|
|
|
|
vsizer.Add(self._sbStyle, 0, wx.EXPAND | wx.ALL, 5)
|
|
|
|
# Misc
|
|
sb = wx.StaticBoxSizer(wx.StaticBox(options, -1, _("Colour Scheme")), wx.VERTICAL)
|
|
self._colourID = wx.NewId()
|
|
|
|
colourChoices = ArtManager.Get().GetColourSchemes()
|
|
colourChoices.sort()
|
|
|
|
self._colour = wx.ComboBox(options, self._colourID, ArtManager.Get().GetMenuBarColourScheme(), choices=colourChoices,
|
|
style=wx.CB_DROPDOWN | wx.CB_READONLY)
|
|
sb.Add(self._colour, 0, wx.EXPAND)
|
|
vsizer.Add(sb, 0, wx.EXPAND | wx.ALL, 5)
|
|
self._colour.Bind(wx.EVT_COMBOBOX, self.OnChangeStyle)
|
|
|
|
# update the dialog by sending all possible events to us
|
|
event = wx.CommandEvent(wx.wxEVT_COMMAND_RADIOBOX_SELECTED, self._menuStyleID)
|
|
event.SetEventObject(self)
|
|
event.SetInt(self._menuStyle.GetSelection())
|
|
self._menuStyle.ProcessEvent(event)
|
|
|
|
event.SetEventType(wx.wxEVT_COMMAND_CHECKBOX_CLICKED)
|
|
event.SetId(self._drawVertGradID)
|
|
event.SetInt(ArtManager.Get().GetMBVerticalGradient())
|
|
self._verticalGradient.ProcessEvent(event)
|
|
|
|
event.SetEventType(wx.wxEVT_COMMAND_CHECKBOX_CLICKED)
|
|
event.SetId(self._shadowUnderTBID)
|
|
event.SetInt(ArtManager.Get().GetRaiseToolbar())
|
|
self._shadowUnderTB.ProcessEvent(event)
|
|
|
|
event.SetEventType(wx.wxEVT_COMMAND_CHECKBOX_CLICKED)
|
|
event.SetId(self._drawBorderID)
|
|
event.SetInt(ArtManager.Get().GetMenuBarBorder())
|
|
self._drawBorder.ProcessEvent(event)
|
|
|
|
event.SetEventType(wx.wxEVT_COMMAND_COMBOBOX_SELECTED)
|
|
event.SetId(self._colourID)
|
|
self._colour.ProcessEvent(event)
|
|
|
|
return options
|
|
|
|
|
|
def OnMenuChecked(self, event):
|
|
"""
|
|
Handles the ``wx.EVT_CHECKBOX`` event for :class:`FMCustomizeDlg`.
|
|
|
|
:param `event`: a :class:`CommandEvent` event to be processed.
|
|
|
|
:note: This method handles the :class:`~lib.agw.flatmenu.FlatMenu` menus visibility.
|
|
"""
|
|
|
|
id = event.GetInt()
|
|
checked = self._checkListMenus.IsChecked(id)
|
|
menuName = self._checkListMenus.GetString(id)
|
|
menu = None
|
|
mb = self.GetParent()
|
|
|
|
if checked:
|
|
|
|
# remove the item from the hidden map
|
|
if menuName in self._hiddenMenus:
|
|
menu = self._hiddenMenus.pop(menuName)
|
|
|
|
# add it to the visible map
|
|
if menu:
|
|
self._visibleMenus.update({menuName: menu})
|
|
|
|
indx = self._checkListMenus.GetItems().index(menuName)
|
|
# update the menubar
|
|
mb.Insert(indx, menu, menu._menuBarFullTitle)
|
|
mb.Refresh()
|
|
|
|
else:
|
|
|
|
# remove the item from the visible items
|
|
if menuName in self._visibleMenus:
|
|
menu = self._visibleMenus.pop(menuName)
|
|
|
|
# add it to the hidden map
|
|
if menu:
|
|
self._hiddenMenus.update({menuName: menu})
|
|
|
|
# update the menubar
|
|
pos = mb.FindMenu(menuName)
|
|
if pos != wx.NOT_FOUND:
|
|
mb.Remove(pos)
|
|
|
|
mb.Refresh()
|
|
|
|
if self.created:
|
|
visible = OrderedDict()
|
|
hidden = OrderedDict()
|
|
for items in self.order:
|
|
if items in self._visibleMenus:
|
|
visible[items] = self._visibleMenus[items]
|
|
elif items in self._hiddenMenus:
|
|
hidden[items] = self._hiddenMenus[items]
|
|
|
|
self._visibleMenus = visible
|
|
self._hiddenMenus = hidden
|
|
|
|
|
|
def OnChangeStyle(self, event):
|
|
"""
|
|
Handles the ``wx.EVT_CHECKBOX`` event for :class:`FMCustomizeDlg`.
|
|
|
|
:param `event`: a :class:`CommandEvent` event to be processed.
|
|
|
|
:note: This method handles the :class:`~lib.agw.flatmenu.FlatMenu` styles.
|
|
"""
|
|
|
|
mb = self.GetParent()
|
|
|
|
if event.GetId() == self._menuStyleID:
|
|
|
|
if event.GetSelection() == 0:
|
|
|
|
# Default style
|
|
ArtManager.Get().SetMenuTheme(StyleXP)
|
|
self._drawBorder.Enable()
|
|
self._verticalGradient.Enable()
|
|
mb.Refresh()
|
|
|
|
else:
|
|
|
|
ArtManager.Get().SetMenuTheme(Style2007)
|
|
self._drawBorder.Enable(False)
|
|
self._verticalGradient.Enable(False)
|
|
mb.Refresh()
|
|
|
|
return
|
|
|
|
if event.GetId() == self._drawBorderID:
|
|
|
|
ArtManager.Get().DrawMenuBarBorder(event.IsChecked())
|
|
mb.Refresh()
|
|
return
|
|
|
|
if event.GetId() == self._drawVertGradID:
|
|
|
|
ArtManager.Get().SetMBVerticalGradient(event.IsChecked())
|
|
mb.Refresh()
|
|
return
|
|
|
|
if event.GetId() == self._colourID:
|
|
|
|
selection = _("Default")
|
|
sel = self._colour.GetSelection()
|
|
if sel != wx.NOT_FOUND:
|
|
# select new colour scheme
|
|
selection = self._colour.GetStringSelection()
|
|
|
|
ArtManager.Get().SetMenuBarColour(selection)
|
|
mb.Refresh()
|
|
return
|
|
|
|
if event.GetId() == self._shadowUnderTBID:
|
|
ArtManager.Get().SetRaiseToolbar(event.IsChecked())
|
|
mb.Refresh()
|
|
return
|
|
|
|
|