commit-gnue
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[gnue] r8208 - in trunk/gnue-designer: images src src/base src/base/tool


From: jcater
Subject: [gnue] r8208 - in trunk/gnue-designer: images src src/base src/base/tools src/forms src/forms/LayoutEditor src/uidrivers/wx src/uidrivers/wx/startup src/uidrivers/wx/uihelpers
Date: Mon, 6 Mar 2006 08:54:03 -0600 (CST)

Author: jcater
Date: 2006-03-06 08:54:02 -0600 (Mon, 06 Mar 2006)
New Revision: 8208

Added:
   trunk/gnue-designer/images/editor_painter-16x16.png
   trunk/gnue-designer/images/editor_py-16x16.png
   trunk/gnue-designer/src/uidrivers/wx/uihelpers/NotebookCtrl.py
Modified:
   trunk/gnue-designer/src/Designer.py
   trunk/gnue-designer/src/base/Instance.py
   trunk/gnue-designer/src/base/MRUManager.py
   trunk/gnue-designer/src/base/ToolBar.py
   trunk/gnue-designer/src/base/ToolBase.py
   trunk/gnue-designer/src/base/tools/TriggerEditor.py
   trunk/gnue-designer/src/forms/Instance.py
   trunk/gnue-designer/src/forms/LayoutEditor/LayoutEditor.py
   trunk/gnue-designer/src/forms/LayoutEditor/WidgetHandler.py
   trunk/gnue-designer/src/uidrivers/wx/Base.py
   trunk/gnue-designer/src/uidrivers/wx/Instance.py
   trunk/gnue-designer/src/uidrivers/wx/startup/Startup.py
   trunk/gnue-designer/src/uidrivers/wx/uihelpers/PyAUI.py
Log:
moved to PyAUI for doc management; misc wx 2.6 fixes

Added: trunk/gnue-designer/images/editor_painter-16x16.png
===================================================================
(Binary files differ)


Property changes on: trunk/gnue-designer/images/editor_painter-16x16.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/gnue-designer/images/editor_py-16x16.png
===================================================================
(Binary files differ)


Property changes on: trunk/gnue-designer/images/editor_py-16x16.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Modified: trunk/gnue-designer/src/Designer.py
===================================================================
--- trunk/gnue-designer/src/Designer.py 2006-03-06 14:25:55 UTC (rev 8207)
+++ trunk/gnue-designer/src/Designer.py 2006-03-06 14:54:02 UTC (rev 8208)
@@ -113,8 +113,9 @@
 
     print "Init'ing"
     # Init the splashscreen
-    self.ui.createStartupSplash()
+#    self.ui.createStartupSplash()
     gStartupStatus(_('Initializing Client Library'))
+    print gStartupStatus
 
     # Load the specified file, a requested new instance, or the default empty 
instance
     if len(self.ARGUMENTS):
@@ -140,7 +141,7 @@
       self.newInstance('forms')
 
     # Close startup screen
-    self.ui.closeStartupSplash()
+#    self.ui.closeStartupSplash()
     return True
 
   def loadModuleInformation(self):
@@ -197,6 +198,8 @@
     ##            + wildcard \
     ##            + "All Files (*.*)|*.*"
       self.supportedOpenWildcard = wildcard + [('*',"All Files")]
+
+
   # ==========================================================================
   # Instance functions
   # ==========================================================================

Modified: trunk/gnue-designer/src/base/Instance.py
===================================================================
--- trunk/gnue-designer/src/base/Instance.py    2006-03-06 14:25:55 UTC (rev 
8207)
+++ trunk/gnue-designer/src/base/Instance.py    2006-03-06 14:54:02 UTC (rev 
8208)
@@ -37,6 +37,7 @@
 from gnue.common.events import EventController, Event
 from gnue.designer.base.MenuBar import MenuBar
 from gnue.designer.base.UndoManager import UndoManager
+from gnue.designer.base.tools.TriggerEditor import TriggerEditor
 from gnue.designer.base.ToolBase import ToolBase
 from gnue.designer.base.ObjectList import ObjectList
 from gnue.designer.base import TemplateBase
@@ -80,6 +81,10 @@
     pass
 
   #
+  def createEditors(self):
+    pass
+
+  #
   def createWizards(self):
     pass
 
@@ -132,6 +137,10 @@
     self._makeBackup = True
     self._isNew = True
 
+    # Create the supplemental tools
+    self._toolCache = []
+    self._editorMapping = {}
+
     self._app = self.base = app
     self.connections = app.connections
     self.nameMappings = {}
@@ -203,19 +212,21 @@
     self.menubar = MenuBar(self)
 
 
-    gStartupStatus(_('Inventorying Document Objects'))
-    self.rootObject.walk(self.__inventory)
-
     gStartupStatus(_('Creating User Interface'))
 
-    # Create the supplemental tools
-    self._toolCache = []
 
     # Set up the menu system
     self._initMenu()
     self.initMenu()
 
     self.createWizards()
+
+    # All tools could support triggers
+    self.registerEditor('triggerEditor',  _('Trigger Editor'), TriggerEditor,
+                      'GCTrigger')
+    # Let the instances register their own editors
+    self.createEditors()
+
     self.createTools()
     self.uiinstance.initTools()
 
@@ -232,6 +243,7 @@
                    'RequestPaste','RequestPasteSpecial','RequestCut'):
       self.dispatchEvent('Disable:%s' % action)
 
+
     # Add ourselve to the main app's instance list
     self._app.addInstance(self)
 
@@ -239,6 +251,11 @@
     self.dispatchEvent('ObjectSelected', originator=self,
                        object=self.rootObject)
 
+    # Inventory the objects
+    gStartupStatus(_('Inventorying Document Objects'))
+    self.rootObject.walk(self.__inventory)
+
+
     self.uiinstance.finalize()
 
     self.stopCachingEvents()
@@ -300,6 +317,11 @@
     self._toolCache.append( (id, title, baseclass, hotkey, menuGroup) )
 
 
+  def registerEditor(self, id, title, baseclass, gtype):
+    self._editorMapping[gtype] = (id, title, baseclass)
+
+
+
   # Return, or create, an ObjectList based on the xml tag
   def getObjectList(self, tag):
     try:
@@ -366,13 +388,19 @@
     self._isNew = True
 
 
+  #--------------------------------------------------------------------------
   #
+  #--------------------------------------------------------------------------
+  #
   #  Used by RuntimeSettings
   #
   def saveRuntimeSettings(self):
     return ( self.runtime_section, self.uiinstance.getRuntimeSettings() )
 
 
+  #--------------------------------------------------------------------------
+  #
+  #--------------------------------------------------------------------------
   # Do we need to be saved?
   def isDirty(self):
     return self._isdirty
@@ -398,6 +426,9 @@
     self.dispatchEvent('MakeClean')
 
 
+  #--------------------------------------------------------------------------
+  #
+  #--------------------------------------------------------------------------
   # Take an object and mangle it all up
   # until it is useful to us
   def __inventory (self, object):
@@ -415,6 +446,11 @@
         self.nameMappings[string.lower(object.name)] = object
         self.usedNames.append(object.name.lower())
 
+    # Do we create an EditorComponent instance?
+    print ' >> ' + object._type
+    if object._type in self._editorMapping.keys():
+      self.uiinstance.createEditor(object, *self._editorMapping[object._type])
+
     # Now, give the tool-specific instances a chance
     self.inventoryObject(object)
 
@@ -456,6 +492,9 @@
     self.makeDirty()
 
 
+  #--------------------------------------------------------------------------
+  #
+  #--------------------------------------------------------------------------
   def getNextGenericName (self, type):
     return self.getUniqueName(type.capitalize() + '1')
 
@@ -528,6 +567,8 @@
       if comment.find(TITLE) > 0:
         self.rootObject._rootComments.remove(comment)
 
+    # Place a timestamp in the XML as a comment
+    # TODO: Replace with Dublin Core?
     fileHandle.write('<!--  %s (%s)\n%s      Saved on: %s  -->\n\n' \
        % (TITLE, VERSION, (len(self.wizardName) and ("      Created by " + 
self.wizardName + "\n") or ""),\
           time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(time.time()))))
@@ -553,6 +594,9 @@
       print _("Unable to connect to %s") % conn
 
 
+  #--------------------------------------------------------------------------
+  #
+  #--------------------------------------------------------------------------
   def OnSave(self, event):
     if not len(self._path):
       self.OnSaveAs(event)
@@ -616,10 +660,9 @@
     self.uiinstance.close()
 
 
-  #################################################################
+  #--------------------------------------------------------------------------
   #
-  #################################################################
-
+  #--------------------------------------------------------------------------
   def loadWizards(self, package):
     templates = []
 
@@ -663,7 +706,9 @@
       except ValueError:
         continue
 
-#
+# ===========================================================================
+# Wrapper Class
+# ===========================================================================
 class GObjectHelper:
   def __init__(self, instance, object):
     self.instance = instance
@@ -689,9 +734,9 @@
   def setStatus(self, text):
     self.uiinstance.setStatus(text)
 
-#
+# ===========================================================================
 # Helper class used by the tool-specific packages
-#
+# ===========================================================================
 class ModuleProperties:
   xmlOpeningTag = 'undefined'
   short = 'undefined'

Modified: trunk/gnue-designer/src/base/MRUManager.py
===================================================================
--- trunk/gnue-designer/src/base/MRUManager.py  2006-03-06 14:25:55 UTC (rev 
8207)
+++ trunk/gnue-designer/src/base/MRUManager.py  2006-03-06 14:54:02 UTC (rev 
8208)
@@ -29,7 +29,7 @@
 
 import os
 from gnue.common.apps import RuntimeSettings
-from wxPython import wx
+import wx
 
 class MRUManager:
   """
@@ -151,7 +151,7 @@
     # Rebuild the menu with the current items.
     i = 0
     for location in self.menulist:
-      tid = wx.wx.NewId()
+      tid = wx.NewId()
       menu.Append ( tid, '&%s %s' % (i+1, location),
                     _('Open "%s" in a new window') % self._locations[i] )
 

Modified: trunk/gnue-designer/src/base/ToolBar.py
===================================================================
--- trunk/gnue-designer/src/base/ToolBar.py     2006-03-06 14:25:55 UTC (rev 
8207)
+++ trunk/gnue-designer/src/base/ToolBar.py     2006-03-06 14:54:02 UTC (rev 
8208)
@@ -34,7 +34,10 @@
 iconlocation = 
os.path.join(GConfig.getInstalledBase('designer_images','common_images') 
,'designer')
 
 def getIcon(name, w, h):
-  return wx.Image(os.path.join(iconlocation,"%s-%sx%s.png" % (name,w, h)),
+  path = os.path.join(iconlocation,"%s-%sx%s.png" % (name,w, h))
+  if not os.path.exists(path):
+    return None
+  return wx.Image(path,
                   wx.BITMAP_TYPE_PNG).ConvertToBitmap()
 
 class BaseToolBar(wx.ToolBar, EventAware):

Modified: trunk/gnue-designer/src/base/ToolBase.py
===================================================================
--- trunk/gnue-designer/src/base/ToolBase.py    2006-03-06 14:25:55 UTC (rev 
8207)
+++ trunk/gnue-designer/src/base/ToolBase.py    2006-03-06 14:54:02 UTC (rev 
8208)
@@ -27,13 +27,16 @@
 # NOTES:
 #
 
-__all__ = ['ToolBase']
+__all__ = ['ToolBase', 'EditorComponent']
 
 import wx
 from gnue.common.apps import RuntimeSettings
 from gnue.common import events
 
 
+# ===========================================================================
+#
+# ===========================================================================
 class ToolBase (wx.Panel, events.EventAware):
 
   default_visible = 1
@@ -62,9 +65,9 @@
   def saveRuntimeSettings(self):
     return (self.runtime_section, {})
 
-#  def setFeedback(self, text):
+  def setFeedback(self, text):
     print "TODO: setFeedback"
-    self.dockpane.setFeedback(text)
+#    self.dockpane.setFeedback(text)
 
   def __show(self, event):
     self._visible = True
@@ -76,3 +79,43 @@
 #    self.dockpane.hide()
 
 
+# ===========================================================================
+#
+# ===========================================================================
+class EditorComponent(wx.Panel, events.EventAware):
+  """
+  An "Editor Component" is presented usually as an editor to the user
+  and is considered a "primary window".
+  """
+  default_dock = 'primary'
+  icon = 'painter'
+
+  def __init__(self, object, id, title, instance, rootObject, parentWindow):
+    wx.Panel.__init__(self, parentWindow, -1)
+    events.EventAware.__init__(self, instance)
+
+    self.id = id
+    self.title = title
+    self.instance = instance
+    self.rootObject = rootObject
+    self.instance.globalAcceleratorListeners.append(self)
+
+    self.init(object)
+
+    RuntimeSettings.registerRuntimeSettingHandler(self.instance, self)
+
+  def saveRuntimeSettings(self):
+    return (self.runtime_section, {})
+
+  def setFeedback(self, text):
+    print "TODO: setFeedback"
+
+  def setCaption(self, caption):
+    self._caption = caption
+    # TODO: tell the ui instance to update, if necessary
+
+  def destroy(self):
+    self.Destroy()
+
+  def setFeedback(self, text):
+    print "TODO: setFeedback"

Modified: trunk/gnue-designer/src/base/tools/TriggerEditor.py
===================================================================
--- trunk/gnue-designer/src/base/tools/TriggerEditor.py 2006-03-06 14:25:55 UTC 
(rev 8207)
+++ trunk/gnue-designer/src/base/tools/TriggerEditor.py 2006-03-06 14:54:02 UTC 
(rev 8208)
@@ -37,218 +37,80 @@
 EVENT_TRIGGER = 0
 
 
-class TriggerEditor (ToolBase):
+# ===========================================================================
+#
+# ===========================================================================
+class TriggerEditor (EditorComponent):
 
   runtime_section = "TriggerEditor"
-  default_width  = int(wx.SystemSettings_GetMetric( wx.SYS_SCREEN_X )/3)
-  default_height = int(wx.SystemSettings_GetMetric( wx.SYS_SCREEN_Y )/3)
-  default_dock = 'right-2'
+  icon = 'py'
 
-  def init(self):
+  def init(self, object):
 
     self.editor = PythonEditorControl(self,-1, pos=wx.Point(0,32))
-    self.editor.InEditMode = 0
+    self.editor.InEditMode = True
 
+    box = wx.BoxSizer(wx.VERTICAL)
+    box.Add(self.editor, 2, wx.EXPAND)
 
-#    self.SetSize(self.frame.GetClientSize())
-#    self.editor.SetSize(self.GetClientSize())
-    self.object = None
+    self.SetAutoLayout(True)
+    self.SetSizer(box)
+    self.Layout()
 
+    self.object = object
+
     self.triggerList = []
     self.triggerMap = {}
 
-
-    self.editor.SetReadOnly(1)
-    wx.EVT_SIZE(self, self._onSize)
+    self.editor.SetReadOnly(False)
     wx.EVT_KILL_FOCUS(self.editor, self.OnKillFocus)
     self.__ignoreevent = 0
 
     self.mode = NAMED_TRIGGER
 
-    self.toolpanel = wx.Panel(self, -1, pos=wx.Point(0,0), 
size=wx.Size(32,32), style=wx.RAISED_BORDER|wx.CLIP_CHILDREN)
+    self.__ignoreevent = 0
 
-    self.namedNameLabel = wx.StaticText(self.toolpanel, -1, _("Trigger: "), 
pos=wx.Point(4,6))
-    self.triggerCombo = wx.ComboBox(self.toolpanel, -1,  choices=['This is to 
make the combo box big 
enough'],pos=wx.Point(self.namedNameLabel.GetSize().width + 10,4), 
style=wx.CB_READONLY)
-    self.toolh = max(self.namedNameLabel.GetSizeTuple()[1], 
self.triggerCombo.GetSizeTuple()[1]) + 12
-    self.triggerCombo.Clear()
-    self.triggerCombo.Append('')
-    self.editor.SetPosition((0, self.toolh))
+    self.object = object
+    self.editor.SetReadOnly(0)
 
-    wx.EVT_COMBOBOX(self, self.triggerCombo.GetId(), self.OnTriggerSelected)
+    if not len(object._children):
+      GParserHelpers.GContent(object, "")
+    elif len(object._children) > 1:
+      content = object.getChildrenAsContent()
+      object._children = []
+      GParserHelpers.GContent(object, content)
 
+    self.editor.InEditMode = 0
+    self.editor.SetText(object.getChildrenAsContent())
+    self.editor.EmptyUndoBuffer()
+    self.editor.Colourise(0, -1)
 
-    # EventAware provided by ToolBase
-    self.registerEventListeners({
-                       'ObjectSelected'      : self.onSetCurrentObject,
-                       'TriggerSelected'     : self.onSetCurrentObject,
-                       'ObjectCreated'       : self.onCreateObject,
-                       'ObjectModified'      : self.onModifyObject,
-                       'ObjectDeleted'       : self.onDeleteObject,
-                      })
+    self.setCaption(self._generateName(object))
 
-    self.rootObject.walk(self.inventoryObject)
-#    if self.object:
-#      self._setObject(object)
 
-
-  def OnTriggerSelected(self, event):
-    s= event.GetSelection()
-    if s:
-      trigger = self.triggerMap[self.triggerList[s-1]]
-      wx.CallAfter(self.dispatchEvent,'TriggerSelected',
-                       object = trigger,
-                       originator = None)
-      if trigger.type.upper() != 'NAMED':
-        wx.CallAfter(self.dispatchEvent,'ObjectSelected',
-                           object = trigger.getParent (),
-                           originator = None)
-
-      self.editor.SetReadOnly(0)
-    else:
-      self.editor.InEditMode = 0
-      self.editor.SetText("")
-      self.editor.EmptyUndoBuffer()
-      self.editor.InEditMode = 1
-      self.editor.SetReadOnly(1)
-      self.object = None
-    event.Skip()
-
-
-  def _onSize(self, event):
-    w,h = self.GetClientSizeTuple()
-    self.toolpanel.SetSize(wx.Size(w,self.toolh))
-    self.editor.SetSize(wx.Size(w,h-self.toolh+1))
-
-
-  def onSetCurrentObject (self, event):
-    object = event.object
-    handler = event.originator
-    if object == None:
-      return
-
-    if isinstance(object, GTrigger.GTrigger) and not object.src:
-      self._setObject(object)
-
-
-  def _setObject(self, object):
-      self.__ignoreevent = 0
-
-      self.object = object
-      self.editor.SetReadOnly(0)
-
-      if not len(object._children):
-        GParserHelpers.GContent(object, "")
-      elif len(object._children) > 1:
-        content = object.getChildrenAsContent()
-        object._children = []
-        GParserHelpers.GContent(object, content)
-
-      self.editor.InEditMode = 0
-      self.editor.SetText(object.getChildrenAsContent())
-      self.editor.EmptyUndoBuffer()
-      self.editor.Colourise(0, -1)
-      self.editor.InEditMode = 1
-
-      i = self.triggerList.index(self._generateName(object)) + 1
-      self.triggerCombo.SetSelection(i)
-
-  def refillTriggerCombo(self):
-    i = self.triggerCombo.GetSelection()
-    if i>0:
-      cur = self.triggerList[i-1]
-    else:
-      cur = None
-    nt = []
-    ct = []
-
-    for key, trigger in self.triggerMap.items():
-      if trigger.type.upper() == 'NAMED':
-        nt.append(key)
-      else:
-        ct.append(key)
-
-    nt.sort()
-    ct.sort()
-
-    self.triggerList = nt + ct
-
-    self.triggerCombo.Clear()
-    self.triggerCombo.Append('')
-    for i in range(0, len(self.triggerList)):
-      self.triggerCombo.Append(self.triggerList[i])
-
-    try:
-      i = self.triggerList.index(cur) + 1
-    except:
-      i = 0
-
-
-    self.triggerCombo.SetSelection(i)
-    try:
-      self._setObject(self.triggerMap[self.triggerList[i - 1]])
-    except KeyError:
-      pass
-
-    self.Refresh()
-
   def _generateName(self, trigger):
     if trigger.type.upper() == 'NAMED':
       return trigger.name
     else:
       parent = trigger.getParent ()
-      name = '%s.%s' % (parent.name, 
parent._validTriggers[trigger.type.upper()])
+      #name = '%s.%s' % (parent.name, 
parent._validTriggers[trigger.type.upper()])
+      name = '%s.%s' % (parent.name, trigger.type)
       try:
         name = parent.getParent ().name + '.' + name
       except:
         pass
       return '('+name+')'
 
-
-
-  def inventoryObject(self, object):
-    if isinstance(object, GTrigger.GTrigger):
-      if not object.src:
-        self.triggerMap[self._generateName(object)] = object
-        self.refillTriggerCombo()
-
   def OnKillFocus(self, event):
     # TODO: We might be able to ditch this now since it's done in onChange
     if self.object != None and not self.__ignoreevent:
       self.object._children[0]._content = self.editor.GetText()
 
-  def onCreateObject (self, event):
-    object = event.object
-    handler = event.originator
-    if object == None:
-      return
 
-    self.inventoryObject(object)
-
-  def onModifyObject (self, event):
-    object = event.object
-    handler = event.originator
-
-    if object == None:
-      return
-    if handler != __name__:
-
-      if isinstance(object, GTrigger.GTrigger):
-        if object.type == 'NAMED':
-          self.refillTriggerCombo()
-
-
-  def onDeleteObject (self, event):
-    object = event.object
-    handler = event.originator
-    if object == None:
-      return
-
-    if isinstance(object, GTrigger.GTrigger) and not object.src:
-      del self.triggerMap[self._generateName(object)]
-      self.refillTriggerCombo()
-
-
-
+# ===========================================================================
+# Scintilla control for python source code
+# ===========================================================================
+# TODO: Add support for our JavaScript triggers
 class PythonEditorControl(PythonSTC):
   def __init__(self, parent, *args, **parms):
     PythonSTC.__init__(self, parent, *args, **parms)
@@ -269,5 +131,3 @@
     self.SetReadOnly(bool)
 
 
-
-

Modified: trunk/gnue-designer/src/forms/Instance.py
===================================================================
--- trunk/gnue-designer/src/forms/Instance.py   2006-03-06 14:25:55 UTC (rev 
8207)
+++ trunk/gnue-designer/src/forms/Instance.py   2006-03-06 14:54:02 UTC (rev 
8208)
@@ -42,7 +42,6 @@
 from PropertyEditor import PropertyEditor
 from EventEditor import EventEditor
 from BlockEditor import BlockEditor
-from gnue.designer.base.tools.TriggerEditor import TriggerEditor
 from gnue.designer.base.tools.DataSourceEditor import DataSourceEditor
 ##from gnue.designer.base.tools.SchemaViewer import SchemaViewer
 from gnue.designer.base.tools.SchemaNavigator import SchemaNavigator
@@ -58,13 +57,13 @@
 
 class Instance(BaseInstance, GFInstance.GFInstance):
   """
-  Designer's form editor instance.  
+  Designer's form editor instance.
   """
   def __init__(self, app, *args, **params):
 
     self.incubator = Incubator(self) # Incubator
     self.properties = formProperties # List of the modules properties
-    self.wizardRunner = WizardRunner # 
+    self.wizardRunner = WizardRunner #
     self.debugLevel = '1'            # The debug level used when running a form
                                      # inside designer
 
@@ -197,9 +196,12 @@
     object._popupMenu = ObjectMenu(self, object)
 
 
+  def createEditors(self):
+    self.registerEditor('visualEditor',   _('Layout Editor'), LayoutEditor,
+                      'GFPage')
+
+
   def createTools(self):
-    self.addTool('visualEditor',   _('Layout Editor'), LayoutEditor,
-                      hotkey='F11', menuGroup=301)
     self.addTool('propertyEditor', _('Property Inspector'), PropertyEditor,
                       hotkey='F10', menuGroup=301)
     self.addTool('treeEditor',     _('Object Navigator'), TreeView,
@@ -207,17 +209,14 @@
 
     self.addTool('schemaNavigator',_('Schema Navigator'), SchemaNavigator,
                       menuGroup=301)
-    self.addTool('datasourceEditor',_('Data Source Editor'), DataSourceEditor,
-                      hotkey='F9', menuGroup=311)
-    self.addTool('blockEditor',   _('Block Editor'), BlockEditor,
-                      hotkey='F5', menuGroup=311)
+    #self.addTool('datasourceEditor',_('Data Source Editor'), DataSourceEditor,
+    #                  hotkey='F9', menuGroup=311)
+    #self.addTool('blockEditor',   _('Block Editor'), BlockEditor,
+    #                  hotkey='F5', menuGroup=311)
     #self.addTool('fieldEditor',   _('Field Editor'), FieldEditor,
     #                  hotkey='F6', menuGroup=201)
-
     self.addTool('eventEditor',    _('Trigger Mappings'), EventEditor,
                       hotkey='F7', menuGroup=321)
-    self.addTool('triggerEditor',  _('Trigger Editor'), TriggerEditor,
-                      hotkey='F12', menuGroup=321)
 
   def createWizards(self):
     self.loadWizards(wizards)

Modified: trunk/gnue-designer/src/forms/LayoutEditor/LayoutEditor.py
===================================================================
--- trunk/gnue-designer/src/forms/LayoutEditor/LayoutEditor.py  2006-03-06 
14:25:55 UTC (rev 8207)
+++ trunk/gnue-designer/src/forms/LayoutEditor/LayoutEditor.py  2006-03-06 
14:54:02 UTC (rev 8208)
@@ -30,16 +30,19 @@
 
 __all__ = ['LayoutEditor']
 
+# System imports
 import sys, os
 import wx
+
+# GNUe imports
 from gnue.common.apps import GDebug
+from gnue.common.events import Event
 from gnue.forms import GFObjects
 from gnue.forms.uidrivers.wx import UIdriver as UIwxpython
 from gnue.forms.uidrivers.wx.common import wxEncode
 from gnue.designer.base.PopupMenu import PageMenu
 from gnue.designer.base.TemplateParser import TemplateParser
-from gnue.designer.base.ToolBase import *
-from gnue.common.events import Event
+from gnue.designer.base.ToolBase import EditorComponent
 
 # My support files
 from Utils import *
@@ -51,34 +54,45 @@
 
 from renderers.Base.GridPane import GridPane
 
-class LayoutEditor (ToolBase):
 
+class LayoutEditor (EditorComponent):
+
   runtime_section = "FormsLayoutEditor"
-  default_dock = 'right-0'
+
+  # TODO: Probably won't need these anymore...
   uses_feedback_bar = 1
   uses_toolbar = 1
 
 
-  def init(self):
+  def init(self, object):
 
     # TODO: blah.... historical reasons
     self._instance = self.instance
 
     self._app = self.instance._app
 
-    self.page = None
+    self.page = object
     self.block = None
     self.lastBlock = None
     self.blockMap = {}
     self.panel = None
-    self._notebookMap = {}
+
     self.positionMappings = {}
     self.widgetList = []
     self._currentSelection = []
 
+    self.setCaption(hasattr(object,'name') and \
+              object['name'] or object['id'])
+
     # Create our own WX GFUserInterface instance
-    self.uidriver = uidriver = UIwxpython.GFUserInterface(self.instance, 0)
+    # TODO: This should be moved into GFInstance...
+    # TODO: here for historical reasons.
+    try:
+      self.uidriver = uidriver = self.instance.__uidriver
+    except AttributeError:
+      self.instance.__uidriver = self.uidriver = uidriver = 
UIwxpython.GFUserInterface(self.instance, 0)
 
+
     # Create a list of all UI widgets
     self.widgets = {}
     self.widgets.update(uidriver._supportedWidgets)
@@ -88,10 +102,9 @@
     del self.widgets['GFPage']
 
 
-    self.notebook = wx.Notebook(self, -1, pos=wx.Point(4, 4), 
size=wx.Size(32,32))
     self.backcolor = wx.WHITE
 
-    wx.EVT_RIGHT_DOWN(self.notebook, self.onRightDown)
+    wx.EVT_RIGHT_DOWN(self, self.onRightDown)
     wx.EVT_SIZE(self, self.OnSize)
 
     self._currentObject = None
@@ -123,19 +136,25 @@
                        'EndWizard': self.endWizard,
                       })
 
-    self.instance.rootObject.walk (self.inventoryObject)
-
-    # don't put this before walk on win32...
-    wx.EVT_NOTEBOOK_PAGE_CHANGED(self,self.notebook.GetId(), 
self.OnPageSelected)
-    try:
-      self._setCurrentPage(self._notebookMap[0])
-    except KeyError:
-      pass
+    self.instance.rootObject.walk (self.inventoryObject)
 
     ## Stuff needed by UIwxpython
     self._pageList = []  # Needed by UIwxpython
 
 
+    self.workspacescroll = wx.ScrolledWindow(self, -1,
+        pos=wx.Point(0,0),
+        style=wx.CLIP_CHILDREN|wx.HSCROLL|wx.VSCROLL|wx.SUNKEN_BORDER)
+
+    self.workspace = wx.Panel(self.workspacescroll,-1)
+    self.workspace.SetBackgroundColour(self.backcolor)
+
+    # TODO: historical reasons
+    object.__workspace = self.workspace
+
+    self.drawPage(object)
+
+
   def createToolbar(self, parent):
     self.toolbar = LayoutEditorTools(parent, self.instance)
     self.blockCombo = self.toolbar.blockCombo
@@ -154,24 +173,6 @@
 
 
   def inventoryObject(self, object):
-    if object._type == 'GFPage':
-      index = self.notebook.GetPageCount()
-      self._notebookMap[object] = index
-      self._notebookMap[index] = object
-
-      self.workspacescroll = wx.ScrolledWindow(self.notebook, -1,
-         pos=wx.Point(0,0),
-         style=wx.CLIP_CHILDREN|wx.HSCROLL|wx.VSCROLL|wx.SUNKEN_BORDER)
-
-      self.workspace = wx.Panel(self.workspacescroll,-1)
-      self.workspace.SetBackgroundColour(self.backcolor)
-
-      self.notebook.AddPage(self.workspacescroll, wxEncode(object.name))
-      # don't put this before AddPage on win32...
-      wx.EVT_SIZE(self.workspacescroll, self.__OnGridSize)
-
-      object.__workspace = self.workspace
-      self.drawPage(object)
     if object._type == 'GFBlock':
       self.blockMap[object.name.lower()] = object
       if not self.block:
@@ -188,8 +189,6 @@
 
     self._currentObject = object
 
-    if handler != "Forms::LayoutEditor":
-      self._setCurrentPage(object)
     self._setFeedback()
     self._setCurrentBlock(object)
     self._setSelection(object, selection)
@@ -260,27 +259,7 @@
      self.setFeedback(ft)
 
 
-  def _setCurrentPage(self, object):
-    if not object:
-      return
-    page = isinstance(object, GFObjects.GFPage) and object or \
-           object.findParentOfType('GFPage')
 
-    if page != None and page != self.page:
-      self.page = page
-
-      self.notebook.SetSelection(self._notebookMap[page])
-      try:
-        self.workspace = page.__workspace
-        self.panel = self.page.__panel
-        UIwxpython.setPointSize(self.page.__pointSize)
-        self.calcGridSpacing()
-      except AttributeError:
-        # This simply means we are setting up
-        # our notebook for the first time.
-        pass
-
-
   def _setSelection(self, focus, objects):
 
     # Unhighlight any previously selected items
@@ -313,12 +292,10 @@
 
       if object._type != 'GFPage':
         page = object.findParentOfType('GFPage')
-        if page:
-          self._setCurrentPage(page)
+        if page == self.page:
           self.__drawItem(object)
 
       self.inventoryObject(object)
-      self._setCurrentPage(origpage)
     if object._type == 'GFBlock':
       self.blockMap[object.name.lower()] = object
       self._rebuildBlockCombo()
@@ -342,15 +319,6 @@
 
 ##    self.propBar.onModifyObject(object, event)
 
-    if handler != "Forms::LayoutEditor":
-      if object._type == 'GFPage':
-        self.notebook.SetPageText(self._notebookMap[object],object.name)
-        self.notebook.SetSelection(self.notebook.GetSelection())
-      else:
-        page = object.findParentOfType('GFPage')
-        if page:
-          self._setCurrentPage(page)
-
       if object in (self.rootObject, self.page, self.rootObject._layout):
         self.refreshPage(self.page)
       elif object in self.widgetList:
@@ -371,15 +339,6 @@
 
     self._currentObject = None
 
-    if 1: ## handler != "Forms::LayoutEditor":
-      if object._type == 'GFPage':
-        index = self._notebookMap[object]
-        for i in range(index+1, len(self._notebookMap.keys())/2):
-          self._notebookMap[i-1] = self._notebookMap[i]
-        del self._notebookMap[int(len(self._notebookMap.keys())/2)-1]
-        del self._notebookMap[object]
-        self.notebook.DeletePage(index)
-
     if hasattr(object, '_widgetHandler') and object._widgetHandler != None:
       if object in self._currentSelection:
         object._widgetHandler.setSelected(0)
@@ -518,15 +477,8 @@
     object._widgetHandler.setSelected(1)
 
   def OnSize(self, event):
-    self.notebook.SetSize(wx.Size(self.GetClientSize().x-8, 
self.GetClientSize().y - 8))
+    self.workspacescroll.SetSize(wx.Size(self.GetClientSize().x-8, 
self.GetClientSize().y - 8))
 
-  def OnPageSelected(self, event):
-    p = self._notebookMap[event.GetSelection()]
-    if p != self.page:
-      self.dispatchEvent('ObjectSelected', object=p, 
originator="Forms::LayoutEditor")
-    self._setCurrentPage(p)
-    self.__OnGridSize(None)
-
   def OnLeftDown(self, event):
     x, y = event.GetPositionTuple()
     self.handleLeftDown(x,y)

Modified: trunk/gnue-designer/src/forms/LayoutEditor/WidgetHandler.py
===================================================================
--- trunk/gnue-designer/src/forms/LayoutEditor/WidgetHandler.py 2006-03-06 
14:25:55 UTC (rev 8207)
+++ trunk/gnue-designer/src/forms/LayoutEditor/WidgetHandler.py 2006-03-06 
14:54:02 UTC (rev 8208)
@@ -69,22 +69,22 @@
       except:
         pass
 
-      self.setAllChildren(EVT_KEY_UP, widget, self.editor.keyTrap)
-      self.setAllChildren(EVT_SET_FOCUS, widget, self.focusGainedTrap)
-      self.setAllChildren(EVT_KILL_FOCUS, widget, self.focusLostTrap)
-      self.setAllChildren(EVT_LEFT_UP, widget, self.OnLeftUp)
-      self.setAllChildren(EVT_LEFT_DOWN, widget, self.OnLeftDown)
-      self.setAllChildren(EVT_RIGHT_DOWN, widget, self.OnRightDown)
-      self.setAllChildren(EVT_RIGHT_UP, widget, self.OnRightUp)
-      self.setAllChildren(EVT_MOTION, widget, self.OnMotion)
-      self.setAllChildren(EVT_LEFT_DCLICK, widget, self.onLeftDClick)
-    self.setAllChildren(EVT_KEY_UP, self.highlightBox, self.editor.keyTrap)
-    self.setAllChildren(EVT_SET_FOCUS, self.highlightBox, self.focusGainedTrap)
-    self.setAllChildren(EVT_KILL_FOCUS, self.highlightBox, self.focusLostTrap)
-    self.setAllChildren(EVT_LEFT_UP, self.highlightBox, self.OnLeftUp)
-    self.setAllChildren(EVT_LEFT_DOWN, self.highlightBox, self.OnLeftDown)
-    self.setAllChildren(EVT_RIGHT_UP, self.highlightBox, self.OnRightUp)
-    self.setAllChildren(EVT_MOTION, self.highlightBox, self.OnMotion)
+      self.setAllChildren(wx.EVT_KEY_UP, widget, self.editor.keyTrap)
+      self.setAllChildren(wx.EVT_SET_FOCUS, widget, self.focusGainedTrap)
+      self.setAllChildren(wx.EVT_KILL_FOCUS, widget, self.focusLostTrap)
+      self.setAllChildren(wx.EVT_LEFT_UP, widget, self.OnLeftUp)
+      self.setAllChildren(wx.EVT_LEFT_DOWN, widget, self.OnLeftDown)
+      self.setAllChildren(wx.EVT_RIGHT_DOWN, widget, self.OnRightDown)
+      self.setAllChildren(wx.EVT_RIGHT_UP, widget, self.OnRightUp)
+      self.setAllChildren(wx.EVT_MOTION, widget, self.OnMotion)
+      self.setAllChildren(wx.EVT_LEFT_DCLICK, widget, self.onLeftDClick)
+    self.setAllChildren(wx.EVT_KEY_UP, self.highlightBox, self.editor.keyTrap)
+    self.setAllChildren(wx.EVT_SET_FOCUS, self.highlightBox, 
self.focusGainedTrap)
+    self.setAllChildren(wx.EVT_KILL_FOCUS, self.highlightBox, 
self.focusLostTrap)
+    self.setAllChildren(wx.EVT_LEFT_UP, self.highlightBox, self.OnLeftUp)
+    self.setAllChildren(wx.EVT_LEFT_DOWN, self.highlightBox, self.OnLeftDown)
+    self.setAllChildren(wx.EVT_RIGHT_UP, self.highlightBox, self.OnRightUp)
+    self.setAllChildren(wx.EVT_MOTION, self.highlightBox, self.OnMotion)
 
     self.widget.Refresh()
 
@@ -292,7 +292,7 @@
 
     try:
       self.object.Char__height
-    except: 
+    except:
       self.object.Char__height = 1
 
     if (self.object.Char__width + dx < 0 or self.object.Char__height + dy < 0):

Modified: trunk/gnue-designer/src/uidrivers/wx/Base.py
===================================================================
--- trunk/gnue-designer/src/uidrivers/wx/Base.py        2006-03-06 14:25:55 UTC 
(rev 8207)
+++ trunk/gnue-designer/src/uidrivers/wx/Base.py        2006-03-06 14:54:02 UTC 
(rev 8208)
@@ -28,44 +28,53 @@
 # NOTES:
 #
 
+# ---------------------------------------------------------------------------
+# Python Imports
+# ---------------------------------------------------------------------------
+import sys, os, string
+
+
+# ---------------------------------------------------------------------------
+# wx Imports
+# ---------------------------------------------------------------------------
 try:
   import wxselect
   wxselect.wx.VersionFinder.setpath(version="2.6")
 except ImportError:
   pass
 
-import sys, os, string
-
-
 try:
   import wx
-  if wx.__version__ < '2.6.1': 
+  if wx.__version__ < '2.6.1':
     raise ImportError
-  
 except ImportError:
-  raise "GNUe Designer requires wxPython 2.6.1 or greater (2.6.2.1 on Mac)"
- 
+  raise "GNUe Designer requires wxPython 2.6.1 or greater."
+
+if wx.__version__ < '2.6.2.1':
+  print
+  print "*" * 70
+  print "WARNING: GNUe Designer is unstable on wxPython %s." % wx.__version__
+  print "         For a stable experience, please install 2.6.2.1 or better"
+  print "*" * 70
+  print
+
+
+# ---------------------------------------------------------------------------
+# GNUe Imports
+# ---------------------------------------------------------------------------
 from gnue.forms.uidrivers.wx.GFwxApp import setWxApp
 
-from startup.Startup import Startup
-from Instance import Instance
-from MenuBar import MenuBar
 
 class UIBase(wx.App):
 
 
-  ######################################################################
-  ######################################################################
-  ######################################################################
-  ###
-  ### Public methods
-  ###
-  ######################################################################
-  ######################################################################
-  ######################################################################
+  # ====================================================================
+  #
+  # Public methods
+  #
+  # ====================================================================
 
   def run(self):
-
     # Set form's wx app to be us
     setWxApp(self)
 
@@ -76,27 +85,30 @@
 
     # Call wx's MainLoop
     self.app.init()
+
+    # TODO: Temp
+    if wx.__version__ < '2.6.2.1':
+      wx.MessageDialog(None, 'Designer may be unstable when used\nwith 
wxWidgets %s. \nVersion 2.6.2.1 or better is recommended.' % wx.__version__)
+
     self.MainLoop()
 
   def createInstance(self, instance):
+    from Instance import Instance
     return Instance(instance)
 
-  ######################################################################
-  #
+  #---------------------------------------------------------------------
   # Startup Splash Screen
-  #
-  ######################################################################
+  #---------------------------------------------------------------------
   def createStartupSplash(self):
+    from startup.Startup import Startup
     self.__splash = Startup()
 
   def closeStartupSplash(self):
     self.__splash.pauseAndClose()
 
-  ######################################################################
-  #
+  #---------------------------------------------------------------------
   # Common dialogs
-  #
-  ######################################################################
+  #---------------------------------------------------------------------
   def dialogOk(self, text, title, parentWindow=None, icon="information", 
_cancel=False):
     """
     icon can be "question", "information", or "warn"
@@ -224,21 +236,15 @@
       return dlg.GetPath()
 
 
-  ##########################################################
-  ##########################################################
-  ##########################################################
-  ###
-  ### Internal Methods
-  ###
-  ##########################################################
-  ##########################################################
-  ##########################################################
+  # ====================================================================
+  #
+  # Internal Methods
+  #
+  # ====================================================================
 
-  ##########################################################
-  #
+  #---------------------------------------------------------------------
   # wx.App methods
-  #
-  ##########################################################
+  #---------------------------------------------------------------------
   def OnInit(self):
     """
     Standard wx.App OnInit function.
@@ -250,12 +256,9 @@
     """
     return True
 
-  ##########################################################
-  #
+  #---------------------------------------------------------------------
   # Misc internal methods
-  #
-  ##########################################################
-
+  #---------------------------------------------------------------------
   def __init__(self, app):
     print "__init__"
     self.app = app

Modified: trunk/gnue-designer/src/uidrivers/wx/Instance.py
===================================================================
--- trunk/gnue-designer/src/uidrivers/wx/Instance.py    2006-03-06 14:25:55 UTC 
(rev 8207)
+++ trunk/gnue-designer/src/uidrivers/wx/Instance.py    2006-03-06 14:54:02 UTC 
(rev 8208)
@@ -31,11 +31,13 @@
 import wx
 from gnue.designer.base import Goat
 from gnue.common.apps import RuntimeSettings
-#from docks.Docker import Docker
+
+
 from gnue.designer import PACKAGE as TITLE
 
 from gnue.designer.base.PrimaryToolBar import PrimaryToolBar
 from uihelpers import PyAUI
+from uihelpers import NotebookCtrl
 
 from MenuBar import MenuBar
 
@@ -44,13 +46,13 @@
     wx.Frame.__init__(self, None, -1, "", style=wx.DEFAULT_FRAME_STYLE |
                                             wx.SUNKEN_BORDER |
                                             wx.CLIP_CHILDREN)
-                                            
+
     # Setup PyAUI
     self._mgr = PyAUI.FrameManager(self)
-    self._mgr.SetFrame(self)    
+    self._mgr.SetFrame(self)
 
     self.instance = instance
-    
+
     # Set our icon
     icon = Goat.getGoatIcon()
     self.SetIcon(icon)
@@ -64,21 +66,22 @@
     self.statusbar = self.CreateStatusBar()
     self.SetStatusText(_('Welcome to GNUe Designer.'))
 
-    
     self._mgr.AddPane(self.toolbar, PyAUI.PaneInfo().
                           Name("PrimaryToolBar").Caption("GNUe Designer").
                           ToolbarPane().Top())
 
 
     wx.EVT_CLOSE(self, self.instance.OnClose)
-    
+
     # I think PyAUI requires this...
-    self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
-    
+    #self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
 
-  def OnEraseBackground(self, event): 
+    self.currentPrimaryEditor = None
+
+
+  def OnEraseBackground(self, event):
     event.Skip()
-    
+
   def createMenuBar(self):
     menuBar = MenuBar(self.instance)
     self.SetMenuBar(menuBar)
@@ -111,23 +114,28 @@
 #       RuntimeSettings.getint(self.instance.runtime_section, 'y', -1)))
 
     perspective = RuntimeSettings.get(self.instance.runtime_section, 
'aui-perspective','')
-    if perspective: 
+    if perspective:
       self._mgr.LoadPerspective(perspective)
 
     self._mgr.Update()
 
     self.Show(True)
-#    self.Refresh()
 
+    # Removing this refresh causes a segfault??
+    self.Refresh()
+
+  # -------------------------------------------------------------------------
+  #
+  # -------------------------------------------------------------------------
   def initTools(self):
     self.tools = []
 
-    pan = wx.Panel(self, -1)
-    pan.SetMinSize((200,200))
-    pan.SetSize((200,200))
-    self._mgr.AddPane(pan, 
PyAUI.PaneInfo().Name('Foo').Caption('Foo').CenterPane())
+    # Create a center notebook pane
+    self.editNotebook = notebook = NotebookCtrl.NotebookCtrl(
+           self,-1)
+    notebook.SetMinSize((200,200))
+    self._mgr.AddPane(notebook, 
PyAUI.PaneInfo().Name('Editor').Caption('Editor').CenterPane())
 
-    
 
     #
     # Add each tool
@@ -164,21 +172,15 @@
         # Docked type
         if tool._dock_location == 'right':
           toolinfo.Right()
-#          if rightrow: 
-#            toolinfo.Row(rightrow)
-#          rightrow += 1
         else:
           toolinfo.Left()
-#          if leftrow: 
-#            toolinfo.Row(leftrow)
-#          leftrow += 1
       else:
         # Frame type
         toolinfo.Float()
-        
-      if not tool._visible: 
+
+      if not tool._visible:
         toolinfo.Hide()
-        
+
       self._mgr.AddPane(tool, toolinfo)
 
       # Keep track of the tools we created
@@ -196,11 +198,25 @@
 #        instance.dispatchEvent('Show:Tool:%s' % id)
 #      else:
 #        instance.dispatchEvent('Hide:Tool:%s' % id)
-    
 
   #
+  def createEditor(self, object, id, title, baseclass):
+    """
+    Create a new editor instance for a GObject
+    """
+    tool = baseclass(object, id, title, self.instance,
+                     self.instance.rootObject, self.editNotebook)
+
+    print " ** Adding %s" % title
+    object._editorComponent = tool
+    page = self.editNotebook.AddPage(tool, tool._caption, False, -1)
+
+
+
+  # -------------------------------------------------------------------------
+  #
+  # -------------------------------------------------------------------------
   #  Used by RuntimeSettings
-  #
   def getRuntimeSettings(self):
     x, y = self.GetPositionTuple()
     width, height = self.GetSizeTuple()
@@ -211,6 +227,9 @@
 
     return settings
 
+  # -------------------------------------------------------------------------
+  #
+  # -------------------------------------------------------------------------
   def close(self):
     self.Destroy()
 

Modified: trunk/gnue-designer/src/uidrivers/wx/startup/Startup.py
===================================================================
--- trunk/gnue-designer/src/uidrivers/wx/startup/Startup.py     2006-03-06 
14:25:55 UTC (rev 8207)
+++ trunk/gnue-designer/src/uidrivers/wx/startup/Startup.py     2006-03-06 
14:54:02 UTC (rev 8208)
@@ -31,7 +31,8 @@
 import __builtin__
 from gnue.common.apps import GConfig
 
-__builtin__.__dict__['gStartupStatus'] = lambda string:string
+def _printStartupStatus(text):
+  print ' * %s' % text
 
 splashloc = 
os.path.join(GConfig.getInstalledBase('designer_images','common_images') 
,'designer', 'splash.png')
 
@@ -64,7 +65,7 @@
     self.Destroy()
 
   def hide(self, event=None):
-    __builtin__.__dict__['gStartupStatus'] = lambda string:string
+    __builtin__.__dict__['gStartupStatus'] = _printStartupStatus
     self.Show(0)
 
   def startupStatus(self, text):

Added: trunk/gnue-designer/src/uidrivers/wx/uihelpers/NotebookCtrl.py
===================================================================
--- trunk/gnue-designer/src/uidrivers/wx/uihelpers/NotebookCtrl.py      
2006-03-06 14:25:55 UTC (rev 8207)
+++ trunk/gnue-designer/src/uidrivers/wx/uihelpers/NotebookCtrl.py      
2006-03-06 14:54:02 UTC (rev 8208)
@@ -0,0 +1,5257 @@
+# --------------------------------------------------------------------------- #
+# NOTEBOOKCTRL Control wxPython IMPLEMENTATION
+# Python Code By:
+#
+# Andrea Gavana, @ 11 Nov 2005
+# Latest Revision: 10 Jan 2006, 18.10 CET
+#
+#
+# TODO List/Caveats
+#
+# 1. Ay Idea?
+#
+# For All Kind Of Problems, Requests Of Enhancements And Bug Reports, Please
+# Write To Me At:
+#
+# address@hidden
+# address@hidden
+#
+# Or, Obviously, To The wxPython Mailing List!!!
+#
+#
+# End Of Comments
+# --------------------------------------------------------------------------- #
+
+
+"""
+Description:
+
+NotebookCtrl Mimics The Behavior Of wx.Notebook, And Most Of Its 
Functionalities
+Are Implemented In NotebookCtrl. However, NotebookCtrl Has A Lot Of Options 
That
+wx.Notebook Does Not Have, And It Is Therefore Quite Customizable.
+wx.Notebook Styles Not Implemented in NotebookCtrl Are:
+
+- wx.NB_LEFT
+- wx.NB_RIGHT
+- wx.NB_MULTILINE (But NotebookCtrl Has A SpinButton To Navigate Through Tabs).
+
+Supported Customizations For NotebookCtrl Include:
+
+- Setting Individual Tab Font And Text Colour;
+- Images On Tabs (Line wx.Notebook);
+- Setting Individual Tab Colours;
+- Disabling/Enabling Individual Tabs (Also Visually Effective); Now Supports 
Grayed
+  Out Icons When A Page Is Disabled;
+- Drawing Of A Small Closing "X" At The Right Of Every Tab, That Enable The 
User
+  To Close A Tab With A Mouse Click (Like eMule Tab Style);
+- Enabling Highlighted Tabs On Selection;
+- Drawing Focus Indicator In Each Tab (Like wx.Notebook);
+- Ctrl-Tab Keyboard Navigation Between Pages;
+- Tab With Animated Icons (Animation On Tabs);
+- Drag And Drop Tabs In NotebookCtrl (Plus A Visual Arrow Effect To Indicate
+  Dropping Position);
+- Drag And Drop Event;
+- ToolTips On Individual Tabs, With Customizable ToolTip Time Popup And ToolTip
+  Window Size For Individual Tabs;
+- Possibility To Hide The TabCtrl There Is Only One Tab (Thus Maximizing The
+  Corresponding Window);
+- Possibility To Convert The Tab Image Into A Close Button While Mouse Is 
Hovering
+  On The Tab Image;
+- Popup Menus On Tabs (Popup Menus Specific To Each Tab);
+- Showing Pages In "Column/Row Mode", Which Means That All Pages Will Be Shown 
In
+  NotebookCtrl While The Tabs Are Hidden. They Can Be Shown In Columns 
(Default)
+  Or In Rows;
+- Possibility To Hide Tabs On User Request, Thus Showing Only The Current 
Panel;
+- Multiple Tabs Selection (Hold Ctrl Key Down And Left Mouse Click), Useful 
When
+  You Use The Show All The Panels In Columns/Rows. In This Case, Only The 
Selected
+  Tabs Are Shown In Columns/Rows;
+- Events For Mouse Events (Left Double Click, Middle Click, Right Click);
+- Possibility To Reparent A NotebookCtrl Page To A Freshly Created Frame As A 
Simple
+  Panel Or To A New NotebookCtrl Created Inside That New Frame.
+- Possibility To Add A Custom Panel To Show A Logo Or HTML Information Or 
Whatever
+  You Like When There Are No Tabs In NotebookCtrl;
+- Possibility To Change The ToolTip Window Background Colour;
+- Possibility To Draw Vertical Or Horizontal Gradient Coloured Tabs (2 
Colours);
+- Themes On Tabs: Built-In Themes Are KDE (Unix/Linux), Metal, Aqua Light
+  And Aqua Dark (MacOS), Windows Silver (Windows) Or Generic Gradient Coloured 
Tabs.
+  It's Also Possible To Define A Separate Theme For Selected Tabs And Control
+  Background (The Last Two Are Work In Progress);
+- Contour Line Colour Around Tabs Is Customizable;
+- Highlight Colour Of Selected Tab Is Customizable;
+- Each Tab Can Have Its Own Gradient Colouring (2 Colours For Every Tab);
+- Custom Images May Be Drawn As A "X" Close Buttons On Tabs;
+- Possibility To Hide A Particular Tab Using A wx.PopupMenu That Is Shown If 
You
+  Call EnableHiding(True). Look At The Top Right Of NotebookCtrl;
+- Allows Drag And Drop Of Tabs/Pages Between Different NotebookCtrls In The 
Same
+  Application.
+
+
+Usage:
+
+NotebookCtrl Construction Is Quite Similar To wx.Notebook:
+
+NotebookCtrl.__init__(self, parent, id, pos=wx.DefaultPosition,
+                      size=wx.DefaultSize, style=style, sizer=nbsizer)
+
+See NotebookCtrl __init__() Method For The Definition Of Non Standard (Non
+wxPython) Parameters.
+
+NotebookCtrl Control Is Freeware And Distributed Under The wxPython License.
+
+Latest Revision: Andrea Gavana @ 10 Jan 2006, 18.10 CET
+
+"""
+
+
+#----------------------------------------------------------------------
+# Beginning Of NOTEBOOKCTRL wxPython Code
+#----------------------------------------------------------------------
+
+import wx
+from wx.lib.buttons import GenBitmapButton as BitmapButton
+
+import cStringIO, zlib
+import cPickle
+import weakref
+
+# HitTest Results
+NC_HITTEST_NOWHERE = 0   # Not On Tab
+NC_HITTEST_ONICON  = 1   # On Icon
+NC_HITTEST_ONLABEL = 2   # On Label
+NC_HITTEST_ONITEM  = 4   # Generic, On Item
+NC_HITTEST_ONX = 8       # On Small Square On Every Page
+
+# NotebookCtrl Styles
+# NotebookCtrl Placed On Top (Default)
+NC_TOP = 1
+# NotebookCtrl Placed At The Bottom
+NC_BOTTOM = 2
+# NotebookCtrl With Fixed Width Tabs
+NC_FIXED_WIDTH = 4
+
+NC_DEFAULT_STYLE = NC_TOP | wx.NO_BORDER
+# Also wx.STATIC_BORDER Is Supported
+
+# Patch To Make NotebookCtrl Working Also On MacOS: Thanks To Stani ;-)
+if wx.Platform == '__WXMAC__':
+    DEFAULT_SIZE = wx.Size(26, 26)
+else:
+    DEFAULT_SIZE = wx.DefaultSize
+
+# Themes On Mac... This May Slow Down The Paint Event If You Turn It On!
+NC_MAC_LIGHT = (240, 236)
+NC_MAC_DARK = (232, 228)
+
+topaqua1 = [wx.Colour(106, 152, 231), wx.Colour(124, 173, 236)]
+botaqua1 = [wx.Colour(54, 128, 213), wx.Colour(130, 225, 249)]
+
+topaqua2 = [wx.Colour(176, 222, 251), wx.Colour(166, 211, 245)]
+botaqua2 = [wx.Colour(120, 182, 244), wx.Colour(162, 230, 245)]
+
+distaqua = [wx.Colour(248, 248, 248), wx.Colour(243, 243, 243)]
+disbaqua = [wx.Colour(219, 219, 219), wx.Colour(248, 248, 248)]
+
+# Themes On KDE... This May Slow Down The Paint Event If You Turn It On!
+kdetheme = [wx.Colour(0xf3,0xf7,0xf9), wx.Colour(0xf3,0xf7,0xf9),
+            wx.Colour(0xee,0xf3,0xf7), wx.Colour(0xee,0xf3,0xf7),
+            wx.Colour(0xea,0xf0,0xf4), wx.Colour(0xea,0xf0,0xf4),
+            wx.Colour(0xe6,0xec,0xf1), wx.Colour(0xe6,0xec,0xf1),
+            wx.Colour(0xe2,0xe9,0xef), wx.Colour(0xe2,0xe9,0xef),
+            wx.Colour(0xdd,0xe5,0xec), wx.Colour(0xdd,0xe5,0xec),
+            wx.Colour(0xd9,0xe2,0xea), wx.Colour(0xd9,0xe2,0xea)]
+
+# Themes On Windows... This May Slow Down The Paint Event If You Turn It On!
+silvertheme2 = [wx.Colour(255, 255, 255), wx.Colour(190, 190, 216),
+                wx.Colour(180, 180, 200)]
+silvertheme1 = [wx.Colour(252, 252, 254), wx.Colour(252, 252, 254)]
+
+# NotebookCtrl Events:
+# wxEVT_NOTEBOOKCTRL_PAGE_CHANGED: Event Fired When You Switch Page;
+# wxEVT_NOTEBOOKCTRL_PAGE_CHANGING: Event Fired When You Are About To Switch
+# Pages, But You Can Still "Veto" The Page Changing By Avoiding To Call
+# event.Skip() In Your Event Handler;
+# wxEVT_NOTEBOOKCTRL_PAGE_CLOSING: Event Fired When A Page Is Closing, But
+# You Can Still "Veto" The Page Changing By Avoiding To Call event.Skip()
+# In Your Event Handler;
+# wxEVT_NOTEBOOKCTRL_PAGE_DND: Event Fired When A Drag And Drop Action On
+# Tabs Ends.
+wxEVT_NOTEBOOKCTRL_PAGE_CHANGED = wx.NewEventType()
+wxEVT_NOTEBOOKCTRL_PAGE_CHANGING = wx.NewEventType()
+wxEVT_NOTEBOOKCTRL_PAGE_CLOSING = wx.NewEventType()
+wxEVT_NOTEBOOKCTRL_PAGE_DND = wx.NewEventType()
+wxEVT_NOTEBOOKCTRL_PAGE_DCLICK = wx.NewEventType()
+wxEVT_NOTEBOOKCTRL_PAGE_RIGHT = wx.NewEventType()
+wxEVT_NOTEBOOKCTRL_PAGE_MIDDLE = wx.NewEventType()
+
+#-----------------------------------#
+#        NotebookCtrlEvent
+#-----------------------------------#
+
+EVT_NOTEBOOKCTRL_PAGE_CHANGED = 
wx.PyEventBinder(wxEVT_NOTEBOOKCTRL_PAGE_CHANGED, 1)
+EVT_NOTEBOOKCTRL_PAGE_CHANGING = 
wx.PyEventBinder(wxEVT_NOTEBOOKCTRL_PAGE_CHANGING, 1)
+EVT_NOTEBOOKCTRL_PAGE_CLOSING = 
wx.PyEventBinder(wxEVT_NOTEBOOKCTRL_PAGE_CLOSING, 1)
+EVT_NOTEBOOKCTRL_PAGE_DND = wx.PyEventBinder(wxEVT_NOTEBOOKCTRL_PAGE_DND, 1)
+EVT_NOTEBOOKCTRL_PAGE_DCLICK = 
wx.PyEventBinder(wxEVT_NOTEBOOKCTRL_PAGE_DCLICK, 1)
+EVT_NOTEBOOKCTRL_PAGE_RIGHT = wx.PyEventBinder(wxEVT_NOTEBOOKCTRL_PAGE_RIGHT, 
1)
+EVT_NOTEBOOKCTRL_PAGE_MIDDLE = 
wx.PyEventBinder(wxEVT_NOTEBOOKCTRL_PAGE_MIDDLE, 1)
+
+attrs = ["_backstyle", "_backtooltip", "_borderpen", "_convertimage", "_drawx",
+         "_drawxstyle", "_enabledragging", "_focusindpen", "_hideonsingletab",
+         "_highlight", "_padding", "_selectioncolour", "_selstyle", 
"_tabstyle",
+         "_upperhigh", "_usefocus", "_usegradients"]
+
+
+# ---------------------------------------------------------------------------- 
#
+def GetMenuButtonData():
+
+    return zlib.decompress(
+"x\xda\xeb\x0c\xf0s\xe7\xe5\x92\xe2b``\xe0\xf5\xf4p\t\x02\xd2\x9c \xcc\xc1\
+\x06$\x1fLd\x13\x00R,address@hidden
+\xbd`\xc8\xc7\xa0\xc0\xe1|q\xdb\x9d\xff'\xba\xb4\x1d\x05v\xff}\xe2\xab\x9a:c\
+\x99\xc4\xbe\xe9\xfd+\x9a\xc5W%t\x1a\xe5\x08\xa6\xd6,\xe2\xf0\x9a\xc2\xc8\
+\xf0\xe1\xf9r\xe6\xa3\xc9\x02b\xd9\x0c35\x80f0x\xba\xfa\xb9\xacsJh\x02\x00\
+\xcd-%1")
+
+
+def GetMenuButtonBitmap():
+
+    return wx.BitmapFromImage(GetMenuButtonImage())
+
+
+def GetMenuButtonImage():
+
+    stream = cStringIO.StringIO(GetMenuButtonData())
+    return wx.ImageFromStream(stream)
+
+# ---------------------------------------------------------------------------- 
#
+
+def GrayOut(anImage):
+    """
+    Convert The Given Image (In Place) To A Grayed-Out Version,
+    Appropriate For A 'Disabled' Appearance.
+    """
+
+    factor = 0.7        # 0 < f < 1.  Higher Is Grayer
+
+    if anImage.HasMask():
+        maskColor = (anImage.GetMaskRed(), anImage.GetMaskGreen(), 
anImage.GetMaskBlue())
+    else:
+        maskColor = None
+
+    data = map(ord, list(anImage.GetData()))
+
+    for i in range(0, len(data), 3):
+
+        pixel = (data[i], data[i+1], data[i+2])
+        pixel = MakeGray(pixel, factor, maskColor)
+
+        for x in range(3):
+            data[i+x] = pixel[x]
+
+    anImage.SetData(''.join(map(chr, data)))
+
+    return anImage
+
+
+def MakeGray((r,g,b), factor, maskColor):
+    """
+    Make A Pixel Grayed-Out. If The Pixel Matches The MaskColor, It Won't Be
+    Changed.
+    """
+
+    if (r,g,b) != maskColor:
+        return map(lambda x: int((230 - x) * factor) + x, (r,g,b))
+    else:
+        return (r,g,b)
+
+
+# ---------------------------------------------------------------------------- 
#
+# Class NotebookCtrlEvent
+# ---------------------------------------------------------------------------- 
#
+
+class NotebookCtrlEvent(wx.PyCommandEvent):
+    """
+    This Events Will Be Sent When A EVT_NOTEBOOKCTRL_PAGE_CHANGED,
+    EVT_NOTEBOOKCTRL_PAGE_CHANGING And EVT_NOTEBOOKCTRL_PAGE_CLOSING Is Mapped 
In
+    The Parent.
+    """
+
+    def __init__(self, eventType, id=1, nSel=-1, nOldSel=-1):
+        """ Default Class Constructor. """
+
+        wx.PyCommandEvent.__init__(self, eventType, id)
+        self._eventType = eventType
+
+
+    def SetSelection(self, nSel):
+        """ Sets Event Selection. """
+
+        self._selection = nSel
+
+
+    def SetOldSelection(self, nOldSel):
+        """ Sets Old Event Selection. """
+
+        self._oldselection = nOldSel
+
+
+    def GetSelection(self):
+        """ Returns Event Selection. """
+
+        return self._selection
+
+
+    def GetOldSelection(self):
+        """ Returns Old Event Selection """
+
+        return self._oldselection
+
+
+    def SetOldPosition(self, pos):
+        """ Sets Old Event Position. """
+
+        self._oldposition = pos
+
+
+    def SetNewPosition(self, pos):
+        """ Sets New Event Position. """
+
+        self._newposition = pos
+
+
+    def GetOldPosition(self):
+        """ Returns Old Event Position. """
+
+        return self._oldposition
+
+
+    def GetNewPosition(self):
+        """ Returns New Event Position. """
+
+        return self._newposition
+
+
+# ---------------------------------------------------------------------------- 
#
+# Class NCDragInfo
+# Stores All The Information To Allow Drag And Drop Between Different
+# NotebookCtrls In The Same Application.
+# ---------------------------------------------------------------------------- 
#
+
+class NCDragInfo:
+
+    _map = weakref.WeakValueDictionary()
+
+    def __init__(self, container, pageindex):
+        """ Default Class Constructor. """
+
+        self._id = id(container)
+        NCDragInfo._map[self._id] = container
+        self._pageindex = pageindex
+
+
+    def GetContainer(self):
+        """ Returns The NotebookCtrl Page (Usually A Panel). """
+
+        return NCDragInfo._map.get(self._id, None)
+
+
+    def GetPageIndex(self):
+        """ Returns The Page Index Associated With A Page. """
+
+        return self._pageindex
+
+
+# ---------------------------------------------------------------------------- 
#
+# Class NCDropTarget
+# Simply Used To Handle The OnDrop() Method When Dragging And Dropping Between
+# Different NotebookCtrls.
+# ---------------------------------------------------------------------------- 
#
+
+class NCDropTarget(wx.DropTarget):
+
+    def __init__(self, parent):
+        """ Default Class Constructor. """
+
+        wx.DropTarget.__init__(self)
+
+        self._parent = parent
+        self._dataobject = 
wx.CustomDataObject(wx.CustomDataFormat("NotebookCtrl"))
+        self.SetDataObject(self._dataobject)
+
+
+    def OnData(self, x, y, dragres):
+        """ Handles The OnData() Method TO Call The Real DnD Routine. """
+
+        if not self.GetData():
+            return wx.DragNone
+
+        draginfo = self._dataobject.GetData()
+        drginfo = cPickle.loads(draginfo)
+
+        return self._parent.OnDropTarget(x, y, drginfo.GetPageIndex(), 
drginfo.GetContainer())
+
+
+# ---------------------------------------------------------------------------- 
#
+# Class ThemeStyle. Used To Define A Custom Style For Tabs And Control
+# Background Colour.
+# ---------------------------------------------------------------------------- 
#
+
+class ThemeStyle:
+
+    def __init__(self):
+        """ Default Constructor For This Class."""
+
+        self.ResetDefaults()
+
+
+    def ResetDefaults(self):
+        """ Resets Default Theme. """
+
+        self._normal = True
+        self._aqua = False
+        self._metal = False
+        self._macstyle = False
+        self._kdetheme = False
+        self._silver = False
+        self._gradient = False
+        self._firstcolour = wx.WHITE
+        self._secondcolour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNFACE)
+
+
+    def EnableMacTheme(self, enable=True, style=1):
+        """
+        Enables/Disables Mac Themes. style=1 Is The Light Style, While style=2
+        Is The Dark Style. Mainly Used For Control Background Colour, Not For 
Tabs.
+        """
+
+        if enable:
+            self._normal = False
+            self._macstyle = style
+            self._kdetheme = False
+            self._metal = False
+            self._aqua = False
+            self._silver = False
+            self._gradient = False
+        else:
+            self._macstyle = 0
+
+
+    def EnableKDETheme(self, enable=True):
+        """ Globally Enables/Disables Unix-Like KDE Theme For Tabs. """
+
+        self._kdetheme = enable
+
+        if enable:
+            self._normal = False
+            self._macstyle = False
+            self._metal = False
+            self._aqua = False
+            self._silver = False
+            self._gradient = False
+
+
+    def EnableMetalTheme(self, enable=True):
+        """ Globally Enables/Disables Mac-Like Metal Theme For Tabs. """
+
+        self._metal = enable
+
+        if enable:
+            self._normal = False
+            self._macstyle = False
+            self._kdetheme = False
+            self._aqua = False
+            self._silver = False
+            self._gradient = False
+
+
+    def EnableAquaTheme(self, enable=True, style=1):
+        """ Globally Enables/Disables Mac-Like Aqua Theme For Tabs. """
+
+        if enable:
+            self._aqua = style
+            self._normal = False
+            self._macstyle = False
+            self._kdetheme = False
+            self._metal = False
+            self._silver = False
+            self._gradient = False
+        else:
+            self._aqua = 0
+
+
+    def EnableSilverTheme(self, enable=True):
+        """ Globally Enables/Disables Windows Silver Theme For Tabs. """
+
+        self._silver = enable
+
+        if enable:
+            self._normal = False
+            self._macstyle = False
+            self._kdetheme = False
+            self._metal = False
+            self._aqua = False
+            self._gradient = False
+
+
+    def EnableGradientStyle(self, enable=True, style=1):
+        """
+        Enables/Disables Gradient Drawing On Tabs. style=1 Is The Vertical 
Gradient,
+        While style=2 Is The Horizontal Gradient.
+        """
+
+        if enable:
+            self._normal = False
+            self._gradient = style
+            self._macstyle = False
+            self._kdetheme = False
+            self._metal = False
+            self._aqua = False
+            self._silver = False
+        else:
+            self._gradient = 0
+
+
+    def SetFirstGradientColour(self, colour=None):
+        """ Sets The First Gradient Colour. """
+
+        if colour is None:
+            colour = wx.WHITE
+
+        self._firstcolour = colour
+
+
+    def SetSecondGradientColour(self, colour=None):
+        """ Sets The Second Gradient Colour. """
+
+        if colour is None:
+            color = self.GetBackgroundColour()
+            r, g, b = int(color.Red()), int(color.Green()), int(color.Blue())
+            color = ((r >> 1) + 20, (g >> 1) + 20, (b >> 1) + 20)
+            colour = wx.Colour(color[0], color[1], color[2])
+
+        self._secondcolour = colour
+
+
+    def GetFirstGradientColour(self):
+        """ Returns The First Gradient Colour. """
+
+        return self._firstcolour
+
+
+    def GetSecondGradientColour(self):
+        """ Returns The Second Gradient Colour. """
+
+        return self._secondcolour
+
+
+
+# ---------------------------------------------------------------------------- 
#
+# Class TabbedPage
+# This Is Just A Container Class That Initialize All The Default Settings For
+# Every Tab.
+# ---------------------------------------------------------------------------- 
#
+
+class TabbedPage:
+
+    def __init__(self, text="", image=-1, hidden=False):
+        """ Default Class Constructor. """
+
+        self._text = text
+        self._image = image
+        self._font = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
+        self._secondaryfont = 
wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
+        self._pagetextcolour = wx.BLACK
+        self._pagecolour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNFACE)
+        self._enable = True
+        self._animationimages = []
+        self._tooltip = ""
+        self._tooltiptime = 500
+        self._winsize = 400
+        self._menu = None
+        self._ishidden = hidden
+        self._firstcolour = color = wx.WHITE
+        r, g, b = int(color.Red()), int(color.Green()), int(color.Blue())
+        color = ((r >> 1) + 20, (g >> 1) + 20, (b >> 1) + 20)
+        colour = wx.Colour(color[0], color[1], color[2])
+        self._secondcolour = colour
+
+
+# ---------------------------------------------------------------------------- 
#
+# Class NotebookSpinButton
+# This SpinButton Is Created/Shown Only When The Total Tabs Size Exceed The
+# Client Size, Allowing The User To Navigate Between Tabs By Clicking On The
+# SpinButton. It Is Very Similar To The wx.Notebook SpinButton
+# ---------------------------------------------------------------------------- 
#
+
+class NotebookSpinButton(wx.SpinButton):
+
+    def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition,
+                 size=wx.DefaultSize, style=wx.SP_HORIZONTAL):
+        """ Default Class Constructor. """
+
+        wx.SpinButton.__init__(self, parent, id, pos, size, style)
+        self._nb = parent
+        self._oldvalue = 0
+        self.Bind(wx.EVT_SPIN, self.OnSpin)
+
+
+    def OnSpin(self, event):
+        """ Handles The User's Clicks On The SpinButton. """
+
+        if type(event) != type(1):
+            pos = event.GetPosition()
+        else:
+            pos = event
+
+        if pos < 0:
+            self.SetValue(0)
+            return
+
+        if type(event) != type(1):
+            if self._nb._enablehiding:
+                if pos < self._oldvalue:
+                    incr = -1
+                else:
+                    incr = 1
+                while self._nb._pages[pos]._ishidden:
+                    pos = pos + incr
+
+            self.SetValue(pos)
+
+        if self._nb.IsLastVisible() and self._oldvalue < pos:
+            self.SetValue(self._oldvalue)
+            return
+
+        self._oldvalue = pos
+
+        self._nb.Refresh()
+
+
+# ---------------------------------------------------------------------------- 
#
+# Class NotebookMenuButton
+# This MenuButton Is Created/Shown Only When You Activate The Option 
EnableHiding
+# Of NotebookCtrl. This Small Button Will Be Shown Right Above The Spin Button
+# (If Present), Or In The Position Of The Spin Button.
+# ---------------------------------------------------------------------------- 
#
+
+class NotebookMenuButton(BitmapButton):
+
+    def __init__(self, parent, id=-1, pos=wx.DefaultPosition, size=(15, 11),
+                 style=0):
+        """ Default Class Constructor. """
+
+        bmp = GetMenuButtonBitmap()
+
+        BitmapButton.__init__(self, parent, id, bmp, pos, size, style)
+
+        self.SetUseFocusIndicator(False)
+        self.SetBezelWidth(1)
+
+        self._originalcolour = self.GetBackgroundColour()
+        self._nb = parent
+
+        self.Bind(wx.EVT_BUTTON, self.OnButton)
+        self.Bind(wx.EVT_ENTER_WINDOW, self.OnEnterWindow)
+        self.Bind(wx.EVT_LEAVE_WINDOW, self.OnLeaveWindow)
+        self.Bind(wx.EVT_MENU, self.OnMenu)
+
+
+    def OnButton(self, event):
+        """ Handles The wx.EVT_BUTTON For NotebookMenuButton (Opens The 
wx.PopupMenu) """
+
+        count = self._nb.GetPageCount()
+
+        if count <= 0:
+            return
+
+        menu = wx.Menu()
+        id = wx.NewId()
+        myids = []
+
+        for ii in xrange(count):
+
+            id = id + 1
+            myids.append(id)
+            name = self._nb.GetPageText(ii)
+
+            if self._nb._pages[ii]._ishidden:
+                msg = "Page Hidden"
+                check = False
+            else:
+                msg = "Page Shown"
+                check = True
+
+            item = wx.MenuItem(menu, id, name, msg, wx.ITEM_CHECK)
+            menu.AppendItem(item)
+
+            if not self._nb._pages[ii]._ishidden:
+                item.Check()
+
+            menu.SetHelpString(id, msg)
+
+        self._myids = myids
+
+        self.PopupMenu(menu)
+
+        event.Skip()
+
+
+    def OnMenu(self, event):
+        """ Handles The wx.EVT_MENU For NotebookMenuButton. Calls HideTab(). 
"""
+
+        indx = self._myids.index(event.GetId())
+        checked = not event.GetEventObject().IsChecked(event.GetId())
+
+        self._nb.HideTab(indx, not checked)
+
+        event.Skip()
+
+
+    def OnEnterWindow(self, event):
+        """
+        Changes The NotebookMenuButton Background Colour When The Mouse
+        Enters The Button Region.
+        """
+
+        entercolour = self.GetBackgroundColour()
+        firstcolour  = entercolour.Red()
+        secondcolour = entercolour.Green()
+        thirdcolour = entercolour.Blue()
+
+        if entercolour.Red() > 235:
+            firstcolour = entercolour.Red() - 40
+        if entercolour.Green() > 235:
+            secondcolour = entercolour.Green() - 40
+        if entercolour.Blue() > 235:
+            thirdcolour = entercolour.Blue() - 40
+
+        entercolour = wx.Colour(firstcolour+20, secondcolour+20, 
thirdcolour+20)
+
+        self.SetBackgroundColour(entercolour)
+        self.Refresh()
+
+        event.Skip()
+
+
+    def OnLeaveWindow(self, event):
+        """
+        Restore The NotebookMenuButton Background Colour When The Mouse
+        Leaves The Button Region.
+        """
+
+        self.SetBackgroundColour(self._originalcolour)
+        self.Refresh()
+
+        event.Skip()
+
+
+# ---------------------------------------------------------------------------- 
#
+# Class TabCtrl
+# This Class Handles The Drawing Of Every Tab In The NotebookCtrl, And Also
+# All Settings/Methods For Every Tab.
+# ---------------------------------------------------------------------------- 
#
+
+class TabCtrl(wx.PyControl):
+
+    def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition,
+                 size=DEFAULT_SIZE, style=NC_DEFAULT_STYLE,
+                 validator=wx.DefaultValidator, name="TabCtrl"):
+        """
+        Default Class Constructor.
+        Used Internally. Do Not Call It Explicitely!
+        """
+
+        wx.PyControl.__init__(self, parent, id, pos, size, wx.NO_BORDER | 
wx.WANTS_CHARS,
+                              validator, name)
+
+        # Set All The Default Parameters For TabCtrl
+        self._selection = -1
+        self._imglist = 0
+        self._style = style
+        self._pages = []
+        self._enabledpages = []
+
+        self._padding = wx.Point(8, 5)
+        self._spacetabs = 2
+        self._xrect = []
+        self._xrefreshed = False
+        self._imageconverted = False
+        self._convertimage = False
+        self._disabledcolour = 
wx.SystemSettings_GetColour(wx.SYS_COLOUR_GRAYTEXT)
+
+        self._hover = False
+        self._parent = parent
+        self._firsttime = True
+        self._somethingchanged = True
+        self._isdragging = False
+        self._tabID = -1
+        self._enabledragging = False
+        self._olddragpos = -1
+        self._fromdnd = False
+        self._isleaving = False
+        self._highlight = False
+        self._usefocus = True
+        self._hideonsingletab = False
+        self._selectioncolour = wx.Colour(255, 180, 0)
+
+        self._tabstyle = ThemeStyle()
+        self._backstyle = ThemeStyle()
+        self._selstyle = ThemeStyle()
+        self._usegradients = False
+
+        self._insidetab = -1
+        self._showtooltip = False
+        self._istooltipshown = False
+        self._tipwindow = None
+        self._tiptimer = wx.PyTimer(self.OnShowToolTip)
+        self._backtooltip = wx.Colour(255, 255, 230)
+        self._xvideo = wx.SystemSettings_GetMetric(wx.SYS_SCREEN_X)
+        self._yvideo = wx.SystemSettings_GetMetric(wx.SYS_SCREEN_Y)
+
+        self._selectedtabs = []
+
+        self._timers = []
+
+        self._dragcursor = wx.StockCursor(wx.CURSOR_HAND)
+        self._dragstartpos = wx.Point()
+
+        self._drawx = False
+        self._drawxstyle = 1
+
+        self._pmenu = None
+
+        self._enablehiding = False
+
+        self.SetDefaultPage()
+
+        self.SetBestSize((-1, 28))
+
+        self._borderpen = 
wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW))
+        self._highlightpen2 = 
wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW))
+        self._highlightpen = wx.Pen((145, 167, 180))
+        self._upperhigh = 
wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW))
+        self._shadowpen = 
wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DDKSHADOW), 2)
+        self._shadowpen.SetCap(wx.CAP_BUTT)
+        self._highlightpen.SetCap(wx.CAP_BUTT)
+        self._highlightpen2.SetCap(wx.CAP_BUTT)
+
+        if wx.Platform == "__WXMAC__":
+            self._focusindpen = wx.Pen(wx.BLACK, 1, wx.SOLID)
+        else:
+            self._focusindpen = wx.Pen(wx.BLACK, 1, wx.USER_DASH)
+            self._focusindpen.SetDashes([1,1])
+            self._focusindpen.SetCap(wx.CAP_BUTT)
+
+        self.Bind(wx.EVT_LEFT_DOWN, self.OnMouseLeftDown)
+        self.Bind(wx.EVT_LEFT_DCLICK, self.OnMouseLeftDClick)
+        self.Bind(wx.EVT_MOTION, self.OnMouseMotion)
+        self.Bind(wx.EVT_LEFT_UP, self.OnMouseLeftUp)
+        self.Bind(wx.EVT_RIGHT_UP, self.OnMouseRightUp)
+        self.Bind(wx.EVT_RIGHT_DOWN, self.OnMouseRightDown)
+        self.Bind(wx.EVT_MIDDLE_DOWN, self.OnMouseMiddleDown)
+        self.Bind(wx.EVT_SIZE, self.OnSize)
+
+        self.Bind(wx.EVT_PAINT, self.OnPaint)
+        self.Bind(wx.EVT_ERASE_BACKGROUND, lambda x: None)
+
+        self.Bind(wx.EVT_TIMER, self.AnimateTab)
+        self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
+        self.Bind(wx.EVT_LEAVE_WINDOW, self.OnLeaveWindow)
+
+        self._droptarget = NCDropTarget(self)
+        self.SetDropTarget(self._droptarget)
+
+
+    def OnDropTarget(self, x, y, nPage, oldcont):
+        """ Handles The OnDrop Action For Drag And Drop Between Different 
NotebookCtrl. """
+
+        where = self.HitTest(wx.Point(x, y))
+
+        oldNotebook = oldcont.GetParent()
+        newNotebook = self.GetParent()
+
+        if oldNotebook == newNotebook:
+            if where >= 0 and where != self._tabID:
+
+                self._isdragging = False
+                self._olddragpos = -1
+                eventOut = NotebookCtrlEvent(wxEVT_NOTEBOOKCTRL_PAGE_DND, 
self.GetId())
+                eventOut.SetOldPosition(self._tabID)
+                eventOut.SetNewPosition(where)
+                eventOut.SetEventObject(self)
+
+                if self.GetEventHandler().ProcessEvent(eventOut):
+                    self._tabID = -1
+                    self._olddragpos = -1
+                    self.SetCursor(wx.STANDARD_CURSOR)
+                    self.Refresh()
+                    return
+
+                self._parent.Freeze()
+
+                try:
+                    text = self.GetPageText(self._tabID)
+                    image = self.GetPageImage(self._tabID)
+                    font1 = self.GetPageTextFont(self._tabID)
+                    font2 = self.GetPageTextSecondaryFont(self._tabID)
+                    fontcolour = self.GetPageTextColour(self._tabID)
+                    pagecolour = self.GetPageColour(self._tabID)
+                    enabled = self.IsPageEnabled(self._tabID)
+                    tooltip, ontime, winsize = self.GetPageToolTip(self._tabID)
+                    menu = self.GetPagePopupMenu(self._tabID)
+                    firstcol = self.GetPageFirstGradientColour(self._tabID)
+                    secondcol = self.GetPageSecondGradientColour(self._tabID)
+                    ishidden = self._pages[self._tabID]._ishidden
+                except:
+                    self._parent.Thaw()
+                    self._tabID = -1
+                    self.SetCursor(wx.STANDARD_CURSOR)
+                    return
+
+                isanimated = 0
+                if self._timers[self._tabID].IsRunning():
+                    isanimated = 1
+                    timer = self._timers[self._tabID].GetInterval()
+
+                self.StopAnimation(self._tabID)
+                animatedimages = self.GetAnimationImages(self._tabID)
+
+                pagerange = range(self.GetPageCount())
+
+                newrange = pagerange[:]
+                newrange.remove(self._tabID)
+                newrange.insert(where, self._tabID)
+
+                newpages = []
+                counter = self.GetPageCount() - 1
+
+                for ii in xrange(self.GetPageCount()):
+                    newpages.append(self._parent.GetPage(ii))
+                    self._parent.bsizer.Detach(counter-ii)
+
+                cc = 0
+
+                self._parent._notebookpages = []
+
+                for jj in newrange:
+                    self._parent.bsizer.Add(newpages[jj], 1, wx.EXPAND | 
wx.ALL, 2)
+                    self._parent.bsizer.Show(cc, False)
+                    self._parent._notebookpages.append(newpages[jj])
+                    cc = cc + 1
+
+                self.DeletePage(self._tabID)
+
+                if enabled:
+                    if id == self.GetPageCount():
+                        self.AddPage(text, True, image)
+                    else:
+                        self.InsertPage(where, text, True, image)
+                else:
+                    if id == self.GetPageCount():
+                        self.AddPage(text, False, image)
+                    else:
+                        self.InsertPage(where, text, False, image)
+
+                self.SetPageImage(where, image)
+                self.SetPageText(where, text)
+                self.SetPageTextFont(where, font1)
+                self.SetPageTextSecondaryFont(where, font2)
+                self.SetPageTextColour(where, fontcolour)
+                self.SetPageColour(where, pagecolour)
+                self.EnablePage(where, enabled)
+                self.SetPageToolTip(where, tooltip, ontime, winsize)
+                self.SetPagePopupMenu(where, menu)
+                self.SetPageFirstGradientColour(where, firstcol)
+                self.SetPageSecondGradientColour(where, secondcol)
+                self._pages[where]._ishidden = ishidden
+
+                if isanimated and len(animatedimages) > 1:
+                    self.SetAnimationImages(where, animatedimages)
+                    self.StartAnimation(where, timer)
+
+                if enabled:
+                    self._parent.bsizer.Show(where, True)
+                else:
+                    sel = self.GetSelection()
+
+                    if sel == -1:
+                        sel = 0
+                    self._parent.bsizer.Show(where, False)
+                    self._parent.SetSelection(sel)
+                    self._parent.bsizer.Show(sel, True)
+
+                self._parent.bsizer.Layout()
+
+                self._parent.Thaw()
+
+            self._isdragging = False
+            self._olddragpos = -1
+            self._fromdnd = True
+            self.Refresh()
+            self._tabID = -1
+            self.SetCursor(wx.STANDARD_CURSOR)
+
+            return
+
+        if nPage >= 0 and where >= 0:
+            panel = oldNotebook.GetPage(nPage)
+
+            if panel:
+                eventOut = NotebookCtrlEvent(wxEVT_NOTEBOOKCTRL_PAGE_DND, 
oldNotebook.GetId())
+                eventOut.SetOldPosition(nPage)
+                eventOut.SetNewPosition(where)
+                eventOut.SetEventObject(oldNotebook)
+
+                if oldNotebook.GetEventHandler().ProcessEvent(eventOut):
+                    oldNotebook.nb._tabID = -1
+                    oldNotebook.nb._olddragpos = -1
+                    oldNotebook.SetCursor(wx.STANDARD_CURSOR)
+                    oldNotebook.Refresh()
+                    return
+
+                oldNotebook.Freeze()
+                infos = oldNotebook.GetPageInfo(nPage)
+
+                text = infos["text"]
+                image = infos["image"]
+                hidden = infos["ishidden"]
+
+                panel.Reparent(newNotebook)
+                newNotebook.InsertPage(where, panel, text, True, image, hidden)
+                newNotebook.SetPageInfo(where, infos)
+
+                oldNotebook.nb.DeletePage(nPage)
+
+                oldNotebook.bsizer.Detach(nPage)
+                oldNotebook.bsizer.Layout()
+                oldNotebook.sizer.Layout()
+
+                oldNotebook._notebookpages.pop(nPage)
+
+                oldNotebook.AdvanceSelection()
+
+                if oldNotebook.GetPageCount() == 0:
+                    if oldNotebook._style & NC_TOP:
+                        oldNotebook.sizer.Show(0, False)
+                        oldNotebook.sizer.Show(1, False)
+                    else:
+                        oldNotebook.sizer.Show(1, False)
+                        oldNotebook.sizer.Show(2, False)
+
+                    oldNotebook.sizer.Layout()
+
+                oldNotebook.Thaw()
+                newNotebook.Refresh()
+
+        return wx.DragMove
+
+
+    def OnLeaveWindow(self, event):
+        """ Handles The wx.EVT_LEAVE_WINDOW Events For TabCtrl. """
+
+        if self._enabledragging:
+            if self._isdragging:
+
+                page = self._parent.GetPage(self._tabID)
+                draginfo = NCDragInfo(page, self._tabID)
+                drginfo = cPickle.dumps(draginfo)
+                dataobject = 
wx.CustomDataObject(wx.CustomDataFormat("NotebookCtrl"))
+                dataobject.SetData(drginfo)
+                dragSource = wx.DropSource(self)
+                dragSource.SetData(dataobject)
+                dragSource.DoDragDrop(wx.Drag_DefaultMove)
+
+                self._isleaving = True
+                self.Refresh()
+
+        if self._istooltipshown:
+            self._tipwindow.Destroy()
+            self._istooltipshown = False
+            self.Refresh()
+
+        event.Skip()
+
+
+    def OnKeyDown(self, event):
+        """
+        Handles The wx.EVT_KEY_DOWN Event For TabCtrl. This Is Only Processed 
If
+        The User Navigate Through Tabs With Ctrl-Tab Keyboard Navigation.
+        """
+
+        if event.GetKeyCode() == wx.WXK_TAB:
+            if event.ControlDown():
+                sel = self.GetSelection()
+                if sel == self.GetPageCount() - 1:
+                    sel = 0
+                else:
+                    sel = sel + 1
+
+                while not self.IsPageEnabled(sel):
+                    sel = sel + 1
+                    if sel == self.GetPageCount() - 1:
+                        sel = 0
+
+                self._parent.SetSelection(sel)
+
+        event.Skip()
+
+
+    def AddPage(self, text, select=False, img=-1, hidden=False):
+        """
+        Add A Page To The Notebook, With Following Parameters:
+        - text: The Tab Text;
+        - select: Whether The Page Should Be Selected Or Not;
+        - img: Specifies The Optional Image Index For The New Page.
+        """
+
+        self._pages.append(TabbedPage(text, img, hidden))
+        self._somethingchanged = True
+
+        self._firsttime = True
+        self._timers.append(wx.Timer(self))
+
+        if select or self.GetSelection() == -1:
+           self._selection = self.GetPageCount() - 1
+
+        self.Refresh()
+
+
+    def InsertPage(self, nPage, text, select=False, img=-1, hidden=False):
+        """
+        Insert A Page Into The Notebook, With Following Parameters:
+        - nPage: Specifies The Position For The New Page;
+        - text: The Tab Text;
+        - select: Whether The Page Should Be Selected Or Not;
+        - img: Specifies The Optional Image Index For The New Page.
+        """
+
+        if nPage < 0 or (self.GetSelection() >= 0 and nPage >= 
self.GetPageCount()):
+            raise "\nERROR: Invalid Notebook Page In InsertPage: (" + 
str(nPage) + ")"
+
+        oldselection = self.GetSelection()
+
+        self._pages.insert(nPage, TabbedPage(text, img, hidden))
+        self._timers.insert(nPage, wx.Timer(self))
+
+        self._somethingchanged = True
+        self._firsttime = True
+
+        if select or self.GetSelection() == -1:
+            self._selection = nPage
+            self.SetSelection(nPage)
+        else:
+            if nPage <= oldselection:
+                self._selection = self._selection + 1
+
+        self.Refresh()
+
+
+    def DeleteAllPages(self):
+        """ Deletes All NotebookCtrl Pages. """
+
+        for tims in self._timers:
+            if tims.IsRunning():
+                tims.Stop()
+
+            tims.Destroy()
+
+        self._timers = []
+        self._pages = []
+        self._selection = -1
+        self._somethingchanged = True
+        self._firsttime = True
+        self.Refresh()
+
+
+    def DeletePage(self, nPage, oncontinue=True):
+        """ Deletes The Page nPage, And The Associated Window. """
+
+        if nPage < 0 or nPage >= self.GetPageCount():
+            raise "\nERROR: Invalid Notebook Page In DeletePage: (" + 
str(nPage) + ")"
+
+        oldselection = self.GetSelection()
+
+        self._pages.pop(nPage)
+
+        if self._timers[nPage].IsRunning():
+            self._timers[nPage].Stop()
+
+        self._timers[nPage].Destroy()
+
+        if self._istooltipshown:
+            self._tipwindow.Destroy()
+            self._istooltipshown = False
+
+        if not oncontinue:
+            self._somethingchanged = True
+            self._firsttime = True
+            self.Refresh()
+            return
+
+        if nPage < self._selection:
+            self._selection = self._selection - 1
+        elif self._selection == nPage and self._selection == 
self.GetPageCount():
+            self._selection = self._selection - 1
+        else:
+            self._selection = oldselection
+
+        self._somethingchanged = True
+        self._firsttime = True
+        self.Refresh()
+
+
+    def SetSelection(self, nPage):
+        """
+        Sets The Current Tab Selection To The Given nPage. This Call Generates 
The
+        EVT_NOTEBOOKCTRL_PAGE_CHANGING Event.
+        """
+
+        if nPage < 0 or nPage >= self.GetPageCount():
+            raise "\nERROR: Invalid Notebook Page In SetSelection: (" + 
str(nPage) + ")"
+
+        oldselection = self._selection
+
+        if nPage != self._selection:
+
+            if not self.IsPageEnabled(nPage):
+                return
+
+            eventOut = NotebookCtrlEvent(wxEVT_NOTEBOOKCTRL_PAGE_CHANGING, 
self.GetId())
+            eventOut.SetSelection(nPage)
+            eventOut.SetOldSelection(self._selection)
+            eventOut.SetEventObject(self)
+
+            if not self.GetEventHandler().ProcessEvent(eventOut):
+
+                self._firsttime = False
+                # Program Allows The Page Change
+                self._selection = nPage
+                eventOut.SetEventType(wxEVT_NOTEBOOKCTRL_PAGE_CHANGED)
+                eventOut.SetOldSelection(self._selection)
+                self.GetEventHandler().ProcessEvent(eventOut)
+
+                if oldselection != -1:
+                    self._parent.bsizer.Show(oldselection, False)
+
+                self.EnsureVisible(self._selection)
+                self._parent.bsizer.Show(self._selection, True)
+                self._parent.bsizer.Layout()
+
+                self.Refresh()
+
+                self._shown = nPage
+
+
+    def EnsureVisible(self, selection):
+
+        if self.GetPageCount() < 2:
+            return
+
+        if not self.HasSpinButton():
+            return
+
+        fullrect = self.GetClientSize()
+        count = self._tabvisible[0:selection].count(0)
+        currect = self._tabrect[selection-self._firstvisible-count]
+
+        spinval = self._spinbutton.GetValue()
+        firstrect = self._initrect[spinval]
+        xpos = currect.x
+        xsize = currect.width
+        torefresh = 0
+
+        while xpos + xsize > fullrect[0] - self._spinbutton.GetSize()[0]:
+
+            xpos = xpos - firstrect.width
+
+            if not self._enablehiding:
+                spinval = spinval + 1
+            else:
+                oldspinval = spinval
+                spinval = spinval + self._tabvisible[0:selection].count(0)
+                if spinval == oldspinval:
+                    spinval = spinval + 1
+
+                if spinval >= len(self._initrect):
+                    spinval = spinval - 1
+
+            firstrect = self._initrect[spinval]
+
+            self._spinbutton.OnSpin(spinval)
+            self._spinbutton.SetValue(spinval)
+
+            torefresh = 1
+
+        if torefresh:
+            self.Refresh()
+
+
+    def GetPageCount(self):
+        """ Returns The Number Of Pages In NotebookCtrl. """
+
+        return len(self._pages)
+
+
+    def GetSelection(self):
+        """ Returns The Current Selection. """
+
+        return self._selection
+
+
+    def GetImageList(self):
+        """ Returns The Image List Associated With The NotebookCtrl. """
+
+        return self._imglist
+
+
+    def SetImageList(self, imagelist):
+        """ Associate An Image List To NotebookCtrl. """
+
+        self._imglist = imagelist
+        self._grayedlist = wx.ImageList(16, 16, True, 0)
+
+        for ii in xrange(imagelist.GetImageCount()):
+
+            bmp = imagelist.GetBitmap(ii)
+            image = wx.ImageFromBitmap(bmp)
+            image = GrayOut(image)
+            newbmp = wx.BitmapFromImage(image)
+            self._grayedlist.Add(newbmp)
+
+
+    def AssignImageList(self, imagelist):
+        """ Associate An Image List To NotebookCtrl. """
+
+        self._imglist = imagelist
+        self._grayedlist = wx.ImageList(16, 16, True, 0)
+
+        for ii in xrange(imagelist.GetImageCount()):
+
+            bmp = imagelist.GetBitmap(ii)
+            image = wx.ImageFromBitmap(bmp)
+            image = GrayOut(image)
+            newbmp = wx.BitmapFromImage(image)
+            self._grayedlist.Add(newbmp)
+
+
+    def GetPadding(self):
+        """ Returns The (Horizontal, Vertical) Padding Of The Text Inside 
Tabs. """
+
+        return self._padding
+
+
+    def SetPadding(self, padding):
+        """ Sets The (Horizontal, Vertical) Padding Of The Text Inside Tabs. 
"""
+
+        self._padding = padding
+        self._somethingchanged = True
+        self._firsttime = True
+        self.Refresh()
+
+
+    def GetPageText(self, nPage):
+        """ Returns The String For The Given Page nPage. """
+
+        if nPage < 0 or nPage >= self.GetPageCount():
+            raise "\nERROR: Invalid Notebook Page In GetPageText: (" + 
str(nPage) + ")"
+
+        return self._pages[nPage]._text
+
+
+    def SetPageText(self, nPage, text):
+        """ Sets The String For The Given Page nPage. """
+
+        if nPage < 0 or nPage >= self.GetPageCount():
+            raise "\nERROR: Invalid Notebook Page In SetPageText: (" + 
str(nPage) + ")"
+
+        if self._pages[nPage]._text != text:
+            self._pages[nPage]._text = text
+            self._somethingchanged = True
+            self._firsttime = True
+            self.Refresh()
+
+
+    def GetPageImage(self, nPage):
+        """ Returns The Image Index For The Given Page nPage. """
+
+        if nPage < 0 or nPage >= self.GetPageCount():
+            raise "\nERROR: Invalid Notebook Page In GetPageImage: (" + 
str(nPage) + ")"
+
+        return self._pages[nPage]._image
+
+
+    def SetPageImage(self, nPage, img):
+        """ Sets The Image Index For The Given Page nPage. """
+
+        if nPage < 0 or nPage >= self.GetPageCount():
+            raise "\nERROR: Invalid Notebook Page In SetPageImage: (" + 
str(nPage) + ")"
+
+        if self._pages[nPage]._image != img:
+            self._pages[nPage]._image = img
+            self._somethingchanged = True
+            self._firsttime = True
+            self.Refresh()
+
+
+    def SetPageTextFont(self, nPage, font=None):
+        """ Sets The Primary Font For The Given Page nPage. """
+
+        if nPage < 0 or nPage >= self.GetPageCount():
+            raise "\nERROR: Invalid Notebook Page In SetPageTextFont: (" + 
str(nPage) + ")"
+
+        if font is None:
+            font = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
+
+        normalfont = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
+
+        self._pages[nPage]._font = font
+
+        if font == normalfont:
+            self._parent.GetSizer().Layout()
+            self._somethingchanged = True
+            self._firsttime = True
+            self.Refresh()
+            return
+
+        dc = wx.ClientDC(self)
+        dc.SetFont(font)
+        w1, h1 = dc.GetTextExtent("Aq")
+        dc.SetFont(normalfont)
+        wn, hn = dc.GetTextExtent("Aq")
+        w2, h2 = (0, 0)
+
+        if hasattr(self._pages[nPage], "_secondaryfont"):
+            dc.SetFont(self._pages[nPage]._secondaryfont)
+            w2, h2 = dc.GetTextExtent("Aq")
+
+        h = max(h1, h2)
+
+        if h < hn:
+            self._somethingchanged = True
+            self._firsttime = True
+            self.Refresh()
+            return
+
+        if h + 2*self._padding.y < 24:
+            newheight = 24
+        else:
+            newheight = h + 2*self._padding.y
+
+        oldsize = self.GetSize()[1]
+
+        if newheight < oldsize:
+            newheight = oldsize
+
+        self.SetBestSize((-1, newheight))
+        self._parent.GetSizer().Layout()
+        self._somethingchanged = True
+        self._firsttime = True
+        self.Refresh()
+
+
+    def SetTabHeight(self, height=28):
+        """ Sets The Tabs Height. """
+
+        self.SetBestSize((-1, height))
+        self._bestsize = height
+
+
+    def SetControlBackgroundColour(self, colour=None):
+        """ Sets The TabCtrl Background Colour (Behind The Tabs). """
+
+        if colour is None:
+            colour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE)
+
+        self.SetBackgroundColour(colour)
+        self.Refresh()
+
+
+    def GetPageTextFont(self, nPage):
+        """ Returns The Primary Font For The Given Page nPage. """
+
+        if nPage < 0 or nPage >= self.GetPageCount():
+            raise "\nERROR: Invalid Notebook Page In GetPageTextFont: (" + 
str(nPage) + ")"
+
+        return self._pages[nPage]._font
+
+
+    def SetPageTextSecondaryFont(self, nPage, font=None):
+        """ Sets The Secondary Font For The Given Page nPage. """
+
+        if nPage < 0 or nPage >= self.GetPageCount():
+            raise "\nERROR: Invalid Notebook Page In SetPageTextSecondaryFont: 
(" + str(nPage) + ")"
+
+        if font is None:
+            font = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
+
+        normalfont = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
+
+        self._pages[nPage]._secondaryfont = font
+
+        if font == normalfont:
+            self._somethingchanged = True
+            self._firsttime = True
+            self.Refresh()
+            return
+
+        dc = wx.ClientDC(self)
+        dc.SetFont(font)
+        w1, h1 = dc.GetTextExtent("Aq")
+        dc.SetFont(normalfont)
+        wn, hn = dc.GetTextExtent("Aq")
+        w2, h2 = (0, 0)
+
+        if hasattr(self._pages[nPage], "_font"):
+            dc.SetFont(self._pages[nPage]._font)
+            w2, h2 = dc.GetTextExtent("Aq")
+
+        h = max(h1, h2)
+
+        if h < hn:
+            self._somethingchanged = True
+            self._firsttime = True
+            self.Refresh()
+            return
+
+        if h + 2*self._padding.y < 24:
+            newheight = 24
+        else:
+            newheight = h + 2*self._padding.y
+
+        oldsize = self.GetSize()[1]
+
+        if newheight < oldsize:
+            newheight = oldsize
+
+        self.SetBestSize((-1, newheight))
+        self._parent.GetSizer().Layout()
+
+        self._somethingchanged = True
+        self._firsttime = True
+        self.Refresh()
+
+
+    def GetPageTextSecondaryFont(self, nPage):
+        """ Returns The Secondary Font For The Given Page nPage. """
+
+        if nPage < 0 or nPage >= self.GetPageCount():
+            raise "\nERROR: Invalid Notebook Page In GetPageTextSecondaryFont: 
(" + str(nPage) + ")"
+
+        return self._pages[nPage]._secondaryfont
+
+
+    def SetPageTextColour(self, nPage, colour=None):
+        """ Sets The Text Colour For The Given Page nPage. """
+
+        if nPage < 0 or nPage >= self.GetPageCount():
+            raise "\nERROR: Invalid Notebook Page In SetPageTextColour: (" + 
str(nPage) + ")"
+
+        if colour is None:
+            colour = wx.BLACK
+
+        self._pages[nPage]._pagetextcolour = colour
+        self._somethingchanged = True
+        self.Refresh()
+
+
+    def GetPageTextColour(self, nPage):
+        """ Returns The Text Colour For The Given Page nPage. """
+
+        if nPage < 0 or nPage >= self.GetPageCount():
+            raise "\nERROR: Invalid Notebook Page In GetPageTextColour: (" + 
str(nPage) + ")"
+
+        return self._pages[nPage]._pagetextcolour
+
+
+    def SetPageColour(self, nPage, colour=None):
+        """ Sets The Tab Background Colour For The Given Page nPage. """
+
+        if nPage < 0 or nPage >= self.GetPageCount():
+            raise "\nERROR: Invalid Notebook Page In SetPageColour: (" + 
str(nPage) + ")"
+
+        if colour is None:
+            colour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNFACE)
+
+        self._pages[nPage]._pagecolour = colour
+        self._somethingchanged = True
+        self.Refresh()
+
+
+    def GetPageColour(self, nPage):
+        """ Returns The Tab Background Colour For The Given Page nPage. """
+
+        if nPage < 0 or nPage >= self.GetPageCount():
+            raise "\nERROR: Invalid Notebook Page In GetPageColour: (" + 
str(nPage) + ")"
+
+        return self._pages[nPage]._pagecolour
+
+
+    def EnablePage(self, nPage, enable=True):
+        """ Enable/Disable The Given Page nPage. """
+
+        if nPage < 0 or nPage >= self.GetPageCount():
+            raise "\nERROR: Invalid Notebook Page In EnablePage: (" + 
str(nPage) + ")"
+
+        self._pages[nPage]._enable = enable
+
+        if not enable and self.GetSelection() == nPage:
+            defpage = self.GetDefaultPage()
+            if defpage < 0:
+                self.AdvanceSelection()
+            else:
+                if defpage >= self.GetPageCount():
+                    self.AdvanceSelection()
+                else:
+                    if defpage == nPage:
+                        self.AdvanceSelection()
+                    else:
+                        self.SetSelection(defpage)
+
+        self.Refresh()
+
+
+    def IsPageEnabled(self, nPage):
+        """ Returns Whether A Page Is Enabled Or Not. """
+
+        if nPage < 0 or nPage >= self.GetPageCount():
+            raise "\nERROR: Invalid Notebook Page In IsPageEnabled: (" + 
str(nPage) + ")"
+
+        return self._pages[nPage]._enable
+
+
+    def SetHighlightSelection(self, highlight=True):
+        """ Globally Enables/Disables Tab Highlighting On Tab Selection. """
+
+        self._highlight = highlight
+        self.Refresh()
+
+
+    def GetHighlightSelection(self):
+        """ Returns Globally Enable/Disable State For Tab Highlighting On Tab 
Selection. """
+
+        return self._highlight
+
+
+    def SetUseFocusIndicator(self, focus=True):
+        """ Globally Enables/Disables Tab Focus Indicator. """
+
+        self._usefocus = focus
+        self.Refresh()
+
+
+    def GetUseFocusIndicator(self):
+        """ Returns Globally Enable/Disable State For Tab Focus Indicator. """
+
+        return self._usefocus
+
+
+    def SetPageToolTip(self, nPage, tooltip="", timer=500, winsize=400):
+        """
+        Sets A ToolTip For The Given Page nPage, With The Following Parameters:
+        - nPage: The Given Page;
+        - tooltip: The ToolTip String;
+        - timer: The Timer After Which The Tip Window Is Popped Up;
+        - winsize: The Maximum Width Of The Tip Window.
+        """
+
+        if nPage < 0 or nPage >= self.GetPageCount():
+            raise "\nERROR: Invalid Notebook Page In SetPageToolTip: (" + 
str(nPage) + ")"
+
+        self._pages[nPage]._tooltip = tooltip
+        self._pages[nPage]._tooltiptime = timer
+        self._pages[nPage]._winsize = winsize
+
+
+    def GetPageToolTip(self, nPage):
+        """ Returns A Tuple With All Page ToolTip Parameters. """
+
+        if nPage < 0 or nPage >= self.GetPageCount():
+            raise "\nERROR: Invalid Notebook Page In GetPageToolTip: (" + 
str(nPage) + ")"
+
+        return self._pages[nPage]._tooltip, self._pages[nPage]._tooltiptime, \
+               self._pages[nPage]._winsize
+
+
+    def EnableToolTip(self, show=True):
+        """ Globally Enables/Disables Tab ToolTips. """
+
+        self._showtooltip = show
+
+        if show:
+            try:
+                wx.PopupWindow(self)
+                self.TransientTipWindow = TransientTipWindow
+
+            except NotImplementedError:
+
+                self.TransientTipWindow = macTransientTipWindow
+
+        else:
+            if self._istooltipshown:
+                self._tipwindow.Destroy()
+                self._istooltipshown = False
+                self.Refresh()
+
+            if self._tiptimer.IsRunning():
+                self._tiptimer.Stop()
+
+
+    def GetToolTipBackgroundColour(self):
+        """ Returns The ToolTip Window Background Colour. """
+
+        return self._backtooltip
+
+
+    def SetToolTipBackgroundColour(self, colour=None):
+        """ Sets The ToolTip Window Background Colour. """
+
+        if colour is None:
+            colour = wx.Colour(255, 255, 230)
+
+        self._backtooltip = colour
+
+
+    def EnableTabGradients(self, enable=True):
+        """ Globally Enables/Disables Drawing Of Gradient Coloured Tabs For 
Each Tab. """
+
+        self._usegradients = enable
+
+        if enable:
+            self._tabstyle.ResetDefaults()
+            self._selstyle.ResetDefaults()
+
+        self.Refresh()
+
+
+    def SetPageFirstGradientColour(self, nPage, colour=None):
+        """ Sets The Single Tab First Gradient Colour. """
+
+        if nPage < 0 or nPage >= self.GetPageCount():
+            raise "\nERROR: Invalid Notebook Page In 
SetPageFirstGradientColour: (" + str(nPage) + ")"
+
+        if colour is None:
+            colour = wx.WHITE
+
+        self._pages[nPage]._firstcolour = colour
+        self.Refresh()
+
+
+    def SetPageSecondGradientColour(self, nPage, colour=None):
+        """ Sets The Single Tab Second Gradient Colour. """
+
+        if nPage < 0 or nPage >= self.GetPageCount():
+            raise "\nERROR: Invalid Notebook Page In 
SetPageSecondGradientColour: (" + str(nPage) + ")"
+
+        if colour is None:
+            color = self._pages[nPage]._firstcolour
+            r, g, b = int(color.Red()), int(color.Green()), int(color.Blue())
+            color = ((r >> 1) + 20, (g >> 1) + 20, (b >> 1) + 20)
+            colour = wx.Colour(color[0], color[1], color[2])
+
+        self._pages[nPage]._secondcolour = colour
+        self.Refresh()
+
+
+    def GetPageFirstGradientColour(self, nPage):
+        """ Returns The Single Tab First Gradient Colour. """
+
+        if nPage < 0 or nPage >= self.GetPageCount():
+            raise "\nERROR: Invalid Notebook Page In 
GetPageFirstGradientColour: (" + str(nPage) + ")"
+
+        return self._pages[nPage]._firstcolour
+
+
+    def GetPageSecondGradientColour(self, nPage):
+        """ Returns The Single Tab Second Gradient Colour. """
+
+        if nPage < 0 or nPage >= self.GetPageCount():
+            raise "\nERROR: Invalid Notebook Page In 
GetPageSecondGradientColour: (" + str(nPage) + ")"
+
+        return self._pages[nPage]._secondcolour
+
+
+    def CancelTip(self):
+        """ Destroys The Tip Window (Probably You Won't Need This One). """
+
+        if self._istooltipshown:
+            self._istooltipshown = False
+            self._tipwindow.Destroy()
+            self.Refresh()
+
+
+    def AdvanceSelection(self, forward=True):
+        """
+        Cycles Through The Tabs. The Call To This Function Generates The
+        EVT_NOTEBOOKCTRL_PAGE_CHANGING Event.
+        """
+
+        if self.GetPageCount() <= 1:
+            return
+
+        sel = self.GetSelection()
+        count = 0
+
+        if forward:
+            if sel == self.GetPageCount() - 1:
+                sel = 0
+            else:
+                sel = sel + 1
+
+            while not self.IsPageEnabled(sel) or \
+                  (self._enablehiding and self._pages[sel]._ishidden):
+
+                count = count + 1
+                sel = sel + 1
+
+                if self._enablehiding and self._pages[sel]._ishidden:
+                    count = count + 1
+                    sel = sel + 1
+
+                if sel == self.GetPageCount() - 1:
+                    sel = 0
+
+                if count > self.GetPageCount() + 1:
+                    return None
+
+        else:
+            if sel == 0:
+                sel = self.GetPageCount() - 1
+            else:
+                sel = sel - 1
+
+            while not self.IsPageEnabled(sel):
+                count = count + 1
+                sel = sel - 1
+                if sel == 0:
+                    sel = self.GetPageCount() - 1
+
+                if count > self.GetPageCount() + 1:
+                    return None
+
+        self._parent.SetSelection(sel)
+
+
+    def SetDefaultPage(self, defaultpage=-1):
+        """
+        Sets The Default Page That Will Be Selected When An Active And Selected
+        Tab Is Made Inactive.
+        """
+
+        if defaultpage >= self.GetPageCount():
+            raise "\nERROR: Invalid Notebook Page In SetDefaultPage: (" + 
str(defaultpage) + ")"
+
+        self._defaultpage = defaultpage
+
+
+    def GetDefaultPage(self):
+        """ Returns The Default Page. """
+
+        return self._defaultpage
+
+
+    def UpdateSpinButton(self):
+        """ Update The NotebookSpinButton. Used Internally. """
+
+        count = self.GetPageCount()
+
+        if count == 0:
+            return
+
+        nbsize = []
+        nbsize.append(self._initrect[-1][0] + self._initrect[-1][2])
+        nbsize.append(self._initrect[-1][1] + self._initrect[-1][3])
+        clsize = self.GetClientSize()
+
+        if nbsize[0] > clsize[0]:
+            if not hasattr(self, "_spinbutton"):
+                self._spinbutton = NotebookSpinButton(self, pos=(10000,10000))
+                self._spinbutton.SetValue(0)
+                self._originalspinsize = self._spinbutton.GetSize()
+
+            sbsize = self._spinbutton.GetSize()
+            xpos = clsize[0] - sbsize[0]
+            ypos = clsize[1] - sbsize[1]
+
+            if self.HasMenuButton():
+                self._spinbutton.SetSize((-1, 16))
+            else:
+                self._spinbutton.SetSize(self._originalspinsize)
+
+            self._spinbutton.Move((xpos, ypos))
+            self._spinbutton.Show()
+            self._spinbutton.SetRange(0, count-1)
+
+        else:
+
+            if hasattr(self, "_spinbutton") and self._spinbutton.IsShown():
+                self._spinbutton.Hide()
+                self._spinbutton.SetValue(0)
+
+
+    def HasSpinButton(self):
+        """ Returns Wheter The NotebookSpinButton Exists And Is Shown. """
+
+        return hasattr(self, "_spinbutton") and self._spinbutton.IsShown()
+
+
+    def IsLastVisible(self):
+        """ Returns Whether The Last Tab Is Visible Or Not. """
+
+        if self.HasSpinButton():
+            lastpos = self._tabrect[-1][0] + self._tabrect[-1][2]
+            if lastpos < self._spinbutton.GetPosition()[0]:
+                return True
+
+        return False
+
+
+    def UpdateMenuButton(self, show):
+        """ Updates The Notebook Menu Button To Show/Hide Tabs. Used 
Internally. """
+
+        count = self.GetPageCount()
+
+        if count == 0:
+            return
+
+        if not hasattr(self, "_initrect"):
+            return
+
+        if not show and not hasattr(self, "_menubutton"):
+            return
+
+        if not hasattr(self, "_menubutton"):
+            self._menubutton = NotebookMenuButton(self, pos=(10000,10000))
+
+        sbsize = self._menubutton.GetSize()
+        nbsize = []
+        nbsize.append(self._initrect[-1][0] + self._initrect[-1][2])
+        nbsize.append(self._initrect[-1][1] + self._initrect[-1][3])
+        clsize = self.GetClientSize()
+
+        xpos = clsize[0] - sbsize[0]
+        ypos = clsize[1] - sbsize[1]
+
+        if self.HasSpinButton():
+            self._menubutton.Move((xpos-1, ypos-16))
+        else:
+            self._menubutton.Move((xpos-1, ypos-1))
+
+        self._menubutton.Show(show)
+
+
+    def HasMenuButton(self):
+        """ Returns Wheter The NotebookMenuButton Exists And Is Shown. """
+
+        return hasattr(self, "_menubutton") and self._menubutton.IsShown()
+
+
+    def HideTab(self, nPage, hide=True):
+        """ Hides A Tab In The NotebookCtrl. """
+
+        if hide:
+            self._pages[nPage]._ishidden = True
+        else:
+            self._pages[nPage]._ishidden = False
+
+        if nPage == self.GetSelection():
+            self.AdvanceSelection()
+
+        self._firsttime = True
+        self.Refresh()
+
+
+    def HitTest(self, point, flags=0):
+        """
+        Standard NotebookCtrl HitTest() Method. If Called With 2 Outputs, It
+        Returns The Page Clicked (If Any) And One Of These Flags:
+
+        NC_HITTEST_NOWHERE = 0   ==> Hit Not On Tab
+        NC_HITTEST_ONICON  = 1   ==> Hit On Icon
+        NC_HITTEST_ONLABEL = 2   ==> Hit On Label
+        NC_HITTEST_ONITEM  = 4   ==> Hit Generic, On Item
+        NC_HITTEST_ONX = 8       ==> Hit On Closing "X" On Every Page
+        """
+
+        mirror = self._style & NC_BOTTOM
+        drawx, dxstyle = self.GetDrawX()
+        size = self.GetSize()
+        dc = wx.ClientDC(self)
+
+        height = self._tabrect[0].height
+
+        if flags:
+            flags = wx.NB_HITTEST_NOWHERE
+
+        if point.x <= 0 or point.x >= size.x:
+            if flags:
+                return wx.NOT_FOUND, flags
+            else:
+                return wx.NOT_FOUND
+
+        if not mirror and \
+           (point.y <= size.y - height or point.y >= size.y):
+            if flags:
+                return wx.NOT_FOUND, flags
+            else:
+                return wx.NOT_FOUND
+
+        if mirror and (point.y <= 0 or point.y >= height + self._padding.y*2):
+            if flags:
+                return wx.NOT_FOUND, flags
+            else:
+                return wx.NOT_FOUND
+
+        posx = 3
+        maxwidth = max(self._maxtabwidths)
+
+        if drawx:
+            if dxstyle == 1:
+                mins = min(self._padding.x, self._padding.y) + 1
+                mins = min(mins, 6)
+
+        if drawx:
+            if dxstyle == 1:
+                xxspace = self._padding.x/2
+            else:
+                xxspace = self._padding.x + self._maxtextheight
+        else:
+            xxspace = 0
+
+        for ii in xrange(self._firstvisible, self.GetPageCount()):
+
+            if not self._enablehiding or not self._pages[ii]._ishidden:
+
+                bmp = wx.NullBitmap
+
+                thefont = self.GetPageTextFont(ii)
+                dc.SetFont(thefont)
+                width, pom = dc.GetTextExtent(self.GetPageText(ii))
+
+                if self.GetPageImage(ii) >= 0:
+                    bmp = self.GetImageList().GetBitmap(ii)
+
+                if self._style & NC_FIXED_WIDTH:
+                    width = maxwidth
+
+                space = self._padding.x + self._incrtext[ii]
+
+                if bmp.Ok():
+                    space = space + bmp.GetWidth() + self._padding.x
+
+                if point.x > posx and point.x < posx + width + space + 
self._padding.x + xxspace:
+                    if flags:
+                        flags = NC_HITTEST_ONITEM
+
+                    #onx attempt
+                    if drawx:
+                        count = self._tabvisible[0:ii].count(0)
+                        if flags and 
self._xrect[ii-self._firstvisible-count].Inside(point):
+                            flags = NC_HITTEST_ONX
+
+                   #onicon attempt
+                    if flags and bmp.Ok() and point.x >= posx + 
self._padding.x and \
+                       point.x <= posx + bmp.GetWidth() + self._padding.x:
+
+                        if not mirror and point.y >= size.y - height \
+                           and point.y <= size.y - self._padding.y:
+
+                            flags = NC_HITTEST_ONICON
+
+                        elif mirror and point.y >= self._padding.y and \
+                             point.y <= self._padding.y + bmp.GetHeight():
+
+                            flags = NC_HITTEST_ONICON
+
+                   #onlabel attempt
+                    elif flags and point.x >= posx + space and \
+                         point.x <= posx + space + width:
+
+                        if not mirror and point.y >= size.y - height \
+                           and point.y <= size.y - self._padding.y:
+                            flags = NC_HITTEST_ONLABEL
+
+                        elif mirror and point.y >= self._padding.y and \
+                             point.y <= height:
+                            flags = NC_HITTEST_ONLABEL
+
+                    if flags:
+                        return ii, flags
+                    else:
+                        return ii
+
+                posx = posx + width + space + self._padding.x + 
self._spacetabs + xxspace
+
+        if flags:
+            return wx.NOT_FOUND, flags
+        else:
+            return wx.NOT_FOUND
+
+
+    def EnableDragAndDrop(self, enable=True):
+        """ Globall Enables/Disables Tabs Drag And Drop. """
+
+        self._enabledragging = enable
+
+
+    def EnableHiding(self, enable=True):
+        """ Globally Enables/Disables Hiding On Tabs In Runtime. """
+
+        self._enablehiding = enable
+        self.UpdateMenuButton(enable)
+
+        wx.FutureCall(1000, self.UpdateMenuButton, enable)
+
+
+    def SetAnimationImages(self, nPage, imgarray):
+        """
+        Sets An Animation List Associated To The Given Page nPage, With The 
Following
+        Parameters:
+        - nPage: The Given Page;
+        - imgarray: A List Of Image Indexes Of Images Inside The ImageList 
Associated
+          To NotebookCtrl.
+        """
+
+        if nPage < 0 or nPage >= self.GetPageCount():
+            raise "\nERROR: Invalid Notebook Page In SetAnimationImages: (" + 
str(nPage) + ")"
+
+        if not imgarray:
+            raise "\nERROR: Invalid Image Array In SetAnimationImages: (" + 
repr(imgarray) + ")"
+
+        if min(imgarray) < 0:
+            raise "\nERROR: Invalid Image Array In SetAnimationImages: 
(Min(ImgArray) = " + \
+                  str(min(imgarray)) + " < 0)"
+
+        if max(imgarray) > self.GetImageList().GetImageCount() - 1:
+            raise "\nERROR: Invalid Image Array In SetAnimationImages: 
(Max(ImgArray) = " + \
+                  str(max(imgarray)) + " > " + 
str(self.GetImageList().GetImageCount()-1) + ")"
+
+        self._pages[nPage]._animationimages = imgarray
+
+
+    def GetAnimationImages(self, nPage):
+        """ Returns The Animation Images List Associated To The Given Page 
nPage. """
+
+        if nPage < 0 or nPage >= self.GetPageCount():
+            raise "\nERROR: Invalid Notebook Page In GetAnimationImages: (" + 
str(nPage) + ")"
+
+        return self._pages[nPage]._animationimages
+
+
+    def AnimateTab(self, event):
+        """ Called When The Refreshing Animation Timer Expires. Used 
Internally"""
+
+        obj = event.GetEventObject()
+        nPage = self._timers.index(obj)
+
+        if not self.IsPageEnabled(nPage):
+            return
+
+        indx = self.GetPageImage(nPage)
+        images = self.GetAnimationImages(nPage)
+        myindx = images.index(indx)
+
+        if indx == images[-1]:
+            myindx = -1
+
+        myindx = myindx + 1
+
+        self.SetPageImage(nPage, images[myindx])
+
+
+    def StartAnimation(self, nPage, timer=500):
+        """ Starts The Animation On The Given Page, With Refreshing Time Rate 
"timer". """
+
+        if nPage < 0 or nPage >= self.GetPageCount():
+            raise "\nERROR: Invalid Notebook Page In StartAnimation: (" + 
str(nPage) + ")"
+
+        images = self.GetAnimationImages(nPage)
+
+        if not images:
+            raise "\nERROR: No Images Array Defined For Page: (" + str(nPage) 
+ ")"
+
+        if len(images) == 1:
+            raise "\nERROR: Impossible To Animate Tab: " + str(nPage) + " With 
Only One Image"
+
+        self._timers[nPage].Start(timer)
+
+
+    def StopAnimation(self, nPage):
+        """ Stops The Animation On The Given Page nPage. """
+
+        if nPage < 0 or nPage >= self.GetPageCount():
+            raise "\nERROR: Invalid Notebook Page In StopAnimation: (" + 
str(nPage) + ")"
+
+        if self._timers[nPage].IsRunning():
+            self._timers[nPage].Stop()
+
+
+    def SetDrawX(self, drawx=True, style=1, image1=None, image2=None):
+        """
+        Globally Enables/Disables The Drawing Of A Closing "X" In The Tab. 
Depending
+        On The "style" Parameter, You Will Have:
+        - style = 1: Small "X" At The Top-Right Of The Tab;
+        - style = 2: Bigger "X" In The Middle Vertical Of The Tab (Like Opera 
Notebook);
+        - style = 3: Custom "X" Image Is Drawn On Tabs.
+        """
+
+        self._drawx = drawx
+        self._drawxstyle = style
+
+        if style == 3:
+            self._imglist2 = wx.ImageList(16, 16, True, 0)
+            self._imglist2.Add(image1)
+            self._imglist2.Add(image2)
+
+        self.Refresh()
+
+
+    def GetDrawX(self):
+        """
+        Returns The Enable/Disable State Of Drawing Of A Small "X" At The 
Top-Right Of
+        Every Page.
+        """
+
+        return self._drawx, self._drawxstyle
+
+
+    def GetInsideTab(self, pt):
+        """ Returns The Tab On Which The Mouse Is Hovering On. """
+
+        count = 0
+
+        for tabs in self._tabrect:
+            if tabs.Inside(pt):
+                return count
+
+            count = count + 1
+
+        return -1
+
+
+    def GetInsideX(self, pt):
+        """ Returns The Tab On Which The Mouse Is Hovering On The "X" Button. 
"""
+
+        count = 0
+
+        for rects in self._xrect:
+            if rects.Inside(pt):
+                return count
+
+            count = count + 1
+
+        return -1
+
+
+    def SetImageToCloseButton(self, convert=True):
+        """ Set Whether The Tab Icon Should Be Converted To The Close Button 
Or Not. """
+
+        self._convertimage = convert
+
+
+    def GetImageToCloseButton(self):
+        """ Get Whether The Tab Icon Should Be Converted To The Close Button 
Or Not. """
+
+        return self._convertimage
+
+
+    def ConvertImageToCloseButton(self, page):
+        """ Globally Converts The Page Image To The "Opera" Style Close 
Button. """
+
+        bmpindex = self.GetPageImage(page)
+        if  bmpindex < 0:
+            return
+
+        tabrect = self._tabrect[page]
+        size = self.GetSize()
+
+        maxfont = self._maxfont
+
+        dc = wx.ClientDC(self)
+
+        dc.SetFont(maxfont)
+        pom, height = dc.GetTextExtent("Aq")
+
+        bmp = self._imglist.GetBitmap(bmpindex)
+
+        bmpposx = tabrect.x + self._padding.x
+        bmpposy = size.y - (height + 2*self._padding.y + bmp.GetHeight())/2 - 1
+
+        ypos = size.y - height - self._padding.y*2
+        ysize = height + self._padding.y*2 + 3
+
+        if page == self.GetSelection():
+            bmpposx = bmpposx + 1
+            bmpposy = bmpposy - 1
+            ypos = ypos - 3
+            ysize = ysize + 2
+
+        colour = self.GetPageColour(page)
+        bmprect = wx.Rect(bmpposx, bmpposy, bmp.GetWidth()+self._padding.x, 
bmp.GetHeight())
+
+        dc.SetBrush(wx.Brush(colour))
+        dc.SetPen(wx.TRANSPARENT_PEN)
+        dc.DrawRectangleRect(bmprect)
+
+        colour = self.GetPageTextColour(page)
+
+        r = colour.Red()
+        g = colour.Green()
+        b = colour.Blue()
+
+        hr, hg, hb = min(255,r+64), min(255,g+64), min(255,b+64)
+
+        colour = wx.Colour(hr, hg, hb)
+        back_colour = wx.WHITE
+
+        yypos = ypos+(ysize-height-self._padding.y/2)/2
+
+        xrect = wx.Rect(bmprect.x+(bmprect.width - self._padding.x - height)/2,
+                        yypos, height, height)
+
+        # Opera Style
+        dc.SetPen(wx.Pen(colour, 1))
+        dc.SetBrush(wx.Brush(colour))
+        dc.DrawRoundedRectangleRect(xrect, 2)
+        dc.SetPen(wx.Pen(back_colour, 2))
+        dc.DrawLine(xrect[0]+2, xrect[1]+2, xrect[0]+xrect[2]-3, 
xrect[1]+xrect[3]-3)
+        dc.DrawLine(xrect[0]+2, xrect[1]+xrect[3]-3, xrect[0]+xrect[2]-3, 
xrect[1]+2)
+
+
+    def RedrawClosingX(self, pt, insidex, drawx, highlight=False):
+        """ Redraw The Closing "X" Accordingly To The Mouse "Hovering" 
Position. """
+
+        colour = self.GetPageTextColour(insidex)
+        back_colour = self.GetBackgroundColour()
+        imagelist = 0
+
+        if highlight:
+            r = colour.Red()
+            g = colour.Green()
+            b = colour.Blue()
+
+            hr, hg, hb = min(255,r+64), min(255,g+64), min(255,b+64)
+
+            colour = wx.Colour(hr, hg, hb)
+            back_colour = wx.WHITE
+            imagelist = 1
+
+        dc = wx.ClientDC(self)
+        xrect = self._xrect[insidex]
+
+        if drawx == 1:
+            # Emule Style
+            dc.SetPen(wx.Pen(colour, 1))
+            dc.SetBrush(wx.TRANSPARENT_BRUSH)
+            dc.DrawRectangleRect(xrect)
+        elif drawx == 2:
+            # Opera Style
+            dc.SetPen(wx.Pen(colour, 1))
+            dc.SetBrush(wx.Brush(colour))
+            dc.DrawRoundedRectangleRect(xrect, 2)
+            dc.SetPen(wx.Pen(back_colour, 2))
+            dc.DrawLine(xrect[0]+2, xrect[1]+2, xrect[0]+xrect[2]-3, 
xrect[1]+xrect[3]-3)
+            dc.DrawLine(xrect[0]+2, xrect[1]+xrect[3]-3, xrect[0]+xrect[2]-3, 
xrect[1]+2)
+        else:
+            self._imglist2.Draw(imagelist, dc, xrect[0], xrect[1],
+                                wx.IMAGELIST_DRAW_TRANSPARENT, True)
+
+
+    def HideOnSingleTab(self, hide=True):
+        """ Hides The TabCtrl When There Is Only One Tab In NotebookCtrl. """
+
+        self._hideonsingletab = hide
+
+
+    def SetPagePopupMenu(self, nPage, menu):
+        """ Sets A Popup Menu Specific To A Single Tab. """
+
+        if nPage < 0 or nPage >= self.GetPageCount():
+            raise "\nERROR: Invalid Notebook Page In SetPagePopupMenu: (" + 
str(nPage) + ")"
+
+        self._pages[nPage]._menu = menu
+
+
+    def GetPagePopupMenu(self, nPage):
+        """ Returns The Popup Menu Associated To A Single Tab. """
+
+        if nPage < 0 or nPage >= self.GetPageCount():
+            raise "\nERROR: Invalid Notebook Page In GetPagePopupMenu: (" + 
str(nPage) + ")"
+
+        return self._pages[nPage]._menu
+
+
+    def DrawInsertionMark(self, dc, nPage):
+        """
+        Draw An Insertion Arrow To Let The User Understand Where A Dragged Tab 
Will
+        Be Dropped (Between Which Tabs).
+        """
+
+        if not self._enablehiding:
+            if nPage < 0 or nPage >= len(self._tabrect):
+                return
+        else:
+            if nPage < 0 or nPage >= len(self._tabrect) + 
self._tabvisible.count(0):
+                return
+
+        colour = wx.BLACK
+        somehidden = False
+
+        if self._enablehiding:
+            for ii in xrange(nPage):
+                if self._pages[ii]._ishidden:
+                    nPage = nPage - 1
+                    somehidden = True
+
+        rect = self._tabrect[nPage]
+
+        x1 = rect.x - 4
+        y1 = rect.y - 1
+        x2 = rect.x
+        y2 = y1 + 5
+        x3 = rect.x + 3
+        y3 = y1
+
+        mybrush = wx.Brush(self.GetPageTextColour(nPage))
+
+        if not self._enablehiding:
+            if nPage > self._tabID:
+                x1 = x1 + rect.width
+                x2 = x2 + rect.width
+                x3 = x3 + rect.width
+        else:
+            mybrush = wx.Brush(self.GetPageTextColour(nPage))
+            if nPage >= self._tabID:
+                x1 = x1 + rect.width
+                x2 = x2 + rect.width
+                x3 = x3 + rect.width
+
+        dc.SetPen(wx.Pen(wx.BLACK, 1))
+        dc.SetBrush(mybrush)
+        dc.DrawPolygon([(x1, y1), (x2, y2), (x3, y3)])
+
+
+    def OnMouseMotion(self, event):
+        """ Handles The wx.EVT_MOTION Event For TabCtrl. """
+
+        pt = event.GetPosition()
+
+        if self._enabledragging:
+
+            if event.Dragging() and not event.RightIsDown() and not 
event.MiddleIsDown():
+
+                tolerance = 2
+
+                dx = abs(pt.x - self._dragstartpos.x)
+                dy = abs(pt.y - self._dragstartpos.y)
+
+                if dx <= tolerance and dy <= tolerance:
+                    self.SetCursor(wx.STANDARD_CURSOR)
+                    return
+
+                self.SetCursor(self._dragcursor)
+                self._isdragging = True
+                self._isleaving = False
+                newpos = self.HitTest(pt)
+
+                if newpos >= 0 and newpos != self._olddragpos:
+                    self._olddragpos = newpos
+                    self.Refresh()
+
+            else:
+
+                self._isdragging = False
+                self.SetCursor(wx.STANDARD_CURSOR)
+
+        if not event.Dragging():
+            drawx = self.GetDrawX()
+
+            if drawx[0]:
+                insidex = self.GetInsideX(pt)
+                if insidex >= 0:
+                    if self.IsPageEnabled(insidex):
+                        self.RedrawClosingX(pt, insidex, drawx[1], True)
+                        self._xrefreshed = False
+                else:
+                    if not self._xrefreshed:
+                        insidetab = self.GetInsideTab(pt)
+                        if insidetab >= 0:
+                            if self.IsPageEnabled(insidetab):
+                                self.RedrawClosingX(pt, insidetab, drawx[1])
+                                self._xrefreshed = True
+            else:
+                if self.GetImageToCloseButton():
+                    page, flags = self.HitTest(pt, 1)
+                    if page >= 0:
+                        if self.IsPageEnabled(page):
+                            if flags == NC_HITTEST_ONICON:
+                                if not self._imageconverted:
+                                    self.ConvertImageToCloseButton(page)
+                                    self._imageconverted = True
+                            else:
+                                if self._imageconverted:
+                                    self.Refresh()
+                                    self._imageconverted = False
+
+        if self._showtooltip:
+            if not event.Dragging():
+                if not event.LeftDown():
+
+                    oldinside = self._insidetab
+                    self._insidetab = self.GetInsideTab(pt)
+
+                    if self._insidetab >= 0:
+                        if oldinside != self._insidetab:
+
+                            if self._istooltipshown:
+                                self._tipwindow.Destroy()
+                                self._istooltipshown = False
+                                self.Refresh()
+
+                            if self._tiptimer.IsRunning():
+                                self._tiptimer.Stop()
+
+                            tip, ontime, winsize= 
self.GetPageToolTip(self._insidetab)
+
+                            if tip.strip() != "":
+                                self._currenttip = tip
+                                self._currentwinsize = winsize
+                                self._tiptimer.Start(ontime, wx.TIMER_ONE_SHOT)
+
+                    else:
+                        if self._istooltipshown:
+                            self._tipwindow.Destroy()
+                            self._istooltipshown = False
+                            self.Refresh()
+
+        self._mousepos = pt
+
+        event.Skip()
+
+
+    def OnShowToolTip(self):
+        """ Called When The Timer For The ToolTip Expires. Used Internally. """
+
+        pt = self.ScreenToClient(wx.GetMousePosition())
+
+        oldinside = self._insidetab
+        self._insidetab = self.GetInsideTab(pt)
+
+        if self._insidetab != oldinside or self._insidetab < 0:
+            return
+
+        self._istooltipshown = True
+        self._tipwindow = self.TransientTipWindow(self, self._currenttip,
+                                                  self._currentwinsize)
+
+        xsize, ysize = self._tipwindow.GetSize()
+        xpos, ypos = self.ClientToScreen(self._mousepos)
+
+        if xpos + xsize > self._xvideo - 10:
+            if ypos + ysize > self._yvideo - 10:  # SW Tip Positioning
+                posx = xpos - xsize
+                posy = ypos - ysize
+            else: # NE Tip Positioning
+                posx = xpos - xsize
+                posy = ypos
+        else:
+            if ypos + ysize > self._yvideo - 10:  # SE Tip Positioning
+                posx = xpos + 10
+                posy = ypos - ysize
+            else: # NW Tip Positioning
+                posx = xpos + 10
+                posy = ypos
+
+        if posy < 0:
+            posy = ypos
+
+        if posx < 0:
+            posx = xpos
+
+        self._tipwindow.SetPosition((posx, posy))
+        self._tipwindow.Show()
+
+
+    def OnMouseLeftDown(self, event):
+        """ Handles The wx.EVT_LEFT_DOWN Event For TabCtrl. """
+
+        pos = event.GetPosition()
+        page, flags = self.HitTest(pos, 1)
+        self._dragstartpos = pos
+
+        if page != wx.NOT_FOUND:
+
+            if self.IsPageEnabled(page):
+
+                if event.m_controlDown:
+                    if page in self._selectedtabs:
+                        self._selectedtabs.remove(page)
+                    else:
+                        self._selectedtabs.append(page)
+                    self.Refresh()
+                else:
+                    self._selectedtabs = []
+                    if flags == NC_HITTEST_ONX or (flags == NC_HITTEST_ONICON 
and self.GetImageToCloseButton()):
+                        eventOut = 
NotebookCtrlEvent(wxEVT_NOTEBOOKCTRL_PAGE_CLOSING, self.GetId())
+                        eventOut.SetOldSelection(self._selection)
+                        eventOut.SetSelection(page)
+                        eventOut.SetEventObject(self)
+
+                        if not self.GetEventHandler().ProcessEvent(eventOut):
+                            self._parent.DeletePage(page)
+                            self._parent.bsizer.Layout()
+
+                    else:
+                        self.SetSelection(page)
+                        self._tabID = page
+
+        event.Skip()
+
+
+    def OnMouseLeftDClick(self, event):
+        """ Handles The wx.EVT_LEFT_DCLICK Event For TabCtrl. """
+
+        pos = event.GetPosition()
+        page = self.HitTest(pos)
+        self._selectedtabs = []
+
+        if page == wx.NOT_FOUND:
+            return
+
+        if not self.IsPageEnabled(page):
+            return
+
+        eventOut = NotebookCtrlEvent(wxEVT_NOTEBOOKCTRL_PAGE_DCLICK, 
self.GetId())
+        eventOut.SetOldSelection(self._selection)
+        eventOut.SetSelection(page)
+        eventOut.SetEventObject(self)
+
+        if not self.GetEventHandler().ProcessEvent(eventOut):
+            return
+
+        event.Skip()
+
+
+    def OnMouseLeftUp(self, event):
+        """ Handles The wx.EVT_LEFT_UP Event For TabCtrl. """
+
+        if not self._enabledragging:
+            event.Skip()
+            return
+
+        if not self._isdragging:
+            self.SetCursor(wx.STANDARD_CURSOR)
+            event.Skip()
+            return
+
+        id = self.HitTest(wx.Point(event.GetX(), event.GetY()))
+
+        if id >= 0 and id != self._tabID:
+
+            self._isdragging = False
+            self._olddragpos = -1
+            eventOut = NotebookCtrlEvent(wxEVT_NOTEBOOKCTRL_PAGE_DND, 
self.GetId())
+            eventOut.SetOldPosition(self._tabID)
+            eventOut.SetNewPosition(id)
+            eventOut.SetEventObject(self)
+
+            if self.GetEventHandler().ProcessEvent(eventOut):
+                self._tabID = -1
+                self._olddragpos = -1
+                self.SetCursor(wx.STANDARD_CURSOR)
+                self.Refresh()
+                return
+
+            self._parent.Freeze()
+
+            try:
+                text = self.GetPageText(self._tabID)
+                image = self.GetPageImage(self._tabID)
+                font1 = self.GetPageTextFont(self._tabID)
+                font2 = self.GetPageTextSecondaryFont(self._tabID)
+                fontcolour = self.GetPageTextColour(self._tabID)
+                pagecolour = self.GetPageColour(self._tabID)
+                enabled = self.IsPageEnabled(self._tabID)
+                tooltip, ontime, winsize = self.GetPageToolTip(self._tabID)
+                menu = self.GetPagePopupMenu(self._tabID)
+                firstcol = self.GetPageFirstGradientColour(self._tabID)
+                secondcol = self.GetPageSecondGradientColour(self._tabID)
+                ishidden = self._pages[self._tabID]._ishidden
+            except:
+                self._parent.Thaw()
+                self._tabID = -1
+                self.SetCursor(wx.STANDARD_CURSOR)
+                return
+
+            isanimated = 0
+            if self._timers[self._tabID].IsRunning():
+                isanimated = 1
+                timer = self._timers[self._tabID].GetInterval()
+
+            self.StopAnimation(self._tabID)
+            animatedimages = self.GetAnimationImages(self._tabID)
+
+            pagerange = range(self.GetPageCount())
+
+            newrange = pagerange[:]
+            newrange.remove(self._tabID)
+            newrange.insert(id, self._tabID)
+
+            newpages = []
+            counter = self.GetPageCount() - 1
+
+            for ii in xrange(self.GetPageCount()):
+                newpages.append(self._parent.GetPage(ii))
+                self._parent.bsizer.Detach(counter-ii)
+
+            cc = 0
+
+            self._parent._notebookpages = []
+
+            for jj in newrange:
+                self._parent.bsizer.Add(newpages[jj], 1, wx.EXPAND | wx.ALL, 2)
+                self._parent.bsizer.Show(cc, False)
+                self._parent._notebookpages.append(newpages[jj])
+                cc = cc + 1
+
+            self.DeletePage(self._tabID)
+
+            if enabled:
+                if id == self.GetPageCount():
+                    self.AddPage(text, True, image)
+                else:
+                    self.InsertPage(id, text, True, image)
+            else:
+                if id == self.GetPageCount():
+                    self.AddPage(text, False, image)
+                else:
+                    self.InsertPage(id, text, False, image)
+
+            self.SetPageImage(id, image)
+            self.SetPageText(id, text)
+            self.SetPageTextFont(id, font1)
+            self.SetPageTextSecondaryFont(id, font2)
+            self.SetPageTextColour(id, fontcolour)
+            self.SetPageColour(id, pagecolour)
+            self.EnablePage(id, enabled)
+            self.SetPageToolTip(id, tooltip, ontime, winsize)
+            self.SetPagePopupMenu(id, menu)
+            self.SetPageFirstGradientColour(id, firstcol)
+            self.SetPageSecondGradientColour(id, secondcol)
+            self._pages[id]._ishidden = ishidden
+
+            if isanimated and len(animatedimages) > 1:
+                self.SetAnimationImages(id, animatedimages)
+                self.StartAnimation(id, timer)
+
+            if enabled:
+                self._parent.bsizer.Show(id, True)
+            else:
+                sel = self.GetSelection()
+
+                if sel == -1:
+                    sel = 0
+                self._parent.bsizer.Show(id, False)
+                self._parent.SetSelection(sel)
+                self._parent.bsizer.Show(sel, True)
+
+            self._parent.bsizer.Layout()
+
+            self._parent.Thaw()
+
+        self._isdragging = False
+        self._olddragpos = -1
+        self._fromdnd = True
+        self.Refresh()
+        self._tabID = -1
+        self.SetCursor(wx.STANDARD_CURSOR)
+
+        event.Skip()
+
+
+    def OnSize(self, event=None):
+        """ Handles The wx.EVT_SIZE Event For TabCtrl. """
+
+        self.Refresh()
+
+        if event is not None:
+            event.Skip()
+
+
+    def OnMouseRightUp(self, event):
+        """ Handles The wx.EVT_RIGHT_UP Event For TabCtrl. """
+
+        pt = event.GetPosition()
+        id = self.HitTest(pt)
+
+        self._selectedtabs = []
+
+        if id >= 0:
+            if self.IsPageEnabled(id):
+                menu = self.GetPagePopupMenu(id)
+                if menu:
+                    self.PopupMenu(menu)
+
+        event.Skip()
+
+
+    def OnMouseRightDown(self, event):
+        """ Handles The wx.EVT_RIGHT_DOWN Event For TabCtrl. """
+
+        pos = event.GetPosition()
+        page = self.HitTest(pos)
+
+        self._selectedtabs = []
+
+        if page == wx.NOT_FOUND:
+            return
+
+        if not self.IsPageEnabled(page):
+            return
+
+        eventOut = NotebookCtrlEvent(wxEVT_NOTEBOOKCTRL_PAGE_RIGHT, 
self.GetId())
+        eventOut.SetOldSelection(self._selection)
+        eventOut.SetSelection(page)
+        eventOut.SetEventObject(self)
+
+        if not self.GetEventHandler().ProcessEvent(eventOut):
+            return
+
+        event.Skip()
+
+
+    def OnMouseMiddleDown(self, event):
+        """ Handles The wx.EVT_MIDDLE_DOWN Event For TabCtrl. """
+
+        pos = event.GetPosition()
+        page = self.HitTest(pos)
+
+        self._selectedtabs = []
+
+        if page == wx.NOT_FOUND:
+            return
+
+        if not self.IsPageEnabled(page):
+            return
+
+        eventOut = NotebookCtrlEvent(wxEVT_NOTEBOOKCTRL_PAGE_MIDDLE, 
self.GetId())
+        eventOut.SetOldSelection(self._selection)
+        eventOut.SetSelection(page)
+        eventOut.SetEventObject(self)
+
+        if not self.GetEventHandler().ProcessEvent(eventOut):
+            return
+
+        event.Skip()
+
+
+    def SetSelectionColour(self, colour=None):
+        """ Sets The Tab Selection Colour (Thin Line Above The Selected Tab). 
"""
+
+        if colour is None:
+            colour = wx.Colour(255, 180, 0)
+
+        self._selectioncolour = colour
+
+
+    def SetContourLineColour(self, colour=None):
+        """ Sets The Contour Line Colour (Controur Line Around Tabs). """
+
+        if colour is None:
+            if not self._tabstyle._normal or self._usegradients:
+                colour = wx.Colour(145, 167, 180)
+            else:
+                colour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW)
+
+        if not self._tabstyle._normal or self._usegradients:
+            self._highlightpen = wx.Pen(colour)
+            self._highlightpen.SetCap(wx.CAP_BUTT)
+        else:
+            self._highlightpen2 = wx.Pen(colour)
+            self._highlightpen2.SetCap(wx.CAP_BUTT)
+
+        self.Refresh()
+
+
+    def ApplyTabTheme(self, theme=None):
+        """ Applies A Particular Theme To Be Drawn On Tabs. """
+
+        if theme is None:
+            theme = ThemeStyle()
+
+        self._tabstyle = theme
+        self.Refresh()
+
+
+    def DrawMacTheme(self, dc, tabrect, theme):
+        """ Draws The Mac Theme On Tabs, If It Is Enabled. """
+
+        if theme == 1:
+            col1, col2 = NC_MAC_LIGHT
+        else:
+            col1, col2 = NC_MAC_DARK
+
+        colour1 = wx.Colour(col1, col1, col1)
+        colour2 = wx.Colour(col2, col2, col2)
+
+        x, y, w, h = tabrect
+        index = 0
+
+        for ii in xrange(0, h, 2):
+            if index%2 == 0:
+                colour = colour1
+            else:
+                colour = colour2
+
+            dc.SetBrush(wx.Brush(colour))
+            dc.SetPen(wx.Pen(colour))
+            if ii > 3:
+                dc.DrawRectangle(x, y+ii, w, 2)
+            else:
+                dc.DrawRoundedRectangle(x, y+ii, w, 3, 3)
+
+            index = index + 1
+
+        self._lastcolour = colour
+
+
+    def DrawKDETheme(self, dc, rect):
+        """ Draws Unix-Style KDE Theme On Tabs. """
+
+        brush = wx.Brush(kdetheme[13], wx.SOLID)
+        dc.SetBackground(brush)
+        x, y, w, h = rect
+
+        for ii in xrange(14):
+            pen = wx.Pen(kdetheme[ii])
+            dc.SetPen(pen)
+            dc.DrawLine(x+1, y+ii, x+w-1, y+ii)
+            dc.DrawLine(x+1, y+h-1-ii, x+w-2, y+h-1-ii)
+
+        self._lastcolour = kdetheme[0]
+
+
+    def DrawSilverTheme(self, dc, rect, selected):
+        """ Draws Windows XP Silver-Like Theme. """
+
+        x, y, w, h = rect
+
+        if selected:
+            r1 = silvertheme1[0].Red()
+            g1 = silvertheme1[0].Green()
+            b1 = silvertheme1[0].Blue()
+            r2 = silvertheme1[1].Red()
+            g2 = silvertheme1[1].Green()
+            b2 = silvertheme1[1].Blue()
+        else:
+            r1 = silvertheme2[0].Red()
+            g1 = silvertheme2[0].Green()
+            b1 = silvertheme2[0].Blue()
+            r2 = silvertheme2[1].Red()
+            g2 = silvertheme2[1].Green()
+            b2 = silvertheme2[1].Blue()
+            rend = silvertheme2[2].Red()
+            gend = silvertheme2[2].Green()
+            bend = silvertheme2[2].Blue()
+
+        flrect = float(h-2)
+
+        rstep = float((r2 - r1)) / flrect
+        gstep = float((g2 - g1)) / flrect
+        bstep = float((b2 - b1)) / flrect
+
+        rf, gf, bf = 0, 0, 0
+
+        counter = 0
+
+        for yy in xrange(y+1, y+h):
+            currCol = (int(round(r1 + rf)), int(round(g1 + gf)), int(round(b1 
+ bf)))
+            dc.SetBrush(wx.Brush(currCol, wx.SOLID))
+            dc.SetPen(wx.Pen(currCol))
+            if counter == 0:
+                xpos = x + 2
+                xend = w - 4
+            elif counter == 1:
+                xpos = x + 1
+                xend = w - 2
+            else:
+                xpos = x + 1
+                xend = w - 2
+
+            counter = counter + 1
+            dc.DrawRectangle(xpos, yy, xend, 1)
+            rf = rf + rstep
+            gf = gf + gstep
+            bf = bf + bstep
+            self._lastcolour = currCol
+
+        if not selected:
+            dc.SetBrush(wx.Brush((rend, gend, bend)))
+            dc.SetPen(wx.Pen((rend, gend, bend)))
+            dc.DrawRectangle(xpos, y+h-3, xend, 3)
+            self._lastcolour = wx.Colour(rend, gend, bend)
+
+
+    def DrawAquaTheme(self, dc, rect, style, selected):
+        """ Draws Mac-Style Aqua Theme On Tabs. """
+
+        x, y, w, h = rect
+
+        if selected:
+            if style == 1:  # Dark Aqua
+                r1 = topaqua1[0].Red()
+                g1 = topaqua1[0].Green()
+                b1 = topaqua1[0].Blue()
+
+                r2 = topaqua1[1].Red()
+                g2 = topaqua1[1].Green()
+                b2 = topaqua1[1].Blue()
+            else:
+                r1 = topaqua2[0].Red()
+                g1 = topaqua2[0].Green()
+                b1 = topaqua2[0].Blue()
+
+                r2 = topaqua2[1].Red()
+                g2 = topaqua2[1].Green()
+                b2 = topaqua2[1].Blue()
+        else:
+            r1 = distaqua[0].Red()
+            g1 = distaqua[0].Green()
+            b1 = distaqua[0].Blue()
+
+            r2 = distaqua[1].Red()
+            g2 = distaqua[1].Green()
+            b2 = distaqua[1].Blue()
+
+        flrect = float((h-2)/2)
+
+        rstep = float((r2 - r1)) / flrect
+        gstep = float((g2 - g1)) / flrect
+        bstep = float((b2 - b1)) / flrect
+
+        rf, gf, bf = 0, 0, 0
+
+        counter = 0
+        dc.SetPen(wx.TRANSPARENT_PEN)
+
+        for yy in xrange(y+1, y+h/2):
+            currCol = (int(round(r1 + rf)), int(round(g1 + gf)), int(round(b1 
+ bf)))
+            dc.SetBrush(wx.Brush(currCol, wx.SOLID))
+            if counter == 0:
+                xpos = x + 2
+                xend = w - 4
+            elif counter == 1:
+                xpos = x + 1
+                xend = w - 2
+            else:
+                xpos = x + 1
+                xend = w - 2
+
+            counter = counter + 1
+
+            dc.DrawRectangle(xpos, yy, xend, 1)
+            rf = rf + rstep
+            gf = gf + gstep
+            bf = bf + bstep
+
+        if selected:
+            if style == 1:  # Dark Aqua
+                r1 = botaqua1[0].Red()
+                g1 = botaqua1[0].Green()
+                b1 = botaqua1[0].Blue()
+
+                r2 = botaqua1[1].Red()
+                g2 = botaqua1[1].Green()
+                b2 = botaqua1[1].Blue()
+            else:
+                r1 = botaqua2[0].Red()
+                g1 = botaqua2[0].Green()
+                b1 = botaqua2[0].Blue()
+
+                r2 = botaqua2[1].Red()
+                g2 = botaqua2[1].Green()
+                b2 = botaqua2[1].Blue()
+        else:
+            r1 = disbaqua[0].Red()
+            g1 = disbaqua[0].Green()
+            b1 = disbaqua[0].Blue()
+
+            r2 = disbaqua[1].Red()
+            g2 = disbaqua[1].Green()
+            b2 = disbaqua[1].Blue()
+
+        flrect = float((h-2)/2)
+
+        rstep = float((r2 - r1)) / flrect
+        gstep = float((g2 - g1)) / flrect
+        bstep = float((b2 - b1)) / flrect
+
+        rf, gf, bf = 0, 0, 0
+
+        counter = 0
+
+        for yy in xrange(y+h/2, y+h):
+            currCol = (int(round(r1 + rf)), int(round(g1 + gf)), int(round(b1 
+ bf)))
+            dc.SetBrush(wx.Brush(currCol, wx.SOLID))
+            dc.DrawRectangle(x+1, yy, w-2, 1)
+            rf = rf + rstep
+            gf = gf + gstep
+            bf = bf + bstep
+
+        self._lastcolour = currCol
+
+
+    def DrawMetalTheme(self, dc, rect):
+        """ Draws Mac-Style Metal Gradient On Tabs. """
+
+        x, y, w, h = rect
+
+        dc.SetPen(wx.TRANSPARENT_PEN)
+        counter = 0
+
+        for yy in xrange(y+1, h+y):
+            intens = (230 + 80 * (y-yy)/h)
+            colour = wx.Colour(intens, intens, intens)
+            dc.SetBrush(wx.Brush(colour))
+            if counter == 0:
+                xpos = x + 2
+                xend = w - 4
+            elif counter == 1:
+                xpos = x + 1
+                xend = w - 2
+            else:
+                xpos = x + 1
+                xend = w - 2
+
+            counter = counter + 1
+            dc.DrawRectangle(xpos, yy, xend, 1)
+
+        self._lastcolour = colour
+
+
+    def DrawVerticalGradient(self, dc, rect):
+        """ Gradient Fill From Colour 1 To Colour 2 From Top To Bottom. """
+
+        dc.SetPen(wx.TRANSPARENT_PEN)
+
+        # calculate gradient coefficients
+        col2 = self._tabstyle._secondcolour
+        col1 = self._tabstyle._firstcolour
+
+        r1, g1, b1 = int(col1.Red()), int(col1.Green()), int(col1.Blue())
+        r2, g2, b2 = int(col2.Red()), int(col2.Green()), int(col2.Blue())
+
+        flrect = float(rect.height)
+
+        rstep = float((r2 - r1)) / flrect
+        gstep = float((g2 - g1)) / flrect
+        bstep = float((b2 - b1)) / flrect
+
+        rf, gf, bf = 0, 0, 0
+
+        counter = 0
+
+        for y in xrange(rect.y+1, rect.y + rect.height):
+            currCol = (r1 + rf, g1 + gf, b1 + bf)
+
+            dc.SetBrush(wx.Brush(currCol, wx.SOLID))
+            if counter == 0:
+                xpos = rect.x + 2
+                xend = rect.width - 4
+            elif counter == 1:
+                xpos = rect.x + 1
+                xend = rect.width - 2
+            else:
+                xpos = rect.x
+                xend = rect.width
+
+            counter = counter + 1
+
+            dc.DrawRectangle(xpos, y, xend, 1)
+            rf = rf + rstep
+            gf = gf + gstep
+            bf = bf + bstep
+
+        self._lastcolour = currCol
+
+
+    def DrawHorizontalGradient(self, dc, rect):
+        """ Gradient Fill From Colour 1 To Colour 2 From Left To Right. """
+
+        dc.SetPen(wx.TRANSPARENT_PEN)
+
+        # calculate gradient coefficients
+        col2 = self._tabstyle._secondcolour
+        col1 = self._tabstyle._firstcolour
+
+        r1, g1, b1 = int(col1.Red()), int(col1.Green()), int(col1.Blue())
+        r2, g2, b2 = int(col2.Red()), int(col2.Green()), int(col2.Blue())
+
+        flrect = float(rect.width)
+
+        rstep = float((r2 - r1)) / flrect
+        gstep = float((g2 - g1)) / flrect
+        bstep = float((b2 - b1)) / flrect
+
+        rf, gf, bf = 0, 0, 0
+        counter = 0
+        lenc = len(xrange(rect.x, rect.x + rect.width))
+
+        for x in xrange(rect.x, rect.x + rect.width):
+            currCol = (r1 + rf, g1 + gf, b1 + bf)
+
+            dc.SetBrush(wx.Brush(currCol, wx.SOLID))
+            if counter in [0, lenc - 1]:
+                ypos = rect.y + 3
+                yend = rect.height - 3
+            elif counter in [1, lenc - 2]:
+                ypos = rect.y + 2
+                yend = rect.height - 2
+            else:
+                ypos = rect.y + 1
+                yend = rect.height - 1
+
+            counter = counter + 1
+
+            dc.DrawRectangle(x, ypos, 1, yend)
+            rf = rf + rstep
+            gf = gf + gstep
+            bf = bf + bstep
+
+        self._lastcolour = currCol
+
+
+    def GetAllTextExtents(self, dc):
+        """ Returns All Tabs Text Extents. Used Internally. """
+
+        self._mintabwidths = []
+        self._maxtabwidths = []
+        self._mintabheights = []
+        self._maxtabheights = []
+        self._incrtext = []
+        minheight = 0
+
+        for ii in xrange(self.GetPageCount()):
+
+            txts = self.GetPageText(ii)
+            font1 = self.GetPageTextFont(ii)
+            dc.SetFont(font1)
+            w1, h1 = dc.GetTextExtent(txts)
+            minheight = max(minheight, h1)
+            self._mintabwidths.append(w1)
+            self._mintabheights.append(h1)
+            font2 = self.GetPageTextSecondaryFont(ii)
+            dc.SetFont(font2)
+            w2, h2 = dc.GetTextExtent(txts)
+            minheight = max(minheight, h2)
+
+            self._maxtabwidths.append(w2)
+            self._maxtabheights.append(h2)
+            self._incrtext.append(abs(self._mintabwidths[ii] - 
self._maxtabwidths[ii]))
+
+        mh1 = max(self._mintabheights)
+        font1 = self.GetPageTextFont(self._mintabheights.index(mh1))
+        mh2 = max(self._maxtabheights)
+        font2 = self.GetPageTextSecondaryFont(self._maxtabheights.index(mh2))
+
+        mhend = max(mh1, mh2)
+
+        if mhend == mh1:
+            maxfont = font1
+        else:
+            maxfont = font2
+
+        minheight = self.GetSize()[1]
+
+        return  minheight, maxfont
+
+
+    def DrawBuiltinStyle(self, dc, style, rect, index, selection):
+        """ Methods That Holds All The Theme Styles. """
+
+        if style._aqua:
+            if self._selstyle._normal:
+                self.DrawAquaTheme(dc, rect, style._aqua, index==selection)
+            else:
+                oldselstyle = self._selstyle[:]
+                self._selstyle._normal = True
+                self.DrawBuiltinStyle(dc, self._selstyle, rect, index, 
selection)
+                self._selstyle = oldselstyle
+
+        elif style._metal:
+            if self._selstyle._normal:
+                self.DrawMetalTheme(dc, rect)
+            else:
+                oldselstyle = self._selstyle[:]
+                self._selstyle._normal = True
+                self.DrawBuiltinStyle(dc, self._selstyle, rect, index, 
selection)
+                self._selstyle = oldselstyle
+
+        elif style._kdetheme:
+            if self._selstyle._normal:
+                self.DrawKDETheme(dc, rect)
+            else:
+                oldselstyle = self._selstyle[:]
+                self._selstyle._normal = True
+                self.DrawBuiltinStyle(dc, self._selstyle, rect, index, 
selection)
+                self._selstyle = oldselstyle
+
+        elif style._macstyle:
+            if self._selstyle._normal:
+                self.DrawMacTheme(dc, rect, style._macstyle)
+            else:
+                oldselstyle = self._selstyle[:]
+                self._selstyle._normal = True
+                self.DrawBuiltinStyle(dc, self._selstyle, rect, index, 
selection)
+                self._selstyle = oldselstyle
+
+        elif style._gradient:
+            if self._selstyle._normal:
+                if style._gradient == 1:
+                    self.DrawVerticalGradient(dc, rect)
+                else:
+                    self.DrawHorizontalGradient(dc, rect)
+            else:
+                oldselstyle = self._selstyle[:]
+                self._selstyle._normal = True
+                self.DrawBuiltinStyle(dc, self._selstyle, rect, index, 
selection)
+                self._selstyle = oldselstyle
+
+        elif style._silver:
+            if self._selstyle._normal:
+                self.DrawSilverTheme(dc, rect, index==selection)
+            else:
+                oldselstyle = self._selstyle[:]
+                self._selstyle._normal = True
+                self.DrawBuiltinStyle(dc, self._selstyle, rect, index, 
selection)
+                self._selstyle = oldselstyle
+
+
+    def DrawGradientOnTab(self, dc, rect, col1, col2):
+        """ Draw A Gradient Coloured Tab. """
+
+        dc.SetPen(wx.TRANSPARENT_PEN)
+
+        r1, g1, b1 = int(col1.Red()), int(col1.Green()), int(col1.Blue())
+        r2, g2, b2 = int(col2.Red()), int(col2.Green()), int(col2.Blue())
+
+        flrect = float(rect.height)
+
+        rstep = float((r2 - r1)) / flrect
+        gstep = float((g2 - g1)) / flrect
+        bstep = float((b2 - b1)) / flrect
+
+        rf, gf, bf = 0, 0, 0
+
+        counter = 0
+
+        for y in xrange(rect.y+1, rect.y + rect.height):
+            currCol = (r1 + rf, g1 + gf, b1 + bf)
+
+            dc.SetBrush(wx.Brush(currCol, wx.SOLID))
+            if counter == 0:
+                xpos = rect.x + 2
+                xend = rect.width - 4
+            elif counter == 1:
+                xpos = rect.x + 1
+                xend = rect.width - 2
+            else:
+                xpos = rect.x
+                xend = rect.width
+
+            counter = counter + 1
+
+            dc.DrawRectangle(xpos, y, xend, 1)
+            rf = rf + rstep
+            gf = gf + gstep
+            bf = bf + bstep
+
+        self._lastcolour = currCol
+
+
+    def OnPaint(self, event):
+        """ Handles The wx.EVT_PAINT Event For TabCtrl. """
+
+        dc = wx.BufferedPaintDC(self)
+        size = self.GetSize()
+
+        if self.GetPageCount() == 0:
+            event.Skip()
+            return
+
+        back_colour = self.GetBackgroundColour()
+        back_brush = wx.Brush(back_colour)
+        back_pen = wx.Pen(back_colour)
+
+        border_pen = self._borderpen
+        highlightpen = self._highlightpen
+        if self._tabstyle._normal and not self._usegradients:
+            highlightpen = self._highlightpen2
+
+        shadowpen = self._shadowpen
+        upperhighpen = self._upperhigh
+
+        mirror = self._style & NC_BOTTOM
+        fullborder = not (self._style & wx.NO_BORDER)
+        drawx, dxstyle = self.GetDrawX()
+        highlight = self.GetHighlightSelection()
+        usefocus = self.GetUseFocusIndicator()
+
+        if highlight:
+            selectionpen = wx.Pen(self._selectioncolour, 2)
+
+        if drawx:
+            if dxstyle == 1:
+                x_pen = wx.BLACK_PEN
+                mins = min(self._padding.x, self._padding.y) + 1
+                mins = min(mins, 6)
+
+        if usefocus:
+            focusindpen = self._focusindpen
+
+        dc.BeginDrawing()
+
+        #background
+        dc.SetBrush(back_brush)
+
+        cancelpen = back_pen
+
+        if fullborder:
+            dc.SetPen(border_pen)
+            dc.SetPen(highlightpen)
+            dc.DrawRectangle(0, 0, size.x, size.y)
+
+        else:
+            dc.SetPen(back_pen)
+            dc.DrawRectangle(0, 0, size.x, size.y)
+            dc.SetPen(highlightpen)
+            dc.DrawLine(0, mirror and 0 or size.y-1, size.x, mirror and 0 or 
size.y-1)
+
+        selection = self.GetSelection()
+        tabrect = []
+        Xrect = []
+
+        if self._somethingchanged:
+            minheight, maxfont = self.GetAllTextExtents(dc)
+            self._minheight = minheight
+            self._maxfont = maxfont
+        else:
+            minheight = self._minheight
+            maxfont = self._maxfont
+
+        dc.SetFont(maxfont)
+        pom, height = dc.GetTextExtent("Aq")
+        self._maxtextheight = height
+
+        posx = 3
+
+        maxwidth = max(self._maxtabwidths)
+
+        if self._firsttime:
+            if not hasattr(self, "_initrect"):
+                self._initrect = []
+            if self.HasSpinButton() and self._fromdnd:
+                self._firstvisible = self._spinbutton.GetValue()
+                self._firsttime = False
+                self._fromdnd = False
+            else:
+                self._initrect = []
+                self._firstvisible = 0
+        else:
+            if self.HasSpinButton():
+                self._firstvisible = self._spinbutton.GetValue()
+            else:
+                self._firstvisible = 0
+
+        lastvisible = self.GetPageCount()
+        selfound = 0
+
+        if drawx:
+            if dxstyle == 1:
+                xxspace = self._padding.x/2
+            else:
+                xxspace = self._padding.x + height
+        else:
+            xxspace = 0
+
+        #and tabs
+        oncount = -1
+
+        self._tabvisible = [1]*self.GetPageCount()
+
+        for ii in xrange(self._firstvisible, lastvisible):
+
+            if not self._enablehiding or not self._pages[ii]._ishidden:
+
+                oncount = oncount + 1
+
+                self._tabvisible[ii] = 1
+
+                bmp = wx.NullBitmap
+                text = self.GetPageText(ii)
+
+                thefont = self.GetPageTextFont(ii)
+                thebrush = wx.Brush(self.GetPageColour(ii))
+
+                if self.IsPageEnabled(ii):
+                    thecolour = self.GetPageTextColour(ii)
+                else:
+                    thecolour = self._disabledcolour
+
+                dc.SetFont(thefont)
+                dc.SetTextForeground(thecolour)
+                dc.SetBrush(thebrush)
+
+                width, pom = dc.GetTextExtent(text)
+
+                incrtext = self._incrtext[ii]
+
+                if self.GetPageImage(ii) >= 0:
+                    bmpindex = self.GetPageImage(ii)
+                    if self.IsPageEnabled(ii):
+                        bmp = self._imglist.GetBitmap(bmpindex)
+                    else:
+                        bmp = self._grayedlist.GetBitmap(bmpindex)
+
+                bmpOk = bmp.Ok()
+                space = self._padding.x
+
+                if bmpOk:
+                    space = space + self._padding.x + bmp.GetWidth()
+
+                xpos = posx
+
+                if self._style & NC_FIXED_WIDTH:
+                    xsize = maxwidth + space + self._padding.x + incrtext + 
xxspace
+                    newwidth = maxwidth
+                else:
+                    newwidth = width
+                    xsize = width + space + self._padding.x + incrtext + 
xxspace
+
+                xtextpos = posx + space + incrtext/2
+
+                ypos = size.y - height - self._padding.y*2
+                ytextpos = size.y - height - self._padding.y + 
abs(self._mintabheights[ii]
+                                                                   - 
self._maxtabheights[ii])/2
+
+                ysize = height + self._padding.y*2 + 3
+
+                if ii == selection:
+                    selfound = 1
+                    xsize = xsize + self._spacetabs
+                    if ii > 0:
+                        xpos = xpos - self._spacetabs
+                        xsize = xsize + self._spacetabs
+                    else:
+                        xtextpos = xtextpos + self._spacetabs/2.0 + 1
+
+                    ytextpos = ytextpos - 2
+                    ypos = ypos - 3
+                    ysize = ysize + 2
+
+                    xselpos = xpos
+                    yselpos = ypos
+                    xselsize = xsize
+                    yselsize = ysize
+
+                if bmpOk:
+                    bmpxpos = posx
+
+                tabrect.append(wx.Rect(xpos, ypos, xsize, ysize))
+
+                if not self._tabstyle._normal or self._usegradients:
+                    if ii != selection:
+                        dc.SetBrush(wx.TRANSPARENT_BRUSH)
+                        dc.SetPen(shadowpen)
+                        dc.DrawRoundedRectangle(xpos+1, ypos+1, xsize, 
ysize-1, 3)
+
+                    if self._usegradients:
+                        self.DrawGradientOnTab(dc, tabrect[-1], 
self._pages[ii]._firstcolour,
+                                                self._pages[ii]._secondcolour)
+                    else:
+                        self.DrawBuiltinStyle(dc, self._tabstyle, tabrect[-1], 
ii, selection)
+
+                    dc.SetPen(highlightpen)
+                    dc.SetBrush(wx.TRANSPARENT_BRUSH)
+
+                    dc.DrawRoundedRectangle(xpos, ypos, xsize, ysize, 3)
+                    dc.SetPen(upperhighpen)
+                    dc.DrawLine(xpos+2, ypos-1, xpos + xsize - 2, ypos-1)
+                    dc.SetPen(highlightpen)
+
+                    if ii == selection:
+                        dc.SetPen(wx.Pen(self._lastcolour))
+                        dc.DrawLine(xpos, ysize, xpos + xsize, ysize)
+
+                    dc.DrawLine(xpos, size.y-1, xpos + xsize, size.y-1)
+
+                else:
+
+                    dc.SetPen(highlightpen)
+                    dc.DrawRoundedRectangle(xpos, ypos, xsize, ysize, 3)
+
+                    if ii == selection:
+                        dc.SetPen(cancelpen)
+                        dc.DrawLine(xpos, ysize, xpos + xsize, ysize)
+
+                    dc.DrawLine(xpos, size.y-1, xpos + xsize, size.y-1)
+                    dc.SetPen(highlightpen)
+                    dc.DrawLine(xpos + 3, ypos, xpos + xsize - 3, ypos)
+                    dc.SetPen(shadowpen)
+                    dc.DrawLine(xpos + xsize, size.y-2, xpos+xsize, ypos+2)
+
+                dc.DrawText(text, xtextpos, ytextpos)
+
+                if bmpOk:
+                    bmpposx = posx + self._padding.x
+                    bmpposy = size.y - (height + 2*self._padding.y + 
bmp.GetHeight())/2 - 1
+
+                    if ii == selection:
+                        bmpposx = bmpposx + 1
+                        bmpposy = bmpposy - 1
+
+                    if self.IsPageEnabled(ii):
+                        self._imglist.Draw(bmpindex, dc, bmpposx, bmpposy,
+                                           wx.IMAGELIST_DRAW_TRANSPARENT, True)
+                    else:
+                        self._grayedlist.Draw(bmpindex, dc, bmpposx, bmpposy,
+                                              wx.IMAGELIST_DRAW_TRANSPARENT, 
True)
+
+                if selfound:
+                    dc.SetPen(highlightpen)
+                    dc.DrawLine(xselpos + 3, yselpos, xselpos + xselsize - 3, 
yselpos)
+                    if self._tabstyle._normal and not self._usegradients:
+                        dc.SetPen(shadowpen)
+                        dc.DrawLine(xselpos + xselsize, size.y-2, 
xselpos+xselsize, yselpos+2)
+                    else:
+                        shadowpen.SetWidth(1)
+                        dc.SetPen(shadowpen)
+                        dc.DrawLine(xselpos + xselsize, size.y-2, 
xselpos+xselsize, yselpos+3)
+
+                if highlight and selfound:
+                    dc.SetBrush(back_brush)
+                    dc.SetPen(selectionpen)
+                    dc.DrawLine(xselpos + 1, yselpos, xselpos + xselsize - 2, 
yselpos)
+
+                if ii == selection and usefocus:
+                    dc.SetBrush(wx.TRANSPARENT_BRUSH)
+                    dc.SetPen(focusindpen)
+                    dc.DrawRoundedRectangle(xpos+self._padding.x/2, 
ypos+self._padding.y/2,
+                                            xsize-self._padding.x,
+                                            ysize-self._padding.y-2, 2)
+
+                if drawx:
+                    if dxstyle == 1:
+                        dc.SetPen(wx.Pen(thecolour, 1))
+                        dc.SetBrush(wx.TRANSPARENT_BRUSH)
+                        dc.DrawLine(xpos+xsize-mins-3, ypos+2, xpos+xsize-2, 
ypos+3+mins)
+                        dc.DrawLine(xpos+xsize-mins-3, ypos+2+mins, 
xpos+xsize-2, ypos+1)
+                        dc.DrawRectangle(xpos+xsize-mins-3, ypos+2, mins+1, 
mins+1)
+                        Xrect.append(wx.Rect(xpos+xsize-mins-3, ypos+2, 
mins+1, mins+1))
+                    elif dxstyle == 2:
+                        dc.SetPen(wx.Pen(thecolour))
+                        dc.SetBrush(wx.Brush(thecolour))
+                        xxpos = xpos+xsize-height-self._padding.x
+                        yypos = ypos+(ysize-height-self._padding.y/2)/2
+                        dc.DrawRoundedRectangle(xxpos, yypos, height, height, 
2)
+                        dc.SetPen(wx.Pen(back_colour, 2))
+                        dc.DrawLine(xxpos+2, yypos+2, xxpos+height-3, 
yypos+height-3)
+                        dc.DrawLine(xxpos+2, yypos+height-3, xxpos+height-3, 
yypos+2)
+                        Xrect.append(wx.Rect(xxpos, yypos, height, height))
+                    else:
+                        xxpos = xpos+xsize-height-self._padding.x
+                        yypos = ypos+(ysize-height-self._padding.y/2)/2
+                        Xrect.append(wx.Rect(xxpos, yypos, height, height))
+                        self._imglist2.Draw(0, dc, xxpos, yypos, 
wx.IMAGELIST_DRAW_TRANSPARENT, True)
+
+                if ii in self._selectedtabs:
+                    dc.SetPen(wx.Pen(thecolour, 1, wx.DOT_DASH))
+                    dc.SetBrush(wx.TRANSPARENT_BRUSH)
+                    dc.DrawRoundedRectangle(xpos+self._padding.x/2+1, 
ypos+self._padding.y/2+1,
+                                            xsize-self._padding.x-2,
+                                            ysize-self._padding.y-2-2, 2)
+
+                posx = posx + newwidth + space + self._padding.x + 
self._spacetabs + incrtext + xxspace
+                if self._firsttime:
+                    self._initrect.append(tabrect[oncount])
+
+            else:
+
+                self._tabvisible[ii] = 0
+
+        self._tabrect = tabrect
+        self._xrect = Xrect
+
+        if self._firsttime:
+            self._firsttime = False
+
+        self.UpdateMenuButton(self.HasMenuButton())
+        self.UpdateSpinButton()
+
+        if self._enabledragging:
+            if self._isdragging and not self._isleaving:
+                self.DrawInsertionMark(dc, self._olddragpos)
+
+        dc.EndDrawing()
+
+
+# ---------------------------------------------------------------------------- 
#
+# Class NotebookCtrl
+# This Is The Main Class Implementation
+# ---------------------------------------------------------------------------- 
#
+
+class NotebookCtrl(wx.Panel):
+
+    def __init__(self, parent, id, pos=wx.DefaultPosition, size=wx.DefaultSize,
+                 style=NC_DEFAULT_STYLE, sizer=wx.HORIZONTAL, margin=2):
+        """
+        Default Class Constructor. Non-Default Parameters Are:
+
+        - style: Style For The NotebookCtrl, Which May Be:
+          a) NC_TOP: NotebookCtrl Placed On Top (Default);
+          b) NC_BOTTOM: NotebookCtrl Placed At The Bottom;
+          c) NC_FIXED_WIDTH: All Tabs Have The Same Width;
+          d) wx.NO_BORDER: Shows No Border For The Control (Default, Looks 
Better);
+          e) wx.STATIC_BORDER: Shows A Static Border On The Control.
+
+        - sizer: The Sizer Orientation For The Sizer That Holds All The Panels:
+          Changing This Style Is Only Useful When You Use The Tile Method.
+          In This Case, If sizer=wx.HORIZONTAL, All The Panels Will Be Shown 
In Columns,
+          While If sizer=wx.VERTICAL All The Panels Will Be Shown In Rows.
+
+        - margin: An Integer Number Of Pixels That Add Space Above TabCtrl If 
style=NC_TOP,
+          Or Below It If style=NC_BOTTOM
+        """
+
+        wx.Panel.__init__(self, parent, -1, style=wx.NO_FULL_REPAINT_ON_RESIZE 
|
+                          wx.CLIP_CHILDREN)
+
+        self.nb = TabCtrl(self, -1, pos, size, style)
+
+        self._notebookpages = []
+
+        if style & NC_TOP == 0 and style & NC_BOTTOM == 0:
+            style = style | NC_TOP
+
+        if style & wx.NO_BORDER == 0 and \
+           style & wx.STATIC_BORDER == 0:
+            style = style | wx.NO_BORDER
+
+        self._style = style
+        self._showcolumns = False
+        self._showtabs = True
+        self._sizerstyle = sizer
+        self._custompanel = None
+        self._focusswitch = False
+        self._oldfocus = None
+
+        self.sizer = wx.BoxSizer(wx.VERTICAL)
+        self.bsizer = wx.BoxSizer(sizer)
+
+        if style & NC_TOP:
+            self.sizer.Add((0, margin), 0)
+            self.sizer.Add(self.nb, 0, wx.EXPAND)
+            self.sizer.Add(self.bsizer, 1, wx.EXPAND)
+        else:
+            self.sizer.Add(self.bsizer, 1, wx.EXPAND)
+            self.sizer.Add(self.nb, 0, wx.EXPAND)
+            self.sizer.Add((0, margin), 0)
+
+        self.SetSizer(self.sizer)
+
+        self.sizer.Show(self.nb, False)
+
+        self.sizer.Layout()
+        self.Bind(wx.EVT_MOTION, self.OnMouseMotion)
+        self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
+
+
+    def OnKeyDown(self, event):
+        """
+        Handles The wx.EVT_KEY_DOWN Event For NotebookCtrl. This Is Only 
Processed
+        If The User Navigate Through Tabs With Ctrl-Tab Keyboard Navigation.
+        """
+
+        if event.GetKeyCode() == wx.WXK_TAB:
+            if event.ControlDown():
+                sel = self.GetSelection()
+                if sel == self.GetPageCount() - 1:
+                    sel = 0
+                else:
+                    sel = sel + 1
+
+                while not self.IsPageEnabled(sel):
+                    sel = sel + 1
+                    if sel == self.GetPageCount() - 1:
+                        sel = 0
+
+                self.SetSelection(sel)
+
+        event.Skip()
+
+
+    def OnMouseMotion(self, event):
+        """ Handles The wx.EVT_MOTION Event For NotebookCtrl. """
+
+        if self.nb._enabledragging:
+
+            if event.Dragging() and not event.RightIsDown() and not 
event.MiddleIsDown():
+
+                tolerance = 2
+                pt = event.GetPosition()
+                dx = abs(pt.x - self.nb._dragstartpos.x)
+                dy = abs(pt.y - self.nb._dragstartpos.y)
+                if dx <= tolerance and dy <= tolerance:
+                    self.SetCursor(wx.STANDARD_CURSOR)
+                    return
+
+                self.SetCursor(self.nb._dragcursor)
+                self.nb._isdragging = True
+
+            else:
+
+                self.nb._isdragging = False
+                self.SetCursor(wx.STANDARD_CURSOR)
+
+        if self.nb._showtooltip:
+            if self.nb._istooltipshown:
+                pt = event.GetPosition()
+                self.nb._insidetab = self.nb.GetInsideTab(pt)
+                if  self.nb._insidetab < 0:
+                    try:
+                        self.nb._tipwindow.Destroy()
+                        self.nb._istooltipshown = False
+                    except:
+                        self.nb._istooltipshown = False
+
+                    self.nb.Refresh()
+
+        event.Skip()
+
+
+    def EnableChildFocus(self, enable=True):
+        """ Enables/Disables Sending EVT_NOTEBOOKCTRL_PAGE_CHANGING When In 
Tile Mode. """
+
+        self._focusswitch = enable
+
+
+    def FindFocusedPage(self, obj):
+        """ Find Which NotebookCtrl Page Has The Focus Based On Its Child 
Focus. """
+
+        while 1:
+            if obj in self._notebookpages:
+                return obj
+
+            try:
+                obj = obj.GetParent()
+            except:
+                return None
+
+        return None
+
+
+    def OnFocus(self, event):
+        """ Handles The wx.EVT_CHILD_FOCUS Event For NotebookCtrl. """
+
+        if not self._focusswitch:
+            event.Skip()
+            return
+
+        newfocus = self.FindFocusedPage(event.GetEventObject())
+
+        if newfocus == self._oldfocus or newfocus is None:
+            event.Skip()
+            return
+
+        self._oldfocus = newfocus
+
+        eventOut = NotebookCtrlEvent(wxEVT_NOTEBOOKCTRL_PAGE_CHANGING, 
self.GetId())
+
+        nPage = self._notebookpages.index(newfocus)
+        eventOut.SetSelection(nPage)
+        eventOut.SetOldSelection(self.GetSelection())
+        eventOut.SetEventObject(self)
+
+        if not self.GetEventHandler().ProcessEvent(eventOut):
+
+            # Program Allows The Page Change
+            self.nb._selection = nPage
+            eventOut.SetEventType(wxEVT_NOTEBOOKCTRL_PAGE_CHANGED)
+            eventOut.SetOldSelection(self.nb._selection)
+            self.GetEventHandler().ProcessEvent(eventOut)
+
+        event.Skip()
+
+
+    def AddPage(self, page, text, select=False, img=-1, hidden=False):
+        """
+        Add A Page To The Notebook, With Following Parameters:
+        - page: Specifies The New Page;
+        - text: The Tab Text;
+        - select: Whether The Page Should Be Selected Or Not;
+        - img: Specifies The Optional Image Index For The New Page.
+        """
+
+        self.Freeze()
+
+        oldselection = self.nb.GetSelection()
+
+        if self.GetPageCount() == 0:
+            if self.GetCustomPage() is not None:
+                self.bsizer.Detach(self._custompanel)
+                self._custompanel.Show(False)
+                self.bsizer.Layout()
+
+        self.bsizer.Add(page, 1, wx.EXPAND | wx.ALL, 2)
+
+        self.nb.AddPage(text, select, img, hidden)
+        self._notebookpages.append(page)
+
+        page.Bind(wx.EVT_CHILD_FOCUS, self.OnFocus)
+
+        if select:
+            if oldselection >= 0:
+               self.bsizer.Show(self.GetPage(oldselection), False)
+
+            self.nb.SetSelection(self.GetPageCount()-1)
+            self.bsizer.Layout()
+        else:
+            if oldselection >= 0:
+                self.bsizer.Show(page, False)
+            else:
+                self.bsizer.Show(page, True)
+                self.nb.SetSelection(self.GetPageCount()-1)
+                self.bsizer.Layout()
+
+        if self.GetPageCount() == 1:
+
+            self.bsizer.Show(page, True)
+
+            if self.nb._hideonsingletab:
+
+                if self._style & NC_TOP:
+                    self.sizer.Show(0, False)
+                    self.sizer.Show(1, False)
+                else:
+                    self.sizer.Show(1, False)
+                    self.sizer.Show(2, False)
+
+            else:
+                self.nb.Show(True)
+                if self._style & NC_TOP:
+                    self.sizer.Show(0, True)
+                    self.sizer.Show(1, True)
+                else:
+                    self.sizer.Show(1, True)
+                    self.sizer.Show(2, True)
+
+        else:
+
+            self.nb.Show(True)
+            if self._style & NC_TOP:
+                self.sizer.Show(0, True)
+                self.sizer.Show(1, True)
+            else:
+                self.sizer.Show(1, True)
+                self.sizer.Show(2, True)
+
+        self.bsizer.Layout()
+        self.sizer.Layout()
+
+        self.Thaw()
+
+        self.Tile(self._showcolumns)
+        self.ShowTabs(self._showtabs)
+
+
+    def InsertPage(self, nPage, page, text, select=False, img=-1, 
hidden=False):
+        """
+        Insert A Page Into The Notebook, With Following Parameters:
+        - page: Specifies The New Page;
+        - nPage: Specifies The Position For The New Page;
+        - text: The Tab Text;
+        - select: Whether The Page Should Be Selected Or Not;
+        - img: Specifies The Optional Image Index For The New Page.
+        """
+
+        if nPage < 0 or (self.GetSelection() >= 0 and nPage >= 
self.GetPageCount()):
+            raise "\nERROR: Invalid Notebook Page In InsertPage: (" + 
str(nPage) + ")"
+
+        self.Freeze()
+
+        oldselection = self.nb.GetSelection()
+
+        if self.GetPageCount() == 0:
+            if self.GetCustomPage() is not None:
+                self.bsizer.Detach(self._custompanel)
+                self._custompanel.Show(False)
+
+        if oldselection >= 0:
+            self.bsizer.Show(oldselection, False)
+            self.bsizer.Layout()
+
+        if oldselection >= nPage:
+            oldselection = oldselection + 1
+
+        self.nb.InsertPage(nPage, text, select, img, hidden)
+        self.bsizer.Insert(nPage, page, 1, wx.EXPAND | wx.ALL, 2)
+        self._notebookpages.insert(nPage, page)
+        self.bsizer.Layout()
+
+        page.Bind(wx.EVT_CHILD_FOCUS, self.OnFocus)
+
+        for ii in xrange(self.GetPageCount()):
+            self.bsizer.Show(ii, False)
+
+        self.bsizer.Layout()
+
+        if select:
+            self.bsizer.Show(nPage, True)
+            self.bsizer.Layout()
+        else:
+            if oldselection >= 0:
+                self.bsizer.Show(oldselection, True)
+                self.bsizer.Layout()
+            else:
+                self.bsizer.Show(nPage, True)
+
+        self.bsizer.Layout()
+
+        if self.GetPageCount() == 1:
+
+            if self.nb._hideonsingletab:
+
+                if self._style & NC_TOP:
+                    self.sizer.Show(0, False)
+                    self.sizer.Show(1, False)
+                else:
+                    self.sizer.Show(1, False)
+                    self.sizer.Show(2, False)
+
+            else:
+
+                self.nb.Show(True)
+                if self._style & NC_TOP:
+                    self.sizer.Show(0, True)
+                    self.sizer.Show(1, True)
+                else:
+                    self.sizer.Show(1, True)
+                    self.sizer.Show(2, True)
+
+        else:
+
+            self.nb.Show(True)
+            if self._style & NC_TOP:
+                self.sizer.Show(0, True)
+                self.sizer.Show(1, True)
+            else:
+                self.sizer.Show(1, True)
+                self.sizer.Show(2, True)
+
+        self.sizer.Layout()
+
+        self.Thaw()
+
+        self.Tile(self._showcolumns)
+        self.ShowTabs(self._showtabs)
+
+
+    def GetPage(self, nPage):
+        """ Returns The Window At The Given Position nPage. """
+
+        if nPage < 0 or nPage >= self.GetPageCount():
+            raise "\nERROR: Invalid Notebook Page In GetPage: (" + str(nPage) 
+ ")"
+
+        return self._notebookpages[nPage]
+
+
+    def DeleteAllPages(self):
+        """ Deletes All NotebookCtrl Pages. """
+
+        self.Freeze()
+
+        counter = self.GetPageCount() - 1
+
+        for ii in xrange(self.GetPageCount()):
+            self.bsizer.Detach(counter-ii)
+            panels = self.GetPage(counter-ii)
+            panels.Destroy()
+
+        self.nb.DeleteAllPages()
+        self._notebookpages = []
+        self.nb._selection = -1
+
+        self.nb.Show(False)
+
+        custom = self.GetCustomPage()
+
+        if custom is not None:
+            self.SetCustomPage(custom)
+            custom.Show(True)
+
+        self.bsizer.Layout()
+
+        if self._style & NC_TOP:
+            self.sizer.Show(0, False)
+            self.sizer.Show(1, False)
+        else:
+            self.sizer.Show(1, False)
+            self.sizer.Show(2, False)
+
+        self.sizer.Layout()
+
+        self.Thaw()
+
+
+    def DeletePage(self, nPage):
+        """ Deletes The Page nPage, And The Associated Window. """
+
+        if nPage < 0 or nPage >= self.GetPageCount():
+            raise "\nERROR: Invalid Notebook Page In DeletePage: (" + 
str(nPage) + ")"
+
+        oldselection = self.GetSelection()
+
+        self.Freeze()
+
+        panel = self.GetPage(nPage)
+        self.bsizer.Detach(nPage)
+
+        panel.Destroy()
+
+        self.bsizer.Layout()
+
+        self._notebookpages.pop(nPage)
+        self.nb.DeletePage(nPage)
+
+        if self.GetPageCount() > 0:
+            if oldselection == nPage:
+                if self.GetSelection() > 0:
+                    self.SetSelection(self.GetSelection()-1)
+                else:
+                    self.SetSelection(self.GetSelection())
+                    self.bsizer.Show(self.GetSelection())
+                    self.bsizer.Layout()
+
+        if self.GetPageCount() == 0:
+            self.nb.Show(False)
+            if self._style & NC_TOP:
+                self.sizer.Show(0, False)
+                self.sizer.Show(1, False)
+            else:
+                self.sizer.Show(1, False)
+                self.sizer.Show(2, False)
+
+            custom = self.GetCustomPage()
+
+            if custom is not None:
+                self.bsizer.Add(custom, 1, wx.EXPAND | wx.ALL, 2)
+                custom.Show(True)
+
+            self.bsizer.Layout()
+            self.sizer.Layout()
+            self.Thaw()
+            return
+
+        if self.GetPageCount() == 1:
+
+            if self.nb._hideonsingletab:
+
+                if self._style & NC_TOP:
+                    self.sizer.Show(0, False)
+                    self.sizer.Show(1, False)
+                else:
+                    self.sizer.Show(1, False)
+                    self.sizer.Show(2, False)
+
+            else:
+
+                self.nb.Show(True)
+                if self._style & NC_TOP:
+                    self.sizer.Show(0, True)
+                    self.sizer.Show(1, True)
+                else:
+                    self.sizer.Show(1, True)
+                    self.sizer.Show(2, True)
+
+        else:
+
+            self.nb.Show(True)
+            if self._style & NC_TOP:
+                self.sizer.Show(0, True)
+                self.sizer.Show(1, True)
+            else:
+                self.sizer.Show(1, True)
+                self.sizer.Show(2, True)
+
+        self.sizer.Layout()
+
+        self.Thaw()
+
+        self.Tile(self._showcolumns)
+        self.ShowTabs(self._showtabs)
+
+
+    def SetSelection(self, nPage):
+        """
+        Sets The Current Tab Selection To The Given nPage. This Call Generates 
The
+        EVT_NOTEBOOKCTRL_PAGE_CHANGING Event.
+        """
+
+        if nPage < 0 or nPage >= self.GetPageCount():
+            raise "\nERROR: Invalid Notebook Page In SetSelection: (" + 
str(nPage) + ")"
+
+        oldselection = self.GetSelection()
+
+        if oldselection == nPage:
+            return
+
+        self.nb.SetSelection(nPage)
+
+        self.Tile(self._showcolumns)
+        self.ShowTabs(self._showtabs)
+
+
+    def GetPageCount(self):
+        """ Returns The Number Of Pages In NotebookCtrl. """
+
+        return self.nb.GetPageCount()
+
+
+    def GetSelection(self):
+        """ Returns The Current Selection. """
+
+        return self.nb.GetSelection()
+
+
+    def GetImageList(self):
+        """ Returns The Image List Associated With The NotebookCtrl. """
+
+        return self.nb.GetImageList()
+
+
+    def SetImageList(self, imagelist):
+        """ Associate An Image List To NotebookCtrl. """
+
+        self.nb.SetImageList(imagelist)
+
+
+    def AssignImageList(self, imagelist):
+        """ Associate An Image List To NotebookCtrl. """
+
+        self.nb.AssignImageList(imagelist)
+
+
+    def GetPadding(self):
+        """ Returns The (Horizontal, Vertical) Padding Of The Text Inside 
Tabs. """
+
+        return self.nb.GetPadding()
+
+
+    def SetPadding(self, padding):
+        """ Sets The (Horizontal, Vertical) Padding Of The Text Inside Tabs. 
"""
+
+        self.nb.SetPadding(padding)
+
+
+    def SetUseFocusIndicator(self, focus=True):
+        """ Globally Enables/Disables Tab Focus Indicator. """
+
+        self.nb.SetUseFocusIndicator(focus)
+
+
+    def GetUseFocusIndicator(self):
+        """ Returns Globally Enable/Disable State For Tab Focus Indicator. """
+
+        return self.nb.GetUseFocusIndicator()
+
+
+    def EnablePage(self, nPage, enable=True):
+        """ Enable/Disable The Given Page nPage. """
+
+        if nPage < 0 or nPage >= self.GetPageCount():
+            raise "\nERROR: Invalid Notebook Page In EnablePage: (" + 
str(nPage) + ")"
+
+        self.nb.EnablePage(nPage, enable)
+
+
+    def IsPageEnabled(self, nPage):
+        """ Returns Whether A Page Is Enabled Or Not. """
+
+        if nPage < 0 or nPage >= self.GetPageCount():
+            raise "\nERROR: Invalid Notebook Page In IsPageEnabled: (" + 
str(nPage) + ")"
+
+        return self.nb.IsPageEnabled(nPage)
+
+
+    def SetHighlightSelection(self, highlight=True):
+        """ Globally Enables/Disables Tab Highlighting On Tab Selection. """
+
+        self.nb.SetHighlightSelection(highlight)
+
+
+    def GetHighlightSelection(self):
+        """ Returns Globally Enable/Disable State For Tab Highlighting On Tab 
Selection. """
+
+        return self.nb.GetHighlightSelection()
+
+
+    def SetAnimationImages(self, nPage, imgarray):
+        """
+        Sets An Animation List Associated To The Given Page nPage, With The 
Following
+        Parameters:
+        - nPage: The Given Page;
+        - imgarray: A List Of Image Indexes Of Images Inside The ImageList 
Associated
+          To NotebookCtrl.
+        """
+
+        if nPage < 0 or nPage >= self.GetPageCount():
+            raise "\nERROR: Invalid Notebook Page In SetAnimationImages: (" + 
str(nPage) + ")"
+
+        if not imgarray:
+            raise "\nERROR: Invalid Image Array In SetAnimationImages: (" + 
repr(imgarray) + ")"
+
+        if min(imgarray) < 0:
+            raise "\nERROR: Invalid Image Array In SetAnimationImages: 
(Min(ImgArray) = " + \
+                  str(min(imgarray)) + " < 0)"
+
+        if max(imgarray) > self.GetImageList().GetImageCount() - 1:
+            raise "\nERROR: Invalid Image Array In SetAnimationImages: 
(Max(ImgArray) = " + \
+                  str(max(imgarray)) + " > " + 
str(self.GetImageList().GetImageCount()-1) + ")"
+
+        self.nb.SetAnimationImages(nPage, imgarray)
+
+
+    def GetAnimationImages(self, nPage):
+        """ Returns The Animation Images List Associated To The Given Page 
nPage. """
+
+        if nPage < 0 or nPage >= self.GetPageCount():
+            raise "\nERROR: Invalid Notebook Page In GetAnimationImages: (" + 
str(nPage) + ")"
+
+        return self.nb.GetAnimationImages(nPage)
+
+
+    def StartAnimation(self, nPage, timer=500):
+        """ Starts The Animation On The Given Page nPage, With Refreshing Time 
Rate "timer". """
+
+        if nPage < 0 or nPage >= self.GetPageCount():
+            raise "\nERROR: Invalid Notebook Page In StartAnimation: (" + 
str(nPage) + ")"
+
+        self.nb.StartAnimation(nPage, timer)
+
+
+    def StopAnimation(self, nPage):
+        """ Stops The Animation On The Given Page nPage. """
+
+        if nPage < 0 or nPage >= self.GetPageCount():
+            raise "\nERROR: Invalid Notebook Page In StopAnimation: (" + 
str(nPage) + ")"
+
+        self.nb.StopAnimation(nPage)
+
+
+    def EnableDragAndDrop(self, enable=True):
+        """ Globall Enables/Disables Tabs Drag And Drop. """
+
+        self.nb.EnableDragAndDrop(enable)
+
+
+    def EnableHiding(self, enable=True):
+        """ Globally Enables/Disables Hiding On Tabs In Runtime. """
+
+        self.nb.EnableHiding(enable)
+
+
+    def SetDrawX(self, drawx=True, style=1, image1=None, image2=None):
+        """
+        Globally Enables/Disables The Drawing Of A Closing "X" In The Tab. 
Depending
+        On The "style" Parameter, You Will Have:
+        - style = 1: Small "X" At The Top-Right Of The Tab;
+        - style = 2: Bigger "X" In The Middle Vertical Of The Tab (Like Opera 
Notebook);
+        - style = 3: Custom "X" Is Drawn On Tabs.
+        """
+
+        self.nb.SetDrawX(drawx, style, image1, image2)
+
+
+    def GetDrawX(self):
+        """
+        Returns The Enable/Disable State Of Drawing Of A Small "X" At The 
Top-Right Of
+        Every Page.
+        """
+
+        return self.nb.GetDrawX()
+
+
+    def SetImageToCloseButton(self, convert=True):
+        """ Set Whether The Tab Icon Should Be Converted To The Close Button 
Or Not. """
+
+        self.nb.SetImageToCloseButton(convert)
+
+
+    def GetImageToCloseButton(self):
+        """ Get Whether The Tab Icon Should Be Converted To The Close Button 
Or Not. """
+
+        return self.nb._convertimage
+
+
+    def HideOnSingleTab(self, hide=True):
+        """ Hides The TabCtrl When There Is Only One Tab In NotebookCtrl. """
+
+        self.nb.HideOnSingleTab(hide)
+
+        if self.GetPageCount() == 1:
+            if hide:
+                if self._style & NC_TOP:
+                    self.sizer.Show(0, False)
+                    self.sizer.Show(1, False)
+                else:
+                    self.sizer.Show(1, False)
+                    self.sizer.Show(2, False)
+            else:
+                if self._style & NC_TOP:
+                    self.sizer.Show(0, True)
+                    self.sizer.Show(1, True)
+                else:
+                    self.sizer.Show(1, True)
+                    self.sizer.Show(2, True)
+
+            self.sizer.Layout()
+
+
+    def SetPagePopupMenu(self, nPage, menu):
+        """ Sets A Popup Menu Specific To A Single Tab. """
+
+        if nPage < 0 or nPage >= self.GetPageCount():
+            raise "\nERROR: Invalid Notebook Page In SetPagePopupMenu: (" + 
str(nPage) + ")"
+
+        self.nb.SetPagePopupMenu(nPage, menu)
+
+
+    def GetPagePopupMenu(self, nPage):
+        """ Returns The Popup Menu Associated To A Single Tab. """
+
+        if nPage < 0 or nPage >= self.GetPageCount():
+            raise "\nERROR: Invalid Notebook Page In GetPagePopupMenu: (" + 
str(nPage) + ")"
+
+        return self.nb.GetPagePopupMenu(nPage)
+
+
+    def SetPageToolTip(self, nPage, tooltip="", timer=500, winsize=400):
+        """
+        Sets A ToolTip For The Given Page nPage, With The Following Parameters:
+        - nPage: The Given Page;
+        - tooltip: The ToolTip String;
+        - timer: The Timer After Which The Tip Window Is Popped Up;
+        - winsize: The Maximum Width Of The Tip Window.
+        """
+
+        if nPage < 0 or nPage >= self.GetPageCount():
+            raise "\nERROR: Invalid Notebook Page In SetPageToolTip: (" + 
str(nPage) + ")"
+
+        self.nb.SetPageToolTip(nPage, tooltip, timer, winsize)
+
+
+    def GetPageToolTip(self, nPage):
+        """ Returns A Tuple With All Page ToolTip Parameters. """
+
+        if nPage < 0 or nPage >= self.GetPageCount():
+            raise "\nERROR: Invalid Notebook Page In GetPageToolTip: (" + 
str(nPage) + ")"
+
+        return self.nb.GetPageToolTip(nPage)
+
+
+    def EnableToolTip(self, show=True):
+        """ Globally Enables/Disables Tab ToolTips. """
+
+        self.nb.EnableToolTip(show)
+
+
+    def GetToolTipBackgroundColour(self):
+        """ Returns The ToolTip Window Background Colour. """
+
+        return self.nb.GetToolTipBackgroundColour()
+
+
+    def SetToolTipBackgroundColour(self, colour=None):
+        """ Sets The ToolTip Window Background Colour. """
+
+        if colour is None:
+            colour = wx.Colour(255, 255, 230)
+
+        self.nb.SetToolTipBackgroundColour(colour)
+
+
+    def EnableTabGradients(self, enable=True):
+        """ Globally Enables/Disables Drawing Of Gradient Coloured Tabs For 
Each Tab. """
+
+        self.nb.EnableTabGradients(enable)
+
+
+    def SetPageFirstGradientColour(self, nPage, colour=None):
+        """ Sets The Single Tab First Gradient Colour. """
+
+        if nPage < 0 or nPage >= self.GetPageCount():
+            raise "\nERROR: Invalid Notebook Page In 
SetPageFirstGradientColour: (" + str(nPage) + ")"
+
+        if colour is None:
+            colour = wx.WHITE
+
+        self.nb.SetPageFirstGradientColour(nPage, colour)
+
+
+    def SetPageSecondGradientColour(self, nPage, colour=None):
+        """ Sets The Single Tab Second Gradient Colour. """
+
+        if nPage < 0 or nPage >= self.GetPageCount():
+            raise "\nERROR: Invalid Notebook Page In 
SetPageSecondGradientColour: (" + str(nPage) + ")"
+
+        self.nb.SetPageSecondGradientColour(nPage, colour)
+
+
+    def GetPageFirstGradientColour(self, nPage):
+        """ Returns The Single Tab First Gradient Colour. """
+
+        if nPage < 0 or nPage >= self.GetPageCount():
+            raise "\nERROR: Invalid Notebook Page In 
GetPageFirstGradientColour: (" + str(nPage) + ")"
+
+        return self.nb.GetPageFirstGradientColour(nPage)
+
+
+    def GetPageSecondGradientColour(self, nPage):
+        """ Returns The Single Tab Second Gradient Colour. """
+
+        if nPage < 0 or nPage >= self.GetPageCount():
+            raise "\nERROR: Invalid Notebook Page In 
GetPageSecondGradientColour: (" + str(nPage) + ")"
+
+        return self.nb.GetPageSecondGradientColour(nPage)
+
+
+    def CancelTip(self):
+        """ Destroys The Tip Window (Probably You Won't Need This One. """
+
+        self.nb.CancelTip()
+
+
+    def AdvanceSelection(self, forward=True):
+        """
+        Cycles Through The Tabs. The Call To This Function Generates The
+        EVT_NOTEBOOKCTRL_PAGE_CHANGING Event.
+        """
+
+        self.nb.AdvanceSelection(forward)
+
+
+    def SetDefaultPage(self, defaultpage=-1):
+        """
+        Sets The Default Page That Will Be Selected When An Active And Selected
+        Tab Is Made Inactive.
+        """
+
+        if defaultpage >= self.GetPageCount():
+            raise "\nERROR: Invalid Notebook Page In SetDefaultPage: (" + 
str(defaultpage) + ")"
+
+        self.nb.SetDefaultPage(defaultpage)
+
+
+    def GetDefaultPage(self):
+        """ Returns The Default Page. """
+
+        return self.nb.GetDefaultPage()
+
+
+    def GetPageText(self, nPage):
+        """ Returns The String For The Given Page nPage. """
+
+        if nPage < 0 or nPage >= self.GetPageCount():
+            raise "\nERROR: Invalid Notebook Page In GetPageText: (" + 
str(nPage) + ")"
+
+        return self.nb.GetPageText(nPage)
+
+
+    def SetPageText(self, nPage, text):
+        """ Sets The String For The Given Page nPage. """
+
+        if nPage < 0 or nPage >= self.GetPageCount():
+            raise "\nERROR: Invalid Notebook Page In SetPageText: (" + 
str(nPage) + ")"
+
+        self.nb.SetPageText(nPage, text)
+
+
+    def GetPageImage(self, nPage):
+        """ Returns The Image Index For The Given Page nPage. """
+
+        if nPage < 0 or nPage >= self.GetPageCount():
+            raise "\nERROR: Invalid Notebook Page In GetPageImage: (" + 
str(nPage) + ")"
+
+        return self.nb.GetPageImage(nPage)
+
+
+    def SetPageImage(self, nPage, img):
+        """ Sets The Image Index For The Given Page nPage. """
+
+        if nPage < 0 or nPage >= self.GetPageCount():
+            raise "\nERROR: Invalid Notebook Page In SetPageImage: (" + 
str(nPage) + ")"
+
+        self.nb.SetPageImage(nPage, img)
+
+
+    def SetPageTextFont(self, nPage, font=None):
+        """ Sets The Primary Font For The Given Page nPage. """
+
+        if nPage < 0 or nPage >= self.GetPageCount():
+            raise "\nERROR: Invalid Notebook Page In SetPageTextFont: (" + 
str(nPage) + ")"
+
+        if font is None:
+            font = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
+
+        self.nb.SetPageTextFont(nPage, font)
+
+
+    def GetPageTextFont(self, nPage):
+        """ Returns The Primary Font For The Given Page nPage. """
+
+        if nPage < 0 or nPage >= self.GetPageCount():
+            raise "\nERROR: Invalid Notebook Page In GetPageTextFont: (" + 
str(nPage) + ")"
+
+        return self.nb.GetPageTextFont(nPage)
+
+
+    def SetPageTextSecondaryFont(self, nPage, font=None):
+        """ Sets The Secondary Font For The Given Page nPage. """
+
+        if nPage < 0 or nPage >= self.GetPageCount():
+            raise "\nERROR: Invalid Notebook Page In SetPageTextSecondaryFont: 
(" + str(nPage) + ")"
+
+        if font is None:
+            font = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
+
+        self.nb.SetPageTextSecondaryFont(nPage, font)
+
+
+    def GetPageTextSecondaryFont(self, nPage):
+        """ Returns The Secondary Font For The Given Page nPage. """
+
+        if nPage < 0 or nPage >= self.GetPageCount():
+            raise "\nERROR: Invalid Notebook Page In GetPageTextSecondaryFont: 
(" + str(nPage) + ")"
+
+        return self.nb.GetPageTextSecondaryFont(nPage)
+
+
+    def SetPageTextColour(self, nPage, colour=None):
+        """ Sets The Text Colour For The Given Page nPage. """
+
+        if nPage < 0 or nPage >= self.GetPageCount():
+            raise "\nERROR: Invalid Notebook Page In SetPageTextColour: (" + 
str(nPage) + ")"
+
+        if colour is None:
+            colour = wx.BLACK
+
+        self.nb.SetPageTextColour(nPage, colour)
+
+
+    def GetPageTextColour(self, nPage):
+        """ Returns The Text Colour For The Given Page nPage. """
+
+        if nPage < 0 or nPage >= self.GetPageCount():
+            raise "\nERROR: Invalid Notebook Page In GetPageTextColour: (" + 
str(nPage) + ")"
+
+        return self.nb.GetPageTextColour(nPage)
+
+
+    def SetPageColour(self, nPage, colour=None):
+        """ Sets The Tab Background Colour For The Given Page nPage. """
+
+        if nPage < 0 or nPage >= self.GetPageCount():
+            raise "\nERROR: Invalid Notebook Page In SetPageColour: (" + 
str(nPage) + ")"
+
+        if colour is None:
+            colour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNFACE)
+
+        self.nb.SetPageColour(nPage, colour)
+
+
+    def GetPageColour(self, nPage):
+        """ Returns The Tab Background Colour For The Given Page nPage. """
+
+        if nPage < 0 or nPage >= self.GetPageCount():
+            raise "\nERROR: Invalid Notebook Page In GetPageColour: (" + 
str(nPage) + ")"
+
+        return self.nb.GetPageColour(nPage)
+
+
+    def SetTabHeight(self, height=28):
+        """ Sets The Tabs Height. """
+
+        if height <= 0:
+            raise "\nERROR: Impossible To Set An Height <= 0. "
+
+        self.nb.SetTabHeight(height)
+
+
+    def SetControlBackgroundColour(self, colour=None):
+        """ Sets The TabCtrl Background Colour (Behind The Tabs). """
+
+        if colour is None:
+            colour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE)
+
+        self.nb.SetBackgroundColour(colour)
+
+
+    def ApplyTabTheme(self, theme=None):
+        """ Apply A Particular Theme To Be Drawn On Tabs. """
+
+        if theme is None:
+            theme = ThemeStyle()
+
+        self.nb.ApplyTabTheme(theme)
+
+
+    def SetSelectionColour(self, colour=None):
+        """ Sets The Tab Selection Colour (Thin Line Above The Selected Tab). 
"""
+
+        if colour is None:
+            colour = wx.Colour(255, 180, 0)
+
+        self.nb.SetSelectionColour(colour)
+
+
+    def SetContourLineColour(self, colour=None):
+        """ Sets The Contour Line Colour (Controur Line Around Tabs). """
+
+        self.nb.SetContourLineColour(colour)
+
+
+    def Tile(self, show=True, orient=None):
+        """ Shows Pages In Column/Row Mode (One Panel After The Other In 
Columns/Rows). """
+
+        if self._style & NC_TOP:
+            if not self.sizer.GetItem(0).IsShown() == show and orient is None:
+                return
+        else:
+            if not self.sizer.GetItem(2).IsShown() == show and orient is None:
+                return
+
+        self.Freeze()
+
+        if orient is not None and show:
+            if orient == wx.VERTICAL:
+                norient = wx.HORIZONTAL
+            else:
+                norient = wx.VERTICAL
+
+        if orient is not None and show:
+            origorient = self.bsizer.GetOrientation()
+            if origorient != norient:
+                for ii in xrange(self.GetPageCount()-1, -1, -1):
+                    self.bsizer.Detach(ii)
+
+                self.sizer.Detach(self.bsizer)
+                self.bsizer.Destroy()
+
+                self.bsizer = wx.BoxSizer(norient)
+
+                for ii in xrange(self.GetPageCount()):
+                    self.bsizer.Add(self._notebookpages[ii], 1, wx.EXPAND | 
wx.ALL, 2)
+
+                if self._style & NC_TOP:
+                    self.sizer.Add(self.bsizer, 1, wx.EXPAND)
+                else:
+                    self.sizer.Insert(0, self.bsizer, 1, wx.EXPAND)
+
+                self.bsizer.Layout()
+                self.sizer.Layout()
+
+        selection = self.GetSelection()
+
+        if show:
+            if self._style & NC_TOP:
+                self.sizer.Show(0, False)
+                self.sizer.Show(1, False)
+                if len(self.nb._selectedtabs) > 0:
+                    for ii in xrange(self.GetPageCount()):
+                        if ii in self.nb._selectedtabs:
+                            self.bsizer.Show(ii, True)
+                        else:
+                            self.bsizer.Show(ii, False)
+                else:
+                    for ii in xrange(self.GetPageCount()):
+                        if self.IsPageEnabled(ii):
+                            if not self.nb._enablehiding or not 
self.nb._pages[ii]._ishidden:
+                                self.bsizer.Show(ii, True)
+                            else:
+                                self.bsizer.Show(ii, False)
+                        else:
+                            self.bsizer.Show(ii, False)
+            else:
+                self.sizer.Show(1, False)
+                self.sizer.Show(2, False)
+                if len(self.nb._selectedtabs) > 0:
+                    for ii in xrange(self.GetPageCount()):
+                        if ii in self.nb._selectedtabs:
+                            self.bsizer.Show(ii, True)
+                else:
+                    for ii in xrange(self.GetPageCount()):
+                        if self.IsPageEnabled(ii):
+                            if not self.nb._enablehiding or not 
self.nb._pages[ii]._ishidden:
+                                self.bsizer.Show(ii, True)
+                            else:
+                                self.bsizer.Show(ii, False)
+                        else:
+                            self.bsizer.Show(ii, False)
+        else:
+            if self._style & NC_TOP:
+                self.sizer.Show(0, True)
+                self.sizer.Show(1, True)
+                for ii in xrange(self.GetPageCount()):
+                    self.bsizer.Show(ii, False)
+            else:
+                self.sizer.Show(1, True)
+                self.sizer.Show(2, True)
+                for ii in xrange(self.GetPageCount()):
+                    self.bsizer.Show(ii, False)
+
+            if selection < 0:
+                self.bsizer.Layout()
+                self.sizer.Layout()
+                return
+            else:
+                self.bsizer.Show(selection, True)
+                self.bsizer.Layout()
+
+        self._showcolumns = show
+
+        self.bsizer.Layout()
+        self.sizer.Layout()
+
+        self.Thaw()
+
+
+    def ShowTabs(self, show=True):
+        """ Shows/Hides Tabs On Request. """
+
+        if self._style & NC_TOP:
+            if self.sizer.GetItem(0).IsShown() == show:
+                return
+        else:
+            if self.sizer.GetItem(2).IsShown() == show:
+                return
+
+        if self.GetPageCount() == 0:
+            return
+
+        self.Freeze()
+
+        if not show:
+
+            if self._style & NC_TOP:
+                self.sizer.Show(0, False)
+                self.sizer.Show(1, False)
+            else:
+                self.sizer.Show(1, False)
+                self.sizer.Show(2, False)
+
+        else:
+
+            if self._style & NC_TOP:
+                self.sizer.Show(0, True)
+                self.sizer.Show(1, True)
+            else:
+                self.sizer.Show(1, True)
+                self.sizer.Show(2, True)
+
+        self._showtabs = show
+
+        self.sizer.Layout()
+
+        self.Thaw()
+
+
+    def GetIndex(self, page):
+        """ Returns The Page Index (Position) Based On The NotebookCtrl Page 
Passed. """
+
+        if page in self._notebookpages:
+            return self._notebookpages.index(page)
+
+        return -1
+
+
+    def ReparentPage(self, nPage, newParent):
+        """ Reparents The NotebookCtrl Page nPage To A New Parent. """
+
+        if nPage < 0 or (self.GetSelection() >= 0 and nPage >= 
self.GetPageCount()):
+            raise "\nERROR: Invalid Notebook Page In ReparentPage: (" + 
str(nPage) + ")"
+
+        page = self.GetPage(nPage)
+        page.Reparent(newParent)
+
+
+    def ReparentToFrame(self, nPage, createNotebook=False):
+        """ Reparents The NotebookCtrl Page nPage To A New Frame. """
+
+        if nPage < 0 or (self.GetSelection() >= 0 and nPage >= 
self.GetPageCount()):
+            raise "\nERROR: Invalid Notebook Page In ReparentToFrame: (" + 
str(nPage) + ")"
+
+        self.Freeze()
+
+        infos = self.GetPageInfo(nPage)
+        panel = self.GetPage(nPage)
+        text = infos["text"]
+        oldparent = panel.GetParent()
+
+        frame = NCFrame(None, -1, text, nb=self, infos=infos, panel=panel, 
oldparent=oldparent)
+
+        if createNotebook:
+            nb = NotebookCtrl(frame, -1, style=self._style, 
sizer=self._sizerstyle)
+            nb.SetImageList(infos["imagelist"])
+            self.ReparentToNotebook(nPage, nb)
+        else:
+            self.ReparentPage(nPage, frame)
+
+            self.nb.DeletePage(nPage, False)
+
+            self.bsizer.Detach(nPage)
+            self.bsizer.Layout()
+            self.sizer.Layout()
+
+            self._notebookpages.pop(nPage)
+
+            self.AdvanceSelection()
+
+        if self.GetPageCount() == 0:
+            if self._style & NC_TOP:
+                self.sizer.Show(0, False)
+                self.sizer.Show(1, False)
+            else:
+                self.sizer.Show(1, False)
+                self.sizer.Show(2, False)
+
+            self.sizer.Layout()
+
+        custom = self.GetCustomPage()
+        if custom is not None:
+            self.SetCustomPage(custom)
+
+        self.Thaw()
+
+        frame.Show()
+
+
+    def ReparentToNotebook(self, nPage, notebook, newPage=None):
+        """ Reparents The NotebookCtrl Page nPage To A New NotebookCtrl. """
+
+        if nPage < 0 or (self.GetSelection() >= 0 and nPage >= 
self.GetPageCount()):
+            raise "\nERROR: Invalid Notebook Page In ReparentToNotebook: (" + 
str(nPage) + ")"
+
+        if newPage is not None and newPage >= notebook.GetPageCount():
+            raise "\nERROR: Invalid Notebook New Page In ReparentToNotebook: 
(" + str(nPage) + ")"
+
+        self.Freeze()
+
+        infos = self.GetPageInfo(nPage)
+        panel = self.GetPage(nPage)
+
+        self.ReparentPage(nPage, notebook)
+
+        if newPage is None:
+            notebook.AddPage(panel, infos["text"], False, infos["image"])
+            notebook.SetPageInfo(0, infos)
+
+        for attr in attrs:
+            setattr(notebook, attr, getattr(self.nb, attr))
+
+        self.nb.DeletePage(nPage, False)
+
+        self.bsizer.Detach(nPage)
+        self.bsizer.Layout()
+        self.sizer.Layout()
+
+        self._notebookpages.pop(nPage)
+
+        self.AdvanceSelection()
+
+        if self.GetPageCount() == 0:
+            if self._style & NC_TOP:
+                self.sizer.Show(0, False)
+                self.sizer.Show(1, False)
+            else:
+                self.sizer.Show(1, False)
+                self.sizer.Show(2, False)
+
+            self.sizer.Layout()
+
+        self.Thaw()
+
+
+    def GetPageInfo(self, nPage):
+        """ Returns All The Style Information For A Given Page. """
+
+        if nPage < 0 or (self.GetSelection() >= 0 and nPage >= 
self.GetPageCount()):
+            raise "\nERROR: Invalid Notebook Page In GetPageInfo: (" + 
str(nPage) + ")"
+
+        text = self.GetPageText(nPage)
+        image = self.GetPageImage(nPage)
+        font1 = self.GetPageTextFont(nPage)
+        font2 = self.GetPageTextSecondaryFont(nPage)
+        fontcolour = self.GetPageTextColour(nPage)
+        pagecolour = self.GetPageColour(nPage)
+        enabled = self.IsPageEnabled(nPage)
+        tooltip, ontime, winsize = self.GetPageToolTip(nPage)
+        menu = self.GetPagePopupMenu(nPage)
+        firstcol = self.GetPageFirstGradientColour(nPage)
+        secondcol = self.GetPageSecondGradientColour(nPage)
+        ishidden = self.nb._pages[nPage]._ishidden
+
+        isanimated = 0
+        timer = None
+
+        if self.nb._timers[nPage].IsRunning():
+            isanimated = 1
+            timer = self.nb._timers[nPage].GetInterval()
+
+        self.StopAnimation(nPage)
+        animatedimages = self.GetAnimationImages(nPage)
+
+        infos = {"text": text, "image": image, "font1": font1, "font2": font2,
+                 "fontcolour": fontcolour, "pagecolour": pagecolour, 
"enabled": enabled,
+                 "tooltip": tooltip, "ontime": ontime, "winsize": winsize,
+                 "menu": menu, "isanimated": isanimated, "timer": timer,
+                 "animatedimages": animatedimages, "imagelist": 
self.nb._imglist,
+                 "firstcol": firstcol, "secondcol": secondcol, "ishidden": 
ishidden}
+
+        return infos
+
+
+    def SetPageInfo(self, nPage, infos):
+        """ Sets All The Style Information For A Given Page. """
+
+        if nPage < 0 or (self.GetSelection() >= 0 and nPage >= 
self.GetPageCount()):
+            raise "\nERROR: Invalid Notebook Page In SetPageInfo: (" + 
str(nPage) + ")"
+
+        self.SetPageTextFont(nPage, infos["font1"])
+        self.SetPageTextSecondaryFont(nPage, infos["font2"])
+        self.SetPageTextColour(nPage, infos["fontcolour"])
+        self.SetPageColour(nPage, infos["pagecolour"])
+        self.EnablePage(nPage, infos["enabled"])
+        self.SetPageToolTip(nPage, infos["tooltip"], infos["ontime"], 
infos["winsize"])
+        self.SetPagePopupMenu(nPage, infos["menu"])
+        self.SetPageFirstGradientColour(nPage, infos["firstcol"])
+        self.SetPageSecondGradientColour(nPage, infos["secondcol"])
+        self.nb._pages[nPage]._ishidden = infos["ishidden"]
+
+        if infos["isanimated"] and len(infos["animatedimages"]) > 1:
+            self.SetAnimationImages(nPage, infos["animatedimages"])
+            self.StartAnimation(nPage, infos["timer"])
+
+
+    def SetCustomPage(self, panel):
+        """ Sets A Custom Panel To Show When There Are No Pages Left In 
NotebookCtrl. """
+
+        self.Freeze()
+
+        if panel is None:
+            if self._custompanel is not None:
+                self.bsizer.Detach(self._custompanel)
+                self._custompanel.Show(False)
+
+            if self.GetPageCount() == 0:
+                if self._style & NC_TOP:
+                    self.sizer.Show(0, False)
+                    self.sizer.Show(1, False)
+                else:
+                    self.sizer.Show(1, False)
+                    self.sizer.Show(2, False)
+        else:
+            if self.GetPageCount() == 0:
+                if self._custompanel is not None:
+                    self.bsizer.Detach(self._custompanel)
+                    self._custompanel.Show(False)
+
+                self.bsizer.Add(panel, 1, wx.EXPAND | wx.ALL, 2)
+                panel.Show(True)
+                if self._style & NC_TOP:
+                    self.sizer.Show(0, False)
+                    self.sizer.Show(1, False)
+                else:
+                    self.sizer.Show(1, False)
+                    self.sizer.Show(2, False)
+            else:
+                panel.Show(False)
+
+        self._custompanel = panel
+
+        self.bsizer.Layout()
+        self.sizer.Layout()
+        self.Thaw()
+
+
+    def GetCustomPage(self):
+        """ Gets A Custom Panel To Show When There Are No Pages Left In 
NotebookCtrl. """
+
+        return self._custompanel
+
+
+    def HideTab(self, nPage, hide=True):
+        """ Hides A Tab In The NotebookCtrl. """
+
+        self.nb.HideTab(nPage, hide)
+
+
+    def HitTest(self, point, flags=0):
+        """
+        Standard NotebookCtrl HitTest() Method. If Called With 2 Outputs, It
+        Returns The Page Clicked (If Any) And One Of These Flags:
+
+        NC_HITTEST_NOWHERE = 0   ==> Hit Not On Tab
+        NC_HITTEST_ONICON  = 1   ==> Hit On Icon
+        NC_HITTEST_ONLABEL = 2   ==> Hit On Label
+        NC_HITTEST_ONITEM  = 4   ==> Hit Generic, On Item
+        NC_HITTEST_ONX = 8       ==> Hit On Closing "X" On Every Page
+        """
+
+        return self.nb.HitTest(point, flags)
+
+
+# ---------------------------------------------------------------------------- 
#
+# Class TransientTipWindow
+# Auxiliary Help Class. Used To Build The Tip Window.
+# ---------------------------------------------------------------------------- 
#
+
+class _PopupWindow:
+
+    def _Fill(self, tip, winsize):
+
+        panel = wx.Panel(self, -1)
+        colour = self.GetParent().GetToolTipBackgroundColour()
+
+        panel.SetBackgroundColour(colour)
+
+        # border from sides and top to text (in pixels)
+        border = 5
+        # how much space between text lines
+        textPadding = 2
+        max_len = len(tip)
+        tw = winsize
+
+        mylines = tip.split("\n")
+
+        sts = wx.StaticText(panel, -1, "\n".join(mylines))
+        sx, sy = sts.GetBestSize()
+        sts.SetPosition((2, 2))
+
+        panel.SetSize((sx+6, sy+6))
+        self.SetSize(panel.GetSize())
+
+
+class TransientTipWindow(_PopupWindow, wx.PopupWindow):
+
+    def __init__(self, parent, tip, winsize):
+
+        wx.PopupWindow.__init__(self, parent, flags=wx.SIMPLE_BORDER)
+        self._Fill(tip,winsize)
+
+
+    def ProcessLeftDown(self, evt):
+
+        return False
+
+
+    def OnDismiss(self):
+
+        return False
+
+
+class macPopupWindow(wx.Frame):
+
+    def __init__(self, parent, flags):
+
+        wx.Frame.__init__(self, parent, id=-1, 
style=flags|wx.FRAME_NO_TASKBAR|wx.STAY_ON_TOP)
+        self._hideOnActivate = False
+        #Get the parent frame: could be improved maybe?
+        self._parentFrame = parent
+
+        while True:
+
+            parent = self._parentFrame.GetParent()
+
+            if parent:
+                self._parentFrame = parent
+            else:
+                break
+
+        self.Bind(wx.EVT_ACTIVATE, self.OnActivate)
+
+
+    def Show(self, show=True):
+
+        wx.Frame.Show(self,show)
+
+        if show:
+            self._parentFrame.Raise()
+            self._hideOnActivate = True
+
+
+    def OnActivate(self, evt):
+        """
+        Let The User Hide The Tooltip By Clicking On It.
+        NotebookCtrl Will Destroy It Later.
+        """
+
+        if self._hideOnActivate:
+            wx.Frame.Show(self,False)
+
+
+class macTransientTipWindow(_PopupWindow, macPopupWindow):
+
+    def __init__(self, parent, tip, winsize):
+
+        macPopupWindow.__init__(self, parent, flags=wx.SIMPLE_BORDER)
+        self._Fill(tip, winsize)
+
+
+class NCFrame(wx.Frame):
+
+    def __init__(self, parent, id=wx.ID_ANY, title="", pos=wx.DefaultPosition,
+                 size=wx.DefaultSize, style=wx.DEFAULT_FRAME_STYLE, nb=None,
+                 panel=None, infos=None, oldparent=None):
+
+        wx.Frame.__init__(self, parent, id, title, pos, size, style)
+
+        self._infos = infos
+        self._nb = nb
+        self._panel = panel
+        self._oldparent = oldparent
+
+        self.Bind(wx.EVT_CLOSE, self.OnClose)
+
+
+    def OnClose(self, event):
+
+        try:
+            infos = self._infos
+            self._panel.Reparent(self._oldparent)
+            self._nb.AddPage(self._panel, infos["text"], False, infos["image"])
+
+            id = self._nb.GetPageCount() - 1
+
+            self._nb.SetPageTextFont(id, infos["font1"])
+            self._nb.SetPageTextSecondaryFont(id, infos["font2"])
+            self._nb.SetPageTextColour(id, infos["fontcolour"])
+            self._nb.SetPageColour(id, infos["pagecolour"])
+            self._nb.EnablePage(id, infos["enabled"])
+            self._nb.SetPageToolTip(id, infos["tooltip"], infos["ontime"], 
infos["winsize"])
+            self._nb.SetPagePopupMenu(id, infos["menu"])
+            self._nb.SetPageFirstGradientColour(id, infos["firstcol"])
+            self._nb.SetPageSecondGradientColour(id, infos["secondcol"])
+            self._nb._pages[id]._ishidden = infos["ishidden"]
+
+            if infos["isanimated"] and len(infos["animatedimages"]) > 1:
+                self._nb.SetAnimationImages(id, infos["animatedimages"])
+                self._nb.StartAnimation(id, infos["timer"])
+
+        except:
+            self.Destroy()
+            event.Skip()
+            return
+
+        self.Destroy()
+
+        event.Skip()
+

Modified: trunk/gnue-designer/src/uidrivers/wx/uihelpers/PyAUI.py
===================================================================
--- trunk/gnue-designer/src/uidrivers/wx/uihelpers/PyAUI.py     2006-03-06 
14:25:55 UTC (rev 8207)
+++ trunk/gnue-designer/src/uidrivers/wx/uihelpers/PyAUI.py     2006-03-06 
14:54:02 UTC (rev 8208)
@@ -19,7 +19,7 @@
 # PyAUI version 0.9.1 Adds:
 #
 # * Support For MDI Frames;
-# * Gradient Captions Option; 
+# * Gradient Captions Option;
 # * Active/Inactive Panes Option;
 # * Support For Vertical Toolbars;
 # * Fix For Screen Artifacts/Paint Problems;
@@ -44,7 +44,7 @@
 #
 # Or, Obviously, To The wxPython Mailing List!!!
 #
-# with OS X support and refactoring implemented by Chris Mellon 
(address@hidden) - 
+# with OS X support and refactoring implemented by Chris Mellon 
(address@hidden) -
 #    contact me directly or on wxPython ML for more info
 #
 #
@@ -62,26 +62,26 @@
 
 * Frame Management: Frame management provides the means to open, move and hide 
common
 controls that are needed to interact with the document, and allow these 
configurations
-to be saved into different perspectives and loaded at a later time. 
+to be saved into different perspectives and loaded at a later time.
 
 * Toolbars: Toolbars are a specialized subset of the frame management system 
and should
 behave similarly to other docked components. However, they also require 
additional
 functionality, such as "spring-loaded" rebar support, "chevron" buttons and 
end-user
-customizability. 
+customizability.
 
 * Modeless Controls: Modeless controls expose a tool palette or set of options 
that
 float above the application content while allowing it to be accessed. Usually 
accessed
 by the toolbar, these controls disappear when an option is selected, but may 
also be
-"torn off" the toolbar into a floating frame of their own. 
+"torn off" the toolbar into a floating frame of their own.
 
 * Look and Feel: Look and feel encompasses the way controls are drawn, both 
when shown
 statically as well as when they are being moved. This aspect of user interface 
design
-incorporates "special effects" such as transparent window dragging as well as 
frame animation. 
+incorporates "special effects" such as transparent window dragging as well as 
frame animation.
 
 PyAUI adheres to the following principles:
 
 - Use native floating frames to obtain a native look and feel for all 
platforms;
-- Use existing wxPython code where possible, such as sizer implementation for 
frame management; 
+- Use existing wxPython code where possible, such as sizer implementation for 
frame management;
 - Use standard wxPython coding conventions.
 
 
@@ -98,7 +98,7 @@
         wx.Frame.__init__(self, parent, id, title, pos, size, style)
 
         self._mgr = PyAUI.FrameManager(self)
-        
+
         # notify PyAUI which frame to use
         self._mgr.SetFrame(self)
 
@@ -106,20 +106,20 @@
         text1 = wx.TextCtrl(self, -1, "Pane 1 - sample text",
                             wx.DefaultPosition, wx.Size(200,150),
                             wx.NO_BORDER | wx.TE_MULTILINE)
-                                           
+
         text2 = wx.TextCtrl(self, -1, "Pane 2 - sample text",
                             wx.DefaultPosition, wx.Size(200,150),
                             wx.NO_BORDER | wx.TE_MULTILINE)
-                                           
+
         text3 = wx.TextCtrl(self, -1, "Main content window",
                             wx.DefaultPosition, wx.Size(200,150),
                             wx.NO_BORDER | wx.TE_MULTILINE)
-        
+
         # add the panes to the manager
         self._mgr.AddPane(text1, wx.LEFT, "Pane Number One")
         self._mgr.AddPane(text2, wx.BOTTOM, "Pane Number Two")
         self._mgr.AddPane(text3, wx.CENTER)
-                              
+
         # tell the manager to "commit" all the changes just made
         self._mgr.Update()
 
@@ -131,8 +131,8 @@
         # deinitialize the frame manager
         self._mgr.UnInit()
 
-        self.Destroy()        
-        event.Skip()        
+        self.Destroy()
+        event.Skip()
 
 
 # our normal wx.App-derived class, as usual
@@ -150,7 +150,7 @@
 PyAUI version 0.9.1 Adds:
 
 * Support For MDI Frames;
-* Gradient Captions Option; 
+* Gradient Captions Option;
 * Active/Inactive Panes Option;
 * Support For Vertical Toolbars;
 * Fix For Screen Artifacts/Paint Problems;
@@ -161,10 +161,10 @@
 
 License And Version:
 
-PyAUI Library Is Freeware And Distributed Under The wxPython License. 
+PyAUI Library Is Freeware And Distributed Under The wxPython License.
 
 Latest Revision: Andrea Gavana @ 23 Jan 2006, 00.00 CET
-Version 0.9.1. 
+Version 0.9.1.
 
 """
 
@@ -212,7 +212,7 @@
                       "The Latest wxPython Version."
 
     else:
-        raise "\nSorry: I Still Don't Know How To Work On GTK/MAC Platforms... 
" \
+        print "\nSorry: I Still Don't Know How To Work On GTK/MAC Platforms... 
" \
               "Please Download The Latest wxPython Version."
 
 
@@ -238,7 +238,7 @@
 AUI_MGR_TRANSPARENT_DRAG      = 4
 AUI_MGR_TRANSPARENT_HINT      = 8
 AUI_MGR_TRANSPARENT_HINT_FADE = 16
-    
+
 AUI_MGR_DEFAULT = AUI_MGR_ALLOW_FLOATING | \
                   AUI_MGR_TRANSPARENT_HINT | \
                   AUI_MGR_TRANSPARENT_HINT_FADE | \
@@ -268,7 +268,7 @@
 AUI_GRADIENT_VERTICAL = 1
 AUI_GRADIENT_HORIZONTAL = 2
 
-# Pane Button State    
+# Pane Button State
 AUI_BUTTON_STATE_NORMAL = 0
 AUI_BUTTON_STATE_HOVER = 1
 AUI_BUTTON_STATE_PRESSED = 2
@@ -331,7 +331,7 @@
     r = c.Red()
     g = c.Green()
     b = c.Blue()
-    
+
     return wx.Colour(min((r*percent)/100, 255),
                      min((g*percent)/100, 255),
                      min((b*percent)/100, 255))
@@ -354,16 +354,16 @@
     BitmapFromBits() is a utility function that creates a
     masked bitmap from raw bits (XBM format).
     """
-    
+
     if type == 0:   # Close Bitmap
         img = GetCloseImage()
     else:
         # this should be GetClosePin()... but what the hell is a "pin"?
         img = GetCloseImage()
-        
+
     img.Replace(255, 255, 255, 123, 123, 123)
     img.Replace(0, 0, 0, color.Red(), color.Green(), color.Blue())
-    
+
     return img.ConvertToBitmap()
 
 
@@ -395,7 +395,7 @@
 class DockInfo:
 
     def __init__(self):
-        
+
         self.dock_direction = 0
         self.dock_layer = 0
         self.dock_row = 0
@@ -412,7 +412,7 @@
 
         return (self.dock_direction != 0 and [True] or [False])[0]
 
-    
+
     def IsHorizontal(self):
 
         return ((self.dock_direction == AUI_DOCK_TOP or \
@@ -425,10 +425,10 @@
         return ((self.dock_direction == AUI_DOCK_LEFT or \
                 self.dock_direction == AUI_DOCK_RIGHT or \
                 self.dock_direction == AUI_DOCK_CENTER) and [True] or 
[False])[0]
-    
 
+
 class DockUIPart:
-    
+
     typeCaption = 0
     typeGripper = 1
     typeDock = 2
@@ -448,7 +448,7 @@
 
 class PaneButton:
 
-    def __init__(self, button_id):    
+    def __init__(self, button_id):
 
         self.button_id = button_id
 
@@ -460,23 +460,23 @@
     def __init__(self, eventType, id=1):
 
         wx.PyCommandEvent.__init__(self, eventType, id)
-        
+
         self.pane = None
         self.button = 0
 
 
     def SetPane(self, p):
-        
+
         self.pane = p
 
-        
+
     def SetButton(self, b):
-        
+
         self.button = b
 
-        
+
     def GetPane(self):
-        
+
         return self.pane
 
 
@@ -531,7 +531,7 @@
         self._inactive_pin_bitmap = 
BitmapFromBits(self._inactive_caption_text_colour, 1)
         self._active_close_bitmap = 
BitmapFromBits(self._active_caption_text_colour, 0)
         self._active_pin_bitmap = 
BitmapFromBits(self._active_caption_text_colour, 1)
-        
+
         # default metric values
         self._sash_size = 4
         self._caption_size = 17
@@ -539,8 +539,8 @@
         self._button_size = 14
         self._gripper_size = 9
         self._gradient_type = AUI_GRADIENT_VERTICAL
-        
 
+
     def GetMetric(self, id):
 
         if id == AUI_ART_SASH_SIZE:
@@ -594,7 +594,7 @@
         elif id == AUI_ART_ACTIVE_CAPTION_GRADIENT_COLOUR:
             return self._active_caption_gradient_colour
         elif id == AUI_ART_ACTIVE_CAPTION_TEXT_COLOUR:
-            return self._active_caption_text_colour        
+            return self._active_caption_text_colour
         elif id == AUI_ART_BORDER_COLOUR:
             return self._border_pen.GetColour()
         elif id == AUI_ART_GRIPPER_COLOUR:
@@ -629,8 +629,8 @@
             self._gripper_pen2.SetColour(DarkenColor(colour, 60))
         else:
             raise "\nERROR: Invalid Metric Ordinal. "
-        
 
+
     def SetFont(self, id, font):
 
         if id == AUI_ART_CAPTION_FONT:
@@ -641,7 +641,7 @@
 
         if id == AUI_ART_CAPTION_FONT:
             return self._caption_font
-        
+
         return wx.NoneFont
 
 
@@ -666,34 +666,34 @@
         drect.y = rect.y
         drect.width = rect.width
         drect.height = rect.height
-        
+
         dc.SetPen(self._border_pen)
         dc.SetBrush(wx.TRANSPARENT_BRUSH)
 
         border_width = self.GetMetric(AUI_ART_PANE_BORDER_SIZE)
 
         if pane.IsToolbar():
-        
+
             for ii in xrange(0, border_width):
-            
+
                 dc.SetPen(wx.WHITE_PEN)
                 dc.DrawLine(drect.x, drect.y, drect.x+drect.width, drect.y)
                 dc.DrawLine(drect.x, drect.y, drect.x, drect.y+drect.height)
-                dc.SetPen(self._border_pen)       
+                dc.SetPen(self._border_pen)
                 dc.DrawLine(drect.x, drect.y+drect.height-1,
                             drect.x+drect.width, drect.y+drect.height-1)
                 dc.DrawLine(drect.x+drect.width-1, drect.y,
                             drect.x+drect.width-1, drect.y+drect.height)
                 drect.Deflate(1, 1)
-        
+
         else:
-        
+
             for ii in xrange(0, border_width):
-            
+
                 dc.DrawRectangle(drect.x, drect.y, drect.width, drect.height)
                 drect.Deflate(1, 1)
-            
 
+
     def DrawCaptionBackground(self, dc, rect, active):
 
         if self._gradient_type == AUI_GRADIENT_NONE:
@@ -702,7 +702,7 @@
             else:
                 dc.SetBrush(wx.Brush(self._inactive_caption_colour))
 
-            dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height)        
+            dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height)
         else:
             if active:
                 DrawGradientRectangle(dc, rect, self._active_caption_colour,
@@ -745,34 +745,34 @@
             y = 5
             while 1:
                 dc.SetPen(self._gripper_pen1)
-                dc.DrawPoint(rect.x+3, rect.y+y) 
-                dc.SetPen(self._gripper_pen2) 
-                dc.DrawPoint(rect.x+3, rect.y+y+1) 
-                dc.DrawPoint(rect.x+4, rect.y+y) 
-                dc.SetPen(self._gripper_pen3) 
-                dc.DrawPoint(rect.x+5, rect.y+y+1) 
-                dc.DrawPoint(rect.x+5, rect.y+y+2) 
-                dc.DrawPoint(rect.x+4, rect.y+y+2) 
-                y = y + 4 
+                dc.DrawPoint(rect.x+3, rect.y+y)
+                dc.SetPen(self._gripper_pen2)
+                dc.DrawPoint(rect.x+3, rect.y+y+1)
+                dc.DrawPoint(rect.x+4, rect.y+y)
+                dc.SetPen(self._gripper_pen3)
+                dc.DrawPoint(rect.x+5, rect.y+y+1)
+                dc.DrawPoint(rect.x+5, rect.y+y+2)
+                dc.DrawPoint(rect.x+4, rect.y+y+2)
+                y = y + 4
                 if y > rect.GetHeight() - 5:
                     break
         else:
             x = 5
             while 1:
-                dc.SetPen(self._gripper_pen1) 
-                dc.DrawPoint(rect.x+x, rect.y+3) 
-                dc.SetPen(self._gripper_pen2) 
-                dc.DrawPoint(rect.x+x+1, rect.y+3) 
-                dc.DrawPoint(rect.x+x, rect.y+4) 
-                dc.SetPen(self._gripper_pen3) 
-                dc.DrawPoint(rect.x+x+1, rect.y+5) 
-                dc.DrawPoint(rect.x+x+2, rect.y+5) 
-                dc.DrawPoint(rect.x+x+2, rect.y+4) 
-                x = x + 4 
+                dc.SetPen(self._gripper_pen1)
+                dc.DrawPoint(rect.x+x, rect.y+3)
+                dc.SetPen(self._gripper_pen2)
+                dc.DrawPoint(rect.x+x+1, rect.y+3)
+                dc.DrawPoint(rect.x+x, rect.y+4)
+                dc.SetPen(self._gripper_pen3)
+                dc.DrawPoint(rect.x+x+1, rect.y+5)
+                dc.DrawPoint(rect.x+x+2, rect.y+5)
+                dc.DrawPoint(rect.x+x+2, rect.y+4)
+                x = x + 4
                 if x > rect.GetWidth() - 5:
-                    break 
-        
+                    break
 
+
     def DrawPaneButton(self, dc, button, button_state, rect, pane):
 
         drect = wx.Rect()
@@ -780,14 +780,14 @@
         drect.y = rect.y
         drect.width = rect.width
         drect.height = rect.height
-        
+
         if button_state == AUI_BUTTON_STATE_PRESSED:
-        
+
             drect.x = drect.x + 1
             drect.y = drect.y + 1
-        
+
         if button_state in [AUI_BUTTON_STATE_HOVER, AUI_BUTTON_STATE_PRESSED]:
-        
+
             if pane.state & PaneInfo.optionActive:
                 dc.SetBrush(wx.Brush(StepColour(self._active_caption_colour, 
120)))
                 dc.SetPen(wx.Pen(StepColour(self._active_caption_colour, 70)))
@@ -800,16 +800,16 @@
 
         if button == PaneInfo.buttonClose:
             if pane.state & PaneInfo.optionActive:
-                
+
                 bmp = self._active_close_bitmap
-            
+
             else:
                 bmp = self._inactive_close_bitmap
         elif button == PaneInfo.buttonPin:
             if pane.state & PaneInfo.optionActive:
-                
+
                 bmp = self._active_pin_bitmap
-            
+
             else:
                 bmp = self._inactive_pin_bitmap
 
@@ -822,10 +822,10 @@
 # PaneInfo specifies all the parameters for a pane. These parameters specify 
where
 # the pane is on the screen, whether it is docked or floating, or hidden. In 
addition,
 # these parameters specify the pane's docked position, floating position, 
preferred
-# size, minimum size, caption text among many other parameters. 
+# size, minimum size, caption text among many other parameters.
 
 class PaneInfo:
-    
+
     optionFloating        = 2**0
     optionHidden          = 2**1
     optionLeftDockable    = 2**2
@@ -853,7 +853,7 @@
     actionPane            = 2**31    # used internally
 
     def __init__(self):
-        
+
         self.window = None
         self.frame = None
         self.state = 0
@@ -871,95 +871,95 @@
         self.buttons = []
         self.name = ""
         self.rect = wx.Rect()
-        
+
         self.DefaultPane()
-    
 
+
     def IsOk(self):
         """ IsOk() returns True if the PaneInfo structure is valid. """
-        
+
         return (self.window != None and [True] or [False])[0]
 
 
     def IsFixed(self):
         """ IsFixed() returns True if the pane cannot be resized. """
-        
+
         return not self.HasFlag(self.optionResizable)
 
-    
+
     def IsResizable(self):
         """ IsResizeable() returns True if the pane can be resized. """
-        
+
         return self.HasFlag(self.optionResizable)
 
-    
+
     def IsShown(self):
         """ IsShown() returns True if the pane should be drawn on the screen. 
"""
-        
+
         return not self.HasFlag(self.optionHidden)
 
-    
+
     def IsFloating(self):
         """ IsFloating() returns True if the pane is floating. """
 
         return self.HasFlag(self.optionFloating)
 
-    
+
     def IsDocked(self):
         """ IsDocked() returns True if the pane is docked. """
-        
+
         return not self.HasFlag(self.optionFloating)
 
-    
+
     def IsToolbar(self):
         """ IsToolbar() returns True if the pane contains a toolbar. """
 
         return self.HasFlag(self.optionToolbar)
 
-    
+
     def IsTopDockable(self):
         """
         IsTopDockable() returns True if the pane can be docked at the top
         of the managed frame.
         """
-        
+
         return self.HasFlag(self.optionTopDockable)
 
-    
+
     def IsBottomDockable(self):
         """
         IsBottomDockable() returns True if the pane can be docked at the bottom
         of the managed frame.
         """
-        
+
         return self.HasFlag(self.optionBottomDockable)
 
-    
+
     def IsLeftDockable(self):
         """
         IsLeftDockable() returns True if the pane can be docked at the left
         of the managed frame.
         """
-        
-        return self.HasFlag(self.optionLeftDockable) 
 
+        return self.HasFlag(self.optionLeftDockable)
 
+
     def IsRightDockable(self):
         """
         IsRightDockable() returns True if the pane can be docked at the right
         of the managed frame.
         """
-        
+
         return self.HasFlag(self.optionRightDockable)
 
 
     def IsDockable(self):
         """ IsDockable() returns True if the pane can be docked. """
-        
+
         return self.IsTopDockable() or self.IsBottomDockable() or 
self.IsLeftDockable() or \
                self.IsRightDockable()
-    
-    
+
+
     def IsFloatable(self):
         """
         IsFloatable() returns True if the pane can be undocked and displayed 
as a
@@ -968,41 +968,41 @@
 
         return self.HasFlag(self.optionFloatable)
 
-    
+
     def IsMovable(self):
         """
         IsMoveable() returns True if the docked frame can be undocked or moved 
to
         another dock position.
         """
-        
+
         return self.HasFlag(self.optionMovable)
-    
 
+
     def HasCaption(self):
         """ HasCaption() returns True if the pane displays a caption. """
-        
+
         return self.HasFlag(self.optionCaption)
-    
 
+
     def HasGripper(self):
         """ HasGripper() returns True if the pane displays a gripper. """
-        
-        return self.HasFlag(self.optionGripper) 
 
+        return self.HasFlag(self.optionGripper)
 
+
     def HasBorder(self):
         """ HasBorder() returns True if the pane displays a border. """
-        
+
         return self.HasFlag(self.optionPaneBorder)
 
-    
+
     def HasCloseButton(self):
         """
         HasCloseButton() returns True if the pane displays a button to close
         the pane.
         """
 
-        return self.HasFlag(self.buttonClose) 
+        return self.HasFlag(self.buttonClose)
 
 
     def HasMaximizeButton(self):
@@ -1010,25 +1010,25 @@
         HasMaximizeButton() returns True if the pane displays a button to
         maximize the pane.
         """
-        
+
         return self.HasFlag(self.buttonMaximize)
 
-    
+
     def HasMinimizeButton(self):
         """
         HasMinimizeButton() returns True if the pane displays a button to
         minimize the pane.
         """
-        
-        return self.HasFlag(self.buttonMinimize) 
 
+        return self.HasFlag(self.buttonMinimize)
 
+
     def HasPinButton(self):
         """ HasPinButton() returns True if the pane displays a button to float 
the pane. """
-        
-        return self.HasFlag(self.buttonPin) 
 
+        return self.HasFlag(self.buttonPin)
 
+
     def HasGripperTop(self):
 
         return self.HasFlag(self.optionGripperTop)
@@ -1039,84 +1039,84 @@
         self.window = w
         return self
 
-    
+
     def Name(self, n):
         """ Name() sets the name of the pane so it can be referenced in lookup 
functions. """
 
         self.name = n
         return self
 
-    
+
     def Caption(self, c):
         """ Caption() sets the caption of the pane. """
-        
+
         self.caption = c
         return self
 
-    
+
     def Left(self):
         """ Left() sets the pane dock position to the left side of the frame. 
"""
-        
+
         self.dock_direction = AUI_DOCK_LEFT
         return self
 
-    
+
     def Right(self):
         """ Right() sets the pane dock position to the right side of the 
frame. """
-        
+
         self.dock_direction = AUI_DOCK_RIGHT
         return self
 
-    
+
     def Top(self):
         """ Top() sets the pane dock position to the top of the frame. """
 
         self.dock_direction = AUI_DOCK_TOP
         return self
 
-    
+
     def Bottom(self):
         """ Bottom() sets the pane dock position to the bottom of the frame. 
"""
 
         self.dock_direction = AUI_DOCK_BOTTOM
         return self
 
-    
+
     def Center(self):
         """ Center() sets the pane to the center position of the frame. """
-        
+
         self.dock_direction = AUI_DOCK_CENTER
         return self
 
-        
+
     def Centre(self):
         """ Centre() sets the pane to the center position of the frame. """
-        
+
         self.dock_direction = AUI_DOCK_CENTRE
         return self
 
-    
+
     def Direction(self, direction):
         """ Direction() determines the direction of the docked pane. """
-        
+
         self.dock_direction = direction
         return self
 
-    
+
     def Layer(self, layer):
         """ Layer() determines the layer of the docked pane. """
-        
+
         self.dock_layer = layer
         return self
 
-    
+
     def Row(self, row):
         """ Row() determines the row of the docked pane. """
-        
+
         self.dock_row = row
         return self
 
-    
+
     def Position(self, pos):
         """ Position() determines the position of the docked pane. """
 
@@ -1126,7 +1126,7 @@
 
     def MinSize(self, arg1=None, arg2=None):
         """ MinSize() sets the minimum size of the pane. """
-        
+
         if isinstance(arg1, wx.Size):
             ret = self.MinSize1(arg1)
         else:
@@ -1134,7 +1134,7 @@
 
         return ret
 
-    
+
     def MinSize1(self, size):
 
         self.min_size = size
@@ -1149,15 +1149,15 @@
 
     def MaxSize(self, arg1=None, arg2=None):
         """ MaxSize() sets the maximum size of the pane. """
-        
+
         if isinstance(arg1, wx.Size):
             ret = self.MaxSize1(arg1)
         else:
             ret = self.MaxSize2(arg1, arg2)
 
         return ret
-    
-    
+
+
     def MaxSize1(self, size):
 
         self.max_size = size
@@ -1179,233 +1179,233 @@
             ret = self.BestSize2(arg1, arg2)
 
         return ret
-    
-            
+
+
     def BestSize1(self, size):
 
         self.best_size = size
         return self
 
-    
+
     def BestSize2(self, x, y):
 
         self.best_size.Set(x,y)
         return self
-    
-    
+
+
     def FloatingPosition(self, pos):
         """ FloatingPosition() sets the position of the floating pane. """
-        
+
         self.floating_pos = pos
         return self
 
-    
+
     def FloatingSize(self, size):
         """ FloatingSize() sets the size of the floating pane. """
-        
+
         self.floating_size = size
         return self
 
-    
+
     def Fixed(self):
         """ Fixed() forces a pane to be fixed size so that it cannot be 
resized. """
-        
+
         return self.SetFlag(self.optionResizable, False)
 
-    
+
     def Resizable(self, resizable=True):
         """
         Resizable() allows a pane to be resizable if resizable is True, and 
forces
         it to be a fixed size if resizeable is False.
         """
-        
+
         return self.SetFlag(self.optionResizable, resizable)
 
-    
+
     def Dock(self):
         """ Dock() indicates that a pane should be docked. """
-        
+
         return self.SetFlag(self.optionFloating, False)
 
-    
+
     def Float(self):
         """ Float() indicates that a pane should be floated. """
-        
+
         return self.SetFlag(self.optionFloating, True)
 
-    
+
     def Hide(self):
         """ Hide() indicates that a pane should be hidden. """
-        
+
         return self.SetFlag(self.optionHidden, True)
 
-    
+
     def Show(self, show=True):
         """ Show() indicates that a pane should be shown. """
-        
+
         return self.SetFlag(self.optionHidden, not show)
-    
-    
+
+
     def CaptionVisible(self, visible=True):
         """ CaptionVisible() indicates that a pane caption should be visible. 
"""
-        
+
         return self.SetFlag(self.optionCaption, visible)
 
-    
+
     def PaneBorder(self, visible=True):
         """ PaneBorder() indicates that a border should be drawn for the pane. 
"""
-        
+
         return self.SetFlag(self.optionPaneBorder, visible)
 
-    
+
     def Gripper(self, visible=True):
         """ Gripper() indicates that a gripper should be drawn for the pane. 
"""
-        
+
         return self.SetFlag(self.optionGripper, visible)
 
 
     def GripperTop(self, attop=True):
         """ GripperTop() indicates that a gripper should be drawn for the 
pane. """
-        
+
         return self.SetFlag(self.optionGripperTop, attop)
 
-    
+
     def CloseButton(self, visible=True):
         """ CloseButton() indicates that a close button should be drawn for 
the pane. """
-        
+
         return self.SetFlag(self.buttonClose, visible)
 
-    
+
     def MaximizeButton(self, visible=True):
         """ MaximizeButton() indicates that a maximize button should be drawn 
for the pane. """
-        
+
         return self.SetFlag(self.buttonMaximize, visible)
 
-    
+
     def MinimizeButton(self, visible=True):
         """ MinimizeButton() indicates that a minimize button should be drawn 
for the pane. """
-        
+
         return self.SetFlag(self.buttonMinimize, visible)
 
-    
+
     def PinButton(self, visible=True):
         """ PinButton() indicates that a pin button should be drawn for the 
pane. """
-        
+
         return self.SetFlag(self.buttonPin, visible)
 
-    
+
     def DestroyOnClose(self, b=True):
         """ DestroyOnClose() indicates whether a pane should be destroyed when 
it is closed. """
-        
+
         return self.SetFlag(self.optionDestroyOnClose, b)
 
-    
+
     def TopDockable(self, b=True):
         """ TopDockable() indicates whether a pane can be docked at the top of 
the frame. """
-        
+
         return self.SetFlag(self.optionTopDockable, b)
 
-    
+
     def BottomDockable(self, b=True):
         """ BottomDockable() indicates whether a pane can be docked at the 
bottom of the frame. """
-        
+
         return self.SetFlag(self.optionBottomDockable, b)
 
-    
+
     def LeftDockable(self, b=True):
         """ LeftDockable() indicates whether a pane can be docked on the left 
of the frame. """
 
         return self.SetFlag(self.optionLeftDockable, b)
 
-    
+
     def RightDockable(self, b=True):
         """ RightDockable() indicates whether a pane can be docked on the 
right of the frame. """
-        
+
         return self.SetFlag(self.optionRightDockable, b)
 
-    
+
     def Floatable(self, b=True):
         """ Floatable() indicates whether a frame can be floated. """
-        
+
         return self.SetFlag(self.optionFloatable, b)
 
-    
+
     def Movable(self, b=True):
         """ Movable() indicates whether a frame can be moved. """
-        
+
         return self.SetFlag(self.optionMovable, b)
 
-    
+
     def Dockable(self, b=True):
-    
+
         return 
self.TopDockable(b).BottomDockable(b).LeftDockable(b).RightDockable(b)
-    
 
+
     def DefaultPane(self):
         """ DefaultPane() specifies that the pane should adopt the default 
pane settings. """
-        
-        state = self.state    
+
+        state = self.state
         state |= self.optionTopDockable | self.optionBottomDockable | \
                  self.optionLeftDockable | self.optionRightDockable | \
                  self.optionFloatable | self.optionMovable | 
self.optionResizable | \
                  self.optionCaption | self.optionPaneBorder | self.buttonClose
 
         self.state = state
-        
+
         return self
-    
-    
+
+
     def CentrePane(self):
         """ CentrePane() specifies that the pane should adopt the default 
center pane settings. """
-        
+
         return self.CenterPane()
 
-    
+
     def CenterPane(self):
         """ CenterPane() specifies that the pane should adopt the default 
center pane settings. """
-        
+
         self.state = 0
         return self.Center().PaneBorder().Resizable()
-    
-     
+
+
     def ToolbarPane(self):
         """ ToolbarPane() specifies that the pane should adopt the default 
toolbar pane settings. """
-        
+
         self.DefaultPane()
         state = self.state
-        
+
         state |= (self.optionToolbar | self.optionGripper)
         state &= ~(self.optionResizable | self.optionCaption)
-        
+
         if self.dock_layer == 0:
             self.dock_layer = 10
 
         self.state = state
-        
+
         return self
-    
 
+
     def SetFlag(self, flag, option_state):
         """ SetFlag() turns the property given by flag on or off with the 
option_state parameter. """
-        
+
         state = self.state
-        
+
         if option_state:
             state |= flag
         else:
             state &= ~flag
 
         self.state = state
-        
+
         return self
-    
-    
+
+
     def HasFlag(self, flag):
         """ HasFlag() returns True if the the property specified by flag is 
active for the pane. """
-        
+
         return (self.state & flag and [True] or [False])[0]
-    
 
+
 NonePaneInfo = PaneInfo()
 
 # -- FloatingPane class implementation --
@@ -1417,7 +1417,7 @@
 # For now, with wx.MSW, the wx.MiniFrame window is used, but on wx.GTK, 
wx.Frame
 
 if wx.Platform == "__WXGTK__":
-    
+
     class FloatingPaneBaseClass(wx.Frame):
         def __init__(self, parent, id=wx.ID_ANY, title="", 
pos=wx.DefaultPosition,
                      size=wx.DefaultSize, style=0):
@@ -1431,8 +1431,8 @@
             wx.MiniFrame.__init__(self, parent, id, title, pos, size, style)
             if wx.Platform == "__WXMAC__":
                 self.MacSetMetalAppearance(True)
-            
 
+
 class FloatingPane(FloatingPaneBaseClass):
 
     def __init__(self, parent, owner_mgr, id=wx.ID_ANY, title="", 
pos=wx.DefaultPosition,
@@ -1443,7 +1443,7 @@
 
         if not resizeborder:
             style = style & ~wx.RESIZE_BORDER
-            
+
         FloatingPaneBaseClass.__init__(self, parent, id, title, pos, size, 
style)
         self._owner_mgr = owner_mgr
         self._moving = False
@@ -1458,8 +1458,8 @@
         self.Bind(wx.EVT_MOVING, self.OnMoveEvent)
         self.Bind(wx.EVT_IDLE, self.OnIdle)
         self.Bind(wx.EVT_ACTIVATE, self.OnActivate)
-        
 
+
     def CopyAttributes(self, pane, contained_pane):
 
         contained_pane.name = pane.name
@@ -1481,17 +1481,17 @@
         contained_pane.rect = pane.rect
 
         return contained_pane
-    
 
+
     def SetPaneWindow(self, pane):
 
         self._pane_window = pane.window
         self._pane_window.Reparent(self)
-        
+
         contained_pane = PaneInfo()
 
-        contained_pane = self.CopyAttributes(pane, contained_pane)        
-        
+        contained_pane = self.CopyAttributes(pane, contained_pane)
+
         contained_pane.Dock().Center().Show(). \
                        CaptionVisible(False). \
                        PaneBorder(False). \
@@ -1499,15 +1499,15 @@
 
         indx = self._owner_mgr._panes.index(pane)
         self._owner_mgr._panes[indx] = pane
-                                              
+
         self._mgr.AddPane(self._pane_window, contained_pane)
-        self._mgr.Update()           
+        self._mgr.Update()
 
         if pane.min_size.IsFullySpecified():
             tmp = self.GetSize()
             self.GetSizer().SetSizeHints(self)
             self.SetSize(tmp)
-        
+
         self.SetTitle(pane.caption)
 
         if pane.floating_size != wx.DefaultSize:
@@ -1529,20 +1529,20 @@
             self._owner_mgr._panes[indx] = pane
             self.SetClientSize(size)
 
-    
+
     def OnSize(self, event):
 
         self._owner_mgr.OnFloatingPaneResized(self._pane_window, 
event.GetSize())
-        
-    
+
+
     def OnClose(self, event):
-    
+
         self._owner_mgr.OnFloatingPaneClosed(self._pane_window)
         self.Destroy()
-        
+
         self._mgr.UnInit()
-    
 
+
     def OnMoveEvent(self, event):
 
         win_rect = self.GetRect()
@@ -1556,7 +1556,7 @@
         if self._last_rect.GetSize() != win_rect.GetSize():
             self._last_rect = win_rect
             return
-        
+
         self._last_rect = win_rect
 
         if not self.IsMouseDown():
@@ -1565,7 +1565,7 @@
         if not self._moving:
             self.OnMoveStart()
             self._moving = True
-        
+
         self.OnMoving(event.GetRect())
 
 
@@ -1582,10 +1582,10 @@
                 elif _libimported == "ctypes":
                     return ((ctypes.windll.user32.GetKeyState(1) & (1<<15)) 
and \
                             [True] or [False])[0]
-            
-    
+
+
     def OnIdle(self, event):
-    
+
         if self._moving:
             if not self.IsMouseDown():
                 self._moving = False
@@ -1595,31 +1595,31 @@
 
         event.Skip()
 
-        
+
     def OnMoveStart(self):
-    
+
         # notify the owner manager that the pane has started to move
         self._owner_mgr.OnFloatingPaneMoveStart(self._pane_window)
-    
 
+
     def OnMoving(self, window_rect):
-    
+
         # notify the owner manager that the pane is moving
         self._owner_mgr.OnFloatingPaneMoving(self._pane_window)
 
-    
+
     def OnMoveFinished(self):
-    
+
         # notify the owner manager that the pane has finished moving
         self._owner_mgr.OnFloatingPaneMoved(self._pane_window)
-    
 
+
     def OnActivate(self, event):
 
         if event.GetActive():
             self._owner_mgr.OnFloatingPaneActivated(self._pane_window)
 
-    
+
 # -- static utility functions --
 
 def PaneCreateStippleBitmap():
@@ -1627,12 +1627,12 @@
     data = [0, 0, 0, 192, 192, 192, 192, 192, 192, 0, 0, 0]
     img = wx.EmptyImage(2, 2)
     counter = 0
-    
+
     for ii in xrange(2):
         for jj in xrange(2):
             img.SetRGB(ii, jj, data[counter], data[counter+1], data[counter+2])
             counter = counter + 3
-    
+
     return img.ConvertToBitmap()
 
 
@@ -1645,7 +1645,7 @@
     dc.SetPen(wx.TRANSPARENT_PEN)
 
     dc.SetLogicalFunction(wx.XOR)
-    dc.DrawRectangleRect(rect)    
+    dc.DrawRectangleRect(rect)
 
 
 def CopyDocksAndPanes(src_docks, src_panes):
@@ -1655,7 +1655,7 @@
     to PaneInfo classes, thus this function is necessary to reliably
     reconstruct that relationship in the new dock info and pane info arrays.
     """
-    
+
     dest_docks = src_docks
     dest_panes = src_panes
 
@@ -1676,7 +1676,7 @@
     to PaneInfo classes, thus this function is necessary to reliably
     reconstruct that relationship in the new dock info and pane info arrays.
     """
-    
+
     dest_docks = []
 
     for ii in xrange(len(src_docks)):
@@ -1722,7 +1722,7 @@
                     dock.panes[jj] = dest_panes[kk]
 
         dest_docks[ii] = dock
-        
+
     return dest_docks, dest_panes
 
 
@@ -1731,14 +1731,14 @@
     GetMaxLayer() is an internal function which returns
     the highest layer inside the specified dock.
     """
-    
+
     max_layer = 0
-    
+
     for ii in xrange(len(docks)):
         dock = docks[ii]
         if dock.dock_direction == dock_direction and dock.dock_layer > 
max_layer and not dock.fixed:
             max_layer = dock.dock_layer
-    
+
     return max_layer
 
 
@@ -1747,7 +1747,7 @@
     GetMaxRow() is an internal function which returns
     the highest layer inside the specified dock.
     """
-    
+
     max_row = 0
 
     for ii in xrange(len(panes)):
@@ -1755,7 +1755,7 @@
         if pane.dock_direction == direction and pane.dock_layer == layer and \
            pane.dock_row > max_row:
             max_row = pane.dock_row
-    
+
     return max_row
 
 
@@ -1764,7 +1764,7 @@
     DoInsertDockLayer() is an internal function that inserts a new dock
     layer by incrementing all existing dock layer values by one.
     """
-    
+
     for ii in xrange(len(panes)):
         pane = panes[ii]
         if not pane.IsFloating() and pane.dock_direction == dock_direction and 
pane.dock_layer >= dock_layer:
@@ -1780,7 +1780,7 @@
     DoInsertDockRow() is an internal function that inserts a new dock
     row by incrementing all existing dock row values by one.
     """
-    
+
     for ii in xrange(len(panes)):
         pane = panes[ii]
         if not pane.IsFloating() and pane.dock_direction == dock_direction and 
\
@@ -1791,7 +1791,7 @@
 
     return panes
 
-    
+
 def DoInsertPane(panes, dock_direction, dock_layer, dock_row, dock_pos):
 
     for ii in xrange(len(panes)):
@@ -1812,7 +1812,7 @@
     the specified conditions in the parameters and returns a sorted array
     (sorted by layer and then row).
     """
-    
+
     begin_layer = dock_layer
     end_layer = dock_layer
     begin_row = dock_row
@@ -1820,17 +1820,17 @@
     dock_count = len(docks)
     max_row = 0
     max_layer = 0
-    
+
     # discover the maximum dock layer and the max row
     for ii in xrange(dock_count):
         max_row = max(max_row, docks[ii].dock_row)
         max_layer = max(max_layer, docks[ii].dock_layer)
-    
+
     # if no dock layer was specified, search all dock layers
     if dock_layer == -1:
         begin_layer = 0
         end_layer = max_layer
-    
+
     # if no dock row was specified, search all dock row
     if dock_row == -1:
         begin_row = 0
@@ -1854,13 +1854,13 @@
     FindPaneInDock() looks up a specified window pointer inside a dock.
     If found, the corresponding PaneInfo pointer is returned, otherwise None.
     """
-    
+
     count = len(dock.panes)
     for ii in xrange(count):
         p = dock.panes[ii]
         if p.window == window:
             return p
-    
+
     return None
 
 
@@ -1869,7 +1869,7 @@
     RemovePaneFromDocks() removes a pane window from all docks
     with a possible exception specified by parameter "except".
     """
-    
+
     for ii in xrange(len(docks)):
         d = docks[ii]
         if d == exc:
@@ -1878,7 +1878,7 @@
         if pi:
             d.panes.remove(pi)
 
-        docks[ii] = d            
+        docks[ii] = d
 
     return docks
 
@@ -1889,7 +1889,7 @@
     to existing rows.  Basically it takes out the gaps so if a
     dock has rows with numbers 0, 2, 5, they will become 0, 1, 2.
     """
-    
+
     for ii in xrange(len(docks)):
         dock = docks[ii]
         dock.dock_row = ii
@@ -1897,12 +1897,12 @@
             dock.panes[jj].dock_row = ii
 
         docks[ii] = dock
-        
+
     return docks
 
 
 def SetActivePane(panes, active_pane):
-    
+
     for ii in xrange(len(panes)):
         pane = panes[ii]
         pane.state &= ~PaneInfo.optionActive
@@ -1911,13 +1911,13 @@
             pane.state |= PaneInfo.optionActive
 
         panes[ii]= pane
-        
+
     return panes
 
 
 def PaneSortFunc(p1, p2):
     """ This function is used to sort panes by dock position. """
-    
+
     return (p1.dock_pos < p2.dock_pos and [-1] or [1])[0]
 
 
@@ -1927,10 +1927,10 @@
     in the input string.  This is an internal functions which is
     used for saving perspectives.
     """
-    
+
     result = s.replace(";", "\\")
     result = result.replace("|", "|\\")
-    
+
     return result
 
 
@@ -1939,7 +1939,7 @@
 actionClickButton = 2
 actionClickCaption = 3
 actionDragToolbarPane = 4
-actionDragFloatingPane = 5    
+actionDragFloatingPane = 5
 
 auiInsertRowPixels = 10
 auiNewRowPixels = 40
@@ -1986,12 +1986,12 @@
 # being docked on the left side of a window. One pane can be placed over 
another.
 # In proportionally managed docks, the pane position indicates it's sequential 
position,
 # starting with zero. So, in our scenario with two panes docked on the left 
side, the
-# top pane in the dock would have position 0, and the second one would occupy 
position 1. 
+# top pane in the dock would have position 0, and the second one would occupy 
position 1.
 #
 # Row - A row can allow for two docks to be placed next to each other. One of 
the most
 # common places for this to happen is in the toolbar. Multiple toolbar rows 
are allowed,
 # the first row being in row 0, and the second in row 1. Rows can also be used 
on
-# vertically docked panes. 
+# vertically docked panes.
 #
 # Layer - A layer is akin to an onion. Layer 0 is the very center of the 
managed pane.
 # Thus, if a pane is in layer 0, it will be closest to the center window (also 
sometimes
@@ -2019,10 +2019,10 @@
         self._last_hint = wx.Rect()
         self._hint_fadetimer = wx.Timer()
         self._hintshown = False
-        
+
         if flags is None:
             flags = AUI_MGR_DEFAULT
-            
+
         self._flags = flags
         self._active_pane = None
 
@@ -2048,7 +2048,7 @@
         This version of GetPane() looks up a pane based on a
         'pane window', see below comment for more info.
         """
-        
+
         for ii in xrange(len(self._panes)):
             p = self._panes[ii]
             if p.window == window:
@@ -2062,12 +2062,12 @@
         This version of GetPane() looks up a pane based on a
         'pane name', see below comment for more info.
         """
-        
+
         for ii in xrange(len(self._panes)):
             p = self._panes[ii]
             if p.name == name:
                 return p
-        
+
         return NonePaneInfo
 
 
@@ -2083,7 +2083,7 @@
         realize the changes in the UI.
 
         AG: Added To Handle 2 Different Versions Of GetPane() For
-        wxPython/Python.         
+        wxPython/Python.
         """
 
         if isinstance(item, type("")):
@@ -2094,7 +2094,7 @@
 
     def GetAllPanes(self):
         """ GetAllPanes() returns a reference to all the pane info structures. 
"""
-        
+
         return self._panes
 
 
@@ -2106,12 +2106,12 @@
         """
 
         result = None
-        
+
         for ii in xrange(len(self._uiparts)):
-        
+
             item = self._uiparts[ii]
-            
-            # we are not interested in typeDock, because this space 
+
+            # we are not interested in typeDock, because this space
             # isn't used to draw anything, just for measurements
             # besides, the entire dock area is covered with other
             # rectangles, which we are interested in.
@@ -2124,11 +2124,11 @@
             if (item.type == DockUIPart.typePane or \
                 item.type == DockUIPart.typePaneBorder) and result:
                 continue
-        
+
             # if the point is inside the rectangle, we have a hit
             if item.rect.Inside((x, y)):
                 result = item
-        
+
         return result
 
 
@@ -2140,13 +2140,13 @@
         SetFlags() is used to specify FrameManager's settings flags. flags 
specifies
         options which allow the frame management behavior to be modified.
         """
-        
+
         self._flags = flags
 
 
     def GetFlags(self):
         """ GetFlags() returns the current manager's flags. """
-        
+
         return self._flags
 
 
@@ -2159,7 +2159,7 @@
 
         if not frame:
             raise "\nERROR: Specified Frame Must Be Non-Null. "
-        
+
         self._frame = frame
         self._frame.PushEventHandler(self)
 
@@ -2169,17 +2169,17 @@
         if isinstance(frame, wx.MDIParentFrame):
             mdi_frame = frame
             client_window = mdi_frame.GetClientWindow()
-            
+
             if not client_window:
                 raise "\nERROR: MDI Client Window Is Null. "
 
             self.AddPane(client_window, PaneInfo().Name("mdiclient").
                          CenterPane().PaneBorder(False))
-        
 
+
     def GetFrame(self):
         """ GetFrame() returns the frame pointer being managed by 
FrameManager. """
-        
+
         return self._frame
 
 
@@ -2189,14 +2189,14 @@
         of the frame class.   If it is not called, usually this
         will result in a crash upon program exit.
         """
-        
+
         if self._frame.GetEventHandler() == self:
             self._frame.PopEventHandler()
 
 
     def GetArtProvider(self):
         """ GetArtProvider() returns the current art provider being used. """
-        
+
         return self._art
 
 
@@ -2206,10 +2206,10 @@
         if self._frame:
             if self._frame.ProcessEvent(event):
                 return
-        
+
         self.ProcessEvent(event)
 
-    
+
     def CanMakeWindowsTransparent(self):
         if wx.Platform == "__WXMSW__":
             version = wx.GetOsDescription()
@@ -2231,26 +2231,26 @@
         # we will runtime bind this
         if wx.Platform == "__WXMSW__":
             hwnd = wnd.GetHandle()
-    
+
             if not hasattr(self, "_winlib"):
                 if _libimported == "MH":
                     self._winlib = win32api.LoadLibrary("user32")
                 elif _libimported == "ctypes":
                     self._winlib = ctypes.windll.user32
-                    
+
             if _libimported == "MH":
                 pSetLayeredWindowAttributes = 
win32api.GetProcAddress(self._winlib,
                                                                       
"SetLayeredWindowAttributes")
-                
+
                 if pSetLayeredWindowAttributes == None:
                     return
-                    
+
                 exstyle = win32api.GetWindowLong(hwnd, win32con.GWL_EXSTYLE)
                 if 0 == (exstyle & 0x80000):
-                    win32api.SetWindowLong(hwnd, win32con.GWL_EXSTYLE, exstyle 
| 0x80000)  
-                         
+                    win32api.SetWindowLong(hwnd, win32con.GWL_EXSTYLE, exstyle 
| 0x80000)
+
                 winxpgui.SetLayeredWindowAttributes(hwnd, 0, amount, 2)
-    
+
             elif _libimported == "ctypes":
                 style = self._winlib.GetWindowLongA(hwnd, 0xffffffecL)
                 style |= 0x00080000
@@ -2266,8 +2266,8 @@
         else:
             #shouldn't be called, but just in case...
             return
-    
-    
+
+
     def SetArtProvider(self, art_provider):
         """
         SetArtProvider() instructs FrameManager to use the
@@ -2277,7 +2277,7 @@
 
         # delete the last art provider, if any
         del self._art
-        
+
         # assign the new art provider
         self._art = art_provider
 
@@ -2300,8 +2300,8 @@
             return self.AddPane2(window, arg1, arg2)
         else:
             return self.AddPane1(window, arg1)
-        
 
+
     def AddPane1(self, window, pane_info):
 
         # check if the pane has a valid window
@@ -2314,19 +2314,19 @@
 
         if isinstance(window, wx.ToolBar):
             window.SetBestFittingSize()
-            
+
         self._panes.append(pane_info)
 
         pinfo = self._panes[-1]
 
         # set the pane window
         pinfo.window = window
-        
+
         # if the pane's name identifier is blank, create a random string
         if len(pinfo.name) == 0 or pinfo.name == "":
             pinfo.name = ("%s%08x%08x%08x")%(pinfo.window.GetName(), 
time.time(),
                                              time.clock(), len(self._panes))
-        
+
         # set initial proportion (if not already set)
         if pinfo.dock_proportion == 0:
             pinfo.dock_proportion = 100000
@@ -2335,7 +2335,7 @@
             button = PaneButton(None)
             button.button_id = PaneInfo.buttonClose
             pinfo.buttons.append(button)
-        
+
         if pinfo.best_size == wx.DefaultSize and pinfo.window:
             pinfo.best_size = pinfo.window.GetClientSize()
             if pinfo.min_size != wx.DefaultSize:
@@ -2345,7 +2345,7 @@
                     pinfo.best_size.y = pinfo.min_size.y
 
         self._panes[-1] = pinfo
-        
+
         return True
 
 
@@ -2353,7 +2353,7 @@
 
         pinfo = PaneInfo()
         pinfo.Caption(caption)
-        
+
         if direction == wx.TOP:
             pinfo.Top()
         elif direction == wx.BOTTOM:
@@ -2364,7 +2364,7 @@
             pinfo.Right()
         elif direction == wx.CENTER:
             pinfo.CenterPane()
-        
+
         return self.AddPane(window, pinfo)
 
 
@@ -2392,18 +2392,18 @@
         elif insert_level == AUI_INSERT_DOCK:
             self._panes = DoInsertDockLayer(self._panes, 
pane_info.dock_direction,
                                             pane_info.dock_layer)
-        
+
         # if the window already exists, we are basically just moving/inserting 
the
         # existing window.  If it doesn't exist, we need to add it and insert 
it
         existing_pane = self.GetPane(window)
         indx = self._panes.index(existing_pane)
-        
+
         if not existing_pane.IsOk():
-        
+
             return self.AddPane(window, pane_info)
-        
+
         else:
-        
+
             if pane_info.IsFloating():
                 existing_pane.Float()
                 if pane_info.floating_pos != wx.DefaultPosition:
@@ -2416,23 +2416,23 @@
                 existing_pane.Row(pane_info.dock_row)
                 existing_pane.Position(pane_info.dock_pos)
 
-            self._panes[indx] = existing_pane                
-            
+            self._panes[indx] = existing_pane
+
         return True
 
-    
+
     def DetachPane(self, window):
         """
         DetachPane() tells the FrameManager to stop managing the pane specified
         by window. The window, if in a floated frame, is reparented to the 
frame
         managed by FrameManager.
         """
-        
+
         for ii in xrange(len(self._panes)):
             if self._panes[ii].window == window:
                 self._panes.pop(ii)
                 return True
-        
+
         return False
 
 
@@ -2468,7 +2468,7 @@
             result = result + "floatw=%d;"%pane.floating_size.x
             result = result + "floath=%d"%pane.floating_size.y
             result = result + "|"
-        
+
         dock_count = len(self._docks)
 
         for dock_i in xrange(dock_count):
@@ -2477,7 +2477,7 @@
                                                            dock.dock_layer,
                                                            dock.dock_row,
                                                            dock.size)
-            
+
         return result
 
 
@@ -2499,7 +2499,7 @@
 
         olddocks = self._docks[:]
         oldpanes = self._panes[:]
-        
+
         # mark all panes currently managed as docked and hidden
         pane_count = len(self._panes)
         for pane_i in xrange(pane_count):
@@ -2509,18 +2509,18 @@
 
         # clear out the dock array this will be reconstructed
         self._docks = []
-        
+
         # replace escaped characters so we can
         # split up the string easily
         input = input.replace("\\|", "\a")
         input = input.replace("\\", "\b")
 
-        input = input.split("|")    
+        input = input.split("|")
 
         for line in input:
-            
+
             if line.startswith("dock_size"):
-                
+
                 indx = line.index("=")
                 size = int(line[indx+1:])
                 indx1 = line.index("(")
@@ -2535,14 +2535,14 @@
                 dock.dock_layer = layer
                 dock.dock_row = row
                 dock.size = size
-                
+
                 self._docks.append(dock)
-                
+
             elif line.startswith("name"):
 
                 newline = line.split(";")
                 pane = PaneInfo()
-                
+
                 for newl in newline:
                     myline = newl.strip()
                     vals = myline.split("=")
@@ -2589,7 +2589,7 @@
                     elif val_name == "floath":
                         pane.floating_size.y = int(value)
                         pane.floating_size = wx.Size(pane.floating_size.x, 
pane.floating_size.y)
-                    else: 
+                    else:
                         raise "\nERROR: Bad Perspective String."
 
                 # replace escaped characters so we can
@@ -2598,14 +2598,14 @@
                 pane.name = pane.name.replace("\b", ";")
                 pane.caption = pane.caption.replace("\a", "|")
                 pane.caption = pane.caption.replace("\b", ";")
-                
+
                 p = self.GetPane(pane.name)
                 if not p.IsOk():
                     # the pane window couldn't be found
                     # in the existing layout
                     return False
 
-                indx = self._panes.index(p)            
+                indx = self._panes.index(p)
                 pane.window = p.window
                 pane.frame = p.frame
                 pane.buttons = p.buttons
@@ -2619,7 +2619,7 @@
 
     def GetPanePositionsAndSizes(self, dock):
         """ Returns all the panes positions and sizes. """
-        
+
         caption_size = self._art.GetMetric(AUI_ART_CAPTION_SIZE)
         pane_border_size = self._art.GetMetric(AUI_ART_PANE_BORDER_SIZE)
         gripper_size = self._art.GetMetric(AUI_ART_GRIPPER_SIZE)
@@ -2635,7 +2635,7 @@
             pane = dock.panes[pane_i]
             if pane.state & PaneInfo.actionPane:
                 action_pane = pane_i
-            
+
         # set up each panes default position, and
         # determine the size (width or height, depending
         # on the dock's orientation) of each pane
@@ -2643,25 +2643,25 @@
             pane = dock.panes[pane_i]
             positions.append(pane.dock_pos)
             size = 0
-            
+
             if pane.HasBorder():
                 size  = size + pane_border_size*2
-                    
+
             if dock.IsHorizontal():
                 if pane.HasGripper() and not pane.HasGripperTop():
                     size = size + gripper_size
-                    
+
                 size = size + pane.best_size.x
-                 
+
             else:
                 if pane.HasGripper() and pane.HasGripperTop():
                     size = size + gripper_size
 
                 if pane.HasCaption():
                     size = size + caption_size
-                    
+
                 size = size + pane.best_size.y
-       
+
             sizes.append(size)
 
         # if there is no action pane, just return the default
@@ -2670,7 +2670,7 @@
             return positions, sizes
 
         offset = 0
-        for pane_i in xrange(action_pane-1, -1, -1):        
+        for pane_i in xrange(action_pane-1, -1, -1):
             amount = positions[pane_i+1] - (positions[pane_i] + sizes[pane_i])
             if amount >= 0:
                 offset = offset + amount
@@ -2678,7 +2678,7 @@
                 positions[pane_i] -= -amount
 
             offset = offset + sizes[pane_i]
-        
+
         # if the dock mode is fixed, make sure none of the panes
         # overlap we will bump panes that overlap
         offset = 0
@@ -2692,10 +2692,10 @@
             offset = offset + sizes[pane_i]
 
         return positions, sizes
-    
 
+
     def LayoutAddPane(self, cont, dock, pane, uiparts, spacer_only):
-        
+
         sizer_item = wx.SizerItem()
         caption_size = self._art.GetMetric(AUI_ART_CAPTION_SIZE)
         gripper_size = self._art.GetMetric(AUI_ART_GRIPPER_SIZE)
@@ -2718,7 +2718,7 @@
         vert_pane_sizer = wx.BoxSizer(wx.VERTICAL)
 
         if pane.HasGripper():
-            
+
             part = DockUIPart()
             if pane.HasGripperTop():
                 sizer_item = vert_pane_sizer.Add((1, gripper_size), 0, 
wx.EXPAND)
@@ -2733,9 +2733,9 @@
             part.cont_sizer = horz_pane_sizer
             part.sizer_item = sizer_item
             uiparts.append(part)
-        
+
         if pane.HasCaption():
-        
+
             # create the caption sizer
             part = DockUIPart()
             caption_sizer = wx.BoxSizer(wx.HORIZONTAL)
@@ -2765,11 +2765,11 @@
                 part.cont_sizer = caption_sizer
                 part.sizer_item = sizer_item
                 uiparts.append(part)
-            
+
             # add the caption sizer
             sizer_item = vert_pane_sizer.Add(caption_sizer, 0, wx.EXPAND)
             uiparts[caption_part_idx].sizer_item = sizer_item
-                
+
         # add the pane window itself
         if spacer_only:
             sizer_item = vert_pane_sizer.Add((1, 1), 1, wx.EXPAND)
@@ -2777,7 +2777,7 @@
             sizer_item = vert_pane_sizer.Add(pane.window, 1, wx.EXPAND)
             vert_pane_sizer.SetItemMinSize(pane.window, (1, 1))
 
-        part = DockUIPart()        
+        part = DockUIPart()
         part.type = DockUIPart.typePane
         part.dock = dock
         part.pane = pane
@@ -2790,17 +2790,17 @@
         # determine if the pane should have a minimum size if the pane is
         # non-resizable (fixed) then we must set a minimum size. Alternitavely,
         # if the pane.min_size is set, we must use that value as well
-        
+
         min_size = pane.min_size
         if pane.IsFixed():
             if min_size == wx.DefaultSize:
                 min_size = pane.best_size
                 pane_proportion = 0
-            
+
         if min_size != wx.DefaultSize:
             vert_pane_sizer.SetItemMinSize(
                 len(vert_pane_sizer.GetChildren())-1, (min_size.x, min_size.y))
-        
+
         # add the verticle sizer (caption, pane window) to the
         # horizontal sizer (gripper, verticle sizer)
         horz_pane_sizer.Add(vert_pane_sizer, 1, wx.EXPAND)
@@ -2821,10 +2821,10 @@
             uiparts.append(part)
         else:
             sizer_item = cont.Add(horz_pane_sizer, pane_proportion, wx.EXPAND)
-        
+
         return uiparts
-        
-        
+
+
     def LayoutAddDock(self, cont, dock, uiparts, spacer_only):
 
         sizer_item = wx.SizerItem()
@@ -2836,7 +2836,7 @@
         # resizable bottom and right docks have a sash before them
         if not dock.fixed and (dock.dock_direction == AUI_DOCK_BOTTOM or \
                                dock.dock_direction == AUI_DOCK_RIGHT):
-        
+
             sizer_item = cont.Add((sash_size, sash_size), 0, wx.EXPAND)
 
             part.type = DockUIPart.typeDockSizer
@@ -2847,7 +2847,7 @@
             part.cont_sizer = cont
             part.sizer_item = sizer_item
             uiparts.append(part)
-        
+
         # create the sizer for the dock
         dock_sizer = wx.BoxSizer(orientation)
 
@@ -2855,20 +2855,20 @@
         pane_count = len(dock.panes)
 
         if dock.fixed:
-        
+
             # figure out the real pane positions we will
             # use, without modifying the each pane's pane_pos member
             pane_positions, pane_sizes = self.GetPanePositionsAndSizes(dock)
 
             offset = 0
             for pane_i in xrange(pane_count):
-            
+
                 pane = dock.panes[pane_i]
                 pane_pos = pane_positions[pane_i]
 
                 amount = pane_pos - offset
                 if amount > 0:
-                
+
                     if dock.IsVertical():
                         sizer_item = dock_sizer.Add((1, amount), 0, wx.EXPAND)
                     else:
@@ -2886,11 +2886,11 @@
                     uiparts.append(part)
 
                     offset = offset + amount
-                
+
                 uiparts = self.LayoutAddPane(dock_sizer, dock, pane, uiparts, 
spacer_only)
 
                 offset = offset + pane_sizes[pane_i]
-            
+
             # at the end add a very small stretchable background area
             sizer_item = dock_sizer.Add((1, 1), 1, wx.EXPAND)
             part = DockUIPart()
@@ -2902,11 +2902,11 @@
             part.cont_sizer = dock_sizer
             part.sizer_item = sizer_item
             uiparts.append(part)
-        
+
         else:
-        
+
             for pane_i in xrange(pane_count):
-            
+
                 pane = dock.panes[pane_i]
 
                 # if this is not the first pane being added,
@@ -2923,9 +2923,9 @@
                     part.cont_sizer = dock_sizer
                     part.sizer_item = sizer_item
                     uiparts.append(part)
-                
+
                 uiparts = self.LayoutAddPane(dock_sizer, dock, pane, uiparts, 
spacer_only)
-            
+
         if dock.dock_direction == AUI_DOCK_CENTER:
             sizer_item = cont.Add(dock_sizer, 1, wx.EXPAND)
         else:
@@ -2949,7 +2949,7 @@
         #  top and left docks have a sash after them
         if not dock.fixed and (dock.dock_direction == AUI_DOCK_TOP or \
                                dock.dock_direction == AUI_DOCK_LEFT):
-        
+
             sizer_item = cont.Add((sash_size, sash_size), 0, wx.EXPAND)
 
             part = DockUIPart()
@@ -2961,10 +2961,10 @@
             part.cont_sizer = cont
             part.sizer_item = sizer_item
             uiparts.append(part)
-        
+
         return uiparts
-    
 
+
     def LayoutAll(self, panes, docks, uiparts, spacer_only=False, 
oncheck=True):
 
         container = wx.BoxSizer(wx.VERTICAL)
@@ -2972,13 +2972,13 @@
         pane_border_size = self._art.GetMetric(AUI_ART_PANE_BORDER_SIZE)
         caption_size = self._art.GetMetric(AUI_ART_CAPTION_SIZE)
         cli_size = self._frame.GetClientSize()
-        
+
         # empty all docks out
         for ii in xrange(len(docks)):
             docks[ii].panes = []
 
         dock_count = len(docks)
-        
+
         # iterate through all known panes, filing each
         # of them into the appropriate dock. If the
         # pane does not exist in the dock, add it
@@ -3004,24 +3004,24 @@
                 docks = RemovePaneFromDocks(docks, p, dock)
 
                 # pane needs to be added to the dock,
-                # if it doesn't already exist 
+                # if it doesn't already exist
                 if not FindPaneInDock(dock, p.window):
                     dock.panes.append(p)
             else:
                 # remove the pane from any existing docks
                 docks = RemovePaneFromDocks(docks, p)
-            
+
         # remove any empty docks
         for ii in xrange(len(docks)-1, -1, -1):
             if len(docks[ii].panes) == 0:
                 docks.pop(ii)
 
-        dock_count = len(docks)        
+        dock_count = len(docks)
         # configure the docks further
         for ii in xrange(len(docks)):
             dock = docks[ii]
             dock_pane_count = len(dock.panes)
-            
+
             # sort the dock pane array by the pane's
             # dock position (dock_pos), in ascending order
             dock.panes.sort(PaneSortFunc)
@@ -3036,19 +3036,19 @@
                         pane_size = pane.min_size
                     if pane_size == wx.DefaultSize:
                         pane_size = pane.window.GetSize()
-                    
+
                     if dock.IsHorizontal():
                         size = max(pane_size.y, size)
                     else:
                         size = max(pane_size.x, size)
-                
+
                 # add space for the border (two times), but only
                 # if at least one pane inside the dock has a pane border
                 for jj in xrange(dock_pane_count):
                     if dock.panes[jj].HasBorder():
                         size = size + pane_border_size*2
                         break
-                    
+
                 # if pane is on the top or bottom, add the caption height,
                 # but only if at least one pane inside the dock has a caption
                 if dock.IsHorizontal():
@@ -3056,7 +3056,7 @@
                         if dock.panes[jj].HasCaption():
                             size = size + caption_size
                             break
-                    
+
                 # new dock's size may not be more than 1/3 of the frame size
                 if dock.IsHorizontal():
                     size = min(size, cli_size.y/3)
@@ -3065,7 +3065,7 @@
 
                 if size < 10:
                     size = 10
-                    
+
                 dock.size = size
 
             # determine the dock's minimum size
@@ -3085,14 +3085,14 @@
                     else:
                         if pane.min_size.x > dock_min_size:
                             dock_min_size = pane.min_size.x
-                    
+
             if plus_border:
                 dock_min_size = dock_min_size + pane_border_size*2
             if plus_caption and dock.IsHorizontal():
                 dock_min_size = dock_min_size + caption_size
-               
+
             dock.min_size = dock_min_size
-            
+
             # if the pane's current size is less than it's
             # minimum, increase the dock's size to it's minimum
             if dock.size < dock.min_size:
@@ -3120,7 +3120,7 @@
                     pane = dock.panes[jj]
                     pane.dock_pos = jj
                     dock.panes[jj] = pane
-                
+
             # if the dock mode is fixed, and none of the panes
             # are being moved right now, make sure the panes
             # do not overlap each other.  If they do, we will
@@ -3141,11 +3141,11 @@
                     dock.panes[jj] = pane
 
             if oncheck:
-                self._docks[ii] = dock                    
-        
+                self._docks[ii] = dock
+
         # discover the maximum dock layer
         max_layer = 0
-        
+
         for ii in xrange(dock_count):
             max_layer = max(max_layer, docks[ii].dock_layer)
 
@@ -3159,7 +3159,7 @@
 
         if oncheck:
             docks = self._docks
-        
+
         for layer in xrange(max_layer+1):
             # find any docks in this layer
             arr = FindDocks(docks, -1, layer, -1)
@@ -3179,10 +3179,10 @@
             if len(arr) > 0:
                 for row in xrange(len(arr)):
                     uiparts = self.LayoutAddDock(cont, arr[row], uiparts, 
spacer_only)
-            
+
             # fill out the middle layer (which consists
             # of left docks, content area and right docks)
-            
+
             middle = wx.BoxSizer(wx.HORIZONTAL)
 
             # find any left docks in this layer
@@ -3191,7 +3191,7 @@
             if len(arr) > 0:
                 for row in xrange(len(arr)):
                     uiparts = self.LayoutAddDock(middle, arr[row], uiparts, 
spacer_only)
-            
+
             # add content dock (or previous layer's sizer
             # to the middle
             if not old_cont:
@@ -3200,7 +3200,7 @@
                 if len(arr) > 0:
                     for row in xrange(len(arr)):
                        uiparts = self.LayoutAddDock(middle, arr[row], uiparts, 
spacer_only)
-                else:                
+                else:
                     # there are no center docks, add a background area
                     sizer_item = middle.Add((1, 1), 1, wx.EXPAND)
                     part = DockUIPart()
@@ -3213,14 +3213,14 @@
                     uiparts.append(part)
             else:
                 middle.Add(old_cont, 1, wx.EXPAND)
-            
+
             # find any right docks in this layer
             arr = FindDocks(docks, AUI_DOCK_RIGHT, layer, -1, arr)
             arr = RenumberDockRows(arr)
             if len(arr) > 0:
                 for row in xrange(len(arr)-1, -1, -1):
                     uiparts = self.LayoutAddDock(middle, arr[row], uiparts, 
spacer_only)
-            
+
             cont.Add(middle, 1, wx.EXPAND)
 
             # find any bottom docks in this layer
@@ -3262,7 +3262,7 @@
         one or more panes, this function should be called.  It is the
         external entry point for running the layout engine.
         """
-    
+
         pane_count = len(self._panes)
         # delete old sizer first
         self._frame.SetSizer(None)
@@ -3277,7 +3277,7 @@
                 # reduce flicker
                 p.window.SetSize((1, 1))
                 p.frame.Show(False)
-                           
+
                 # reparent to self._frame and destroy the pane
                 p.window.Reparent(self._frame)
                 p.frame.SetSizer(None)
@@ -3285,15 +3285,15 @@
                 p.frame = None
 
             self._panes[ii] = p
-            
+
         # create a layout for all of the panes
         sizer = self.LayoutAll(self._panes, self._docks, self._uiparts, False)
 
         # hide or show panes as necessary,
         # and float panes as necessary
-        
+
         pane_count = len(self._panes)
-        
+
         for ii in xrange(pane_count):
             p = self._panes[ii]
             if p.IsFloating():
@@ -3303,23 +3303,23 @@
                     resizeborder = 1
                     if p.IsFixed():
                         resizeborder = 0
-                        
+
                     frame = FloatingPane(self._frame, self, -1, "", 
p.floating_pos,
                                          p.floating_size, 
resizeborder=resizeborder)
-                                    
+
                     # on MSW, if the owner desires transparent dragging, and
                     # the dragging is happening right now, then the floating
-                    # window should have this style by default                 
 
-                    
+                    # window should have this style by default
+
                     if self.UseTransparentDrag():
                         self.MakeWindowTransparent(frame, 150)
-                    
+
                     frame.SetPaneWindow(p)
                     p.frame = frame
                     if p.IsShown():
                         frame.Show()
                 else:
-                
+
                     # frame already exists, make sure it's position
                     # and size reflect the information in PaneInfo
                     if p.frame.GetPosition() != p.floating_pos:
@@ -3327,7 +3327,7 @@
                                         -1, -1, wx.SIZE_USE_EXISTING)
                     p.frame.Show(p.IsShown())
             else:
-            
+
                 p.window.Show(p.IsShown())
 
             # if "active panes" are no longer allowed, clear
@@ -3339,7 +3339,7 @@
 
 
         old_pane_rects = []
-        
+
         for ii in xrange(pane_count):
             r = wx.Rect()
             p = self._panes[ii]
@@ -3347,13 +3347,13 @@
             if p.window and p.IsShown() and p.IsDocked():
                 r = p.rect
 
-            old_pane_rects.append(r)    
-            
+            old_pane_rects.append(r)
+
         # apply the new sizer
         self._frame.SetSizer(sizer)
         self._frame.SetAutoLayout(False)
         self.DoFrameLayout()
-        
+
         # now that the frame layout is done, we need to check
         # the new pane rectangles against the old rectangles that
         # we saved a few lines above here.  If the rectangles have
@@ -3364,10 +3364,10 @@
                 if p.rect != old_pane_rects[ii]:
                     p.window.Refresh()
                     p.window.Update()
-        
+
         self.Repaint()
 
-        
+
     def DoFrameLayout(self):
         """
         DoFrameLayout() is an internal function which invokes wx.Sizer.Layout
@@ -3377,16 +3377,16 @@
         """
 
         self._frame.Layout()
-        
+
         for ii in xrange(len(self._uiparts)):
             part = self._uiparts[ii]
-            
+
             # get the rectangle of the UI part
             # originally, this code looked like this:
             #    part.rect = wx.Rect(part.sizer_item.GetPosition(),
             #                       part.sizer_item.GetSize())
             # this worked quite well, with one exception: the mdi
-            # client window had a "deferred" size variable 
+            # client window had a "deferred" size variable
             # that returned the wrong size.  It looks like
             # a bug in wx, because the former size of the window
             # was being returned.  So, we will retrieve the part's
@@ -3395,7 +3395,7 @@
             part.rect = part.sizer_item.GetRect()
             flag = part.sizer_item.GetFlag()
             border = part.sizer_item.GetBorder()
-            
+
             if flag & wx.TOP:
                 part.rect.y -= border
                 part.rect.height += border
@@ -3433,7 +3433,7 @@
             if part.type == DockUIPart.typePane and \
                part.pane and part.pane.window == wnd:
                 return part
-    
+
         return None
 
 
@@ -3472,12 +3472,12 @@
             if test.dock_direction == dock.dock_direction and \
                test.dock_layer == dock.dock_layer and  \
                test.dock_row == dock.dock_row:
-            
+
                 if dock.IsVertical():
                     return dock.rect.y
                 else:
                     return dock.rect.x
-            
+
         return 0
 
 
@@ -3497,7 +3497,7 @@
             allowed = target.IsLeftDockable()
         elif new_pos.dock_direction == AUI_DOCK_RIGHT:
             allowed = target.IsRightDockable()
-        
+
         if allowed:
             target = new_pos
 
@@ -3541,62 +3541,62 @@
         # (or near to the outside of the window), if so, dock it along the edge
 
         layer_insert_offset = auiLayerInsertOffset
-        
+
         if target.IsToolbar():
             layer_insert_offset = 0
 
         if pt.x < layer_insert_offset and \
            pt.x > layer_insert_offset-auiLayerInsertPixels:
             new_layer = max(max(GetMaxLayer(docks, AUI_DOCK_LEFT),
-                                GetMaxLayer(docks, AUI_DOCK_BOTTOM)), 
+                                GetMaxLayer(docks, AUI_DOCK_BOTTOM)),
                             GetMaxLayer(docks, AUI_DOCK_TOP)) + 1
-            
+
             drop.Dock().Left().Layer(new_layer).Row(0). \
                  Position(pt.y - self.GetDockPixelOffset(drop) - offset.y)
 
             return self.ProcessDockResult(target, drop)
-        
+
         elif pt.y < layer_insert_offset and \
               pt.y > layer_insert_offset-auiLayerInsertPixels:
             new_layer = max(max(GetMaxLayer(docks, AUI_DOCK_TOP),
                                 GetMaxLayer(docks, AUI_DOCK_LEFT)),
                             GetMaxLayer(docks, AUI_DOCK_RIGHT)) + 1
-            
+
             drop.Dock().Top().Layer(new_layer).Row(0). \
                  Position(pt.x - self.GetDockPixelOffset(drop) - offset.x)
-            
+
             return self.ProcessDockResult(target, drop)
-        
+
         elif pt.x >= cli_size.x - layer_insert_offset and \
               pt.x < cli_size.x - layer_insert_offset + auiLayerInsertPixels:
-        
+
             new_layer = max(max(GetMaxLayer(docks, AUI_DOCK_RIGHT),
                                 GetMaxLayer(docks, AUI_DOCK_TOP)),
                             GetMaxLayer(docks, AUI_DOCK_BOTTOM)) + 1
-            
+
             drop.Dock().Right().Layer(new_layer).Row(0). \
                  Position(pt.y - self.GetDockPixelOffset(drop) - offset.y)
-            
+
             return self.ProcessDockResult(target, drop)
-        
+
         elif pt.y >= cli_size.y - layer_insert_offset and \
              pt.y < cli_size.y - layer_insert_offset + auiLayerInsertPixels:
-        
+
             new_layer = max(max(GetMaxLayer(docks, AUI_DOCK_BOTTOM),
                                 GetMaxLayer(docks, AUI_DOCK_LEFT)),
                             GetMaxLayer(docks, AUI_DOCK_RIGHT)) + 1
-            
+
             drop.Dock().Bottom().Layer(new_layer).Row(0). \
                  Position(pt.x - self.GetDockPixelOffset(drop) - offset.x)
-            
+
             return self.ProcessDockResult(target, drop)
-        
+
         part = self.HitTest(pt.x, pt.y)
 
         if drop.IsToolbar():
             if not part or not part.dock:
                 return False, target
-            
+
             # calculate the offset from where the dock begins
             # to the point where the user dropped the pane
             dock_drop_offset = 0
@@ -3611,9 +3611,9 @@
             if not part.dock.fixed or part.dock.dock_direction == 
AUI_DOCK_CENTER:
                 if self._flags & AUI_MGR_ALLOW_FLOATING:
                     drop.Float()
-                    
+
                 return self.ProcessDockResult(target, drop)
-            
+
             drop.Dock(). \
                  Direction(part.dock.dock_direction). \
                  Layer(part.dock.dock_layer). \
@@ -3625,17 +3625,17 @@
                 panes = DoInsertDockRow(panes, part.dock.dock_direction,
                                         part.dock.dock_layer,
                                         part.dock.dock_row)
-                drop.dock_row = row            
-                
+                drop.dock_row = row
+
             if pt.y > part.dock.rect.y + part.dock.rect.height - 2 and \
                len(part.dock.panes) > 1:
                 panes = DoInsertDockRow(panes, part.dock.dock_direction,
                                         part.dock.dock_layer,
                                         part.dock.dock_row+1)
                 drop.dock_row = part.dock.dock_row + 1
-                
+
             return self.ProcessDockResult(target, drop)
-        
+
         if not part:
             return False, target
 
@@ -3647,11 +3647,11 @@
             part.type == DockUIPart.typePaneSizer or \
             part.type == DockUIPart.typeDockSizer or \
             part.type == DockUIPart.typeBackground:
-        
+
             if part.type == DockUIPart.typeDockSizer:
                 if len(part.dock.panes) != 1:
                     return False, target
-                
+
                 part = self.GetPanePart(part.dock.panes[0].window)
 
             # If a normal frame is being dragged over a toolbar, insert it
@@ -3676,7 +3676,7 @@
                 elif part.dock.dock_direction == AUI_DOCK_BOTTOM:
                     layer = max(max(GetMaxLayer(docks, AUI_DOCK_BOTTOM),
                                     GetMaxLayer(docks, AUI_DOCK_LEFT)),
-                                GetMaxLayer(docks, AUI_DOCK_RIGHT))            
    
+                                GetMaxLayer(docks, AUI_DOCK_RIGHT))
 
                 panes = DoInsertDockRow(panes, part.dock.dock_direction,
                                         layer, 0)
@@ -3685,19 +3685,19 @@
                      Layer(layer).Row(0).Position(0)
 
                 return self.ProcessDockResult(target, drop)
-            
+
             if not part.pane:
                 return False, target
 
             part = self.GetPanePart(part.pane.window)
             if not part:
                 return False, target
-                
+
             insert_dock_row = False
             insert_row = part.pane.dock_row
             insert_dir = part.pane.dock_direction
             insert_layer = part.pane.dock_layer
-            
+
             if part.pane.dock_direction == AUI_DOCK_TOP:
                 if pt.y >= part.rect.y and \
                    pt.y < part.rect.y+auiInsertRowPixels:
@@ -3736,7 +3736,7 @@
 
                     insert_layer = 0
                     insert_dock_row = True
-                                        
+
                     if pt.x >= part.rect.x and \
                        pt.x < part.rect.x+new_row_pixels_x:
                         insert_dir = AUI_DOCK_LEFT
@@ -3751,11 +3751,11 @@
                         insert_dir = AUI_DOCK_BOTTOM
                     else:
                         return False, target
-                    
+
                     insert_row = GetMaxRow(panes, insert_dir, insert_layer) + 1
 
             if insert_dock_row:
-             
+
                 panes = DoInsertDockRow(panes, insert_dir, insert_layer,
                                         insert_row)
                 drop.Dock().Direction(insert_dir). \
@@ -3764,37 +3764,37 @@
                             Position(0)
 
                 return self.ProcessDockResult(target, drop)
-            
+
             # determine the mouse offset and the pane size, both in the
             # direction of the dock itself, and perpendicular to the dock
-            
+
             if part.orientation == wx.VERTICAL:
-            
+
                 offset = pt.y - part.rect.y
-                size = part.rect.GetHeight() 
-            
+                size = part.rect.GetHeight()
+
             else:
-            
+
                 offset = pt.x - part.rect.x
                 size = part.rect.GetWidth()
-            
+
             drop_position = part.pane.dock_pos
-            
+
             # if we are in the top/left part of the pane,
             # insert the pane before the pane being hovered over
             if offset <= size/2:
-            
+
                 drop_position = part.pane.dock_pos
                 panes = DoInsertPane(panes,
                                      part.pane.dock_direction,
                                      part.pane.dock_layer,
                                      part.pane.dock_row,
                                      part.pane.dock_pos)
-            
+
             # if we are in the bottom/right part of the pane,
             # insert the pane before the pane being hovered over
             if offset > size/2:
-            
+
                 drop_position = part.pane.dock_pos+1
                 panes = DoInsertPane(panes,
                                      part.pane.dock_direction,
@@ -3807,9 +3807,9 @@
                  Layer(part.dock.dock_layer). \
                  Row(part.dock.dock_row). \
                  Position(drop_position)
-                        
+
             return self.ProcessDockResult(target, drop)
-        
+
         return False, target
 
 
@@ -3820,11 +3820,11 @@
         #sanity check
         if not self.UseTransparentHint():
             return
-            
+
         if not self._hint_wnd or self._hint_fadeamt >= 50:
             self._hint_fadetimer.Stop()
             return
-        
+
         self._hint_fadeamt = self._hint_fadeamt + 5
         self.MakeWindowTransparent(self._hint_wnd, self._hint_fadeamt)
 
@@ -3832,18 +3832,18 @@
     def ShowHint(self, rect):
         self._hintshown = True
         if self.UseTransparentHint():
-            if wx.Platform == "__WXMSW__":                    
+            if wx.Platform == "__WXMSW__":
                 if self._last_hint == rect:
                     return
                 self._last_hint = rect
-                
+
                 initial_fade = 50
-                
+
                 if self._flags & AUI_MGR_TRANSPARENT_HINT_FADE:
                     initial_fade = 0
-                    
+
                 if self._hint_wnd == None:
-                
+
                     pt = rect.GetPosition()
                     size = rect.GetSize()
                     self._hint_wnd = wx.Frame(self._frame, -1, "", pt, size,
@@ -3856,19 +3856,19 @@
                     self._hint_wnd.Show()
 
                     # if we are dragging a floating pane, set the focus
-                    
+
                     # back to that floating pane (otherwise it becomes 
unfocused)
-                    
+
                     if self._action == actionDragFloatingPane and 
self._action_window:
                         self._action_window.SetFocus()
-                
+
                 else:
-                
+
                     pt = rect.GetPosition()
                     size = rect.GetSize()
                     self.MakeWindowTransparent(self._hint_wnd, initial_fade)
                     self._hint_wnd.SetDimensions(pt.x, pt.y, rect.width, 
rect.height)
-                
+
                 if self._flags & AUI_MGR_TRANSPARENT_HINT_FADE:
                     # start fade in timer
                     self._hint_fadeamt = 0
@@ -3882,7 +3882,7 @@
                     initial_fade = 0
                 else:
                     initial_fade = 80
-   
+
                 if not self._hint_wnd:
                     self._hint_wnd = wx.MiniFrame(self._frame,
                         style=wx.FRAME_FLOAT_ON_PARENT|wx.FRAME_TOOL_WINDOW
@@ -3892,23 +3892,23 @@
                         #and distracting.
                         #wx.CAPTION + wx.FRAME_TOOL_WINDOW cures the focus 
problem,
                         #but then it draws the caption. Adding wx.FRAME_SHAPED 
takes
-                        #care of that, but then SetRect doesn't work to size - 
need to 
+                        #care of that, but then SetRect doesn't work to size - 
need to
                         #create a bitmap or mask or something.
                         )
                     #can't set the background of a wx.Frame in OSX
                     p = wx.Panel(self._hint_wnd)
-                    
+
                     #the caption color is a light silver thats really hard to 
see
                     #especially transparent. See if theres some other system
                     #setting that is more appropriate, or just extend the art 
provider
                     #to cover this
                     
#p.SetBackgroundColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_ACTIVECAPTION))
                     p.SetBackgroundColour(wx.BLUE)
-                    
+
                 self.MakeWindowTransparent(self._hint_wnd, initial_fade)
                 self._hint_wnd.SetRect(rect)
                 self._hint_wnd.Show()
-                
+
                 if self._action == actionDragFloatingPane and 
self._action_window:
                    self._action_window.SetFocus()
 
@@ -3919,7 +3919,7 @@
                     self._hint_fadetimer.Start(5)
                 return
 
-            
+
         if self._last_hint != rect:
             # remove the last hint rectangle
             self._last_hint = rect
@@ -3927,7 +3927,7 @@
             self._frame.Update()
 
 
-        
+
         screendc = wx.ScreenDC()
         clip = wx.Region(1, 1, 10000, 10000)
 
@@ -3954,13 +3954,13 @@
         screendc.DrawRectangle(rect.x, rect.y, 5, rect.height)
         screendc.DrawRectangle(rect.x+5, rect.y, rect.width-10, 5)
         screendc.DrawRectangle(rect.x+rect.width-5, rect.y, 5, rect.height)
-        screendc.DrawRectangle(rect.x+5, rect.y+rect.height-5, rect.width-10, 
5)  
+        screendc.DrawRectangle(rect.x+5, rect.y+rect.height-5, rect.width-10, 
5)
 
 
     def HideHint(self):
 
         self._hintshown = False
-        
+
         # hides a transparent window hint (currently wx.MSW only)
         if self.UseTransparentHint():
             if self._hint_wnd:
@@ -3968,16 +3968,16 @@
                 #self._hint_wnd.Destroy()
                 self.MakeWindowTransparent(self._hint_wnd, 0)
                 self._last_hint = wx.Rect()
-                
+
         return
-        
+
         # hides a painted hint by redrawing the frame window
         if not self._last_hint.IsEmpty():
             self._frame.Refresh()
             self._frame.Update()
             self._last_hint = wx.Rect()
-        
 
+
     def DrawHintRect(self, pane_window, pt, offset):
         """
         DrawHintRect() draws a drop hint rectangle. First calls DoDrop() to
@@ -3987,7 +3987,7 @@
         "pane_window" is the window pointer of the pane being dragged, pt is
         the mouse position, in client coordinates.
         """
-        
+
         # we need to paint a hint rectangle to find out the exact hint 
rectangle,
         # we will create a new temporary layout and then measure the resulting
         # rectangle we will create a copy of the docking structures 
(self._docks)
@@ -3995,14 +3995,14 @@
 
         rect = wx.Rect()
         pane = self.GetPane(pane_window)
-        
+
         attrs = self.GetAttributes(pane)
         hint = PaneInfo()
         hint = self.SetAttributes(hint, attrs)
-        
+
         if hint.name != "__HINT__":
             self._oldname = hint.name
-            
+
         hint.name = "__HINT__"
 
         if not hint.IsOk():
@@ -4025,7 +4025,7 @@
         if not allow:
             self.HideHint()
             return
-        
+
         panes.append(hint)
 
         sizer, panes, docks, uiparts = self.LayoutAll(panes, docks, [], True, 
False)
@@ -4041,7 +4041,7 @@
                 size = part.sizer_item.GetSize()
                 rect = wx.Rect(pos[0], pos[1], size[0], size[1])
                 break
-            
+
         sizer.Destroy()
 
         # actually show the hint rectangle on the screen
@@ -4059,8 +4059,8 @@
                      pane.buttons, pane.rect])
 
         return attrs
-    
 
+
     def SetAttributes(self, pane, attrs):
 
         pane.window = attrs[0]
@@ -4082,14 +4082,14 @@
         pane.rect = attrs[16]
 
         return pane
-    
+
     def UseTransparentDrag(self):
         if self._flags & AUI_MGR_TRANSPARENT_DRAG:
             return self.CanMakeWindowsTransparent()
         else:
             return False
-        
- 
+
+
     def OnFloatingPaneMoveStart(self, wnd):
 
         # try to find the pane
@@ -4107,10 +4107,10 @@
 
         if not pane.IsOk():
             raise "\nERROR: Pane Window Not Found"
-        
+
         pt = wx.GetMousePosition()
         client_pt = self._frame.ScreenToClient(pt)
-        
+
         # calculate the offset from the upper left-hand corner
         # of the frame to the mouse pointer
         frame_pos = pane.frame.GetPosition()
@@ -4119,7 +4119,7 @@
         # no hint for toolbar floating windows
         if pane.IsToolbar() and self._action == actionDragFloatingPane:
             if self._action == actionDragFloatingPane:
-                
+
                 oldname = pane.name
                 indx = self._panes.index(pane)
                 hint = pane
@@ -4127,7 +4127,7 @@
 
                 # find out where the new pane would be
                 ret, hint = self.DoDrop(docks, panes, hint, client_pt)
-                
+
                 if not ret:
                     return
 
@@ -4136,13 +4136,13 @@
 
                 pane = hint
                 pane.name = oldname
-                
+
                 self._panes[indx] = pane
                 self._action = actionDragToolbarPane
                 self._action_window = pane.window
-                
+
                 self.Update()
-            
+
             return
 
         # if a key modifier is pressed while dragging the frame,
@@ -4150,10 +4150,10 @@
         if wx.GetKeyState(wx.WXK_CONTROL):
             self.HideHint()
             return
-    
+
         if pane.IsDockable():
             self.DrawHintRect(wnd, client_pt, action_offset)
-        
+
         # reduces flicker
         self._frame.Update()
         wx.CallAfter(pane.frame.Refresh)
@@ -4166,12 +4166,12 @@
 
         if not pane.IsOk():
             raise "\nERROR: Pane Window Not Found"
-        
+
         pt = wx.GetMousePosition()
         client_pt = self._frame.ScreenToClient(pt)
 
         indx = self._panes.index(pane)
-        
+
         # calculate the offset from the upper left-hand corner
         # of the frame to the mouse pointer
         frame_pos = pane.frame.GetPosition()
@@ -4190,7 +4190,7 @@
                 self._panes[indx] = pane
                 if self.UseTransparentDrag():
                     self.MakeWindowTransparent(pane.frame, 255)
-            
+
         # do the drop calculation
         allow, pane = self.DoDrop(self._docks, self._panes, pane, client_pt, 
action_offset)
 
@@ -4203,9 +4203,9 @@
 
         if not pane.IsToolbar() and pane.IsDockable():
             pane.name = self._oldname
-            
+
         self._panes[indx] = pane
-            
+
         self.Update()
         self.HideHint()
 
@@ -4217,7 +4217,7 @@
         if not pane.IsOk():
             raise "\nERROR: Pane Window Not Found"
 
-        indx = self._panes.index(pane)    
+        indx = self._panes.index(pane)
         pane.floating_size = size
         self._panes[indx] = pane
 
@@ -4236,7 +4236,7 @@
         pane.window.Reparent(self._frame)
         pane.frame = None
         pane.Hide()
-        
+
         self._panes[indx] = pane
 
 
@@ -4250,8 +4250,8 @@
 
             self._panes = SetActivePane(self._panes, wnd)
             self.Repaint()
-            
 
+
     def Render(self, dc):
         """
         Render() draws all of the pane captions, sashes,
@@ -4265,7 +4265,7 @@
             # don't draw hidden pane items
             if part.sizer_item and not part.sizer_item.IsShown():
                 continue
-            
+
             if part.type == DockUIPart.typeDockSizer or \
                part.type == DockUIPart.typePaneSizer:
                 self._art.DrawSash(dc, part.orientation, part.rect)
@@ -4280,8 +4280,8 @@
             elif part.type == DockUIPart.typePaneButton:
                 self._art.DrawPaneButton(dc, part.button.button_id,
                                          AUI_BUTTON_STATE_NORMAL, part.rect, 
part.pane)
-                
 
+
     def Repaint(self, dc=None):
 
         w, h = self._frame.GetClientSize()
@@ -4289,11 +4289,11 @@
         # has been specified, use it, otherwise
         # make a client dc
         client_dc = None
-        
+
         if not dc:
             client_dc = wx.ClientDC(self._frame)
             dc = client_dc
-        
+
         # if the frame has a toolbar, the client area
         # origin will not be (0,0).
         pt = self._frame.GetClientAreaOrigin()
@@ -4306,8 +4306,8 @@
         # if we created a client_dc, delete it
         if client_dc:
             del client_dc
-        
 
+
     def OnPaint(self, event):
         dc = wx.PaintDC(self._frame)
         if wx.Platform == "__WXMAC__":
@@ -4322,7 +4322,7 @@
 
     def OnEraseBackground(self, event):
 
-        event.Skip()        
+        event.Skip()
 
 
     def OnSize(self, event):
@@ -4357,7 +4357,7 @@
                     cursor = wx.StockCursor(wx.CURSOR_SIZEWE)
                 else:
                     cursor = wx.StockCursor(wx.CURSOR_SIZENS)
-            
+
             elif part.type == DockUIPart.typeGripper:
                 cursor = wx.StockCursor(wx.CURSOR_SIZING)
 
@@ -4369,7 +4369,7 @@
 
         hit_test = self.HitTest(event.GetX(), event.GetY())
         state = AUI_BUTTON_STATE_NORMAL
-        
+
         if hit_test == button_ui_part:
             if event.LeftDown():
                 state = AUI_BUTTON_STATE_PRESSED
@@ -4378,7 +4378,7 @@
         else:
             if event.LeftDown():
                 state = AUI_BUTTON_STATE_HOVER
-        
+
         # now repaint the button with hover state
         cdc = wx.ClientDC(self._frame)
 
@@ -4404,7 +4404,7 @@
 
             if part.type == DockUIPart.typeDockSizer or \
                part.type == DockUIPart.typePaneSizer:
-            
+
                 # a dock may not be resized if it has a single
                 # pane which is not resizable
                 if part.type == DockUIPart.typeDockSizer and part.dock and \
@@ -4426,16 +4426,16 @@
                 print "\tRect: ", self._action_hintrect
                 print "\tStart:", self._action_start
                 print "\tOffset:", self._action_offset
-            
+
             elif part.type == DockUIPart.typePaneButton:
-            
+
                 self._action = actionClickButton
                 self._action_part = part
                 self._action_start = wx.Point(event.GetX(), event.GetY())
                 self._frame.CaptureMouse()
 
                 self.UpdateButtonOnScreen(part, event)
-            
+
             elif part.type == DockUIPart.typeCaption or \
                   part.type == DockUIPart.typeGripper:
 
@@ -4443,7 +4443,7 @@
                     # set the caption as active
                     self._panes = SetActivePane(self._panes, part.pane.window)
                     self.Repaint()
-            
+
                 self._action = actionClickCaption
                 self._action_part = part
                 self._action_start = wx.Point(event.GetX(), event.GetY())
@@ -4485,10 +4485,10 @@
 
                 self.Update()
                 self.Repaint(None)
-            
+
             elif self._action_part and \
                  self._action_part.type == DockUIPart.typePaneSizer:
-            
+
                 dock = self._action_part.dock
                 pane = self._action_part.pane
 
@@ -4526,18 +4526,18 @@
                 # the fixed panes
                 dock_pane_count = len(dock.panes)
                 pane_position = -1
-                
+
                 for ii in xrange(dock_pane_count):
                     p = dock.panes[ii]
                     if p.window == pane.window:
                         pane_position = ii
-                    
+
                     # while we're at it, subtract the pane sash
                     # width from the dock width, because this would
                     # skew our proportion calculations
                     if ii > 0:
                         dock_pixels = dock_pixels - sash_size
-                 
+
                     # also, the whole size (including decorations) of
                     # all fixed panes must also be subtracted, because they
                     # are not part of the proportion calculation
@@ -4548,35 +4548,35 @@
                             dock_pixels = dock_pixels - p.best_size.y
                     else:
                         total_proportion = total_proportion + p.dock_proportion
-                    
+
                 # find a pane in our dock to 'steal' space from or to 'give'
                 # space to -- this is essentially what is done when a pane is
                 # resized the pane should usually be the first non-fixed pane
                 # to the right of the action pane
                 borrow_pane = -1
-                
+
                 for ii in xrange(pane_position+1, dock_pane_count):
                     p = dock.panes[ii]
                     if not p.IsFixed():
                         borrow_pane = ii
                         break
-                
+
                 # demand that the pane being resized is found in this dock
                 # (this assert really never should be raised)
                 if pane_position == -1:
                     raise "\nERROR: Pane not found in dock"
-                
+
                 # prevent division by zero
                 if dock_pixels == 0 or total_proportion == 0 or borrow_pane == 
-1:
                     self._action = actionNone
                     return
-                
+
                 # calculate the new proportion of the pane
                 new_proportion = new_pixsize*total_proportion/dock_pixels
-                
+
                 # default minimum size
                 min_size = 0
-                
+
                 # check against the pane's minimum size, if specified. please 
note
                 # that this is not enough to ensure that the minimum size will
                 # not be violated, because the whole frame might later be 
shrunk,
@@ -4593,18 +4593,18 @@
                             min_size = min_size + caption_size
                     else:
                         min_size = min_size + pane.min_size.x
-                    
+
                 # for some reason, an arithmatic error somewhere is causing
                 # the proportion calculations to always be off by 1 pixel
                 # for now we will add the 1 pixel on, but we really should
                 # determine what's causing this.
                 min_size = min_size + 1
-                
+
                 min_proportion = min_size*total_proportion/dock_pixels
-                    
+
                 if new_proportion < min_proportion:
                     new_proportion = min_proportion
-                
+
                 prop_diff = new_proportion - pane.dock_proportion
 
                 # borrow the space from our neighbor pane to the
@@ -4617,33 +4617,33 @@
 
                 self._docks[indxd] = dock
                 self._panes[indxp] = pane
-                
+
                 # repaint
                 self.Update()
                 self.Repaint(None)
-        
+
         elif self._action == actionClickButton:
-        
+
             self._hover_button = None
-            self._frame.ReleaseMouse()     
+            self._frame.ReleaseMouse()
             self.UpdateButtonOnScreen(self._action_part, event)
 
             # make sure we're still over the item that was originally clicked
             if self._action_part == self.HitTest(event.GetX(), event.GetY()):
-                # fire button-click event  
+                # fire button-click event
                 e = FrameManagerEvent(wx.EVT_AUI_PANEBUTTON)
                 e.SetPane(self._action_part.pane)
                 e.SetButton(self._action_part.button.button_id)
                 self.ProcessMgrEvent(e)
-        
+
         elif self._action == actionClickCaption:
-        
+
             self._frame.ReleaseMouse()
-        
+
         elif self._action == actionDragFloatingPane:
-            
+
             self._frame.ReleaseMouse()
-        
+
         elif self._action == actionDragToolbarPane:
 
             self._frame.ReleaseMouse()
@@ -4651,7 +4651,7 @@
             pane = self.GetPane(self._action_window)
             if not pane.IsOk():
                 raise "\nERROR: Pane Window Not Found"
-        
+
             # save the new positions
             docks = FindDocks(self._docks, pane.dock_direction,
                               pane.dock_layer, pane.dock_row)
@@ -4659,17 +4659,17 @@
             if len(docks) == 1:
                 dock = docks[0]
                 pane_positions, pane_sizes = 
self.GetPanePositionsAndSizes(dock)
-                
+
                 dock_pane_count = len(dock.panes)
                 for ii in xrange(dock_pane_count):
                     dock.panes[ii].dock_pos = pane_positions[ii]
-            
+
             pane.state &= ~PaneInfo.actionPane
             indx = self._panes.index(pane)
             self._panes[indx] = pane
-            
+
             self.Update()
-        
+
         self._action = actionNone
         self._last_mouse_move = wx.Point() # see comment in OnMotion()
 
@@ -4681,11 +4681,11 @@
         # sure that only real mouse moves will get anywhere in this method
         # this appears to be a bug somewhere, and I don't know where the
         # mouse move event is being generated.  only verified on MSW
-        
+
         mouse_pos = event.GetPosition()
         if self._last_mouse_move == mouse_pos:
             return
-        
+
         self._last_mouse_move = mouse_pos
 
         if self._action == actionResize:
@@ -4700,32 +4700,32 @@
             rect = wx.Rect(mypos[0], mypos[1], mysize[0], mysize[1])
 
             dc = wx.ScreenDC()
-            
+
             if not self._action_hintrect.IsEmpty() and self._action_hintrect 
!= rect:
                 DrawResizeHint(dc, self._action_hintrect)
-                
+
             DrawResizeHint(dc, rect)
             self._action_hintrect = rect
-        
+
         elif self._action == actionClickCaption:
-        
+
             drag_x_threshold = wx.SystemSettings_GetMetric(wx.SYS_DRAG_X)
             drag_y_threshold = wx.SystemSettings_GetMetric(wx.SYS_DRAG_Y)
-            
+
             # caption has been clicked.  we need to check if the mouse
             # is now being dragged. if it is, we need to change the
             # mouse action to 'drag'
             if abs(mouse_pos.x - self._action_start.x) > drag_x_threshold or \
                abs(mouse_pos.y - self._action_start.y) > drag_y_threshold:
-            
+
                 pane_info = self._action_part.pane
                 indx = self._panes.index(pane_info)
 
                 if not pane_info.IsToolbar():
-                
+
                     if self._flags & AUI_MGR_ALLOW_FLOATING and \
                        pane_info.IsFloatable():
-                    
+
                         self._action = actionDragFloatingPane
 
                         # set initial float position
@@ -4735,11 +4735,11 @@
                         # float the window
                         pane_info.Float()
                         self._panes[indx] = pane_info
-                        
+
                         self.Update()
 
                         self._action_window = pane_info.frame
-                        
+
                         # action offset is used here to make it feel "natural" 
to the user
                         # to drag a docked pane and suddenly have it become a 
floating frame.
                         # Sometimes, however, the offset where the user 
clicked on the docked
@@ -4748,63 +4748,63 @@
                         frame_size = self._action_window.GetSize()
                         if frame_size.x <= self._action_offset.x:
                             self._action_offset.x = 30
-                    
+
                 else:
-                
+
                     self._action = actionDragToolbarPane
                     self._action_window = pane_info.window
-                
+
         elif self._action == actionDragFloatingPane:
-        
+
             pt = self._frame.ClientToScreen(event.GetPosition())
             if self._action_window:
                 self._action_window.Move((pt.x - self._action_offset.x,
                                          pt.y - self._action_offset.y))
-        
+
         elif self._action == actionDragToolbarPane:
 
             pane = self.GetPane(self._action_window)
             if not pane.IsOk():
                 raise "\nERROR: Pane Window Not Found"
 
-            indx = self._panes.index(pane)            
+            indx = self._panes.index(pane)
             pane.state |= PaneInfo.actionPane
-        
+
             pt = event.GetPosition()
             ret, pane = self.DoDrop(self._docks, self._panes, pane, pt, 
self._action_offset)
 
             if not ret:
                 return
-            
+
             # if DoDrop() decided to float the pane, set up
             # the floating pane's initial position
             if pane.IsFloating():
-            
+
                 pt = self._frame.ClientToScreen(event.GetPosition())
                 pane.floating_pos = wx.Point(pt.x - self._action_offset.x,
                                              pt.y - self._action_offset.y)
 
             self._panes[indx] = pane
-            
+
             # this will do the actiual move operation
             # in the case that the pane has been floated,
             # this call will create the floating pane
             # and do the reparenting
             self.Update()
-            
+
             # if the pane has been floated, change the mouse
             # action actionDragFloatingPane so that subsequent
             # wx.EVT_MOTION() events will move the floating pane
             if pane.IsFloating():
-            
+
                 pane.state &= ~PaneInfo.actionPane
                 self._action = actionDragFloatingPane
                 self._action_window = pane.frame
 
-            self._panes[indx] = pane                
-            
+            self._panes[indx] = pane
+
         else:
-        
+
             part = self.HitTest(event.GetX(), event.GetY())
             if part and part.type == DockUIPart.typePaneButton:
                 if part != self._hover_button:
@@ -4816,13 +4816,13 @@
                     # button in hover mode
                     self.UpdateButtonOnScreen(part, event)
                     self._hover_button = part
-            else:            
+            else:
                 if self._hover_button:
-                
+
                     self._hover_button = None
                     self.Repaint()
 
-                
+
     def OnLeaveWindow(self, event):
 
         if self._hover_button:
@@ -4832,17 +4832,17 @@
 
     def OnChildFocus(self, event):
 
-        # when a child pane has it's focus set, we should change the 
-        # pane's active state to reflect this. (this is only True if 
+        # when a child pane has it's focus set, we should change the
+        # pane's active state to reflect this. (this is only True if
         # active panes are allowed by the owner)
         if self.GetFlags() & AUI_MGR_ALLOW_ACTIVE_PANE:
             if self.GetPane(event.GetWindow()).IsOk():
                 self._panes = SetActivePane(self._panes, event.GetWindow())
                 self._frame.Refresh()
-    
+
         event.Skip()
-        
 
+
     def OnPaneButton(self, event):
         """
         OnPaneButton() is an event handler that is called
@@ -4851,16 +4851,16 @@
 
         pane = event.pane
         indx = self._panes.index(pane)
-        
+
         if event.button == PaneInfo.buttonClose:
             pane.Hide()
             self._panes[indx] = pane
             self.Update()
-        
+
         elif event.button == PaneInfo.buttonPin:
-        
+
             if self._flags & AUI_MGR_ALLOW_FLOATING and pane.IsFloatable():
                 pane.Float()
 
-            self._panes[indx] = pane                
+            self._panes[indx] = pane
             self.Update()





reply via email to

[Prev in Thread] Current Thread [Next in Thread]