Demo entry 2282417

a timer

   

Submitted by anonymous on Jul 20, 2015 at 12:24
Language: Python 3. Code size: 38.4 kB.

import pygame
from winsound import Beep
from os import listdir, curdir
from os.path import isfile
from sys import exit, argv
from ctypes import windll, Structure, c_ulong, byref
from pygame.locals import *

class POINT(Structure):
    _fields_ = [("x", c_ulong), ("y", c_ulong)]

def getMousePos():
    pt = POINT()
    windll.user32.GetCursorPos(byref(pt))
    return pt.x, pt.y

def unitHoverPos(posX, secondsPosition, minutesPosition): #Returns the number of milliseconds in an hour, minute or second depending on where the mouse is over
    x = getMousePos()[0]
    if x >= (posX+secondsPosition):
        return 1000
    elif x >= (posX+minutesPosition):
        return 60000
    else:
        return 3600000

def inRect(posX, posY, width, height):  #Returns True if mouse is over window
    mouseX, mouseY = getMousePos()
    windowX = range(posX, (posX + width+1))
    windowY = range(posY, (posY + height+1))
    if mouseX in windowX and mouseY in windowY:
        return True
    else:
        return False

def progressBar(width, maxheight, initial, remaining): #Returns progress bar depending on progress of timer and pause and stop status
    if remaining <= 0:
        progressBarHeight = (maxheight)
    else:
        progressBarHeight = maxheight*(float(remaining)/float(initial))
        if progressBarHeight < 1:
            progressBarHeight = 1
    progressBarRect = Rect(0, 0, width, progressBarHeight)
    return progressBarRect

def addZero(num, newLength): #Standardises time/colour format
    num = str(num)
    while len(num)<newLength:
        num = str("0" + num)
    return num

def determineDarkOrLight(colour):
    WHITE = (255, 255, 255)
    BLACK = (0, 0, 0)
    if int(colour[0]) <= 125 and int(colour[1]) <= 125 and int(colour[2]) <= 125:
        crossImage = "crossWhite.png"
        WB = WHITE
    else:
        crossImage = "crossBlack.png"
        WB = BLACK
    return crossImage, WB

def getColour(pauseStatus, stopStatus, activeColour, pauseColour, stopColour): #Returns colour depending on pause and stop status
    if stopStatus:
        return stopColour
    elif pauseStatus:
        return pauseColour
    else:
        return activeColour

def setWindow(x, y, width, height, caption, background = (38, 38, 38)): #creates a window in position x, y of set height and width
    SetWindowPos = windll.user32.SetWindowPos
    window = pygame.display.set_mode((width, height), pygame.NOFRAME)
    pygame.display.set_caption(caption)
    pygame.mouse.set_cursor((16, 19), (0, 0), (128, 0, 192, 0, 160, 0, 144, 0,
        136, 0, 132, 0, 130, 0, 129, 0, 128, 128, 128, 64, 128, 32, 128, 16, 129,
        240, 137, 0, 148, 128, 164, 128, 194, 64, 2, 64, 1, 128), (128, 0, 192, 0,
        224, 0, 240, 0, 248, 0, 252, 0, 254, 0, 255, 0, 255, 128, 255, 192, 255,
        224, 255, 240, 255, 240, 255, 0, 247, 128, 231, 128, 195, 192, 3, 192, 1, 128))
    pygame.display.set_icon(pygame.image.load("icon.png"))
    SetWindowPos(pygame.display.get_wm_info()["window"], -1, x, y, 0, 0, 0x0001)

    pygame.display.update() #Redraw screen
    return window, width, height

def getDistance(p1, p2): #Uses pythagoras to get distance between 2 points
    xLength = abs(p1[0]-p2[0])
    yLength = abs(p1[1]-p2[1])
    distance = ((xLength**2)+(yLength**2))**0.5
    return distance

def inCircle(centre, radius): #Uses getDistance(p1, p2) to check if a point is in the circle
    if getDistance(getMousePos(), centre) <= radius:
        return True
    else:
        return False

def getUnitMultiplier(position):
    values = (1000, 10000, 60000, 600000, 3600000)
    if position <= 4:
        return values[position]
    else:
        return (int("3600000" + (position-4)*"0"))

def chooseColour(uiFont, captionFont, initialBackgroundColour, initialActiveColour, initialPauseColour, initialStopColour, caption = "Select Colour"): #Causes colour selection screen to be displayed
    pygame.init()
    pygame.font.init()

    displayXResolution = pygame.display.list_modes()[0][0]

    posY = 0
    posX = int((displayXResolution/2) - 250)

    #mouse buttons
    LEFT = 1
    RIGHT = 3

    #Colours
    WHITE = (255, 255, 255)
    BLACK = (0, 0, 0)
    GREY = (38, 38, 38)

    #Things to blit
    #Font syntax: pygame.font.render(text, antialiasing, colour)
    captionText = captionFont.render(caption, True, WHITE).convert_alpha()
    applyText = uiFont.render("Apply", True, BLACK).convert_alpha()  #Shows when bright colour is selected
    okayText = uiFont.render("OK", True, BLACK).convert_alpha()
    applyTextWhite = uiFont.render("Apply", True, WHITE).convert_alpha()  #Shows when dark colour is selected
    okayTextWhite = uiFont.render("OK", True, WHITE).convert_alpha()
    colourCircle = pygame.image.load("colourCircle.png").convert_alpha()  #Shows all the different hues
    chosenColourCircle = pygame.image.load("chosenCircleOutline.png").convert_alpha()  #Square with circular cutout (smooth edge)
    coloursOutline = pygame.image.load("coloursOutline.png").convert_alpha() #Show outline of initial colours
    coloursOutlineSelect = pygame.image.load("coloursOutlineSelect.png").convert_alpha()
    coloursOutlineHover = pygame.image.load("coloursOutlineHover.png").convert_alpha()
    colourOverlay = pygame.image.load("circleSelectOverlay.png").convert_alpha()  #A translucent dark circle. Shows when mouse hovers over apply circle
    cross = pygame.image.load("crossWhite.png").convert_alpha()  #Header bar cross
    slider = pygame.image.load("slider.png").convert_alpha()  #circle for slider
    sliderSelect = pygame.image.load("sliderSelect.png").convert_alpha()  #circle for slider when selected
    chosenColourRect = pygame.Surface((200, 200))  #Needs to be surface in order to use pygame.surface.get_at(co-ords)

    backgroundColour = initialBackgroundColour
    activeColour = initialActiveColour
    pauseColour = initialPauseColour
    stopColour = initialStopColour
    hue = initialActiveColour

    selectYPositions = (537, 575, 615, 653)
    selectYPosition = 0

    followMouseColour = False  #Used to select hue
    sliding = False  #Used to determine shade
    sliderY = 510  #Slider starts at the top (brightest)
    OK = False

    fpsClock = pygame.time.Clock()

    colourWindow, currentSizeX, currentSizeY = setWindow(posX, posY, 500, 745, "Colour Picker")
    #setWindow(x, y, width, height, caption, background)
    while True:
        mouseX, mouseY = getMousePos()
        colourWindow.fill(GREY)
        activeRect = pygame.draw.circle(colourWindow, activeColour, (450, 556), 17)
        pauseRect = pygame.draw.circle(colourWindow, pauseColour, (450, 594), 17)
        stopRect = pygame.draw.circle(colourWindow, stopColour, (450, 633), 17)
        backgroundRect = pygame.draw.circle(colourWindow, backgroundColour, (450, 671), 17)

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                return initialColour
            elif event.type == pygame.MOUSEBUTTONDOWN and event.button == LEFT:  #Right mouse button does nothing
                if inRect((452+posX), posY, 45, 32):
                    return initialBackgroundColour, initialActiveColour, initialPauseColour, initialStopColour
                elif inCircle(((125+posX), (645+posY)), 100) and OK == True:  #Click the apply circle
                    return backgroundColour, activeColour, pauseColour, stopColour
                elif inCircle(((125+posX), (645+posY)), 100):
                    if selectYPosition == 0:
                        activeColour = chosenColour
                    elif selectYPosition == 1:
                        pauseColour = chosenColour
                    elif selectYPosition == 2:
                        stopColour = chosenColour
                    elif selectYPosition == 3:
                        backgroundColour = chosenColour
                    OK = True
                elif inRect((posX + tuple(activeRect)[0]), (posY + tuple(activeRect)[1]), tuple(activeRect)[2], tuple(activeRect)[3]):
                    selectYPosition = 0
                    hue = activeColour
                    captionText = captionFont.render("Select Active Colour", True, WHITE).convert_alpha()
                    OK = False
                elif inRect((posX + tuple(pauseRect)[0]), (posY + tuple(pauseRect)[1]), tuple(pauseRect)[2], tuple(pauseRect)[3]):
                    selectYPosition = 1
                    hue = pauseColour
                    captionText = captionFont.render("Select Pause Colour", True, WHITE).convert_alpha()
                    OK = False
                elif inRect((posX + tuple(stopRect)[0]), (posY + tuple(stopRect)[1]), tuple(stopRect)[2], tuple(stopRect)[3]):
                    selectYPosition = 2
                    hue = stopColour
                    captionText = captionFont.render("Select Stop Colour", True, WHITE).convert_alpha()
                    OK = False
                elif inRect((posX + tuple(backgroundRect)[0]), (posY + tuple(backgroundRect)[1]), tuple(backgroundRect)[2], tuple(backgroundRect)[3]):
                    selectYPosition = 3
                    hue = backgroundColour
                    captionText = captionFont.render("Select Background Colour", True, WHITE).convert_alpha()
                    OK = False
                elif sliding == False and inRect((360+posX), (515+posY), 30, 205):  #Click slider
                    sliding = True
                    OK = False
                elif followMouseColour == False and inCircle(((250+posX), (260+posY)), 220):  #Click colour circle
                    followMouseColour = True
                    OK = False
            elif sliding and event.type == pygame.MOUSEBUTTONUP:  #Let go of slider
                sliding = False
            #Let go of circle or mouse leaves circle
            elif followMouseColour and ((event.type == pygame.MOUSEBUTTONUP and event.button == LEFT) or (not inCircle(((250+posX), (260+posY)), 220))):
                followMouseColour = False

        colourWindow.blit(colourCircle, (30, 40))
        pygame.draw.rect(colourWindow, (100, 100, 100), Rect(375, 530, 2, 180))  #Slider rectangle
        colourWindow.blit(coloursOutline, (433, 539))
        colourWindow.blit(coloursOutlineSelect, (431, selectYPositions[selectYPosition]))

        if followMouseColour:
            #get hue from colour circle => pygame.Surface.get_at(co-ords)
            hue = colourCircle.get_at(((mouseX-posX-30), (mouseY-posY-40)))

        if sliding and (530 <= mouseY <= 710):  #if slider selected and in slider range
            colourWindow.blit(sliderSelect, (355, (mouseY-20)))  #sliderSelect radius = 20 hence co-ords = (375-20, mouseY-20)
            sliderY = mouseY-20
        elif sliding and mouseY <= 530:  #if slider selected and mouse is above slider
            colourWindow.blit(sliderSelect, (355, (510)))
            sliderY = 510  #slider stays at top
        elif sliding and mouseY >= 710:  #if slider selected and mouse is below slider
            colourWindow.blit(sliderSelect, (355, (690)))
            sliderY = 690  #slider stays at bottom
        elif not sliding:
            #slider not selected blit slider at last point. slider int(radius) = 13, hence co-ords = (376-13, sliderY+20-13)
            colourWindow.blit(slider, (363, sliderY+7))

        #darkening
        brightnessLevel = (690-sliderY)/180.0  #float => the closer to 1 the brighter, the closer to 0 the darker
        chosenColour = (int(brightnessLevel*hue[0]),int(brightnessLevel*hue[1]), int(brightnessLevel*hue[2]))

        #Header bar
        if inRect((452+posX), posY, 48, 32):  #Close box hovered over
            pygame.draw.rect(colourWindow, chosenColour, Rect(452, 0, 48, 32))

        colourWindow.blit(cross, (452, 0))
        colourWindow.blit(captionText, (16, 7))

        #blitting chosen colour rectangle
        chosenColourRect.fill(chosenColour)
        colourWindow.blit(chosenColourRect, (25, 520))

        if inCircle(((125+posX), (645+posY)), 100):  #if hovered over apply circle
            colourWindow.blit(colourOverlay, (24, 519))  #darken apply circle

        if sliderY <= 600 and not OK:  #halfway between 510 and 690 => if slider is above halfway point
            colourWindow.blit(applyText, (100, 610))  #=> dark apply text
        elif not OK:
            colourWindow.blit(applyTextWhite, (100, 610))  #=>white apply text
        elif sliderY <= 600 and OK:
            colourWindow.blit(okayText, (112, 610))
        else:
            colourWindow.blit(okayTextWhite, (112, 610))

        colourWindow.blit(chosenColourCircle, (24, 519))  #blit apply circle outline

        pygame.display.update()
        fpsClock.tick(30)

def getTimeLeft(remainingMilliseconds):
    hoursLeft = remainingMilliseconds//3600000
    minutesLeft = (remainingMilliseconds // 60000)-(hoursLeft*60)
    secondsLeft = (remainingMilliseconds//1000)-(minutesLeft*60)-(hoursLeft*3600)
    return hoursLeft, minutesLeft, secondsLeft

def main():
    #Things which are dependent on colour:
    #- Header bar caption (automatic)
    #- Text (automatic)
    #- Icons
    #- Header bar cross
    #

    if isfile("userColours.txt"):
        colourPreferences = open("userColours.txt")
    else:
        txtFiles = []
        for file in listdir(curdir):
            if file.endswith(".txt"):
                txtFiles.append(file)
        if txtFiles == 1:
            colourPreferences = txtFiles[0]
        else:
            colourPreferences = open("userColours.txt", "w+")
            colourPreferences.write("Background colour (RGB): (038, 038, 038)\nActive counting colour (RGB): (022, 208, 118)\nPause Colour (RGB): (100, 100, 100)\nStop Colour (RGB): (136, 000, 021)\n")
            colourPreferences.seek(0)
    lines = colourPreferences.readlines()
    backgroundColour = (int(lines[0][-16:][1:4]), int(lines[0][-16:][6:9]), int(lines[0][-16:][11:14]))
    activeColour = (int(lines[1][-16:][1:4]), int(lines[1][-16:][6:9]), int(lines[1][-16:][11:14]))
    pauseColour = (int(lines[2][-16:][1:4]), int(lines[2][-16:][6:9]), int(lines[2][-16:][11:14]))
    stopColour = (int(lines[3][-16:][1:4]), int(lines[3][-16:][6:9]), int(lines[3][-16:][11:14]))
    colourPreferences.close()

    WHITE = (255, 255, 255)
    BLACK = (0, 0, 0)
    GREY = (38, 38, 38)

    pygame.init()
    pygame.font.init()

    windowPosX, windowPosY = 0, 200
    minSizeX, minSizeY = 5, 200
    initialmaxSizeX, maxSizeX, maxSizeY = 575, 575, 200
    timerWindow, currentSizeX, currentSizeY = setWindow(0, 0, 1, 1, "Timer", background = backgroundColour) #setWindow(x, y, width, height, caption, background)

    #if segoeUI is not available (windows version <7), use arial, if not use pygame default.
    if "segoemdl2" in pygame.font.get_fonts():
        captionFontName = "segoeuisemibold"
        fontName = "segoeui"
        iconFontName = "segoemdl2"
        colourFontName = "segoeuisemilight"
    elif "segoeuisemibold" in pygame.font.get_fonts():
        captionFontName = "segoeuisemibold"
        fontName = "segoeui"
        iconFontName = "segoeuisymbol"
        colourFontName = "segoeuisemilight"
    else:
        FONTSMISSING = open("PLEASE INSTALL SEGOE UI FONT FAMILY AND SEGOE UI SYMBOL FONT.txt", "w+")
        FONTSMISSING.close()
        return 0

    fontSize = int(maxSizeY/1.75)

    uiFont = pygame.font.SysFont(colourFontName, 20)
    uiFontBig = pygame.font.SysFont(fontName, fontSize)
    unitFont = pygame.font.SysFont(fontName, 50)
    captionFont = pygame.font.SysFont(captionFontName, 14)
    iconFont = pygame.font.SysFont(iconFontName, 20)

    crossImage, WB = determineDarkOrLight(backgroundColour)

    cross = pygame.image.load(crossImage).convert_alpha()  #Header bar cross
    captionText = captionFont.render("Timer", True, WB).convert_alpha()

    displayYResolution = pygame.display.list_modes()[0][1]

    time = (0, 0, 0) #(hours, minutes, seconds)
    initialSecondsRemaining = ((time[0]*3600)+(time[1]*60)+time[2])
    initialMillisecondsRemaining = initialSecondsRemaining*1000
    progressBarIncrementPeriod = float(initialMillisecondsRemaining)/float(minSizeY)

    millisecondsRemaining = initialMillisecondsRemaining
    fpsClock = pygame.time.Clock()

    TICKEVENT, tickincrement = pygame.USEREVENT+1, 100
    pygame.time.set_timer(TICKEVENT, tickincrement)
    increment = tickincrement + 2
    #Initial status
    PAUSE = True
    STOP = False
    BEEP = True #The program needs to know when to show maximised window (displays stop sign)
    MOVE = False
    EDIT = False
    timeLeftList = ["0", "0", "0", "0", "0", "0"]
    initialTimeLength = len(timeLeftList)
    editPosition = 1

    #STOP tone settings
    stopSoundFrequency = 450
    stopSoundDuration = 500


    #Pygame mouse keys
    LEFT = 1
    RIGHT = 3
    SCROLLUP = 4
    SCROLLDOWN = 5

    #Keys which cause the timer to pause/play
    PAUSEKEYS = (pygame.K_SPACE, pygame.K_KP_ENTER, pygame.K_RETURN)
    NUMBERKEYS = (pygame.K_0, pygame.K_1, pygame.K_2, pygame.K_3, pygame.K_4, pygame.K_5, pygame.K_6, pygame.K_7, pygame.K_8, pygame.K_9)
    NUMPADKEYS = (pygame.K_KP0, pygame.K_KP1, pygame.K_KP2, pygame.K_KP3, pygame.K_KP4, pygame.K_KP5, pygame.K_KP6, pygame.K_KP7, pygame.K_KP8, pygame.K_KP9)
    #Causes pygame to ignore first right click up event
    rightClickDelay = False
    colourWidth = 1
    hoursWidth, minutesWidth = 118, 118

    hoursLeft = 0
    minutesLeft = 0
    secondsLeft = 0
    while True:
        for event in pygame.event.get():
            kmods = pygame.key.get_mods()
            if event.type == pygame.QUIT:
                pygame.quit()
                exit()

            elif event.type == KEYDOWN:
                if EDIT and event.key in NUMBERKEYS or event.key in NUMPADKEYS:
                    if event.key in NUMBERKEYS:
                        NUMBERINDEX = NUMBERKEYS.index(event.key)
                    elif event.key in NUMPADKEYS:
                        NUMBERINDEX = NUMPADKEYS.index(event.key)
                    if initialTimeLength:
                        timeLeftList.pop(-editPosition)
                        initialTimeLength = initialTimeLength - 1
                        editPosition = editPosition + 1
                    timeLeftList.append(str(NUMBERINDEX))
                    PAUSE, BEEP, STOP = True, True, False
                    hoursLeft = int("".join(timeLeftList[:-4]))
                    minutesLeft = int("".join(timeLeftList[-4:-2]))
                    secondsLeft = int("".join(timeLeftList[-2:]))
                    print(timeLeftList)
                elif EDIT and event.key == K_BACKSPACE:
                    timeLeftList.pop(-1)
                    if len(timeLeftList) < 6:
                        timeLeftList.insert(0, "0")
                    hoursLeft = int("".join(timeLeftList[:-4]))
                    minutesLeft = int("".join(timeLeftList[-4:-2]))
                    secondsLeft = int("".join(timeLeftList[-2:]))
                elif EDIT and event.key in PAUSEKEYS:
                    PAUSE = False
                    millisecondsRemaining = int(hoursLeft)*3600000 + int(minutesLeft)*60000 + int(secondsLeft)*1000
                    hoursLeft, minutesLeft, secondsLeft = getTimeLeft(millisecondsRemaining)
                elif (kmods & KMOD_SHIFT):
                    if event.key == K_o:    #Clear
                        if millisecondsRemaining == 0:
                            initialMillisecondsRemaining = 0
                        millisecondsRemaining = 0
                        PAUSE, BEEP, STOP = True, True, False
                        hoursLeft, minutesLeft, secondsLeft = getTimeLeft(millisecondsRemaining)
                    elif event.key == K_r:  #Reset to largest time
                        millisecondsRemaining = initialMillisecondsRemaining
                        PAUSE, BEEP, STOP = True, True, False
                        hoursLeft, minutesLeft, secondsLeft = getTimeLeft(millisecondsRemaining)
                    elif event.key == K_s:  #Refill progress bar
                        initialMillisecondsRemaining = millisecondsRemaining
                    elif event.key == K_BACKSPACE and millisecondsRemaining:  #Takes off 30 minutes
                        millisecondsRemaining = millisecondsRemaining - (1800000)
                        hoursLeft, minutesLeft, secondsLeft = getTimeLeft(millisecondsRemaining)
                else:
                    if event.key == K_BACKSPACE:  #Removes time
                        millisecondsRemaining = millisecondsRemaining - (300000)
                        hoursLeft, minutesLeft, secondsLeft = getTimeLeft(millisecondsRemaining)
                    elif event.key in PAUSEKEYS:    #Pauses
                        if (PAUSE == True and millisecondsRemaining > 0):
                            PAUSE = False
                        else:
                            PAUSE = True
            elif event.type == pygame.MOUSEBUTTONDOWN:
                if (kmods & KMOD_SHIFT):
                    scrollIncrement = 5 #Every scroll wheel event adds 5 units (hours, minutes or seconds) of time
                else:
                    scrollIncrement = 1 #Every scroll wheel event adds 1 unit of time
                if event.button == LEFT:
                    if inRect((maxSizeX-48+windowPosX), windowPosY, 48, 32):
                        pygame.quit()
                        exit()
                    elif inRect((minSizeX+windowPosX), windowPosY, (maxSizeY//4), (maxSizeY//4)):
                        millisecondsRemaining = initialMillisecondsRemaining
                        EDIT = False
                        timeLeftList = ["0", "0", "0", "0", "0", "0"]
                        initialTimeLength = len(timeLeftList)
                        editPosition = 1
                        PAUSE, BEEP, STOP = True, True, False
                        hoursLeft, minutesLeft, secondsLeft = getTimeLeft(millisecondsRemaining)
                    elif inRect((minSizeX+windowPosX), (windowPosY+maxSizeY//4), (maxSizeY//4), (maxSizeY//4)):
                        PAUSE, BEEP, STOP, EDIT = True, True, False, True
                    elif inRect((minSizeX+windowPosX), (windowPosY+maxSizeY//2), (maxSizeY//4), (maxSizeY//4)):
                        if millisecondsRemaining == 0:
                            initialMillisecondsRemaining = 0
                        millisecondsRemaining = 0
                        hoursLeft, minutesLeft, secondsLeft = getTimeLeft(millisecondsRemaining)
                        EDIT = False
                        timeLeftList = ["0", "0", "0", "0", "0", "0"]
                        initialTimeLength = len(timeLeftList)
                        editPosition = 1
                        PAUSE, BEEP, STOP = True, True, False
                    elif inRect((minSizeX+windowPosX), (windowPosY+(3*maxSizeY//4)), (maxSizeY//4), (maxSizeY//4)):
                        PAUSE, BEEP, STOP = True, True, False
                        backgroundColour, activeColour, pauseColour, stopColour = chooseColour(uiFont, captionFont, backgroundColour, activeColour, pauseColour, stopColour, caption = "Select Active Colour")

                        backgroundColourToWrite = "(" + addZero(backgroundColour[0], 3) + ", " + addZero(backgroundColour[1], 3) + ", " + addZero(backgroundColour[2], 3) + ")"
                        activeColourToWrite = "(" + addZero(activeColour[0], 3) + ", " + addZero(activeColour[1], 3) + ", " + addZero(activeColour[2], 3) + ")"
                        pauseColourToWrite = "(" + addZero(pauseColour[0], 3) + ", " + addZero(pauseColour[1], 3) + ", " + addZero(pauseColour[2], 3) + ")"
                        stopColourToWrite = "(" + addZero(stopColour[0], 3) + ", " + addZero(stopColour[1], 3) + ", " + addZero(stopColour[2], 3) + ")"

                        crossImage, WB = determineDarkOrLight(backgroundColour)
                        cross = pygame.image.load(crossImage).convert_alpha()  #Header bar cross
                        captionText = captionFont.render("Timer", True, WB).convert_alpha()
                        colourPreferences = open("userColours.txt", "w+")
                        colourPreferences.write("Background colour (RGB): " + backgroundColourToWrite + "\nActive counting colour (RGB): " + activeColourToWrite + "\nPause Colour (RGB): " + pauseColourToWrite + "\nStop Colour (RGB): " + stopColourToWrite + "\n")
                        colourPreferences.close()
                    elif (PAUSE == True and millisecondsRemaining > 0):   #Pause/play
                        PAUSE = False
                        if EDIT == True:
                            EDIT = False
                            millisecondsRemaining = int(hoursLeft)*3600000 + int(minutesLeft)*60000 + int(secondsLeft)*1000
                            hoursLeft, minutesLeft, secondsLeft = getTimeLeft(millisecondsRemaining)
                            initialTimeLength = len(timeLeftList)
                            editPosition = 1
                    else:
                        PAUSE = True
                elif STOP == False and event.button == RIGHT: #Move window
                    mouseX, mouseY = getMousePos()
                    distFromTop = mouseY-windowPosY #distance from the top of the window
                    MOVE = True
                    rightClickDelay = True
                elif not EDIT and (event.button == SCROLLUP or event.button == SCROLLDOWN) and inRect(windowPosX, windowPosY, currentSizeX, currentSizeY): #if user scrolls and mouse is in window
                    if event.button == SCROLLDOWN:
                        scrollIncrement = -scrollIncrement
                    unitMultiplier = unitHoverPos(windowPosX, (182+hoursWidth+minutesWidth), (121+hoursWidth)) #returns 1000, 60000 and 3600000 if hovering over seconds, minutes and hours respectively
                    millisecondsRemaining = millisecondsRemaining+(scrollIncrement*unitMultiplier)
                    PAUSE, BEEP, STOP = True, True, False   #pause when time is changed, next time it stops it will beep
                    hoursLeft, minutesLeft, secondsLeft = getTimeLeft(millisecondsRemaining)
            elif event.type == pygame.MOUSEBUTTONUP and event.button == RIGHT and STOP == False:  #placing window
                if rightClickDelay and MOVE:
                    rightClickDelay = False #ignore initial right MOUSEBUTTONUP event
                elif rightClickDelay == False and MOVE:
                    MOVE = False    #place window
            if millisecondsRemaining < 0:
                millisecondsRemaining = 0
                hoursLeft, minutesLeft, secondsLeft = getTimeLeft(millisecondsRemaining)
                PAUSE, BEEP, STOP = True, True, False   #pause when time is changed, next time it stops it will beep

            if event.type == TICKEVENT and PAUSE == False:  #passage of time
                millisecondsRemaining = millisecondsRemaining-increment
                hoursLeft, minutesLeft, secondsLeft = getTimeLeft(millisecondsRemaining)

        #no milliseconds remain >> stop
        if millisecondsRemaining <= 0 and not PAUSE:
            millisecondsRemaining = 0
            hoursLeft, minutesLeft, secondsLeft = getTimeLeft(millisecondsRemaining)
            STOP, PAUSE, MOVE, rightClickDelay = True, True, False, False

        if MOVE:    #window is moving
            mouseX, mouseY = getMousePos()
            if (mouseY-distFromTop) < (displayYResolution-40-currentSizeY): #if mouse is above lowest point (window cannot be placed over start icon)
                windowPosY = mouseY-distFromTop
                timerWindow, currentSizeX, currentSizeY = setWindow(windowPosX, windowPosY, maxSizeX, maxSizeY, "Timer", background = backgroundColour) #setWindow(x, y, width, height, caption, background)
        else:
            if millisecondsRemaining > initialMillisecondsRemaining:    #sets greatest time to be initial time
                initialMillisecondsRemaining = millisecondsRemaining

            if millisecondsRemaining < 359999999 and len(timeLeftList) <= 5:   #allows window to grow when hours>99
                maxSizeX = initialmaxSizeX
            elif millisecondsRemaining >= 359999999:
                extraDigitsPixels = 59*(len(str(hoursLeft))-2)
                maxSizeX = initialmaxSizeX + extraDigitsPixels
            else:
                extraDigitsPixels = 59*(len(timeLeftList)-6)
                maxSizeX = initialmaxSizeX + extraDigitsPixels

            #Gets colour to use for non-background surfaces
            currentColour = getColour(PAUSE, STOP, activeColour, pauseColour, stopColour)
            h = unitFont.render("h", 1, currentColour)
            m = unitFont.render("m", 1, currentColour)
            s = unitFont.render("s", 1, currentColour)

            if iconFontName == "segoemdl2":
                if millisecondsRemaining == 0:
                    clearOrBin = ""
                    clearOrBinX = 18
                else:
                    clearOrBin = ""
                    clearOrBinX = 16
                resetIcon, resetIconHoveredOver = iconFont.render("", True, currentColour).convert_alpha(), iconFont.render("", True, backgroundColour).convert_alpha()
                editIcon, editIconHoveredOver = iconFont.render("", True, currentColour).convert_alpha(), iconFont.render("", True, backgroundColour).convert_alpha()
                clearIcon, clearIconHoveredOver = iconFont.render(clearOrBin, True, currentColour).convert_alpha(), iconFont.render(clearOrBin, True, backgroundColour).convert_alpha()
                changeColourIcon, changeColourIconHoveredOver = iconFont.render("", True, currentColour).convert_alpha(), iconFont.render("", True, backgroundColour).convert_alpha()
            else:
                if millisecondsRemaining == 0:
                    clearOrBin = ""
                    clearOrBinX = 18
                else:
                    clearOrBin = ""
                    clearOrBinX = 16
                resetIcon, resetIconHoveredOver = iconFont.render("", True, currentColour).convert_alpha(), iconFont.render("", True, backgroundColour).convert_alpha()
                editIcon, editIconHoveredOver = iconFont.render("", True, currentColour).convert_alpha(), iconFont.render("", True, backgroundColour).convert_alpha()
                clearIcon, clearIconHoveredOver = iconFont.render(clearOrBin, True, currentColour).convert_alpha(), iconFont.render(clearOrBin, True, backgroundColour).convert_alpha()
                changeColourIcon, changeColourIconHoveredOver = iconFont.render("", True, currentColour).convert_alpha(), iconFont.render("", True, backgroundColour).convert_alpha()
            #Manage window size
            #This is where beep is crucial
            #if the time has just run out or the window is minimised and the mouse has hovered over window...)
            if ((BEEP and STOP) or (currentSizeX != maxSizeX and inRect(windowPosX, windowPosY, currentSizeX, currentSizeY))):
                timerWindow, currentSizeX, currentSizeY = setWindow(windowPosX, windowPosY, maxSizeX, maxSizeY, "Timer", background = backgroundColour) #setWindow(x, y, width, height, caption, background)
            #if the window is not minimised but the mouse is outside the window
            elif currentSizeX != minSizeX and not inRect(windowPosX, windowPosY, currentSizeX, currentSizeY):
                timerWindow, currentSizeX, currentSizeY = setWindow(windowPosX, windowPosY, minSizeX, minSizeY, "Timer", background = backgroundColour) #setWindow(x, y, width, height, caption, background)
            #Fills window
            timerWindow.fill(backgroundColour)

            #Draw progress bar
            #progressBar(width, maxheight, initial, remaining)
            #rect(Surface, color, Rect, width=0)
            progressRect = progressBar(minSizeX, minSizeY, initialMillisecondsRemaining, millisecondsRemaining)
            pygame.draw.rect(timerWindow, currentColour, progressRect)
            #Draws things on maximized window
            if currentSizeX == maxSizeX:
                resetIconToBlit = resetIcon
                editIconToBlit = editIcon
                clearIconToBlit = clearIcon
                changeColourIconToBlit = changeColourIcon
                if inRect((maxSizeX-48+windowPosX), windowPosY, 48, 32):  #Close box hovered tover
                    pygame.draw.rect(timerWindow, currentColour, Rect(maxSizeX-48, 0, 48, 32))
                if inRect((minSizeX+windowPosX), windowPosY, (maxSizeY//4), (maxSizeY//4)): #reset hovered
                    pygame.draw.rect(timerWindow, currentColour, Rect(minSizeX, 0, (maxSizeY//4), (maxSizeY//4)))
                    resetIconToBlit = resetIconHoveredOver
                elif inRect((minSizeX+windowPosX), (windowPosY+maxSizeY//4), (maxSizeY//4), (maxSizeY//4)): #edit hovered
                    pygame.draw.rect(timerWindow, currentColour, Rect(minSizeX, (maxSizeY//4), (maxSizeY//4), (maxSizeY//4)))
                    editIconToBlit = editIconHoveredOver
                elif inRect((minSizeX+windowPosX), (windowPosY+maxSizeY//2), (maxSizeY//4), (maxSizeY//4)): #clear hovered
                    pygame.draw.rect(timerWindow, currentColour, Rect(minSizeX, (maxSizeY//2), (maxSizeY//4), (maxSizeY//4)))
                    clearIconToBlit = clearIconHoveredOver
                elif inRect((minSizeX+windowPosX), (windowPosY+(3*maxSizeY//4)), (maxSizeY//4), (maxSizeY//4)): #colour hovered
                    pygame.draw.rect(timerWindow, currentColour, Rect(minSizeX, (3*maxSizeY//4), (maxSizeY//4), (maxSizeY//4)))
                    changeColourIconToBlit = changeColourIconHoveredOver


                timerWindow.blit(resetIconToBlit, (18, 11))
                timerWindow.blit(editIconToBlit, (18, 61))
                timerWindow.blit(clearIconToBlit, (clearOrBinX, 111))
                timerWindow.blit(changeColourIconToBlit, (18, 161))
                timerWindow.blit(cross, (maxSizeX-48, 0))
                timerWindow.blit(captionText, (66, 7))

                if EDIT:
                    if timeLeftList[0] != "0":
                        hoursLeft = addZero(hoursLeft, (len(timeLeftList) - 3))
                    else:
                        hoursLeft = addZero(hoursLeft, 2)
                    minutesLeft = addZero(minutesLeft, 2)
                    secondsLeft = addZero(secondsLeft, 2)
                    timeLeft = hoursLeft + "  " + minutesLeft + "  " + secondsLeft
                    hoursWidth = uiFontBig.render(hoursLeft, 1, BLACK).get_width()
                    minutesWidth = uiFontBig.render(minutesLeft, 1, BLACK).get_width()
                    secondsWidth = uiFontBig.render(secondsLeft, 1, BLACK).get_width()
                    timerWindow.blit(h, ((60+hoursWidth), 95))
                    timerWindow.blit(m, ((121+hoursWidth+minutesWidth), 95))
                    timerWindow.blit(s, ((182+hoursWidth+minutesWidth+secondsWidth), 94))
                elif PAUSE:
                    hoursLeft = addZero(hoursLeft, 2)
                    minutesLeft = addZero(minutesLeft, 2)
                    secondsLeft = addZero(secondsLeft, 2)
                    hoursWidth = uiFontBig.render(hoursLeft, 1, BLACK).get_width()
                    minutesWidth = uiFontBig.render(minutesLeft, 1, BLACK).get_width()
                    secondsWidth = uiFontBig.render(secondsLeft, 1, BLACK).get_width()
                    timeLeft = hoursLeft + "  " + minutesLeft + "  " + secondsLeft
                    timerWindow.blit(h, ((60+hoursWidth), 95))
                    timerWindow.blit(m, ((121+hoursWidth+minutesWidth), 95))
                    timerWindow.blit(s, ((182+hoursWidth+minutesWidth+secondsWidth), 94))
                elif not minutesLeft and not hoursLeft:
                    secondsLeft = str(secondsLeft)
                    secondsWidth = uiFontBig.render(secondsLeft, 1, BLACK).get_width()
                    timeLeft = secondsLeft
                    timerWindow.blit(s, ((60+secondsWidth), 94))
                elif not hoursLeft:
                    minutesLeft = str(minutesLeft)
                    secondsLeft = str(secondsLeft)
                    minutesWidth = uiFontBig.render(minutesLeft, 1, BLACK).get_width()
                    secondsWidth = uiFontBig.render(secondsLeft, 1, BLACK).get_width()
                    timeLeft = minutesLeft + "  " + secondsLeft
                    timerWindow.blit(m, ((60+minutesWidth), 95))
                    timerWindow.blit(s, ((121+minutesWidth+secondsWidth), 94))
                elif not minutesLeft:
                    hoursLeft = str(hoursLeft)
                    secondsLeft = str(secondsLeft)
                    hoursWidth = uiFontBig.render(hoursLeft, 1, BLACK).get_width()
                    secondsWidth = uiFontBig.render(secondsLeft, 1, BLACK).get_width()
                    timeLeft = hoursLeft + "  " + secondsLeft
                    timerWindow.blit(h, ((60+hoursWidth), 95))
                    timerWindow.blit(s, ((121+hoursWidth+secondsWidth), 94))
                else:
                    hoursLeft = str(hoursLeft)
                    minutesLeft = str(minutesLeft)
                    secondsLeft = str(secondsLeft)
                    hoursWidth = uiFontBig.render(hoursLeft, 1, BLACK).get_width()
                    minutesWidth = uiFontBig.render(minutesLeft, 1, BLACK).get_width()
                    secondsWidth = uiFontBig.render(secondsLeft, 1, BLACK).get_width()
                    timeLeft = hoursLeft + "  " + minutesLeft + "  " + secondsLeft
                    timerWindow.blit(h, ((60+hoursWidth), 95))
                    timerWindow.blit(m, ((121+hoursWidth+minutesWidth), 95))
                    timerWindow.blit(s, ((182+hoursWidth+minutesWidth+secondsWidth), 94))

                timeText = uiFontBig.render(timeLeft, 1, currentColour)
                timeText = timeText.convert_alpha()
                timerWindow.blit(timeText, (55, 24))
                pygame.display.update()
                if BEEP and STOP:
                    for x in range(5):
                        Beep(stopSoundFrequency, stopSoundDuration)
                    BEEP = False
        pygame.display.update()
        fpsClock.tick(30)
main()

This snippet took 0.05 seconds to highlight.

Back to the Entry List or Home.

Delete this entry (admin only).