Прикреплённый файл «win.py»

Загрузка

   1 #!/usr/bin/python
   2 # coding: utf-8
   3 # vim: expandtab:ts=4:sw=4
   4 '''
   5 Написать «оконную систему», состоящую из классов
   6 
   7         * Экран (контейнер окон, позволяет манипулировать окнами)
   8                     o Список окон, определение окна-получателя события
   9                     o Глубина окон, изменение глубины окон
  10                     o Перемещение и изменение размера окон 
  11         * Окно (позволяет манипулировать своим содержимым)
  12 
  13 win.py: классы
  14 '''
  15 
  16 import pygame, sys
  17 
  18 class descriptor:
  19     '''Window descritor'''
  20     def __init__(self, rect, window, mode=["basic"], **argn):
  21         '''Create a window descriptor object with defaut basic mode'''
  22         self.rect=rect
  23         self.window=window
  24         if type(mode) is str:
  25             self.mode=[mode]
  26         else:
  27             self.mode=mode or ["basic"]
  28 
  29 class basic_screen:
  30     '''Windows container'''
  31     def __init__(self, surface, bg=(0,0,0)):
  32         '''Create a screen using given surface'''
  33         self.surface = surface
  34         self.windows = []
  35         self.immed = []     # events to be handled immediately
  36         self.hanled = []    # events we handle if no child doesn.t
  37         self.bg = bg
  38 
  39     def append(self, rect, mode, creator, *args, **argn):
  40         '''Call creator() with *args, **argn
  41         to produce a window (of mode type) on rect-sized subsurface
  42         and put the window in the top'''
  43         wnd = creator(self.surface.subsurface(rect), *args, **argn)
  44         self.windows.append(descriptor(rect,wnd,mode))
  45         return wnd
  46 
  47     def pop(self, index=-1):
  48         '''Unregister corresponded window and return it'''
  49         if self.windows:
  50             return self.windows.pop(index)
  51         else:
  52             return None
  53 
  54     def clear(self):
  55         '''Draw initial screen's surface without all windows'''
  56         if self.bg:
  57             self.surface.fill(self.bg)
  58 
  59     def redraw(self):
  60         '''Redraw all the contents'''
  61         self.clear()
  62         for wnd in self.windows:
  63             wnd.window.redraw()
  64 
  65     def up(self, index):
  66         '''Put indexed window deeper'''
  67         if len(self.windows) > 1 and index < len(self.windows)-1:
  68             index+=1
  69             self.windows[index-1],self.windows[index]= \
  70             self.windows[index],  self.windows[index-1]
  71         return index
  72 
  73     def down(self, index):
  74         '''Pull indexed window upper'''
  75         if len(self.windows) > 1 and index > 0:
  76             self.windows[index-1],self.windows[index]= \
  77             self.windows[index]  ,self.windows[index-1]
  78             index-=1
  79         return index
  80 
  81     def top(self, index):
  82         '''Bring indexed window to the top'''
  83         if index < len(self.windows):
  84             w=self.windows.pop(index)
  85             self.windows.append(w)
  86 
  87     def locate(self, pos):
  88         '''Locate a window than owns visible pos coordinate.
  89         If not found return -1'''
  90         for i in xrange(len(self.windows)-1, -1, -1):
  91             if self.windows[i].rect.collidepoint(pos):
  92                 return i
  93         return -1
  94 
  95     def handler(self, event, pos):
  96         '''Handle an event that not correspond any window'''
  97         return False
  98 
  99     def proceed(self, event, pos):
 100         '''Check if the event is to be handled by certain window
 101         and let the window do it. If no appropriete windows found 
 102         or window nas no idea how to handle an event, handle it manually.
 103         Return false if no event handler is provided.'''
 104         ret=False
 105         if event in self.immed:
 106             ret=self.handler(event, pos)
 107         if not ret:
 108             index=self.locate(pos)
 109             if index>=0:
 110                 wpos=(pos[0]-self.windows[index].rect.left,pos[1]-self.windows[index].rect.top)
 111                 ret=self.windows[index].window.proceed(event,wpos)
 112         return ret or self.handler(event, pos)
 113 
 114     def renew(self,surface):
 115         '''Stck window to a new surface'''
 116         self.surface = surface
 117         for wnd in self.windows:
 118             wnd.window.renew(surface.subsurface(wnd.rect))
 119 
 120 class simple_screen(basic_screen):
 121     '''Screen with simple window management'''
 122     def __init__(self, *argv, **argn):
 123         '''Additional parameters:
 124         titlebg: title background
 125         titlefg: title foreground
 126         borderwidth: width of border line
 127         bordercolor: base color of border (3D effect applied)
 128         '''
 129         self.titlebg=argn.get('titlebg',(0,32,64))
 130         self.titlefg=argn.get('titlefg',(255,248,128))
 131         self.borderwidth=argn.get('borderwidth',2)
 132         self.bordercolor=argn.get('bordercolor',(128,128,128))
 133         self.titlesize=14
 134         basic_screen.__init__(self, *argv, **argn)
 135         self.immed.extend([pygame.MOUSEMOTION, pygame.MOUSEBUTTONDOWN])
 136         self.focus=-1
 137 
 138     def handler(self, event, pos):
 139         '''
 140 pygame.MOUSEMOTION with button1 down -- move focused window
 141 pygame.MOUSEBUTTONDOWN with button1 -- focus a window
 142                        with buttion4/5 -- raise/lower a window
 143         '''                   
 144         ret=False
 145         if event.type == pygame.MOUSEMOTION and event.buttons[0]:
 146             if self.focus >= 0:
 147                 nrect = self.windows[self.focus].rect.move(event.rel)
 148                 if self.surface.get_rect().contains(nrect):
 149                     self.windows[self.focus].rect.move_ip(event.rel)
 150                     self.windows[self.focus].window.renew(self.surface.subsurface(self.windows[self.focus].rect))
 151                     ret=True
 152         elif event.type == pygame.MOUSEBUTTONDOWN:
 153             if event.button == 1:
 154                 index = self.locate(pos)
 155                 if index >=0 and index != self.focus:
 156                     self.focus=index
 157                     ret=True
 158             elif event.button == 4:
 159                 self.focus=self.up(self.locate(pos))
 160                 ret=True
 161             elif event.button == 5:
 162                 self.focus=self.down(self.locate(pos))
 163                 ret=True
 164         return ret
 165 
 166     def highlight_window(self, index):
 167         '''Draw 4 black-white circles to merk a window'''
 168         for center in [ self.windows[index].rect.topleft, 
 169                         self.windows[index].rect.bottomleft, 
 170                         self.windows[index].rect.topright, 
 171                         self.windows[index].rect.bottomright ]:
 172             pygame.draw.circle(self.surface, (0,0,0), center, 4)
 173             pygame.draw.circle(self.surface, (255,255,255), center, 3)
 174 
 175     def pop(self, index=-1):
 176         w=basic_screen.pop(self,index)
 177         if w:
 178             # TODO not to lose focus if non-focused window is deleted
 179             self.focus=-1
 180         return w
 181 
 182     def redraw(self):
 183         '''Redraw all windows then highlight focused window, if any'''
 184         basic_screen.redraw(self)
 185         if self.focus >=0:
 186             self.highlight_window(self.focus)
 187 
 188 class basic_window:
 189     '''Basic type window'''
 190     def __init__(self, surface, bg=(0,0,0)):
 191         '''Create a window based on given surface
 192         if bg is None, make transparent window'''
 193         self.surface = surface
 194         self.bg = bg
 195 
 196     def renew(self,surface):
 197         '''Stck window to a new surface'''
 198         self.surface = surface
 199 
 200     def redraw(self):
 201         if self.bg:
 202             self.surface.fill(self.bg)
 203 
 204     def proceed(self, event, pos):
 205         return False
 206 
 207     def drawable(self):
 208         return self.surface
 209 
 210 class text_window(basic_window):
 211     '''Window with text inside'''
 212     def __init__(self, surface, bg=(0,0,0), fg=(200,200,200), text='', font="dejavusans", size=14):
 213         basic_window.__init__(self, surface, bg)
 214         self.fg=fg
 215         self.text=text
 216         if type(font) is pygame.font.Font:
 217             self.font = font
 218         else:
 219             if not pygame.font.get_init:
 220                 pygame.font.init()
 221             self.font=pygame.font.SysFont(font, size)
 222 
 223     def redraw(self):
 224         basic_window.redraw(self)
 225         self.surface.blit(self.font.render(self.text,True,self.fg),(0,0))
 226 
 227 class screen_window(basic_screen):
 228     '''Window with title and frame, screen internal'''
 229     def __init__(self, surface, screen, title):
 230         '''Use parent simple_creen defaults for title and frame'''
 231         basic_screen.__init__(self, surface, screen.bg)
 232         self.bordercolor, self.borderwidth = screen.bordercolor, screen.borderwidth
 233         self.title = title
 234         self.parent = screen
 235         trect=pygame.Rect(screen.borderwidth, screen.borderwidth, 
 236                 surface.get_width()-2*screen.borderwidth, screen.titlesize+2*screen.borderwidth)
 237 
 238         self.append(trect, "text", text_window, text=title,
 239                 bg=screen.titlebg, fg=screen.titlefg, size=screen.titlesize)
 240         drect=pygame.Rect(screen.borderwidth, trect.height+2*screen.borderwidth, 
 241                 trect.width, surface.get_height()-trect.height-3*screen.borderwidth)
 242         self.append(drect, "basic", basic_window, bg=screen.bg)
 243 
 244     def redraw(self):
 245         basic_screen.redraw(self)
 246         rect=self.surface.get_rect()
 247         x,y,w,h=rect.topleft+rect.size
 248         line=((x,y), (x+w-self.borderwidth,y), (x+w-self.borderwidth,y+h-self.borderwidth), (x,y+h-self.borderwidth))
 249         pygame.draw.lines(self.surface, self.bordercolor, True, line, self.borderwidth)
 250         middle=self.windows[0].rect.height+self.borderwidth
 251         pygame.draw.line(self.surface, self.bordercolor, (self.borderwidth,middle), (rect.width-self.borderwidth,middle), self.borderwidth)
 252 
 253     def drawable(self):
 254         return self.windows[1].window.surface

Прикреплённые файлы

Для ссылки на прикреплённый файл в тексте страницы напишите attachment:имяфайла, как показано ниже в списке файлов. Не используйте URL из ссылки «[получить]», так как он чисто внутренний и может измениться.

Вам нельзя прикреплять файлы к этой странице.