def addToDialog( self, gridPosition ): "Add this to the dialog." #http://www.pythonware.com/library/tkinter/introduction/x5453-patterns.htm self.root = gridPosition.master gridPosition.increment() scrollbar = HiddenScrollbar( gridPosition.master ) self.listbox = settings.Tkinter.Listbox( gridPosition.master, selectmode = settings.Tkinter.SINGLE, yscrollcommand = scrollbar.set ) self.listbox.bind( '<ButtonRelease-1>', self.buttonReleaseOne ) gridPosition.master.bind( '<FocusIn>', self.focusIn ) scrollbar.config( command = self.listbox.yview ) self.listbox.grid( row = gridPosition.row, column = 0, sticky = settings.Tkinter.N + settings.Tkinter.S ) scrollbar.grid( row = gridPosition.row, column = 1, sticky = settings.Tkinter.N + settings.Tkinter.S ) self.setStateToValue() self.repository.saveListenerTable[ 'updateProfileSaveListeners' ] = updateProfileSaveListeners
def addToDialog( self, gridPosition ): "Add this to the dialog." #http://www.pythonware.com/library/tkinter/introduction/x5453-patterns.htm self.root = gridPosition.master gridPosition.increment() from fabmetheus_utilities.hidden_scrollbar import HiddenScrollbar scrollbar = HiddenScrollbar( gridPosition.master ) self.listbox = settings.Tkinter.Listbox( gridPosition.master, selectmode = settings.Tkinter.SINGLE, yscrollcommand = scrollbar.set ) self.listbox.bind('<ButtonRelease-1>', self.buttonReleaseOne ) gridPosition.master.bind('<FocusIn>', self.focusIn ) scrollbar.config( command = self.listbox.yview ) self.listbox.grid( row = gridPosition.row, column = 0, sticky = settings.Tkinter.N + settings.Tkinter.S ) scrollbar.grid( row = gridPosition.row, column = 1, sticky = settings.Tkinter.N + settings.Tkinter.S ) self.setStateToValue() self.repository.saveListenerTable['updateProfileSaveListeners'] = updateProfileSaveListeners
class TableauWindow: def activateMouseModeTool(self): "Activate the mouse mode tool." self.repository.setToDisplaySave() self.canvas.focus_set() self.createMouseModeTool() self.mouseTool.update() def addCanvasMenuRootScrollSkein(self, repository, skein, suffix, title): "Add the canvas, menu bar, scroll bar, skein panes, tableau repository, root and skein." self.imagesDirectoryPath = archive.getFabmetheusUtilitiesPath('images') self.movementTextID = None self.mouseInstantButtons = [] self.photoImages = {} self.repository = repository self.root = settings.Tkinter.Tk() self.gridPosition = settings.GridVertical(0, 1) self.gridPosition.master = self.root self.root.title(os.path.basename(skein.fileName) + ' - ' + title) self.rulingExtent = 24 self.rulingTargetSeparation = 150.0 self.screenSize = skein.screenSize self.skein = skein self.skeinPanes = skein.skeinPanes self.suffix = suffix self.timerID = None repository.animationSlideShowRate.value = max( repository.animationSlideShowRate.value, 0.01) repository.animationSlideShowRate.value = min( repository.animationSlideShowRate.value, 85.0) repository.drawArrows.setUpdateFunction( self.setWindowToDisplaySaveUpdate) repository.goAroundExtruderOffTravel.setUpdateFunction( self.setWindowToDisplaySavePhoenixUpdate) repository.layerExtraSpan.setUpdateFunction( self.setWindowToDisplaySaveUpdate) repository.widthOfSelectionThread.setUpdateFunction( self.setWindowToDisplaySaveUpdate) repository.widthOfTravelThread.setUpdateFunction( self.setWindowToDisplaySaveUpdate) repository.window = self for menuRadio in repository.mouseMode.menuRadios: fileName = menuRadio.name.lower() fileName = fileName.replace(' ', '_') + '.ppm' menuRadio.mouseButton = self.getPhotoButtonGridIncrement( menuRadio.invoke, fileName, self.gridPosition) self.gridPosition = settings.GridHorizontal(1, 99) self.gridPosition.master = self.root self.xScrollbar = HiddenScrollbar(self.root, orient=settings.Tkinter.HORIZONTAL) self.xScrollbar.grid(row=98, column=2, columnspan=96, sticky=settings.Tkinter.E + settings.Tkinter.W) self.yScrollbar = HiddenScrollbar(self.root) self.yScrollbar.grid(row=1, rowspan=97, column=99, sticky=settings.Tkinter.N + settings.Tkinter.S) self.canvasHeight = min( int(skein.screenSize.imag), self.root.winfo_screenheight() - repository.screenVerticalInset.value) self.canvasWidth = min( int(skein.screenSize.real), self.root.winfo_screenwidth() - repository.screenHorizontalInset.value) scrollRegionBoundingBox = (0, 0, int(skein.screenSize.real), int(skein.screenSize.imag)) self.canvas = settings.Tkinter.Canvas( self.root, highlightthickness=3, width=self.canvasWidth, height=self.canvasHeight, scrollregion=scrollRegionBoundingBox) self.canvas.grid(row=1, rowspan=97, column=2, columnspan=96, sticky=settings.Tkinter.E + settings.Tkinter.W + settings.Tkinter.N + settings.Tkinter.S) self.fileHelpMenuBar = settings.FileHelpMenuBar(self.root) self.exportMenu = settings.Tkinter.Menu(self.fileHelpMenuBar.fileMenu, tearoff=0) self.fileHelpMenuBar.fileMenu.add_cascade(label="Export", menu=self.exportMenu, underline=0) exportCanvasPluginsFolderPath = archive.getAbsoluteFolderPath( os.path.dirname(__file__), 'export_canvas_plugins') exportCanvasPluginFileNames = archive.getPluginFileNamesFromDirectoryPath( exportCanvasPluginsFolderPath) for exportCanvasPluginFileName in exportCanvasPluginFileNames: ExportCanvasDialog().addPluginToMenu(self.canvas, skein.fileName, self.exportMenu, exportCanvasPluginFileName, suffix) self.fileHelpMenuBar.fileMenu.add_separator() self.fileHelpMenuBar.completeMenu(self.close, repository, self.save, self) def addLayer(self, gridPosition): "Add the layer frame items." self.diveButton = self.getPhotoButtonGridIncrement( self.dive, 'dive.ppm', gridPosition) self.soarButton = self.getPhotoButtonGridIncrement( self.soar, 'soar.ppm', gridPosition) gridPosition.increment() settings.Tkinter.Label(gridPosition.master, text='Layer:').grid(row=gridPosition.row, column=gridPosition.column, sticky=settings.Tkinter.W) gridPosition.increment() self.limitIndex() self.layerEntry = settings.Tkinter.Spinbox( gridPosition.master, command=self.layerEntryReturnPressed, from_=0, increment=1, to=getLengthMinusOneMinimumOne(self.skeinPanes)) self.layerEntry.bind('<Return>', self.layerEntryReturnPressed) self.layerEntry.grid(row=gridPosition.row, column=gridPosition.column, sticky=settings.Tkinter.W) def addLine(self, gridPosition): "Add the line frame items." self.lineDiveButton = self.getPhotoButtonGridIncrement( self.lineDive, 'dive.ppm', gridPosition) self.lineSoarButton = self.getPhotoButtonGridIncrement( self.lineSoar, 'soar.ppm', gridPosition) gridPosition.increment() settings.Tkinter.Label(gridPosition.master, text='Line:').grid(row=gridPosition.row, column=gridPosition.column, sticky=settings.Tkinter.W) gridPosition.increment() self.lineEntry = settings.Tkinter.Spinbox( gridPosition.master, command=self.lineEntryReturnPressed, from_=0, increment=1, to=getLengthMinusOneMinimumOne(self.getColoredLines())) self.lineEntry.bind('<Return>', self.lineEntryReturnPressed) self.lineEntry.grid(row=gridPosition.row, column=gridPosition.column, sticky=settings.Tkinter.W) def addMouseInstantTool(self, fileName, gridPosition, mouseInstantTool): "Add the mouse instant tool and derived photo button." mouseInstantTool.getReset(self) photoButton = self.getPhotoButtonGridIncrement(mouseInstantTool.click, fileName, gridPosition) mouseInstantTool.mouseButton = photoButton self.mouseInstantButtons.append(photoButton) def addMouseToolsBind(self): "Add the mouse tool and bind button one clicked, button one released and motion." self.xScrollbar.config(command=self.relayXview) self.yScrollbar.config(command=self.relayYview) self.canvas['xscrollcommand'] = self.xScrollbar.set self.canvas['yscrollcommand'] = self.yScrollbar.set settings.CloseListener( self, self.destroyAllDialogWindows).listenToWidget(self.canvas) self.canvasScreenCenter = 0.5 * complex( float(self.canvasWidth) / float(self.screenSize.real), float(self.canvasHeight) / float(self.screenSize.imag)) self.addPhotoImage('stop.ppm', self.gridPosition) self.gridPosition.increment() self.addLayer(getGridHorizontalFrame(self.gridPosition)) self.gridPosition.increment() self.addLine(getGridHorizontalFrame(self.gridPosition)) self.gridPosition.increment() self.addScale(getGridHorizontalFrame(self.gridPosition)) self.gridPosition = settings.GridVertical( self.gridPosition.columnStart + 1, self.gridPosition.row) self.gridPosition.master = self.root for name in self.repository.frameList.value: entity = self.getEntityFromName(name) if entity != None: self.gridPosition.incrementGivenNumberOfColumns(3) entity.addToDialog(getGridHorizontalFrame(self.gridPosition)) for menuRadio in self.repository.mouseMode.menuRadios: menuRadio.mouseTool = menuRadio.getNewMouseToolFunction().getReset( self) self.mouseTool = menuRadio.mouseTool self.createMouseModeTool() self.canvas.bind('<Button-1>', self.button1) self.canvas.bind('<ButtonRelease-1>', self.buttonRelease1) self.canvas.bind('<KeyPress-Down>', self.keyPressDown) self.canvas.bind('<KeyPress-Left>', self.keyPressLeft) self.canvas.bind('<KeyPress-Right>', self.keyPressRight) self.canvas.bind('<KeyPress-Up>', self.keyPressUp) self.canvas.bind('<Motion>', self.motion) self.canvas.bind('<Return>', self.keyPressReturn) self.canvas.bind('<Shift-ButtonRelease-1>', self.shiftButtonRelease1) self.canvas.bind('<Shift-Motion>', self.shiftMotion) self.layerEntry.bind('<Destroy>', self.cancelTimer) self.root.grid_columnconfigure(44, weight=1) self.root.grid_rowconfigure(44, weight=1) self.resetPeriodicButtonsText() self.repository.animationLineQuickening.setUpdateFunction( self.repository.setToDisplaySave) self.repository.animationSlideShowRate.setUpdateFunction( self.repository.setToDisplaySave) self.repository.screenHorizontalInset.setUpdateFunction( self.redisplayWindowUpdate) self.repository.screenVerticalInset.setUpdateFunction( self.redisplayWindowUpdate) rankZeroSeperation = self.getRulingSeparationWidthPixels(0) zoom = self.rulingTargetSeparation / rankZeroSeperation self.rank = euclidean.getRank(zoom) rankTop = self.rank + 1 seperationBottom = self.getRulingSeparationWidthPixels(self.rank) seperationTop = self.getRulingSeparationWidthPixels(rankTop) bottomDifference = getGeometricDifference(self.rulingTargetSeparation, seperationBottom) topDifference = getGeometricDifference(self.rulingTargetSeparation, seperationTop) if topDifference < bottomDifference: self.rank = rankTop self.rulingSeparationWidthMillimeters = euclidean.getIncrementFromRank( self.rank) self.canvas.focus_set() def addPhotoImage(self, fileName, gridPosition): "Get a PhotoImage button, grid the button and increment the grid position." photoImage = None try: photoImage = settings.Tkinter.PhotoImage( file=os.path.join(self.imagesDirectoryPath, fileName), master=gridPosition.master) except: print( 'Image %s was not found in the images directory, so a text button will be substituted.' % fileName) untilDotFileName = archive.getUntilDot(fileName) self.photoImages[untilDotFileName] = photoImage return untilDotFileName def addScale(self, gridPosition): "Add the line frame items." self.addMouseInstantTool('zoom_out.ppm', gridPosition, zoom_out.getNewMouseTool()) self.addMouseInstantTool('zoom_in.ppm', gridPosition, zoom_in.getNewMouseTool()) gridPosition.increment() settings.Tkinter.Label(gridPosition.master, text='Scale:').grid(row=gridPosition.row, column=gridPosition.column, sticky=settings.Tkinter.W) gridPosition.increment() self.scaleEntry = settings.Tkinter.Spinbox( gridPosition.master, command=self.scaleEntryReturnPressed, from_=10.0, increment=5.0, to=100.0) self.scaleEntry.bind('<Return>', self.scaleEntryReturnPressed) self.scaleEntry.grid(row=gridPosition.row, column=gridPosition.column, sticky=settings.Tkinter.W) def addSettingsMenuSetWindowGeometry(self, center): "Add the settings menu, center the scroll region, update, and set the window geometry." self.settingsMenu = settings.Tkinter.Menu(self.fileHelpMenuBar.menuBar, tearoff=0) self.fileHelpMenuBar.addMenuToMenuBar("Settings", self.settingsMenu) settings.addMenuEntitiesToMenuFrameable(self.settingsMenu, self.repository.menuEntities) self.relayXview(settings.Tkinter.MOVETO, center.real - self.canvasScreenCenter.real) self.relayYview(settings.Tkinter.MOVETO, center.imag - self.canvasScreenCenter.imag) self.root.withdraw() self.root.update_idletasks() movedGeometryString = '%sx%s+%s' % (self.root.winfo_reqwidth(), self.root.winfo_reqheight(), '0+0') self.root.geometry(movedGeometryString) def button1(self, event): "The button was clicked." self.mouseTool.button1(event) def buttonRelease1(self, event): "The button was released." self.mouseTool.buttonRelease1(event) def cancel(self, event=None): "Set all entities to their saved state." settings.cancelRepository(self.repository) def cancelTimer(self, event=None): "Cancel the timer and set it to none." if self.timerID != None: self.canvas.after_cancel(self.timerID) self.timerID = None def cancelTimerResetButtons(self): "Cancel the timer and set it to none." self.cancelTimer() self.resetPeriodicButtonsText() def close(self, event=None): "The dialog was closed." try: self.root.after( 1, self.root.destroy ) # to get around 'Font Helvetica -12 still in cache.' segmentation bug, instead of simply calling self.root.destroy() except: pass def createMouseModeTool(self): "Create the mouse mode tool." self.destroyMouseToolRaiseMouseButtons() for menuRadio in self.repository.mouseMode.menuRadios: if menuRadio.value: self.mouseTool = menuRadio.mouseTool menuRadio.mouseButton['relief'] = settings.Tkinter.SUNKEN def destroyAllDialogWindows(self): "Destroy all the dialog windows." settings.writeSettings(self.repository) return for menuEntity in self.repository.menuEntities: lowerName = menuEntity.name.lower() if lowerName in settings.globalRepositoryDialogListTable: globalRepositoryDialogValues = settings.globalRepositoryDialogListTable[ lowerName] for globalRepositoryDialogValue in globalRepositoryDialogValues: settings.quitWindow(globalRepositoryDialogValue.root) def destroyMouseToolRaiseMouseButtons(self): "Destroy the mouse tool and raise the mouse buttons." self.mouseTool.destroyEverything() for menuRadio in self.repository.mouseMode.menuRadios: menuRadio.mouseButton['relief'] = settings.Tkinter.RAISED for mouseInstantButton in self.mouseInstantButtons: mouseInstantButton['relief'] = settings.Tkinter.RAISED def dive(self): "Dive, go down periodically." oldDiveButtonText = self.diveButton['text'] self.cancelTimerResetButtons() if oldDiveButtonText == 'stop': return self.diveCycle() def diveCycle(self): "Start the dive cycle." self.cancelTimer() self.repository.layer.value -= 1 self.update() if self.repository.layer.value < 1: self.resetPeriodicButtonsText() return self.setButtonImageText(self.diveButton, 'stop') self.timerID = self.canvas.after(self.getSlideShowDelay(), self.diveCycle) def getAnimationLineDelay(self, coloredLine): "Get the animation line delay in milliseconds." # maybe later, add animation along line # nextLayerIndex = self.repository.layer.value # nextLineIndex = self.repository.line.value + 1 # coloredLinesLength = len( self.getColoredLines() ) # self.skein.feedRateMinute # if nextLineIndex >= coloredLinesLength: # if nextLayerIndex + 1 < len( self.skeinPanes ): # nextLayerIndex += 1 # nextLineIndex = 0 # else: # nextLineIndex = self.repository.line.value splitLine = gcodec.getSplitLineBeforeBracketSemicolon( coloredLine.displayString) self.skein.feedRateMinute = gcodec.getFeedRateMinute( self.skein.feedRateMinute, splitLine) feedRateSecond = self.skein.feedRateMinute / 60.0 coloredLineLength = abs( coloredLine.end - coloredLine.begin) / self.repository.scale.value duration = coloredLineLength / feedRateSecond animationLineDelay = int( round(1000.0 * duration / self.repository.animationLineQuickening.value)) return max(animationLineDelay, 1) def getDrawnLineText(self, location, tags, text): "Get the line text drawn on the canvas." anchorTowardCenter = settings.Tkinter.N if location.imag > float(self.canvasHeight) * 0.1: anchorTowardCenter = settings.Tkinter.S if location.real > float(self.canvasWidth) * 0.7: anchorTowardCenter += settings.Tkinter.E else: anchorTowardCenter += settings.Tkinter.W return self.canvas.create_text(int(location.real), int(location.imag), anchor=anchorTowardCenter, tags=tags, text=text) def getEntityFromName(self, name): "Get the entity of the given name." for entity in self.repository.displayEntities: if entity.name == name: return entity return None def getPhotoButtonGridIncrement(self, commandFunction, fileName, gridPosition): "Get a PhotoImage button, grid the button and increment the grid position." gridPosition.increment() untilDotFileName = self.addPhotoImage(fileName, gridPosition) photoImage = self.photoImages[untilDotFileName] photoButton = settings.Tkinter.Button(gridPosition.master, activebackground='black', activeforeground='white', command=commandFunction, text=untilDotFileName) if photoImage != None: photoButton['image'] = photoImage photoButton.grid(row=gridPosition.row, column=gridPosition.column, sticky=settings.Tkinter.W) return photoButton def getRoundedRulingText(self, extraDecimalPlaces, number): "Get the rounded ruling text." rulingText = euclidean.getRoundedToDecimalPlacesString( extraDecimalPlaces - math.floor(math.log10(self.rulingSeparationWidthMillimeters)), number) if self.rulingSeparationWidthMillimeters < .99: return rulingText if rulingText[-len('.0'):] == '.0': return rulingText[:-len('.0')] return rulingText def getRulingSeparationWidthPixels(self, rank): "Get the separation width in pixels." return euclidean.getIncrementFromRank(rank) * self.skein.scale def getScrollPaneCenter(self): "Get the center of the scroll pane." return self.getScrollPaneFraction() + self.canvasScreenCenter def getScrollPaneFraction(self): "Get the center of the scroll pane." return complex(self.xScrollbar.get()[0], self.yScrollbar.get()[0]) def getSlideShowDelay(self): "Get the slide show delay in milliseconds." slideShowDelay = int( round(1000.0 / self.repository.animationSlideShowRate.value)) return max(slideShowDelay, 1) def getUpdateSkeinPanes(self): "Get the update skein panes." layerPlusExtraSpan = self.repository.layer.value + self.repository.layerExtraSpan.value layersFrom = max(0, min(self.repository.layer.value, layerPlusExtraSpan)) layersTo = min( len(self.skeinPanes), max(self.repository.layer.value, layerPlusExtraSpan) + 1) return self.skeinPanes[layersFrom:layersTo] def isLineBelowZeroSetLayer(self): "Determine if the line index is below zero, and if so set the layer index." if self.repository.line.value >= 0: return False self.repository.line.value = 0 if self.repository.layer.value > 0: self.setLayerIndex(self.repository.layer.value - 1) return True return False def isLineBeyondListSetLayer(self): "Determine if the line index is beyond the end of the list, and if so set the layer index." coloredLinesLength = len(self.getColoredLines()) if self.repository.line.value < coloredLinesLength: return False self.repository.line.value = coloredLinesLength - 1 if self.repository.layer.value < len(self.skeinPanes) - 1: self.setLayerIndex(self.repository.layer.value + 1) return True return False def keyPressDown(self, event): "The down arrow was pressed." self.mouseTool.keyPressDown(event) def keyPressLeft(self, event): "The left arrow was pressed." self.mouseTool.keyPressLeft(event) def keyPressReturn(self, event): "The return key was pressed." self.mouseTool.keyPressReturn(event) def keyPressRight(self, event): "The right arrow was pressed." self.mouseTool.keyPressRight(event) def keyPressUp(self, event): "The up arrow was pressed." self.mouseTool.keyPressUp(event) def layerEntryReturnPressed(self, event=None): "The layer index entry return was pressed." self.setLayerIndex(int(self.layerEntry.get())) def limitIndex(self): "Limit the index so it is not below zero or above the top." self.repository.layer.value = max(0, self.repository.layer.value) self.repository.layer.value = min( len(self.skeinPanes) - 1, self.repository.layer.value) def limitIndexSetArrowMouseDeleteCanvas(self): "Limit the index, set the arrow type, and delete all the canvas items." self.limitIndex() self.arrowType = None if self.repository.drawArrows.value: self.arrowType = 'last' self.canvas.delete(settings.Tkinter.ALL) def lineEntryReturnPressed(self, event=None): "The line index entry return was pressed." self.repository.line.value = int(self.lineEntry.get()) if self.isLineBelowZeroSetLayer(): return if self.isLineBeyondListSetLayer(): return self.cancelTimerResetButtons() self.updateMouseToolIfSelection() self.setLineButtonsState() def lineDive(self): "Line dive, go down periodically." oldLineDiveButtonText = self.lineDiveButton['text'] self.cancelTimerResetButtons() if oldLineDiveButtonText == 'stop': return self.lineDiveCycle() def lineDiveCycle(self): "Start the line dive cycle." self.cancelTimer() self.repository.line.value -= 1 if self.repository.line.value < 0: self.repository.line.value = 0 if self.repository.layer.value == 0: self.resetPeriodicButtonsText() self.setLineButtonsState() return self.setLayerIndex(self.repository.layer.value - 1) else: self.updateMouseToolIfSelection() self.setLineButtonsState() self.setButtonImageText(self.lineDiveButton, 'stop') coloredLine = self.getColoredLines()[self.repository.line.value] self.timerID = self.canvas.after( self.getAnimationLineDelay(coloredLine), self.lineDiveCycle) def lineSoar(self): "Line soar, go up periodically." oldLineSoarButtonText = self.lineSoarButton['text'] self.cancelTimerResetButtons() if oldLineSoarButtonText == 'stop': return self.lineSoarCycle() def lineSoarCycle(self): "Start the line soar cycle." self.cancelTimer() self.repository.line.value += 1 coloredLinesLength = len(self.getColoredLines()) if self.repository.line.value >= coloredLinesLength: self.repository.line.value = coloredLinesLength - 1 if self.repository.layer.value > len(self.skeinPanes) - 2: self.resetPeriodicButtonsText() self.setLineButtonsState() return self.setLayerIndex(self.repository.layer.value + 1) else: self.updateMouseToolIfSelection() self.setLineButtonsState() self.setButtonImageText(self.lineSoarButton, 'stop') coloredLine = self.getColoredLines()[self.repository.line.value] self.timerID = self.canvas.after( self.getAnimationLineDelay(coloredLine), self.lineSoarCycle) def motion(self, event): "The mouse moved." self.mouseTool.motion(event) def phoenixUpdate(self): "Update the skein, and deiconify a new window and destroy the old." self.updateNewDestroyOld(self.getScrollPaneCenter()) def relayXview(self, *args): "Relay xview changes." self.canvas.xview(*args) def relayYview(self, *args): "Relay yview changes." self.canvas.yview(*args) def resetPeriodicButtonsText(self): "Reset the text of the periodic buttons." self.setButtonImageText(self.diveButton, 'dive') self.setButtonImageText(self.soarButton, 'soar') self.setButtonImageText(self.lineDiveButton, 'dive') self.setButtonImageText(self.lineSoarButton, 'soar') def redisplayWindowUpdate(self, event=None): "Deiconify a new window and destroy the old." self.repository.setToDisplaySave() self.getCopy().updateDeiconify(self.getScrollPaneCenter()) self.root.after( 1, self.root.destroy ) # to get around 'Font Helvetica -12 still in cache.' segmentation bug, instead of simply calling self.root.destroy() def save(self): "Set the setting values to the display, save the new values." for menuEntity in self.repository.menuEntities: if menuEntity in self.repository.preferences: menuEntity.setToDisplay() self.setInsetToDisplay() settings.writeSettings(self.repository) def scaleEntryReturnPressed(self, event=None): "The scale entry return was pressed." self.repository.scale.value = float(self.scaleEntry.get()) self.phoenixUpdate() def setButtonImageText(self, button, text): "Set the text of the e periodic buttons." photoImage = self.photoImages[text] if photoImage != None: button['image'] = photoImage button['text'] = text def setDisplayLayerIndex(self): "Set the display of the layer index entry field and buttons." coloredLines = self.getColoredLines() isAboveFloor = self.repository.layer.value > 0 isBelowCeiling = self.repository.layer.value < len(self.skeinPanes) - 1 setStateNormalDisabled(isAboveFloor, self.diveButton) setStateNormalDisabled(isBelowCeiling, self.soarButton) self.setLineButtonsState() settings.setEntryText(self.layerEntry, self.repository.layer.value) settings.setEntryText(self.lineEntry, self.repository.line.value) settings.setEntryText(self.scaleEntry, self.repository.scale.value) self.mouseTool.update() self.setInsetToDisplay() def setInsetToDisplay(self): "Set the repository to the display." if self.root.state() != 'normal': return excessExtent = int(self.xScrollbar['width']) * 21 / 15 screenSize = self.skein.screenSize xScrollbarCanvasPortion = getScrollbarCanvasPortion(self.xScrollbar) newScreenHorizontalInset = int(self.root.winfo_screenwidth() - round(xScrollbarCanvasPortion * screenSize.real) + excessExtent) if xScrollbarCanvasPortion < .99: self.repository.screenHorizontalInset.value = newScreenHorizontalInset else: self.repository.screenHorizontalInset.value = min( self.repository.screenHorizontalInset.value, newScreenHorizontalInset) yScrollbarCanvasPortion = getScrollbarCanvasPortion(self.yScrollbar) newScreenVerticalInset = int(self.root.winfo_screenheight() - round(yScrollbarCanvasPortion * screenSize.imag) + excessExtent) if yScrollbarCanvasPortion < .99: self.repository.screenVerticalInset.value = newScreenVerticalInset else: self.repository.screenVerticalInset.value = min( self.repository.screenVerticalInset.value, newScreenVerticalInset) def setLayerIndex(self, layerIndex): "Set the layer index." self.cancelTimerResetButtons() oldLayerIndex = self.repository.layer.value self.repository.layer.value = layerIndex self.limitIndex() coloredLines = self.getColoredLines() if self.repository.layer.value < oldLayerIndex: self.repository.line.value = len(coloredLines) - 1 self.lineEntry['to'] = getLengthMinusOneMinimumOne(coloredLines) if self.repository.layer.value > oldLayerIndex: self.repository.line.value = 0 self.lineEntry['to'] = getLengthMinusOneMinimumOne(coloredLines) self.update() def setLineButtonsState(self): "Set the state of the line buttons." coloredLines = self.getColoredLines() isAboveFloor = self.repository.layer.value > 0 isBelowCeiling = self.repository.layer.value < len(self.skeinPanes) - 1 setStateNormalDisabled(isAboveFloor or self.repository.line.value > 0, self.lineDiveButton) setStateNormalDisabled( isBelowCeiling or self.repository.line.value < len(coloredLines) - 1, self.lineSoarButton) def setWindowNewMouseTool(self, getNewMouseToolFunction, mouseTool): "Set the getNewMouseTool function and the update function." mouseTool.getNewMouseToolFunction = getNewMouseToolFunction mouseTool.setUpdateFunction(self.activateMouseModeTool) def setWindowToDisplaySavePhoenixUpdate(self, event=None): "Set the setting values to the display, save the new values, then call the update function." self.repository.setToDisplaySave() self.phoenixUpdate() def setWindowToDisplaySaveUpdate(self, event=None): "Set the setting values to the display, save the new values, then call the update function." self.repository.setToDisplaySave() self.update() def shiftButtonRelease1(self, event): "The button was released while the shift key was pressed." self.mouseTool.buttonRelease1(event, True) def shiftMotion(self, event): "The mouse moved." self.mouseTool.motion(event, True) def soar(self): "Soar, go up periodically." oldSoarButtonText = self.soarButton['text'] self.cancelTimerResetButtons() if oldSoarButtonText == 'stop': return self.soarCycle() def soarCycle(self): "Start the soar cycle." self.cancelTimer() self.repository.layer.value += 1 self.update() if self.repository.layer.value > len(self.skeinPanes) - 2: self.resetPeriodicButtonsText() return self.setButtonImageText(self.soarButton, 'stop') self.timerID = self.canvas.after(self.getSlideShowDelay(), self.soarCycle) def updateDeiconify(self, center=complex(0.5, 0.5)): "Update and deiconify the window." self.addSettingsMenuSetWindowGeometry(center) self.update() self.root.deiconify() def updateMouseToolIfSelection(self): "Update the mouse tool if it is a selection tool." if self.mouseTool == None: return if self.mouseTool.isSelectionTool(): self.mouseTool.update() def updateNewDestroyOld(self, scrollPaneCenter): "Update and deiconify a window and destroy the old." self.getCopyWithNewSkein().updateDeiconify(scrollPaneCenter) self.root.after( 1, self.root.destroy ) # to get around 'Font Helvetica -12 still in cache.' segmentation bug, instead of simply calling self.root.destroy()
class TableauWindow: def activateMouseModeTool(self): "Activate the mouse mode tool." self.repository.setToDisplaySave() self.canvas.focus_set() self.createMouseModeTool() self.mouseTool.update() def addCanvasMenuRootScrollSkein(self, repository, skein, suffix, title): "Add the canvas, menu bar, scroll bar, skein panes, tableau repository, root and skein." self.imagesDirectoryPath = settings.getPathInFabmetheus(os.path.join("fabmetheus_utilities", "images")) self.movementTextID = None self.mouseInstantButtons = [] self.photoImages = {} self.repository = repository self.root = settings.Tkinter.Tk() self.gridPosition = settings.GridVertical(0, 1) self.gridPosition.master = self.root self.root.title(os.path.basename(skein.fileName) + " - " + title) self.rulingExtent = 24 self.rulingTargetSeparation = 150.0 self.screenSize = skein.screenSize self.skein = skein self.skeinPanes = skein.skeinPanes self.suffix = suffix self.timerID = None repository.animationSlideShowRate.value = max(repository.animationSlideShowRate.value, 0.01) repository.animationSlideShowRate.value = min(repository.animationSlideShowRate.value, 85.0) repository.drawArrows.setUpdateFunction(self.setWindowToDisplaySaveUpdate) repository.goAroundExtruderOffTravel.setUpdateFunction(self.setWindowToDisplaySavePhoenixUpdate) repository.layerExtraSpan.setUpdateFunction(self.setWindowToDisplaySaveUpdate) repository.widthOfSelectionThread.setUpdateFunction(self.setWindowToDisplaySaveUpdate) repository.widthOfTravelThread.setUpdateFunction(self.setWindowToDisplaySaveUpdate) repository.window = self for menuRadio in repository.mouseMode.menuRadios: fileName = menuRadio.name.lower() fileName = fileName.replace(" ", "_") + ".ppm" menuRadio.mouseButton = self.getPhotoButtonGridIncrement(menuRadio.invoke, fileName, self.gridPosition) self.gridPosition = settings.GridHorizontal(1, 99) self.gridPosition.master = self.root self.xScrollbar = HiddenScrollbar(self.root, orient=settings.Tkinter.HORIZONTAL) self.xScrollbar.grid(row=98, column=2, columnspan=96, sticky=settings.Tkinter.E + settings.Tkinter.W) self.yScrollbar = HiddenScrollbar(self.root) self.yScrollbar.grid(row=1, rowspan=97, column=99, sticky=settings.Tkinter.N + settings.Tkinter.S) self.canvasHeight = min( int(skein.screenSize.imag), self.root.winfo_screenheight() - repository.screenVerticalInset.value ) self.canvasWidth = min( int(skein.screenSize.real), self.root.winfo_screenwidth() - repository.screenHorizontalInset.value ) scrollRegionBoundingBox = (0, 0, int(skein.screenSize.real), int(skein.screenSize.imag)) self.canvas = settings.Tkinter.Canvas( self.root, highlightthickness=3, width=self.canvasWidth, height=self.canvasHeight, scrollregion=scrollRegionBoundingBox, ) self.canvas.grid( row=1, rowspan=97, column=2, columnspan=96, sticky=settings.Tkinter.E + settings.Tkinter.W + settings.Tkinter.N + settings.Tkinter.S, ) self.fileHelpMenuBar = settings.FileHelpMenuBar(self.root) self.exportMenu = settings.Tkinter.Menu(self.fileHelpMenuBar.fileMenu, tearoff=0) self.fileHelpMenuBar.fileMenu.add_cascade(label="Export", menu=self.exportMenu, underline=0) exportCanvasPluginsFolderPath = gcodec.getAbsoluteFolderPath(os.path.dirname(__file__), "export_canvas_plugins") exportCanvasPluginFileNames = gcodec.getPluginFileNamesFromDirectoryPath(exportCanvasPluginsFolderPath) for exportCanvasPluginFileName in exportCanvasPluginFileNames: ExportCanvasDialog().addPluginToMenu( self.canvas, skein.fileName, self.exportMenu, exportCanvasPluginFileName, suffix ) self.fileHelpMenuBar.fileMenu.add_separator() self.fileHelpMenuBar.completeMenu(self.close, repository, self.save, self) def addLayer(self, gridPosition): "Add the layer frame items." self.diveButton = self.getPhotoButtonGridIncrement(self.dive, "dive.ppm", gridPosition) self.soarButton = self.getPhotoButtonGridIncrement(self.soar, "soar.ppm", gridPosition) gridPosition.increment() settings.Tkinter.Label(gridPosition.master, text="Layer:").grid( row=gridPosition.row, column=gridPosition.column, sticky=settings.Tkinter.W ) gridPosition.increment() self.limitIndex() self.layerEntry = settings.Tkinter.Spinbox( gridPosition.master, command=self.layerEntryReturnPressed, from_=0, increment=1, to=getLengthMinusOneMinimumOne(self.skeinPanes), ) self.layerEntry.bind("<Return>", self.layerEntryReturnPressed) self.layerEntry.grid(row=gridPosition.row, column=gridPosition.column, sticky=settings.Tkinter.W) def addLine(self, gridPosition): "Add the line frame items." self.lineDiveButton = self.getPhotoButtonGridIncrement(self.lineDive, "dive.ppm", gridPosition) self.lineSoarButton = self.getPhotoButtonGridIncrement(self.lineSoar, "soar.ppm", gridPosition) gridPosition.increment() settings.Tkinter.Label(gridPosition.master, text="Line:").grid( row=gridPosition.row, column=gridPosition.column, sticky=settings.Tkinter.W ) gridPosition.increment() self.lineEntry = settings.Tkinter.Spinbox( gridPosition.master, command=self.lineEntryReturnPressed, from_=0, increment=1, to=getLengthMinusOneMinimumOne(self.getColoredLines()), ) self.lineEntry.bind("<Return>", self.lineEntryReturnPressed) self.lineEntry.grid(row=gridPosition.row, column=gridPosition.column, sticky=settings.Tkinter.W) def addMouseInstantTool(self, fileName, gridPosition, mouseInstantTool): "Add the mouse instant tool and derived photo button." mouseInstantTool.getReset(self) photoButton = self.getPhotoButtonGridIncrement(mouseInstantTool.click, fileName, gridPosition) mouseInstantTool.mouseButton = photoButton self.mouseInstantButtons.append(photoButton) def addMouseToolsBind(self): "Add the mouse tool and bind button one clicked, button one released and motion." self.xScrollbar.config(command=self.relayXview) self.yScrollbar.config(command=self.relayYview) self.canvas["xscrollcommand"] = self.xScrollbar.set self.canvas["yscrollcommand"] = self.yScrollbar.set settings.CloseListener(self, self.destroyAllDialogWindows).listenToWidget(self.canvas) self.canvasScreenCenter = 0.5 * complex( float(self.canvasWidth) / float(self.screenSize.real), float(self.canvasHeight) / float(self.screenSize.imag), ) self.addPhotoImage("stop.ppm", self.gridPosition) self.gridPosition.increment() self.addLayer(getGridHorizontalFrame(self.gridPosition)) self.gridPosition.increment() self.addLine(getGridHorizontalFrame(self.gridPosition)) self.gridPosition.increment() self.addScale(getGridHorizontalFrame(self.gridPosition)) self.gridPosition = settings.GridVertical(self.gridPosition.columnStart + 1, self.gridPosition.row) self.gridPosition.master = self.root for name in self.repository.frameList.value: entity = self.getEntityFromName(name) if entity != None: self.gridPosition.incrementGivenNumberOfColumns(3) entity.addToDialog(getGridHorizontalFrame(self.gridPosition)) for menuRadio in self.repository.mouseMode.menuRadios: menuRadio.mouseTool = menuRadio.getNewMouseToolFunction().getReset(self) self.mouseTool = menuRadio.mouseTool self.createMouseModeTool() self.canvas.bind("<Button-1>", self.button1) self.canvas.bind("<ButtonRelease-1>", self.buttonRelease1) self.canvas.bind("<KeyPress-Down>", self.keyPressDown) self.canvas.bind("<KeyPress-Left>", self.keyPressLeft) self.canvas.bind("<KeyPress-Right>", self.keyPressRight) self.canvas.bind("<KeyPress-Up>", self.keyPressUp) self.canvas.bind("<Motion>", self.motion) self.canvas.bind("<Return>", self.keyPressReturn) self.canvas.bind("<Shift-ButtonRelease-1>", self.shiftButtonRelease1) self.canvas.bind("<Shift-Motion>", self.shiftMotion) self.layerEntry.bind("<Destroy>", self.cancelTimer) self.root.grid_columnconfigure(44, weight=1) self.root.grid_rowconfigure(44, weight=1) self.resetPeriodicButtonsText() self.repository.animationLineQuickening.setUpdateFunction(self.repository.setToDisplaySave) self.repository.animationSlideShowRate.setUpdateFunction(self.repository.setToDisplaySave) self.repository.screenHorizontalInset.setUpdateFunction(self.redisplayWindowUpdate) self.repository.screenVerticalInset.setUpdateFunction(self.redisplayWindowUpdate) rankZeroSeperation = self.getRulingSeparationWidthPixels(0) zoom = self.rulingTargetSeparation / rankZeroSeperation self.rank = euclidean.getRank(zoom) rankTop = self.rank + 1 seperationBottom = self.getRulingSeparationWidthPixels(self.rank) seperationTop = self.getRulingSeparationWidthPixels(rankTop) bottomDifference = getGeometricDifference(self.rulingTargetSeparation, seperationBottom) topDifference = getGeometricDifference(self.rulingTargetSeparation, seperationTop) if topDifference < bottomDifference: self.rank = rankTop self.rulingSeparationWidthMillimeters = euclidean.getIncrementFromRank(self.rank) self.canvas.focus_set() def addPhotoImage(self, fileName, gridPosition): "Get a PhotoImage button, grid the button and increment the grid position." photoImage = None try: photoImage = settings.Tkinter.PhotoImage( file=os.path.join(self.imagesDirectoryPath, fileName), master=gridPosition.master ) except: print("Image %s was not found in the images directory, so a text button will be substituted." % fileName) untilDotFileName = gcodec.getUntilDot(fileName) self.photoImages[untilDotFileName] = photoImage return untilDotFileName def addScale(self, gridPosition): "Add the line frame items." self.addMouseInstantTool("zoom_out.ppm", gridPosition, zoom_out.getNewMouseTool()) self.addMouseInstantTool("zoom_in.ppm", gridPosition, zoom_in.getNewMouseTool()) gridPosition.increment() settings.Tkinter.Label(gridPosition.master, text="Scale:").grid( row=gridPosition.row, column=gridPosition.column, sticky=settings.Tkinter.W ) gridPosition.increment() self.scaleEntry = settings.Tkinter.Spinbox( gridPosition.master, command=self.scaleEntryReturnPressed, from_=10.0, increment=5.0, to=100.0 ) self.scaleEntry.bind("<Return>", self.scaleEntryReturnPressed) self.scaleEntry.grid(row=gridPosition.row, column=gridPosition.column, sticky=settings.Tkinter.W) def addSettingsMenuSetWindowGeometry(self, center): "Add the settings menu, center the scroll region, update, and set the window geometry." self.settingsMenu = settings.Tkinter.Menu(self.fileHelpMenuBar.menuBar, tearoff=0) self.fileHelpMenuBar.addMenuToMenuBar("Settings", self.settingsMenu) settings.addMenuEntitiesToMenuFrameable(self.settingsMenu, self.repository.menuEntities) self.relayXview(settings.Tkinter.MOVETO, center.real - self.canvasScreenCenter.real) self.relayYview(settings.Tkinter.MOVETO, center.imag - self.canvasScreenCenter.imag) self.root.withdraw() self.root.update_idletasks() movedGeometryString = "%sx%s+%s" % (self.root.winfo_reqwidth(), self.root.winfo_reqheight(), "0+0") self.root.geometry(movedGeometryString) def button1(self, event): "The button was clicked." self.mouseTool.button1(event) def buttonRelease1(self, event): "The button was released." self.mouseTool.buttonRelease1(event) def cancelTimer(self, event=None): "Cancel the timer and set it to none." if self.timerID != None: self.canvas.after_cancel(self.timerID) self.timerID = None def cancelTimerResetButtons(self): "Cancel the timer and set it to none." self.cancelTimer() self.resetPeriodicButtonsText() def close(self, event=None): "The dialog was closed." try: self.root.after( 1, self.root.destroy ) # to get around 'Font Helvetica -12 still in cache.' segmentation bug, instead of simply calling self.root.destroy() except: pass def createMouseModeTool(self): "Create the mouse mode tool." self.destroyMouseToolRaiseMouseButtons() for menuRadio in self.repository.mouseMode.menuRadios: if menuRadio.value: self.mouseTool = menuRadio.mouseTool menuRadio.mouseButton["relief"] = settings.Tkinter.SUNKEN def destroyAllDialogWindows(self): "Destroy all the dialog windows." settings.writeSettings(self.repository) return for menuEntity in self.repository.menuEntities: lowerName = menuEntity.name.lower() if lowerName in settings.globalRepositoryDialogListTable: globalRepositoryDialogValues = settings.globalRepositoryDialogListTable[lowerName] for globalRepositoryDialogValue in globalRepositoryDialogValues: settings.quitWindow(globalRepositoryDialogValue.root) def destroyMouseToolRaiseMouseButtons(self): "Destroy the mouse tool and raise the mouse buttons." self.mouseTool.destroyEverything() for menuRadio in self.repository.mouseMode.menuRadios: menuRadio.mouseButton["relief"] = settings.Tkinter.RAISED for mouseInstantButton in self.mouseInstantButtons: mouseInstantButton["relief"] = settings.Tkinter.RAISED def dive(self): "Dive, go down periodically." oldDiveButtonText = self.diveButton["text"] self.cancelTimerResetButtons() if oldDiveButtonText == "stop": return self.diveCycle() def diveCycle(self): "Start the dive cycle." self.cancelTimer() self.repository.layer.value -= 1 self.update() if self.repository.layer.value < 1: self.resetPeriodicButtonsText() return self.setButtonImageText(self.diveButton, "stop") self.timerID = self.canvas.after(self.getSlideShowDelay(), self.diveCycle) def getAnimationLineDelay(self, coloredLine): "Get the animation line delay in milliseconds." # maybe later, add animation along line # nextLayerIndex = self.repository.layer.value # nextLineIndex = self.repository.line.value + 1 # coloredLinesLength = len( self.getColoredLines() ) # self.skein.feedRateMinute # if nextLineIndex >= coloredLinesLength: # if nextLayerIndex + 1 < len( self.skeinPanes ): # nextLayerIndex += 1 # nextLineIndex = 0 # else: # nextLineIndex = self.repository.line.value splitLine = gcodec.getSplitLineBeforeBracketSemicolon(coloredLine.displayString) self.skein.feedRateMinute = gcodec.getFeedRateMinute(self.skein.feedRateMinute, splitLine) feedRateSecond = self.skein.feedRateMinute / 60.0 coloredLineLength = abs(coloredLine.end - coloredLine.begin) / self.repository.scale.value duration = coloredLineLength / feedRateSecond animationLineDelay = int(round(1000.0 * duration / self.repository.animationLineQuickening.value)) return max(animationLineDelay, 1) def getDrawnLineText(self, location, tags, text): "Get the line text drawn on the canvas." anchorTowardCenter = settings.Tkinter.N if location.imag > float(self.canvasHeight) * 0.1: anchorTowardCenter = settings.Tkinter.S if location.real > float(self.canvasWidth) * 0.7: anchorTowardCenter += settings.Tkinter.E else: anchorTowardCenter += settings.Tkinter.W return self.canvas.create_text( int(location.real), int(location.imag), anchor=anchorTowardCenter, tags=tags, text=text ) def getEntityFromName(self, name): "Get the entity of the given name." for entity in self.repository.displayEntities: if entity.name == name: return entity return None def getPhotoButtonGridIncrement(self, commandFunction, fileName, gridPosition): "Get a PhotoImage button, grid the button and increment the grid position." gridPosition.increment() untilDotFileName = self.addPhotoImage(fileName, gridPosition) photoImage = self.photoImages[untilDotFileName] photoButton = settings.Tkinter.Button( gridPosition.master, activebackground="black", activeforeground="white", command=commandFunction, text=untilDotFileName, ) if photoImage != None: photoButton["image"] = photoImage photoButton.grid(row=gridPosition.row, column=gridPosition.column, sticky=settings.Tkinter.W) return photoButton def getRoundedRulingText(self, extraDecimalPlaces, number): "Get the rounded ruling text." rulingText = euclidean.getRoundedToDecimalPlacesString( extraDecimalPlaces - math.floor(math.log10(self.rulingSeparationWidthMillimeters)), number ) if self.rulingSeparationWidthMillimeters < 0.99: return rulingText if rulingText[-len(".0") :] == ".0": return rulingText[: -len(".0")] return rulingText def getRulingSeparationWidthPixels(self, rank): "Get the separation width in pixels." return euclidean.getIncrementFromRank(rank) * self.skein.scale def getScrollPaneCenter(self): "Get the center of the scroll pane." return self.getScrollPaneFraction() + self.canvasScreenCenter def getScrollPaneFraction(self): "Get the center of the scroll pane." return complex(self.xScrollbar.get()[0], self.yScrollbar.get()[0]) def getSlideShowDelay(self): "Get the slide show delay in milliseconds." slideShowDelay = int(round(1000.0 / self.repository.animationSlideShowRate.value)) return max(slideShowDelay, 1) def getUpdateSkeinPanes(self): "Get the update skein panes." layerPlusExtraSpan = self.repository.layer.value + self.repository.layerExtraSpan.value layersFrom = max(0, min(self.repository.layer.value, layerPlusExtraSpan)) layersTo = min(len(self.skeinPanes), max(self.repository.layer.value, layerPlusExtraSpan) + 1) return self.skeinPanes[layersFrom:layersTo] def isLineBelowZeroSetLayer(self): "Determine if the line index is below zero, and if so set the layer index." if self.repository.line.value >= 0: return False self.repository.line.value = 0 if self.repository.layer.value > 0: self.setLayerIndex(self.repository.layer.value - 1) return True return False def isLineBeyondListSetLayer(self): "Determine if the line index is beyond the end of the list, and if so set the layer index." coloredLinesLength = len(self.getColoredLines()) if self.repository.line.value < coloredLinesLength: return False self.repository.line.value = coloredLinesLength - 1 if self.repository.layer.value < len(self.skeinPanes) - 1: self.setLayerIndex(self.repository.layer.value + 1) return True return False def keyPressDown(self, event): "The down arrow was pressed." self.mouseTool.keyPressDown(event) def keyPressLeft(self, event): "The left arrow was pressed." self.mouseTool.keyPressLeft(event) def keyPressReturn(self, event): "The return key was pressed." self.mouseTool.keyPressReturn(event) def keyPressRight(self, event): "The right arrow was pressed." self.mouseTool.keyPressRight(event) def keyPressUp(self, event): "The up arrow was pressed." self.mouseTool.keyPressUp(event) def layerEntryReturnPressed(self, event=None): "The layer index entry return was pressed." self.setLayerIndex(int(self.layerEntry.get())) def limitIndex(self): "Limit the index so it is not below zero or above the top." self.repository.layer.value = max(0, self.repository.layer.value) self.repository.layer.value = min(len(self.skeinPanes) - 1, self.repository.layer.value) def limitIndexSetArrowMouseDeleteCanvas(self): "Limit the index, set the arrow type, and delete all the canvas items." self.limitIndex() self.arrowType = None if self.repository.drawArrows.value: self.arrowType = "last" self.canvas.delete(settings.Tkinter.ALL) def lineEntryReturnPressed(self, event=None): "The line index entry return was pressed." self.repository.line.value = int(self.lineEntry.get()) if self.isLineBelowZeroSetLayer(): return if self.isLineBeyondListSetLayer(): return self.cancelTimerResetButtons() self.updateMouseToolIfSelection() self.setLineButtonsState() def lineDive(self): "Line dive, go down periodically." oldLineDiveButtonText = self.lineDiveButton["text"] self.cancelTimerResetButtons() if oldLineDiveButtonText == "stop": return self.lineDiveCycle() def lineDiveCycle(self): "Start the line dive cycle." self.cancelTimer() self.repository.line.value -= 1 if self.repository.line.value < 0: self.repository.line.value = 0 if self.repository.layer.value == 0: self.resetPeriodicButtonsText() self.setLineButtonsState() return self.setLayerIndex(self.repository.layer.value - 1) else: self.updateMouseToolIfSelection() self.setLineButtonsState() self.setButtonImageText(self.lineDiveButton, "stop") coloredLine = self.getColoredLines()[self.repository.line.value] self.timerID = self.canvas.after(self.getAnimationLineDelay(coloredLine), self.lineDiveCycle) def lineSoar(self): "Line soar, go up periodically." oldLineSoarButtonText = self.lineSoarButton["text"] self.cancelTimerResetButtons() if oldLineSoarButtonText == "stop": return self.lineSoarCycle() def lineSoarCycle(self): "Start the line soar cycle." self.cancelTimer() self.repository.line.value += 1 coloredLinesLength = len(self.getColoredLines()) if self.repository.line.value >= coloredLinesLength: self.repository.line.value = coloredLinesLength - 1 if self.repository.layer.value > len(self.skeinPanes) - 2: self.resetPeriodicButtonsText() self.setLineButtonsState() return self.setLayerIndex(self.repository.layer.value + 1) else: self.updateMouseToolIfSelection() self.setLineButtonsState() self.setButtonImageText(self.lineSoarButton, "stop") coloredLine = self.getColoredLines()[self.repository.line.value] self.timerID = self.canvas.after(self.getAnimationLineDelay(coloredLine), self.lineSoarCycle) def motion(self, event): "The mouse moved." self.mouseTool.motion(event) def phoenixUpdate(self): "Update the skein, and deiconify a new window and destroy the old." self.updateNewDestroyOld(self.getScrollPaneCenter()) def relayXview(self, *args): "Relay xview changes." self.canvas.xview(*args) def relayYview(self, *args): "Relay yview changes." self.canvas.yview(*args) def resetPeriodicButtonsText(self): "Reset the text of the periodic buttons." self.setButtonImageText(self.diveButton, "dive") self.setButtonImageText(self.soarButton, "soar") self.setButtonImageText(self.lineDiveButton, "dive") self.setButtonImageText(self.lineSoarButton, "soar") def redisplayWindowUpdate(self, event=None): "Deiconify a new window and destroy the old." self.repository.setToDisplaySave() self.getCopy().updateDeiconify(self.getScrollPaneCenter()) self.root.after( 1, self.root.destroy ) # to get around 'Font Helvetica -12 still in cache.' segmentation bug, instead of simply calling self.root.destroy() def save(self): "Set the setting values to the display, save the new values." for menuEntity in self.repository.menuEntities: if menuEntity in self.repository.archive: menuEntity.setToDisplay() self.setInsetToDisplay() settings.writeSettings(self.repository) def scaleEntryReturnPressed(self, event=None): "The scale entry return was pressed." self.repository.scale.value = float(self.scaleEntry.get()) self.phoenixUpdate() def setButtonImageText(self, button, text): "Set the text of the e periodic buttons." photoImage = self.photoImages[text] if photoImage != None: button["image"] = photoImage button["text"] = text def setDisplayLayerIndex(self): "Set the display of the layer index entry field and buttons." coloredLines = self.getColoredLines() isAboveFloor = self.repository.layer.value > 0 isBelowCeiling = self.repository.layer.value < len(self.skeinPanes) - 1 setStateNormalDisabled(isAboveFloor, self.diveButton) setStateNormalDisabled(isBelowCeiling, self.soarButton) self.setLineButtonsState() settings.setEntryText(self.layerEntry, self.repository.layer.value) settings.setEntryText(self.lineEntry, self.repository.line.value) settings.setEntryText(self.scaleEntry, self.repository.scale.value) self.mouseTool.update() self.setInsetToDisplay() def setInsetToDisplay(self): "Set the archive to the display." if self.root.state() != "normal": return excessExtent = int(self.xScrollbar["width"]) * 21 / 15 screenSize = self.skein.screenSize xScrollbarCanvasPortion = getScrollbarCanvasPortion(self.xScrollbar) newScreenHorizontalInset = int( self.root.winfo_screenwidth() - round(xScrollbarCanvasPortion * screenSize.real) + excessExtent ) if xScrollbarCanvasPortion < 0.99: self.repository.screenHorizontalInset.value = newScreenHorizontalInset else: self.repository.screenHorizontalInset.value = min( self.repository.screenHorizontalInset.value, newScreenHorizontalInset ) yScrollbarCanvasPortion = getScrollbarCanvasPortion(self.yScrollbar) newScreenVerticalInset = int( self.root.winfo_screenheight() - round(yScrollbarCanvasPortion * screenSize.imag) + excessExtent ) if yScrollbarCanvasPortion < 0.99: self.repository.screenVerticalInset.value = newScreenVerticalInset else: self.repository.screenVerticalInset.value = min( self.repository.screenVerticalInset.value, newScreenVerticalInset ) def setLayerIndex(self, layerIndex): "Set the layer index." self.cancelTimerResetButtons() oldLayerIndex = self.repository.layer.value self.repository.layer.value = layerIndex self.limitIndex() coloredLines = self.getColoredLines() if self.repository.layer.value < oldLayerIndex: self.repository.line.value = len(coloredLines) - 1 self.lineEntry["to"] = getLengthMinusOneMinimumOne(coloredLines) if self.repository.layer.value > oldLayerIndex: self.repository.line.value = 0 self.lineEntry["to"] = getLengthMinusOneMinimumOne(coloredLines) self.update() def setLineButtonsState(self): "Set the state of the line buttons." coloredLines = self.getColoredLines() isAboveFloor = self.repository.layer.value > 0 isBelowCeiling = self.repository.layer.value < len(self.skeinPanes) - 1 setStateNormalDisabled(isAboveFloor or self.repository.line.value > 0, self.lineDiveButton) setStateNormalDisabled( isBelowCeiling or self.repository.line.value < len(coloredLines) - 1, self.lineSoarButton ) def setWindowNewMouseTool(self, getNewMouseToolFunction, mouseTool): "Set the getNewMouseTool function and the update function." mouseTool.getNewMouseToolFunction = getNewMouseToolFunction mouseTool.setUpdateFunction(self.activateMouseModeTool) def setWindowToDisplaySavePhoenixUpdate(self, event=None): "Set the setting values to the display, save the new values, then call the update function." self.repository.setToDisplaySave() self.phoenixUpdate() def setWindowToDisplaySaveUpdate(self, event=None): "Set the setting values to the display, save the new values, then call the update function." self.repository.setToDisplaySave() self.update() def shiftButtonRelease1(self, event): "The button was released while the shift key was pressed." self.mouseTool.buttonRelease1(event, True) def shiftMotion(self, event): "The mouse moved." self.mouseTool.motion(event, True) def soar(self): "Soar, go up periodically." oldSoarButtonText = self.soarButton["text"] self.cancelTimerResetButtons() if oldSoarButtonText == "stop": return self.soarCycle() def soarCycle(self): "Start the soar cycle." self.cancelTimer() self.repository.layer.value += 1 self.update() if self.repository.layer.value > len(self.skeinPanes) - 2: self.resetPeriodicButtonsText() return self.setButtonImageText(self.soarButton, "stop") self.timerID = self.canvas.after(self.getSlideShowDelay(), self.soarCycle) def updateDeiconify(self, center=complex(0.5, 0.5)): "Update and deiconify the window." self.addSettingsMenuSetWindowGeometry(center) self.update() self.root.deiconify() def updateMouseToolIfSelection(self): "Update the mouse tool if it is a selection tool." if self.mouseTool == None: return if self.mouseTool.isSelectionTool(): self.mouseTool.update() def updateNewDestroyOld(self, scrollPaneCenter): "Update and deiconify a window and destroy the old." self.getCopyWithNewSkein().updateDeiconify(scrollPaneCenter) self.root.after( 1, self.root.destroy ) # to get around 'Font Helvetica -12 still in cache.' segmentation bug, instead of simply calling self.root.destroy()