123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621 |
- #
- # DigitalWatchGUI.py
- #
- # class DigitalWatchGUI provides a simple Tkinter GUI for a Digital Watch
- # to add: battery dies ... DONE OCT 2008 by Reehan Shaikh reehan.shaikh@cs.mcgill.ca
- # Updated for the SCCDXML compiler and AToMPM formalism by Yentl Van Tendeloo
- from time import localtime
- from tkinter import Frame, PhotoImage, Canvas
- from tkinter.constants import BOTH
- CANVAS_W = 222
- CANVAS_H = 236
- OVAL_X0 = 2
- OVAL_Y0 = 1
- OVAL_X1 = CANVAS_W - OVAL_X0
- OVAL_Y1 = CANVAS_H - OVAL_Y0
- RECT_X0 = 51
- RECT_Y0 = 95
- RECT_X1 = CANVAS_W - RECT_X0 + 1
- RECT_Y1 = CANVAS_H - RECT_Y0 + 10
- FONT_TIME = ("terminal", 14)
- FONT_DATE = ("terminal", 8)
- FONT_NOTE = ("symbol", 10)
- class DigitalWatchGUI:
-
- def __init__(self, parent):
- self.controller = DigitalWatchGUI_Controller()
- self.staticGUI = DigitalWatchGUI_Static(parent, self.controller)
- class DigitalWatchGUI_Controller:
- def __init__(self):
- self.send_event = None
- self.GUI = None
- self.battery = True
-
- def bindStatic(self, GUI):
- self.GUI = GUI
- # Interface for the GUI
- def window_close(self):
- import sys
- sys.exit(0)
- self.send_event('GUIQuit')
- def topRightPressed(self):
- self.send_event('topRightPressed')
- def topRightReleased(self):
- self.send_event('topRightReleased')
-
- def topLeftPressed(self):
- self.send_event('topLeftPressed')
-
- def topLeftReleased(self):
- self.send_event('topLeftReleased')
-
- def bottomRightPressed(self):
- self.send_event('bottomRightPressed')
- def bottomRightReleased(self):
- self.send_event('bottomRightReleased')
-
- def bottomLeftPressed(self):
- self.send_event('bottomLeftPressed')
-
- def bottomLeftReleased(self):
- self.send_event('bottomLeftReleased')
- def alarm(self):
- self.send_event('alarmStart')
-
- # Interface for the statechart
-
- # synchronize the state with the display:
- def batteryHalf(self):
- self.battery = False
- self.GUI.battery = False
- self.refreshDateDisplay()
-
- def batteryFull(self):
- self.battery = True
- self.GUI.battery = True
- self.refreshDateDisplay()
-
- def refreshTimeDisplay(self):
- self.GUI.drawTime()
- def refreshChronoDisplay(self):
- self.GUI.drawChrono()
-
- def refreshDateDisplay(self):
- self.GUI.drawDate()
-
- def refreshAlarmDisplay(self):
- self.GUI.drawAlarm()
-
- # Modify the state:
-
- def increaseTimeByOne(self):
- self.GUI.increaseTimeByOne()
-
- def resetChrono(self):
- self.GUI.resetChrono()
-
- def increaseChronoByOne(self):
- self.GUI.increaseChronoByOne()
-
- # Select current display:
- def startSelection(self):
- self.GUI.startSelection()
-
- def selectNext(self):
- self.GUI.selectNext()
-
- # Modify the state corresponing to the selection
- def increaseSelection(self):
- self.GUI.increaseSelection()
-
- def stopSelection(self):
- self.GUI.stopSelection()
-
- # Light / Alarm:
-
- def setIndiglo(self):
- self.GUI.setIndiglo()
-
- def unsetIndiglo(self):
- self.GUI.unsetIndiglo()
-
- def setAlarm(self):
- self.GUI.setAlarm()
- # Query
- def getTime(self):
- return self.GUI.getTime()
- def getAlarm(self):
- return self.GUI.getAlarm()
-
- # Check if time = alarm set time
- def checkTime(self):
- if self.GUI.getTime()[0] == self.GUI.getAlarm()[0] and self.GUI.getTime()[1] == self.GUI.getAlarm()[1] and self.GUI.getTime()[2] == self.GUI.getAlarm()[2]:
- self.alarm()
- return True
- else:
- return False
- #======================================================================#
- # GUI Static class
- class DigitalWatchGUI_Static(Frame):
- def __init__(self, parent, controller):
- Frame.__init__(self, parent)
- self.parent = parent
- self.controller = controller
- self.controller.bindStatic(self)
- self.battery = True
-
- tmpDate = list(localtime()[0:3])
- self.curDate = [tmpDate[1], tmpDate[2], int(str(tmpDate[0])[3:]) ]
- self.dateTag = None
-
- # self.curTime = list(localtime()[3:6])
- self.curTime = [11, 59, 55]
- self.timeTag = None
-
- self.curAlarm = [12, 0, 0]
- self.alarmTag = None
-
- self.curChrono = [0, 0, 0]
- self.chronoTag = None
-
- self.noteImage = PhotoImage(file="./noteSmall.gif")
- self.watchImage = PhotoImage(file="./watch.gif")
-
- self.alarmNoteTag = None
-
- self.curSelectionInfo = None
- self.curSelection = ["hours", "minutes", "seconds",
- "months", "days", "years"]
- self.curSelectionIndex = 0
-
- self.lastPressed = ""
-
- self.createWidgets()
-
- # self.b_playpause.focus_force()
- parent.protocol("WM_DELETE_WINDOW", self.controller.window_close)
-
- self.drawTime()
- self.drawDate()
- def getTime(self):
- return self.curTime
- def getAlarm(self):
- return self.curAlarm
-
- def createWidgets(self):
- self.pack()
- self.displayCanvas = Canvas(master=self,
- takefocus=1,
- width=CANVAS_W, height=CANVAS_H,
- background="black")
-
- self.displayCanvas.pack(fill=BOTH, expand=1)
- self.displayCanvas.focus_set()
-
- self.watch = self.displayCanvas.create_image(0, 0, image=self.watchImage, anchor="nw")
-
- self.display = self.displayCanvas.create_rectangle(RECT_X0,
- RECT_Y0,
- RECT_X1,
- RECT_Y1,
- fill="#DCDCDC")
- self.topRightButton = self.displayCanvas.create_rectangle(CANVAS_W - 13,
- 60,
- CANVAS_W - 3,
- 70,
- fill='')
- self.topLeftButton = self.displayCanvas.create_rectangle(3,
- 62,
- 13,
- 72,
- fill='')
- self.bottomRightButton = self.displayCanvas.create_rectangle(CANVAS_W - 10,
- 162,
- CANVAS_W,
- 172,
- fill='')
- self.bottomLeftButton = self.displayCanvas.create_rectangle(3,
- 161,
- 13,
- 171,
- fill='')
- self.displayCanvas.bind("<ButtonPress-1>", self.mouse1Click)
- self.displayCanvas.bind("<ButtonRelease-1>", self.mouse1Release)
- def mouse1Click(self, event):
- X = self.displayCanvas.canvasx(event.x)
- Y = self.displayCanvas.canvasy(event.y)
-
- objTag = self.displayCanvas.find_closest(X, Y, halo=5)
-
- if self.topRightButton in objTag:
- self.controller.topRightPressed()
- self.lastPressed = "topRight"
- elif self.topLeftButton in objTag:
- self.controller.topLeftPressed()
- self.lastPressed = "topLeft"
- elif self.bottomLeftButton in objTag:
- self.controller.bottomLeftPressed()
- self.lastPressed = "bottomLeft"
- elif self.bottomRightButton in objTag:
- self.controller.bottomRightPressed()
- self.lastPressed = "bottomRight"
- else:
- self.lastPressed = ""
-
- def mouse1Release(self, event):
- if self.lastPressed == "topRight":
- self.controller.topRightReleased()
- elif self.lastPressed == "topLeft":
- self.controller.topLeftReleased()
- elif self.lastPressed == "bottomLeft":
- self.controller.bottomLeftReleased()
- elif self.lastPressed == "bottomRight":
- self.controller.bottomRightReleased()
- self.lastPressed = ""
-
- def __intToString(self, i):
- if i < 10:
- return "0" + str(i)
- else:
- return str(i)
-
- def __getTimeAsString(self):
- hours = self.__intToString(self.curTime[0])
- minutes = self.__intToString(self.curTime[1])
- seconds = self.__intToString(self.curTime[2])
- return hours + ":" + minutes + ":" + seconds
-
- def __getAlarmAsString(self):
- hours = self.__intToString(self.curAlarm[0])
- minutes = self.__intToString(self.curAlarm[1])
- seconds = self.__intToString(self.curAlarm[2])
- return hours + ":" + minutes + ":" + seconds
-
- def __getChronoAsString(self):
- minutes = self.__intToString(self.curChrono[0])
- seconds = self.__intToString(self.curChrono[1])
- centisecs = self.__intToString(self.curChrono[2])
- return minutes + ":" + seconds + ":" + centisecs
-
- def __getDateAsString(self):
- month = self.__intToString(self.curDate[0])
- day = self.__intToString(self.curDate[1])
- year = self.__intToString(self.curDate[2])
-
- return month + "/" + day + "/" + year
-
- def increaseHoursByOne(self):
- if self.timeTag != None:
- self.curTime[0] = (self.curTime[0] + 1) % 24
- else:
- self.curAlarm[0] = (self.curAlarm[0] + 1) % 24
-
- def increaseMinutesByOne(self):
- if self.timeTag != None:
- self.curTime[1] = (self.curTime[1] + 1) % 60
- else:
- self.curAlarm[1] = (self.curAlarm[1] + 1) % 60
-
- def increaseSecondsByOne(self):
- if self.timeTag != None:
- self.curTime[2] = (self.curTime[2] + 1) % 60
- else:
- self.curAlarm[2] = (self.curAlarm[2] + 1) % 60
-
- def increaseMonthsByOne(self):
- self.curDate[0] = (self.curDate[0] + 1) % 13
- if self.curDate[0] == 0:
- self.curDate[0] = 1
-
- def increaseDaysByOne(self):
- numDays = self.getNumDays()
- self.curDate[1] = (self.curDate[1] + 1) % (numDays + 1)
- if self.curDate[1] == 0:
- self.curDate[1] = 1
-
- def increaseYearsByOne(self):
- self.curDate[2] = (self.curDate[2] + 1) % 100
- if self.curDate[2] == 0:
- self.curDate[2] = 1
-
- def getNumDays(self):
- month = self.curDate[0]
- year = self.curDate[2]
- numDays = 0
- if month == 2: # february
- if year % 4 == 0: # leap year
- numDays = 29
- else:
- numDays = 28
- else:
- if (month % 2 == 1 and month <= 7) or (month % 2 == 0 and month >= 8):
- numDays = 31
- else:
- numDays = 30
- return numDays
-
- def stopSelection(self):
- if self.curSelectionInfo != None:
- self.parent.after_cancel(self.curSelectionInfo[0])
- self.parent.after_cancel(self.curSelectionInfo[1])
- self.parent.after_cancel(self.curSelectionInfo[2])
- self.curSelectionInfo = None
-
- if self.timeTag != None:
- self.drawTime()
- self.drawDate()
- else:
- self.drawAlarm()
-
- def increaseSelection(self):
-
- self.stopSelection()
- selection = self.curSelection[self.curSelectionIndex]
- if selection == "hours":
- self.increaseHoursByOne()
- elif selection == "minutes":
- self.increaseMinutesByOne()
- elif selection == "seconds":
- self.increaseSecondsByOne()
- elif selection == "months":
- self.increaseMonthsByOne()
- elif selection == "days":
- self.increaseDaysByOne()
- elif selection == "years":
- self.increaseYearsByOne()
-
- if self.timeTag != None:
- self.drawTime()
- self.drawDate()
- else:
- self.drawAlarm()
-
- self.animateSelection()
-
- def selectNext(self):
- self.stopSelection()
- if self.timeTag != None:
- numDigits = len(self.curSelection)
- self.drawTime()
- self.drawDate()
- else:
- numDigits = 3
- self.drawAlarm()
- self.curSelectionIndex = (self.curSelectionIndex + 1) % numDigits
- self.animateSelection()
-
- def startSelection(self):
- self.curSelectionIndex = 0
- self.animateSelection()
- def animateSelection(self):
-
- timeFunc = None
- if self.timeTag != None:
- timeFunc = self.drawTime
- else:
- timeFunc = self.drawAlarm
-
- curSelection = self.curSelection[self.curSelectionIndex]
- deleteEvent = None
- creationEvent = None
- if curSelection in ["hours", "minutes", "seconds"]:
- toDrawTime = ["hours", "minutes", "seconds"]
- toDrawTime.remove(curSelection)
- deleteEvent = self.parent.after(500, timeFunc, toDrawTime)
- creationEvent = self.parent.after(1000, timeFunc)
- else:
- toDrawDate = ["years", "months", "days"]
- toDrawDate.remove(curSelection)
- deleteEvent = self.parent.after(500, self.drawDate, toDrawDate)
- creationEvent = self.parent.after(1000, self.drawDate)
- animationEvent = self.parent.after(1000, self.animateSelection)
- self.curSelectionInfo = [deleteEvent,
- creationEvent,
- animationEvent]
- def increaseTimeByOne(self):
- self.curTime[2] = self.curTime[2] + 1
- self.curTime[1] = (self.curTime[1] + self.curTime[2] // 60)
- self.curTime[0] = (self.curTime[0] + self.curTime[1] // 60)
-
- self.curTime[2] = self.curTime[2] % 60
- self.curTime[1] = self.curTime[1] % 60
- self.curTime[0] = self.curTime[0] % 24
-
- if self.curTime[0] == 0 and\
- self.curTime[1] == 0 and\
- self.curTime[2] == 0:
- self.increaseDateByOne()
- def increaseDateByOne(self):
- month = self.curDate[0]
- day = self.curDate[1]
- year = self.curDate[2]
-
- numMonths = 12
- numDays = self.getNumDays()
- self.curDate[1] = self.curDate[1] + 1
- self.curDate[0] = (self.curDate[0] + self.curDate[1] // (numDays + 1))
- self.curDate[2] = (self.curDate[2] + self.curDate[0] // (numMonths + 1))
-
- self.curDate[1] = self.curDate[1] % (numDays + 1)
- self.curDate[0] = self.curDate[0] % (numMonths + 1)
-
- def increaseChronoByOne(self):
- self.curChrono[2] = self.curChrono[2] + 1
- self.curChrono[1] = (self.curChrono[1] + self.curChrono[2] // 100)
- self.curChrono[0] = (self.curChrono[0] + self.curChrono[1] // 100)
-
- self.curChrono[2] = self.curChrono[2] % 100
- self.curChrono[1] = self.curChrono[1] % 100
- self.curChrono[0] = self.curChrono[0] % 100
-
- def clearDisplay(self):
- if self.alarmTag != None:
- self.displayCanvas.delete(self.alarmTag)
- self.alarmTag = None
- if self.timeTag != None:
- self.displayCanvas.delete(self.timeTag)
- self.timeTag = None
- if self.chronoTag != None:
- self.displayCanvas.delete(self.chronoTag)
- self.chronoTag = None
-
- def clearDate(self):
- if self.dateTag != None:
- self.displayCanvas.delete(self.dateTag)
- self.dateTag = None
-
- def drawTime(self, toDraw=["hours", "minutes", "seconds"]):
- timeToDraw = self.__getTimeAsString()
- if "hours" not in toDraw:
- timeToDraw = " " + timeToDraw[2:]
- if "minutes" not in toDraw:
- timeToDraw = timeToDraw[0:3] + " " + timeToDraw[5:]
- if "seconds" not in toDraw:
- timeToDraw = timeToDraw[0:6] + " "
-
- if not self.battery:
- timeToDraw = "88:88:88"
- self.clearDisplay()
-
- self.timeTag = self.displayCanvas.create_text((RECT_X0 + RECT_X1) / 2,
- (RECT_Y0 + RECT_Y1) / 2 + 5,
- font=FONT_TIME,
- justify="center",
- text=timeToDraw)
- def hideTime(self):
- if self.timeTag != None:
- self.displayCanvas.delete(self.timeTag)
- self.timeTag = None
- def drawChrono(self):
- chronoToDraw = self.__getChronoAsString()
- if not self.battery:
- chronoToDraw = "88:88:88"
- if self.chronoTag:
- self.displayCanvas.itemconfigure(self.chronoTag, text=chronoToDraw)
- else:
- self.clearDisplay()
- self.chronoTag = self.displayCanvas.create_text(
- (RECT_X0 + RECT_X1) / 2,
- (RECT_Y0 + RECT_Y1) / 2 + 5,
- font=FONT_TIME,
- justify="center",
- text=chronoToDraw)
- def hideChrono(self):
- if self.chronoTag != None:
- self.displayCanvas.delete(self.chronoTag)
- self.chronoTag = None
-
- def resetChrono(self):
- self.curChrono = [0, 0, 0]
- def drawDate(self, toDraw=["years", "months", "days"]):
- dateToDraw = self.__getDateAsString()
-
- if "months" not in toDraw:
- dateToDraw = " " + dateToDraw[2:]
- if "days" not in toDraw:
- dateToDraw = dateToDraw[0:3] + " " + dateToDraw[5:]
- if "years" not in toDraw:
- dateToDraw = dateToDraw[0:6] + " "
- if not self.battery:
- dateToDraw = "88/88/88"
- self.clearDate()
-
- self.dateTag = self.displayCanvas.create_text(RECT_X1 - 33,
- RECT_Y0 + 7,
- font=FONT_DATE,
- justify="center",
- text=dateToDraw)
- def drawAlarm(self, toDraw=["hours", "minutes", "seconds"]):
- alarmToDraw = self.__getAlarmAsString()
-
- if "hours" not in toDraw:
- alarmToDraw = " " + alarmToDraw[2:]
- if "minutes" not in toDraw:
- alarmToDraw = alarmToDraw[0:3] + " " + alarmToDraw[5:]
- if "seconds" not in toDraw:
- alarmToDraw = alarmToDraw[0:6] + " "
- if not self.battery:
- alarmToDraw = "88:88:88"
- self.clearDisplay()
-
- self.alarmTag = self.displayCanvas.create_text((RECT_X0 + RECT_X1) / 2,
- (RECT_Y0 + RECT_Y1) / 2 + 5,
- font=FONT_TIME,
- justify="center",
- text=alarmToDraw)
- def hideAlarm(self):
- if self.alarmTag != None:
- self.displayCanvas.delete(self.alarmTag)
- self.alarmTag = None
- def setAlarm(self):
- if self.alarmNoteTag != None:
- self.displayCanvas.delete(self.alarmNoteTag)
- self.alarmNoteTag = None
- else:
- self.alarmNoteTag = self.displayCanvas.create_image(RECT_X0 + 5, RECT_Y0 + 3, image=self.noteImage, anchor="nw")
- def setIndiglo(self):
- self.displayCanvas.itemconfigure(self.display, fill='#96DCFA')
- def unsetIndiglo(self):
- self.displayCanvas.itemconfigure(self.display, fill="#DCDCDC")
|