Package fife :: Package extensions :: Package pychan :: Package widgets' :: Module containers
[hide private]
[frames] | no frames]

Source Code for Module fife.extensions.pychan.widgets'.containers

  1  # -*- coding: utf-8 -*- 
  2   
  3  # #################################################################### 
  4  #  Copyright (C) 2005-2011 by the FIFE team 
  5  #  http://www.fifengine.net 
  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'), 47 Attr('background_image'), 48 BoolAttr('opaque'), 49 PointAttr('margins') 50 ] 51 52 DEFAULT_OPAQUE = True 53 DEFAULT_MARGINS = 5,5 54 DEFAULT_PADDING = 5 55 DEFAULT_BACKGROUND = None 56
57 - def __init__(self, 58 parent = None, 59 name = None, 60 size = None, 61 min_size = None, 62 max_size = None, 63 helptext = None, 64 position = None, 65 style = None, 66 hexpand = None, 67 vexpand = None, 68 font = None, 69 base_color = None, 70 background_color = None, 71 foreground_color = None, 72 selection_color = None, 73 border_size = None, 74 position_technique = None, 75 is_focusable = None, 76 comment = None, 77 padding = None, 78 background_image = None, 79 opaque = None, 80 margins = None, 81 _real_widget = None):
82 83 self.real_widget = _real_widget or fife.Container() 84 self.children = [] 85 self.children_position_cache = [] 86 self.hidden_children = [] 87 self._background = [] 88 self._background_image = None 89 self.background_image = self.DEFAULT_BACKGROUND 90 self.margins = self.DEFAULT_MARGINS 91 self.padding = self.DEFAULT_PADDING 92 self.opaque = self.DEFAULT_OPAQUE 93 94 super(Container,self).__init__(parent=parent, 95 name=name, 96 size=size, 97 min_size=min_size, 98 max_size=max_size, 99 helptext=helptext, 100 position=position, 101 style=style, 102 hexpand=hexpand, 103 vexpand=vexpand, 104 font=font, 105 base_color=base_color, 106 background_color=background_color, 107 foreground_color=foreground_color, 108 selection_color=selection_color, 109 border_size=border_size, 110 position_technique=position_technique, 111 is_focusable=is_focusable, 112 comment=comment) 113 114 if margins is not None: self.margins = margins 115 if padding is not None: self.padding = padding 116 if opaque is not None: self.opaque = opaque 117 if background_image is not None: self.background_image = background_image
118
119 - def clone(self, prefix):
120 containerClone = Container(None, 121 self._createNameWithPrefix(prefix), 122 self.size, 123 self.min_size, 124 self.max_size, 125 self.helptext, 126 self.position, 127 self.style, 128 self.hexpand, 129 self.vexpand, 130 self.font, 131 self.base_color, 132 self.background_color, 133 self.foreground_color, 134 self.selection_color, 135 self.border_size, 136 self.position_technique, 137 self.is_focusable, 138 self.comment, 139 self.padding, 140 self.background_image, 141 self.opaque, 142 self.margins) 143 144 containerClone.addChildren(self._cloneChildren(prefix)) 145 146 return containerClone
147 148
149 - def addChild(self, widget):
150 """ 151 Adds a child widget to the container. 152 153 This makes the childs widgets visible state the same as the containers. 154 i.e. if the containter is visible the child will be as well and if the 155 container widget is hidden so will the child. The child however WILL 156 be shown when you show the container widget. If you want the child to 157 be hidden when you show the container widget you must call child.hide(). 158 """ 159 160 widget.parent = self 161 widget._visible = self._visible 162 self.children.append(widget) 163 self.children_position_cache.append(widget) 164 self.real_widget.add(widget.real_widget) 165 166 #update the states of the child widgets. This does not actually call 167 #the show() or hide() functions of the widget. 168 if self._visible: 169 def _show(shown_widget): 170 shown_widget._visible = True
171 172 self.deepApply(_show, shown_only=True) 173 else: 174 def _hide(hidden_widget): 175 hidden_widget._visible = False
176 177 self.deepApply(_hide) 178
179 - def insertChild(self, widget, position):
180 if position > len(self.children) or 0-position > len(self.children): 181 print "insertChild: Warning: Index overflow.", 182 if position >= 0: 183 self.addChild(widget) 184 else: 185 self.insertChild(widget, 0) 186 return 187 188 children = self.children[0:position]+[widget]+self.children[position:] 189 #assert len(children) == len(self.children) + 1 190 191 for child_to_remove in self.children[:]: 192 self.removeChild(child_to_remove) 193 194 for child in children: 195 self.addChild(child)
196
197 - def insertChildBefore(self, widget, before):
198 if before not in self.children: 199 raise RuntimeError("Couldn't find widget %s as child of %s - in insertChildBefore" % (str(widget),str(before))) 200 self.insertChild(widget, self.children.index(before))
201
202 - def removeChild(self,widget):
203 if not widget in self.children and not widget in self.hidden_children: 204 raise RuntimeError("%s does not have %s as direct child widget." % (str(self),str(widget))) 205 206 if widget in self.children: 207 self.children.remove(widget) 208 self.real_widget.remove(widget.real_widget) 209 210 if widget in self.children_position_cache: 211 self.children_position_cache.remove(widget) 212 213 if widget in self.hidden_children: 214 self.hidden_children.remove(widget) 215 216 widget.parent = None
217
218 - def hideChild(self, child):
219 if not child in self.children: 220 raise RuntimeError("%s does not have %s as direct child widget." % (str(self), str(child))) 221 222 self.hidden_children.append(child) 223 self.children.remove(child) 224 225 self.real_widget.remove(child.real_widget) 226 child._visible = False
227
228 - def showChild(self, child):
229 if not child in self.hidden_children: 230 return 231 232 self.hidden_children.remove(child) 233 234 children = self.children[:] 235 children_position_cache = self.children_position_cache[:] 236 hidden_children = self.hidden_children[:] 237 238 for widget in children: 239 self.removeChild(widget) 240 241 for child_widget in children_position_cache: 242 if not child_widget in hidden_children: 243 self.addChild(child_widget) 244 245 self.children_position_cache = children_position_cache[:] 246 self.hidden_children = hidden_children[:]
247
248 - def add(self,*widgets):
249 print "PyChan: Deprecation warning: Please use 'addChild' or 'addChildren' instead." 250 self.addChildren(*widgets)
251
252 - def getMaxChildrenWidth(self):
253 if not self.children: return 0 254 return max(widget.width for widget in self.children)
255
256 - def getMaxChildrenHeight(self):
257 if not self.children: return 0 258 return max(widget.height for widget in self.children)
259
260 - def deepApply(self,visitorFunc, leaves_first = True, shown_only = False):
261 if not shown_only: 262 children = self.children + self.hidden_children 263 else: 264 children = self.children 265 266 if leaves_first: 267 for child in children: 268 child.deepApply(visitorFunc, leaves_first = leaves_first, shown_only = shown_only) 269 visitorFunc(self) 270 if not leaves_first: 271 for child in children: 272 child.deepApply(visitorFunc, leaves_first = leaves_first, shown_only = shown_only)
273
274 - def beforeShow(self):
275 self._resetTiling()
276
277 - def _resetTiling(self):
278 image = self._background_image 279 if image is None: 280 return 281 282 back_w,back_h = self.width, self.height 283 image_w, image_h = image.getWidth(), image.getHeight() 284 285 map(self.real_widget.remove,self._background) 286 287 # Now tile the background over the widget 288 self._background = [] 289 icon = fife.Icon(image) 290 x, w = 0, image_w 291 while x < back_w: 292 y, h = 0, image_h 293 while y < self.height: 294 icon = fife.Icon(image) 295 icon.setPosition(x,y) 296 self._background.append(icon) 297 y += h 298 x += w 299 map(self.real_widget.add,self._background) 300 for tile in self._background: 301 tile.requestMoveToBottom()
302
303 - def setBackgroundImage(self,image):
304 self._background = getattr(self,'_background',None) 305 if image is None: 306 self._background_image = None 307 map(self.real_widget.remove,self._background) 308 self._background = [] 309 return 310 # Background generation is done in _resetTiling 311 312 if not isinstance(image, fife.GuiImage): 313 image = get_manager().loadImage(image) 314 self._background_image = image
315
316 - def getBackgroundImage(self): return self._background_image
317 background_image = property(getBackgroundImage,setBackgroundImage) 318
319 - def _setOpaque(self,opaque): self.real_widget.setOpaque(opaque)
320 - def _getOpaque(self): return self.real_widget.isOpaque()
321 opaque = property(_getOpaque,_setOpaque) 322
323 - def _cloneChildren(self, prefix):
324 """ 325 Clones each child and return the clones in a list. 326 """ 327 cloneList = [] 328 329 for child in self.children: 330 cloneList.append(child.clone(prefix)) 331 332 return cloneList
333
334 -class VBox(VBoxLayoutMixin,Container):
335 """ 336 A vertically aligned box - for containement of child widgets. 337 338 Widgets added to this container widget, will layout on top of each other. 339 Also the minimal width of the container will be the maximum of the minimal 340 widths of the contained widgets. 341 342 The default alignment is to the top. This can be changed by adding a Spacer 343 to the widget at any point (but only one!). The spacer will expand, so that 344 widgets above the spacer are aligned to the top, while widgets below the spacer 345 are aligned to the bottom. 346 """ 347 DEFAULT_HEXPAND = 0 348 DEFAULT_VEXPAND = 1 349
350 - def __init__(self, 351 parent = None, 352 name = None, 353 size = None, 354 min_size = None, 355 max_size = None, 356 helptext = None, 357 position = None, 358 style = None, 359 hexpand = None, 360 vexpand = None, 361 font = None, 362 base_color = None, 363 background_color = None, 364 foreground_color = None, 365 selection_color = None, 366 border_size = None, 367 position_technique = None, 368 is_focusable = None, 369 comment = None, 370 padding = None, 371 background_image = None, 372 opaque = None, 373 margins = None, 374 _real_widget = None):
375 376 super(VBox,self).__init__(parent=parent, 377 name=name, 378 size=size, 379 min_size=min_size, 380 max_size=max_size, 381 helptext=helptext, 382 position=position, 383 style=style, 384 hexpand=hexpand, 385 vexpand=vexpand, 386 font=font, 387 base_color=base_color, 388 background_color=background_color, 389 foreground_color=foreground_color, 390 selection_color=selection_color, 391 border_size=border_size, 392 position_technique=position_technique, 393 is_focusable=is_focusable, 394 comment=comment, 395 padding=padding, 396 background_image=background_image, 397 opaque=opaque, 398 margins=margins, 399 _real_widget=_real_widget)
400 - def clone(self, prefix):
401 vboxClone = VBox(None, 402 self._createNameWithPrefix(prefix), 403 self.size, 404 self.min_size, 405 self.max_size, 406 self.helptext, 407 self.position, 408 self.style, 409 self.hexpand, 410 self.vexpand, 411 self.font, 412 self.base_color, 413 self.background_color, 414 self.foreground_color, 415 self.selection_color, 416 self.border_size, 417 self.position_technique, 418 self.is_focusable, 419 self.comment, 420 self.padding, 421 self.background_image, 422 self.opaque, 423 self.margins) 424 425 vboxClone.addChildren(self._cloneChildren(prefix)) 426 427 return vboxClone
428 429
430 -class HBox(HBoxLayoutMixin,Container):
431 """ 432 A horizontally aligned box - for containement of child widgets. 433 434 Please see L{VBox} for details - just change the directions :-). 435 """ 436 DEFAULT_HEXPAND = 1 437 DEFAULT_VEXPAND = 0 438
439 - def __init__(self, 440 parent = None, 441 name = None, 442 size = None, 443 min_size = None, 444 max_size = None, 445 helptext = None, 446 position = None, 447 style = None, 448 hexpand = None, 449 vexpand = None, 450 font = None, 451 base_color = None, 452 background_color = None, 453 foreground_color = None, 454 selection_color = None, 455 border_size = None, 456 position_technique = None, 457 is_focusable = None, 458 comment = None, 459 padding = None, 460 background_image = None, 461 opaque = None, 462 margins = None, 463 _real_widget = None):
464 465 super(HBox,self).__init__(parent=parent, 466 name=name, 467 size=size, 468 min_size=min_size, 469 max_size=max_size, 470 helptext=helptext, 471 position=position, 472 style=style, 473 hexpand=hexpand, 474 vexpand=vexpand, 475 font=font, 476 base_color=base_color, 477 background_color=background_color, 478 foreground_color=foreground_color, 479 selection_color=selection_color, 480 border_size=border_size, 481 position_technique=position_technique, 482 is_focusable=is_focusable, 483 comment=comment, 484 padding=padding, 485 background_image=background_image, 486 opaque=opaque, 487 margins=margins, 488 _real_widget=_real_widget)
489
490 - def clone(self, prefix):
491 hboxClone = HBox(None, 492 self._createNameWithPrefix(prefix), 493 self.size, 494 self.min_size, 495 self.max_size, 496 self.helptext, 497 self.position, 498 self.style, 499 self.hexpand, 500 self.vexpand, 501 self.font, 502 self.base_color, 503 self.background_color, 504 self.foreground_color, 505 self.selection_color, 506 self.border_size, 507 self.position_technique, 508 self.is_focusable, 509 self.comment, 510 self.padding, 511 self.background_image, 512 self.opaque, 513 self.margins) 514 515 hboxClone.addChildren(self._cloneChildren(prefix)) 516 517 return hboxClone
518 519
520 -class Window(VBoxLayoutMixin,Container):
521 """ 522 A L{VBox} with a draggable title bar aka a window 523 524 New Attributes 525 ============== 526 527 - title: The Caption of the window 528 - titlebar_height: The height of the window title bar 529 """ 530 531 ATTRIBUTES = Container.ATTRIBUTES + [ UnicodeAttr('title'), 532 IntAttr('titlebar_height') 533 ] 534 535 DEFAULT_TITLE = u"title" 536 DEFAULT_TITLE_HEIGHT = 0 537 DEFAULT_POSITION_TECHNIQUE = "automatic" 538
539 - def __init__(self, 540 parent = None, 541 name = None, 542 size = None, 543 min_size = None, 544 max_size = None, 545 helptext = None, 546 position = None, 547 style = None, 548 hexpand = None, 549 vexpand = None, 550 font = None, 551 base_color = None, 552 background_color = None, 553 foreground_color = None, 554 selection_color = None, 555 border_size = None, 556 position_technique = None, 557 is_focusable = None, 558 comment = None, 559 padding = None, 560 background_image = None, 561 opaque = None, 562 margins = None, 563 _real_widget = None, 564 title = None, 565 titlebar_height = None):
566 567 super(Window,self).__init__(parent=parent, 568 name=name, 569 size=size, 570 min_size=min_size, 571 max_size=max_size, 572 helptext=helptext, 573 position=position, 574 style=style, 575 hexpand=hexpand, 576 vexpand=vexpand, 577 font=font, 578 base_color=base_color, 579 background_color=background_color, 580 foreground_color=foreground_color, 581 selection_color=selection_color, 582 border_size=border_size, 583 position_technique=position_technique, 584 is_focusable=is_focusable, 585 comment=comment, 586 padding=padding, 587 background_image=background_image, 588 opaque=opaque, 589 margins=margins, 590 _real_widget= fife.Window()) 591 592 if titlebar_height is not None: 593 if titlebar_height == 0: 594 titlebar_height = self.real_font.getHeight() + 4 595 self.titlebar_height = titlebar_height 596 else: 597 self.titlebar_height = self.real_font.getHeight() + 4 598 599 if title is not None: 600 self.title = title 601 else: 602 self.title = self.DEFAULT_TITLE
603
604 - def clone(self, prefix):
605 606 windowClone = Window(None, 607 self._createNameWithPrefix(prefix), 608 self.size, 609 self.min_size, 610 self.max_size, 611 self.helptext, 612 self.position, 613 self.style, 614 self.hexpand, 615 self.vexpand, 616 self.font, 617 self.base_color, 618 self.background_color, 619 self.foreground_color, 620 self.selection_color, 621 self.border_size, 622 self.position_technique, 623 self.is_focusable, 624 self.comment, 625 self.padding, 626 self.background_image, 627 self.opaque, 628 self.margins, 629 None, 630 self.title, 631 self.titlebar_height 632 ) 633 634 windowClone.addChildren(self._cloneChildren(prefix)) 635 636 return windowClone
637
638 - def _getTitle(self): return gui2text(self.real_widget.getCaption())
639 - def _setTitle(self,text): self.real_widget.setCaption(text2gui(text))
640 title = property(_getTitle,_setTitle) 641
642 - def _getTitleBarHeight(self): return self.real_widget.getTitleBarHeight()
643 - def _setTitleBarHeight(self,h): self.real_widget.setTitleBarHeight(h)
644 titlebar_height = property(_getTitleBarHeight,_setTitleBarHeight) 645 646 # Hackish way of hiding that title bar height in the perceived height. 647 # Fixes VBox calculation
648 - def _setHeight(self,h):
649 h = max(self.min_size[1],h) 650 h = min(self.max_size[1],h) 651 self.real_widget.setHeight(h + self.titlebar_height)
652 - def _getHeight(self): return self.real_widget.getHeight() - self.titlebar_height
653 height = property(_getHeight,_setHeight)
654