# $Id: StatusBar.py,v 1.16.2.2 2007/01/20 12:56:26 marcusva Exp $
#
# Copyright (c) 2004-2006, 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 widget class, which can display information of any kind using a
stack technique.
"""
from datetime import datetime
from Container import Container
from Constants import *
from StyleInformation import StyleInformation
import base
_TIMER = 50
class StatusBar (Container):
"""StatusBar () -> StatusBar
A widget class, which can display information using a stack.
The StatusBar widget class can display the current date and info
messages using a message stack.
Info messages can be enabled or disabled using the 'tips' attribute
or show_tips() method. If the tips are enabled, only the topmost
(at last added) tip will be displayed.
statusbar.tips = True
statusbar.show_tips (False)
The push_tip() method will put the message on the top of the stack,
while the pop_tip() method will remove the topmost message. If there
are several messages on the stack, pop_tip() will reveal previously
added messages, which will be displayed then.
statusbar.push_tip ('This is a message') # 'This is a message' is shown
statusbar.push_tip ('Another message') # 'Another message' is shown
statusbar.pop_tip () # 'This is a message' is shown
To get the currently displayed message, the 'current_tip' attribute
or get_current_tip() method can be used.
current = statusbar.current_tip
current = statusbar.get_current_tip ()
The width of the area, that displays the tips can be adjusted using
the 'tip_width' attribute or set_tip_width () method.
If the rendered text exceeds the width of the area, it will be cut down
to its width.
statusbar.tip_width = 50
statusbar.set_tip_width (50)
Displaying the actual date can be enabled or disabled with the
'date' attribute or show_date() method.
statusbar.date = True
statusbar.show_date (False)
The display format of it can be adjusted through the 'date_format'
attribute or set_date_format() method. The format has to be a string
in a format, which can be understood by the strftime() method.
statusbar.date_format = '%x'
statusbar.set_date_format ('%H: %M')
The current date (which can differ from the displayed one) can be
fetched through the 'current_date' attribute. Usually the update resolution
for the date is set to one second. Due to the internal drawing and update
code it can happen that the the displayed and current date differ by one
second.
The width of the area, that displays the date can be adjusted using
the 'date_width' attribute or set_date_width () method.
If the rendered date exceeds the width of the area, it will be cut
down to its width.
statusbar.date_width = 50
statusbar.set_date_width (50)
Additionally you are able to place widgets on the StatusBar through
the usual Container methods. The widgets will be placed between the
info message text and the date.
Note:
The StatusBar updates itself every 500 ms. Thus you will not have a
real time clock in the date display, which updates itself correctly
every second.
Default action (invoked by activate()):
None
Mnemonic action (invoked by activate_mnemonic()):
None
Attributes:
tips - Indicates, whether the info messages should be shown.
current_tip - The current tooltip to display.
tip_width - The width of the tip area. Default is 80.
date - Indicates, whether the date should be shown.
current_date - The current date to display.
date_format - The display format of the date. Default is '%x %H:%M'
date_width - The width of the date area. Default is 90.
"""
def __init__ (self):
Container.__init__ (self)
# Info values.
self._showtips = True
self._tips = []
self._tipwidth = 80
self._timer = _TIMER
self._xoffset = 0
# Date.
self._showdate = True
self._dateformat = "%x %H:%M:%S"
self._datewidth = 90
self._signals[SIG_TICK] = None
# Default size.
self.minsize = 204, 24
def set_focus (self, focus=True):
"""S.set_focus (focus=True) -> None
Overrides the set_focus() behaviour for the StatusBar.
The StatusBar class is not focusable by default.
"""
return False
def set_tip_width (self, width):
"""S.set_tip_width (...) -> None
Sets the width of the tip area.
Raises a TypeError, if the passed argument is not a positive
integer.
"""
if (type (width) != int) or (width < 0):
raise TypeError ("width must be a positive integer")
self._tipwidth = width
self.dirty = True
def set_date_width (self, width):
"""S.set_date_width (...) -> None
Sets the width of the date area.
Raises a TypeError, if the passed argument is not a positive
integer.
"""
if (type (width) != int) or (width < 0):
raise TypeError ("width must be a positive integer")
self._datewidth = width
self.dirty = True
def show_tips (self, show):
"""S.show_tips (...) -> None
Shows or hides the info message display of the StatusBar.
"""
if show != self._showtips:
self._showtips = show
self.dirty = True
def show_date (self, show):
"""S.show_date (...) -> None
Shows or hides the date display of the StatusBar.
"""
if show != self._showdate:
self._showdate = show
self.dirty = True
def set_date_format (self, format):
"""S.set_date_format (...) -> None
Sets the display format for the date.
The passed format string has to be in a format, which can be
understood by the strftime() method.
"""
self._dateformat = format
self.dirty = True
def get_current_tip (self):
"""S.get_current_tip () -> string or unicode
Gets the current info message to display.
"""
length = len (self._tips)
if length > 0:
return self._tips[length - 1]
return ""
def push_tip (self, tip):
"""S.push_tip (...) -> None
Puts a info message on the queue of the StatusBar.
Raises a TypeError, if the passed argument is not a string or
unicode.
"""
if type (tip) not in (str, unicode):
raise TypeError ("tip must be a string or unicode")
self._tips.append (tip)
self.dirty = True
def pop_tip (self):
"""S.pop_tip () -> None
Removes the last info message from the StatusBar queue.
"""
if len (self._tips) > 0:
self._tips.pop ()
self.dirty = True
def calculate_size (self):
"""S.calculate_size () -> int, int.
Calculates the size needed by the children.
Calculates the size needed by the children and returns the
resulting width and height.
"""
border = base.GlobalStyle.get_border_size \
(self.__class__, self.style,
StyleInformation.get ("STATUSBAR_BORDER"))
width = 2 * (border + self.padding)
height = 0
spacing = self.spacing
for widget in self.children:
width += widget.width + spacing
if widget.height > height:
height = widget.height
height += 2 * (border + self.padding)
# Add width for the tips and date.
if self.tips:
width += self.tip_width
if self.date:
width += self.spacing
if self.date:
width += self.date_width
if not self.tips and not self.date:
width -= self.spacing
return width, height
def dispose_widgets (self):
"""S.dispose_widgets (...) -> None
Moves the children of the StatusBar to their correct positions.
"""
border = base.GlobalStyle.get_border_size \
(self.__class__, self.style,
StyleInformation.get ("STATUSBAR_BORDER"))
padding = self.padding
spacing = self.spacing
diff = (self.height - 2 * (border + padding)) / 2
x = self._xoffset
addy = border + padding + diff
for widget in self.children:
y = border + padding + diff - widget.height / 2
y = addy - widget.height / 2
widget.topleft = (x, y)
x += widget.width + spacing
def notify (self, event):
"""S.notify (...) -> None
Notifies the StatusBar about an event.
"""
if event.signal == SIG_TICK:
if self._timer == 0:
self._timer = _TIMER
if self.date:
self.dirty = True
self._timer -= 1
def draw_bg (self):
"""S.draw_bg () -> Surface
Draws the background surface of the StatusBar and returns it.
Creates the visible surface of the StatusBar and returns it to
the caller.
"""
return base.GlobalStyle.engine.draw_statusbar (self)
def draw (self):
"""S.draw () -> None
Draws the StatusBar surface and places its children on it.
"""
Container.draw (self)
cls = self.__class__
style = base.GlobalStyle
border = style.get_border_size \
(cls, self.style, StyleInformation.get ("STATUSBAR_BORDER"))
blit = self.image.blit
rect = self.image.get_rect()
self._xoffset = self.padding + border
# Draw the current tip.
if self.tips:
surface_tip = style.engine.draw_string (self.current_tip,
self.state, cls,
self.style)
r = surface_tip.get_rect ()
r.x = self._xoffset
r.centery = rect.centery
blit (surface_tip, r, (0, 0, self.tip_width, r.height))
self._xoffset += self.tip_width + self.spacing
# Place the children of the StatusBar and blit them.
self.dispose_widgets ()
for widget in self.children:
blit (widget.image, widget.rect)
# Draw the date.
if self.date:
surface_date = style.engine.draw_string (self.current_date,
self.state, cls,
self.style)
r = surface_date.get_rect ()
r.right = rect.right - border - self.padding
r.centery = rect.centery
blit (surface_date, r, (0, 0, self._datewidth, r.height))
tips = property (lambda self: self._showtips,
lambda self, var: self.show_tips (var),
doc = "Indicates, whether the tooltips should be shown.")
tip_width = property (lambda self: self._tipwidth,
lambda self, var: self.set_tip_width (var),
doc = "The width of the tip area.")
date = property (lambda self: self._showdate,
lambda self, var: self.show_date (var),
doc = "Indicates, whether the date should be shown.")
date_width = property (lambda self: self._datewidth,
lambda self, var: self.set_date_width (var),
doc = "The width of the date area.")
current_tip = property (lambda self: self.get_current_tip (),
doc = "The current tooltip to display.")
current_date = property (lambda self: datetime.now ().strftime \
(self._dateformat),
doc = "The current date to display.")
date_format = property (lambda self: self._dateformat,
lambda self, var: self.set_date_format (var),
doc = "Sets the display format of the date.")
syntax highlighted by Code2HTML, v. 0.9.1