def addMenuCommand(level, identifier, label=None, pos=None, separate=False, group=''): """Insert a new popup menu item for the Menu button. @param level Priority level (0, 1, 2). @param identifier Identifier of the command. @param label Label for the command. If not specified, the same as the identifier. @param pos Position in the menu. None will cause the new item to be appended to the end of the menu. The first item in the menu has position 0. @param separate If True and there are existing items already, add a separator. @param group If specified, items are sorted by this before adding to the menu. The items without a group are inserted first. Groups are separated with separators. """ global menuItems if host.isMac() and level == 0: # On the Mac, the Snowberry menu is integrated into the app menu. # There is no need for a level zero menu. # Put the items temporarily on level 1, where they will be moved # by wxPython to the app menu. level = 1 if label is None: item = (identifier, identifier, separate, group) else: item = (identifier, label, separate, group) if pos is None: menuItems[level].append(item) else: menuItems[level].insert(pos, item)
def __init__(self, parent, wxId, useHtmlFormatting=True, initialText=''): """Constructor. @param parent Parent wxWidget ID. @param wxId ID of the formatted text widget. @param useHtmlFormatting Use a HTML window widget. @param initialText Initial contents. """ self.useHtml = useHtmlFormatting if self.useHtml: base.Widget.__init__(self, MyHtmlWindow(parent, wxId)) else: if host.isMac(): # It appears wxWidgets fancy text is broken on the Mac. useFancy = True #False else: useFancy = True if useFancy: text = initialText.replace('<b>', '<font weight="bold">') text = text.replace('</b>', '</font>') text = text.replace('<i>', '<font style="italic">') text = text.replace('</i>', '</font>') text = text.replace('<tt>', '<font family="fixed">') text = text.replace('</tt>', '</font>') text = '<font family="swiss" size="%s">' \ % st.getSystemString('style-normal-size') + text + '</font>' # fancytext doesn't support non-ascii chars? text = text.replace('ä', 'a') text = text.replace('ö', 'o') text = text.replace('ü', 'u') text = text.replace('å', 'a') text = text.replace('Ä', 'A') text = text.replace('Ö', 'O') text = text.replace('Ü', 'U') text = text.replace('Å', 'A') else: text = initialText.replace('<b>', '') text = text.replace('</b>', '') text = text.replace('<i>', '') text = text.replace('</i>', '') text = text.replace('<tt>', '') text = text.replace('</tt>', '') # Break it up if too long lines detected. brokenText = breakLongLines(text, 70) if useFancy: base.Widget.__init__(self, fancy.StaticFancyText( parent, wxId, uniConv(brokenText))) else: base.Widget.__init__(self, StaticText(parent, wxId, uniConv(brokenText))) self.resizeToBestSize()
def updateLayout(self): """Update the layout of the widgets inside the main window.""" # Also update all UI areas. for key in uiAreas: uiAreas[key].updateLayout() self.mainPanel.updateLayout() #self.Show() if not host.isMac(): self.mainPanel.GetSizer().Fit(self.mainPanel)
def readConfigFile(fileName): """Reads a configuration file from the specified path. The file must be a .conf file that contains either settings or components, or both.""" p = cfparser.FileParser(fileName) # We'll collect all the elements into this array. elements = [] try: # Loop through all the elements in the config file. while True: e = p.get() if e.isKey() and e.getName() == 'required-platform': # This configuration file is specific to a particular # platform. if (e.getValue() == 'windows' and not host.isWindows()) or \ (e.getValue() == 'mac' and not host.isMac()) or \ (e.getValue() == 'unix' and not host.isUnix()): # Look, we ran out early. raise cfparser.OutOfElements # Config files may contain blocks that group similar # settings together. if e.isBlock() and e.getType() == 'group': # Add everything inside the group into the elements. # A group can only contain settings. for sub in e.getContents(): # There can only be blocks in a group. if not sub.isBlock(): continue # Add the 'group' key element to the setting. sub.add(cfparser.KeyElement('group', e.getName())) elements.append(sub) else: elements.append(e) except cfparser.OutOfElements: # Parsing was completed. pass except Exception, exception: # Log an error message. import traceback traceback.print_exc() logger.add(logger.HIGH, 'error-read-config-file', fileName, str(exception))
def _checkSnowberryHome(): """Checks if the Snowberry home directory exists. If it doesn't, it is created and populated with the basic files and directories.""" global homeDir # When this is run for the first time, we'll need to figure out # where the home directory should be. if not homeDir: if isHomeless(): homeLocation = os.getcwd() else: if host.isMac(): # Home on the Mac. homeLocation = os.path.join(os.getenv('HOME'), 'Library/Application Support') else: # First see if a HOME environment variable has been defined. homeLocation = os.getenv('HOME') if not homeLocation: # The failsafe. homeLocation = os.getcwd() # The environment variable was not defined. Let's try # something else. if host.isWindows(): if os.getenv('HOMEPATH'): homeLocation = os.getenv('HOMEDRIVE') + \ os.getenv('HOMEPATH') elif os.getenv('USERPROFILE'): homeLocation = os.getenv('USERPROFILE') elif os.getenv('APPDATA'): homeLocation = os.getenv('APPDATA') homeDir = os.path.join(homeLocation, SNOWBERRY_HOME_DIR) homeDir = os.path.abspath(homeDir) # The home needs to be created if it doesn't exist yet. _createDir(homeDir) # Create the rest of the user directories if they don't exist yet. for p in [ADDONS, MANIFESTS, UNINSTALLED, CONF, LANG, PLUGINS, PROFILES, GRAPHICS, RUNTIME, SERVER_RUNTIME]: _createDir(getUserPath(p))
def isCaseSensitive(): """Returns True if the file system is case sensitive.""" return not host.isWindows() and not host.isMac()
MANIFESTS = 'manifests' UNINSTALLED = 'uninstalled' CONF = 'conf' LANG = 'lang' PLUGINS = 'plugins' PROFILES = 'profiles' GRAPHICS = 'graphics' RUNTIME = 'runtime' SERVER_RUNTIME = 'server-runtime' # List of custom addons directories. addonPaths = [] # On the Mac, change the current directory to Resources inside the bundle. if host.isMac(): import __main__ os.chdir(os.path.dirname(os.path.abspath(__main__.__file__))) # This is the name of the directory under which Snowberry's files will # be stored in the user's home directory. if host.isMac(): SNOWBERRY_HOME_DIR = 'Doomsday Engine' elif host.isWindowsVista(): SNOWBERRY_HOME_DIR = os.path.join('Documents', 'Doomsday Frontend') elif host.isWindows(): SNOWBERRY_HOME_DIR = os.path.join('My Documents', 'Doomsday Frontend') else: SNOWBERRY_HOME_DIR = '.doomsday' # In a homeless setup all the user data goes in the main installation folder.
def createButtonDialog(id, buttons, defaultButton=None, size=None, resizable=True): """Returns the area where the caller may add the contents of the dialog. @param id Identifier of the dialog. @param buttons An array of button commands. @param defaultButton The identifier of the default button. @return Tuple (dialog, user-area) """ dialog = createDialog(id, ui.ALIGN_HORIZONTAL, size, resizable) area = dialog.getArea() area.setMinSize(400, 20) # The Snowberry logo is on the left. #area.setWeight(0) #imageArea = area.createArea(alignment=ui.ALIGN_VERTICAL, border=0, # backgroundColor=wx.Colour(255, 255, 255)) #imageArea.setWeight(1) #imageArea.setExpanding(True) #imageArea.addSpacer() #imageArea.setWeight(0) #imageArea.createImage('snowberry') area.setWeight(1) area.setBorderDirs(ui.BORDER_NOT_BOTTOM) contentArea = area.createArea(alignment=ui.ALIGN_VERTICAL, border=6) contentArea.setWeight(0) # Generous borders. contentArea.setBorder(16) contentArea.setWeight(1) userArea = contentArea.createArea(border=6) # Create the buttons. contentArea.setWeight(0) contentArea.setBorderDirs(ui.BORDER_NOT_TOP) buttonArea = contentArea.createArea(alignment=ui.ALIGN_HORIZONTAL, border=0) # If no explicit spacing is defined, use the default right # alignment. if '' not in buttons: # The implied spacer. buttonArea.addSpacer() buttonArea.setBorder(6, ui.BORDER_LEFT_RIGHT) buttonArea.setWeight(0) if not host.isMac(): # Follow the general guidelines of the platform. if '' in buttons: # Only reverse the portion after the ''. index = buttons.index('') + 1 sub = buttons[index:] sub.reverse() buttons = buttons[:index] + sub else: buttons.reverse() for button in buttons: # If an empty identifier is given, insert a space here. if button == '': buttonArea.setWeight(1) buttonArea.addSpacer() buttonArea.setWeight(0) continue if button == defaultButton: style = wb.Button.STYLE_DEFAULT else: style = wb.Button.STYLE_NORMAL widget = buttonArea.createButton(button, style=style) dialog.identifyWidget(button, widget) # By default, focus the default button. if defaultButton: dialog.focusWidget(defaultButton) return dialog, userArea
def updateMenus(self): """Create the main frame menus based on menuItems array.""" global menuItems self.menuCommandMap = {} # Array of menus. Number to wxMenu. self.menus = {} # Three levels of priority. for level in range(len(menuItems)): if len(menuItems[level]) == 0: # No menu for this. self.menus[level] = None continue self.menus[level] = wx.Menu() self.menuBar.Append(self.menus[level], language.translate("menu-" + str(level))) # Sort the items based on groups, and append separators where necessary. menuItems[level].sort(lambda x, y: cmp(x[3], y[3])) separated = [] previousItem = None for item in menuItems[level]: if previousItem and previousItem[3] != item[3]: separated.append(('-', '', False, item[3])) separated.append(item) previousItem = item # Create the menu items. for itemId, itemCommand, itemSeparate, itemGroup in separated: if itemId == '-': # This is just a separator. self.menus[level].AppendSeparator() continue if itemSeparate and self.menus[level].GetMenuItemCount() > 0: self.menus[level].AppendSeparator() menuItemId = 'menu-' + itemId accel = '' if language.isDefined(menuItemId + '-accel'): accel = "\t" + language.translate(menuItemId + '-accel') # Generate a new ID for the item. wxId = wx.NewId() self.menuCommandMap[wxId] = itemCommand self.menus[level].Append(wxId, uniConv(language.translate(menuItemId) + accel)) wx.EVT_MENU(self, wxId, self.onPopupCommand) if host.isMac(): # Special menu items on Mac. if itemId == 'about': wx.App_SetMacAboutMenuItemId(wxId) if itemId == 'quit': wx.App_SetMacExitMenuItemId(wxId) if itemId == 'show-snowberry-settings': wx.App_SetMacPreferencesMenuItemId(wxId) if host.isMac(): # Special Help menu on Mac. wx.App_SetMacHelpMenuTitleName(language.translate('menu-' + str(MENU_HELP))) self.SetMenuBar(self.menuBar)
def __init__(self, title): """Initialize the main window. @param title Title for the main window. """ from sb.widget.area import Area # Commands for the popup menu. self.menuCommandMap = {} # FIXME: Layout is botched. Way too wide. if host.isMac(): initialSize = (769, 559) elif host.isUnix(): initialSize = (900, 610) else: initialSize = (733, 527) # The configuration may define a window size. if st.isDefined('main-width'): initialSize = (st.getSystemInteger('main-width'), initialSize[1]) if st.isDefined('main-height'): initialSize = (initialSize[0], st.getSystemInteger('main-height')) # The configuration can also specify the window position. if st.isDefined('main-x') and st.isDefined('main-y'): initialPos = (st.getSystemInteger('main-x'), st.getSystemInteger('main-y')) else: initialPos = None wx.Frame.__init__(self, None, -1, title, size=initialSize) #self.SetExtraStyle(wx.FRAME_EX_METAL) #self.Create(None, -1, title, size=initialSize) if initialPos is not None: self.MoveXY(*initialPos) else: self.Center() # Set the icon for the frame. icon = wx.Icon('graphics/snowberry.ico', wx.BITMAP_TYPE_ICO) self.SetIcon(icon) #self.Iconize(True) #self.Hide() SPLITTER_ID = 9501 PROF_SPLITTER_ID = 9502 self.splitter = None self.profSplitter = None # The parentWin is where the profSplitter and the help panel # are inside. parentWin = self if USE_HELP_AREA: # The help area is in a splitter. self.splitter = wx.SplitterWindow(self, SPLITTER_ID, style=wx.SP_3DSASH) self.splitter.SetMinimumPaneSize(10) parentWin = self.splitter if not USE_MINIMAL_PROFILE: self.profSplitter = wx.SplitterWindow(parentWin, PROF_SPLITTER_ID, style=wx.SP_3DSASH)# | #wx.SP_NO_XP_THEME) self.profSplitter.SetMinimumPaneSize(100) # Profile panel. profilePanel = wx.Panel(self.profSplitter, -1, style=wx.NO_BORDER | wx.CLIP_CHILDREN) area = Area(PROFILES, profilePanel, ALIGN_VERTICAL, 10) _newArea(area) # Create panels inside the profile splitter. self.mainPanel = MainPanel(self.profSplitter) else: profilePanel = None self.mainPanel = MainPanel(parentWin) getArea(TABS).setWeight(0) profArea = getArea(TABS).createArea(alignment=ALIGN_HORIZONTAL, border=12) profArea.setId(PROFILES) _newArea(profArea) getArea(TABS).setWeight(1) getArea(TABS).setBorderDirs(BORDER_NOT_TOP) # Create a TabArea into the TABS area. self.mainPanel.tabs = getArea(TABS).createTabArea( 'tab', style=sb.widget.tab.TabArea.STYLE_BASIC) if st.isDefined('main-split-position'): self.splitPos = INITIAL_SASH_POS else: self.splitPos = None self.profSplitPos = INITIAL_PROFILE_SASH_POS # Create the help area. if self.splitter: self.helpPanel = wx.Panel(self.splitter, -1, style = wx.NO_BORDER | wx.CLIP_CHILDREN) self.helpPanel.SetBackgroundColour(wx.WHITE) _newArea( Area(HELP, self.helpPanel, ALIGN_VERTICAL, border=4) ) # Init the splitter. leftSide = self.profSplitter if not leftSide: leftSide = self.mainPanel self.splitter.SplitVertically(leftSide, self.helpPanel, -INITIAL_SASH_POS) else: self.helpPanel = None if self.profSplitter: self.profSplitter.SplitVertically(profilePanel, self.mainPanel, self.profSplitPos) # Listen for changes in the sash position. wx.EVT_SPLITTER_SASH_POS_CHANGED(self, SPLITTER_ID, self.onSplitChange) wx.EVT_SPLITTER_SASH_POS_CHANGED(self, PROF_SPLITTER_ID, self.onProfSplitChange) # The main panel should be globally accessible. global mainPanel mainPanel = self.mainPanel # Intercept the window close event. wx.EVT_CLOSE(self, self.onWindowClose) # Maintain the splitter position. wx.EVT_SIZE(self, self.onWindowSize) # Listen to some commands. events.addCommandListener(self.handleCommand, ['quit']) # Create a menu bar. self.menuBar = wx.MenuBar()
def updateMenus(self): """Create the main frame menus based on menuItems array.""" global menuItems self.menuCommandMap = {} # Array of menus. Number to wxMenu. self.menus = {} # Three levels of priority. for level in range(len(menuItems)): if len(menuItems[level]) == 0: # No menu for this. self.menus[level] = None continue self.menus[level] = wx.Menu() self.menuBar.Append(self.menus[level], language.translate("menu-" + str(level))) # Sort the items based on groups, and append separators where necessary. menuItems[level].sort(lambda x, y: cmp(x[3], y[3])) separated = [] previousItem = None for item in menuItems[level]: if previousItem and previousItem[3] != item[3]: separated.append(('-', '', False, item[3])) separated.append(item) previousItem = item # Create the menu items. for itemId, itemCommand, itemSeparate, itemGroup in separated: if itemId == '-': # This is just a separator. self.menus[level].AppendSeparator() continue if itemSeparate and self.menus[level].GetMenuItemCount() > 0: self.menus[level].AppendSeparator() menuItemId = 'menu-' + itemId accel = '' if language.isDefined(menuItemId + '-accel'): accel = "\t" + language.translate(menuItemId + '-accel') # Generate a new ID for the item. wxId = wx.NewId() self.menuCommandMap[wxId] = itemCommand self.menus[level].Append( wxId, uniConv(language.translate(menuItemId) + accel)) wx.EVT_MENU(self, wxId, self.onPopupCommand) if host.isMac(): # Special menu items on Mac. if itemId == 'about': wx.App_SetMacAboutMenuItemId(wxId) if itemId == 'quit': wx.App_SetMacExitMenuItemId(wxId) if itemId == 'show-snowberry-settings': wx.App_SetMacPreferencesMenuItemId(wxId) if host.isMac(): # Special Help menu on Mac. wx.App_SetMacHelpMenuTitleName( language.translate('menu-' + str(MENU_HELP))) self.SetMenuBar(self.menuBar)
def __init__(self, title): """Initialize the main window. @param title Title for the main window. """ from sb.widget.area import Area # Commands for the popup menu. self.menuCommandMap = {} # FIXME: Layout is botched. Way too wide. if host.isMac(): initialSize = (769, 559) elif host.isUnix(): initialSize = (900, 610) else: initialSize = (733, 527) # The configuration may define a window size. if st.isDefined('main-width'): initialSize = (st.getSystemInteger('main-width'), initialSize[1]) if st.isDefined('main-height'): initialSize = (initialSize[0], st.getSystemInteger('main-height')) # The configuration can also specify the window position. if st.isDefined('main-x') and st.isDefined('main-y'): initialPos = (st.getSystemInteger('main-x'), st.getSystemInteger('main-y')) else: initialPos = None wx.Frame.__init__(self, None, -1, title, size=initialSize) #self.SetExtraStyle(wx.FRAME_EX_METAL) #self.Create(None, -1, title, size=initialSize) if initialPos is not None: self.MoveXY(*initialPos) else: self.Center() # Set the icon for the frame. icon = wx.Icon('graphics/snowberry.ico', wx.BITMAP_TYPE_ICO) self.SetIcon(icon) #self.Iconize(True) #self.Hide() SPLITTER_ID = 9501 PROF_SPLITTER_ID = 9502 self.splitter = None self.profSplitter = None # The parentWin is where the profSplitter and the help panel # are inside. parentWin = self if USE_HELP_AREA: # The help area is in a splitter. self.splitter = wx.SplitterWindow(self, SPLITTER_ID, style=wx.SP_3DSASH) self.splitter.SetMinimumPaneSize(10) parentWin = self.splitter if not USE_MINIMAL_PROFILE: self.profSplitter = wx.SplitterWindow(parentWin, PROF_SPLITTER_ID, style=wx.SP_3DSASH) # | #wx.SP_NO_XP_THEME) self.profSplitter.SetMinimumPaneSize(100) # Profile panel. profilePanel = wx.Panel(self.profSplitter, -1, style=wx.NO_BORDER | wx.CLIP_CHILDREN) area = Area(PROFILES, profilePanel, ALIGN_VERTICAL, 10) _newArea(area) # Create panels inside the profile splitter. self.mainPanel = MainPanel(self.profSplitter) else: profilePanel = None self.mainPanel = MainPanel(parentWin) getArea(TABS).setWeight(0) profArea = getArea(TABS).createArea(alignment=ALIGN_HORIZONTAL, border=12) profArea.setId(PROFILES) _newArea(profArea) getArea(TABS).setWeight(1) getArea(TABS).setBorderDirs(BORDER_NOT_TOP) # Create a TabArea into the TABS area. self.mainPanel.tabs = getArea(TABS).createTabArea( 'tab', style=sb.widget.tab.TabArea.STYLE_BASIC) if st.isDefined('main-split-position'): self.splitPos = INITIAL_SASH_POS else: self.splitPos = None self.profSplitPos = INITIAL_PROFILE_SASH_POS # Create the help area. if self.splitter: self.helpPanel = wx.Panel(self.splitter, -1, style=wx.NO_BORDER | wx.CLIP_CHILDREN) self.helpPanel.SetBackgroundColour(wx.WHITE) _newArea(Area(HELP, self.helpPanel, ALIGN_VERTICAL, border=4)) # Init the splitter. leftSide = self.profSplitter if not leftSide: leftSide = self.mainPanel self.splitter.SplitVertically(leftSide, self.helpPanel, -INITIAL_SASH_POS) else: self.helpPanel = None if self.profSplitter: self.profSplitter.SplitVertically(profilePanel, self.mainPanel, self.profSplitPos) # Listen for changes in the sash position. wx.EVT_SPLITTER_SASH_POS_CHANGED(self, SPLITTER_ID, self.onSplitChange) wx.EVT_SPLITTER_SASH_POS_CHANGED(self, PROF_SPLITTER_ID, self.onProfSplitChange) # The main panel should be globally accessible. global mainPanel mainPanel = self.mainPanel # Intercept the window close event. wx.EVT_CLOSE(self, self.onWindowClose) # Maintain the splitter position. wx.EVT_SIZE(self, self.onWindowSize) # Listen to some commands. events.addCommandListener(self.handleCommand, ['quit']) # Create a menu bar. self.menuBar = wx.MenuBar()