Beispiel #1
0
    def __init__(self, parent, frame, log):

        ### instance variables
        self.maxWidth = 1280
        self.maxHeight = 1000
        self.parent = parent
        self.frame = frame  # top-level frame containing this wx.Panel
        self.transformServer = None  # for transforming societies with rules
        self.aRuleIsChecked = False
        self.filename = None
        self.ruleBooks = []
        self.ruleIndex = {}
        self.tempSociety = None

        ### static layout items
        wx.Panel.__init__(self, parent, -1)
        self.log = log
        self.winCount = 0
        sizer = RowColSizer()

        # RuleBook button
        tID = wx.NewId()
        self.ruleBookButton = wx.Button(self, tID, "Open RuleBook")
        self.Bind(wx.EVT_BUTTON, self.OnOpenRuleBook, self.ruleBookButton)
        self.ruleBookButton.SetBackgroundColour(wx.BLUE)
        self.ruleBookButton.SetForegroundColour(wx.WHITE)
        self.ruleBookButton.SetDefault()
        sizer.Add(
            self.ruleBookButton, flag=wx.ALIGN_CENTER_HORIZONTAL | wx.ALIGN_CENTER_VERTICAL, pos=(1, 1), colspan=2
        )

        # Rule CheckListBox
        tID = wx.NewId()
        rules = []
        self.lb = wx.CheckListBox(self, tID, size=(-1, 250), choices=rules, style=wx.LB_NEEDED_SB | wx.LB_HSCROLL)
        # ~ style=wx.LB_NEEDED_SB|wx.LB_HSCROLL|wx.LB_SORT)
        sizer.Add(self.lb, flag=wx.EXPAND, pos=(2, 1), colspan=2, rowspan=11)

        self.Bind(wx.EVT_LISTBOX, self.OnListBox, self.lb)
        self.Bind(wx.EVT_CHECKLISTBOX, self.OnChecklistBox, self.lb)
        ###

        self.Bind(EVT_UPDATE_SOCIETY, self.OnUpdate)

        # Rule Description label
        tID = wx.NewId()
        self.descLabel = wx.StaticText(self, tID, "Rule Description:")
        sizer.Add(self.descLabel, flag=wx.ALIGN_CENTER_VERTICAL, pos=(1, 4))

        # Rule Description text box
        tID = wx.NewId()
        self.ruleDescription = wx.TextCtrl(self, tID, "", size=(220, -1), style=wx.TE_READONLY)
        self.ruleDescription.SetInsertionPoint(0)
        sizer.Add(self.ruleDescription, pos=(2, 4), colspan=2)

        # Society name label
        tID = wx.NewId()
        self.societyNameLabel = wx.StaticText(self, tID, "Current Society:")
        sizer.Add(self.societyNameLabel, flag=wx.LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_LEFT, border=20, pos=(1, 6))

        # Society name text box
        tID = wx.NewId()
        self.societyName = wx.TextCtrl(self, tID, "", size=(180, -1), style=wx.TE_READONLY)
        self.societyName.SetStyle(0, len(self.societyName.GetValue()), wx.TextAttr(wx.BLUE))
        sizer.Add(
            self.societyName, flag=wx.LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_LEFT, border=20, pos=(2, 6), colspan=2
        )

        # Rule label
        tID = wx.NewId()
        self.ruleLabel = wx.StaticText(self, tID, "Rule:")
        sizer.Add(self.ruleLabel, flag=wx.ALIGN_CENTER_VERTICAL, pos=(3, 4))

        # Rule styled text box
        tID = wx.NewId()
        self.rule = EditorControl(self, tID, self.log)
        sizer.Add(self.rule, flag=wx.EXPAND, pos=(4, 4), colspan=6, rowspan=11)

        # Apply Rules button
        tID = wx.NewId()
        self.applyRulesButton = wx.Button(self, tID, "Apply Rules")
        #    EVT_BUTTON(self, tID, self.OnApplyRules)
        self.Bind(wx.EVT_BUTTON, self.OnApplyRules, self.applyRulesButton)
        self.applyRulesButton.Enable(False)
        sizer.Add(
            self.applyRulesButton,
            flag=wx.ALIGN_CENTER_HORIZONTAL | wx.ALIGN_CENTER_VERTICAL,
            pos=(14, 1),
            colspan=2,
            rowspan=1,
        )

        # Create New Rule button
        tID = wx.NewId()
        createRuleButton = wx.Button(self, tID, "Create New Rule")
        #    EVT_BUTTON(self, tID, self.OnCreateRule)
        self.Bind(wx.EVT_BUTTON, self.OnCreateRule, createRuleButton)
        sizer.Add(
            createRuleButton,
            flag=wx.ALIGN_CENTER_HORIZONTAL | wx.ALIGN_CENTER_VERTICAL,
            pos=(16, 1),
            colspan=2,
            rowspan=1,
        )

        # Button sizer to hold buttons along bottom
        self.btnSizer = wx.BoxSizer(wx.HORIZONTAL)

        # Save Rule button
        tID = wx.NewId()
        self.saveRuleButton = wx.Button(self, tID, "Save Rule")
        #    EVT_BUTTON(self, tID, self.OnSaveRule)
        self.Bind(wx.EVT_BUTTON, self.OnSaveRule, self.saveRuleButton)
        self.saveRuleButton.Enable(False)
        self.btnSizer.Add(self.saveRuleButton, flag=wx.LEFT | wx.RIGHT, border=20)

        # Open Society button
        tID = wx.NewId()
        self.openSocietyButton = wx.Button(self, tID, "Open Society")
        #    EVT_BUTTON(self, tID, self.OnOpenSociety)
        self.Bind(wx.EVT_BUTTON, self.OnOpenSociety, self.openSocietyButton)
        self.openSocietyButton.SetBackgroundColour(wx.GREEN)
        self.btnSizer.Add(self.openSocietyButton, flag=wx.LEFT | wx.RIGHT, border=20)

        # Save Society button
        tID = wx.NewId()
        self.saveSocietyButton = wx.Button(self, tID, "Save Society")
        #    EVT_BUTTON(self, tID, self.OnSaveSociety)
        self.Bind(wx.EVT_BUTTON, self.OnSaveSociety, self.saveSocietyButton)
        self.saveSocietyButton.Enable(False)
        self.btnSizer.Add(self.saveSocietyButton, flag=wx.LEFT | wx.RIGHT, border=20)

        # Undo Transform button
        tID = wx.NewId()
        self.undoTransformButton = wx.Button(self, tID, "Undo Transform")
        #    EVT_BUTTON(self, tID, self.OnUndoTransform)
        self.Bind(wx.EVT_BUTTON, self.OnUndoTransform, self.undoTransformButton)
        self.undoTransformButton.Enable(False)
        self.btnSizer.Add(self.undoTransformButton, flag=wx.LEFT | wx.RIGHT, border=20)

        sizer.Add(self.btnSizer, pos=(16, 4), colspan=6)

        # Progress gizmo image
        tID = wx.NewId()
        lesImages = [gizmoImages.catalog[i].getBitmap() for i in gizmoImages.index]
        self.gizmo = Gizmo(self, -1, lesImages, size=(36, 36), frameDelay=0.1)
        sizer.Add(self.gizmo, pos=(2, 9), flag=wx.ALIGN_RIGHT, rowspan=2)

        if SHOW_BACKGROUND:
            self.bg_bmp = images.getGridBGBitmap()
            self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)

        # Add finishing touches to the layout
        sizer.AddGrowableCol(7)  # makes rule styled text box and Society Viewer expand to the right on window resize
        sizer.AddGrowableRow(4)  # makes Society Viewer expand downward on window resize
        sizer.AddSpacer(10, 10, pos=(1, 10))  # adds a constant size border along top and right side
        sizer.AddSpacer(10, 10, pos=(17, 1))  # adds a constant size border along bottom and left side

        self.SetSizer(sizer)
        self.SetAutoLayout(True)
        #    EVT_RIGHT_DOWN(self.lb, self.OnRightDown)  # emits a wx.MouseEvent
        self.lb.Bind(wx.EVT_RIGHT_DOWN, self.OnRightDown)
        #    self.Bind(wx.EVT_RIGHT_DOWN, self.OnRightDown) # either this r this one above is right
        #    EVT_RIGHT_UP(self.lb, self.OnRightUp)  # emits a wx.MouseEvent
        self.lb.Bind(wx.EVT_RIGHT_UP, self.OnRightUp)
Beispiel #2
0
class SocietyBuilderPanel(wx.Panel):
    def __init__(self, parent, frame, log):

        ### instance variables
        self.maxWidth = 1280
        self.maxHeight = 1000
        self.parent = parent
        self.frame = frame  # top-level frame containing this wx.Panel
        self.transformServer = None  # for transforming societies with rules
        self.aRuleIsChecked = False
        self.filename = None
        self.ruleBooks = []
        self.ruleIndex = {}
        self.tempSociety = None

        ### static layout items
        wx.Panel.__init__(self, parent, -1)
        self.log = log
        self.winCount = 0
        sizer = RowColSizer()

        # RuleBook button
        tID = wx.NewId()
        self.ruleBookButton = wx.Button(self, tID, "Open RuleBook")
        self.Bind(wx.EVT_BUTTON, self.OnOpenRuleBook, self.ruleBookButton)
        self.ruleBookButton.SetBackgroundColour(wx.BLUE)
        self.ruleBookButton.SetForegroundColour(wx.WHITE)
        self.ruleBookButton.SetDefault()
        sizer.Add(
            self.ruleBookButton, flag=wx.ALIGN_CENTER_HORIZONTAL | wx.ALIGN_CENTER_VERTICAL, pos=(1, 1), colspan=2
        )

        # Rule CheckListBox
        tID = wx.NewId()
        rules = []
        self.lb = wx.CheckListBox(self, tID, size=(-1, 250), choices=rules, style=wx.LB_NEEDED_SB | wx.LB_HSCROLL)
        # ~ style=wx.LB_NEEDED_SB|wx.LB_HSCROLL|wx.LB_SORT)
        sizer.Add(self.lb, flag=wx.EXPAND, pos=(2, 1), colspan=2, rowspan=11)

        self.Bind(wx.EVT_LISTBOX, self.OnListBox, self.lb)
        self.Bind(wx.EVT_CHECKLISTBOX, self.OnChecklistBox, self.lb)
        ###

        self.Bind(EVT_UPDATE_SOCIETY, self.OnUpdate)

        # Rule Description label
        tID = wx.NewId()
        self.descLabel = wx.StaticText(self, tID, "Rule Description:")
        sizer.Add(self.descLabel, flag=wx.ALIGN_CENTER_VERTICAL, pos=(1, 4))

        # Rule Description text box
        tID = wx.NewId()
        self.ruleDescription = wx.TextCtrl(self, tID, "", size=(220, -1), style=wx.TE_READONLY)
        self.ruleDescription.SetInsertionPoint(0)
        sizer.Add(self.ruleDescription, pos=(2, 4), colspan=2)

        # Society name label
        tID = wx.NewId()
        self.societyNameLabel = wx.StaticText(self, tID, "Current Society:")
        sizer.Add(self.societyNameLabel, flag=wx.LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_LEFT, border=20, pos=(1, 6))

        # Society name text box
        tID = wx.NewId()
        self.societyName = wx.TextCtrl(self, tID, "", size=(180, -1), style=wx.TE_READONLY)
        self.societyName.SetStyle(0, len(self.societyName.GetValue()), wx.TextAttr(wx.BLUE))
        sizer.Add(
            self.societyName, flag=wx.LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_LEFT, border=20, pos=(2, 6), colspan=2
        )

        # Rule label
        tID = wx.NewId()
        self.ruleLabel = wx.StaticText(self, tID, "Rule:")
        sizer.Add(self.ruleLabel, flag=wx.ALIGN_CENTER_VERTICAL, pos=(3, 4))

        # Rule styled text box
        tID = wx.NewId()
        self.rule = EditorControl(self, tID, self.log)
        sizer.Add(self.rule, flag=wx.EXPAND, pos=(4, 4), colspan=6, rowspan=11)

        # Apply Rules button
        tID = wx.NewId()
        self.applyRulesButton = wx.Button(self, tID, "Apply Rules")
        #    EVT_BUTTON(self, tID, self.OnApplyRules)
        self.Bind(wx.EVT_BUTTON, self.OnApplyRules, self.applyRulesButton)
        self.applyRulesButton.Enable(False)
        sizer.Add(
            self.applyRulesButton,
            flag=wx.ALIGN_CENTER_HORIZONTAL | wx.ALIGN_CENTER_VERTICAL,
            pos=(14, 1),
            colspan=2,
            rowspan=1,
        )

        # Create New Rule button
        tID = wx.NewId()
        createRuleButton = wx.Button(self, tID, "Create New Rule")
        #    EVT_BUTTON(self, tID, self.OnCreateRule)
        self.Bind(wx.EVT_BUTTON, self.OnCreateRule, createRuleButton)
        sizer.Add(
            createRuleButton,
            flag=wx.ALIGN_CENTER_HORIZONTAL | wx.ALIGN_CENTER_VERTICAL,
            pos=(16, 1),
            colspan=2,
            rowspan=1,
        )

        # Button sizer to hold buttons along bottom
        self.btnSizer = wx.BoxSizer(wx.HORIZONTAL)

        # Save Rule button
        tID = wx.NewId()
        self.saveRuleButton = wx.Button(self, tID, "Save Rule")
        #    EVT_BUTTON(self, tID, self.OnSaveRule)
        self.Bind(wx.EVT_BUTTON, self.OnSaveRule, self.saveRuleButton)
        self.saveRuleButton.Enable(False)
        self.btnSizer.Add(self.saveRuleButton, flag=wx.LEFT | wx.RIGHT, border=20)

        # Open Society button
        tID = wx.NewId()
        self.openSocietyButton = wx.Button(self, tID, "Open Society")
        #    EVT_BUTTON(self, tID, self.OnOpenSociety)
        self.Bind(wx.EVT_BUTTON, self.OnOpenSociety, self.openSocietyButton)
        self.openSocietyButton.SetBackgroundColour(wx.GREEN)
        self.btnSizer.Add(self.openSocietyButton, flag=wx.LEFT | wx.RIGHT, border=20)

        # Save Society button
        tID = wx.NewId()
        self.saveSocietyButton = wx.Button(self, tID, "Save Society")
        #    EVT_BUTTON(self, tID, self.OnSaveSociety)
        self.Bind(wx.EVT_BUTTON, self.OnSaveSociety, self.saveSocietyButton)
        self.saveSocietyButton.Enable(False)
        self.btnSizer.Add(self.saveSocietyButton, flag=wx.LEFT | wx.RIGHT, border=20)

        # Undo Transform button
        tID = wx.NewId()
        self.undoTransformButton = wx.Button(self, tID, "Undo Transform")
        #    EVT_BUTTON(self, tID, self.OnUndoTransform)
        self.Bind(wx.EVT_BUTTON, self.OnUndoTransform, self.undoTransformButton)
        self.undoTransformButton.Enable(False)
        self.btnSizer.Add(self.undoTransformButton, flag=wx.LEFT | wx.RIGHT, border=20)

        sizer.Add(self.btnSizer, pos=(16, 4), colspan=6)

        # Progress gizmo image
        tID = wx.NewId()
        lesImages = [gizmoImages.catalog[i].getBitmap() for i in gizmoImages.index]
        self.gizmo = Gizmo(self, -1, lesImages, size=(36, 36), frameDelay=0.1)
        sizer.Add(self.gizmo, pos=(2, 9), flag=wx.ALIGN_RIGHT, rowspan=2)

        if SHOW_BACKGROUND:
            self.bg_bmp = images.getGridBGBitmap()
            self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)

        # Add finishing touches to the layout
        sizer.AddGrowableCol(7)  # makes rule styled text box and Society Viewer expand to the right on window resize
        sizer.AddGrowableRow(4)  # makes Society Viewer expand downward on window resize
        sizer.AddSpacer(10, 10, pos=(1, 10))  # adds a constant size border along top and right side
        sizer.AddSpacer(10, 10, pos=(17, 1))  # adds a constant size border along bottom and left side

        self.SetSizer(sizer)
        self.SetAutoLayout(True)
        #    EVT_RIGHT_DOWN(self.lb, self.OnRightDown)  # emits a wx.MouseEvent
        self.lb.Bind(wx.EVT_RIGHT_DOWN, self.OnRightDown)
        #    self.Bind(wx.EVT_RIGHT_DOWN, self.OnRightDown) # either this r this one above is right
        #    EVT_RIGHT_UP(self.lb, self.OnRightUp)  # emits a wx.MouseEvent
        self.lb.Bind(wx.EVT_RIGHT_UP, self.OnRightUp)

    #    self.Bind(wx.EVT_RIGHT_UP, self.OnRightUp) # either this r this one above is right

    # ---------------------------------------------------------------------------------------------------
    def OnOpenRuleBook(self, event):
        dlg = wx.DirDialog(self, "Choose a RuleBook:", "", style=wx.DD_DEFAULT_STYLE | wx.DD_NEW_DIR_BUTTON)
        if dlg.ShowModal() == wx.ID_OK:
            ruleBookPath = dlg.GetPath()
            # check if this rulebook already open
            for rulebook in self.ruleBooks:
                if ruleBookPath == rulebook.getPath():
                    dlg.Destroy()
                    self.log.WriteText("Ignored attempt to open an already opened Rulebook (%s)\n" % rulebook.getName())
                    return
            # Must not be already open, so continue
            ruleBook = Rulebook(ruleBookPath)
            # Next, if there are no [.rul | .rule] files in the dir, show user a dialog and return.
            if ruleBook.isEmpty():
                emptyRulebookDialog = CougaarMessageDialog(self, "info", "The selected rulebook is empty.")
                emptyRulebookDialog.display()
                dlg.Destroy()
                return
            # Wasn't empty, so continue
            self.ruleBooks.append(ruleBook)
            for rule in ruleBook.each_rule():
                self.lb.Append(rule)
                self.ruleIndex[rule] = ruleBook  # links rules to their containing rulebook
            addRulebook = True
            self.frame.updateCloseRulebookMenuItem(addRulebook)
        dlg.Destroy()

    # ----------------------------------------------------------------------

    def OnSaveRule(self, event):
        self.SaveRule()

    # ----------------------------------------------------------------------

    def OnCreateRule(self, event):
        # First check for changes to current rule
        if self.rule.textIsDirty:
            msg = "Save changes to rule?"
            dlg = wx.MessageDialog(
                self, msg, style=wx.CAPTION | wx.YES_NO | wx.NO_DEFAULT | wx.THICK_FRAME | wx.ICON_EXCLAMATION
            )

            val = dlg.ShowModal()
            if val == wx.ID_YES:
                self.SaveRule()

        self.clearRule()

    # ----------------------------------------------------------------------

    def clearRule(self):
        self.rule.SetText("")
        self.ruleDescription.SetValue("")
        self.frame.enableRuleSaveMenuItems()
        item = self.lb.GetSelection()
        if item > -1:
            # if an item is selected, deselect it
            self.lb.SetSelection(item, FALSE)
        self.rule.textIsDirty = False
        self.rule.SetFocus()
        self.frame.enableRuleSaveMenuItems(False)
        self.filename = None

    # ----------------------------------------------------------------------

    def OnOpenSociety(self, event):
        self.frame.openSocietyFile(self, "society")
        if self.aRuleIsChecked:
            self.applyRulesButton.Enable(True)

    # ------------------------------------------------------------------------------

    def OnSaveSociety(self, event):
        if not self.frame.societyOpen:
            dlg = wx.MessageDialog(
                self,
                "No society is open. You must open a society before you can save it.",
                "No Society Open",
                wx.OK | wx.ICON_EXCLAMATION,
            )
            dlg.ShowModal()
            dlg.Destroy()
        else:
            self.frame.saveSociety()
            self.tempSociety = None  # clear out the backup copy

    # ------------------------------------------------------------------------------

    def OnUndoTransform(self, event):
        msg = """
Are you sure you want to undo the transformation?

You will lose all changes made to the society since the transformation."""
        choice = CougaarMessageDialog(self, "confirm", msg).getUserInput()
        if choice == wx.ID_YES:
            self.frame.society = self.tempSociety
            self.frame.societyViewer.UpdateControl(self.frame.society, True)
            self.frame.ruleEditor.societyName.SetValue(self.frame.society.name)
            for node in self.frame.society.each_node():
                node.updateNameServerParam(self.frame.society.get_nameserver())
            self.undoTransformButton.Disable()

    # -------------------------------------------------------------------------------

    def OnListBox(self, event):
        # self.log.WriteText('EvtListBox: %s\n' % event.GetString())
        if self.rule.textIsDirty == True:
            msg = "Save changes to rule?"
            dlg = wx.MessageDialog(
                self, msg, style=wx.CAPTION | wx.YES_NO | wx.NO_DEFAULT | wx.THICK_FRAME | wx.ICON_EXCLAMATION
            )
            val = dlg.ShowModal()
            if val == wx.ID_YES:
                self.SaveRule()

        selectedRule = self.lb.GetStringSelection()
        rulebook = self.ruleIndex[selectedRule]  # get this rule's associated rulebook
        self.filename = os.path.join(rulebook.getPath(), selectedRule)
        self.ruleText = RuleText(self.filename)
        # ~ if self.filename.endswith(".rule"):
        # ~ self.rule.SetLexer(wx.STC_LEX_RUBY)
        # ~ print "Lexer set to Ruby"
        # ~ else:
        # ~ self.rule.SetLexer(wx.STC_LEX_PYTHON)
        self.rule.SetLexer(stc.STC_LEX_PYTHON)
        self.rule.SetText(self.ruleText.rule)
        # ~ self.rule.adjustEOL()
        self.rule.convertEOL()
        self.rule.EmptyUndoBuffer()
        self.rule.Colourise(0, -1)
        self.ruleDescription.SetValue(self.ruleText.description)
        # line numbers in the margin
        self.rule.SetMarginType(1, stc.STC_MARGIN_NUMBER)
        self.rule.SetMarginWidth(1, 25)
        self.rule.textIsDirty = False
        self.frame.enableRuleSaveMenuItems(False)
        self.frame.enableRuleSaveAs(True)
        self.frame.enableRuleMenuItems()

    # -------------------------------------------------------------------------------

    def OnChecklistBox(self, event):
        # event.IsChecked() returns True regardless of whether checkbox was checked or unchecked!!!
        # So, we'll just have to search the whole list and see if anything is checked.
        self.aRuleIsChecked = False
        for item in range(self.lb.GetCount()):
            if self.lb.IsChecked(item):
                # a rule is checked; set the flag and stop searching
                self.aRuleIsChecked = True
                break
        if self.frame.societyOpen and self.aRuleIsChecked:
            self.applyRulesButton.Enable(True)
        if not self.aRuleIsChecked:
            # no rules were checked; disable the button
            self.applyRulesButton.Enable(False)

    # -------------------------------------------------------------------------------

    def OnEraseBackground(self, evt):
        dc = evt.GetDC()
        if not dc:
            dc = wx.ClientDC(self.GetClientWindow())

        # tile the background bitmap
        sz = self.GetClientSize()
        w = self.bg_bmp.GetWidth()
        h = self.bg_bmp.GetHeight()
        x = 0
        while x < sz.width:
            y = 0
            while y < sz.height:
                dc.DrawBitmap(self.bg_bmp, x, y)
                y = y + h
            x = x + w

    # --------------------------------------------------------------------------------------------

    def OnApplyRules(self, event):
        self.tempSociety = self.frame.society.clone()  # save a copy in case we must restore
        numRules = self.lb.GetCount()
        if numRules > 0:
            checkedRules = []  # will hold a string path/filename for ea rule checked
            ruleFilename = None
            for item in range(numRules):
                if self.lb.IsChecked(item):
                    ruleFilename = self.lb.GetString(item)
                    wx.LogMessage("Applying rule " + str(item) + ": " + ruleFilename + "\n")
                    if self.lb.IsSelected(item) and self.rule.textIsDirty == True:
                        msg = (
                            "The rule you are applying has been changed. If you wish "
                            + "to apply the changed version, you must first save the rule. "
                            + "Would you like to save the rule now?"
                        )
                        dlg = wx.MessageDialog(
                            self,
                            msg,
                            style=wx.CAPTION | wx.YES_NO | wx.NO_DEFAULT | wx.THICK_FRAME | wx.ICON_EXCLAMATION,
                        )

                        val = dlg.ShowModal()
                        if val == wx.ID_YES:
                            self.SaveRule()
                    rulebook = self.ruleIndex[ruleFilename]  # get this rule's associated rulebook
                    checkedRules.append(os.path.join(rulebook.getPath(), ruleFilename))
            msg = ""
            if len(checkedRules) > 0:
                self.frame.ruleApplied = True
                # All rules are now python rules
                # Create one SocietyTransformServer instance and pass it a list of rules to execute
                self.transformServer = SocietyTransformServer(self.frame.society, checkedRules, self, self.log)
                self.transformServer.Start()
                # ~ self.StartAnimation()
                self.log.WriteText("Transformation complete.\n")
                self.undoTransformButton.Enable(True)
                msg = "Transformation complete.\n" + msg
                doneDialog = CougaarMessageDialog(self, "info", msg)
                doneDialog.display()

    # --------------------------------------------------------------------------------------------

    def OnRightDown(self, event):
        if wx.Platform == "__WXMSW__":
            pt = event.GetPosition()
            itemId = self.lb.HitTest(pt)
            self.lb.SetSelection(itemId, True)
            self.OnListBox(None)

    # --------------------------------------------------------------------------------------------

    def OnRightUp(self, event):
        if wx.Platform == "__WXMSW__":
            x = event.GetX()
            y = event.GetY()
            # ~ point = wx.Point(x, y+20)
            point = wx.Point(x, y)
            menu = wx.Menu()
            menuItem = wx.MenuItem(menu, 200, "Delete Rule")
            menu.AppendItem(menuItem)
            menuItem = wx.MenuItem(menu, 210, "Rename Rule")
            menu.AppendItem(menuItem)
            self.Bind(wx.EVT_MENU, self.OnDeleteRule, 200)
            self.Bind(wx.EVT_MENU, self.OnRenameRule, 210)
            self.PopupMenu(menu, point)
            menu.Destroy()
            event.Skip()

    # --------------------------------------------------------------------------------------------

    def OnDeleteRule(self, event):
        ruleIdToDelete = self.lb.GetSelection()
        if ruleIdToDelete < 0:
            self.log.WriteText("Unable to delete rule: no rule selected\n")
            return
        ruleNameToDelete = self.lb.GetString(ruleIdToDelete)
        rulebook = self.ruleIndex[ruleNameToDelete]  # get this rule's associated rulebook
        msg = """Are you sure you want to delete this rule?
Doing so will permanently delete it from disk."""
        dlg = CougaarMessageDialog(self, "delete", msg)
        response = dlg.getUserInput()
        if response == wx.ID_YES:
            self.lb.Delete(ruleIdToDelete)  # remove it from the list box
            os.remove(os.path.join(rulebook.getPath(), ruleNameToDelete))  # delete from disk
            self.clearRule()  # clear the rule text
        self.frame.enableRuleMenuItems(False)
        rulebook.removeRule(ruleNameToDelete)
        if rulebook.size() == 0:
            self.removeRulebook(rulebook)

    # --------------------------------------------------------------------------------------------

    def OnRenameRule(self, event):
        ruleIdToRename = self.lb.GetSelection()
        if ruleIdToRename < 0:
            self.log.WriteText("Unable to rename rule: no rule selected\n")
            return
        ruleNameToRename = self.lb.GetString(ruleIdToRename)
        rulebook = self.ruleIndex[ruleNameToRename]  # get this rule's associated rulebook
        # Get the new rule name from the user
        newRuleName = []
        msg = "Current rule name: " + ruleNameToRename + "\nNew rule name:"
        renameDialog = wx.TextEntryDialog(self, msg, "Rename Rule")
        renameDialog.SetSize((175, -1))
        if renameDialog.ShowModal() == wx.ID_OK:
            newRuleName.append(renameDialog.GetValue())
        renameDialog.Destroy()
        if len(newRuleName) > 0:
            self.lb.InsertItems(newRuleName, ruleIdToRename)  # This messes up the sort order. Is that OK?
            self.lb.Delete(ruleIdToRename + 1)
            # Replace the old rule name with the new in the ruleIndex dictionary
            del self.ruleIndex[ruleNameToRename]
            self.ruleIndex[newRuleName[0]] = rulebook
            # Update rulebook with new rule name
            rulebook.replaceRule(ruleNameToRename, newRuleName[0])
            os.chdir(rulebook.path)
            os.rename(ruleNameToRename, newRuleName[0])

    # --------------------------------------------------------------------------------------------

    def StartAnimation(self):
        self.gizmo.Start()

    # --------------------------------------------------------------------------------------------

    def StopAnimation(self):
        self.gizmo.Rest()

    # ----------------------------------------------------------------------

    def SaveRule(self):
        if self.filename is None:
            wildcard = "Rule File (*.rule)|*.rule|" "All files (*.*)|*.*"
            rulePath = os.getcwd()
            if len(self.ruleBooks) > 1:
                rulePath = self.ruleBooks[-1].path
            dlg = wx.FileDialog(self, "Save Rule As", rulePath, "", wildcard, wx.SAVE)
            try:
                if dlg.ShowModal() == wx.ID_OK:
                    self.filename = dlg.GetPath()
                    self.save_rule()
            finally:
                dlg.Destroy()
        else:
            self.save_rule()

    # ----------------------------------------------------------------------

    def save_rule(self):
        ruleText = RuleText(None, description=self.ruleDescription.GetValue(), rule=self.rule.GetText())
        ruleText.saveRule(self.filename)
        self.log.WriteText("Rule saved as %s\n" % self.filename)
        rulebook = self.addToRulebook()
        dir, file = os.path.split(self.filename)
        if self.lb.FindString(file) < 0:
            # Add rule to list box only if it's not already there
            self.lb.Append(file)
            self.ruleIndex[file] = rulebook  # links rule to its containing rulebook
        self.ruleDescription.SetValue(ruleText.getDescription())
        self.rule.textIsDirty = False
        self.frame.enableRuleSaveMenuItems(False)
        self.frame.enableRuleSaveAs(True)

    # ----------------------------------------------------------------------

    def removeRulebook(self, rulebook):
        if isinstance(rulebook, Rulebook):
            # if rule in editor window is in this rulebook, clear the editor window
            if self.filename is not None:
                dir, rule = os.path.split(self.filename)
                if rulebook.containsRule(rule):
                    if self.rule.textIsDirty:
                        # First give user a chance to save rule
                        msg = "Closing this rulebook will also close the\ncurrently open rule. Save rule first?"
                        dlg = CougaarMessageDialog(self, "close", msg)
                        disposition = dlg.getUserInput()
                        if disposition == wx.ID_CANCEL:
                            return
                        elif disposition == wx.ID_YES:
                            self.save_rule()
                    self.clearRule()
            for rule in rulebook.each_rule():
                item = self.lb.FindString(rule)
                if item >= 0:
                    self.lb.Delete(item)
            self.ruleBooks.remove(rulebook)
            removeRulebook = False
            self.frame.updateCloseRulebookMenuItem(removeRulebook)
        else:  # must be a rulebook name (String)
            aRulebook = self.getRulebook(rulebook)
            if aRulebook is not None:
                self.removeRulebook(aRulebook)

    # ----------------------------------------------------------------------

    def getRulebook(self, rulebookName):
        for rulebook in self.ruleBooks:
            if rulebook.name == rulebookName:
                return rulebook
        return None

    # ----------------------------------------------------------------------

    def getRulebookNames(self):
        rbookNames = []
        for rulebook in self.ruleBooks:
            rbookNames.append(rulebook.name)
        return rbookNames

    # ----------------------------------------------------------------------

    def addToRulebook(self):
        dir, file = os.path.split(self.filename)
        for rulebook in self.ruleBooks:
            if rulebook.path == dir:
                if not rulebook.containsRule(file):
                    rulebook.addRule(file)
                return rulebook
            # If no rulebook found (i.e., this is the first rule in a new rulebook dir),
            # create a new rulebook
            rulebook = Rulebook(dir)
            rulebook.addRule(file)
            self.ruleBooks.append(rulebook)
            return rulebook

    # ----------------------------------------------------------------------

    def OnUpdate(self, event):
        # ~ self.log.WriteText("Stop time: %s\n" % time.ctime())
        self.StopAnimation()
        if self.transformServer is not None and self.transformServer.IsRunning():
            self.transformServer.Stop()
        if self.frame.server is not None and self.frame.server.IsRunning():
            self.frame.server.Stop()
        self.frame.society = event.msg
        if self.frame.society is not None:
            self.societyName.SetValue(self.frame.society.name)
            viewer = self.frame.societyViewer
            viewer.UpdateControl(self.frame.society, True)
            if self.frame.ruleApplied:  # if we're updating due to rule application, make a log entry
                num = self.frame.societyViewer.getNumEntitiesChanged()
                wx.LogMessage("Number of society entities modified: " + str(num))
                self.frame.ruleApplied = False
            self.frame.enableSocietySaveMenuItems()
            self.setNextHighlightButton()
            self.frame.societyOpen = True

    # ----------------------------------------------------------------------

    # All we're trying to do here is determine if the Next Highlight button
    # should be enabled or not.  Also, if there are highlighted items that
    # are already visible, increment the colourisedItemIndex to
    # the first non-visible item's position in the colourisedItemsList.
    #
    def setNextHighlightButton(self):
        viewer = self.frame.societyViewer
        btn = self.frame.societyEditor.nextHighlightButton
        if viewer.colourisedItemIndex < len(viewer.colourisedItemsList):  # if we've got some highlighted items
            hiItem = viewer.colourisedItemsList[viewer.colourisedItemIndex]  # get the first one

            while viewer.IsVisible(hiItem):
                # while there are more highlighted items and they are already visible:
                viewer.colourisedItemIndex += 1  # increment index to look at the next one
                if viewer.colourisedItemIndex < len(viewer.colourisedItemsList):
                    hiItem = viewer.colourisedItemsList[viewer.colourisedItemIndex]
                else:
                    btn.Enable(False)
                    break

            else:  # there is another highlighted item that is not visible
                btn.Enable(True)
        else:
            btn.Enable(False)