Beispiel #1
0
class PluginManagerDialog(wx.Dialog):
    """Manage the available plugins."""
    def __init__(self):
        pre = wx.PreDialog()
        # the Create step is done by XRC.
        self.PostCreate(pre)

    def Init(self, plugins, pluginsDisabled):
        """Method called after the panel has been initialized."""

        # Set window icon
        if not guiutil.IsMac():
            self.SetIcon(guiutil.get_icon())

        # Initialize controls
        self.tcPlugins = XRCCTRL(self, 'tcPlugins')
        self.panelTreeView = XRCCTRL(self, 'panelTreeView')
        self.panelProperties = XRCCTRL(self, 'panelProperties')
        self.lblName = XRCCTRL(self, 'lblName')
        self.lblAuthor = XRCCTRL(self, 'lblAuthor')
        self.lblPluginType = XRCCTRL(self, 'lblPluginType')
        self.lblVersion = XRCCTRL(self, 'lblVersion')
        self.lblVersionNumber = XRCCTRL(self, 'lblVersionNumber')
        self.lblDescription = XRCCTRL(self, 'lblDescription')
        self.checkEnabled = XRCCTRL(self, 'checkEnabled')
        self.lblMessage = XRCCTRL(self, 'lblMessage')
        self.btnGetMorePlugins = XRCCTRL(self, 'btnGetMorePlugins')
        self.btnDeletePlugin = XRCCTRL(self, 'btnDeletePlugin')

        self.plugins = plugins
        self.pluginsDisabled = set(pluginsDisabled)

        # Bind interface events to the proper methods
        #        wx.EVT_BUTTON(self, XRCID('btnDeletePlugin'), self.DeletePlugin)
        wx.EVT_CHECKBOX(self, XRCID('checkEnabled'), self.OnEnablePlugin)
        wx.EVT_TREE_ITEM_ACTIVATED(self, XRCID('tcPlugins'),
                                   self.OnEnablePlugin)
        wx.EVT_TREE_SEL_CHANGED(self, XRCID('tcPlugins'),
                                self.OnSelectTreeItem)
        wx.EVT_TREE_SEL_CHANGING(self, XRCID('tcPlugins'),
                                 self.OnSelectRootItem)

        # Modify the control and font size as needed
        font = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT)
        if guiutil.IsMac():
            children = list(self.Children) + \
                        list(self.panelTreeView.Children) + \
                        list(self.panelProperties.Children)
            for control in children:
                control.SetFont(font)
                control.SetWindowVariant(wx.WINDOW_VARIANT_SMALL)
            XRCCTRL(self, 'wxID_OK').SetWindowVariant(wx.WINDOW_VARIANT_NORMAL)
        font.SetWeight(wx.FONTWEIGHT_BOLD)
        if guiutil.IsMSWindows():
            self.tcPlugins.SetPosition((0, 3))
            self.panelTreeView.SetWindowStyle(wx.STATIC_BORDER)
        if (guiutil.IsMac() or guiutil.IsGtk()):
            self.tcPlugins.SetPosition((-30, 0))
            self.panelTreeView.SetWindowStyle(wx.SUNKEN_BORDER)
        self.lblName.SetFont(font)
        self.lblMessage.SetFont(font)

        self.Layout()
        self.InitPluginList()
        self.LoadPlugins()

    def InitPluginList(self):
        """Initialize the plugin list control."""

        iSize = (16, 16)
        iList = wx.ImageList(iSize[0], iSize[1])
        iList.Add(
            wx.Bitmap(util.GetResourcePath('bricks.png'), wx.BITMAP_TYPE_PNG))
        iList.Add(
            wx.Bitmap(util.GetResourcePath('plugin.png'), wx.BITMAP_TYPE_PNG))
        iList.Add(
            wx.Bitmap(util.GetResourcePath('plugin_disabled.png'),
                      wx.BITMAP_TYPE_PNG))
        self.tcPlugins.AssignImageList(iList)
        self.root = self.tcPlugins.AddRoot('Plugins')
        self.baseroot = self.tcPlugins.AppendItem(self.root,
                                                  "Built-In Plugins", 0)
        self.userroot = self.tcPlugins.AppendItem(self.root, "User Plugins", 0)

        font = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT)
        font.SetWeight(wx.FONTWEIGHT_BOLD)
        self.tcPlugins.SetItemFont(self.baseroot, font)
        self.tcPlugins.SetItemFont(self.userroot, font)

    def LoadPlugins(self):
        """Update and load the data for the plugin list control."""

        # Set up the plugins for each plugin entry point of dicompyler
        for n, plugin in enumerate(self.plugins):
            # Skip plugin if it doesn't contain the required dictionary
            # or actually is a proper Python module
            p = plugin['plugin']
            if not hasattr(p, 'pluginProperties'):
                continue
            props = p.pluginProperties()
            root = self.userroot
            if (plugin['location'] == 'base'):
                root = self.baseroot
            else:
                root = self.userroot
            i = self.tcPlugins.AppendItem(root, props['name'], 1)

            if (p.__name__ in self.pluginsDisabled):
                self.tcPlugins.SetItemImage(i, 2)
                self.tcPlugins.SetItemTextColour(i, wx.Colour(169, 169, 169))

            self.tcPlugins.SetPyData(i, n)
            self.tcPlugins.SelectItem(i)
        self.tcPlugins.ExpandAll()
        wx.EVT_TREE_ITEM_COLLAPSING(self, XRCID('tcPlugins'),
                                    self.OnExpandCollapseTree)
        wx.EVT_TREE_ITEM_EXPANDING(self, XRCID('tcPlugins'),
                                   self.OnExpandCollapseTree)

    def OnSelectTreeItem(self, evt):
        """Update the interface when the selected item has changed."""

        item = evt.GetItem()
        n = self.tcPlugins.GetPyData(item)
        if (n == None):
            self.panelProperties.Hide()
            return
        self.panelProperties.Show()
        plugin = self.plugins[n]
        p = plugin['plugin']
        props = p.pluginProperties()
        self.lblName.SetLabel(props['name'])
        self.lblAuthor.SetLabel(props['author'].replace('&', '&&'))
        self.lblVersionNumber.SetLabel(str(props['version']))
        ptype = props['plugin_type']
        self.lblPluginType.SetLabel(ptype[0].capitalize() + ptype[1:])
        self.lblDescription.SetLabel(props['description'].replace('&', '&&'))

        self.checkEnabled.SetValue(not (p.__name__ in self.pluginsDisabled))

        self.Layout()
        self.panelProperties.Layout()

    def OnSelectRootItem(self, evt):
        """Block the root items from being selected."""

        item = evt.GetItem()
        n = self.tcPlugins.GetPyData(item)
        if (n == None):
            evt.Veto()

    def OnExpandCollapseTree(self, evt):
        """Block the tree from expanding or collapsing."""

        evt.Veto()

    def OnEnablePlugin(self, evt=None):
        """Publish the enabled/disabled state of the plugin."""

        item = self.tcPlugins.GetSelection()
        n = self.tcPlugins.GetPyData(item)
        plugin = self.plugins[n]
        p = plugin['plugin']

        # Set the checkbox to the appropriate state if the event
        # comes from the treeview
        if (evt.EventType == wx.EVT_TREE_ITEM_ACTIVATED.typeId):
            self.checkEnabled.SetValue(not self.checkEnabled.IsChecked())

        if self.checkEnabled.IsChecked():
            self.tcPlugins.SetItemImage(item, 1)
            self.tcPlugins.SetItemTextColour(item, wx.BLACK)
            self.pluginsDisabled.remove(p.__name__)
            logger.debug("%s enabled", p.__name__)
        else:
            self.tcPlugins.SetItemImage(item, 2)
            self.tcPlugins.SetItemTextColour(item, wx.Colour(169, 169, 169))
            self.pluginsDisabled.add(p.__name__)
            logger.debug("%s disabled", p.__name__)

        pub.sendMessage(
            'preferences.updated.value',
            {'general.plugins.disabled_list': list(self.pluginsDisabled)})
class EditorFrame(wx.Frame):
    """
    A wx.Panel for displaying and editing Categories
    """
    def __init__(self, parent, block_store, id=wx.ID_ANY, style=wx.EXPAND):
        #load from XRC, need to use two-stage create
        res = gui.XrcUtilities.XmlResource('./gui/xrc/TpclEditorFrame.xrc')
        pre = wx.PreFrame()
        res.LoadOnFrame(pre, parent, "editor")
        self.PostCreate(pre)

        self.block_store = block_store
        self.OnCreate()

    def OnCreate(self):
        self.SetSize((600, 400))

        #widgets
        self.code_stc = XRCCTRL(self, "code_stc")
        self.code_stc.Bind(wx.EVT_LEFT_UP, self.ContextMenuHandler)
        self.block_tree = XRCCTRL(self, "block_tree")
        self.block_tree.SetBlockstore(self.block_store)
        self.preview_ctrl = XRCCTRL(self, "preview_ctrl")
        self.block_tree.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnSelectionChanged)

        #buttons
        self.clear_button = XRCCTRL(self, "clear_button")
        self.Bind(wx.EVT_BUTTON, self.OnClear, self.clear_button)
        self.remove_button = XRCCTRL(self, "remove_button")
        self.Bind(wx.EVT_BUTTON, self.OnRemove, self.remove_button)
        self.save_button = XRCCTRL(self, "save_button")
        self.Bind(wx.EVT_BUTTON, self.OnSave, self.save_button)
        self.info_button = XRCCTRL(self, "info_button")
        self.Bind(wx.EVT_BUTTON, self.OnInfo, self.info_button)

        #fill the block_tree
        #tpcl.IO.LoadBlockIntoTree(self.block_tree)
        self.root_expression = None

        self.CreateQuickInsertMenu()

    def CreateQuickInsertMenu(self):
        self.quick_insert_menu = wx.Menu()
        submenus = [
            "Procedure Definitions", "Literal Expression",
            "Numerical Functions", "Flow Control"
        ]
        for sm in submenus:
            cat_id = self.block_store.FindCategory(sm)
            smenu = wx.Menu()
            for child_id in self.block_store.GetChildBlocks(cat_id):
                node = self.block_store.GetNode(child_id)
                mitem = smenu.Append(wx.ID_ANY, node.name)
                self.Bind(wx.EVT_MENU, MakeInserter(self, node.block), mitem)
            self.quick_insert_menu.AppendMenu(wx.ID_ANY, sm, smenu)

    def OnInfo(self, event):
        """\
        Opens a dialog without a parent for the moment
        """
        sel_id = self.block_tree.GetSelection()
        if sel_id.IsOk():
            block = self.block_tree.GetPyData(sel_id)
            if block:
                info_dialog = BlockInfoDialog(self, block.name, block.display,
                                              block.description)
                info_dialog.ShowModal()
        event.Skip()

    def OnClear(self, event):
        """\
        Clears the code window, deleting all unsaved
        changes.
        """
        self.code_stc.ClearAll()
        #for now we'll put the root expression back in place
        self.root_expression = None
        event.Skip()

    def OnRemove(self, event):
        """\
        Removes the current tpcl code block that is
        selected.
        """
        pos = self.code_stc.GetCurrentPos()
        try:
            self.root_expression.RemoveExpression(pos)
            self.code_stc.SetText(str(self.root_expression))
        except ValueError:
            #text in top level expression, get rid of it
            self.root_expression = None
            self.code_stc.ClearAll()
        event.Skip()

    def OnSave(self, event):
        """\
        Saves the current work.
        """
        event.Skip()

    def OnSelectionChanged(self, event):
        """\
        Selection change in the block tree
        We need to fill the preview control here
        """
        print "Handling selection changed event."
        sel_id = self.block_tree.GetSelection()
        if sel_id.IsOk():
            block = self.block_tree.GetPyData(sel_id)
            if block:
                self.preview_ctrl.SetValue(block.display)
            else:
                self.preview_ctrl.SetValue("")
        else:
            self.preview_ctrl.SetValue("")
        event.Skip()

    def OnInsert(self, event, block=None):
        """\
        Inserts the currently selected code block
        into the currently selected code socket.
        """
        pos = self.code_stc.GetCurrentPos()

        if not block:
            sel_id = self.block_tree.GetSelection()
            if sel_id.IsOk():
                block = self.block_tree.GetPyData(sel_id)

        if block:
            print "Trying to insert block..."
            try:
                #provide the OnInsert function of the block
                # access to us as a parent frame for when they
                # need to show a dialog
                parent_frame = self

                expression = TpclExpression(block)
                insert_ok = True
                if block.on_insert:
                    print "Trying to use OnInsert function of block"
                    exec(block.on_insert)
                    insert_ok = OnInsert(expression)

                if insert_ok:
                    if not self.root_expression:
                        self.root_expression = expression
                    else:
                        self.root_expression.InsertExpression(pos, expression)
                    self.code_stc.SetText(str(self.root_expression))

            except ValueError:
                print "Tried to insert in a place where there's no expansion point"
        event.Skip()

    def ContextMenuHandler(self, event):
        """\
        Processes a left click on the STC
        """
        event.Skip()
        print "Trying to show context menu at pos:", self.code_stc.GetCurrentPos(
        )
        try:
            if wx.GetMouseState().ControlDown():
                print "Trying to show popup menu..."
                menu = wx.Menu()

                offset = self.code_stc.GetCurrentPos()

                if not self.root_expression:
                    is_insertion_point = True
                    is_added_insertion_point = False
                    is_expansion_point = False
                else:
                    is_insertion_point = self.root_expression.IsInsertionPoint(
                        offset)[0]
                    is_added_insertion_point = self.root_expression.IsAddedInsertionPoint(
                        offset)[0]
                    is_expansion_point = self.root_expression.IsExpansionPoint(
                        offset)[0]

                print "is_insertion_point", is_insertion_point
                print "is_expansion_point", is_expansion_point

                sel_id = self.block_tree.GetSelection()
                if sel_id.IsOk():
                    block = self.block_tree.GetPyData(sel_id)
                else:
                    block = None

                #insert item
                insert_item = menu.Append(wx.ID_ANY, "Insert")
                self.Bind(wx.EVT_MENU, self.OnInsert, insert_item)
                #only enable if we're on an expansion point
                insert_item.Enable(block != None and is_insertion_point)

                #quick insert
                quick_insert = menu.AppendMenu(wx.ID_ANY, "Quick Insert...",
                                               self.quick_insert_menu)
                quick_insert.Enable(is_insertion_point)

                #remove item
                remove_item = menu.Append(wx.ID_ANY, "Remove")
                self.Bind(wx.EVT_MENU, self.OnRemove, remove_item)
                remove_item.Enable(
                    (not is_insertion_point and not is_expansion_point)
                    or is_added_insertion_point)

                #check for expansion menu
                if is_expansion_point:
                    exp_menu = wx.Menu()
                    i = 0
                    for option in self.root_expression.GetExpansionOptions(
                            offset):
                        opt_item = exp_menu.Append(wx.ID_ANY, option)
                        self.Bind(wx.EVT_MENU, MakeExpander(self, offset, i),
                                  opt_item)
                        i += 1
                    menu.AppendMenu(wx.ID_ANY, "Expansion Point...", exp_menu)

                self.code_stc.PopupMenu(menu, event.GetPosition())

        except ValueError:
            print "Index out of range..."

    def ShowModal(self):
        print "TPCLEE Showing itself Modally"
        self.MakeModal(True)
        self.old_top_window = wx.GetApp().GetTopWindow()
        wx.GetApp().SetTopWindow(self)
        self.Bind(wx.EVT_CLOSE, self.OnClose)
        self.Show(True)

    def OnClose(self, event):
        self.MakeModal(False)
        self.Unbind(wx.EVT_CLOSE)
        wx.GetApp().SetTopWindow(self.old_top_window)
        event.Skip()