page.py 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603
  1. # -*- coding: utf-8 -*-
  2. import pygame
  3. from pygame.locals import *
  4. from sys import exit
  5. import os
  6. import sys
  7. import math
  8. from libs import easing
  9. #import base64
  10. #from beeprint import pp
  11. ### local import
  12. from constants import ALIGN,icon_width,icon_height,Width,Height,ICON_TYPES
  13. from util_funcs import midRect
  14. from keys_def import CurKeys
  15. from icon_pool import MyIconPool
  16. class PageStack:
  17. def __init__(self):
  18. self.stack = list()
  19. def Push(self,data):
  20. if data not in self.stack:
  21. self.stack.append(data)
  22. return True
  23. return False
  24. def Pop(self):
  25. if len(self.stack)<=0:
  26. return None,False
  27. return self.stack.pop(),True
  28. def Length(self):
  29. return len(self.stack)
  30. class PageSelector:
  31. _PosX = 0
  32. _PosY = 0
  33. _Width = 0
  34. _Height = 0
  35. _Parent = None
  36. _Alpha = 0
  37. _OnShow = True
  38. _IconSurf = None
  39. def __init__(self):
  40. pass
  41. def Init(self,x,y,w,h,alpha):
  42. self._PosX = x
  43. self._PosY = y
  44. self._Width = w
  45. self._Height = h
  46. self._Alpha = alpha
  47. def Adjust(self,x,y,w,h,alpha):
  48. self._PosX = x
  49. self._PosY = y
  50. self._Width = w
  51. self._Height = h
  52. self._Alpha = alpha
  53. def Draw(self):
  54. canvas = self._Parent._CanvasHWND
  55. idx = self._Parent._PsIndex
  56. iconidx = self._Parent._IconIndex
  57. if idx < len(self._Parent._Icons):
  58. x = self._Parent._Icons[idx]._PosX+self._Parent._PosX
  59. y = self._Parent._Icons[iconidx]._PosY ## only use current icon's PosY
  60. rect = midRect(x,y,self._Width,self._Height,self._Parent._Width,self._Parent._Height)
  61. if rect.width <=0 or rect.height <= 0 :
  62. return
  63. #color = (244,197,66,50)
  64. #pygame.draw.rect(canvas,color,rect,1)
  65. if self._IconSurf != None:
  66. self._Parent._CanvasHWND.blit(self._IconSurf,rect)
  67. class Page(object):
  68. _PosX=0
  69. _PosY=0
  70. _Width=0
  71. _Height=0
  72. _Icons = []
  73. _Ps = None
  74. _PsIndex = 0
  75. _IconNumbers = 0
  76. _IconIndex = 0 ## shows which icon current selected, the Selector can not move here
  77. _PrevIconIndex = 0 ## for remember the Highlighted Icon ,restore it's PosY to average
  78. _Index = 0
  79. _Align = ALIGN["SLeft"]
  80. _CanvasHWND = None #
  81. _HWND = None #
  82. _OnShow = False
  83. _Name = ""
  84. _Screen = None ## Should be the Screen Class
  85. _PageIconMargin = 20
  86. _FootMsg = ["Nav.","","","","Enter"] ## Default Page Foot info
  87. _SelectedIconTopOffset=20
  88. _EasingDur = 30
  89. def __init__(self):
  90. self._Icons = []
  91. def AdjustHLeftAlign(self): ## adjust coordinator and append the PageSelector
  92. self._PosX = self._Index*self._Screen._Width
  93. self._Width = self._Screen._Width
  94. self._Height = self._Screen._Height
  95. cols = int(Width /icon_width)
  96. rows = int( (self._IconNumbers * icon_width)/Width + 1)
  97. if rows < 1:
  98. rows = 1
  99. cnt = 0
  100. for i in range(0,rows):
  101. for j in range(0,cols):
  102. start_x = icon_width/2 + j*icon_width
  103. start_y = icon_height/2 + i*icon_height
  104. icon = self._Icons[cnt]
  105. icon.Adjust(start_x,start_y,icon_width-4,icon_height-4,0)
  106. icon._Index = cnt
  107. icon._Parent = self
  108. if cnt >= (self._IconNumbers -1):
  109. break
  110. cnt+=1
  111. ps = PageSelector()
  112. ps._IconSurf = MyIconPool._Icons["blueselector"]
  113. ps._Parent = self
  114. ps.Init(icon_width/2, TitleBar._BarHeight+icon_height/2,92,92,128)
  115. self._Ps = ps
  116. self._PsIndex = 0
  117. self._OnShow = False
  118. def AdjustSLeftAlign(self): ## adjust coordinator and append the PageSelector
  119. self._PosX = self._Index*self._Screen._Width
  120. self._Width = self._Screen._Width
  121. self._Height = self._Screen._Height
  122. start_x = (self._PageIconMargin + icon_width+self._PageIconMargin) /2
  123. start_y = self._Height/2
  124. for i in range(0,self._IconNumbers):
  125. it = self._Icons[i]
  126. it._Parent = self
  127. it._Index = i
  128. it.Adjust(start_x+i*self._PageIconMargin+i*icon_width,start_y,icon_width-6,icon_height-6,0)
  129. it._ImgSurf = pygame.transform.smoothscale(it._ImgSurf,(it._Width,it._Height))
  130. ps = PageSelector()
  131. ps._IconSurf = MyIconPool._Icons["blueselector"]
  132. ps._Parent = self
  133. ps.Init(start_x,start_y,92,92,128)
  134. self._Ps = ps
  135. self._PsIndex = 0
  136. self._OnShow = False
  137. if self._IconNumbers > 1:
  138. self._PsIndex = 1
  139. self._IconIndex = self._PsIndex
  140. self._PrevIconIndex = self._IconIndex
  141. self._Icons[self._IconIndex]._PosY -= self._SelectedIconTopOffset
  142. def AdjustSAutoLeftAlign(self): ## adjust coordinator and append the PageSelector
  143. self._PosX = self._Index*self._Screen._Width
  144. self._Width = self._Screen._Width
  145. self._Height = self._Screen._Height
  146. start_x = (self._PageIconMargin + icon_width+self._PageIconMargin) /2
  147. start_y = self._Height/2
  148. if self._IconNumbers == 1:
  149. start_x = self._Width / 2
  150. start_y = self._Height/2
  151. it = self._Icons[0]
  152. it._Parent = self
  153. it._Index = 0
  154. it.Adjust(start_x,start_y,icon_width-6,icon_height-6,0)
  155. it._ImgSurf = pygame.transform.smoothscale(it._ImgSurf,(it._Width,it._Height))
  156. elif self._IconNumbers == 2:
  157. start_x = (self._Width - self._PageIconMargin - self._IconNumbers*icon_width) / 2 + icon_width/2
  158. start_y = self._Height /2
  159. for i in range(0,self._IconNumbers):
  160. it = self._Icons[i]
  161. it._Parent = self
  162. it._Index = i
  163. it.Adjust(start_x+i*self._PageIconMargin + i*icon_width,start_y, icon_width-6, icon_height-6,0)
  164. it._ImgSurf = pygame.transform.smoothscale(it._ImgSurf,(it._Width,it._Height))
  165. elif self._IconNumbers > 2:
  166. for i in range(0,self._IconNumbers):
  167. it = self._Icons[i]
  168. it._Parent = self
  169. it._Index = i
  170. it.Adjust(start_x+i*self._PageIconMargin + i*icon_width,start_y,icon_width-6,icon_height-6,0)
  171. it._ImgSurf = pygame.transform.smoothscale(it._ImgSurf,(it._Width,it._Height))
  172. ps = PageSelector()
  173. ps._IconSurf = MyIconPool._Icons["blueselector"]
  174. ps._Parent = self
  175. ps.Init(start_x,start_y,92,92,128)
  176. self._Ps = ps
  177. self._PsIndex = 0
  178. self._OnShow = False
  179. if self._IconNumbers > 1:
  180. self._PsIndex = 1
  181. self._IconIndex = self._PsIndex
  182. self._PrevIconIndex = self._IconIndex
  183. self._Icons[self._IconIndex]._PosY -= self._SelectedIconTopOffset
  184. def InitLeftAlign(self):
  185. self._PosX = self._Index*Width
  186. self._Width = self._Screen._Width
  187. self._Height = self._Screen._Height
  188. cols = int(self._Width /icon_width)
  189. rows = int((self._IconNumbers * icon_width)/self._Width + 1)
  190. if rows < 1:
  191. rows = 1
  192. cnt = 0
  193. for i in range(0,rows):
  194. for j in range(0,cols):
  195. start_x = icon_width/2 + j*icon_width
  196. start_y = TitleBar._BarHeight + icon_height/2 + i*icon_height
  197. icon = IconItem()
  198. icon.Init(start_x,start_y,icon_width-4,icon_height-4,0)
  199. icon._Index = cnt
  200. icon._Parent = self
  201. self._Icons.append(icon)
  202. if cnt >= (self._IconNumbers -1):
  203. break
  204. cnt+=1
  205. ps = PageSelector()
  206. ps._IconSurf = MyIconPool._Icons["blueselector"]
  207. ps._Parent = self
  208. ps.Init(icon_width/2,icon_height/2,92,92,128)
  209. self._Ps = ps
  210. self._PsIndex = 0
  211. self._OnShow = False
  212. def Adjust(self): ## default init way,
  213. self._PosX = self._Index*self._Screen._Width
  214. self._Width = self._Screen._Width ## equal to screen width
  215. self._Height = self._Screen._Height
  216. if self._Align == ALIGN["HLeft"]:
  217. start_x = (self._Width - self._IconNumbers*icon_width)/2 + icon_width/2
  218. start_y = self._Height/2
  219. for i in range(0,self._IconNumbers):
  220. it = self._Icons[i]
  221. it._Parent = self
  222. it._Index = i
  223. it.Adjust(start_x+i*icon_width,start_y,icon_width,icon_height,0)
  224. ps = PageSelector()
  225. ps._IconSurf = blueselector_surf
  226. ps._Parent = self
  227. ps.Init(start_x,start_y,92,92,128)
  228. self._Ps = ps
  229. self._PsIndex = 0
  230. self._OnShow = False
  231. elif self._Align == ALIGN["SLeft"]:
  232. start_x = (self._PageIconMargin + icon_width+self._PageIconMargin) /2
  233. start_y = self._Height/2
  234. for i in range(0,self._IconNumbers):
  235. it = self._Icons[i]
  236. it._Parent = self
  237. it._Index = i
  238. it.Adjust(start_x+i*self._PageIconMargin+i*icon_width,start_y,icon_width,icon_height,0)
  239. ps = PageSelector()
  240. ps._IconSurf = MyIconPool._Icons["blueselector"]
  241. ps._Parent = self
  242. ps.Init(start_x,start_y-self._SelectedIconTopOffset,92,92,128)
  243. self._Ps = ps
  244. self._PsIndex = 0
  245. self._OnShow = False
  246. if self._IconNumbers > 1:
  247. self._PsIndex = 1
  248. self._IconIndex = self._PsIndex
  249. self._PrevIconIndex = self._IconIndex
  250. self._Icons[self._IconIndex]._PosY -= self._SelectedIconTopOffset
  251. def Init(self): ## default init way,
  252. if self._Screen != None:
  253. if self._Screen._CanvasHWND != None and self._CanvasHWND == None:
  254. self._CanvasHWND = self._Screen._CanvasHWND
  255. self._PosX = self._Index*self._Screen._Width
  256. self._Width = self._Screen._Width ## equal to screen width
  257. self._Height = self._Screen._Height
  258. start_x = (self._Width - self._IconNumbers*icon_width)/2 + icon_width/2
  259. start_y = self._Height/2
  260. for i in range(0,self._IconNumbers):
  261. it = IconItem()
  262. it._Parent = self
  263. it._Index = i
  264. it.Init(start_x+i*icon_width,start_y,icon_width,icon_height,0)
  265. self._Icons.append(it)
  266. if self._IconNumbers > 0:
  267. ps = PageSelector()
  268. ps._IconSurf = MyIconPool._Icons["blueselector"]
  269. ps._Parent = self
  270. ps.Init(start_x,start_y,icon_width+4,icon_height+4,128)
  271. self._Ps = ps
  272. self._PsIndex = 0
  273. self._OnShow = False
  274. def IconStepMoveData(self,icon_eh,cuts):## no Sine,No curve,plain movement steps data
  275. all_pieces = []
  276. piece = icon_eh / cuts
  277. c = 0.0
  278. prev = 0.0
  279. for i in range(0,cuts):
  280. c+=piece
  281. dx = c-prev
  282. if dx < 0.5:
  283. dx = 1.0
  284. all_pieces.append( math.ceil(dx) )
  285. if c >= icon_eh:
  286. break
  287. c = 0
  288. bidx = 0
  289. for i in all_pieces:
  290. c+=i
  291. bidx+=1
  292. if c >= icon_eh:
  293. break
  294. all_pieces = all_pieces[0:bidx]
  295. if len(all_pieces) < cuts:
  296. dff = cuts - len(all_pieces)
  297. diffa = []
  298. for i in range(0,dff):
  299. diffa.append(0)
  300. all_pieces.extend( diffa)
  301. return all_pieces
  302. def EasingData(self,start,distance):##generate easing steps data
  303. current_time = 0.0
  304. start_posx = 0.0
  305. current_posx = start_posx
  306. final_posx = float(distance)
  307. posx_init = start
  308. dur = self._EasingDur
  309. last_posx = 0.0
  310. all_last_posx = []
  311. for i in range(0,distance*dur):
  312. current_posx = easing.SineIn(current_time,start_posx,final_posx-start_posx,float(dur))
  313. if current_posx >= final_posx:
  314. current_posx = final_posx
  315. dx = current_posx - last_posx
  316. all_last_posx.append(int(dx))
  317. current_time+=1
  318. last_posx = current_posx
  319. if current_posx >= final_posx:
  320. break
  321. c = 0
  322. for i in all_last_posx:
  323. c+=i
  324. if c < final_posx -start_posx:
  325. all_last_posx.append(final_posx - c)
  326. return all_last_posx
  327. def IconSmoothUp(self,icon_ew):
  328. data = self.EasingData(self._PosX,icon_ew)
  329. data2 = self.IconStepMoveData(self._SelectedIconTopOffset,len(data))
  330. for i,v in enumerate(data):
  331. self.ClearCanvas()
  332. self._Icons[self._IconIndex]._PosY -= data2[i]
  333. if self._Icons[self._PrevIconIndex]._PosY < self._Height/2:
  334. self._Icons[self._PrevIconIndex]._PosY+=data2[i]
  335. self.DrawIcons()
  336. self._Screen.SwapAndShow()
  337. def IconsEasingLeft(self,icon_ew):
  338. data = self.EasingData(self._PosX,icon_ew)
  339. data2 = self.IconStepMoveData(self._SelectedIconTopOffset,len(data))
  340. for i,v in enumerate(data):
  341. self.ClearCanvas()
  342. self._PosX -= v
  343. self._Icons[self._IconIndex]._PosY -= data2[i]
  344. if self._Icons[self._PrevIconIndex]._PosY < self._Height/2:
  345. self._Icons[self._PrevIconIndex]._PosY+=data2[i]
  346. self.DrawIcons()
  347. self._Screen.SwapAndShow()
  348. def IconsEasingRight(self,icon_ew):
  349. data = self.EasingData(self._PosX,icon_ew)
  350. data2 = self.IconStepMoveData(self._SelectedIconTopOffset,len(data))
  351. for i,v in enumerate(data):
  352. self.ClearCanvas()
  353. self._PosX += v
  354. self._Icons[self._IconIndex]._PosY-=data2[i]
  355. if self._Icons[self._PrevIconIndex]._PosY < self._Height/2:
  356. self._Icons[self._PrevIconIndex]._PosY+=data2[i]
  357. self.DrawIcons()
  358. self._Screen.SwapAndShow()
  359. def EasingLeft(self,ew): #ew int
  360. data = self.EasingData(self._PosX,ew)
  361. for i in data:
  362. self._PosX -=i
  363. self.Draw()
  364. self._Screen.SwapAndShow()
  365. def EasingRight(self,ew):
  366. data = self.EasingData(self._PosX,ew)
  367. for i in data:
  368. self._PosX += i
  369. self.Draw()
  370. self._Screen.SwapAndShow()
  371. def MoveLeft(self,ew):
  372. self._PosX -= ew
  373. def MoveRight(self,ew):
  374. self._PosX += ew
  375. def ResetPageSelector(self):
  376. self._PsIndex = 0
  377. self._IconIndex = 0
  378. self._Ps._OnShow = True
  379. def DrawPageSelector(self):
  380. if self._Ps._OnShow == True:
  381. self._Ps.Draw()
  382. def MoveIconIndexPrev(self):
  383. self._IconIndex-=1
  384. if self._IconIndex < 0:
  385. self._IconIndex = 0
  386. self._PrevIconIndex = self._IconIndex
  387. return False
  388. self._PrevIconIndex = self._IconIndex+1
  389. return True
  390. def MoveIconIndexNext(self):
  391. #True for Moved,False is boundary
  392. self._IconIndex+=1
  393. if self._IconIndex > (self._IconNumbers - 1):
  394. self._IconIndex = self._IconNumbers -1
  395. self._PrevIconIndex = self._IconIndex
  396. return False
  397. self._PrevIconIndex = self._IconIndex-1
  398. return True
  399. def IconClick(self):
  400. if self._IconIndex > (len(self._Icons) -1):
  401. return
  402. cur_icon = self._Icons[self._IconIndex]
  403. if self._Ps._OnShow == False:
  404. return
  405. if cur_icon._MyType == ICON_TYPES["EXE"]:
  406. print("IconClick: %s %d"%(cur_icon._CmdPath,cur_icon._Index))
  407. self._Screen.RunEXE(cur_icon._CmdPath)
  408. elif cur_icon._MyType == ICON_TYPES["DIR"]:
  409. child_page = self._Icons[self._IconIndex]._LinkPage
  410. if child_page != None:
  411. child_page.Draw()
  412. self._Screen._MyPageStack.Push(self._Screen._CurrentPage)
  413. self._Screen._CurrentPage = child_page
  414. elif cur_icon._MyType == ICON_TYPES["FUNC"]:
  415. print("IconClick API: %d"%(cur_icon._Index))
  416. #print("%s"% cur_icon._CmdPath)
  417. api_cb = getattr(cur_icon._CmdPath,"API",None)
  418. if api_cb != None:
  419. if callable(api_cb):
  420. cur_icon._CmdPath.API(self._Screen)
  421. elif cur_icon._MyType == ICON_TYPES["Emulator"]:
  422. cur_icon._CmdPath.API(self._Screen)
  423. def ReturnToUpLevelPage(self):
  424. pop_page,ok = self._Screen._MyPageStack.Pop()
  425. if ok == True:
  426. #self._Screen._CurrentPage.ResetPageSelector()
  427. pop_page.Draw()
  428. self._Screen._CurrentPage = pop_page
  429. on_return_back_cb = getattr(self._Screen._CurrentPage,"OnReturnBackCb",None)
  430. if on_return_back_cb != None:
  431. if callable(on_return_back_cb):
  432. self._Screen._CurrentPage.OnReturnBackCb()
  433. else:
  434. if self._Screen._MyPageStack.Length() == 0:
  435. if len(self._Screen._Pages) > 0:
  436. self._Screen._CurrentPage = self._Screen._Pages[self._Screen._PageIndex]
  437. self._Screen._CurrentPage.Draw()
  438. print("OnTopLevel ",self._Screen._PageIndex)
  439. def ClearCanvas(self):
  440. self._CanvasHWND.fill(self._Screen._SkinManager.GiveColor("White"))
  441. def ClearIcons(self):
  442. for i in range(0,self._IconNumbers):
  443. self._Icons[i].Clear()
  444. def DrawIcons(self):
  445. for i in range(0,self._IconNumbers):
  446. self._Icons[i].Draw()
  447. def KeyDown(self,event):##default keydown,every inherited page class should have it's own KeyDown
  448. if event.key == CurKeys["A"]:
  449. if self._FootMsg[3] == "Back":
  450. self.ReturnToUpLevelPage()
  451. self._Screen.Draw()
  452. self._Screen.SwapAndShow()
  453. return
  454. if event.key == CurKeys["Menu"]:
  455. self.ReturnToUpLevelPage()
  456. self._Screen.Draw()
  457. self._Screen.SwapAndShow()
  458. if event.key == CurKeys["Right"]:
  459. if self.MoveIconIndexNext() == True:
  460. if self._IconIndex == (self._IconNumbers -1) or self._PrevIconIndex == 0:
  461. self.IconSmoothUp(icon_width+ self._PageIconMargin) # only move up selected icon,no horizontal translation
  462. else:
  463. self.IconsEasingLeft(icon_width + self._PageIconMargin)
  464. self._PsIndex = self._IconIndex
  465. self._Screen.Draw()
  466. self._Screen.SwapAndShow()
  467. if event.key == CurKeys["Left"]:
  468. if self.MoveIconIndexPrev() == True:
  469. if self._IconIndex == 0 or self._PrevIconIndex == (self._IconNumbers -1):
  470. self.IconSmoothUp(icon_width+ self._PageIconMargin)
  471. else:
  472. self.IconsEasingRight(icon_width + self._PageIconMargin)
  473. self._PsIndex = self._IconIndex
  474. self._Screen.Draw()
  475. self._Screen.SwapAndShow()
  476. if event.key == CurKeys["Enter"]:
  477. self.IconClick()
  478. self._Screen.Draw()
  479. self._Screen.SwapAndShow()
  480. def Draw(self):
  481. self.ClearCanvas()
  482. self.DrawIcons()
  483. self.DrawPageSelector()