Poodletooth-iLand/panda/python/Lib/site-packages/wx/lib/agw/fmcustomizedlg.py
2015-03-06 06:11:40 -06:00

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