1) Update XmlRoutines.py to strip all whitespace
authormdkinney <mdkinney@6f19259b-4bc3-4df7-8a09-765794883524>
Thu, 4 Jan 2007 01:07:52 +0000 (01:07 +0000)
committermdkinney <mdkinney@6f19259b-4bc3-4df7-8a09-765794883524>
Thu, 4 Jan 2007 01:07:52 +0000 (01:07 +0000)
2) Add function to read section of an XML file
3) Add class to handle workspace relative paths
4) Add utility to manage target.txt
5) Add utility to manage FrameworkDatabase.db

git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@2164 6f19259b-4bc3-4df7-8a09-765794883524

Tools/Python/ContextTool.py [new file with mode: 0644]
Tools/Python/EdkIIWorkspace.py [new file with mode: 0644]
Tools/Python/Fd.py [new file with mode: 0644]
Tools/Python/XmlRoutines.py

diff --git a/Tools/Python/ContextTool.py b/Tools/Python/ContextTool.py
new file mode 100644 (file)
index 0000000..3c95adb
--- /dev/null
@@ -0,0 +1,590 @@
+#!/usr/bin/env python
+
+# The EDK II Build System Context Tool Utility maintains Target.txt settings in an EDK II Workspace.
+
+import wx, os, sys, copy
+from EdkIIWorkspace import *
+
+class ContextToolModel(EdkIIWorkspace):
+  def __init__(self):
+    self.WorkspaceStatus = EdkIIWorkspace.__init__(self)
+    self.Database = {}    
+    self.OriginalDatabase = {}
+        
+  def LoadTargetTxtFile(self):
+    self.ConvertTextFileToDictionary('Tools/Conf/Target.txt', self.TargetTxtDictionary, '#', '=', True, None)
+    if self.TargetTxtDictionary['ACTIVE_PLATFORM'] == []:  
+      self.TargetTxtDictionary['ACTIVE_PLATFORM']            = ['']
+    else:
+      self.TargetTxtDictionary['ACTIVE_PLATFORM']            = [self.TargetTxtDictionary['ACTIVE_PLATFORM'][0]]
+    self.TargetTxtDictionary['TOOL_CHAIN_CONF']              = [self.TargetTxtDictionary['TOOL_CHAIN_CONF'][0]]
+    self.TargetTxtDictionary['MULTIPLE_THREAD']              = [self.TargetTxtDictionary['MULTIPLE_THREAD'][0]]
+    self.TargetTxtDictionary['MAX_CONCURRENT_THREAD_NUMBER'] = [self.TargetTxtDictionary['MAX_CONCURRENT_THREAD_NUMBER'][0]]
+    self.TargetTxtDictionary['TARGET']                       = list(set(self.TargetTxtDictionary['TARGET']))
+    self.TargetTxtDictionary['TOOL_CHAIN_TAG']               = list(set(self.TargetTxtDictionary['TOOL_CHAIN_TAG']))
+    self.TargetTxtDictionary['TARGET_ARCH']                  = list(set(self.TargetTxtDictionary['TARGET_ARCH']))
+    if self.TargetTxtDictionary['TARGET'] == []:
+      self.TargetTxtDictionary['TARGET'] = ['']
+    if self.TargetTxtDictionary['TOOL_CHAIN_TAG'] == []:
+      self.TargetTxtDictionary['TOOL_CHAIN_TAG'] = ['']
+    if self.TargetTxtDictionary['TARGET_ARCH'] == []:
+      self.TargetTxtDictionary['TARGET_ARCH'] = ['']
+    self.TargetTxtDictionary['TARGET'].sort()
+    self.TargetTxtDictionary['TOOL_CHAIN_TAG'].sort()
+    self.TargetTxtDictionary['TARGET_ARCH'].sort()
+    self.OriginalTargetTxtDictionary = copy.deepcopy(self.TargetTxtDictionary)
+    
+  def LoadToolsDefTxtFile(self):
+    self.ToolsDefTxtDictionary = {}
+    if self.TargetTxtDictionary['TOOL_CHAIN_CONF'] != ['']:
+      self.ConvertTextFileToDictionary(self.TargetTxtDictionary['TOOL_CHAIN_CONF'][0], self.ToolsDefTxtDictionary, '#', '=', False, None)
+
+  def LoadFrameworkDatabase(self):
+    self.PlatformDatabase = {}
+    Fd = self.XmlParseFile ('Tools/Conf/FrameworkDatabase.db')
+    PlatformList = XmlList (Fd, '/FrameworkDatabase/PlatformList/Filename')
+    for File in PlatformList:
+      FpdFileName            = XmlElementData(File)
+      FpdPlatformHeader      = self.XmlParseFileSection (FpdFileName, 'PlatformHeader')
+      FpdPlatformDefinitions = self.XmlParseFileSection (FpdFileName,'PlatformDefinitions')
+      PlatformName           = XmlElement (FpdPlatformHeader, '/PlatformHeader/PlatformName')
+      PlatformVersion        = XmlElement (FpdPlatformHeader, '/PlatformHeader/Version')
+      PlatformUiName         = PlatformName + '[' + PlatformVersion + ']'
+      if PlatformUiName not in self.PlatformDatabase:
+        self.PlatformDatabase[PlatformUiName] = {}
+      self.PlatformDatabase[PlatformUiName]['XmlFileName']            = FpdFileName
+      self.PlatformDatabase[PlatformUiName]['SupportedArchitectures'] = set(XmlElement (FpdPlatformDefinitions, '/PlatformSurfaceArea/PlatformDefinitions/SupportedArchitectures').split(' '))
+      self.PlatformDatabase[PlatformUiName]['BuildTargets']           = set(XmlElement (FpdPlatformDefinitions, '/PlatformSurfaceArea/PlatformDefinitions/BuildTargets').split(' '))
+      
+  def ComputeToolsDefTxtDatabase(self):
+    self.ToolsDefTxtDatabase = {
+      'TARGET'                       : [],
+      'TOOL_CHAIN_TAG'               : [],
+      'TARGET_ARCH'                  : []
+    }
+    for Key in dict(self.ToolsDefTxtDictionary):
+      List = Key.split('_')
+      if len(List) != 5:
+        del self.ToolsDefTxtDictionary[Key]
+      elif List[4] == '*':
+        del self.ToolsDefTxtDictionary[Key]
+      else:
+        if List[0] != '*':
+          self.ToolsDefTxtDatabase['TARGET'] += [List[0]] 
+        if List[1] != '*':
+          self.ToolsDefTxtDatabase['TOOL_CHAIN_TAG'] += [List[1]] 
+        if List[2] != '*':
+          self.ToolsDefTxtDatabase['TARGET_ARCH'] += [List[2]] 
+    self.ToolsDefTxtDatabase['TARGET']         = list(set(self.ToolsDefTxtDatabase['TARGET']))
+    self.ToolsDefTxtDatabase['TOOL_CHAIN_TAG'] = list(set(self.ToolsDefTxtDatabase['TOOL_CHAIN_TAG']))
+    self.ToolsDefTxtDatabase['TARGET_ARCH']    = list(set(self.ToolsDefTxtDatabase['TARGET_ARCH']))
+    self.ToolsDefTxtDatabase['TARGET'].sort()
+    self.ToolsDefTxtDatabase['TOOL_CHAIN_TAG'].sort()
+    self.ToolsDefTxtDatabase['TARGET_ARCH'].sort()
+
+  def NewModel(self):
+    self.TargetTxtDictionary = {
+      'ACTIVE_PLATFORM'              : [''],
+      'TOOL_CHAIN_CONF'              : [''],
+      'MULTIPLE_THREAD'              : ['Disable'],
+      'MAX_CONCURRENT_THREAD_NUMBER' : ['2'],
+      'TARGET'                       : [''],
+      'TOOL_CHAIN_TAG'               : [''],
+      'TARGET_ARCH'                  : ['']
+    }
+
+  def RevertModel(self):
+    self.TargetTxtDictionary = copy.deepcopy(self.OriginalTargetTxtDictionary)
+    
+  def RescanModel(self):
+    self.NewModel()
+    self.LoadTargetTxtFile()
+    
+  def RefreshModel(self):
+    self.LoadFrameworkDatabase()
+    self.LoadToolsDefTxtFile()
+    self.ComputeToolsDefTxtDatabase()
+
+    if self.Verbose:
+      print self.TargetTxtDictionary
+      print 'ActivePlatform    = ', self.TargetTxtDictionary['ACTIVE_PLATFORM'][0]
+      print 'ToolChainConf     = ', self.TargetTxtDictionary['TOOL_CHAIN_CONF'][0]
+      print 'MultipleThread    = ', self.TargetTxtDictionary['MULTIPLE_THREAD'][0]
+      print 'MaxThreads        = ', self.TargetTxtDictionary['MAX_CONCURRENT_THREAD_NUMBER'][0]
+      print 'TargetSet         = ', self.TargetTxtDictionary['TARGET']
+      print 'ToolChainSet      = ', self.TargetTxtDictionary['TOOL_CHAIN_TAG']
+      print 'TargetArchSet     = ', self.TargetTxtDictionary['TARGET_ARCH']
+      Platforms = self.PlatformDatabase.keys()
+      print 'Possible Settings:'
+      print '  Platforms       = ', Platforms
+      print '  TargetSet       = ', self.ToolsDefTxtDatabase['TARGET']
+      print '  ToolChainSet    = ', self.ToolsDefTxtDatabase['TOOL_CHAIN_TAG']
+      print '  TargetArchSet   = ', self.ToolsDefTxtDatabase['TARGET_ARCH']
+    return True
+
+  def ModelModified(self):
+    if self.TargetTxtDictionary != self.OriginalTargetTxtDictionary:
+      return True
+    return False
+
+  def SaveModel(self, Filename='Tools/Conf/Target.txt'):
+    if self.Verbose:
+      for Item in self.TargetTxtDictionary:
+        print Item,'=',self.TargetTxtDictionary[Item]
+    self.ConvertDictionaryToTextFile(Filename, self.TargetTxtDictionary, '#', '=', True, None)
+    self.OriginalTargetTxtDictionary = copy.deepcopy(self.TargetTxtDictionary)
+
+  def CloseModel(self):
+    pass
+    
+class Frame(wx.Frame):
+  def __init__(self):
+    wx.Frame.__init__(self,None,-1,'EDK II Build System Context Tool')
+    panel = wx.Panel(self, style=wx.SUNKEN_BORDER | wx.TAB_TRAVERSAL)
+    wx.HelpProvider_Set(wx.SimpleHelpProvider())
+    self.Model = ContextToolModel()
+    if not self.Model.WorkspaceStatus:
+      self.Close()
+      return
+
+    #
+    #  Help text
+    #
+    ActivePlatformHelpText = ( 
+    "Specifies the Platform Name and Platform Version of the platform that will be "
+    "used for build.  If set to [Build Directory] and the current directory contains "
+    "an FPD file, then a plaform build on that FPD file will be performed.  If set "
+    "to [Build Directory] and there is no FPD file in the current directory, then no "
+    "build will be performed."
+    )
+
+    ToolChainConfHelpText = ( 
+    "Specifies the name of the file that declares all the tools and flag settings "
+    "required to complete a build.  This is typically set to Tools/Conf/tools_def.txt."
+    )
+
+    MultipleThreadHelpText = (  
+    "Flag to enable or disable multi-thread builds. If your computer is multi-core "
+    "or contans multiple CPUs, enabling this feature will improve build performance.  "
+    "For multi-thread builds, a log will be written to ${BUILD_DIR}/build.log.  This "
+    "feature is only for platform builds.  Clean, cleanall, and stand-alone module "
+    "builds only use one thread."
+    )
+
+    ThreadsHelpText = (
+    "The number of concurrent threads. The best performance is achieved if this "
+    "value is set to one greater than the number or cores or CPUs in the build system."
+    )
+
+    TargetHelpText = (
+    "Specifies the set of targets to build.  If set to All, then all build targets "
+    "are built.  Otherwise, the subset of enabled build targets are built.  The "
+    "standard build targets are RELEASE and DEBUG, but additional user-defined build "
+    "targets may be declared in the TOOL_CHAIN_CONF file.  The DEBUG builds with "
+    "source level debugging enabled.  RELEASE builds with source level debugging "
+    "disabled and results in smaller firmware images."
+    )
+
+    ToolChainTagHelpText = (
+    "Specifies the set of tool chains to use during a build.  If set to All, then "
+    "all of the supported tools chains are used.  Otherwise, only the subset of "
+    "enabled tool chains are used.  The TOOL_CHAIN_CONF file declares one or more "
+    "tool chains that may be used."
+    )
+
+    TargetArchHelpText = (
+    "Specifies the set of CPU architectures to build.  If set to All, then all the "
+    "CPU architectures supported by the platform FPD file are built.  Otherwise, "
+    "only the subset of enabled CPU architectures are built.  The standard CPU  "
+    "architectures are IA32, X64, IPF, and EBC, but additional CPU architectures "
+    "may be declared in the TOOL_CHAIN_CONF file."
+    )
+    
+    #
+    # Status Bar
+    #
+    self.CreateStatusBar()    
+    
+    #
+    # Build Menus
+    #    
+    MenuBar = wx.MenuBar()
+    
+    FileMenu = wx.Menu()
+    NewMenuItem    = FileMenu.Append(-1, "&New\tCtrl+N",  "New target.txt")
+    SaveMenuItem   = FileMenu.Append(-1, "&Save\tCtrl+S", "Save target.txt")
+    SaveAsMenuItem = FileMenu.Append(-1, "Save &As...",   "Save target.txt as...")
+    RevertMenuItem = FileMenu.Append(-1, "&Revert",       "Revert to the original target.txt")
+    ExitMenuItem   = FileMenu.Append(-1, "E&xit\tAlt+F4", "Exit ContextTool")
+    MenuBar.Append(FileMenu, "&File")
+    self.Bind(wx.EVT_MENU, self.OnSaveClick,   SaveMenuItem)
+    self.Bind(wx.EVT_MENU, self.OnSaveAsClick, SaveAsMenuItem)
+    self.Bind(wx.EVT_MENU, self.OnRevertClick, RevertMenuItem)
+    self.Bind(wx.EVT_MENU, self.OnExitClick,   ExitMenuItem)
+
+    ViewMenu = wx.Menu()
+    RefreshMenuItem = ViewMenu.Append (-1, "&Refresh\tF5", "Rescan target.txt")
+    ShowToolBarMenuItem = ViewMenu.AppendCheckItem (-1, "Show &Toolbar", "Shows or hides the toolbar")
+    ShowToolBarMenuItem.Check(True)
+    MenuBar.Append(ViewMenu, "&View")
+    self.Bind(wx.EVT_MENU, self.OnViewRefreshClick, RefreshMenuItem)
+    self.Bind(wx.EVT_MENU, self.OnShowToolBarClick, ShowToolBarMenuItem)
+
+    HelpMenu = wx.Menu()
+    AboutMenuItem = HelpMenu.Append (-1, "&About...", "About")
+    MenuBar.Append(HelpMenu, "&Help")
+    self.Bind(wx.EVT_MENU, self.OnAboutClick, AboutMenuItem)
+    
+    self.SetMenuBar (MenuBar)
+
+    #
+    # Build Toolbar
+    #    
+    self.ShowToolBar = False
+    self.OnShowToolBarClick(self)
+    
+    #
+    # Active Platform Combo Box
+    #
+    ActivePlatformLabel = wx.StaticText(panel, -1, 'ACTIVE_PLATFORM')
+    ActivePlatformLabel.SetHelpText(ActivePlatformHelpText)
+    self.ActivePlatformText = wx.ComboBox(panel,-1, style=wx.CB_DROPDOWN | wx.CB_SORT | wx.CB_READONLY)
+    self.ActivePlatformText.SetHelpText(ActivePlatformHelpText)
+    self.ActivePlatformText.Bind(wx.EVT_TEXT, self.OnActivePlatformClick)
+    
+    #
+    # Tool Chain Configuration Text Control and Browse Button for a File Dialog Box
+    #
+    ToolChainConfFileLabel = wx.StaticText(panel, -1, 'TOOL_CHAIN_CONF')
+    ToolChainConfFileLabel.SetHelpText(ToolChainConfHelpText)
+    self.ToolChainConfFileText  = wx.TextCtrl(panel, -1, style=wx.TE_PROCESS_ENTER)
+    self.ToolChainConfFileText.Bind(wx.EVT_TEXT_ENTER, self.OnToolChainConfClick)
+    self.ToolChainConfFileText.Bind(wx.EVT_KILL_FOCUS, self.OnToolChainConfClick)
+    self.ToolChainConfFileText.SetHelpText(ToolChainConfHelpText)
+    self.BrowseButton = wx.Button(panel, -1, 'Browse...')
+    self.BrowseButton.Bind(wx.EVT_BUTTON, self.OnBrowseButtonClick)
+
+    #
+    # Multiple Thread enable/disable radio button 
+    #
+    MultipleThreadLabel = wx.StaticText(panel, -1, 'MULTIPLE_THREAD')
+    MultipleThreadLabel.SetHelpText(MultipleThreadHelpText)
+    self.MultipleThreadRadioBox = wx.RadioBox(panel, -1, choices=['Enable','Disable'], style=wx.RA_SPECIFY_COLS)
+    self.MultipleThreadRadioBox.Bind(wx.EVT_RADIOBOX, self.OnMultipleThreadRadioBox)
+    self.MultipleThreadRadioBox.SetHelpText(MultipleThreadHelpText)
+
+    #
+    # Thread count spin control
+    #
+    ThreadsLabel = wx.StaticText(panel, -1, 'THREADS')
+    ThreadsLabel.SetHelpText(ThreadsHelpText)
+    self.ThreadsSpinCtrl = wx.SpinCtrl(panel, -1, size=(50, -1), min=2)
+    self.ThreadsSpinCtrl.Bind(wx.EVT_TEXT, self.OnThreadsSpinCtrl)
+    self.ThreadsSpinCtrl.SetHelpText(ThreadsHelpText)
+
+    #
+    # Target, ToolChain, and Arch Check List Boxes
+    #
+    TargetLabel = wx.StaticText(panel, -1, 'TARGET')
+    TargetLabel.SetHelpText(TargetHelpText)
+    
+    ToolChainTagLabel = wx.StaticText(panel, -1, 'TOOL_CHAIN_TAG')
+    ToolChainTagLabel.SetHelpText(ToolChainTagHelpText)
+    
+    TargetArchLabel = wx.StaticText(panel, -1, 'TARGET_ARCH')
+    TargetArchLabel.SetHelpText(TargetArchHelpText)
+    
+    self.TargetCheckListBox = wx.CheckListBox(panel, -1)
+    self.TargetCheckListBox.Bind(wx.EVT_CHECKLISTBOX, self.OnTargetCheckListClick)
+    self.TargetCheckListBox.Bind(wx.EVT_SET_FOCUS, self.OnTargetSetFocus)
+    self.TargetCheckListBox.Bind(wx.EVT_KILL_FOCUS, self.OnTargetKillFocus)
+    self.TargetCheckListBox.SetHelpText(TargetHelpText)
+
+    self.ToolChainTagCheckListBox = wx.CheckListBox(panel, -1)
+    self.ToolChainTagCheckListBox.Bind(wx.EVT_CHECKLISTBOX, self.OnToolChainTagCheckListClick)
+    self.ToolChainTagCheckListBox.Bind(wx.EVT_SET_FOCUS, self.OnToolChainTagSetFocus)
+    self.ToolChainTagCheckListBox.Bind(wx.EVT_KILL_FOCUS, self.OnToolChainTagKillFocus)
+    self.ToolChainTagCheckListBox.SetHelpText(ToolChainTagHelpText)
+
+    self.TargetArchCheckListBox = wx.CheckListBox(panel, -1)
+    self.TargetArchCheckListBox.Bind(wx.EVT_CHECKLISTBOX, self.OnTargetArchCheckListClick)
+    self.TargetArchCheckListBox.Bind(wx.EVT_SET_FOCUS, self.OnTargetArchSetFocus)
+    self.TargetArchCheckListBox.Bind(wx.EVT_KILL_FOCUS, self.OnTargetArchKillFocus)
+    self.TargetArchCheckListBox.SetHelpText(TargetArchHelpText)
+
+    #
+    # Define layout using sizers
+    #
+    self.mainSizer = wx.BoxSizer(wx.VERTICAL)
+    
+    flexSizer = wx.FlexGridSizer(cols=3, hgap=5, vgap=5)
+    flexSizer.AddGrowableCol(1)
+    flexSizer.Add(ActivePlatformLabel, 0, wx.ALIGN_RIGHT | wx.ALIGN_CENTER_VERTICAL)
+    flexSizer.Add(self.ActivePlatformText, 0, wx.EXPAND)
+    flexSizer.Add((0,0), wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL)
+
+    flexSizer.Add(ToolChainConfFileLabel, 0, wx.ALIGN_RIGHT | wx.ALIGN_CENTER_VERTICAL)
+    flexSizer.Add(self.ToolChainConfFileText, 0, wx.EXPAND)
+    flexSizer.Add(self.BrowseButton, 0, wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL)
+
+    self.mainSizer.Add (flexSizer, 0, wx.EXPAND | wx.ALL, 10)    
+    
+    threadsSizer = wx.FlexGridSizer(cols = 5, hgap=5, vgap=5)
+    threadsSizer.Add(MultipleThreadLabel, 0, wx.ALIGN_RIGHT | wx.ALIGN_CENTER_VERTICAL)
+    threadsSizer.Add(self.MultipleThreadRadioBox, 0, wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL)
+    threadsSizer.Add(ThreadsLabel, 0, wx.ALIGN_RIGHT | wx.ALIGN_CENTER_VERTICAL)
+    threadsSizer.Add(self.ThreadsSpinCtrl, 0, wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL)
+    
+    self.mainSizer.Add (threadsSizer, 0, wx.ALL, 10)
+
+    listSizer = wx.FlexGridSizer(rows = 2, cols = 3, hgap=5, vgap=5)
+    listSizer.AddGrowableRow(1)
+    listSizer.AddGrowableCol(0)
+    listSizer.AddGrowableCol(1)
+    listSizer.AddGrowableCol(2)
+    listSizer.Add(TargetLabel, 0, wx.ALIGN_CENTER)
+    listSizer.Add(ToolChainTagLabel, 0, wx.ALIGN_CENTER)
+    listSizer.Add(TargetArchLabel, 0, wx.ALIGN_CENTER)
+    listSizer.Add(self.TargetCheckListBox, 0, wx.ALL | wx.EXPAND)
+    listSizer.Add(self.ToolChainTagCheckListBox, 0, wx.ALL | wx.EXPAND)
+    listSizer.Add(self.TargetArchCheckListBox, 0, wx.ALL | wx.EXPAND)
+
+    self.mainSizer.Add (listSizer, wx.EXPAND | wx.ALL, wx.EXPAND | wx.ALL, 10)    
+    
+    panel.SetSizer (self.mainSizer)
+   
+    self.Model.RescanModel()
+    self.OnRefreshClick(self)
+
+  def OnActivePlatformClick(self, event):
+    Platform = self.ActivePlatformText.GetValue()
+    if Platform == ' [Build Directory]':
+      self.Model.TargetTxtDictionary['ACTIVE_PLATFORM'][0] = ''
+    else:
+      self.Model.TargetTxtDictionary['ACTIVE_PLATFORM'][0] = self.Model.PlatformDatabase[Platform]['XmlFileName']
+
+  def OnToolChainConfClick(self, event):
+    if self.Model.TargetTxtDictionary['TOOL_CHAIN_CONF'][0] != self.ToolChainConfFileText.GetValue():
+      self.Model.TargetTxtDictionary['TOOL_CHAIN_CONF'][0] = self.ToolChainConfFileText.GetValue()
+      self.OnRefreshClick(self)
+      
+  def OnBrowseButtonClick(self, event):
+    wildcard = "Text Documents (*.txt)|*.txt|" \
+               "All files (*.*)|*.*"
+    dialog = wx.FileDialog (None, 'Choose a Tool Chain Configuration File', self.Model.WorkspaceFile('Tools/Conf'), '', wildcard, wx.OPEN)
+    if dialog.ShowModal() == wx.ID_OK:
+      print dialog.GetPath()
+      ToolChainConfFile = self.Model.WorkspaceRelativePath(dialog.GetPath())
+      self.ToolChainConfFileText.SetValue(ToolChainConfFile)
+      self.Model.TargetTxtDictionary['TOOL_CHAIN_CONF'][0] = self.ToolChainConfFileText.GetValue()
+      self.OnRefreshClick(self)
+    dialog.Destroy()
+
+  def OnMultipleThreadRadioBox (self, event):
+    self.Model.TargetTxtDictionary['MULTIPLE_THREAD'] = [self.MultipleThreadRadioBox.GetStringSelection()]
+    if self.MultipleThreadRadioBox.GetStringSelection() == 'Disable':
+      self.ThreadsSpinCtrl.Disable()
+    else:
+      self.ThreadsSpinCtrl.Enable()
+
+  def OnThreadsSpinCtrl(self, event):
+    self.Model.TargetTxtDictionary['MAX_CONCURRENT_THREAD_NUMBER'] = [str(self.ThreadsSpinCtrl.GetValue())]
+
+  def CheckListFocus(self, CheckListBox, Set):
+    Index = 0
+    while Index < CheckListBox.GetCount():
+      CheckListBox.SetSelection(Index, False)
+      Index += 1
+    if Set:
+      CheckListBox.SetSelection(0, True)
+    
+  def CheckListClick(self, CheckListBox, Name):
+    if CheckListBox.IsChecked(0):
+      Index = 1
+      while Index < CheckListBox.GetCount():
+        CheckListBox.Check(Index, False)
+        Index += 1
+    if CheckListBox.IsChecked(0):
+      self.Model.TargetTxtDictionary[Name] = ['']
+    else:
+      self.Model.TargetTxtDictionary[Name] = []
+      Index = 1
+      while Index < CheckListBox.GetCount():
+        if CheckListBox.IsChecked(Index):
+          self.Model.TargetTxtDictionary[Name] += [CheckListBox.GetString(Index)]
+        Index += 1
+      if self.Model.TargetTxtDictionary[Name] == []:
+        self.Model.TargetTxtDictionary[Name] = ['']
+  
+  def OnTargetCheckListClick(self, event):
+    self.CheckListClick(self.TargetCheckListBox, 'TARGET')
+
+  def OnTargetSetFocus(self, event):
+    self.CheckListFocus(self.TargetCheckListBox, True)
+
+  def OnTargetKillFocus(self, event):
+    self.CheckListFocus(self.TargetCheckListBox, False)
+
+  def OnToolChainTagCheckListClick(self, event):
+    self.CheckListClick(self.ToolChainTagCheckListBox, 'TOOL_CHAIN_TAG')
+
+  def OnToolChainTagSetFocus(self, event):
+    self.CheckListFocus(self.ToolChainTagCheckListBox, True)
+
+  def OnToolChainTagKillFocus(self, event):
+    self.CheckListFocus(self.ToolChainTagCheckListBox, False)
+    
+  def OnTargetArchCheckListClick(self, event):
+    self.CheckListClick(self.TargetArchCheckListBox, 'TARGET_ARCH')
+  
+  def OnTargetArchSetFocus(self, event):
+    self.CheckListFocus(self.TargetArchCheckListBox, True)
+
+  def OnTargetArchKillFocus(self, event):
+    self.CheckListFocus(self.TargetArchCheckListBox, False)
+
+  def OnRevertClick(self, event):
+    self.Model.RevertModel()
+    self.OnRefreshClick(self)
+
+  def RefreshCheckListBox(self, CheckListBox, Name):
+    CheckListBox.Set(['All'] + self.Model.ToolsDefTxtDatabase[Name])
+    Index = 0
+    MaximumString = ''
+    while Index < CheckListBox.GetCount():
+      String = CheckListBox.GetString(Index)
+      if len(String) > len(MaximumString):
+        MaximumString = String
+      if String in self.Model.TargetTxtDictionary[Name]:
+        CheckListBox.Check(Index, True)
+      else:
+        CheckListBox.Check(Index, False)
+      Index += 1
+    if self.Model.TargetTxtDictionary[Name] == ['']:
+      CheckListBox.Check(0, True)
+    Extents = CheckListBox.GetFullTextExtent (MaximumString)
+    CheckListBox.SetMinSize((Extents[0],(CheckListBox.GetCount()+1) * (Extents[1]+Extents[2])))
+    
+  def OnRefreshClick(self, event):
+    self.Model.RefreshModel()
+    Platforms = self.Model.PlatformDatabase.keys()
+    Platforms.sort()
+    self.ActivePlatformText.SetItems([' [Build Directory]'] + Platforms)
+    self.ActivePlatformText.SetValue(' [Build Directory]')
+    for Platform in self.Model.PlatformDatabase:
+      if self.Model.PlatformDatabase[Platform]['XmlFileName'] == self.Model.TargetTxtDictionary['ACTIVE_PLATFORM'][0]:
+        self.ActivePlatformText.SetValue(Platform)
+    if self.ActivePlatformText.GetValue() == ' [Build Directory]':
+      self.Model.TargetTxtDictionary['ACTIVE_PLATFORM'][0] = ''
+    MaximumString = ' [Build Directory]'
+    for String in Platforms:
+      if len(String) > len(MaximumString):
+        MaximumString = String
+    Extents = self.ActivePlatformText.GetFullTextExtent (MaximumString)
+    self.ActivePlatformText.SetMinSize((Extents[0] + 24,-1))
+
+    self.ToolChainConfFileText.SetValue(self.Model.TargetTxtDictionary['TOOL_CHAIN_CONF'][0])
+    Extents = self.ToolChainConfFileText.GetFullTextExtent (self.Model.TargetTxtDictionary['TOOL_CHAIN_CONF'][0])
+    self.ToolChainConfFileText.SetMinSize((Extents[0] + 24,-1))
+        
+    self.MultipleThreadRadioBox.SetStringSelection(self.Model.TargetTxtDictionary['MULTIPLE_THREAD'][0])
+    if self.MultipleThreadRadioBox.GetStringSelection() == 'Disable':
+      self.ThreadsSpinCtrl.Disable()
+    self.ThreadsSpinCtrl.SetValue(int(self.Model.TargetTxtDictionary['MAX_CONCURRENT_THREAD_NUMBER'][0]))
+
+    self.RefreshCheckListBox (self.TargetCheckListBox,       'TARGET')
+    self.RefreshCheckListBox (self.ToolChainTagCheckListBox, 'TOOL_CHAIN_TAG')
+    self.RefreshCheckListBox (self.TargetArchCheckListBox,   'TARGET_ARCH')
+
+    self.mainSizer.SetSizeHints(self)
+    self.mainSizer.Fit(self)
+
+  def OnViewRefreshClick(self, event):
+    self.Model.RescanModel()
+    self.OnRefreshClick(self)
+    
+  def AddTool (self, Handler, ArtId, Label, HelpText):
+    Tool = self.ToolBar.AddSimpleTool(
+      -1, 
+      wx.ArtProvider.GetBitmap(ArtId, wx.ART_TOOLBAR, self.ToolSize), 
+      Label, 
+      HelpText
+      )
+    self.Bind(wx.EVT_MENU, Handler, Tool)
+    
+  def OnShowToolBarClick(self, event):
+    if self.ShowToolBar:
+      self.ShowToolBar = False
+      self.ToolBar.Destroy()
+    else:
+      self.ShowToolBar = True
+      self.ToolBar = self.CreateToolBar()
+      self.ToolSize = (24,24)
+      self.ToolBar.SetToolBitmapSize(self.ToolSize)
+      self.AddTool (self.OnNewClick,    wx.ART_NEW,          "New",        "New target.txt")  
+      self.AddTool (self.OnSaveClick,   wx.ART_FILE_SAVE,    "Save",       "Save target.txt")  
+      self.AddTool (self.OnSaveAsClick, wx.ART_FILE_SAVE_AS, "Save As...", "Save target.txt as...")
+      self.AddTool (self.OnRevertClick, wx.ART_UNDO,         "Revert",     "Revert to original target.txt")
+      self.AddTool (self.OnHelpClick,   wx.ART_HELP,         "Help",       "Context Sensitive Help")
+      self.AddTool (self.OnExitClick,   wx.ART_QUIT,         "Exit",       "Exit Context Tool application")
+      self.ToolBar.Realize()
+  
+  def OnNewClick(self, event):
+    self.Model.NewModel()
+    self.OnRefreshClick(self)
+
+  def OnSaveClick(self, event):
+    self.Model.SaveModel()
+
+  def OnSaveAsClick(self, event):
+    wildcard = "Text Documents (*.txt)|*.txt|" \
+               "All files (*.*)|*.*"
+    dialog = wx.FileDialog (None, 'Save As', self.Model.WorkspaceFile('Tools/Conf'), '', wildcard, wx.SAVE | wx.OVERWRITE_PROMPT)
+    if dialog.ShowModal() == wx.ID_OK:
+      TargetTxtFile = self.Model.WorkspaceRelativePath(dialog.GetPath())
+      if TargetTxtFile != '':
+        self.Model.SaveModel(TargetTxtFile)
+    dialog.Destroy()
+  
+  def OnExitClick(self, event):
+    if self.Model.ModelModified():
+      dialog = wx.MessageDialog(None, 'The contents have changed.\nDo you want to save changes?', 'EDK II Build System Context Tool', style = wx.YES_NO | wx.YES_DEFAULT | wx.CANCEL | wx.ICON_EXCLAMATION)
+      Status = dialog.ShowModal()
+      dialog.Destroy()
+      if Status == wx.ID_YES:
+        self.OnSaveClick (self)
+      elif Status == wx.ID_CANCEL:
+        return
+    self.Model.CloseModel()
+    self.Close()
+
+  def OnHelpClick(self, event):
+    wx.ContextHelp().BeginContextHelp()
+
+  def OnAboutClick(self, event):
+    AboutInfo = wx.AboutDialogInfo()
+    AboutInfo.Name = 'EDK II Build System Context Tool'
+    AboutInfo.Version = '0.3'
+    AboutInfo.Copyright = 'Copyright (c) 2006, Intel Corporation'
+    AboutInfo.Description = """
+      The EDK II Build System Context Tool maintains the target.txt 
+      settings in an EDK II Workspace."""
+    AboutInfo.WebSite = ("http://tianocore.org", "Tiano Core home page")
+    AboutInfo.License = """
+      All rights reserved. This program and the accompanying materials are 
+      licensed and made available under the terms and conditions of the BSD 
+      License which accompanies this distribution.  The full text of the 
+      license may be found at http://opensource.org/licenses/bsd-license.php
+      
+      THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" 
+      BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, 
+      EITHER EXPRESS OR IMPLIED."""
+    if self.Model.Icon != None:
+      AboutInfo.Icon = self.Model.Icon
+    wx.AboutBox(AboutInfo)
+    
+if __name__ == '__main__':
+  app = wx.PySimpleApp()
+  frame = Frame()
+  frame.Show()
+  app.MainLoop()
diff --git a/Tools/Python/EdkIIWorkspace.py b/Tools/Python/EdkIIWorkspace.py
new file mode 100644 (file)
index 0000000..935ffad
--- /dev/null
@@ -0,0 +1,148 @@
+#!/usr/bin/env python
+
+# This is the base class for applications that operate on an EDK II Workspace 
+
+import os, sys
+from XmlRoutines import *
+
+class EdkIIWorkspace:
+  def __init__(self):
+    """Collect WorkspaceDir from the environment, the Verbose command line flag, and detect an icon bitmap file."""
+    if os.environ.get('WORKSPACE') == None:
+      print 'ERROR: WORKSPACE not defined.  Please run EdkSetup from the EDK II install directory.'
+      return False
+
+    self.WorkspaceDir = os.path.realpath(os.environ.get('WORKSPACE'))
+    (Drive, Path) = os.path.splitdrive(self.WorkspaceDir)
+    if Drive == '':
+      (Drive, CwdPath) = os.path.splitdrive(os.getcwd())
+      if Drive != '':
+        self.WorkspaceDir = Drive + Path
+    else:
+      self.WorkspaceDir = Drive.upper() + Path
+
+    try:
+      self.Icon = wx.Icon(self.WorkspaceFile('tools/Python/TianoCoreOrgLogo.gif'),wx.BITMAP_TYPE_GIF)
+    except:
+      self.Icon = None
+      
+    self.Verbose = False
+    for arg in sys.argv:
+      if arg.lower() == '-v':
+        self.Verbose = True      
+
+    return True
+
+  def WorkspaceRelativePath(self, FileName):
+    """Convert a full path filename to a workspace relative filename."""
+    FileName = os.path.realpath(FileName)
+    if FileName.find(self.WorkspaceDir) != 0:
+      return ''
+    return FileName.replace (self.WorkspaceDir, '').strip('\\').strip('/')
+    
+  def WorkspaceFile(self, FileName):
+    """Convert a workspace relative filename to a full path filename."""
+    return os.path.realpath(os.path.join(self.WorkspaceDir,FileName))
+
+  def XmlParseFile (self, FileName):
+    """Parse an XML file into a DOM and return the DOM."""
+    if self.Verbose:
+      print FileName
+    return XmlParseFile (self.WorkspaceFile(FileName))
+    
+  def XmlParseFileSection (self, FileName, SectionTag):
+    """Parse a section of an XML file into a DOM(Document Object Model) and return the DOM."""
+    if self.Verbose:
+      print FileName
+    return XmlParseFileSection (self.WorkspaceFile(FileName), SectionTag)    
+
+  def XmlSaveFile (self, Dom, FileName):
+    """Save a DOM(Document Object Model) into an XML file."""
+    if self.Verbose:
+      print FileName
+    return XmlSaveFile (Dom, self.WorkspaceFile(FileName))
+
+  def ConvertTextFileToDictionary(self, FileName, Dictionary, CommentCharacter, KeySplitCharacter, ValueSplitFlag, ValueSplitCharacter):
+    """Convert a workspace relative text file to a dictionary of (name:value) pairs."""
+    if self.Verbose:
+      print FileName
+    return ConvertTextFileToDictionary(self.WorkspaceFile(FileName), Dictionary, CommentCharacter, KeySplitCharacter, ValueSplitFlag, ValueSplitCharacter)
+  
+  def ConvertDictionaryToTextFile(self, FileName, Dictionary, CommentCharacter, KeySplitCharacter, ValueSplitFlag, ValueSplitCharacter):
+    """Convert a dictionary of (name:value) pairs to a workspace relative text file."""
+    if self.Verbose:
+      print FileName
+    return ConvertDictionaryToTextFile(self.WorkspaceFile(FileName), Dictionary, CommentCharacter, KeySplitCharacter, ValueSplitFlag, ValueSplitCharacter)
+
+#
+# Convert a text file to a dictionary
+#
+def ConvertTextFileToDictionary(FileName, Dictionary, CommentCharacter, KeySplitCharacter, ValueSplitFlag, ValueSplitCharacter):
+  """Convert a text file to a dictionary of (name:value) pairs."""
+  try:
+    f = open(FileName,'r')
+  except:
+    return False
+  Keys = []
+  for Line in f:
+    LineList = Line.split(KeySplitCharacter,1)
+    if len(LineList) >= 2:
+      Key = LineList[0].split()
+      if len(Key) == 1 and Key[0][0] != CommentCharacter and Key[0] not in Keys: 
+        if ValueSplitFlag:
+          Dictionary[Key[0]] = LineList[1].replace('\\','/').split(ValueSplitCharacter)
+        else:
+          Dictionary[Key[0]] = LineList[1].strip().replace('\\','/')
+        Keys += [Key[0]]
+  f.close()
+  return True
+
+def ConvertDictionaryToTextFile(FileName, Dictionary, CommentCharacter, KeySplitCharacter, ValueSplitFlag, ValueSplitCharacter):
+  """Convert a dictionary of (name:value) pairs to a text file."""
+  try:
+    f = open(FileName,'r')
+    Lines = []
+    Lines = f.readlines()
+    f.close()
+  except:
+    Lines = []
+  Keys = Dictionary.keys()
+  MaxLength = 0
+  for Key in Keys:
+    if len(Key) > MaxLength:
+      MaxLength = len(Key)
+  Index = 0
+  for Line in Lines:
+    LineList = Line.split(KeySplitCharacter,1)
+    if len(LineList) >= 2:
+      Key = LineList[0].split()
+      if len(Key) == 1 and Key[0][0] != CommentCharacter and Key[0] in Dictionary:
+        if ValueSplitFlag:
+          Line = '%-*s %c %s\n' % (MaxLength, Key[0], KeySplitCharacter, ' '.join(Dictionary[Key[0]]))
+        else:
+          Line = '%-*s %c %s\n' % (MaxLength, Key[0], KeySplitCharacter, Dictionary[Key[0]])
+        Lines.pop(Index)
+        if Key[0] in Keys:
+          Lines.insert(Index,Line)
+          Keys.remove(Key[0])
+    Index += 1
+  for RemainingKey in Keys:
+    if ValueSplitFlag:
+      Line = '%-*s %c %s\n' % (MaxLength, RemainingKey, KeySplitCharacter,' '.join(Dictionary[RemainingKey])) 
+    else:
+      Line = '%-*s %c %s\n' % (MaxLength, RemainingKey, KeySplitCharacter, Dictionary[RemainingKey])
+    Lines.append(Line)
+  try:
+    f = open(FileName,'w')
+  except:
+    return False
+  f.writelines(Lines)
+  f.close()
+  return True
+    
+# This acts like the main() function for the script, unless it is 'import'ed into another
+# script.
+if __name__ == '__main__':
+
+  # Nothing to do here. Could do some unit tests.
+  pass
diff --git a/Tools/Python/Fd.py b/Tools/Python/Fd.py
new file mode 100644 (file)
index 0000000..f71cc07
--- /dev/null
@@ -0,0 +1,573 @@
+#!/usr/bin/env python
+
+# An EDK II Build System Framework Database Utility maintains FrameworkDatabase.db 
+#  settings in an EDK II Workspace.
+
+import wx, os, sys, copy
+from EdkIIWorkspace import *
+
+class FrameworkDatabaseModel(EdkIIWorkspace):
+  def __init__(self):
+    self.WorkspaceStatus = EdkIIWorkspace.__init__(self)
+    self.Database = {}    
+    self.OriginalDatabase = {}
+        
+  def AddFile (self, DirName, FileName, FileType, Enabled):
+    if DirName != '':
+      FileName = os.path.join(DirName,FileName)
+    if FileType == 'Package':
+      Header  = self.XmlParseFileSection (FileName, 'SpdHeader')
+      Name    = XmlElement (Header, '/SpdHeader/PackageName')
+      Version = XmlElement (Header, '/SpdHeader/Version')
+    elif FileType == 'Platform':
+      Header  = self.XmlParseFileSection (FileName, 'PlatformHeader')
+      Name    = XmlElement (Header, '/PlatformHeader/PlatformName')
+      Version = XmlElement (Header, '/PlatformHeader/Version')
+    else:
+      return
+    FileName = FileName.replace('\\','/')
+    if Name == '' and Version == '':
+      ValidType = 'Invalid'
+      OtherType = 'Valid'
+      UiName    = FileName
+    else:
+      ValidType = 'Valid'
+      OtherType = 'Invalid'
+      UiName    = Name + ' [' + Version + ']'
+    self.Database[FileType][OtherType]['PossibleSettings'].pop(FileName, None)
+    self.Database[FileType][OtherType]['EnabledSettings'].pop(FileName, None)
+    self.Database[FileType][ValidType]['PossibleSettings'][FileName] = UiName
+    if Enabled:
+      self.Database[FileType][ValidType]['EnabledSettings'][FileName] = UiName
+    return
+
+  def NewModel(self):
+    self.Database['Platform'] = {'Valid': {'PossibleSettings':{}, 'EnabledSettings':{}},'Invalid': {'PossibleSettings':{}, 'EnabledSettings':{}}}
+    self.Database['Package']  = {'Valid': {'PossibleSettings':{}, 'EnabledSettings':{}},'Invalid': {'PossibleSettings':{}, 'EnabledSettings':{}}}
+
+  def RevertModel(self):
+    self.Database = copy.deepcopy(self.OriginalDatabase)
+    
+  def RescanModel(self):
+    self.NewModel()
+    self.Fd = self.XmlParseFile ('Tools/Conf/FrameworkDatabase.db')
+    PackageList = XmlList (self.Fd, '/FrameworkDatabase/PackageList/Filename')
+    for File in PackageList:
+      SpdFileName = XmlElementData(File)
+      self.AddFile ('', SpdFileName, 'Package', True)
+    PlatformList = XmlList (self.Fd, '/FrameworkDatabase/PlatformList/Filename')
+    for File in PlatformList:
+      FpdFileName = XmlElementData(File)
+      self.AddFile ('', FpdFileName, 'Platform', True)
+    self.OriginalDatabase = copy.deepcopy(self.Database)
+
+  def RefreshModel(self):
+    Temp = copy.deepcopy(self.Database)
+    for FileType in ['Package','Platform']:
+      for Valid in ['Valid','Invalid']:
+        for Item in Temp[FileType][Valid]['PossibleSettings']:
+          self.AddFile('',Item, FileType, Item in Temp[FileType][Valid]['EnabledSettings'])
+    return True
+
+  def ModelModified(self):
+    if self.Database['Package']['Valid']['EnabledSettings'] != self.OriginalDatabase['Package']['Valid']['EnabledSettings']:
+      return True
+    if self.Database['Package']['Invalid']['EnabledSettings'] != self.OriginalDatabase['Package']['Invalid']['EnabledSettings']:
+      return True
+    if self.Database['Platform']['Valid']['EnabledSettings'] != self.OriginalDatabase['Platform']['Valid']['EnabledSettings']:
+      return True
+    if self.Database['Platform']['Invalid']['EnabledSettings'] != self.OriginalDatabase['Platform']['Invalid']['EnabledSettings']:
+      return True
+    return False
+    
+  def SaveModel(self, Filename='Tools/Conf/FrameworkDatabase.db'):
+    EnabledList =  self.Database['Package']['Valid']['EnabledSettings'].keys() 
+    EnabledList += self.Database['Package']['Invalid']['EnabledSettings'].keys() 
+    PackageList =  XmlList (self.Fd, '/FrameworkDatabase/PackageList/Filename')
+    for File in PackageList:
+      SpdFileName = XmlElementData(File)
+      if SpdFileName in EnabledList:
+        EnabledList.remove(SpdFileName)
+        continue
+      XmlRemoveElement(File)
+      
+    ParentNode = XmlList (self.Fd, '/FrameworkDatabase/PackageList')[0]
+    for SpdFileName in EnabledList:
+      XmlAppendChildElement(ParentNode, u'Filename', SpdFileName)
+
+    EnabledList =  self.Database['Platform']['Valid']['EnabledSettings'].keys() 
+    EnabledList += self.Database['Platform']['Invalid']['EnabledSettings'].keys() 
+    PlatformList = XmlList (self.Fd, '/FrameworkDatabase/PlatformList/Filename')
+    for File in PlatformList:
+      FpdFileName = XmlElementData(File)
+      if FpdFileName in EnabledList:
+        EnabledList.remove(FpdFileName)
+        continue
+      XmlRemoveElement(File)
+      
+    ParentNode = XmlList (self.Fd, '/FrameworkDatabase/PlatformList')[0]
+    for FpdFileName in EnabledList:
+      XmlAppendChildElement(ParentNode, u'Filename', FpdFileName)
+
+    self.XmlSaveFile (self.Fd, Filename)
+    self.OriginalDatabase = copy.deepcopy(self.Database)
+
+  def CloseModel(self):
+    pass
+    
+class Frame(wx.Frame):
+  def __init__(self):
+    wx.Frame.__init__(self,None,-1,'EDK II Build System Framework Database Utility')
+    panel = wx.Panel(self, style=wx.SUNKEN_BORDER | wx.TAB_TRAVERSAL)
+    wx.HelpProvider_Set(wx.SimpleHelpProvider())
+
+    self.Model = FrameworkDatabaseModel()
+
+    #
+    #  Help text
+    #
+    PackagesHelpText = ( 
+    "The set of packages that are active in the current WORKSPACE."
+    )
+
+    PlatformsHelpText = ( 
+    "The set of platforms that are active in the current WORKSPACE."
+    )
+
+    InvalidPackagesHelpText = ( 
+    "The set of packages that are in Framework Database, but not in the current WORKSPACE."
+    )
+
+    InvalidPlatformsHelpText = ( 
+    "The set of platforms that are in Framework Database, but not in the current WORKSPACE."
+    )
+    
+    #
+    # Status Bar
+    #
+    self.StatusBar = self.CreateStatusBar()    
+    
+    #
+    # Build Menus
+    #    
+    MenuBar = wx.MenuBar()
+    
+    FileMenu = wx.Menu()
+    NewMenuItem         = FileMenu.Append(-1, "&New\tCtrl+N",            "New FrameworkDatabase.db")
+    SaveMenuItem        = FileMenu.Append(-1, "&Save\tCtrl+S",           "Save FramdworkDatabase.db")
+    SaveAsMenuItem      = FileMenu.Append(-1, "Save &As...",             "Save FrameworkDatabase.db as...")
+    RevertMenuItem      = FileMenu.Append(-1, "&Revert",                 "Revert to the original FrameworkDatabase.db")
+    ScanMenuItem        = FileMenu.Append(-1, "Scan &WORKSPACE\tCtrl+W", "Scan WORKSPACE for additional packages and platforms")
+    ScanAndSyncMenuItem = FileMenu.Append(-1, "Scan &WORKSPACE and Sync\tCtrl+W", "Scan WORKSPACE for additional packages and platforms and sync FramdworkDatabase.db")
+    ExitMenuItem        = FileMenu.Append(-1, "E&xit\tAlt+F4",           "Exit Framework Database Tool")
+    MenuBar.Append(FileMenu, "&File")
+    self.Bind(wx.EVT_MENU, self.OnSaveClick,        SaveMenuItem)
+    self.Bind(wx.EVT_MENU, self.OnSaveAsClick,      SaveAsMenuItem)
+    self.Bind(wx.EVT_MENU, self.OnRevertClick,      RevertMenuItem)
+    self.Bind(wx.EVT_MENU, self.OnScanClick,        ScanMenuItem)
+    self.Bind(wx.EVT_MENU, self.OnScanAndSyncClick, ScanAndSyncMenuItem)
+    self.Bind(wx.EVT_MENU, self.OnExitClick,        ExitMenuItem)
+
+    EditMenu = wx.Menu()
+    SelectAllPlatformsMenuItem = EditMenu.Append (-1, "Select All Platforms", "Select all platforms")
+    ClearAllPlatformsMenuItem  = EditMenu.Append (-1, "Clear All Platforms",  "Clear all platforms")
+    SelectAllPackagesMenuItem  = EditMenu.Append (-1, "Select All Packages",  "Select all packages")
+    ClearAllPackagesMenuItem   = EditMenu.Append (-1, "Clear All Packages",   "Clear all packages")
+    SelectAllInvalidPlatformsMenuItem = EditMenu.Append (-1, "Select All Invalid Platforms", "Select all invalid platforms")
+    ClearAllInvalidPlatformsMenuItem  = EditMenu.Append (-1, "Clear All Invalid Platforms",  "Clear all invalid platforms")
+    SelectAllInvalidPackagesMenuItem  = EditMenu.Append (-1, "Select All Invalid Packages",  "Select all invalid packages")
+    ClearAllInvalidPackagesMenuItem   = EditMenu.Append (-1, "Clear All Invalid Packages",   "Clear all invalid packages")
+    MenuBar.Append(EditMenu, "&Edit")
+    self.Bind(wx.EVT_MENU, self.OnSelectAllPlatformsClick, SelectAllPlatformsMenuItem)
+    self.Bind(wx.EVT_MENU, self.OnClearAllPlatformsClick,  ClearAllPlatformsMenuItem)
+    self.Bind(wx.EVT_MENU, self.OnSelectAllPackagesClick,  SelectAllPackagesMenuItem)
+    self.Bind(wx.EVT_MENU, self.OnClearAllPackagesClick,   ClearAllPackagesMenuItem)
+    self.Bind(wx.EVT_MENU, self.OnSelectAllInvalidPlatformsClick, SelectAllInvalidPlatformsMenuItem)
+    self.Bind(wx.EVT_MENU, self.OnClearAllInvalidPlatformsClick,  ClearAllInvalidPlatformsMenuItem)
+    self.Bind(wx.EVT_MENU, self.OnSelectAllInvalidPackagesClick,  SelectAllInvalidPackagesMenuItem)
+    self.Bind(wx.EVT_MENU, self.OnClearAllInvalidPackagesClick,   ClearAllInvalidPackagesMenuItem)
+    
+    ViewMenu = wx.Menu()
+    RefreshMenuItem = ViewMenu.Append (-1, "&Refresh\tF5", "Rescan FrameworkDatabase.db")
+    ShowToolBarMenuItem = ViewMenu.AppendCheckItem (-1, "Show &Toolbar", "Shows or hides the toolbar")
+    ShowToolBarMenuItem.Check(True)
+    MenuBar.Append(ViewMenu, "&View")
+    self.Bind(wx.EVT_MENU, self.OnViewRefreshClick, RefreshMenuItem)
+    self.Bind(wx.EVT_MENU, self.OnShowToolBarClick, ShowToolBarMenuItem)
+    
+    HelpMenu = wx.Menu()
+    AboutMenuItem = HelpMenu.Append (-1, "&About...", "About")
+    MenuBar.Append(HelpMenu, "&Help")
+    self.Bind(wx.EVT_MENU, self.OnAboutClick, AboutMenuItem)
+    
+    self.SetMenuBar (MenuBar)
+
+    #
+    # Build Toolbar
+    #    
+    self.ShowToolBar = False
+    self.OnShowToolBarClick(self)
+
+    #
+    # Target, ToolChain, and Arch Check List Boxes
+    #
+    PackagesLabel = wx.StaticText(panel, -1, 'Packages')
+    PackagesLabel.SetFont(wx.Font(12, wx.FONTFAMILY_DEFAULT, wx.NORMAL, wx.FONTWEIGHT_BOLD))
+    PackagesLabel.SetHelpText(PackagesHelpText)
+
+    PlatformsLabel = wx.StaticText(panel, -1, 'Platforms')
+    PlatformsLabel.SetFont(wx.Font(12, wx.FONTFAMILY_DEFAULT, wx.NORMAL, wx.FONTWEIGHT_BOLD))
+    PlatformsLabel.SetHelpText(PlatformsHelpText)
+    
+    #
+    # Buttons
+    #
+    self.SelectAllPackagesButton  = wx.Button(panel, -1, 'Select All')
+    self.ClearAllPackagesButton   = wx.Button(panel, -1, 'Clear All')
+    self.SelectAllPackagesButton.Bind (wx.EVT_BUTTON, self.OnSelectAllPackagesClick)
+    self.ClearAllPackagesButton.Bind  (wx.EVT_BUTTON, self.OnClearAllPackagesClick)
+    
+    self.PackagesCheckListBox = wx.CheckListBox(panel, -1)
+    self.PackagesCheckListBox.Bind(wx.EVT_CHECKLISTBOX, self.OnPackagesCheckListClick)
+    self.PackagesCheckListBox.Bind(wx.EVT_SET_FOCUS, self.OnPackagesSetFocus)
+    self.PackagesCheckListBox.Bind(wx.EVT_KILL_FOCUS, self.OnPackagesKillFocus)
+    self.PackagesCheckListBox.SetHelpText(PackagesHelpText)
+
+    
+    self.SelectAllPlatformsButton = wx.Button(panel, -1, 'Select All')
+    self.ClearAllPlatformsButton  = wx.Button(panel, -1, 'Clear All')
+    self.SelectAllPlatformsButton.Bind(wx.EVT_BUTTON, self.OnSelectAllPlatformsClick)
+    self.ClearAllPlatformsButton.Bind (wx.EVT_BUTTON, self.OnClearAllPlatformsClick)
+
+    self.PlatformsCheckListBox = wx.CheckListBox(panel, -1)
+    self.PlatformsCheckListBox.Bind(wx.EVT_CHECKLISTBOX, self.OnPlatformsCheckListClick)
+    self.PlatformsCheckListBox.Bind(wx.EVT_SET_FOCUS, self.OnPlatformsSetFocus)
+    self.PlatformsCheckListBox.Bind(wx.EVT_KILL_FOCUS, self.OnPlatformsKillFocus)
+    self.PlatformsCheckListBox.SetHelpText(PlatformsHelpText)
+
+    InvalidPackagesLabel = wx.StaticText(panel, -1, 'Invalid Packages')
+    InvalidPackagesLabel.SetFont(wx.Font(12, wx.FONTFAMILY_DEFAULT, wx.NORMAL, wx.FONTWEIGHT_BOLD))
+    InvalidPackagesLabel.SetHelpText(InvalidPackagesHelpText)
+
+    InvalidPlatformsLabel = wx.StaticText(panel, -1, 'Invalid Platforms')
+    InvalidPlatformsLabel.SetFont(wx.Font(12, wx.FONTFAMILY_DEFAULT, wx.NORMAL, wx.FONTWEIGHT_BOLD))
+    InvalidPlatformsLabel.SetHelpText(InvalidPlatformsHelpText)
+    
+    self.SelectAllInvalidPackagesButton  = wx.Button(panel, -1, 'Select All')
+    self.ClearAllInvalidPackagesButton   = wx.Button(panel, -1, 'Clear All')
+    self.SelectAllInvalidPackagesButton.Bind (wx.EVT_BUTTON, self.OnSelectAllInvalidPackagesClick)
+    self.ClearAllInvalidPackagesButton.Bind  (wx.EVT_BUTTON, self.OnClearAllInvalidPackagesClick)
+
+    self.InvalidPackagesCheckListBox = wx.CheckListBox(panel, -1)
+    self.InvalidPackagesCheckListBox.Bind(wx.EVT_CHECKLISTBOX, self.OnInvalidPackagesCheckListClick)
+    self.InvalidPackagesCheckListBox.Bind(wx.EVT_SET_FOCUS, self.OnInvalidPackagesSetFocus)
+    self.InvalidPackagesCheckListBox.Bind(wx.EVT_KILL_FOCUS, self.OnInvalidPackagesKillFocus)
+    self.InvalidPackagesCheckListBox.SetHelpText(PackagesHelpText)
+
+    self.SelectAllInvalidPlatformsButton = wx.Button(panel, -1, 'Select All')
+    self.ClearAllInvalidPlatformsButton  = wx.Button(panel, -1, 'Clear All')
+    self.SelectAllInvalidPlatformsButton.Bind(wx.EVT_BUTTON, self.OnSelectAllInvalidPlatformsClick)
+    self.ClearAllInvalidPlatformsButton.Bind (wx.EVT_BUTTON, self.OnClearAllInvalidPlatformsClick)
+
+    self.InvalidPlatformsCheckListBox = wx.CheckListBox(panel, -1)
+    self.InvalidPlatformsCheckListBox.Bind(wx.EVT_CHECKLISTBOX, self.OnInvalidPlatformsCheckListClick)
+    self.InvalidPlatformsCheckListBox.Bind(wx.EVT_SET_FOCUS, self.OnInvalidPlatformsSetFocus)
+    self.InvalidPlatformsCheckListBox.Bind(wx.EVT_KILL_FOCUS, self.OnInvalidPlatformsKillFocus)
+    self.InvalidPlatformsCheckListBox.SetHelpText(PlatformsHelpText)
+
+    #
+    # Define layout using sizers
+    #
+    self.mainSizer = wx.BoxSizer(wx.VERTICAL)
+
+    listSizer = wx.GridBagSizer(hgap=5, vgap=5)
+    listSizer.Add(PackagesLabel,  pos=(0,0), span=(1,2), flag=wx.ALIGN_CENTER)
+    listSizer.Add(PlatformsLabel, pos=(0,2), span=(1,2), flag=wx.ALIGN_CENTER)
+    listSizer.Add(self.SelectAllPackagesButton, pos=(1,0), flag=wx.ALIGN_CENTER)
+    listSizer.Add(self.ClearAllPackagesButton,  pos=(1,1), flag=wx.ALIGN_CENTER)
+    listSizer.Add(self.SelectAllPlatformsButton, pos=(1,2), flag=wx.ALIGN_CENTER)
+    listSizer.Add(self.ClearAllPlatformsButton,  pos=(1,3), flag=wx.ALIGN_CENTER)
+    listSizer.Add(self.PackagesCheckListBox,  pos=(2,0), span=(1,2), flag=wx.ALL | wx.EXPAND)
+    listSizer.Add(self.PlatformsCheckListBox, pos=(2,2), span=(1,2), flag=wx.ALL | wx.EXPAND)
+
+    listSizer.Add(InvalidPackagesLabel,  pos=(3,0), span=(1,2), flag=wx.ALIGN_CENTER)
+    listSizer.Add(InvalidPlatformsLabel, pos=(3,2), span=(1,2), flag=wx.ALIGN_CENTER)
+    listSizer.Add(self.SelectAllInvalidPackagesButton, pos=(4,0), flag=wx.ALIGN_CENTER)
+    listSizer.Add(self.ClearAllInvalidPackagesButton,  pos=(4,1), flag=wx.ALIGN_CENTER)
+    listSizer.Add(self.SelectAllInvalidPlatformsButton, pos=(4,2), flag=wx.ALIGN_CENTER)
+    listSizer.Add(self.ClearAllInvalidPlatformsButton,  pos=(4,3), flag=wx.ALIGN_CENTER)
+    listSizer.Add(self.InvalidPackagesCheckListBox,  pos=(5,0), span=(1,2), flag=wx.ALL | wx.EXPAND)
+    listSizer.Add(self.InvalidPlatformsCheckListBox, pos=(5,2), span=(1,2), flag=wx.ALL | wx.EXPAND)
+
+    listSizer.AddGrowableRow(2)
+    listSizer.AddGrowableRow(5)
+    listSizer.AddGrowableCol(0)
+    listSizer.AddGrowableCol(1)
+    listSizer.AddGrowableCol(2)
+    listSizer.AddGrowableCol(3)
+    
+    self.mainSizer.Add (listSizer, wx.EXPAND | wx.ALL, wx.EXPAND | wx.ALL, 10)    
+    
+    panel.SetSizer (self.mainSizer)
+
+    self.OnViewRefreshClick(self)
+
+  def CheckListFocus(self, CheckListBox, Set):
+    Index = 0
+    while Index < CheckListBox.GetCount():
+      CheckListBox.SetSelection(Index, False)
+      Index += 1
+    if Set and CheckListBox.GetCount() > 0:
+      CheckListBox.SetSelection(0, True)
+    
+  def CheckListClick(self, CheckListBox, Database):
+    Index = 0
+    Database['EnabledSettings'] = {}
+    while Index < CheckListBox.GetCount():
+      if CheckListBox.IsChecked(Index):
+        for Item in Database['PossibleSettings']:
+          if Database['PossibleSettings'][Item] == CheckListBox.GetString(Index):
+            Database['EnabledSettings'][Item] = Database['PossibleSettings'][Item]
+      Index += 1
+     
+  def OnPackagesCheckListClick(self, event):
+    self.CheckListClick(self.PackagesCheckListBox, self.Model.Database['Package']['Valid'])
+
+  def OnPackagesSetFocus(self, event):
+    self.CheckListFocus(self.PackagesCheckListBox, True)
+
+  def OnPackagesKillFocus(self, event):
+    self.CheckListFocus(self.PackagesCheckListBox, False)
+    
+  def OnPlatformsCheckListClick(self, event):
+    self.CheckListClick(self.PlatformsCheckListBox, self.Model.Database['Platform']['Valid'])
+
+  def OnPlatformsSetFocus(self, event):
+    self.CheckListFocus(self.PlatformsCheckListBox, True)
+
+  def OnPlatformsKillFocus(self, event):
+    self.CheckListFocus(self.PlatformsCheckListBox, False)
+
+  def OnInvalidPackagesCheckListClick(self, event):
+    self.CheckListClick(self.InvalidPackagesCheckListBox, self.Model.Database['Package']['Invalid'])
+
+  def OnInvalidPackagesSetFocus(self, event):
+    self.CheckListFocus(self.InvalidPackagesCheckListBox, True)
+
+  def OnInvalidPackagesKillFocus(self, event):
+    self.CheckListFocus(self.InvalidPackagesCheckListBox, False)
+    
+  def OnInvalidPlatformsCheckListClick(self, event):
+    self.CheckListClick(self.InvalidPlatformsCheckListBox, self.Model.Database['Platform']['Invalid'])
+
+  def OnInvalidPlatformsSetFocus(self, event):
+    self.CheckListFocus(self.InvalidPlatformsCheckListBox, True)
+
+  def OnInvalidPlatformsKillFocus(self, event):
+    self.CheckListFocus(self.InvalidPlatformsCheckListBox, False)
+    
+  def OnRevertClick(self, event):
+    self.Model.RevertModel()
+    self.StatusBar.SetFocus()
+    self.OnRefreshClick(self)
+
+  def RefreshCheckListBox(self, CheckListBox, SelectAllButton, ClearAllButton, Database):
+    NameList = []
+    for Item in Database['PossibleSettings']:
+      NameList.append(Database['PossibleSettings'][Item])
+    NameList.sort()
+    CheckListBox.Set(NameList)
+    Index = 0
+    MaximumString = '.'
+    while Index < CheckListBox.GetCount():
+      String = CheckListBox.GetString(Index)
+      if len(String) > len(MaximumString):
+        MaximumString = String
+      Enabled = False
+      for Item in Database['EnabledSettings']:
+        if String == Database['EnabledSettings'][Item]:
+          Enabled = True
+      if Enabled:
+        CheckListBox.Check(Index, True)
+      else:
+        CheckListBox.Check(Index, False)
+      Index += 1
+    Extents = CheckListBox.GetFullTextExtent (MaximumString)
+    CheckListBox.SetMinSize((Extents[0] + 30,(CheckListBox.GetCount()+2) * (Extents[1]+Extents[2])))
+    if NameList == []:
+      CheckListBox.Disable()
+      SelectAllButton.Disable()
+      ClearAllButton.Disable()
+    else:
+      CheckListBox.Enable()
+      SelectAllButton.Enable()
+      ClearAllButton.Enable()
+    
+  def OnRefreshClick(self, event):
+    self.Model.RefreshModel()
+    self.RefreshCheckListBox (self.PackagesCheckListBox,  self.SelectAllPackagesButton, self.ClearAllPackagesButton, self.Model.Database['Package']['Valid'])
+    self.RefreshCheckListBox (self.PlatformsCheckListBox, self.SelectAllPlatformsButton, self.ClearAllPlatformsButton, self.Model.Database['Platform']['Valid'])
+    self.RefreshCheckListBox (self.InvalidPackagesCheckListBox,  self.SelectAllInvalidPackagesButton, self.ClearAllInvalidPackagesButton, self.Model.Database['Package']['Invalid'])
+    self.RefreshCheckListBox (self.InvalidPlatformsCheckListBox, self.SelectAllInvalidPlatformsButton, self.ClearAllInvalidPlatformsButton, self.Model.Database['Platform']['Invalid'])
+    self.mainSizer.SetSizeHints(self)
+    self.mainSizer.Fit(self)
+    self.Update()
+
+  def OnViewRefreshClick(self, event):
+    self.Model.RescanModel()
+    self.StatusBar.SetFocus()
+    self.OnRefreshClick(self)
+   
+  def AddTool (self, Handler, ArtId, Label, HelpText):
+    Tool = self.ToolBar.AddSimpleTool(
+      -1, 
+      wx.ArtProvider.GetBitmap(ArtId, wx.ART_TOOLBAR, self.ToolSize), 
+      Label, 
+      HelpText
+      )
+    self.Bind(wx.EVT_MENU, Handler, Tool)
+    
+  def OnShowToolBarClick(self, event):
+    if self.ShowToolBar:
+      self.ShowToolBar = False
+      self.ToolBar.Destroy()
+    else:
+      self.ShowToolBar = True
+      self.ToolBar = self.CreateToolBar()
+      self.ToolSize = (24,24)
+      self.ToolBar.SetToolBitmapSize(self.ToolSize)
+      self.AddTool (self.OnNewClick,         wx.ART_NEW,          "New",            "New FrameworkDatabase.db")  
+      self.AddTool (self.OnScanAndSyncClick, wx.ART_HARDDISK,     "Scan WORKSPACE and Sync", "Scan WORKSPACE for new Packages and Platforms and sync FrameworkDatabase.db")  
+      self.AddTool (self.OnSaveClick,        wx.ART_FILE_SAVE,    "Save",           "Save FrameworkDatabase.db")
+      self.AddTool (self.OnSaveAsClick,      wx.ART_FILE_SAVE_AS, "Save As...",     "Save FrameworkDatabase.db as...")
+      self.AddTool (self.OnRevertClick,      wx.ART_UNDO,         "Revert",         "Revert to original FrameworkDatabase.db")
+      self.AddTool (self.OnHelpClick,        wx.ART_HELP,         "Help",           "Context Sensitive Help")
+      self.AddTool (self.OnExitClick,        wx.ART_QUIT,         "Exit",           "Exit EDK II Build System Framework Database Utility")
+      self.ToolBar.Realize()
+  
+  def OnNewClick(self, event):
+    self.Model.NewModel()
+    self.OnRefreshClick(self)
+
+  def ScanDirectory(self, Data, DirName, FilesInDir):
+    WorkspaceDirName = self.Model.WorkspaceRelativePath(DirName)
+    self.StatusBar.SetStatusText('Scanning: ' + WorkspaceDirName)
+    RemoveList = []
+    for File in FilesInDir:
+      if File[0] == '.':
+        RemoveList.insert(0, File)
+    for File in RemoveList:
+      FilesInDir.remove(File)
+    for File in FilesInDir:
+      if os.path.splitext(File)[1].lower() == '.spd':
+        self.Model.AddFile (WorkspaceDirName, File, 'Package', False)
+        self.OnRefreshClick(self)
+      if os.path.splitext(File)[1].lower() == '.fpd':
+        self.Model.AddFile (WorkspaceDirName, File, 'Platform', False)
+        self.OnRefreshClick(self)
+    
+  def OnScanClick(self, event):
+    os.path.walk(self.Model.WorkspaceFile(''), self.ScanDirectory, None)
+    self.StatusBar.SetStatusText('Scanning: Complete')
+    self.StatusBar.SetFocus()
+    self.OnRefreshClick(self)
+
+  def OnScanAndSyncClick(self, event):
+    self.OnSelectAllPackagesClick(self)
+    self.OnSelectAllPlatformsClick(self)
+    self.OnClearAllInvalidPackagesClick(self)
+    self.OnClearAllInvalidPlatformsClick(self)
+    self.OnScanClick(self)
+    self.OnSelectAllPackagesClick(self)
+    self.OnSelectAllPlatformsClick(self)
+    self.OnClearAllInvalidPackagesClick(self)
+    self.OnClearAllInvalidPlatformsClick(self)
+    
+  def OnSelectAllPackagesClick(self, event):
+    self.Model.Database['Package']['Valid']['EnabledSettings'] = self.Model.Database['Package']['Valid']['PossibleSettings']
+    self.OnRefreshClick(self)
+
+  def OnClearAllPackagesClick(self, event):
+    self.Model.Database['Package']['Valid']['EnabledSettings'] = {}
+    self.OnRefreshClick(self)
+
+  def OnSelectAllPlatformsClick(self, event):
+    self.Model.Database['Platform']['Valid']['EnabledSettings'] = self.Model.Database['Platform']['Valid']['PossibleSettings']
+    self.OnRefreshClick(self)
+
+  def OnClearAllPlatformsClick(self, event):
+    self.Model.Database['Platform']['Valid']['EnabledSettings'] = {}
+    self.OnRefreshClick(self)
+
+  def OnSelectAllInvalidPackagesClick(self, event):
+    self.Model.Database['Package']['Invalid']['EnabledSettings'] = self.Model.Database['Package']['Invalid']['PossibleSettings']
+    self.OnRefreshClick(self)
+
+  def OnClearAllInvalidPackagesClick(self, event):
+    self.Model.Database['Package']['Invalid']['EnabledSettings'] = {}
+    self.OnRefreshClick(self)
+
+  def OnSelectAllInvalidPlatformsClick(self, event):
+    self.Model.Database['Platform']['Invalid']['EnabledSettings'] = self.Model.Database['Platform']['Invalid']['PossibleSettings']
+    self.OnRefreshClick(self)
+
+  def OnClearAllInvalidPlatformsClick(self, event):
+    self.Model.Database['Platform']['Invalid']['EnabledSettings'] = {}
+    self.OnRefreshClick(self)
+    
+  def OnSaveClick(self, event):
+    self.Model.SaveModel()
+
+  def OnSaveAsClick(self, event):
+    wildcard = "Text Documents (*.db)|*.db|" \
+               "All files (*.*)|*.*"
+    dialog = wx.FileDialog (None, 'Save As', self.Model.WorkspaceFile('Tools/Conf'), '', wildcard, wx.SAVE | wx.OVERWRITE_PROMPT)
+    if dialog.ShowModal() == wx.ID_OK:
+      FrameworkDatabaseDbFile = self.Model.WorkspaceRelativePath(dialog.GetPath())
+      if FrameworkDatabaseDbFile != '':
+        self.Model.SaveModel(FrameworkDatabaseDbFile)
+    dialog.Destroy()
+  
+  def OnExitClick(self, event):
+    if self.Model.ModelModified():
+      dialog = wx.MessageDialog(None, 'The contents have changed.\nDo you want to save changes?', 'EDK II Build System Framework Databsase Utility', style = wx.YES_NO | wx.YES_DEFAULT | wx.CANCEL | wx.ICON_EXCLAMATION)
+      Status = dialog.ShowModal()
+      dialog.Destroy()
+      if Status == wx.ID_YES:
+        self.OnSaveClick (self)
+      elif Status == wx.ID_CANCEL:
+        return
+    self.Model.CloseModel()
+    self.Close()
+
+  def OnHelpClick(self, event):
+    wx.ContextHelp().BeginContextHelp()
+
+  def OnAboutClick(self, event):
+    AboutInfo = wx.AboutDialogInfo()
+    AboutInfo.Name = 'EDK II Build System Framework Database Utility'
+    AboutInfo.Version = '0.3'
+    AboutInfo.Copyright = 'Copyright (c) 2006, Intel Corporation'
+    AboutInfo.Description = """
+      The EDK II Build System Framework Database Utility maintains FrameworkDatabase.db 
+      settings in an EDK II Workspace."""
+    AboutInfo.WebSite = ("http://tianocore.org", "Tiano Core home page")
+    AboutInfo.License = """
+      All rights reserved. This program and the accompanying materials are 
+      licensed and made available under the terms and conditions of the BSD 
+      License which accompanies this distribution.  The full text of the 
+      license may be found at http://opensource.org/licenses/bsd-license.php
+      
+      THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" 
+      BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, 
+      EITHER EXPRESS OR IMPLIED."""
+    if self.Model.Icon != None:
+      AboutInfo.Icon = self.Model.Icon
+    wx.AboutBox(AboutInfo)
+
+if __name__ == '__main__':
+  app = wx.PySimpleApp()
+  frame = Frame()
+  frame.Show()
+  app.MainLoop()
+  
\ No newline at end of file
index 9d1ff4a..2707bcb 100755 (executable)
@@ -27,13 +27,13 @@ def XmlList(Dom, String):
 def XmlElement (Dom, String):
   """Return a single element that matches the String which is XPath style syntax."""
   try:
-    return XmlList (Dom, String)[0].firstChild.data.strip(' ')
+    return XmlList (Dom, String)[0].firstChild.data.strip()
   except:
     return ''
 
 def XmlElementData (Dom):
   """Get the text for this element."""
-  return Dom.firstChild.data.strip(' ')
+  return Dom.firstChild.data.strip()
 
 def XmlAttribute (Dom, String):
   """Return a single attribute that named by String."""
@@ -44,7 +44,84 @@ def XmlAttribute (Dom, String):
 
 def XmlTopTag(Dom):
   """Return the name of the Root or top tag in the XML tree."""
-  return Dom.documentElement.nodeName
+  return Dom.firstChild.nodeName
+  
+def XmlParseFile (FileName):
+  """Parse an XML file into a DOM and return the DOM."""
+  try:
+    f = open(FileName, 'r')
+    Dom = xml.dom.minidom.parse(f)
+    f.close()
+    return Dom
+  except:
+    return xml.dom.minidom.parseString('<empty/>')
+
+def XmlParseFileSection (FileName, Tag):
+  """Parse a section of an XML file into a DOM(Document Object Model) and return the DOM."""
+  try:
+    f = open(FileName, 'r')
+  except:
+    return xml.dom.minidom.parseString('<empty/>')
+  Start = '<' + Tag
+  End = '</' + Tag + '>'
+  File = ''
+  while File.find(Start) < 0 or File.find(End) < 0:
+    Section = f.read(0x1000)
+    if Section == '':
+      break
+    File += Section
+  f.close()
+  if File.find(Start) < 0 or File.find(End) < 0:
+    return xml.dom.minidom.parseString('<empty/>')
+  File = File[File.find(Start):File.find(End)+len(End)]
+  try:
+    return xml.dom.minidom.parseString(File)
+  except:
+    return xml.dom.minidom.parseString('<empty/>')
+
+def XmlSaveFile (Dom, FileName, Encoding='UTF-8'):
+  """Save a DOM(Document Object Model) into an XML file."""
+  try:
+    f = open(FileName, 'w')
+    f.write(Dom.toxml(Encoding).replace('&quot;','"').replace('&gt;','>'))
+    f.close()
+    return True
+  except:
+    return False
+
+def XmlRemoveElement(Node):
+  """Remove an element node from DOM(Document Object Model) tree."""
+  ParentNode = Node.parentNode
+  if ParentNode == None:
+    return False
+  PreviousSibling = Node.previousSibling
+  while PreviousSibling != None and PreviousSibling.nodeType == PreviousSibling.TEXT_NODE and PreviousSibling.data.strip() == '':
+    Temp = PreviousSibling
+    PreviousSibling = PreviousSibling.previousSibling
+    ParentNode.removeChild(Temp)
+  ParentNode.removeChild(Node)
+  return True
+
+def XmlAppendChildElement(ParentNode, TagName, ElementText='', AttributeDictionary = {}):
+  """Add a child element to a DOM(Document Object Model) tree with optional Attributes."""
+  TagName = TagName.strip()
+  if TagName == '':
+    return False
+  Depth = 0
+  Dom = ParentNode
+  while Dom != None and Dom.nodeType != Dom.DOCUMENT_NODE:
+    Dom = Dom.parentNode
+    Depth += 1
+  if Dom == None:
+    return False
+  ParentNode.appendChild(Dom.createTextNode('\n%*s' % (Depth * 2, '')))
+  ElementNode = Dom.createElement(TagName)
+  if ElementText != '':
+    ElementNode.appendChild(Dom.createTextNode(ElementText))
+  for Item in AttributeDictionary:
+    ElementNode.setAttribute(Item, AttributeDictionary[Item])
+  ParentNode.appendChild(ElementNode)
+  return True
   
 
 # This acts like the main() function for the script, unless it is 'import'ed into another