Example #1
0
    def __init__(self, parent, app, state=None):
        wx.Frame.__init__(self, parent, wx.ID_ANY, title = StoryFrame.DEFAULT_TITLE, \
                          size = StoryFrame.DEFAULT_SIZE)
        self.app = app
        self.parent = parent
        self.pristine = True  # the user has not added any content to this at all
        self.dirty = False  # the user has not made unsaved changes
        self.storyFormats = {}  # list of available story formats

        # inner state

        if (state):
            self.buildDestination = state['buildDestination']
            self.saveDestination = state['saveDestination']
            self.target = state['target']
            self.storyPanel = StoryPanel(self, app, state=state['storyPanel'])
            self.pristine = False
        else:
            self.buildDestination = ''
            self.saveDestination = ''
            self.target = 'sugarcube'
            self.storyPanel = StoryPanel(self, app)

        # window events

        self.Bind(wx.EVT_CLOSE, self.checkClose)
        self.Bind(wx.EVT_UPDATE_UI, self.updateUI)

        # Timer for the auto build file watcher
        self.autobuildtimer = wx.Timer(self)
        self.Bind(wx.EVT_TIMER, self.autoBuildTick, self.autobuildtimer)

        # File menu

        fileMenu = wx.Menu()

        fileMenu.Append(wx.ID_NEW, '&New Story\tCtrl-Shift-N')
        self.Bind(wx.EVT_MENU, self.app.newStory, id=wx.ID_NEW)

        fileMenu.Append(wx.ID_OPEN, '&Open Story...\tCtrl-O')
        self.Bind(wx.EVT_MENU, self.app.openDialog, id=wx.ID_OPEN)

        recentFilesMenu = wx.Menu()
        self.recentFiles = wx.FileHistory(self.app.RECENT_FILES)
        self.recentFiles.Load(self.app.config)
        self.app.verifyRecentFiles(self)
        self.recentFiles.UseMenu(recentFilesMenu)
        self.recentFiles.AddFilesToThisMenu(recentFilesMenu)
        fileMenu.AppendMenu(wx.ID_ANY, 'Open &Recent', recentFilesMenu)
        self.Bind(wx.EVT_MENU,
                  lambda e: self.app.openRecent(self, 0),
                  id=wx.ID_FILE1)
        self.Bind(wx.EVT_MENU,
                  lambda e: self.app.openRecent(self, 1),
                  id=wx.ID_FILE2)
        self.Bind(wx.EVT_MENU,
                  lambda e: self.app.openRecent(self, 2),
                  id=wx.ID_FILE3)
        self.Bind(wx.EVT_MENU,
                  lambda e: self.app.openRecent(self, 3),
                  id=wx.ID_FILE4)
        self.Bind(wx.EVT_MENU,
                  lambda e: self.app.openRecent(self, 4),
                  id=wx.ID_FILE5)
        self.Bind(wx.EVT_MENU,
                  lambda e: self.app.openRecent(self, 5),
                  id=wx.ID_FILE6)
        self.Bind(wx.EVT_MENU,
                  lambda e: self.app.openRecent(self, 6),
                  id=wx.ID_FILE7)
        self.Bind(wx.EVT_MENU,
                  lambda e: self.app.openRecent(self, 7),
                  id=wx.ID_FILE8)
        self.Bind(wx.EVT_MENU,
                  lambda e: self.app.openRecent(self, 8),
                  id=wx.ID_FILE9)
        self.Bind(wx.EVT_MENU,
                  lambda e: self.app.openRecent(self, 9),
                  id=wx.ID_FILE9 + 1)

        fileMenu.AppendSeparator()

        fileMenu.Append(wx.ID_SAVE, '&Save Story\tCtrl-S')
        self.Bind(wx.EVT_MENU, self.save, id=wx.ID_SAVE)

        fileMenu.Append(wx.ID_SAVEAS, 'S&ave Story As...\tCtrl-Shift-S')
        self.Bind(wx.EVT_MENU, self.saveAs, id=wx.ID_SAVEAS)

        fileMenu.Append(wx.ID_REVERT_TO_SAVED, '&Revert to Saved')
        self.Bind(wx.EVT_MENU, self.revert, id=wx.ID_REVERT_TO_SAVED)

        fileMenu.AppendSeparator()

        fileMenu.Append(StoryFrame.FILE_EXPORT_PROOF,
                        'Export &Proofing Copy...')
        self.Bind(wx.EVT_MENU, self.proof, id=StoryFrame.FILE_EXPORT_PROOF)

        fileMenu.Append(StoryFrame.FILE_IMPORT_SOURCE,
                        '&Import Source Code...')
        self.Bind(wx.EVT_MENU,
                  self.importSource,
                  id=StoryFrame.FILE_IMPORT_SOURCE)

        fileMenu.Append(StoryFrame.FILE_EXPORT_SOURCE,
                        'Export Source &Code...')
        self.Bind(wx.EVT_MENU,
                  self.exportSource,
                  id=StoryFrame.FILE_EXPORT_SOURCE)

        fileMenu.AppendSeparator()

        fileMenu.Append(wx.ID_CLOSE, '&Close Story\tCtrl-W')
        self.Bind(wx.EVT_MENU, self.checkCloseMenu, id=wx.ID_CLOSE)

        fileMenu.Append(wx.ID_EXIT, 'E&xit Twine\tCtrl-Q')
        self.Bind(wx.EVT_MENU, lambda e: self.app.exit(), id=wx.ID_EXIT)

        # Edit menu

        editMenu = wx.Menu()

        editMenu.Append(wx.ID_UNDO, '&Undo\tCtrl-Z')
        self.Bind(wx.EVT_MENU, lambda e: self.storyPanel.undo(), id=wx.ID_UNDO)

        editMenu.Append(wx.ID_REDO, '&Redo\tCtrl-Y')
        self.Bind(wx.EVT_MENU, lambda e: self.storyPanel.redo(), id=wx.ID_REDO)

        editMenu.AppendSeparator()

        editMenu.Append(wx.ID_CUT, 'Cu&t\tCtrl-X')
        self.Bind(wx.EVT_MENU,
                  lambda e: self.storyPanel.cutWidgets(),
                  id=wx.ID_CUT)

        editMenu.Append(wx.ID_COPY, '&Copy\tCtrl-C')
        self.Bind(wx.EVT_MENU,
                  lambda e: self.storyPanel.copyWidgets(),
                  id=wx.ID_COPY)

        editMenu.Append(wx.ID_PASTE, '&Paste\tCtrl-V')
        self.Bind(wx.EVT_MENU,
                  lambda e: self.storyPanel.pasteWidgets(),
                  id=wx.ID_PASTE)

        editMenu.Append(wx.ID_DELETE, '&Delete\tDel')
        self.Bind(wx.EVT_MENU,
                  lambda e: self.storyPanel.removeWidgets(e, saveUndo=True),
                  id=wx.ID_DELETE)

        editMenu.Append(wx.ID_SELECTALL, 'Select &All\tCtrl-A')
        self.Bind(wx.EVT_MENU,
                  lambda e: self.storyPanel.eachWidget(lambda i: i.setSelected(
                      True, exclusive=False)),
                  id=wx.ID_SELECTALL)

        editMenu.AppendSeparator()

        editMenu.Append(wx.ID_FIND, 'Find...\tCtrl-F')
        self.Bind(wx.EVT_MENU, self.showFind, id=wx.ID_FIND)

        editMenu.Append(StoryFrame.EDIT_FIND_NEXT, 'Find Next\tCtrl-G')
        self.Bind(wx.EVT_MENU,
                  lambda e: self.storyPanel.findWidgetRegexp(),
                  id=StoryFrame.EDIT_FIND_NEXT)

        if sys.platform == 'darwin':
            shortcut = 'Ctrl-Shift-H'
        else:
            shortcut = 'Ctrl-H'

        editMenu.Append(wx.ID_REPLACE,
                        'Replace Across Entire Story...\t' + shortcut)
        self.Bind(wx.EVT_MENU, self.showReplace, id=wx.ID_REPLACE)

        editMenu.AppendSeparator()

        editMenu.Append(wx.ID_PREFERENCES, 'Preferences...\tCtrl-,')
        self.Bind(wx.EVT_MENU, self.app.showPrefs, id=wx.ID_PREFERENCES)

        # View menu

        viewMenu = wx.Menu()

        viewMenu.Append(wx.ID_ZOOM_IN, 'Zoom &In\t=')
        self.Bind(wx.EVT_MENU,
                  lambda e: self.storyPanel.zoom('in'),
                  id=wx.ID_ZOOM_IN)

        viewMenu.Append(wx.ID_ZOOM_OUT, 'Zoom &Out\t-')
        self.Bind(wx.EVT_MENU,
                  lambda e: self.storyPanel.zoom('out'),
                  id=wx.ID_ZOOM_OUT)

        viewMenu.Append(wx.ID_ZOOM_FIT, 'Zoom to &Fit\t0')
        self.Bind(wx.EVT_MENU,
                  lambda e: self.storyPanel.zoom('fit'),
                  id=wx.ID_ZOOM_FIT)

        viewMenu.Append(wx.ID_ZOOM_100, 'Zoom &100%\t1')
        self.Bind(wx.EVT_MENU,
                  lambda e: self.storyPanel.zoom(1),
                  id=wx.ID_ZOOM_100)

        viewMenu.AppendSeparator()

        viewMenu.Append(StoryFrame.VIEW_SNAP,
                        'Snap to &Grid',
                        kind=wx.ITEM_CHECK)
        self.Bind(wx.EVT_MENU,
                  lambda e: self.storyPanel.toggleSnapping(),
                  id=StoryFrame.VIEW_SNAP)

        viewMenu.Append(StoryFrame.VIEW_CLEANUP, '&Clean Up Passages')
        self.Bind(wx.EVT_MENU,
                  lambda e: self.storyPanel.cleanup(),
                  id=StoryFrame.VIEW_CLEANUP)

        viewMenu.AppendSeparator()

        viewMenu.Append(StoryFrame.VIEW_TOOLBAR,
                        '&Toolbar',
                        kind=wx.ITEM_CHECK)
        self.Bind(wx.EVT_MENU, self.toggleToolbar, id=StoryFrame.VIEW_TOOLBAR)

        # Story menu

        self.storyMenu = wx.Menu()

        self.storyMenu.Append(StoryFrame.STORY_NEW_PASSAGE,
                              '&New Passage\tCtrl-N')
        self.Bind(wx.EVT_MENU,
                  self.storyPanel.newWidget,
                  id=StoryFrame.STORY_NEW_PASSAGE)

        self.storyMenu.Append(wx.ID_EDIT, '&Edit Passage\tCtrl-E')
        self.Bind(wx.EVT_MENU,
                  lambda e: self.storyPanel.eachSelectedWidget(lambda w: w.
                                                               openEditor(e)),
                  id=wx.ID_EDIT)

        self.storyMenu.Append(StoryFrame.STORY_EDIT_FULLSCREEN,
                              '&Edit Passage Text Fullscreen\tF12')
        self.Bind(wx.EVT_MENU, lambda e: self.storyPanel.eachSelectedWidget(lambda w: w.openEditor(e, fullscreen = True)), \
                  id = StoryFrame.STORY_EDIT_FULLSCREEN)

        self.storyMenu.Append(wx.ID_DELETE, '&Delete Passage')
        self.Bind(wx.EVT_MENU,
                  lambda e: self.storyPanel.removeWidgets(e, saveUndo=True),
                  id=wx.ID_DELETE)

        self.storyMenu.AppendSeparator()

        self.storyMenu.Append(StoryFrame.STORY_BUILD,
                              '&Build Story...\tCtrl-B')
        self.Bind(wx.EVT_MENU, self.build, id=StoryFrame.STORY_BUILD)

        self.storyMenu.Append(StoryFrame.STORY_REBUILD,
                              '&Rebuild Story\tCtrl-R')
        self.Bind(wx.EVT_MENU, self.rebuild, id=StoryFrame.STORY_REBUILD)

        self.storyMenu.Append(StoryFrame.STORY_VIEW_LAST,
                              '&View Last Build\tCtrl-L')
        self.Bind(wx.EVT_MENU, self.viewBuild, id=StoryFrame.STORY_VIEW_LAST)

        self.autobuildmenuitem = self.storyMenu.Append(
            StoryFrame.STORY_AUTO_BUILD, '&Auto Build', kind=wx.ITEM_CHECK)
        self.Bind(wx.EVT_MENU, self.autoBuild, self.autobuildmenuitem)
        self.storyMenu.Check(StoryFrame.STORY_AUTO_BUILD, False)

        self.storyMenu.AppendSeparator()

        self.storyMenu.Append(StoryFrame.STORY_STATS,
                              'Story &Statistics\tCtrl-I')
        self.Bind(wx.EVT_MENU, self.stats, id=StoryFrame.STORY_STATS)

        # Story Format submenu

        storyFormatMenu = wx.Menu()
        storyFormatCounter = StoryFrame.STORY_FORMAT_BASE
        storyFormatPath = app.getPath() + os.sep + 'targets' + os.sep
        for sfdir in os.listdir(storyFormatPath):
            if os.access(storyFormatPath + sfdir + os.sep + 'header.html',
                         os.R_OK):
                if sfdir == 'jonah':
                    sfdirlabel = 'Jonah'
                elif sfdir == 'sugarcane':
                    sfdirlabel = 'Sugarcane'
                elif sfdir == 'sugarcube':
                    sfdirlabel = 'SugarCube'
                elif sfdir == 'tw':
                    sfdirlabel = 'TW'
                elif sfdir == 'tw2':
                    sfdirlabel = 'TW2'
                else:
                    sfdirlabel = sfdir
                storyFormatMenu.Append(storyFormatCounter,
                                       sfdirlabel,
                                       kind=wx.ITEM_CHECK)
                self.Bind(wx.EVT_MENU,
                          lambda e, target=sfdir: self.setTarget(target),
                          id=storyFormatCounter)
                self.storyFormats[storyFormatCounter] = sfdir
                storyFormatCounter = storyFormatCounter + 1

        storyFormatMenu.AppendSeparator()

        storyFormatMenu.Append(StoryFrame.STORY_FORMAT_HELP,
                               '&About Story Formats')
        self.Bind(wx.EVT_MENU,
                  lambda e: self.app.storyFormatHelp(),
                  id=StoryFrame.STORY_FORMAT_HELP)

        self.storyMenu.AppendMenu(wx.ID_ANY, 'Story &Format', storyFormatMenu)

        # Help menu

        helpMenu = wx.Menu()

        helpMenu.Append(StoryFrame.HELP_MANUAL, 'Online &Help')
        self.Bind(wx.EVT_MENU, self.app.openDocs, id=StoryFrame.HELP_MANUAL)

        helpMenu.Append(StoryFrame.HELP_GROUP, '&Discuss Twine Online')
        self.Bind(wx.EVT_MENU, self.app.openGroup, id=StoryFrame.HELP_GROUP)

        helpMenu.Append(StoryFrame.HELP_BUG, 'Report a &Bug')
        self.Bind(wx.EVT_MENU, self.app.reportBug, id=StoryFrame.HELP_BUG)

        helpMenu.AppendSeparator()

        helpMenu.Append(wx.ID_ABOUT, '&About Twine')
        self.Bind(wx.EVT_MENU, self.app.about, id=wx.ID_ABOUT)

        # add menus

        self.menus = wx.MenuBar()
        self.menus.Append(fileMenu, '&File')
        self.menus.Append(editMenu, '&Edit')
        self.menus.Append(viewMenu, '&View')
        self.menus.Append(self.storyMenu, '&Story')
        self.menus.Append(helpMenu, '&Help')
        self.SetMenuBar(self.menus)

        # extra shortcuts

        self.SetAcceleratorTable(wx.AcceleratorTable([ \
                                    (wx.ACCEL_NORMAL, wx.WXK_RETURN, wx.ID_EDIT), \
                                    (wx.ACCEL_CTRL, wx.WXK_RETURN, StoryFrame.STORY_EDIT_FULLSCREEN) \
                                                      ]))

        # add toolbar

        iconPath = self.app.getPath() + os.sep + 'icons' + os.sep

        self.toolbar = self.CreateToolBar(style=wx.TB_FLAT | wx.TB_NODIVIDER)
        self.toolbar.SetToolBitmapSize(
            (StoryFrame.TOOLBAR_ICON_SIZE, StoryFrame.TOOLBAR_ICON_SIZE))

        self.toolbar.AddLabelTool(StoryFrame.STORY_NEW_PASSAGE, 'New Passage', \
                                  wx.Bitmap(iconPath + 'newpassage.png'), \
                                  shortHelp = StoryFrame.NEW_PASSAGE_TOOLTIP)
        self.Bind(wx.EVT_TOOL,
                  lambda e: self.storyPanel.newWidget(),
                  id=StoryFrame.STORY_NEW_PASSAGE)

        self.toolbar.AddSeparator()

        self.toolbar.AddLabelTool(wx.ID_ZOOM_IN, 'Zoom In', \
                                  wx.Bitmap(iconPath + 'zoomin.png'), \
                                  shortHelp = StoryFrame.ZOOM_IN_TOOLTIP)
        self.Bind(wx.EVT_TOOL,
                  lambda e: self.storyPanel.zoom('in'),
                  id=wx.ID_ZOOM_IN)

        self.toolbar.AddLabelTool(wx.ID_ZOOM_OUT, 'Zoom Out', \
                                  wx.Bitmap(iconPath + 'zoomout.png'), \
                                  shortHelp = StoryFrame.ZOOM_OUT_TOOLTIP)
        self.Bind(wx.EVT_TOOL,
                  lambda e: self.storyPanel.zoom('out'),
                  id=wx.ID_ZOOM_OUT)

        self.toolbar.AddLabelTool(wx.ID_ZOOM_FIT, 'Zoom to Fit', \
                                  wx.Bitmap(iconPath + 'zoomfit.png'), \
                                  shortHelp = StoryFrame.ZOOM_FIT_TOOLTIP)
        self.Bind(wx.EVT_TOOL,
                  lambda e: self.storyPanel.zoom('fit'),
                  id=wx.ID_ZOOM_FIT)

        self.toolbar.AddLabelTool(wx.ID_ZOOM_100, 'Zoom to 100%', \
                                  wx.Bitmap(iconPath + 'zoom1.png'), \
                                  shortHelp = StoryFrame.ZOOM_ONE_TOOLTIP)
        self.Bind(wx.EVT_TOOL,
                  lambda e: self.storyPanel.zoom(1.0),
                  id=wx.ID_ZOOM_100)

        self.SetIcon(self.app.icon)

        if app.config.ReadBool('storyFrameToolbar'):
            self.showToolbar = True
            self.toolbar.Realize()
        else:
            self.showToolbar = False
            self.toolbar.Realize()
            self.toolbar.Hide()