# $Id: Label.py,v 1.28.2.3 2007/02/19 17:43:28 marcusva Exp $ # # Copyright (c) 2004-2007, Marcus von Appen # All rights reserved. # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright notice, # this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. """A simple widget, which can display text.""" from BaseWidget import BaseWidget from Constants import * import base class Label (BaseWidget): """Label (text) -> Label A simple widget class, which can display text. The Label widget is able to display a short amount of text. It supports a mnemonic keybinding to activate other widgets. The text to display on the Label can be set through the 'text' attribute or set_text() method. To create a mnemonic within the text, a hash ('#') has to precede the the wanted character. A normal hash character can be created using two hashes ('##'). If more than one mnemonic identifier are placed in the text (like in '#Two #mnemonics', only the first one will be used, while all others will be ignored. label.text = '#Mnemonics' # Use the M character as mnemonic. label.text = 'Use ##1' # Creates the text 'Use #1'. label.set_text ('No mnemonic here') label.set_text ('#Two #mnemonics') # Only the first '#' will be used. A widget can be bound to the mnemonic with the 'widget' attribute or set_widget() method. Whenever the mnemonic is activated, the connected widget will receive the focus. label.widget = widget label.set_widget (widget) The 'padding' attribute and set_padding() method are used to place a certain amount of pixels between the text and the outer edges of the Label. label.padding = 10 label.set_padding (10) The Label supports the display of multiple text lines via the 'multiline' attribute and set_multiline() method. If it is set to True, the text to display will be splitted into several lines using the newline character '\\n' and each line will be displayed beneath the previous one. label.multiline = True label.set_multiline (True) The layout for the text within the Label can be set individually using the set_align() method and 'align' attribute. Alignments can be combined, which means, that a ALIGN_TOP | ALIGN_LEFT would align the text at the topleft corner of the Label. However, not every alignment make sense, so a ALIGN_TOP | ALIGN_BOTTOM would cause the widget to be placed at the top. The priority order for the alignment follows. The lower the value, the higher the priority. Alignment Priority ----------------------- ALIGN_TOP 0 ALIGN_BOTTOM 1 ALIGN_LEFT 0 ALIGN_RIGHT 1 ALIGN_NONE 2 Default action (invoked by activate()): None Mnemonic action (invoked by activate_mnemonic()): The activate() method of the connected widget will be invoked. Attributes: text - The text to display on the Label. widget - The widget to focus, if the mnemonic is activated. padding - Additional padding between text and borders. Default is 2. mnemonic - A tuple with index location character of the mnemonic. multiline - Indicates, whether the text spans over multiple lines. Default is False. linespace - The line space in multiline mode. align - The alignment of the text on the Label. lines - A list containing the single text lines. """ def __init__ (self, text): BaseWidget.__init__ (self) # Mnemonic identifiers in a tuple: (index, key). self._mnemonic = (-1, None) self._widget = None self.__active = False # Internal mnemonic handler. self._multiline = False self._linespace = 0 self._text = None self._padding = 2 self._align = ALIGN_NONE self.set_text (text) def set_align (self, align): """L.set_align (...) -> None Sets the alignment for the text on the Label. Raises a TypeError, if the passed argument is not a value from ALIGN_TYPES. """ if not constants_is_align (align): raise TypeError ("align must be a value from ALIGN_TYPES") self._align = align self.dirty = True def set_text (self, text): """L.set_text (...) -> None Sets the text of the Label to the passed argument. Sets the text of the Label to the passed argument. If the text contains a hash ('#') character, then the character, the hash precedes, will be used as a mnemonic (see also set_widget()). Any other single hash character will be dropped and ignored. To create a normal hash character to display, use two '##'. Raises a TypeError, if the passed argument is not a string or unicode. """ if type (text) not in (str, unicode): raise TypeError ("text must be a string or unicode") text = self._get_mnemonic (text) self._text = text self.dirty = True def _get_mnemonic (self, text): """L._get_mnemonic (...) -> str Sets the mnemonic position (if any). Sets the internal mnemonic position to first position with a single '#'. """ self._mnemonic = (-1, None) newtext = "" index = 0 hashfound = False mnemonicset = False for char in text: if char == "#": if hashfound: newtext += "#" hashfound = False else: hashfound = True index -= 1 elif hashfound: if not mnemonicset: self._mnemonic = (index, unicode (char.lower())) mnemonicset = True hashfound = False newtext += char else: newtext += char index += 1 return newtext def get_lines (self): """L.get_lines () -> list Gets a list with the text lines. Gets a list of lines from the set text. The text will be splitted using the newline character '\\n' and returned as a list. If the 'multiline' attribute is set to false, a single text line is returned. """ if not self.multiline: return [self.text] return self.text.split ('\n') def set_multiline (self, multiline): """L.set_multiline (...) -> None Sets the multiline support of the Label. The multiline support indicates, that the text to display on the label can span over several lines. The text usually will be splitted using the newline character '\\n'. """ self._multiline = multiline self.dirty = True def set_linespace (self, linespace): """L.set_linespace (...) -> None Sets the line space between each line in multiline mode. The line space is defined in pixels. Raises a TypeError, if the passed argument is not a positive integer. """ if (linespace != None) and (type (linespace) != int): raise TypeError ("linespace must be an integer") self._linespace = linespace self.dirty = True def activate (self): """L.activate () -> None Activates the Label. Note: Labels can not be activated by default, thus this method does not do anything. """ pass def activate_mnemonic (self, mnemonic): """L.activate_mnemonic (...) -> bool Activates the mnemonic widget of the Label. Checks, if the Label uses the passed mnemonic, invokes the activate() method of its mnemonic widget on a successful check and returns True, otherwise False. """ if self.widget and (self._mnemonic[1] == mnemonic): try: # If the widget does not have an activate() method or # raises an exception, just give it the input focus. self.widget.activate () except NotImplementedError: self.widget.focus = True return True return False def set_widget (self, widget): """L.set_widget (...) -> None Sets the widget to activate, if the mnemonic key gets pressed. Note: This method only works as supposed using a render loop, which supports the Renderer class specification. Raises a TypeError, if the passed argument does not inherit from the BaseWidget class. """ if (widget != None) and not isinstance (widget, BaseWidget): raise TypeError ("widget must inherit from BaseWidget") self._widget = widget def set_padding (self, padding): """L.set_padding (...) -> None Sets the padding between the edges and text of the Label. The padding value is the amount of pixels to place between the edges of the Label and the displayed text. Raises a TypeError, if the passed argument is not a positive integer. Note: If the 'size' attribute is set, it can influence the visible space between the text and the edges. That does not mean, that any padding is set. """ if (type (padding) != int) or (padding < 0): raise TypeError ("padding must be a positive integer") self._padding = padding self.dirty = True def set_focus (self, focus=True): """L.set_focus (...) -> bool Overrides the default widget input focus. Labels cannot be focused by default, thus this method always returns False and does not do anything. """ return False def draw_bg (self): """L.draw_bg () -> Surface Draws the Label background surface and returns it. Creates the visible background surface of the Label and returns it to the caller. """ return base.GlobalStyle.engine.draw_label (self) text = property (lambda self: self._text, lambda self, var: self.set_text (var), doc = "The text to display on the Label.") widget = property (lambda self: self._widget, lambda self, var: self.set_widget (var), doc = "The connected widget for the mnemonic key.") padding = property (lambda self: self._padding, lambda self, var: self.set_padding (var), doc = "Additional padding between text and borders.") mnemonic = property (lambda self: self._mnemonic, doc = "The index and character of the mnemonic.") multiline = property (lambda self: self._multiline, lambda self, var: self.set_multiline (var), doc = "Indicates, whether the text spans over " \ "multiple lines.") linespace = property (lambda self: self._linespace, lambda self, var: self.set_linespace (var), doc = "The line space in multiline mode.") lines = property (lambda self: self.get_lines (), doc = "A list containing the single text lines.") align = property (lambda self: self._align, lambda self, var: self.set_align (var), doc = "The alignment to use for the text.")