Hi,
[EMAIL PROTECTED] wrote:
freevo-weather ===============
REQUIREMENTS: freevo 1.5 (or current cvs)
A mythtv-style enhanced weather plugin. This plugin allows you to
track the weather at multiple locations.
This plugin is a great and small plugin example. I don't want to integrate in Freevo because this way, a plugin writer can easily see what is needed to write a plugin.
If you want to draw something on the skin (mail reader plugin?), this is the perfect example on how to do that.
Dischi
Hello! I tried the weather plugin and I think it's great. Although the plugin required me to update to python 2.3 because of the datetime module (it was about time I did though :).
There is a bug when drawing the screens today and extended forecast when having set OSD_OVERSCAN values. See: - http://www.matrise.net/~viggo/freevo/weather/ext_forecast.jpg - http://www.matrise.net/~viggo/freevo/weather/today_forecast.jpg
It would be interesting to do something like this for the mailreader. I did some work on the gui last week, and while it's not pretty yet, this is what it looks like atm. - http://www.matrise.net/~viggo/freevo/weather/newreader.jpg
It doesn't use the <content> area, but it uses the <view> area, and gets the sizerects to draw a scrollable surface in. The text background is transparent, so scrolling is seemless to the view area. And it now also draws image attachments to the surface. I would like to draw this on a seperate surface in the future (toggle between text and image).
I would think that the weather approach would be a more elegant solution to this. But would it be possible to scroll the text both vertical and horizontal? I haven't taken a good look at the write_text method yet.
I would like to get some ideas on how to do it better than it is today. I attached the gui if someone wants to take a look.
.viggo
#if 0 /* # ----------------------------------------------------------------------- # TextReader.py - a scrollable textreader # Author: Viggo Fredriksen <[EMAIL PROTECTED]> # Notes: # :The sizes of the reader is determined by the # skins <reader> <view layout # :Should this be split up into two things: # - one part in skins/main/TextArea.py # - one part in gui/TextReader.py # -> How to do this correctly? # Todo: # - Cleanup frame width/height/padding # - Check bug: ... on other box # ----------------------------------------------------------------------- # Freevo - A Home Theater PC framework # Copyright (C) 2002 Krister Lagerstrom, et al. # Please see the file freevo/Docs/CREDITS for a complete list of authors. # # 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 2 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 MER- # CHANTABILITY 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, write to the Free Software Foundation, Inc., # 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # ----------------------------------------------------------------------- */ #endif
import rc, skin, pygame
from gui import Scrollbar, Color, Container, AlertBox
from event import *
skin = skin.get_singleton()
skin.register('reader', ('screen', 'title', 'view', 'info', 'plugin'))
class TextReader(Container):
"""
text : text to render (uses soft drawstringframed)
item : item to associate it with (for info)
imagelist : list of pairs of filenames and description text
menuw : pass this if you want to reload the menuwidget
after the reader has finished
fontname : name of the skin font to use
"""
def __init__(self, text=' ', item=None, imagelist=None, menuw=None,
fontname='default'):
## init
self.item = item
self.menuw = menuw
self.pictures = []
self.int_pad = 5
self.img_h = 0
self.x_scroll_interval = 25
self.y_scroll_interval = 25
self.v_x,self.v_y = 0,0
self.show_v_scrollbar = 0
self.show_h_scrollbar = 0
# draw the skin and get the View_Area sizes
skin.draw('reader', self.item)
self.font = skin.get_font(fontname)
area = skin.areas['view'].area_val
# the area we draw to
self.left = area.x
self.top = area.y
self.width = area.width
self.height = area.height
Container.__init__(self, 'frame', self.left, self.top,
self.width, self.height)
## Initialize drawing
# get sizes for the text
(x0,y0,x1,y1) = self.osd.drawstringframed(text, 0, 0, 10000,
10000, self.font, mode='soft', layer='')[1]
self.s_h = y1-y0
self.s_w = x1-x0
if self.s_w<self.width:
self.s_w = self.width
# prepare images and surfaces
if imagelist: self.set_images(imagelist)
self.set_surface()
# draw string to the surface
self.osd.drawstringframed(text, 0, 0, self.s_w, self.s_h,
self.font, mode='soft',
layer=self.region_surface)
# draw the pictures to the surface
self.s_h += self.img_h
if imagelist:
self.draw_pictures(self.s_w, (y1-y0) + self.int_pad)
## Scrollbars
self.v_scrollbar = Scrollbar(self, 'vertical',bd_width=0)
self.h_scrollbar = Scrollbar(self, 'horizontal',bd_width=0)
#def __init__(self, parent, orientation, thickness=10, left=None, top=None,
# width=None, height=None, bg_color=None, fg_color=None,
# border=None, bd_color=None, bd_width=1):
self.add_child(self.v_scrollbar)
self.add_child(self.h_scrollbar)
if self.s_h>self.height:
self.show_v_scrollbar = 1
if self.s_w>self.width:
self.show_h_scrollbar = 1
self.max_x_offset = self.s_w - self.width
self.max_y_offset = self.s_h - self.height
## setup rc and osd
parent = self.osd.app_list[0]
parent.add_child(self)
self.parent = parent
self.osd.add_app(self)
rc.app(self)
rc.set_context('input')
def set_surface(self):
# get current snapshot of osd
self.filler = pygame.Surface((10, 10), 0, 32)
filler_c = Color((0,0,0,255))
fc_c = filler_c.get_color_sdl()
fc_a = filler_c.get_alpha()
self.filler.fill(fc_c)
self.filler.set_alpha(fc_a)
self.snapshot = \
self.osd.getsurface(self.left, self.top,
self.width, self.height)
# create a new transparent surface
# - take the image height in consideration
h = self.s_h + self.img_h
if h<self.height:
h = self.height
self.region_surface = pygame.Surface((self.s_w, h),
0, 32)
self.region_surface.set_colorkey(0)
def set_images(self, imglist=[]):
"""
Create and transform picture surfaces
Sets img_h to total height of the surfaces
Note: Perhaps utilize Layouts?
"""
max_width = self.s_w-self.int_pad
for i in imglist:
name = i[1]
p = pygame.image.load(i[0]).convert_alpha()
w = p.get_width()
h = p.get_height()
# handle pictures larger than width of surface
if w>max_width:
aspect = ( float(w) / float(h) )
h = int( ( float(max_width) / aspect ) )
p = pygame.transform.scale(p, (max_width, h))
self.img_h += ( h + self.font.height )
self.pictures += [ ( p, name ) ]
def draw_pictures(self, width, height):
offset = height + self.int_pad
for p in self.pictures:
# draw the filename
(x0,y0,x1,y1) = self.osd.drawstringframed(p[1], 0, offset, width, -1,
self.font,align_h='left',
align_v='top', mode='hard',
layer=self.region_surface)[1]
offset += (y1-y0)
# blit the picture to the surface
self.region_surface.blit(p[0], (0, offset) )
offset += (p[0].get_height() + self.int_pad)
def _draw(self, surface=None):
if not self.width or not self.height or not self.region_surface:
raise TypeError, 'Not all needed variables set.'
rect = (self.v_x, self.v_y,
self.width-2*self.int_pad,
self.height-2*self.int_pad)
self.surface = pygame.Surface((self.width, self.height), 0, 32)
self.surface.blit(self.snapshot, (0, 0))
self.surface.blit(self.region_surface, (self.int_pad, self.int_pad), rect)
if self.show_v_scrollbar and self.v_scrollbar:
self.v_scrollbar.draw()
if self.show_h_scrollbar and self.h_scrollbar:
self.h_scrollbar.draw()
if self.show_v_scrollbar and self.show_h_scrollbar:
self.surface.blit(self.filler,
(self.width-self.v_scrollbar.thickness,
self.height-self.h_scrollbar.thickness))
self.blit_parent()
def scroll(self, direction):
if direction == INPUT_RIGHT:
new_x = self.v_x + self.x_scroll_interval
if new_x > self.max_x_offset:
new_x = self.max_x_offset
self.v_x = new_x
elif direction == INPUT_LEFT:
new_x = self.v_x - self.x_scroll_interval
if new_x < 0:
new_x = 0
self.v_x = new_x
elif direction == INPUT_DOWN:
new_y = self.v_y + self.y_scroll_interval
if new_y > self.max_y_offset:
new_y = self.max_y_offset
self.v_y = new_y
elif direction == INPUT_UP:
new_y = self.v_y - self.y_scroll_interval
if new_y < 0:
new_y = 0
self.v_y = new_y
def get_view_percent(self, orientation):
if orientation == 'vertical':
a = self.v_y * 100 / self.s_h
b = self.height * 100 / self.s_h
c = (self.s_h - (self.v_y + self.height)) * 100 / self.s_h
else:
a = self.v_x * 100 / self.s_w
b = self.width * 100 / self.s_w
c = (self.s_w - (self.v_x + self.width)) * 100 / self.s_w
rem = 100 - a - b - c
b = b + rem
return (a, b, c)
def eventhandler(self, event, menuw=None):
if event in (INPUT_UP, INPUT_DOWN,INPUT_LEFT, INPUT_RIGHT):
self.scroll(event)
self.draw()
self.osd.update(self.get_rect())
elif event == INPUT_EXIT:
self.destroy()
rc.app(None)
self.visible = 0
if self.menuw:
self.menuw.refresh(reload=1)
return
