comparison engine/python/fife/extensions/pychan/widgets/containers.py @ 378:64738befdf3b

bringing in the changes from the build_system_rework branch in preparation for the 0.3.0 release. This commit will require the Jan2010 devkit. Clients will also need to be modified to the new way to import fife.
author vtchill@33b003aa-7bff-0310-803a-e67f0ece8222
date Mon, 11 Jan 2010 23:34:52 +0000
parents
children
comparison
equal deleted inserted replaced
377:fe6fb0e0ed23 378:64738befdf3b
1 # -*- coding: utf-8 -*-
2
3 # ####################################################################
4 # Copyright (C) 2005-2009 by the FIFE team
5 # http://www.fifengine.de
6 # This file is part of FIFE.
7 #
8 # FIFE is free software; you can redistribute it and/or
9 # modify it under the terms of the GNU Lesser General Public
10 # License as published by the Free Software Foundation; either
11 # version 2.1 of the License, or (at your option) any later version.
12 #
13 # This library is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 # Lesser General Public License for more details.
17 #
18 # You should have received a copy of the GNU Lesser General Public
19 # License along with this library; if not, write to the
20 # Free Software Foundation, Inc.,
21 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 # ####################################################################
23
24 from common import *
25 from widget import Widget
26 from layout import VBoxLayoutMixin, HBoxLayoutMixin
27
28 class Container(Widget):
29 """
30 This is the basic container class. It provides space in which child widgets can
31 be position via the position attribute. If you want to use the layout engine,
32 you have to use derived containers with vertical or horizontal orientation
33 (L{VBox} or L{HBox})
34
35 New Attributes
36 ==============
37
38 - padding - Integer: Not used in the Container class istelf, distance between child widgets.
39 - background_image - Set this to a GuiImage or a resource location (simply a filename).
40 The image will be tiled over the background area.
41 - opaque - Boolean: Whether the background should be drawn at all. Set this to False
42 to make the widget transparent.
43 - children - Just contains the list of contained child widgets. Do NOT modify.
44 """
45
46 ATTRIBUTES = Widget.ATTRIBUTES + [ IntAttr('padding'), Attr('background_image'), BoolAttr('opaque'),PointAttr('margins') ]
47
48 def __init__(self,padding=5,margins=(5,5),_real_widget=None, **kwargs):
49 self.real_widget = _real_widget or fife.Container()
50 self.children = []
51 self.margins = margins
52 self.padding = padding
53 self._background = []
54 self._background_image = None
55 super(Container,self).__init__(**kwargs)
56
57 def addChild(self, widget):
58 widget.parent = self
59 self.children.append(widget)
60 self.real_widget.add(widget.real_widget)
61
62 def insertChild(self, widget, position):
63 if position > len(self.children) or 0-position > len(self.children):
64 print "insertChild: Warning: Index overflow.",
65 if position >= 0:
66 self.addChild(widget)
67 else:
68 self.insertChild(widget, 0)
69 return
70
71 children = self.children[0:position]+[widget]+self.children[position:]
72 #assert len(children) == len(self.children) + 1
73 self.removeAllChildren()
74 for child in children:
75 self.addChild(child)
76
77 def insertChildBefore(self, widget, before):
78 if before not in self.children:
79 raise RuntimeError("Couldn't find widget %s as child of %s - in insertChildBefore" % (str(widget),str(before)))
80 self.insertChild(widget, self.children.index(before))
81
82 def removeChild(self,widget):
83 if not widget in self.children:
84 raise RuntimeError("%s does not have %s as direct child widget." % (str(self),str(widget)))
85 self.children.remove(widget)
86 self.real_widget.remove(widget.real_widget)
87 widget.parent = None
88
89 def add(self,*widgets):
90 print "PyChan: Deprecation warning: Please use 'addChild' or 'addChildren' instead."
91 self.addChildren(*widgets)
92
93 def getMaxChildrenWidth(self):
94 if not self.children: return 0
95 return max(widget.width for widget in self.children)
96
97 def getMaxChildrenHeight(self):
98 if not self.children: return 0
99 return max(widget.height for widget in self.children)
100
101 def deepApply(self,visitorFunc, leaves_first = True):
102 if leaves_first:
103 for child in self.children:
104 child.deepApply(visitorFunc, leaves_first = leaves_first)
105 visitorFunc(self)
106 if not leaves_first:
107 for child in self.children:
108 child.deepApply(visitorFunc, leaves_first = leaves_first)
109
110 def beforeShow(self):
111 self._resetTiling()
112
113 def _resetTiling(self):
114 image = self._background_image
115 if image is None:
116 return
117
118 back_w,back_h = self.width, self.height
119 image_w, image_h = image.getWidth(), image.getHeight()
120
121 map(self.real_widget.remove,self._background)
122
123 # Now tile the background over the widget
124 self._background = []
125 icon = fife.Icon(image)
126 x, w = 0, image_w
127 while x < back_w:
128 y, h = 0, image_h
129 while y < self.height:
130 icon = fife.Icon(image)
131 icon.setPosition(x,y)
132 self._background.append(icon)
133 y += h
134 x += w
135 map(self.real_widget.add,self._background)
136 for tile in self._background:
137 tile.requestMoveToBottom()
138
139 def setBackgroundImage(self,image):
140 self._background = getattr(self,'_background',None)
141 if image is None:
142 self._background_image = image
143 map(self.real_widget.remove,self._background)
144 self._background = []
145 return
146 # Background generation is done in _resetTiling
147
148 if not isinstance(image, fife.GuiImage):
149 image = get_manager().loadImage(image)
150 self._background_image = image
151
152 def getBackgroundImage(self): return self._background_image
153 background_image = property(getBackgroundImage,setBackgroundImage)
154
155 def _setOpaque(self,opaque): self.real_widget.setOpaque(opaque)
156 def _getOpaque(self): return self.real_widget.isOpaque()
157 opaque = property(_getOpaque,_setOpaque)
158
159 class VBox(VBoxLayoutMixin,Container):
160 """
161 A vertically aligned box - for containement of child widgets.
162
163 Widgets added to this container widget, will layout on top of each other.
164 Also the minimal width of the container will be the maximum of the minimal
165 widths of the contained widgets.
166
167 The default alignment is to the top. This can be changed by adding a Spacer
168 to the widget at any point (but only one!). The spacer will expand, so that
169 widgets above the spacer are aligned to the top, while widgets below the spacer
170 are aligned to the bottom.
171 """
172 DEFAULT_HEXPAND = 0
173 DEFAULT_VEXPAND = 1
174
175 def __init__(self,padding=5,**kwargs):
176 super(VBox,self).__init__(**kwargs)
177 self.padding = padding
178
179
180 class HBox(HBoxLayoutMixin,Container):
181 """
182 A horizontally aligned box - for containement of child widgets.
183
184 Please see L{VBox} for details - just change the directions :-).
185 """
186 DEFAULT_HEXPAND = 1
187 DEFAULT_VEXPAND = 0
188
189 def __init__(self,padding=5,**kwargs):
190 super(HBox,self).__init__(**kwargs)
191 self.padding = padding
192
193 class Window(VBoxLayoutMixin,Container):
194 """
195 A L{VBox} with a draggable title bar aka a window
196
197 New Attributes
198 ==============
199
200 - title: The Caption of the window
201 - titlebar_height: The height of the window title bar
202 """
203
204 ATTRIBUTES = Container.ATTRIBUTES + [ UnicodeAttr('title'), IntAttr('titlebar_height') ]
205
206 def __init__(self,title=u"title",titlebar_height=0,**kwargs):
207 super(Window,self).__init__(_real_widget = fife.Window(), **kwargs)
208 if titlebar_height == 0:
209 titlebar_height = self.real_font.getHeight() + 4
210 self.titlebar_height = titlebar_height
211 self.title = title
212
213 # Override explicit positioning
214 self.position_technique = "automatic"
215
216
217 def _getTitle(self): return gui2text(self.real_widget.getCaption())
218 def _setTitle(self,text): self.real_widget.setCaption(text2gui(text))
219 title = property(_getTitle,_setTitle)
220
221 def _getTitleBarHeight(self): return self.real_widget.getTitleBarHeight()
222 def _setTitleBarHeight(self,h): self.real_widget.setTitleBarHeight(h)
223 titlebar_height = property(_getTitleBarHeight,_setTitleBarHeight)
224
225 # Hackish way of hiding that title bar height in the perceived height.
226 # Fixes VBox calculation
227 def _setHeight(self,h):
228 h = max(self.min_size[1],h)
229 h = min(self.max_size[1],h)
230 self.real_widget.setHeight(h + self.titlebar_height)
231 def _getHeight(self): return self.real_widget.getHeight() - self.titlebar_height
232 height = property(_getHeight,_setHeight)
233