import sys, wx, wx.stc class FullscreenEditFrame(wx.Frame): """ This opens a modal fullscreen editor with some text. When the user's done, this calls the callback function passed to the constructor with the new text. A lot of the stuff dealing with wx.stc.StyledTextCtrl comes from: http://www.psychicorigami.com/2009/01/05/a-5k-python-fullscreen-text-editor/ """ def __init__(self, parent, app, frame = None, title = '', initialText = '', callback = lambda i: i): wx.Frame.__init__(self, parent, wx.ID_ANY, title = title, size = (400, 400)) self.app = app self.callback = callback self.frame = frame self.cursorVisible = True # menu bar # this is never seen by the user, # but lets them hit ctrl-S to save menuBar = wx.MenuBar() menu = wx.Menu() menu.Append(wx.ID_SAVE, '&Save Story\tCtrl-S') self.Bind(wx.EVT_MENU, lambda e: self.frame.widget.parent.parent.save, id = wx.ID_SAVE) menuBar.Append(menu, 'Commands') self.SetMenuBar(menuBar) # margins self.marginPanel = wx.Panel(self) marginSizer = wx.BoxSizer(wx.VERTICAL) # doesn't really matter self.marginPanel.SetSizer(marginSizer) # content self.panel = wx.Panel(self.marginPanel) sizer = wx.BoxSizer(wx.VERTICAL) marginSizer.Add(self.panel, 1, flag = wx.EXPAND | wx.LEFT | wx.RIGHT, border = 100) # controls self.editCtrl = wx.stc.StyledTextCtrl(self.panel, style = wx.NO_BORDER | wx.TE_NO_VSCROLL | \ wx.TE_MULTILINE | wx.TE_PROCESS_TAB) self.editCtrl.SetMargins(0, 0) self.editCtrl.SetMarginWidth(1, 0) self.editCtrl.SetWrapMode(wx.stc.STC_WRAP_WORD) self.editCtrl.SetText(initialText) self.editCtrl.SetUseHorizontalScrollBar(False) self.editCtrl.SetUseVerticalScrollBar(False) self.editCtrl.SetCaretPeriod(750) self.directions = wx.StaticText(self.panel, label = FullscreenEditFrame.DIRECTIONS, style = wx.ALIGN_CENTRE) labelFont = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT) labelFont.SetPointSize(FullscreenEditFrame.LABEL_FONT_SIZE) self.directions.SetFont(labelFont) self.applyPrefs() sizer.Add(self.editCtrl, 1, flag = wx.EXPAND | wx.ALL) sizer.Add(self.directions, 0, flag = wx.TOP | wx.BOTTOM, border = 6) self.panel.SetSizer(sizer) # events self.Bind(wx.EVT_KEY_DOWN, self.keyListener) self.Bind(wx.EVT_MOTION, self.showCursor) self.editCtrl.Bind(wx.EVT_KEY_DOWN, self.keyListener) self.editCtrl.Bind(wx.EVT_MOTION, self.showCursor) self.editCtrl.SetFocus() self.editCtrl.SetSelection(-1, -1) self.SetIcon(self.app.icon) self.Show(True) self.ShowFullScreen(True) def close(self): self.callback(self.editCtrl.GetText()) if sys.platform == 'darwin': self.ShowFullScreen(False) self.Close() def applyPrefs(self): """ Applies user preferences to this frame. """ editFont = wx.Font(self.app.config.ReadInt('fsFontSize'), wx.FONTFAMILY_MODERN, \ wx.FONTSTYLE_NORMAL, wx.NORMAL, False, self.app.config.Read('fsFontFace')) bgColor = self.app.config.Read('fsBgColor') textColor = self.app.config.Read('fsTextColor') lineHeight = self.app.config.ReadInt('fslineHeight') / float(100) self.panel.SetBackgroundColour(bgColor) self.marginPanel.SetBackgroundColour(bgColor) self.editCtrl.SetBackgroundColour(bgColor) self.editCtrl.SetForegroundColour(textColor) self.editCtrl.StyleSetBackground(wx.stc.STC_STYLE_DEFAULT, bgColor) self.editCtrl.SetCaretForeground(textColor) self.editCtrl.SetSelBackground(True, textColor) self.editCtrl.SetSelForeground(True, bgColor) defaultStyle = self.editCtrl.GetStyleAt(0) self.editCtrl.StyleSetForeground(defaultStyle, textColor) self.editCtrl.StyleSetBackground(defaultStyle, bgColor) self.editCtrl.StyleSetFont(defaultStyle, editFont) # we stuff a larger font into a style def we never use # to force line spacing editFont.SetPointSize(editFont.GetPointSize() * lineHeight) self.editCtrl.StyleSetFont(wx.stc.STC_STYLE_BRACELIGHT, editFont) self.directions.SetForegroundColour(textColor) def keyListener(self, event): """ Listens for a key that indicates this frame should close; otherwise lets the event propagate. This also hides the mouse cursor; the showCursor method, bound to the mouse motion event, restores it when the user moves it. """ key = event.GetKeyCode() if key == wx.WXK_F12: self.close() if key == wx.WXK_ESCAPE: self.close() self.frame.Destroy() self.hideCursor() event.Skip() def hideCursor(self, event = None): if self.cursorVisible: self.SetCursor(wx.StockCursor(wx.CURSOR_BLANK)) self.editCtrl.SetCursor(wx.StockCursor(wx.CURSOR_BLANK)) self.cursorVisible = False def showCursor(self, event = None): if not self.cursorVisible: self.SetCursor(wx.StockCursor(wx.CURSOR_DEFAULT)) self.editCtrl.SetCursor(wx.StockCursor(wx.CURSOR_IBEAM)) self.cursorVisible = True DIRECTIONS = 'Press Escape to close this passage, F12 to leave fullscreen.' LABEL_FONT_SIZE = 10