eg/Classes/MainFrame/__init__.py
# -*- coding: utf-8 -*-
#
# This file is part of EventGhost.
# Copyright © 2005-2020 EventGhost Project <http://www.eventghost.net/>
#
# EventGhost is free software: you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free
# Software Foundation, either version 2 of the License, or (at your option)
# any later version.
#
# EventGhost is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
# more details.
#
# You should have received a copy of the GNU General Public License along
# with EventGhost. If not, see <http://www.gnu.org/licenses/>.
import inspect
import re
import types
import wx
import wx.aui
from collections import defaultdict
from os.path import join
# Local imports
import eg
from eg.Classes.MainFrame.LogCtrl import LogCtrl
from eg.Classes.MainFrame.StatusBar import StatusBar
from eg.Classes.MainFrame.TreeCtrl import TreeCtrl
from eg.Icons import CreateBitmapOnTopOfIcon, GetInternalBitmap
from eg.WinApi.Dynamic import GetDesktopWindow, HH_DISPLAY_TOPIC, HtmlHelp
from eg.WinApi.Utils import BringHwndToFront
ADD_ICON = eg.Icons.ADD_ICON
ADD_PLUGIN_ICON = CreateBitmapOnTopOfIcon(ADD_ICON, eg.Icons.PLUGIN_ICON)
ADD_FOLDER_ICON = CreateBitmapOnTopOfIcon(ADD_ICON, eg.Icons.FOLDER_ICON)
ADD_MACRO_ICON = CreateBitmapOnTopOfIcon(ADD_ICON, eg.Icons.MACRO_ICON)
ADD_EVENT_ICON = CreateBitmapOnTopOfIcon(ADD_ICON, eg.Icons.EVENT_ICON)
ADD_ACTION_ICON = CreateBitmapOnTopOfIcon(ADD_ICON, eg.Icons.ACTION_ICON)
ID_DISABLED = wx.NewId()
ID_EXECUTE = wx.NewId()
ID_PYTHON = wx.NewId()
ID_TOOLBAR_EXECUTE = wx.NewId()
ID = defaultdict(wx.NewId, {
"Save": wx.ID_SAVE,
"Undo": wx.ID_UNDO,
"Redo": wx.ID_REDO,
"Cut": wx.ID_CUT,
"Copy": wx.ID_COPY,
"Python": ID_PYTHON,
"Paste": wx.ID_PASTE,
"Delete": wx.ID_DELETE,
"Disabled": ID_DISABLED,
"Execute": ID_EXECUTE,
})
Text = eg.text.MainFrame
class Config(eg.PersistentData):
position = (50, 50)
size = (700, 450)
showToolbar = True
logDate = False
logTime = False
indentLog = True
expandOnEvents = False
perspective = None
perspective2 = None
ratio = 2.0
class MainFrame(wx.Frame):
"""
This is the MainFrame of EventGhost
"""
style = (
wx.MINIMIZE_BOX | wx.MAXIMIZE_BOX | wx.RESIZE_BORDER | wx.CAPTION |
wx.SYSTEM_MENU | wx.CLOSE_BOX | wx.CLIP_CHILDREN | wx.TAB_TRAVERSAL
)
@eg.AssertInMainThread
def __init__(self, document):
"""
Create the MainFrame
"""
self.document = document
self.findDialog = None
self.openDialogs = []
self.lastClickedTool = None
self.egEvent = None
self.lastFocus = None
wx.Frame.__init__(
self,
None,
-1,
document.GetTitle(),
pos=Config.position,
size=(1, 1),
style=self.style
)
self.SetMinSize((400, 200))
document.frame = self
auiManager = wx.aui.AuiManager(self, wx.aui.AUI_MGR_DEFAULT)
self.auiManager = auiManager
self.logCtrl = self.CreateLogCtrl()
self.corConst = self.logCtrl.GetWindowBorderSize()[0] + \
wx.SystemSettings.GetMetric(wx.SYS_VSCROLL_X)
self.treeCtrl = self.CreateTreeCtrl()
self.toolBar = self.CreateToolBar()
self.menuBar = self.CreateMenuBar()
self.statusBar = StatusBar(self)
self.SetStatusBar(self.statusBar)
# tree popup menu
self.popupMenu = self.CreateTreePopupMenu()
iconBundle = wx.IconBundle()
iconBundle.AddIcon(eg.taskBarIcon.stateIcons[0])
icon = wx.EmptyIcon()
icon.LoadFile(join(eg.imagesDir, "icon32x32.png"), wx.BITMAP_TYPE_PNG)
iconBundle.AddIcon(icon)
self.SetIcons(iconBundle)
self.Bind(wx.EVT_ICONIZE, self.OnIconize)
self.Bind(wx.EVT_MENU_OPEN, self.OnMenuOpen)
self.Bind(wx.EVT_CLOSE, self.OnClose)
self.mainSizeFlag = True
self.ratioLock = False
self.ratio = Config.ratio
self.Bind(wx.EVT_SIZE, self.OnSize)
self.Bind(wx.EVT_MOVE, self.OnMove)
self.Bind(wx.aui.EVT_AUI_PANE_CLOSE, self.OnPaneClose)
self.Bind(wx.aui.EVT_AUI_PANE_MAXIMIZE, self.OnPaneMaximize)
self.Bind(wx.aui.EVT_AUI_PANE_RESTORE, self.OnPaneRestore)
self.UpdateViewOptions()
self.SetSize(Config.size)
eg.Bind("DocumentFileChange", self.OnDocumentFileChange)
eg.Bind("DocumentChange", self.OnDocumentChange)
eg.Bind("DialogCreate", self.OnAddDialog)
eg.Bind("DialogDestroy", self.OnRemoveDialog)
eg.Bind("UndoChange", self.OnUndoChange)
self.OnUndoChange(document.undoState)
eg.Bind("SelectionChange", self.OnSelectionChange)
if document.selection is not None:
self.OnSelectionChange(document.selection)
eg.Bind("FocusChange", self.OnFocusChange)
self.OnFocusChange(self.treeCtrl)
eg.Bind("ClipboardChange", self.OnClipboardChange)
# tell FrameManager to manage this frame
if (Config.perspective is not None):
try:
auiManager.LoadPerspective(Config.perspective, False)
except:
pass
artProvider = auiManager.GetArtProvider()
artProvider.SetMetric(wx.aui.AUI_DOCKART_PANE_BORDER_SIZE, 0)
artProvider.SetMetric(
wx.aui.AUI_DOCKART_GRADIENT_TYPE,
wx.aui.AUI_GRADIENT_HORIZONTAL
)
artProvider.SetColour(
wx.aui.AUI_DOCKART_INACTIVE_CAPTION_COLOUR,
eg.colour.inactiveCaption
)
artProvider.SetColour(
wx.aui.AUI_DOCKART_INACTIVE_CAPTION_GRADIENT_COLOUR,
eg.colour.inactiveCaptionGradient
)
artProvider.SetColour(
wx.aui.AUI_DOCKART_INACTIVE_CAPTION_TEXT_COLOUR,
eg.colour.inactiveCaptionTextColour
)
auiManager.GetPane("tree").Caption(" " + Text.Tree.caption)
self.toolBar.Show(Config.showToolbar)
auiManager.Update()
auiManager.GetPane("logger").MinSize((100, 100))\
.Caption(" " + Text.Logger.caption)
# create an accelerator for the "Log only assigned and activated
# events" checkbox. An awful hack.
@eg.LogIt
def ToggleOnlyLogAssigned(dummyEvent):
checkBox = self.statusBar.checkBox
flag = not checkBox.GetValue()
checkBox.SetValue(flag)
eg.config.onlyLogAssigned = flag
self.statusBar.SetCheckBoxColour(flag)
toggleOnlyLogAssignedId = wx.NewId()
wx.EVT_MENU(self, toggleOnlyLogAssignedId, ToggleOnlyLogAssigned)
# find the accelerator key in the label of the checkbox
labelText = eg.text.MainFrame.onlyLogAssigned
result = re.search(r'&([a-z])', labelText, re.IGNORECASE)
if result:
hotKey = result.groups()[0].upper()
else:
hotKey = "L"
# create an accelerator for the "Del" key. This way we can temporarily
# disable it while editing a tree label.
# (see TreeCtrl.py OnBeginLabelEdit and OnEndLabelEdit)
def OnDelKey(dummyEvent):
self.DispatchCommand('OnCmdDelete')
delId = wx.NewId()
wx.EVT_MENU(self, delId, OnDelKey)
def OnEnterKey(dummyEvent):
if self.lastFocus == self.treeCtrl.editControl:
self.treeCtrl.EndEditLabel(self.treeCtrl.editLabelId, False)
enterId = wx.NewId()
wx.EVT_MENU(self, enterId, OnEnterKey)
self.acceleratorTable = wx.AcceleratorTable(
[
(wx.ACCEL_NORMAL, wx.WXK_DELETE, delId),
(wx.ACCEL_NORMAL, wx.WXK_RETURN, enterId),
(wx.ACCEL_ALT, ord(hotKey), toggleOnlyLogAssignedId),
]
)
self.SetAcceleratorTable(self.acceleratorTable)
self.logCtrl.Bind(wx.EVT_SIZE, self.OnLogCtrlSize)
eg.EnsureVisible(self)
if eg.debugLevel:
@eg.LogIt
def __del__(self):
pass
def CreateLogCtrl(self):
logCtrl = LogCtrl(self)
logCtrl.Freeze()
if not Config.logDate:
logCtrl.SetDateLogging(False)
if not Config.logTime:
logCtrl.SetTimeLogging(False)
logCtrl.SetIndent(Config.indentLog)
self.auiManager.AddPane(
logCtrl,
wx.aui.AuiPaneInfo().
Name("logger").
Left().
MinSize((280, 300)).
MaximizeButton(True).
CloseButton(False).
Caption(" " + Text.Logger.caption)
)
self.auiManager.Update()
logCtrl.Thaw()
return logCtrl
def CreateMenuBar(self):
"""
Creates the main menu bar and all its menus.
"""
text = Text.Menu
menuBar = wx.MenuBar()
def Append(ident, hotkey="", kind=wx.ITEM_NORMAL, image=None):
label = getattr(text, ident, ident)
item = wx.MenuItem(menu, ID[ident], label + hotkey, "", kind)
if image:
item.SetBitmap(image)
menu.AppendItem(item)
func = getattr(self, "OnCmd" + ident)
def FuncWrapper(dummyEvent):
func()
self.Bind(wx.EVT_MENU, FuncWrapper, item)
return item
# file menu
menu = wx.Menu()
menuBar.Append(menu, text.FileMenu)
Append("New", "\tCtrl+N")
Append("Open", "\tCtrl+O")
Append("Save", "\tCtrl+S").Enable(False)
Append("SaveAs", "\tShift+Ctrl+S")
menu.AppendSeparator()
Append("Options", "\tCtrl+P")
menu.AppendSeparator()
Append("Restart", "\tShift+Ctrl+~")
Append("RestartAsAdmin")
menu.AppendSeparator()
Append("Exit")
# edit menu
menu = wx.Menu()
menuBar.Append(menu, text.EditMenu)
Append("Undo", "\tCtrl+Z")
Append("Redo", "\tCtrl+Y")
menu.AppendSeparator()
Append("Cut", "\tCtrl+X")
Append("Copy", "\tCtrl+C")
Append("Python", "\tShift+Ctrl+C")
Append("Paste", "\tCtrl+V")
# notice that we add a ascii zero byte at the end of the hotkey.
# this way we prevent the normal accelerator to happen. We will later
# catch the key ourself.
oldLogging = wx.Log.EnableLogging(False) # suppress warning
Append("Delete", "\tDel\x00")
wx.Log.EnableLogging(oldLogging)
menu.AppendSeparator()
Append("Find", "\tCtrl+F")
Append("FindNext", "\tF3")
# view menu
menu = wx.Menu()
menuBar.Append(menu, text.ViewMenu)
Append("HideShowToolbar", kind=wx.ITEM_CHECK).Check(Config.showToolbar)
menu.AppendSeparator()
Append("Expand", image=GetInternalBitmap("expand"))
Append("Collapse", image=GetInternalBitmap("collapse"))
Append("ExpandChilds", image=GetInternalBitmap("expand_children"))
Append("CollapseChilds", image=GetInternalBitmap("collapse_children"))
Append("ExpandAll", image=GetInternalBitmap("expand_all"))
Append("CollapseAll", image=GetInternalBitmap("collapse_all"))
menu.AppendSeparator()
item = Append("ExpandOnEvents", kind=wx.ITEM_CHECK)
item.Check(Config.expandOnEvents)
menu.AppendSeparator()
Append("LogMacros", kind=wx.ITEM_CHECK).Check(eg.config.logMacros)
Append("LogActions", kind=wx.ITEM_CHECK).Check(eg.config.logActions)
Append("LogDebug", kind=wx.ITEM_CHECK).Check(eg.config.logDebug)
menu.AppendSeparator()
Append("IndentLog", kind=wx.ITEM_CHECK).Check(Config.indentLog)
Append("LogDate", kind=wx.ITEM_CHECK).Check(Config.logDate)
Append("LogTime", kind=wx.ITEM_CHECK).Check(Config.logTime)
menu.AppendSeparator()
Append("ClearLog", "\tCtrl+L")
# configuration menu
menu = wx.Menu()
menuBar.Append(menu, text.ConfigurationMenu)
Append("AddPlugin", "\tShift+Ctrl+P", image=ADD_PLUGIN_ICON)
Append("AddFolder", "\tShift+Ctrl+N", image=ADD_FOLDER_ICON)
Append("AddMacro", "\tShift+Ctrl+M", image=ADD_MACRO_ICON)
Append("AddEvent", "\tShift+Ctrl+E", image=ADD_EVENT_ICON)
Append("AddAction", "\tShift+Ctrl+A", image=ADD_ACTION_ICON)
menu.AppendSeparator()
Append("Configure", "\tReturn")
Append("Rename", "\tF2")
Append("Execute", "\tF5")
menu.AppendSeparator()
Append("Disabled", "\tCtrl+D", kind=wx.ITEM_CHECK)
# help menu
menu = wx.Menu()
menuBar.Append(menu, text.HelpMenu)
Append("HelpContents", "\tF1")
menu.AppendSeparator()
Append("WebHomepage")
Append("WebForum")
Append("WebWiki")
menu.AppendSeparator()
Append("CheckUpdate")
menu.AppendSeparator()
Append("PythonShell", "\tShift+Ctrl+I")
Append("WIT")
menu.AppendSeparator()
Append("About")
self.SetMenuBar(menuBar)
return menuBar
def CreateToolBar(self):
"""
Creates the toolbar of the frame.
"""
toolBar = wx.ToolBar(self, style=wx.TB_FLAT)
toolBar.SetToolBitmapSize((16, 16))
text = Text.Menu
def Append(ident, image):
toolBar.AddSimpleTool(ID[ident], image, getattr(text, ident))
Append("New", GetInternalBitmap("New"))
Append("Open", GetInternalBitmap("Open"))
Append("Save", GetInternalBitmap("Save"))
toolBar.AddSeparator()
Append("Cut", GetInternalBitmap("Cut"))
Append("Copy", GetInternalBitmap("Copy"))
Append("Python", GetInternalBitmap("Python"))
Append("Paste", GetInternalBitmap("Paste"))
toolBar.AddSeparator()
Append("Undo", GetInternalBitmap("Undo"))
Append("Redo", GetInternalBitmap("Redo"))
toolBar.AddSeparator()
Append("AddPlugin", ADD_PLUGIN_ICON)
Append("AddFolder", ADD_FOLDER_ICON)
Append("AddMacro", ADD_MACRO_ICON)
Append("AddEvent", ADD_EVENT_ICON)
Append("AddAction", ADD_ACTION_ICON)
toolBar.AddSeparator()
Append("Disabled", GetInternalBitmap("Disabled"))
toolBar.AddSeparator()
# the execute button must be added with unique id, because otherwise
# the menu command OnCmdExecute will be used in conjunction to
# our special mouse click handlers
toolBar.AddSimpleTool(
ID_TOOLBAR_EXECUTE,
GetInternalBitmap("Execute"),
getattr(text, "Execute")
)
toolBar.AddSeparator()
Append("Expand", GetInternalBitmap("expand"))
Append("Collapse", GetInternalBitmap("collapse"))
Append("ExpandChilds", GetInternalBitmap("expand_children"))
Append("CollapseChilds", GetInternalBitmap("collapse_children"))
Append("ExpandAll", GetInternalBitmap("expand_all"))
Append("CollapseAll", GetInternalBitmap("collapse_all"))
toolBar.EnableTool(wx.ID_SAVE, self.document.isDirty)
toolBar.Realize()
self.SetToolBar(toolBar)
toolBar.Bind(wx.EVT_LEFT_DOWN, self.OnToolBarLeftDown)
toolBar.Bind(wx.EVT_LEFT_UP, self.OnToolBarLeftUp)
return toolBar
def CreateTreeCtrl(self):
treeCtrl = TreeCtrl(self, document=self.document)
self.auiManager.AddPane(
treeCtrl,
wx.aui.AuiPaneInfo().
Name("tree").
Center().
MinSize((100, 100)).
Floatable(True).
Dockable(True).
MaximizeButton(True).
Caption(" " + Text.Tree.caption).
CloseButton(False)
)
self.auiManager.Update()
treeCtrl.SetFocus()
return treeCtrl
def CreateTreePopupMenu(self):
"""
Creates the pop-up menu for the configuration tree.
"""
menu = wx.Menu()
text = Text.Menu
def Append(ident, kind=wx.ITEM_NORMAL, image=wx.NullBitmap):
item = wx.MenuItem(menu, ID[ident], getattr(text, ident), "", kind)
item.SetBitmap(image)
menu.AppendItem(item)
return item
Append("Expand", image=GetInternalBitmap("expand"))
Append("Collapse", image=GetInternalBitmap("collapse"))
Append("ExpandChilds", image=GetInternalBitmap("expand_children"))
Append("CollapseChilds", image=GetInternalBitmap("collapse_children"))
Append("ExpandAll", image=GetInternalBitmap("expand_all"))
Append("CollapseAll", image=GetInternalBitmap("collapse_all"))
subm = menu
menu = wx.Menu()
Append("Undo")
Append("Redo")
menu.AppendSeparator()
Append("Cut")
Append("Copy")
Append("Python")
Append("Paste")
Append("Delete")
menu.AppendSeparator()
menu.AppendMenu(wx.ID_ANY, text=text.ExpandCollapseMenu, submenu=subm)
menu.AppendSeparator()
Append("AddPlugin", image=ADD_PLUGIN_ICON)
Append("AddFolder", image=ADD_FOLDER_ICON)
Append("AddMacro", image=ADD_MACRO_ICON)
Append("AddEvent", image=ADD_EVENT_ICON)
Append("AddAction", image=ADD_ACTION_ICON)
menu.AppendSeparator()
Append("Configure")
Append("Rename")
Append("Execute")
menu.AppendSeparator()
Append("Disabled", kind=wx.ITEM_CHECK)
return menu
@eg.LogItWithReturn
def Destroy(self):
self.Hide()
eg.log.SetCtrl(None)
Config.perspective = self.auiManager.SavePerspective()
eg.Unbind("DocumentFileChange", self.OnDocumentFileChange)
eg.Unbind("DocumentChange", self.OnDocumentChange)
eg.Unbind("FocusChange", self.OnFocusChange)
eg.Unbind("ClipboardChange", self.OnClipboardChange)
eg.Unbind("DialogCreate", self.OnAddDialog)
eg.Unbind("DialogDestroy", self.OnRemoveDialog)
eg.Unbind("SelectionChange", self.OnSelectionChange)
eg.Unbind("UndoChange", self.OnUndoChange)
self.logCtrl.Destroy()
self.treeCtrl.Destroy()
self.SetStatusBar(None)
self.statusBar.Destroy()
result = wx.Frame.Destroy(self)
self.popupMenu.Destroy()
return result
@eg.LogIt
def DispatchCommand(self, command):
focus = self.FindFocus()
if focus is self.treeCtrl:
getattr(self.document, command[2:])()
elif isinstance(focus, wx.TextCtrl): # Added by Pako
getattr(focus.GetParent().editControl, command)()
else:
getattr(focus, command)()
def DisplayError(self, errorText):
eg.MessageBox(
errorText,
style=wx.ICON_EXCLAMATION | wx.OK,
parent=self
)
def GetEditCmdState(self):
focus = self.lastFocus
if focus == self.treeCtrl.editControl:
return (
focus.CanCut(),
focus.CanCopy(),
False,
focus.CanPaste(),
focus.CanDelete()
)
elif focus == self.logCtrl:
return (False, True, False, False, False)
elif focus == self.treeCtrl:
return self.treeCtrl.GetEditCmdState()
return (False, False, False, False, False)
def GetPanelDirection(self, panel):
info = self.auiManager.SavePaneInfo(panel)
pos = info.find(";dir=") + 5
return info[pos]
def SetWindowStyleFlag(self, *args, **kwargs):
"""
Changes the main frame style depending on the display of the tray icon.
Sets the style flags for the minimize button. It will be grayed out if
the tray icon is shown and there child dialogs open.
If the tray icon is not shown the minimize button will function as
usual.
:param args: unused, kept for compatibility with
wxFrame.SetWindowStyleFlag()
:param kwargs: unused, kept for compatibility with
wxFrame.SetWindowStyleFlag()
:return: None
"""
if eg.config.showTrayIcon:
if len(self.openDialogs):
style = ~(wx.MINIMIZE_BOX | wx.CLOSE_BOX) & self.style
else:
style = self.style
else:
style = self.style
wx.Frame.SetWindowStyleFlag(self, style)
@eg.LogIt
def Iconize(self, flag=True):
if flag and eg.config.showTrayIcon:
self.document.HideFrame()
else:
wx.Frame.Iconize(self, flag)
for dialog in self.openDialogs:
dialog.Iconize(flag)
def OnAddDialog(self, dialog):
if dialog.GetParent() != self:
return
self.openDialogs.append(dialog)
dialog.Bind(wx.EVT_WINDOW_DESTROY, self.OnDialogDestroy)
self.SetWindowStyleFlag()
@eg.LogIt
def OnClipboardChange(self, dummyValue):
if self.lastFocus == self.treeCtrl:
canPaste = self.treeCtrl.GetSelectedNode().CanPaste()
self.toolBar.EnableTool(wx.ID_PASTE, canPaste)
@eg.LogIt
def OnClose(self, dummyEvent):
"""
Handle wx.EVT_CLOSE
"""
if eg.config.hideOnClose:
self.Iconize(True)
elif len(self.openDialogs) == 0:
eg.app.Exit()
else:
self.Iconize(False)
self.Raise()
for dialog in self.openDialogs:
dialog.Iconize(False)
BringHwndToFront(dialog.GetHandle())
dialog.Raise()
dialog.RequestUserAttention()
self.RequestUserAttention()
@eg.LogIt
def OnDialogDestroy(self, event):
dialog = event.GetWindow()
try:
self.openDialogs.remove(dialog)
except ValueError:
pass
self.SetWindowStyleFlag()
def OnDocumentChange(self, isDirty):
wx.CallAfter(self.toolBar.EnableTool, wx.ID_SAVE, bool(isDirty))
wx.CallAfter(self.menuBar.Enable, wx.ID_SAVE, bool(isDirty))
def OnDocumentFileChange(self, filepath):
self.SetTitle(self.document.GetTitle())
def OnFocusChange(self, focus):
if focus == self.lastFocus:
return
if focus == self.treeCtrl.editControl:
# avoid programmatic change of the selected item while editing
self.UpdateViewOptions()
# temporarily disable the "Del" accelerator
#self.SetAcceleratorTable(wx.AcceleratorTable([]))
elif self.lastFocus == self.treeCtrl.editControl:
# restore the "Del" accelerator
#self.SetAcceleratorTable(self.acceleratorTable)
self.UpdateViewOptions()
self.lastFocus = focus
toolBar = self.toolBar
canCut, canCopy, canPython, canPaste = self.GetEditCmdState()[:4]
toolBar.EnableTool(wx.ID_CUT, canCut)
toolBar.EnableTool(wx.ID_COPY, canCopy)
toolBar.EnableTool(ID_PYTHON, canPython)
toolBar.EnableTool(wx.ID_PASTE, canPaste)
@eg.LogIt
def OnIconize(self, event):
"""
Handle wx.EVT_ICONIZE
"""
self.Iconize(event.Iconized())
def OnLogCtrlSize(self, evt):
if self.mainSizeFlag:
wx.CallAfter(self.UpdateRatio)
evt.Skip()
def OnMenuOpen(self, dummyEvent):
"""
Handle wx.EVT_MENU_OPEN
"""
self.SetupEditMenu(self.menuBar)
def OnMove(self, event):
"""
Handle wx.EVT_MOVE
"""
if not self.IsMaximized() and not self.IsIconized():
Config.position = self.GetPositionTuple()
event.Skip()
def OnPaneClose(self, event):
"""
React to a wx.aui.EVT_AUI_PANE_CLOSE event.
Monitors if the toolbar gets closed and updates the check menu
entry accordingly
"""
paneName = event.GetPane().name
if paneName == "toolBar":
Config.showToolbar = False
self.menuBar.Check(ID["HideShowToolbar"], False)
def OnPaneMaximize(self, dummyEvent):
"""
React to a wx.aui.EVT_AUI_PANE_MAXIMIZE event.
"""
Config.perspective2 = self.auiManager.SavePerspective()
def OnPaneRestore(self, dummyEvent):
"""
React to a wx.aui.EVT_AUI_PANE_RESTORE event.
"""
if Config.perspective2 is not None:
self.auiManager.LoadPerspective(Config.perspective2)
def OnRemoveDialog(self, dialog):
try:
self.openDialogs.remove(dialog)
except ValueError:
pass
if len(self.openDialogs) == 0:
self.SetWindowStyleFlag(self.style)
def OnSelectionChange(self, dummySelection):
canCut, canCopy, canPython, canPaste = self.GetEditCmdState()[:4]
self.toolBar.EnableTool(wx.ID_CUT, canCut)
self.toolBar.EnableTool(wx.ID_COPY, canCopy)
self.toolBar.EnableTool(ID_PYTHON, canPython)
self.toolBar.EnableTool(wx.ID_PASTE, canPaste)
def OnSize(self, event):
"""
Handle wx.EVT_SIZE
"""
self.mainSizeFlag = False
wx.CallAfter(self.UpdateSize)
event.Skip()
@eg.LogIt
def OnToolBarLeftDown(self, event):
"""
Handles the wx.EVT_LEFT_DOWN events for the toolbar.
"""
x, y = event.GetPosition()
item = self.toolBar.FindToolForPosition(x, y)
if item and item.GetId() == ID_TOOLBAR_EXECUTE:
node = self.treeCtrl.GetSelectedNode()
if not node.isExecutable:
self.DisplayError(Text.Messages.cantExecute)
else:
self.lastClickedTool = item
self.egEvent = self.document.ExecuteNode(node)
event.Skip()
@eg.LogIt
def OnToolBarLeftUp(self, event):
"""
Handles the wx.EVT_LEFT_UP events for the toolbar.
"""
if self.lastClickedTool:
self.lastClickedTool = None
self.egEvent.SetShouldEnd()
event.Skip()
def OnUndoChange(self, undoState):
hasUndos, hasRedos, undoName, redoName = undoState
undoName = Text.Menu.Undo + undoName
redoName = Text.Menu.Redo + redoName
self.menuBar.Enable(wx.ID_UNDO, hasUndos)
self.menuBar.SetLabel(wx.ID_UNDO, undoName + "\tCtrl+Z")
self.menuBar.Enable(wx.ID_REDO, hasRedos)
self.menuBar.SetLabel(wx.ID_REDO, redoName + "\tCtrl+Y")
self.popupMenu.Enable(wx.ID_UNDO, hasUndos)
self.popupMenu.SetLabel(wx.ID_UNDO, undoName)
self.popupMenu.Enable(wx.ID_REDO, hasRedos)
self.popupMenu.SetLabel(wx.ID_REDO, redoName)
self.toolBar.EnableTool(wx.ID_UNDO, hasUndos)
self.toolBar.SetToolShortHelp(wx.ID_UNDO, undoName)
self.toolBar.EnableTool(wx.ID_REDO, hasRedos)
self.toolBar.SetToolShortHelp(wx.ID_REDO, redoName)
def Raise(self):
BringHwndToFront(self.GetHandle())
wx.Frame.Raise(self)
def SetupEditMenu(self, menu):
canCut, canCopy, canPython, canPaste, canDelete = self.GetEditCmdState()
menu.Enable(wx.ID_CUT, canCut)
menu.Enable(wx.ID_COPY, canCopy)
menu.Enable(ID_PYTHON, canPython)
menu.Enable(wx.ID_PASTE, canPaste)
menu.Enable(wx.ID_DELETE, canDelete)
selection = self.treeCtrl.GetSelectedNode()
menu.Check(ID_DISABLED, selection is not None and not selection.isEnabled)
def UpdateRatio(self):
self.logCtrl.SetColumnWidth(
0,
self.logCtrl.GetSizeTuple()[0] - self.corConst
)
if not eg.config.propResize:
return
panel = self.auiManager.GetPane("logger")
if panel.IsDocked():
if self.ratioLock:
self.ratioLock = False
self.UpdateSize()
#self.UpdateSize(False)
dir = self.GetPanelDirection(panel)
coord = None
if dir in ("2", "4"):
coord = 0
elif dir in ("1", "3"):
coord = 1
if coord is not None:
l_val = self.logCtrl.GetSizeTuple()[coord]
t_val = self.treeCtrl.GetSizeTuple()[coord]
self.ratio = float(t_val) / float(l_val)
Config.ratio = self.ratio
else:
self.ratioLock = True
def UpdateSize(self):
if eg.config.propResize:
panel = self.auiManager.GetPane("logger")
if panel.IsDocked():
s = self.auiManager.SavePerspective()
dir = self.GetPanelDirection(panel)
coord = None
if dir in ("2", "4"):
coord = 0
elif dir in ("1", "3"):
coord = 1
if coord is not None:
l_val = self.logCtrl.GetSizeTuple()[coord]
t_val = self.treeCtrl.GetSizeTuple()[coord]
c_val = self.GetClientSizeTuple()[coord]
k = c_val - l_val - t_val
l_val = int((c_val - k) / (1 + self.ratio))
#t_val = (c_val-k)-l_val
b1 = s.find("|dock_size(%s," % dir) + 1
b2 = s.find("=", b1) + 1
e = s.find("|", b1)
s = "%s%i%s" % (s[:b2], l_val, s[e:])
self.auiManager.LoadPerspective(s, True)
self.logCtrl.SetColumnWidth(
0,
self.logCtrl.GetSizeTuple()[0] - self.corConst
)
self.mainSizeFlag = True
if not self.IsMaximized() and not self.IsIconized():
Config.size = self.GetSizeTuple()
def UpdateViewOptions(self):
expandOnEvents = (
not self.IsIconized() and
Config.expandOnEvents and
(self.treeCtrl and self.treeCtrl.editLabelId is None)
)
self.document.ActionItem.shouldSelectOnExecute = expandOnEvents
self.document.MacroItem.shouldSelectOnExecute = expandOnEvents
#-------------------------------------------------------------------------
#---- Menu Handlers ------------------------------------------------------
#-------------------------------------------------------------------------
#---- File ---------------------------------------------------------------
def OnCmdNew(self):
self.document.New()
def OnCmdOpen(self):
self.document.Open()
def OnCmdSave(self):
self.document.Save()
def OnCmdSaveAs(self):
self.document.SaveAs()
@eg.AsTasklet
def OnCmdOptions(self):
eg.OptionsDialog.GetResult(self)
def OnCmdRestart(self):
eg.app.Restart()
def OnCmdRestartAsAdmin(self):
eg.app.RestartAsAdmin()
def OnCmdExit(self):
eg.app.Exit()
#---- Edit ---------------------------------------------------------------
def OnCmdUndo(self):
self.document.Undo()
def OnCmdRedo(self):
self.document.Redo()
def OnCmdCut(self):
self.DispatchCommand("OnCmdCut")
def OnCmdCopy(self):
self.DispatchCommand("OnCmdCopy")
def OnCmdPython(self):
self.DispatchCommand("OnCmdPython")
def OnCmdPaste(self):
self.DispatchCommand("OnCmdPaste")
def OnCmdDelete(self):
self.DispatchCommand("OnCmdDelete")
def OnCmdFind(self):
if self.findDialog is None:
self.findDialog = eg.FindDialog(self, self.document)
self.findDialog.Show()
def OnCmdFindNext(self):
if (
self.findDialog is None or
not self.findDialog.searchButton.IsEnabled()
):
self.OnCmdFind()
else:
self.findDialog.OnFindButton()
#---- View ---------------------------------------------------------------
def OnCmdHideShowToolbar(self):
Config.showToolbar = not Config.showToolbar
#self.auiManager.GetPane("toolBar").Show(Config.showToolbar)
#self.auiManager.Update()
self.toolBar.Show(Config.showToolbar)
self.Layout()
self.SendSizeEvent()
def OnCmdExpand(self):
self.treeCtrl.Expand(self.treeCtrl.GetSelection())
def OnCmdCollapse(self):
self.treeCtrl.Collapse(self.treeCtrl.GetSelection())
def OnCmdExpandChilds(self):
self.treeCtrl.ExpandAllChildren(self.treeCtrl.GetSelection())
def OnCmdCollapseChilds(self):
self.treeCtrl.CollapseAllChildren(self.treeCtrl.GetSelection())
def OnCmdExpandAll(self):
self.treeCtrl.ExpandAll()
def OnCmdCollapseAll(self):
self.treeCtrl.CollapseAll()
def OnCmdExpandOnEvents(self):
Config.expandOnEvents = not Config.expandOnEvents
self.menuBar.Check(ID["ExpandOnEvents"], Config.expandOnEvents)
self.UpdateViewOptions()
def OnCmdLogMacros(self):
eg.config.logMacros = not eg.config.logMacros
self.menuBar.Check(ID["LogMacros"], eg.config.logMacros)
def OnCmdLogActions(self):
eg.config.logActions = not eg.config.logActions
self.menuBar.Check(ID["LogActions"], eg.config.logActions)
def OnCmdLogDebug(self):
eg.config.logDebug = not eg.config.logDebug
self.menuBar.Check(ID["LogDebug"], eg.config.logDebug)
eg.debugLevel = int(eg.config.logDebug)
def OnCmdLogTime(self):
flag = self.menuBar.IsChecked(ID["LogTime"])
Config.logTime = flag
self.logCtrl.SetTimeLogging(flag)
def OnCmdLogDate(self):
flag = self.menuBar.IsChecked(ID["LogDate"])
Config.logDate = flag
self.logCtrl.SetDateLogging(flag)
def OnCmdIndentLog(self):
shouldIndent = self.menuBar.IsChecked(ID["IndentLog"])
Config.indentLog = shouldIndent
self.logCtrl.SetIndent(shouldIndent)
def OnCmdClearLog(self):
self.logCtrl.OnCmdClearLog()
#---- Configuration ------------------------------------------------------
@eg.AsTasklet
def OnCmdAddPlugin(self):
self.document.CmdAddPlugin()
def OnCmdAddFolder(self):
self.document.CmdAddFolder()
@eg.AsTasklet
def OnCmdAddMacro(self):
self.document.CmdAddMacro()
@eg.AsTasklet
def OnCmdAddEvent(self):
self.document.CmdAddEvent()
@eg.AsTasklet
def OnCmdAddAction(self):
self.document.CmdAddAction()
@eg.AsTasklet
def OnCmdConfigure(self):
self.document.CmdConfigure()
def OnCmdRename(self):
self.document.CmdRename()
def OnCmdExecute(self):
self.document.CmdExecute()
def OnCmdDisabled(self):
self.document.CmdToggleEnable()
#---- Help ---------------------------------------------------------------
def OnCmdHelpContents(self):
HtmlHelp(
GetDesktopWindow(),
join(eg.mainDir, "EventGhost.chm"),
HH_DISPLAY_TOPIC,
0
)
def OnCmdWebHomepage(self):
import webbrowser
webbrowser.open("http://www.eventghost.net/", 2, 1)
def OnCmdWebForum(self):
import webbrowser
webbrowser.open("http://www.eventghost.net/forum/", 2, 1)
def OnCmdWebWiki(self):
import webbrowser
webbrowser.open("http://www.eventghost.net/mediawiki/", 2, 1)
def OnCmdCheckUpdate(self):
eg.CheckUpdate.CheckUpdateManually()
def OnCmdWIT(self):
if eg.wit:
eg.wit.Show(refreshTree=True)
return
from wx.lib.inspection import InspectionTool
eg.wit = InspectionTool()
eg.wit.Show(refreshTree=True)
def OnCmdPythonShell(self):
if eg.pyCrustFrame:
eg.pyCrustFrame.Raise()
return
import wx.py as py
# The FillingTree of the pyCrustFrame has some bug, that will raise
# a UnicodeError if some item has a non-ascii str-representation.
# For example a module that resides in a non-ascii file-system path
# will trigger that error.
# Thus we monkey-path the responsible code here with a bug-fixed
# version.
from wx.py.filling import FillingTree
def display(self):
item = self.item
if not item:
return
if self.IsExpanded(item):
self.addChildren(item)
self.setText('')
obj = self.GetPyData(item)
if wx.Platform == '__WXMSW__':
if obj is None: # Windows bug fix.
return
self.SetItemHasChildren(item, self.objHasChildren(obj))
otype = type(obj)
text = u''
text += self.getFullName(item)
text += '\n\nType: ' + str(otype)
try:
# BUGFIX: Here is the problematic code. We replace str(obj)
# with unicode(obj) and everything seems to be fine.
#value = str(obj)
value = unicode(obj)
except:
value = ''
if otype is types.StringType or otype is types.UnicodeType: # NOQA
value = repr(obj)
text += '\n\nValue: ' + value
if otype not in SIMPLETYPES: # NOQA
try:
text += '\n\nDocstring:\n\n"""' + \
inspect.getdoc(obj).strip() + '"""'
except:
pass
if otype is types.InstanceType: # NOQA
try:
text += '\n\nClass Definition:\n\n' + \
inspect.getsource(obj.__class__)
except:
pass
else:
try:
text += '\n\nSource Code:\n\n' + \
inspect.getsource(obj)
except:
pass
self.setText(text)
FillingTree.display.im_func.func_code = display.func_code
fileName = join(eg.configDir, 'PyCrust')
pyCrustConfig = wx.FileConfig(localFilename=fileName)
pyCrustConfig.SetRecordDefaults(True)
eg.pyCrustFrame = frame = py.crust.CrustFrame(
rootObject=eg.globals.__dict__,
#locals=eg.globals.__dict__,
rootLabel="eg.globals",
config=pyCrustConfig,
dataDir=eg.configDir,
)
tree = frame.crust.filling.tree
tree.Expand(tree.GetRootItem())
@eg.LogIt
def OnPyCrustClose(event):
frame.OnClose(event)
# I don't know if this is a bug of wxPython, but if we don't
# delete the notebook explicitly, the program crashes on exit.
frame.crust.notebook.Destroy()
eg.pyCrustFrame = None
#event.Skip()
frame.Bind(wx.EVT_CLOSE, OnPyCrustClose)
frame.Show()
@eg.AsTasklet
@eg.LogItWithReturn
def OnCmdAbout(self):
eg.AboutDialog.GetResult(self)