From 392a0c5a4d19da8f06b3ccab8b9d7fdcd558e64d Mon Sep 17 00:00:00 2001 From: Brian Jordan Date: Fri, 27 Jun 2008 18:17:45 +0000 Subject: Initial commit --- (limited to 'elements/menu.py') diff --git a/elements/menu.py b/elements/menu.py new file mode 100755 index 0000000..1c8a417 --- /dev/null +++ b/elements/menu.py @@ -0,0 +1,237 @@ +""" +This file is part of the 'Elements' Project +Elements is a 2D Physics API for Python (supporting Box2D2) + +Copyright (C) 2008, The Elements Team, + +Home: http://elements.linuxuser.at +IRC: #elements on irc.freenode.org + +Code: http://www.assembla.com/wiki/show/elements + svn co http://svn2.assembla.com/svn/elements + +License: GPLv3 | See LICENSE for the full text +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +""" +import pygame +from pygame.locals import * + +import tools + +COLOR_HEX_BLUE1 = "6491a4" +COLOR_HEX_BLUE2 = "9ec9ff" + +class MenuItem: + # padding [px]: left, top, right, bottom + padding = (5, 2, 5, 2) + + def empty(self, *args): + pass + + def __init__(self, title, pos, userData, parent=None, callback=None): + self.title = title + self.userData = userData + self.parent = parent + self.childs = [] + + if self.parent: + self.visible = False + else: + self.visible = True + + if callback: + self.callback = callback + else: + self.callback = self.empty + + # Create Surface and Stuff :) + self.font = pygame.font.Font(None, 32) + text = self.font.render(title, 1, (255,255,255)) + + rx, ry, rw, rh = rect = text.get_rect() + pl, pt, pr, pb = self.padding + + s1 = pygame.Surface((rw+pl+pr, rh+pt+pb)) + s1.fill(tools.hex2rgb(COLOR_HEX_BLUE1)) + s1.blit(text, (pl, pt)) + + s2 = pygame.Surface((rw+pl+pr, rh+pt+pb)) + s2.fill(tools.hex2rgb(COLOR_HEX_BLUE2)) + s2.blit(text, (pl, pt)) + + self.rect = s1.get_rect().move(pos) + + self.surface_inactive = s1 + self.surface_active = s2 + + def pos_inside(self, pos): + if not self.visible: + return False + + x,y,w,h = self.rect + px, py = pos + + if px > x and px < x+w and py > y and py < y+h: + return True + else: + return False + +class MenuClass: + """ Important: Never delete an Item, just overwrite it if deleting, + else the menuitem id's get messed up + """ + # current active menu point it + focus = False + + # each item is stored as MenuItem + items = [] + + # where to start drawing + start_at = (0, 0) + + # menubar properties + height = 0 # px + width = 0 # px (set in set_width) + setWidth = False # if width was set by hand (if not, increase width by adding stuff) + + def __init__(self): + self.draw_at = self.start_at + + def set_width(self, width): + self.setWidth = True + self.width = width + + def addItem(self, title, callback=None, userData='', parent=None): + # Get position for the Item + if parent: draw_at = (0,0) + else: draw_at = self.draw_at + + # Create Items + M = MenuItem(title=title, pos=draw_at, userData=userData, parent=parent, callback=callback) + self.items.append(M) + + # Set a new position + x,y,w,h = M.rect + x, y = self.draw_at + + if parent: + # Set the info that the item has a child to the parent item + self.items[parent-1].childs.append(len(self.items)-1) + + else: + # New next drawing position + self.draw_at = (x+w, y) + + # Adjust the width of the menu bar + if not self.setWidth: + self.width = x+w + + # Adjust the height of the menu bar + if h > self.height: self.height = h + 2 + + # Return array id of this item + return len(self.items) + + def click(self, pos): + """ Checks a click for menuitems and starts the callback if found + + Return: True if a menu item was found or hit the MenuBar, and False if not + """ + focus_in = self.focus + + found = False + for i in xrange(len(self.items)): + item = self.items[i] + if item.pos_inside(pos): + found = True + item.callback(item.title, item.userData) + + # Expand the menu if necessary + if len(item.childs) > 0: + self.focus = i+1 + + # Close any opened menu windows if clicked somewhere else + if self.focus == focus_in: + self.focus = False + self.subwin_rect = (0,0,0,0) + for item in self.items: + if item.parent: + item.visible = False + + # Check if click is inside menubar + x,y = pos + mx, my = self.start_at + + if found: + return True + else: + return False + + def draw(self, surface): + """ Draw the menu with pygame on a given surface + """ + s = pygame.Surface((self.width, self.height)) + s.fill(tools.hex2rgb(COLOR_HEX_BLUE1)) + + surface.blit(s, (0,0)) + + for i in xrange(len(self.items)): + item = self.items[i] + if not item.parent: + x,y,w,h = item.rect + if self.focus == i+1: + surface.blit(item.surface_active, (x,y)) + else: + surface.blit(item.surface_inactive, (x,y)) + + # If a menu item is open, draw that + if self.focus: + width = 0 + height = 0 + + i = [] + for j in self.items: + if j.parent == self.focus: + i.append(j) + x, y, w, h = j.rect + if w > width: width = w + height += h + + if len(i) > 0: + s = pygame.Surface((width, height)) + s.fill(tools.hex2rgb(COLOR_HEX_BLUE1)) + + # Parent Coordinates + px, py, pw, ph = self.items[self.focus-1].rect + + # y Counter + y = 0 + + for item in i: + item.visible = True + s.blit(item.surface_inactive, (0, y)) + + ix, iy, iw, ih = item.rect + if (ix, iy) == (0, 0): + item.rect = item.rect.move((px, y+ph)) + ix, iy, iw, ih = item.rect + + if iw < width: + item.rect = (ix,iy,width,ih) + + y += ih + + surface.blit(s, (px,py+ph)) + self.subwin_rect = s.get_rect().move(px, py+ph) + -- cgit v0.9.1