fseditframe.py 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. import sys, wx, wx.stc
  2. class FullscreenEditFrame(wx.Frame):
  3. """
  4. This opens a modal fullscreen editor with some text. When the user's done,
  5. this calls the callback function passed to the constructor with the new text.
  6. A lot of the stuff dealing with wx.stc.StyledTextCtrl comes from:
  7. http://www.psychicorigami.com/2009/01/05/a-5k-python-fullscreen-text-editor/
  8. """
  9. def __init__(self, parent, app, frame = None, title = '', initialText = '', callback = lambda i: i):
  10. wx.Frame.__init__(self, parent, wx.ID_ANY, title = title, size = (400, 400))
  11. self.app = app
  12. self.callback = callback
  13. self.frame = frame
  14. self.cursorVisible = True
  15. # menu bar
  16. # this is never seen by the user,
  17. # but lets them hit ctrl-S to save
  18. menuBar = wx.MenuBar()
  19. menu = wx.Menu()
  20. menu.Append(wx.ID_SAVE, '&Save Story\tCtrl-S')
  21. self.Bind(wx.EVT_MENU, lambda e: self.frame.widget.parent.parent.save, id = wx.ID_SAVE)
  22. menuBar.Append(menu, 'Commands')
  23. self.SetMenuBar(menuBar)
  24. # margins
  25. self.marginPanel = wx.Panel(self)
  26. marginSizer = wx.BoxSizer(wx.VERTICAL) # doesn't really matter
  27. self.marginPanel.SetSizer(marginSizer)
  28. # content
  29. self.panel = wx.Panel(self.marginPanel)
  30. sizer = wx.BoxSizer(wx.VERTICAL)
  31. marginSizer.Add(self.panel, 1, flag = wx.EXPAND | wx.LEFT | wx.RIGHT, border = 100)
  32. # controls
  33. self.editCtrl = wx.stc.StyledTextCtrl(self.panel, style = wx.NO_BORDER | wx.TE_NO_VSCROLL | \
  34. wx.TE_MULTILINE | wx.TE_PROCESS_TAB)
  35. self.editCtrl.SetMargins(0, 0)
  36. self.editCtrl.SetMarginWidth(1, 0)
  37. self.editCtrl.SetWrapMode(wx.stc.STC_WRAP_WORD)
  38. self.editCtrl.SetText(initialText)
  39. self.editCtrl.SetUseHorizontalScrollBar(False)
  40. self.editCtrl.SetUseVerticalScrollBar(False)
  41. self.editCtrl.SetCaretPeriod(750)
  42. self.directions = wx.StaticText(self.panel, label = FullscreenEditFrame.DIRECTIONS, style = wx.ALIGN_CENTRE)
  43. labelFont = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT)
  44. labelFont.SetPointSize(FullscreenEditFrame.LABEL_FONT_SIZE)
  45. self.directions.SetFont(labelFont)
  46. self.applyPrefs()
  47. sizer.Add(self.editCtrl, 1, flag = wx.EXPAND | wx.ALL)
  48. sizer.Add(self.directions, 0, flag = wx.TOP | wx.BOTTOM, border = 6)
  49. self.panel.SetSizer(sizer)
  50. # events
  51. self.Bind(wx.EVT_KEY_DOWN, self.keyListener)
  52. self.Bind(wx.EVT_MOTION, self.showCursor)
  53. self.editCtrl.Bind(wx.EVT_KEY_DOWN, self.keyListener)
  54. self.editCtrl.Bind(wx.EVT_MOTION, self.showCursor)
  55. self.editCtrl.SetFocus()
  56. self.editCtrl.SetSelection(-1, -1)
  57. self.SetIcon(self.app.icon)
  58. self.Show(True)
  59. self.ShowFullScreen(True)
  60. def close(self):
  61. self.callback(self.editCtrl.GetText())
  62. if sys.platform == 'darwin': self.ShowFullScreen(False)
  63. self.Close()
  64. def applyPrefs(self):
  65. """
  66. Applies user preferences to this frame.
  67. """
  68. editFont = wx.Font(self.app.config.ReadInt('fsFontSize'), wx.FONTFAMILY_MODERN, \
  69. wx.FONTSTYLE_NORMAL, wx.NORMAL, False, self.app.config.Read('fsFontFace'))
  70. bgColor = self.app.config.Read('fsBgColor')
  71. textColor = self.app.config.Read('fsTextColor')
  72. lineHeight = self.app.config.ReadInt('fslineHeight') / float(100)
  73. self.panel.SetBackgroundColour(bgColor)
  74. self.marginPanel.SetBackgroundColour(bgColor)
  75. self.editCtrl.SetBackgroundColour(bgColor)
  76. self.editCtrl.SetForegroundColour(textColor)
  77. self.editCtrl.StyleSetBackground(wx.stc.STC_STYLE_DEFAULT, bgColor)
  78. self.editCtrl.SetCaretForeground(textColor)
  79. self.editCtrl.SetSelBackground(True, textColor)
  80. self.editCtrl.SetSelForeground(True, bgColor)
  81. defaultStyle = self.editCtrl.GetStyleAt(0)
  82. self.editCtrl.StyleSetForeground(defaultStyle, textColor)
  83. self.editCtrl.StyleSetBackground(defaultStyle, bgColor)
  84. self.editCtrl.StyleSetFont(defaultStyle, editFont)
  85. # we stuff a larger font into a style def we never use
  86. # to force line spacing
  87. editFont.SetPointSize(editFont.GetPointSize() * lineHeight)
  88. self.editCtrl.StyleSetFont(wx.stc.STC_STYLE_BRACELIGHT, editFont)
  89. self.directions.SetForegroundColour(textColor)
  90. def keyListener(self, event):
  91. """
  92. Listens for a key that indicates this frame should close; otherwise lets the event propagate.
  93. This also hides the mouse cursor; the showCursor method, bound to the mouse motion event,
  94. restores it when the user moves it.
  95. """
  96. key = event.GetKeyCode()
  97. if key == wx.WXK_F12:
  98. self.close()
  99. if key == wx.WXK_ESCAPE:
  100. self.close()
  101. self.frame.Destroy()
  102. self.hideCursor()
  103. event.Skip()
  104. def hideCursor(self, event = None):
  105. if self.cursorVisible:
  106. self.SetCursor(wx.StockCursor(wx.CURSOR_BLANK))
  107. self.editCtrl.SetCursor(wx.StockCursor(wx.CURSOR_BLANK))
  108. self.cursorVisible = False
  109. def showCursor(self, event = None):
  110. if not self.cursorVisible:
  111. self.SetCursor(wx.StockCursor(wx.CURSOR_DEFAULT))
  112. self.editCtrl.SetCursor(wx.StockCursor(wx.CURSOR_IBEAM))
  113. self.cursorVisible = True
  114. DIRECTIONS = 'Press Escape to close this passage, F12 to leave fullscreen.'
  115. LABEL_FONT_SIZE = 10