Skip to content

Commit

Permalink
Merge pull request #54 from AustL/popups
Browse files Browse the repository at this point in the history
Popups
  • Loading branch information
AustL authored Sep 25, 2022
2 parents 617c79f + f6a1f44 commit 76a661d
Show file tree
Hide file tree
Showing 5 changed files with 205 additions and 6 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ while run:

## Prerequisites

* [Python 3](https://www.python.org/downloads) `>= 3.7`
* [Python 3](https://www.python.org/downloads) `>= 3.10`
* [Pygame](https://www.pygame.org/wiki/GettingStarted) `>= 2.0.0`

## Installation
Expand Down
126 changes: 126 additions & 0 deletions pygame_widgets/popup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
import pygame
import tkinter as tk
from tkinter import messagebox
from enum import Enum

import pygame_widgets
from pygame_widgets.widget import WidgetBase

tk.Tk().wm_withdraw()


class PopupType(Enum):
INFO = 0
ERROR = 1
WARNING = 2
QUESTION = 3
OK_CANCEL = 4
YES_NO = 5
YES_NO_CANCEL = 6
RETRY_CANCEL = 7


class Popup(WidgetBase):
def __init__(self, win: pygame.Surface, x: int, y: int, width: int, height: int, popupType: PopupType,
title: str, text: str, trigger=lambda *args: None, *buttons, **kwargs):
super().__init__(win, x, y, width, height)
self.popupType = popupType
self.title = title
self.text = text
self.trigger = trigger
self.buttons = buttons

self.margin = kwargs.get('margin', 20)

self.titleColour = kwargs.get('titleColour', (0, 0, 0))
self.titleSize = kwargs.get('titleSize', 40)
self.titleFont = kwargs.get('titleFont', pygame.font.SysFont('calibri', self.titleSize, True))
self.titleRect = self.alignTitleRect()

self.textColour = kwargs.get('textColour', (0, 0, 0))
self.textSize = kwargs.get('textSize', 18)
self.textFont = kwargs.get('textFont', pygame.font.SysFont('calibri', self.textSize))
self.textRect = self.alignTextRect()

self.radius = kwargs.get('radius', 0)

self.colour = kwargs.get('colour', (150, 150, 150))
self.shadowDistance = kwargs.get('shadowDistance', 0)
self.shadowColour = kwargs.get('shadowColour', (210, 210, 180))

self.result = None

self.hide()

def alignTitleRect(self):
return pygame.Rect(self._x + self.margin, self._y + self.margin,
self._width - self.margin * 2, self._height // 3 - self.margin * 2)

def alignTextRect(self):
return pygame.Rect(self._x + self.margin, self._y + self._height // 3,
self._width - self.margin * 2, self._height // 2 - self.margin * 2)

def listen(self, events):
if self.trigger():
self.show()
messagebox.showinfo(self.title, self.text)

def draw(self):
pass

def show(self):
super().show()
match self.popupType:
case PopupType.INFO:
messagebox.showinfo(self.title, self.text)
case PopupType.ERROR:
messagebox.showerror(self.title, self.text)
case PopupType.WARNING:
messagebox.showwarning(self.title, self.text)
case PopupType.QUESTION:
self.result = messagebox.askquestion(self.title, self.text)
case PopupType.OK_CANCEL:
self.result = messagebox.askokcancel(self.title, self.text)
case PopupType.YES_NO:
self.result = messagebox.askyesno(self.title, self.text)
case PopupType.YES_NO_CANCEL:
self.result = messagebox.askyesnocancel(self.title, self.text)
case PopupType.RETRY_CANCEL:
self.result = messagebox.askretrycancel(self.title, self.text)

def getResult(self):
return self.result


if __name__ == '__main__':
from pygame_widgets.button import Button

def setButtonColour():
if popup.getResult():
button.setInactiveColour('green')
elif popup.getResult() == False:
button.setInactiveColour('red')

pygame.init()
win = pygame.display.set_mode((600, 600))

popup = Popup(win, 100, 100, 400, 400, PopupType.YES_NO, 'Popup',
'This is the text in the popup. Would you like to continue? The buttons below can be customised.',
radius=20, textSize=20)

button = Button(win, 100, 100, 400, 400, text='Popup', onClick=popup.show)

run = True
while run:
events = pygame.event.get()
for event in events:
if event.type == pygame.QUIT:
pygame.quit()
run = False
quit()

win.fill((255, 255, 255))

pygame_widgets.update(events)
pygame.display.update()
setButtonColour()
39 changes: 39 additions & 0 deletions pygame_widgets/util.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import pygame


def drawText(win, text, colour, rect, font, align='centre'):
rect = pygame.Rect(rect)
y = rect.top
lineSpacing = -2

fontHeight = font.size('Tg')[1]

while text:
i = 1

if y + fontHeight > rect.bottom:
break

while font.size(text[:i])[0] < rect.width and i < len(text):
i += 1

if i < len(text):
i = text.rfind(' ', 0, i) + 1

image: pygame.Surface = font.render(text[:i], 1, colour)

imageRect: pygame.Rect = image.get_rect()

imageRect.center = rect.center

if align == 'left':
imageRect.left = rect.left
elif align == 'right':
imageRect.right = rect.right

win.blit(image, (imageRect.left, y))
y += fontHeight + lineSpacing

text = text[i:]

return text
40 changes: 37 additions & 3 deletions pygame_widgets/widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,17 @@ def listen(self, events):
def draw(self):
pass

def __repr__(self):
return f'{type(self).__name__}(x = {self._x}, y = {self._y}, width = {self._width}, height = {self._height})'

def contains(self, x, y):
return (self._x < x - self.win.get_abs_offset()[0] < self._x + self._width) and \
(self._y < y - self.win.get_abs_offset()[1] < self._y + self._height)

def hide(self):
self._hidden = True
if not self._isSubWidget:
WidgetHandler.moveToBottom(self)

def show(self):
self._hidden = False
Expand All @@ -65,6 +70,9 @@ def isSubWidget(self):
def moveToTop(self):
WidgetHandler.moveToTop(self)

def moveToBottom(self):
WidgetHandler.moveToBottom(self)

def moveX(self, x):
self._x += x

Expand Down Expand Up @@ -137,6 +145,13 @@ def setWidth(self, width):
def setHeight(self, height):
self._height = height

def setIsSubWidget(self, isSubWidget):
self._isSubWidget = isSubWidget
if isSubWidget:
WidgetHandler.removeWidget(self)
else:
WidgetHandler.addWidget(self)


class WidgetHandler:
_widgets: [WidgetBase] = []
Expand All @@ -158,12 +173,31 @@ def main(events: [Event]) -> None:

@staticmethod
def addWidget(widget: WidgetBase) -> None:
WidgetHandler._widgets.append(widget)
if widget not in WidgetHandler._widgets:
WidgetHandler._widgets.append(widget)

@staticmethod
def removeWidget(widget: WidgetBase) -> None:
try:
WidgetHandler._widgets.remove(widget)
except ValueError:
print(f'Error: Tried to remove {widget} when {widget} not in WidgetHandler.')

@staticmethod
def moveToTop(widget: WidgetBase):
WidgetHandler._widgets.remove(widget)
WidgetHandler.addWidget(widget)
try:
WidgetHandler._widgets.remove(widget)
WidgetHandler.addWidget(widget)
except ValueError:
print(f'Error: Tried to move {widget} to top when {widget} not in WidgetHandler.')

@staticmethod
def moveToBottom(widget: WidgetBase):
try:
WidgetHandler._widgets.remove(widget)
WidgetHandler._widgets.insert(0, widget)
except ValueError:
print(f'Error: Tried to move {widget} to bottom when {widget} not in WidgetHandler.')

@staticmethod
def getWidgets() -> [WidgetBase]:
Expand Down
4 changes: 2 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

setuptools.setup(
name='pygame-widgets',
version='1.0.0',
version='1.1.0',
author='AustL',
author_email='21chydra@gmail.com',
description='Widgets for use with Pygame',
Expand All @@ -18,7 +18,7 @@
'License :: OSI Approved :: MIT License',
'Operating System :: OS Independent'
],
python_requires='>=3.6',
python_requires='>=3.10',
license='MIT',
install_requires=['pygame>=2.0.0']
)

0 comments on commit 76a661d

Please sign in to comment.