예제 #1
0
    def __init__(self, parent, macro: Macro = None):

        tk.Toplevel.__init__(self, parent)
        self.attributes("-topmost", 1)

        self.title("Create a Macro")
        icon = GetResourcePath('.\\Resources\\keystone.ico')
        if (icon != None):
            self.iconbitmap(icon)
        self.protocol("WM_DELETE_WINDOW", self.OnClose)
        self.columnconfigure(0, weight=1)
        self.rowconfigure(0, weight=1)

        frame = KeystoneFrame(self)
        frame.columnconfigure(0, weight=0)
        frame.columnconfigure(1, weight=1, minsize='205')
        frame.rowconfigure(0, weight=1)
        frame.rowconfigure(1, weight=0)

        if (macro == None):
            macro = Macro("Name", [SlashCommand(repr="powexec_name power")])
        self.Editor = EditMacro(frame, macro)
        self.Editor.grid(column = 1, row = 0, rowspan=2, sticky='nsew')
        self.Close = KeystoneButton(frame)
        self.Close.configure(text="Close",  command=self.OnClose)
        self.Close.Color('red', 'black')
        self.Close.grid(column=0, row=1, sticky='nsew')
        self.Copy = KeystoneButton(frame, text="Copy to Clipboard", command=self.OnCopy)
        self.Copy.Color('green', 'black')
        self.Copy.grid(column=0, row=0, sticky='nsew')
        frame.grid(column=0, row=0, sticky='nsew')
예제 #2
0
    def __init__(self, parent, *args, **kwargs):

        tk.Toplevel.__init__(self, parent, *args, **kwargs)
        self.maxsize(324, 180)
        self.attributes("-toolwindow", 1)
        self.attributes("-topmost", 1)

        icon = GetResourcePath('.\\Resources\\keystone.ico')
        if (icon != None):
            self.iconbitmap(icon)

        self.title("About")

        frame = KeystoneFrame(self)

        #setup grid
        self.columnconfigure(0, weight=1, minsize=324)
        self.rowconfigure(0, weight=1, minsize=180)
        frame.columnconfigure(0, minsize=108)
        frame.columnconfigure(1, minsize=216)
        frame.rowconfigure(0, minsize=60)
        frame.rowconfigure(1, minsize=120)

        frame.grid(row=0, column=0, sticky='nsew')

        #logo
        imgPath = GetResourcePath('.\\Resources\\Keystone.png')
        if (imgPath != None):
            img = Image.open(imgPath)
            img = img.resize((54, 54))
            self.Logo = ImageTk.PhotoImage(img)
            logoLabel = KeystoneLabel(frame, image=self.Logo)
            logoLabel.grid(row=0, column=0, padx=3, pady=3)

        #name
        nameLabel = KeystoneLabel(frame,
                                  text='Keystone',
                                  font=(TEXT_FONT, LARGE_FONT_SIZE))
        nameLabel.grid(row=0, column=1, sticky='nw')
        subtextLabel = KeystoneLabel(frame,
                                     text='City of Heroes Keybind Editor')
        subtextLabel.grid(row=0, column=1, sticky='sw')

        #version
        versionPath = GetResourcePath('VERSION.txt')
        if (versionPath != None):
            file = open(versionPath, "r")
            try:
                version = file.read()
            finally:
                file.close()
            version = version.split("\n")
            versionLabel = KeystoneLabel(frame,
                                         text=version[0],
                                         font=(TEXT_FONT, LARGE_FONT_SIZE))
            versionLabel.grid(row=1, column=0, columnspan=2)
            dateLabel = KeystoneLabel(frame, text=version[1])
            dateLabel.grid(row=1, column=0, columnspan=2, sticky='s', pady=3)
예제 #3
0
class EditMacro(KeystoneFrame):

    def Load(self, macro: Macro):
        self.Name.set(macro.Name)
        self.Commands.Load(SlashCommandEditor, macro.Commands, SlashCommand(repr=DEFAULT_COMMAND))

    def Get(self) -> Macro:
        commands = [item.Item.Get() for item in self.Commands.Items]
        if (self.CommandOnly.get()):
            name = None
        else:
            name = self.Name.get()
        return Macro(name, commands)
    
    def __init__(self, parent, macro: Macro):
        KeystoneFrame.__init__(self, parent)

        #StringVar for Name
        self.Name = ""

        #List of commands view frame
        self.Commands = None

        #layout grid
        self.columnconfigure(0, weight=1, minsize=200)
        self.columnconfigure(1, weight=0)
        self.columnconfigure(2, weight=7)
        self.rowconfigure(0, weight=1)

        #add controls
        
        self.NameFrame = KeystoneFrame(self)
        self.NameFrame.columnconfigure(1, weight=1)
        self.NameFrame.columnconfigure(2, weight=0)
        self.NameFrame.rowconfigure(4, weight=1)
        self.NameFrame.grid(row=0, column=0, sticky='nsew') 

        self.CommandsFrame=KeystoneFrame(self)
        self.CommandsFrame.columnconfigure(0, weight=1)
        self.CommandsFrame.grid(row=0, column=2, sticky='nsew', padx="3", pady="3")
        
        self.Commands = FrameListView(self.CommandsFrame)
        self.Commands.grid(row=0, column=0, sticky='new')

        nameLabel = KeystoneLabel(self.NameFrame, anchor='nw', text="Name", width=5)
        nameLabel.grid(row=1, column=0, sticky="nw", padx="3", pady="3")
        self.Name = tk.StringVar()
        self.NameBox = KeystoneEntry(self.NameFrame, textvariable=self.Name)
        self.NameBox.grid(row=1, column=1, sticky="nsew", padx="3", pady="3")

        self.CommandOnly = tk.BooleanVar(value=False)
        self.CommandOnlyCheck = KeystoneCheckbutton(self.NameFrame, variable=self.CommandOnly)
        self.CommandOnlyCheck.grid(row=2, column=0, sticky="ne", padx="3", pady="3")
        commandOnlyLabel = KeystoneLabel(self.NameFrame, anchor='nw', text='Copy command only')
        commandOnlyLabel.grid(row=2, column=1, sticky="nw", padx="3", pady="3")
        
        self.Load(macro)
class KeystoneWizard(tk.Toplevel):
    def __init__(self,
                 parent,
                 title=None,
                 icon=None,
                 onBack=None,
                 onNext=None,
                 onClose=None,
                 *args,
                 **kwargs):

        #initialize
        tk.Toplevel.__init__(self, parent, *args, **kwargs)

        if (title == None):
            title = type(parent).__name__ + " Wizard"
        self.title(title)

        if (icon == None):
            icon = GetResourcePath('.\\Resources\\keystone.ico')
        if (icon != None):
            self.iconbitmap(icon)

        self.Frame = KeystoneFrame(self)

        self.Pages = None
        self.CurrentPage = None

        self.PageIndex = tk.IntVar(value=0)
        self.PageIndex.trace("w", self.ShowPage)

        #callbacks
        self.OnBackCallback = onBack
        self.OnNexCallback = onNext
        self.OnCloseCallback = onClose

        #setup grid
        self.rowconfigure(0, weight=1, minsize=200)
        self.columnconfigure(0, weight=1, minsize=400)
        self.Frame.columnconfigure(0, weight=0, minsize=50)
        self.Frame.columnconfigure(1, weight=1)
        self.Frame.columnconfigure(2, weight=0, minsize=50)
        self.Frame.columnconfigure(3, weight=1)
        self.Frame.columnconfigure(4, weight=0, minsize=50)
        self.Frame.rowconfigure(0, weight=1)
        self.Frame.rowconfigure(1, weight=0)

        #setup controls
        self.Frame.grid(row=0, column=0, sticky='nsew')

        self.Back = KeystoneButton(self.Frame,
                                   text="Back",
                                   command=self.OnBack)
        self.Back.Color('green', 'black')
        self.ShowBack = tk.BooleanVar(value=False)
        self.ShowBack.trace("w", self.OnShowBack)

        self.Next = KeystoneButton(self.Frame,
                                   text="Next",
                                   command=self.OnNext)
        self.Next.Color('green', 'black')
        self.ShowNext = tk.BooleanVar(value=False)
        self.ShowNext.trace("w", self.OnShowNext)

        self.Close = KeystoneButton(self.Frame,
                                    text="Close",
                                    command=self.OnClose)
        self.Close.Color('red', 'black')
        self.ShowClose = tk.BooleanVar(value=False)
        self.ShowClose.trace("w", self.OnShowClose)

    def LoadPages(self, pages: [KeystoneWizardPage]):
        if (self.CurrentPage != None):
            self.CurrentPage.grid_forget()
            self.CurrentPage = None
        self.Pages = pages
        for eachPage in pages:
            eachPage.Wizard = self
        self.PageIndex.set(0)

    def PageCount(self) -> int:
        if (self.Pages == None):
            return 0
        return len(self.Pages)

    def OnShowBack(self, *args):
        if (self.PageIndex.get() == 0):
            show = False
        else:
            show = self.ShowBack.get()
        if (show):
            self.Back.grid(column=0, row=1, sticky='nsew')
        else:
            self.Back.grid_forget()

    def OnShowNext(self, *args):
        if (self.PageIndex.get() == (self.PageCount() - 1)):
            show = False
        else:
            show = self.ShowNext.get()
        if (show):
            self.Next.grid(column=4, row=1, sticky='nsew')
        else:
            self.Next.grid_forget()

    def OnShowClose(self, *args):
        show = self.ShowClose.get()
        if (show):
            self.Close.grid(column=2, row=1, sticky='nsew')
        else:
            self.Close.grid_forget()

    def ShowPage(self, *args):

        if (self.PageCount() == 0):
            return

        #get index
        index = self.PageIndex.get()
        if (index >= self.PageCount()):
            index = self.PageCount() - 1
            self.PageIndex.set(index)
            return  #as set will callback due to trace
        elif (index < 0):
            index = 0
            self.PageIndex.set(index)
            return  #as set will callback due to trace

        #drop current page
        if (self.CurrentPage != None):
            self.CurrentPage.grid_forget()

        #show page and buttons
        page = self.Pages[index]
        page.grid(row=0, column=0, columnspan=5, sticky='nsew')
        self.CurrentPage = page
        self.ShowBack.set(page.AllowBack.get())
        self.ShowNext.set(page.AllowNext.get())
        self.ShowClose.set(page.AllowClose.get())

    def _onButton(self, callback, pageCallback, allowVar, showVar,
                  indexChange):
        if (pageCallback != None):
            pageCallback(self, self.CurrentPage)
        allow = allowVar.get()
        showVar.set(allow)
        index = self.PageIndex.get() + indexChange
        if (index > self.PageCount()):
            index = self.PageCount() - 1
        elif (index < 0):
            index = 0
        if (index != self.PageIndex.get()):
            self.PageIndex.set(index)
            if (callback != None):
                callback(self)

    def OnBack(self, *args):
        page = self.CurrentPage
        self._onButton(self.OnBackCallback, page.OnBack, page.AllowBack,
                       self.ShowBack, -1)

    def OnNext(self, *args):
        page = self.CurrentPage
        self._onButton(self.OnNexCallback, page.OnNext, page.AllowClose,
                       self.ShowClose, 1)

    def OnClose(self, *args):
        page = self.CurrentPage
        if (page.OnClose != None):
            page.OnClose(self)
        if (page.AllowClose.get()):
            self.destroy()
        if (self.OnCloseCallback != None):
            self.OnCloseCallback(self)
예제 #5
0
class EditBindFileCollection(KeystoneEditFrame):
    def SetEditedItem(self, *args):
        editor = args[0]
        item = self.viewFrame.GetEditedItem(editor)
        self.viewFrame.SetEdited(item, True)
        hasChildren = (not (self.viewFrame.Dictionary[KEY_CHAINS] == NONE))
        self.ShowTree.set(hasChildren)
        if (self.EditedItems == None):
            self.EditedItems = [editor]
        elif (not (editor in self.EditedItems)):
            self.EditedItems.append(editor)
        self.SetDirty()

    def ClearEditedItem(self, *args):
        editor = args[0]
        item = self.viewFrame.GetEditedItem(editor)
        self.viewFrame.SetEdited(item, False)
        if (self.EditedItems != None):
            if (editor in self.EditedItems):
                self.EditedItems.remove(editor)
                if (len(self.EditedItems) == 0):
                    self.EditedItems = None
                    self.SetClean()

    def selectItem(self, *args):
        self.selectedItem = self.viewFrame.Tree.focus()
        if (self.selectedItem == self.lastItem):
            return
        if (not self.viewFrame.Tree.HasTag(self.selectedItem, FILE_TAG)):
            self.lastItem = None
            if (self.editor != None):
                self.editor.grid_forget()
                self.editor = None
            return
        self.lastItem = self.selectedItem

        fileTag = self.viewFrame.Tree.GetTags(self.selectedItem)[1]
        editor = self.viewFrame.GetEditor(fileTag)
        if (self.editor != None):
            self.editor.grid_forget()
        if (editor != None):
            self.editor = editor
        else:
            bindFile = self.viewFrame.Get(fileTag)
            self.editor = EditBindFile(self.editFrame, bindFile)
            self.editor.OnSetDirty.append(self.SetEditedItem)
            self.editor.OnSetClean.append(self.ClearEditedItem)
            self.viewFrame.SetEditor(fileTag, self.editor)

        self.editor.grid(row=0, column=0, sticky='nsew')

    def OnShowTree(self, *args):
        value = self.ShowTree.get()
        if (value and (self._showingTree != True)):
            self.Pane.insert(0, self.viewFrame)
            self._showingTree = True
        elif ((not value) and (self._showingTree != False)):
            self.Pane.forget(self.viewFrame)
            self._showingTree = False

    def Reset(self):
        if (self.editor != None):
            self.editor.grid_forget()
        self.EditedItems = None
        self.FilePath = None
        self.viewFrame.Reset()
        self.ShowTree.set(False)

    def Load(self, bindFileCollection):
        self.Reset()
        self.FilePath = bindFileCollection.FilePath
        self.viewFrame.Load(bindFileCollection)
        self.viewFrame.SelectRoot()
        hasChildren = (not (self.viewFrame.Dictionary[KEY_CHAINS] == NONE))
        self.ShowTree.set(hasChildren)
        if ((self.FilePath != None) and os.path.exists(self.FilePath)):
            self.SetClean(self)
        else:
            self.SetDirty(self)

    def Get(self):
        return self.viewFrame.GetCollection()

    def New(self, defaults: bool = False):
        editor = EditBindFile(self.editFrame)
        editor.New(defaults)
        bindFile = editor.Get()
        collection = BindFileCollection(None, bindFile)
        self.Load(collection)

    def Open(self, fileName=None):
        if (fileName == None):
            options = {}
            filePath = self.FilePath
            if (filePath != None):
                options['initialfile'] = filePath
                options['initialdir'] = os.path.dirname(filePath)
            options['title'] = "Open Keybind File"
            options['filetypes'] = (("Text Files", "*.txt"), ("All Files",
                                                              "*.*"))
            options['defaultextension'] = "txt"
            options['multiple'] = False
            self.master.update()
            fileName = filedialog.askopenfilename(**options)
            self.master.update()

        if (fileName != ''):
            self.Reset()
            collection = BindFileCollection()
            collection.Load(fileName)
            self.Load(collection)

    def Save(self, promptForPath: bool = False):

        if (self.viewFrame.Dictionary == None):
            return

        currentFilePath = self.FilePath
        if (promptForPath or (currentFilePath == None)):
            options = {}
            options['initialfile'] = "keybinds.txt"
            options['title'] = "Save Keybind File As"
            options['filetypes'] = (("Text Files", "*.txt"), ("All Files",
                                                              "*.*"))
            options['defaultextension'] = "txt"
            self.master.update()
            filePath = filedialog.asksaveasfilename(**options)
            self.master.update()
            if (filePath == ''):
                return
        else:
            filePath = currentFilePath

        self.FilePath = os.path.abspath(filePath)

        collection = self.Get()
        collection.Save(filePath)
        self.Reset()
        self.Load(collection)

        if (self.SaveCallback != None):
            self.SaveCallback(self)

    def ImportBinds(self, filePath):

        if (self.editor == None):
            return
        importCollection = BindFileCollection()
        importCollection.Deserialize(filePath)
        boundFiles = importCollection.GetBoundFiles()
        if (((self.editor.FilePath == None) or
             (self.editor.FilePath == NEW_FILE)) and (len(boundFiles) > 0)):
            response = messagebox.askokcancel(
                'Path Needed For Linked Files',
                'You must choose a target path for this file to set paths for linked files.\n'
                + 'The paths will be set, but no files will be saved yet.')
            if (not response):
                return
            options = {}
            options['initialfile'] = "keybinds.txt"
            options['title'] = "Select Target Destination for Linked Files"
            options['filetypes'] = (("Keybind Files", "*.txt"), ("All Files",
                                                                 "*.*"))
            options['defaultextension'] = "txt"
            self.master.update()
            pointPath = filedialog.asksaveasfilename(**options)
            self.master.update()
            if (pointPath == ''):
                return False
            self.FilePath = pointPath
        else:
            pointPath = self.editor.FilePath

        importCollection.RepointFilePaths(pointPath)
        if (pointPath != None):
            self.editor.FilePath = pointPath
            self.editor.PathLabel.configure(text=self.editor.FilePath)
            self.FilePath = self.editor.FilePath
            self.viewFrame.Directory = os.path.dirname(self.editor.FilePath)
            self.viewFrame.Dictionary[PATH] = self.editor.FilePath

        boundFiles = importCollection.GetBoundFiles()
        if (len(boundFiles) > 0):
            #put them in the orphange so refresh can find them
            orphans = [{
                PATH: boundFile.FilePath,
                REPR: boundFile.__repr__(),
                EDITOR: None,
                SELECTED_TAG: False
            } for boundFile in boundFiles]
            self.viewFrame.GetOrphanage(True, orphans)

        for bind in importCollection.File.Binds:
            self.editor.NewBindCallback(True, bind)

    def __init__(self, parent, saveCallback=None):

        KeystoneEditFrame.__init__(self, parent)

        self.lastItem = None
        self.editor = None
        self.selectedItem = None
        self.EditedItems = None
        self.SaveCallback = saveCallback

        self.Pane = KeystonePanedWindow(self, orient=tk.HORIZONTAL)
        self.Pane.pack(fill=tk.BOTH, expand=1)

        self.viewFrame = BindFileCollectionView(self.Pane)
        self.viewFrame.Tree.OnSelect.append(self.selectItem)
        self.Pane.add(self.viewFrame)

        self.editFrame = KeystoneFrame(self.Pane,
                                       style='editStyle.TFrame',
                                       width=1000)
        self.editFrame.columnconfigure(0, weight=1)
        self.editFrame.rowconfigure(0, weight=1)
        self.Pane.add(self.editFrame)

        self._showingTree = None
        self.ShowTree = tk.BooleanVar(value=False)
        self.ShowTree.trace("w", self.OnShowTree)

        self.Reset()
class BindFileEditorWindow(tk.Tk):
    def _isOpenFile(self, path):
        if (self.Notebook.Items == None):
            return None
        thisPath = ComparableFilePath(path)
        for item in self.Notebook.Items:
            openPath = item.FilePath
            if (openPath == None):
                continue
            openPath = ComparableFilePath(openPath)

            if (thisPath == openPath):
                return item

        return None

    def NewTab(self, mode, path=None, bindFile=None):
        with self.TabLock:
            setDirty = False
            self.config(cursor="wait")
            self.update()
            try:
                if ((mode == "open") and (path != None)
                        and (self.Notebook.Items != None)):
                    if (self._isOpenFile(path) != None):
                        return
                self.Notebook.NewFrame("")
                editor = self.Notebook.SelectedFrame()
                if (mode == "open"):
                    editor.Open(fileName=path)
                    if (editor.FilePath == None):
                        self.Notebook.RemoveSelectedFrame()
                        return
                elif (mode == "new"):
                    editor.New(defaults=False)
                    if (bindFile != None):
                        editor.Load(bindFile)
                        setDirty = True
                elif (mode == "default"):
                    editor.New(defaults=True)
                self.SetTabName()
                if setDirty:
                    editor.SetDirty()
            finally:
                self.config(cursor="")
            self._showNotebook()
        print("Unlock")

    def SetTabName(self, editor=None):
        if (editor == None):
            editor = self.Notebook.SelectedFrame()
            if (editor == None):
                return
        else:
            tab = self.Notebook.GetTabNameFromItem(editor)
            self.Notebook.select(tab)

        filePath = editor.FilePath
        if (filePath == None):
            fileName = NEW_FILE
        else:
            fileName = GetFileName(filePath)
        self.Notebook.tab(self.Notebook.select(), text=fileName)

    def OnFileOpen(self):
        self.NewTab("open")

    def OnFileNew(self):
        self.NewTab("new")

    def OnFileNewDefaults(self):
        self.NewTab("default")

    def OnSaveCallback(self, editor, *args):
        self.SetTabName(editor=editor)

    def OnFileSave(self):
        collectionEditor = self.Notebook.SelectedFrame()
        if (collectionEditor == None):
            return
        editor = self.Notebook.SelectedFrame()
        if (editor == None):
            return
        editor.Save()

    def OnFileSaveAs(self):
        collectionEditor = self.Notebook.SelectedFrame()
        if (collectionEditor == None):
            return
        editor = self.Notebook.SelectedFrame()
        if (editor == None):
            return
        editor.Save(True)

    def CancelFromSavePrompt(self) -> bool:
        collectionEditor = self.Notebook.SelectedFrame()
        if (collectionEditor == None):
            return
        editor = self.Notebook.SelectedFrame()
        if (editor == None):
            return False
        if (editor.Dirty.get()):
            response = messagebox.askyesnocancel(
                "Edited File", "Save changes before proceeding?")
            if (response):
                self.OnFileSaveAs()
                if (editor.Dirty.get()):
                    #didn't save, abort
                    return True
            elif (response == None):
                return True
        return False

    def OnFileClose(self):
        collectionEditor = self.Notebook.SelectedFrame()
        if (collectionEditor == None):
            return
        editor = self.Notebook.SelectedFrame()
        if (editor == None):
            return
        if (self.CancelFromSavePrompt()):
            return
        self.Notebook.RemoveSelectedFrame()

    def OnDownloadFile(self):
        options = {}
        options['initialfile'] = "keybinds.txt"
        options['title'] = "Select File Destination"
        options['filetypes'] = (("Text Files", "*.txt"), ("All Files", "*.*"))
        options['defaultextension'] = "txt"
        self.update()
        filePath = filedialog.asksaveasfilename(**options)
        self.update()
        if (filePath == ''):
            return
        command = SlashCommand(name=SAVE_COMMAND,
                               text="\"%s\"" % os.path.abspath(filePath))
        self.clipboard_clear()
        self.clipboard_append("/" + str(command))
        response = messagebox.askokcancel(
            "Download from City of Heroes",
            "The command:\n\n" + "/%s\n\n" % str(command) +
            "has been copied to  the clipboard.\n\n" +
            "Paste and execute this command in the game to save the current keybinds to the selected location\n\n"
            + "Click OK to open the saved file.")
        if (response):
            self.NewTab("open", filePath)

    def OnUploadFile(self):
        collectionEditor = self.Notebook.SelectedFrame()
        if (collectionEditor == None):
            return
        editor = self.Notebook.SelectedFrame().editor
        if (editor == None):
            return
        if (self.CancelFromSavePrompt()):
            return
        if (editor.FilePath == None):
            return
        filePath = os.path.abspath(editor.FilePath)
        command = SlashCommand(name=LOAD_COMMAND,
                               text="\"%s\"" % os.path.abspath(filePath))
        self.clipboard_clear()
        self.clipboard_append("/" + str(command))
        messagebox.showinfo(
            "Upload to City of Heroes",
            "The command:\n\n" + "/%s\n\n" % str(command) +
            "has been copied to  the clipboard.\n\n" +
            "Paste and execute this command in the game to load the current keybinds from the selected location\n"
            +
            "You can add this command as a bind using the Add Upload Bind menu item."
        )

    def OnAddUploadBind(self):
        collectionEditor = self.Notebook.SelectedFrame()
        if (collectionEditor == None):
            return
        editor = self.Notebook.SelectedFrame().editor
        if (editor == None):
            return
        if ((editor.FilePath == None) and self.CancelFromSavePrompt()):
            return
        if (editor.FilePath == None):
            return
        editor.AddUploadBind()

    def OnClosing(self):
        if (self.Notebook.Dirty == True):
            response = messagebox.askyesnocancel(
                "Edited Files", "Save all changes before closing?")
            if (response):
                self.OnSaveAll()
            elif (response == None):
                return
        self.destroy()

    def OnSaveAll(self):
        if (self.Notebook.Dirty == True):
            if (self.Notebook.Items != None):
                for editor in self.Notebook.Items:
                    if editor.Dirty.get():
                        editor.Save()

    def OnCloseAll(self):
        while ((self.Notebook.Items != None)
               and (len(self.Notebook.Items) > 0)):
            self.CancelFromSavePrompt()
            self.Notebook.RemoveSelectedFrame()

    def _getBoundFilesSource(self):
        return [e.Get() for e in self.Notebook.Items if e.FilePath != None]

    def _onSelectCallback(self, binds, *args):

        editor = self.Notebook.SelectedFrame().editor
        bindFilePath = editor.FilePath
        options = {}
        options['initialfile'] = "keybinds.kst"
        options['title'] = "Select File Destination"
        options['filetypes'] = (("Keybind Export Files", "*.kst"),
                                ("All Files", "*.*"))
        options['defaultextension'] = "kst"
        self.update()
        filePath = filedialog.asksaveasfilename(**options)
        self.update()
        if (filePath == ''):
            return False

        bindFile = BindFile(binds, filePath=bindFilePath)
        boundFilesSource = self._getBoundFilesSource()
        bindFileCollection = BindFileCollection()
        bindFileCollection.Load(bindFilePath,
                                bindFile=bindFile,
                                boundFilesSource=boundFilesSource)
        bindFileCollection.Serialize(filePath)

        return True

    def OnImportBinds(self):
        collectionEditor = self.Notebook.SelectedFrame()
        if (collectionEditor == None):
            return
        bindFileEditor = self.Notebook.SelectedFrame().editor
        if (bindFileEditor == None):
            return
        if (self.CancelFromSavePrompt()):
            return

        options = {}

        options['title'] = "Open Keybind Export File"
        options['filetypes'] = (("Keybind Export Files", "*.kst"),
                                ("All Files", "*.*"))
        options['defaultextension'] = "kst"
        options['multiple'] = False
        self.update()
        fileName = filedialog.askopenfilename(**options)
        self.update()
        if (fileName == ''):
            return

        collectionEditor.ImportBinds(fileName)
        self.SetTabName(collectionEditor)

    def OnExportBinds(self):
        collectionEditor = self.Notebook.SelectedFrame()
        if (collectionEditor == None):
            return
        editor = self.Notebook.SelectedFrame().editor
        if (editor == None):
            return
        if (self.CancelFromSavePrompt()):
            return
        editor.OnSelectCallback = self._onSelectCallback
        editor.SetSelectMode(not editor.SelectMode)

    def OnCreateMacro(self):
        EditMacroWindow(self)

    def OnPredefinedBindsCallback(self, importWindow, filePath):
        collectionEditor = self.Notebook.SelectedFrame()
        if (collectionEditor == None):
            return
        bindFileEditor = self.Notebook.SelectedFrame().editor
        if (bindFileEditor == None):
            return
        if (self.CancelFromSavePrompt()):
            return

        collectionEditor.ImportBinds(filePath)
        self.SetTabName(collectionEditor)

    def AddCommand(self, menu: tk.Menu, frame, label, command):
        menu.add_command(label=label, command=command)
        KeystoneButton(frame, text=label, command=command).pack(anchor='nw',
                                                                side=tk.LEFT)

    def _openLinkedFileCallback(self, path):
        if not self.SuppressCallback:
            self.NewTab("open", path)

    def _showNotebook(self):
        if (not self.ShowingNotebook):
            self.Notebook.pack(fill=tk.BOTH, expand=True, side=tk.TOP)
            self.FirstFrame.pack_forget()
            self.ShowingNotebook = True

    def __init__(self, *args, **kwargs):

        tk.Tk.__init__(self, *args, **kwargs)

        win = self
        win.title("Keystone")
        icon = GetResourcePath('.\\Resources\\keystone.ico')
        if (icon != None):
            win.iconbitmap(icon)

        speedBar = KeystoneFrame(win)
        speedBar.config(height=45)
        speedBar.pack(anchor='n', fill=tk.X, expand=False, side=tk.TOP)

        menu = tk.Menu(win)

        fileMenu = tk.Menu(menu, tearoff=0)
        self.AddCommand(menu=fileMenu,
                        frame=speedBar,
                        label="Open",
                        command=self.OnFileOpen)
        self.AddCommand(menu=fileMenu,
                        frame=speedBar,
                        label="New (Empty)",
                        command=self.OnFileNew)
        self.AddCommand(menu=fileMenu,
                        frame=speedBar,
                        label="New (Defaults)",
                        command=self.OnFileNewDefaults)
        self.AddCommand(menu=fileMenu,
                        frame=speedBar,
                        label="Save",
                        command=self.OnFileSave)
        self.AddCommand(menu=fileMenu,
                        frame=speedBar,
                        label="Save As...",
                        command=self.OnFileSaveAs)
        fileMenu.add_command(label="Save All", command=self.OnSaveAll)
        self.AddCommand(menu=fileMenu,
                        frame=speedBar,
                        label="Close",
                        command=self.OnFileClose)
        fileMenu.add_command(label="Close All", command=self.OnCloseAll)
        menu.add_cascade(label="File", menu=fileMenu)

        cohMenu = tk.Menu(menu, tearoff=0)
        cohMenu.add_command(label="Download File", command=self.OnDownloadFile)
        cohMenu.add_command(label="Upload File", command=self.OnUploadFile)
        cohMenu.add_command(label="Create Macro", command=self.OnCreateMacro)
        menu.add_cascade(label="Game Commands", menu=cohMenu)

        importExportMenu = tk.Menu(menu, tearoff=0)
        importExportMenu.add_command(label="Import Binds",
                                     command=self.OnImportBinds)
        importExportMenu.add_command(label="Export Binds",
                                     command=self.OnExportBinds)
        importExportMenu.add_command(label="Add Upload Bind",
                                     command=self.OnAddUploadBind)
        importExportMenu.add_command(
            label="Predefined Binds...",
            command=lambda parent=win, callback=self.OnPredefinedBindsCallback:
            ShowSelectKeybindImportWindow(parent, importCallback=callback))
        menu.add_cascade(label="Import\\Export", menu=importExportMenu)

        helpMenu = tk.Menu(menu, tearoff=0)
        helpMenu.add_command(
            label='Getting Started',
            command=lambda parent=win: ShowWalkthrough(parent))
        helpMenu.add_command(label='Import and Export',
                             command=lambda parent=win: ShowWalkthrough(
                                 parent,
                                 title="Import and Export Walkthrough",
                                 walkthrough=IMPORT_EXPORT_WALKTHROUGH))
        helpMenu.add_command(
            label='Collections and Loaded Files',
            command=lambda parent=win: ShowWalkthrough(
                parent,
                title="Collections and Loaded Files Walkthrough",
                walkthrough=COLLECTIONS_AND_KEYCHAINS_WALKTHROUGH,
                endPages=COLLECTIONS_AND_KEYCHAINS_WALKTHROUGH_END_PAGES))
        self.AddCommand(menu=helpMenu,
                        frame=speedBar,
                        label="About",
                        command=lambda parent=win: ShowHelpAbout(parent))
        menu.add_cascade(label='Help', menu=helpMenu)

        SetOpenLinkedFileCallback(self._openLinkedFileCallback)

        self.FirstFrame = KeystoneFrame(win)
        self.FirstFrame.columnconfigure(0, weight=1, minsize=800)
        self.FirstFrame.rowconfigure(0, weight=1, minsize=400)
        walkthroughButton = KeystoneButton(
            self.FirstFrame,
            text='Intro Walkthrough',
            command=lambda parent=win: ShowWalkthrough(parent))
        walkthroughButton.Color('lightskyblue', 'black')
        walkthroughButton.configure(relief=tk.RAISED)
        walkthroughButton.grid()
        self.FirstFrame.pack(fill=tk.BOTH, expand=True, side=tk.TOP)

        self.Notebook = FrameNotebook(win, EditBindFileCollection,
                                      [self.OnSaveCallback])
        self.ShowingNotebook = False
        self.SuppressCallback = False

        win.config(menu=menu, width=800, height=400)

        win.protocol("WM_DELETE_WINDOW", self.OnClosing)

        self.TabLock = threading.Lock()
예제 #7
0
class BindEditor(KeystoneEditFrame):

    DELETE_TEXT = 'UNBIND'
    DELETE_COLOR = 'black'
    DELETE_TEXT_COLOR = 'red'
    DELETE_STYLE = tk.FLAT

    ASSIGN_TEXT = 'BIND'
    UNASSIGN_TEXT = 'Unassign Bind'
    UNASSIGN_MESSAGE = 'Include no assignment?  Use "nop" to  assign a key to do nothing.  Use /unbind <key> to restore a default in the UI'
    DEFAULT_TEXT = 'Default Bind'
    DEFAULT_COLOR = 'yellow'
    DEFAULT_TEXT_COLOR = 'black'
    CANCEL_TEXT = 'Cancel'
    ASSIGN_COLOR = 'black'
    ASSIGN_TEXT_COLOR = 'green'

    def SetKeyDescription(self, keyVar: tk.StringVar, descVar: tk.StringVar,
                          list):
        keyName = keyVar.get()
        key = MatchKeyName(keyName, list)
        if (key != None):
            desc = key[2]
            altname = key[1]
            if ((desc == '') and (altname != '')):
                desc = altname
            descVar.set(desc)
        else:
            descVar.set('')

    def SelectKey(self, *args):
        self.SetKeyDescription(self.Key, self.KeyDescription, KEY_NAMES)

    def SelectChord(self, *args):
        self.SetKeyDescription(self.Chord, self.ChordDescription, CHORD_KEYS)

    def AssignCommand(self, *args):
        model = Bind(key=self.Key.get(),
                     chord=self.Chord.get(),
                     commands=[SlashCommand(repr=DEFAULT_COMMAND)])
        self.Load(model)
        self.SetDirty()

    def UnassignCommand(self, *args):
        text = args[0]
        if (text == self.UNASSIGN_TEXT):
            self.ShowCommands.set(False)
            self.SetDirty()
        elif (text == self.DEFAULT_TEXT):
            bind = GetDefaultBindForKey(self.Key.get(), self.Chord.get())
            self.Commands.Load(SlashCommandEditor, bind.Commands,
                               SlashCommand(repr=DEFAULT_COMMAND))
            self.ShowCommands.set(True)
            self.SetDirty()
        else:  #Cancel
            self.ShowCommands.set(True)

    def OnDelete(self, *args):
        self.CommandsFrame.grid_forget()
        self.Delete.grid_forget()
        buttons = [self.UNASSIGN_TEXT, self.DEFAULT_TEXT, self.CANCEL_TEXT]
        colors = [[self.DELETE_TEXT_COLOR, self.DELETE_COLOR],
                  [self.DEFAULT_COLOR, self.DEFAULT_TEXT_COLOR],
                  [self.ASSIGN_TEXT_COLOR, self.ASSIGN_COLOR]]
        results = [self.UNASSIGN_TEXT, self.DEFAULT_TEXT, self.CANCEL_TEXT]
        commands = [
            self.UnassignCommand, self.UnassignCommand, self.UnassignCommand
        ]
        unassignPrompt = KeystonePromptFrame(self,
                                             self.UNASSIGN_MESSAGE,
                                             buttons=buttons,
                                             colors=colors,
                                             results=results,
                                             commands=commands)
        unassignPrompt.grid(row=0, column=1, sticky='nsew')

    def OnShowCommands(self, *args):
        show = self.ShowCommands.get()
        if (show):
            self.Assign.grid_forget()
            self.Delete.grid(row=0, column=1, sticky='nsw')
            self.CommandsFrame.grid(row=0,
                                    column=2,
                                    sticky='nsew',
                                    padx="3",
                                    pady="3")
        else:
            self.Assign.grid(row=0, column=1, sticky='nsw')
            self.CommandsFrame.grid_forget()
            self.Delete.grid_forget()

    def OnShowTextEditor(self, *args):
        show = self.ShowTextEditor.get()
        if (show):
            self.Assign.grid_forget()
            self.Delete.grid_forget()
            self.KeyFrame.grid_forget()
            self.CommandsFrame.grid_forget()
            self.UIToTextButton.grid_forget()
            self.UnlockKeysButton.grid_forget()
            self.TextFrame.grid(row=0,
                                column=0,
                                rowspan="2",
                                columnspan="3",
                                sticky='nsew')
        else:
            self.TextFrame.grid_forget()
            self.KeyFrame.grid(row=0, column=0, sticky='nsew')
            if (self._lockKey):
                self.UIToTextButton.grid(row=1,
                                         column=1,
                                         columnspan="2",
                                         sticky="nsew",
                                         padx="3",
                                         pady="3")
                self.UnlockKeysButton.grid(row=1, column=0, sticky="sw")
            else:
                self.UIToTextButton.grid(row=1,
                                         column=0,
                                         columnspan="3",
                                         sticky="nsew",
                                         padx="3",
                                         pady="3")
            self.OnShowCommands()

    def UnlockKeys(self, unlock=True):
        if unlock:
            self._lockKey = False
            self.KeyBox.grid(row=1,
                             column=1,
                             sticky="nsew",
                             padx="3",
                             pady="3")
            self.ChordBox.grid(row=3,
                               column=1,
                               sticky="nsew",
                               padx="3",
                               pady="3")
            self.KeyValue.grid_forget()
            self.ChordValue.grid_forget()
            self.UnlockKeysButton.grid_forget()
        else:
            self._lockKey = True
            self.KeyBox.grid_forget()
            self.ChordBox.grid_forget()
            self.KeyValue.grid(row=1,
                               column=1,
                               sticky="nsew",
                               padx="3",
                               pady="3")
            self.ChordValue.grid(row=3,
                                 column=1,
                                 sticky="nsew",
                                 padx="3",
                                 pady="3")

    def Load(self, bind: Bind):
        self.Loading = True
        try:
            if (self._lockKey):
                self.TextEntry.SetText(bind.GetCommands())
            else:
                self.TextEntry.SetText(bind.__repr__())
            self.SynchTextToUI()
        finally:
            self.Loading = False
        self.SetClean(self)

    def SynchTextToUI(self):
        key = self.Key.get()
        chord = self.Chord.get()
        text = self.TextEntry.GetText()
        if (self._lockKey):
            text = "%s %s" % (FormatKeyWithChord(key, chord), text)
        bind = Bind(repr=text)
        if (key != bind.Key):
            self.Key.set(bind.Key)
        if (chord != bind.Chord):
            self.Chord.set(bind.Chord)
        if (bind.Commands != None):
            self.Commands.Load(SlashCommandEditor, bind.Commands,
                               SlashCommand(repr=DEFAULT_COMMAND))
            self.ShowCommands.set(True)
        else:
            self.ShowCommands.set(False)
        self.ShowTextEditor.set(False)

    def SynchUIToText(self):
        bind = self.GetBindFromUI()
        if (self._lockKey):
            self.TextEntry.SetText(bind.GetCommands())
        else:
            self.TextEntry.SetText(bind)
        self.ShowTextEditor.set(True)

    def GetBindFromUI(self) -> Bind:
        bind = Bind()
        if (self.ShowCommands.get()):
            bind.Commands = [item.Item.Get() for item in self.Commands.Items]
        else:
            bind.Commands = None
        bind.Key = self.Key.get()
        bind.Chord = self.Chord.get()
        return bind

    def Get(self) -> Bind:
        if (self.ShowTextEditor.get()):
            self.SynchTextToUI()
        model = self.GetBindFromUI()
        return model

    def __init__(self, parent, bind: Bind, lockKey=False, dirty=False):
        KeystoneEditFrame.__init__(self, parent)

        #StringVar for Key
        self.Key = None

        #StringVar for Chord
        self.Chord = None

        #StringVar for Key Description
        self.KeyDescription = None

        #StringVar for Chord Description
        self.ChordDescription = None

        #List of commands view frame
        self.Commands = None

        #Indicates keys cannot be edited
        self._lockKey = lockKey

        #layout grid
        self.columnconfigure(0, weight=1, minsize=200)
        self.columnconfigure(1, weight=0)
        self.columnconfigure(2, weight=7)
        self.rowconfigure(0, weight=1)

        #add controls

        self.KeyFrame = KeystoneFrame(self)
        self.KeyFrame.columnconfigure(1, weight=1)
        self.KeyFrame.columnconfigure(2, weight=0)
        self.KeyFrame.rowconfigure(4, weight=1)

        self.CommandsFrame = KeystoneFrame(self)
        self.CommandsFrame.columnconfigure(0, weight=1)

        self.Commands = FrameListView(self.CommandsFrame)
        self.Commands.OnSetDirty.append(self.SetDirty)
        self.Commands.grid(row=0, column=0, sticky='new')

        self.TextFrame = KeystoneFrame(self)
        self.TextFrame.rowconfigure(0, weight=1, minsize='55')
        self.TextFrame.columnconfigure(0, weight=1, minsize='405')

        self.Delete = tk.Button(self,
                                text=self.DELETE_TEXT,
                                background=self.DELETE_COLOR,
                                foreground=self.DELETE_TEXT_COLOR,
                                font=(TEXT_FONT, 7, "bold"),
                                relief=self.DELETE_STYLE,
                                width=1,
                                wraplength=1,
                                command=self.OnDelete)

        self.Assign = tk.Button(self,
                                text=self.ASSIGN_TEXT,
                                background=self.ASSIGN_COLOR,
                                foreground=self.ASSIGN_TEXT_COLOR,
                                font=(TEXT_FONT, 7, "bold"),
                                relief=self.DELETE_STYLE,
                                width=1,
                                wraplength=1,
                                command=self.AssignCommand)

        self.UIToTextButton = KeystoneButton(self,
                                             text="Edit As Text",
                                             command=self.SynchUIToText)

        keyLabel = KeystoneLabel(self.KeyFrame,
                                 anchor='nw',
                                 text="Key",
                                 width=5)
        keyLabel.grid(row=1, column=0, sticky="nw", padx="3", pady="3")
        self.Key = tk.StringVar()
        self.KeyValue = KeystoneLabel(self.KeyFrame,
                                      anchor='nw',
                                      textvariable=self.Key,
                                      width=5)
        self.KeyBox = KeystoneKeyCombo(self.KeyFrame,
                                       textvariable=self.Key,
                                       values=" ".join(
                                           [c[0] for c in KEY_NAMES]))
        self.Key.trace("w", self.SelectKey)

        self.KeyDescription = tk.StringVar()
        keyDescription = KeystoneLabel(self.KeyFrame,
                                       anchor="nw",
                                       textvariable=self.KeyDescription,
                                       wraplength=200)
        keyDescription.grid(row=2,
                            column=0,
                            columnspan=2,
                            sticky="nsew",
                            padx="3",
                            pady="3")

        self.Key.set(bind.Key)
        self.Key.trace("w", self.SetDirty)

        chordLabel = KeystoneLabel(self.KeyFrame,
                                   anchor='nw',
                                   text="Chord",
                                   width=5)
        chordLabel.grid(row=3, column=0, sticky="nw", padx="3", pady="3")
        self.Chord = tk.StringVar()
        self.ChordValue = KeystoneLabel(self.KeyFrame,
                                        anchor='nw',
                                        textvariable=self.Chord,
                                        width=5)
        self.ChordBox = KeystoneKeyCombo(self.KeyFrame,
                                         textvariable=self.Chord,
                                         values=" ".join(
                                             [c[0] for c in CHORD_KEYS]))
        self.Chord.trace("w", self.SelectChord)

        self.ChordDescription = tk.StringVar()
        chordDescription = KeystoneLabel(self.KeyFrame,
                                         anchor="nw",
                                         textvariable=self.ChordDescription,
                                         wraplength=200)
        chordDescription.grid(row=4,
                              column=0,
                              columnspan=2,
                              sticky="nsew",
                              padx="3",
                              pady="3")

        self.Chord.set(bind.Chord)
        self.Chord.trace("w", self.SetDirty)

        self.UnlockKeysButton = KeystoneButton(self,
                                               text="Change Assigned Key",
                                               command=self.UnlockKeys)
        self.UnlockKeysButton.Color(FOREGROUND, BACKGROUND)

        self.ShowCommands = tk.BooleanVar()
        self.ShowCommands.trace("w", self.OnShowCommands)

        self.TextEntry = KeystoneTextEntry(self.TextFrame, height=5)
        self.TextEntry.grid(row=0, column=0, sticky="nsew", padx="3", pady="3")
        self.TextEntry.bind("<Key>", self.SetDirty)

        self.ShowTextEditor = tk.BooleanVar()
        self.ShowTextEditor.set(False)
        self.ShowTextEditor.trace("w", self.OnShowTextEditor)

        self.TextToUIButton = KeystoneButton(self.TextFrame,
                                             text="Editor",
                                             command=self.SynchTextToUI)
        self.TextToUIButton.grid(row=1,
                                 column=0,
                                 sticky="nsew",
                                 padx="3",
                                 pady="3")

        self.OnShowTextEditor()
        self.UnlockKeys(not lockKey)

        self.Load(bind)
        self.Dirty.set(dirty)