""" I really wish tkinter had native support for Drag and Drop. But they don't. So everything here is painfully manual. """ import tkinter as tk import tkinter.font as tkFont from peld import settings class LabelSettingsFrame(tk.Frame): text = {"dpsOut": "DPS Out:", "dpsIn": "DPS In:", "logiOut": "Logi Out:", "logiIn": "Logi In:", "capTransfered": "Cap Out:", "capRecieved": "Cap In:", "capDamageOut": "Cap Dmg Out:", "capDamageIn": "Cap Dmg In:", "mining": "Mining:"} def __init__(self, parent, mainWindow, **kwargs): tk.Frame.__init__(self, parent, **kwargs) self.parent = parent self.mainWindow = mainWindow self.columnconfigure(2, weight=1) self.gridColumns = settings.getLabelColumns() self.labels = settings.getLabels() tk.Label(self, text="Labels on the left grid will be attached to the left side of the window.\n" + "Labels on the right grid will be attached to the right side of the window.\n\n" + "You can drag and drop labels to move them to a different position in the grid." ).grid(row="0", column="1", columnspan="5", pady=10) tk.Label(self, text="Use the arrows to move columns from one side of the window to another." ).grid(row="3", column="1", columnspan="5") tk.Label(self, text="The number box represents how many decimal places the label will use. 0 is no decimal places.\n" + "The checkbox is to represent the number in thousands.\n\n" + "For instance, if you choose '3' decimals, and check the box, the number 1,234 will show as 1.234K" ).grid(row="100", column="1", columnspan="5", pady=10) tk.Frame(self, height="1", width="10").grid(row="1",column="2") self.makeArrowButtons() self.makeGrids() def makeGrids(self): self.gridFrameLeft = tk.Frame(self) self.gridListLeft = [[self.makeGridBlock(self.gridFrameLeft, row, i) for row in range(8)] for i in range(self.gridColumns[0])] self.gridFrameLeft.grid(row="5", column="1", padx="10") self.gridFrameRight = tk.Frame(self) self.gridListRight = [[self.makeGridBlock(self.gridFrameRight, row, i) for row in range(8)] for i in range(self.gridColumns[1])] self.gridFrameRight.grid(row="5", column="3", padx="10") for item, entries in self.labels.items(): row = entries["row"] column = entries["column"] title = self.text[item] try: GridEntry(self.gridListLeft[column][row], title, entries["decimalPlaces"], entries["inThousands"]) except IndexError: column = column - len(self.gridListLeft) GridEntry(self.gridListRight[column][row], title, entries["decimalPlaces"], entries["inThousands"]) def makeArrowButtons(self): leftButton = tk.Canvas(self, width=15, height=15) leftButton.create_polygon(1,1,15,8,1,15, fill="black") leftButton.grid(row="4", column="1", sticky="e") leftButton.bind("<Button-1>", self.moveRowRight) rightButton = tk.Canvas(self, width=15, height=15) rightButton.create_polygon(15,15,1,8,15,1, fill="black") rightButton.grid(row="4", column="3", sticky="w") rightButton.bind("<Button-1>", self.moveRowLeft) def moveRowRight(self, event): if len(self.gridListLeft) == 0: return self.gridColumns[0] -= 1 self.gridColumns[1] += 1 self.saveLabels() self.gridFrameLeft.destroy() self.gridFrameRight.destroy() self.makeGrids() def moveRowLeft(self, event): if len(self.gridListRight) == 0: return self.gridColumns[0] += 1 self.gridColumns[1] -= 1 self.saveLabels() self.gridFrameLeft.destroy() self.gridFrameRight.destroy() self.makeGrids() def saveLabels(self): columnAdder = 0 for gridFrame in [self.gridListLeft, self.gridListRight]: for column, gridColumn in enumerate(gridFrame): for row, gridBox in enumerate(gridColumn): gridBoxChildren = gridBox.winfo_children() if len(gridBoxChildren) > 0: gridEntry = gridBoxChildren[0] for name, text in self.text.items(): if text == gridEntry.getLabelText(): self.labels[name]["row"] = row self.labels[name]["column"] = column + columnAdder self.labels[name]["decimalPlaces"] = gridEntry.getListboxValue() self.labels[name]["inThousands"] = gridEntry.getCheckboxValue() columnAdder += len(gridFrame) def makeGridBlock(self, parent, row, column): frame = tk.Frame(parent, width="100", height="25", relief="ridge", borderwidth=1) frame.columnconfigure(0,weight=1) frame.grid(row=row, column=column, sticky="news") return frame def moveGridEntry(self, title, decimalPlaces, inThousands, gridBox, parent): oldBox = self._nametowidget(parent.winfo_parent()) if len(gridBox.winfo_children()) > 0 and not gridBox.winfo_children()[0] == parent: #this means we need to swap boxes gridEntry = gridBox.winfo_children()[0] parent.destroy() GridEntry(oldBox, gridEntry.getLabelText(), gridEntry.getListboxValue(), gridEntry.getCheckboxValue()) gridEntry.destroy() else: parent.destroy() oldBox.configure(width=100) GridEntry(gridBox, title, decimalPlaces, inThousands) def doSettings(self): self.saveLabels() labelColumns = [len(self.gridListLeft), len(self.gridListRight)] return {"labels": self.labels, "labelColumns": labelColumns} class GridEntry(tk.Frame): def __init__(self, parent=None, title="", decimalPlaces=0, inThousands=0, *args, **kwargs): tk.Frame.__init__(self, parent, *args, **kwargs) gridFrame = self._nametowidget(parent.winfo_parent()) self.parent = self._nametowidget(gridFrame.winfo_parent()) self.grid(row="0", column="0", sticky="ew") self.columnconfigure(0,weight=1) self.singleLabel = singleLabel = tk.Label(self, text=title) singleLabel.grid(row="0",column="0", sticky="ew") self.listbox = listbox = tk.Spinbox(self, from_=0, to=9, width=1, borderwidth=1, highlightthickness=0) listbox.delete(0,tk.END) listbox.insert(0,decimalPlaces) listbox.grid(row="0", column="1") checkboxValue = tk.IntVar() checkboxValue.set(inThousands) self.checkbox = checkbox = tk.Checkbutton(self, text="K", variable=checkboxValue, borderwidth=0, highlightthickness=0) checkbox.var = checkboxValue checkbox.grid(row="0", column="2") singleLabel.bind("<Button-1>", lambda e:self.dragStart(e, listbox, checkbox)) def dragStart(self, event, listbox, checkbox): listbox.grid_remove() checkbox.grid_remove() x = self.winfo_pointerx()-event.x y = self.winfo_pointery()-event.y self.floatingWindow = FloatingWindow(self, width=self.winfo_width()) self.floatingWindow.geometry("+%s+%s" % (x, y)) self.x = event.x self.y = event.y self.floatingWindow.StartMove(event) event.widget.grab_set() event.widget.bind("<ButtonRelease-1>", lambda e:self.dragStop(e, listbox, checkbox)) event.widget.bind("<Motion>", self.dragMove) event.widget.grid_remove() def dragStop(self, event, listbox, checkbox): self.floatingWindow.StopMove(event) self.x = None self.y = None event.widget.unbind("<ButtonRelease-1>") event.widget.unbind("<Motion>") event.widget.grab_release() pointerx = self.winfo_pointerx() pointery = self.winfo_pointery() for gridSection in [self.parent.gridListLeft, self.parent.gridListRight]: for gridRow in gridSection: for gridBox in gridRow: if (pointerx >= gridBox.winfo_rootx() and pointerx <= gridBox.winfo_rootx()+gridBox.winfo_width() and pointery >= gridBox.winfo_rooty() and pointery <= gridBox.winfo_rooty()+gridBox.winfo_height()): parentName = event.widget.winfo_parent() parent = event.widget._nametowidget(parentName) self.parent.moveGridEntry(title=event.widget["text"], decimalPlaces=listbox.get(), inThousands=checkbox.var.get(), gridBox=gridBox, parent=parent) return event.widget.grid() listbox.grid() checkbox.grid() def dragMove(self, event): event.x = event.x - self.x event.y = event.y - self.y self.x += event.x self.y += event.y self.floatingWindow.OnMotion(event) def getLabelText(self): return self.singleLabel["text"] def getListboxValue(self): return self.listbox.get() def getCheckboxValue(self): return self.checkbox.var.get() class FloatingWindow(tk.Toplevel): def __init__(self, gridEntry=None, width=100, *args, **kwargs): tk.Toplevel.__init__(self, *args, **kwargs) self.overrideredirect(True) self.wm_attributes("-topmost", True) self.columnconfigure(0, weight=1) GridEntry(self, gridEntry.getLabelText(), gridEntry.getListboxValue(), gridEntry.getCheckboxValue()).grid(row="0", column="0") self.update_idletasks() self.geometry("%sx%s" % (width, self.winfo_height())) def StartMove(self, event): self.x = event.x self.y = event.y def StopMove(self, event): self.x = None self.y = None self.destroy() def OnMotion(self, event): x = self.winfo_x() + event.x y = self.winfo_y() + event.y self.geometry("+%s+%s" % (x, y))