main_screen.py 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575
  1. # -*- coding: utf-8 -*-
  2. import pygame
  3. from pygame.locals import *
  4. from sys import exit
  5. import os
  6. import sys
  7. from libs import easing
  8. from datetime import datetime
  9. from beeprint import pp
  10. ## local package import
  11. from constants import ICON_TYPES,icon_ext,icon_width,icon_height,RUNEVT
  12. from icon_item import IconItem
  13. from page import Page,PageStack
  14. from title_bar import TitleBar
  15. from foot_bar import FootBar
  16. from constants import Width,Height,bg_color
  17. from util_funcs import midRect,FileExists,ReplaceSuffix,ReadTheFileContent,CmdClean,MakeExecutable,SkinMap
  18. from fonts import fonts
  19. from keys_def import CurKeys
  20. from label import Label
  21. from untitled_icon import UntitledIcon
  22. from Emulator import MyEmulator
  23. from skin_manager import SkinManager
  24. from counter_screen import CounterScreen
  25. class MessageBox(Label):
  26. _Parent = None
  27. def __init__(self):
  28. pass
  29. def Init(self,text,font_obj,color=pygame.Color(83,83,83)):
  30. self._Color = color
  31. self._FontObj = font_obj
  32. self._Text = text
  33. self._Width = 0
  34. self._Height = 0
  35. self._CanvasHWND = pygame.Surface( ( int(self._Parent._Width),int(self._Parent._Height)))
  36. self._HWND = self._Parent._CanvasHWND
  37. def SetText(self,text):
  38. self._Text = text
  39. def PreDraw(self):
  40. self._Width = 0
  41. self._Height = 0
  42. self._CanvasHWND.fill( (255,255,255))
  43. words = self._Text.split(' ')
  44. space = self._FontObj.size(' ')[0]
  45. max_width = self._Parent._Width-40
  46. x ,y = (0,0)
  47. row_total_width = 0
  48. lines = 0
  49. for word in words:
  50. word_surface = self._FontObj.render(word, True, self._Color)
  51. word_width = word_surface.get_width()
  52. word_height = word_surface.get_height()
  53. row_total_width += word_width
  54. if lines == 0:
  55. lines += word_height
  56. if row_total_width+space >= max_width:
  57. x = 0 # Reset the x.
  58. y += word_height # Start on new row.
  59. row_total_width = word_width
  60. lines += word_height
  61. self._CanvasHWND.blit(word_surface, (x, y))
  62. if len(words) == 1: # single line
  63. x += word_width
  64. else:
  65. x += word_width + space
  66. if x > self._Width:
  67. self._Width = x
  68. if lines >= (self._Parent._Height - 40):
  69. break
  70. self._Height = lines
  71. def DrawWith(self, x_,y_, withborder):
  72. self.PreDraw()
  73. x_ = x_ - self._Width/2
  74. y_ = y_ - self._Height/2
  75. padding = 5
  76. pygame.draw.rect(self._HWND,(255,255,255),(x_-padding,y_-padding, self._Width+padding*2,self._Height+padding*2))
  77. if self._HWND != None:
  78. rect = pygame.Rect(x_,y_,self._Width,self._Height)
  79. self._HWND.blit(self._CanvasHWND,rect,(0,0,self._Width,self._Height))
  80. #self._HWND.blit(self._CanvasHWND,rect)
  81. if withborder == True:
  82. pygame.draw.rect(self._HWND,(0,0,0),(x_-padding,y_-padding, self._Width+padding*2,self._Height+padding*2),1)
  83. def Draw(self):
  84. x = (self._Parent._Width)/2
  85. y = (self._Parent._Height)/2
  86. self.DrawWith(x,y,True)
  87. python_package_flag = "__init__.py"
  88. emulator_flag = "action.config"
  89. ##Abstract object for manage Pages ,not the pygame's physic screen
  90. class MainScreen(object):
  91. _Pages = []
  92. _PageMax = 0
  93. _PageIndex = 0
  94. _PosX = 0
  95. _PosY = TitleBar._BarHeight+1
  96. _Width = Width
  97. _Height = Height -FootBar._BarHeight -TitleBar._BarHeight
  98. _MyPageStack = None
  99. _CurrentPage = None # pointer to the current displaying Page Class
  100. _CanvasHWND = None
  101. _HWND = None
  102. _TitleBar = None
  103. _FootBar = None
  104. _MsgBox = None
  105. _MsgBoxFont = fonts["veramono20"]
  106. _IconFont = fonts["varela15"]
  107. _SkinManager = None
  108. _Closed = False
  109. _CounterScreen = None
  110. def __init__(self):
  111. self._Pages = []
  112. self._MyPageStack = PageStack()
  113. def Init(self):
  114. self._CanvasHWND = pygame.Surface((self._Width,self._Height))
  115. self._MsgBox= MessageBox()
  116. self._MsgBox._Parent= self
  117. self._MsgBox.Init(" ", self._MsgBoxFont)
  118. self._SkinManager = SkinManager()
  119. self._SkinManager.Init()
  120. self._CounterScreen = CounterScreen()
  121. self._CounterScreen._HWND = self._HWND
  122. self._CounterScreen.Init()
  123. def FartherPages(self):
  124. self._PageMax = len(self._Pages)
  125. for i in range(0,self._PageMax):
  126. self._Pages[i]._Index = i
  127. self._Pages[i]._CanvasHWND = self._CanvasHWND
  128. self._Pages[i]._IconNumbers = len(self._Pages[i]._Icons)
  129. self._Pages[i]._Screen = self
  130. self._Pages[i].Adjust()
  131. if self._Pages[i]._IconNumbers > 1:
  132. self._Pages[i]._PsIndex = 1
  133. self._Pages[i]._IconIndex = self._Pages[i]._PsIndex
  134. self._CurrentPage = self._Pages[self._PageIndex]
  135. self._CurrentPage._OnShow = True
  136. def GetMyRightSidePage(self):
  137. ret = self._PageIndex +1
  138. if ret > (self._PageMax -1):
  139. ret = self._PageMax -1
  140. return ret
  141. def PageMoveLeft(self):
  142. self._Pages[self._PageIndex]._OnShow = False
  143. if self._PageIndex < (self._PageMax - 1):
  144. my_right_side_page = self.GetMyRightSidePage()
  145. for i in range(0,self._PageMax):
  146. if i!= self._PageIndex and i != my_right_side_page:
  147. self._Pages[i].MoveLeft(Width)
  148. self._Pages[self._PageIndex].EasingLeft(Width)
  149. if self._PageIndex != my_right_side_page:
  150. self._Pages[my_right_side_page].EasingLeft(Width)
  151. self._Pages[self._PageIndex].ResetPageSelector()
  152. self._PageIndex+=1
  153. if self._PageIndex > (self._PageMax -1):
  154. self._PageIndex = (self._PageMax -1)
  155. self._Pages[self._PageIndex]._OnShow = True
  156. self._CurrentPage = self._Pages[self._PageIndex]
  157. def GetMyLeftSidePage(self):
  158. ret = self._PageIndex -1
  159. if ret < 0:
  160. ret = 0
  161. return ret
  162. def PageMoveRight(self):
  163. self._Pages[self._PageIndex]._OnShow = False
  164. if self._PageIndex > 0:
  165. my_left_side_page = self.GetMyLeftSidePage()
  166. for i in range(0,self._PageMax):
  167. if i!= self._PageIndex and i!= my_left_side_page:
  168. pass
  169. #self._Pages[i].MoveRight(Width)
  170. self._Pages[self._PageIndex].EasingRight(Width)
  171. if self._PageIndex != my_left_side_page:
  172. self._Pages[my_left_side_page].EasingRight(Width)
  173. self._Pages[self._PageIndex].ResetPageSelector()
  174. self._PageIndex-=1
  175. if self._PageIndex < 0:
  176. self._PageIndex = 0
  177. self._Pages[self._PageIndex]._OnShow = True
  178. self._CurrentPage = self._Pages[self._PageIndex]
  179. def EasingAllPageLeft(self):
  180. current_time = 0.0
  181. start_posx = 0.0
  182. current_posx = start_posx
  183. final_posx = float(Width)
  184. posx_init = 0
  185. dur = 30
  186. last_posx = 0.0
  187. all_last_posx = []
  188. if self._PageIndex >= (self._PageMax - 1):
  189. return
  190. for i in range(0,Width*dur):
  191. current_posx = easing.SineIn(current_time,start_posx,final_posx-start_posx,float(dur))
  192. if current_posx >= final_posx:
  193. current_posx = final_posx
  194. dx = current_posx - last_posx
  195. all_last_posx.append(int(dx))
  196. current_time+=1
  197. last_posx = current_posx
  198. if current_posx >= final_posx:
  199. break
  200. c = 0
  201. for i in all_last_posx:
  202. c+=i
  203. if c < final_posx - start_posx:
  204. all_last_posx.append( final_posx - c )
  205. for i in all_last_posx:
  206. self.ClearCanvas()
  207. for j in self._Pages:
  208. j._PosX -= i
  209. j.DrawIcons()
  210. j._Screen.SwapAndShow()
  211. self._Pages[self._PageIndex]._OnShow = False
  212. self._PageIndex+=1
  213. if self._PageIndex > (self._PageMax -1):
  214. self._PageIndex = (self._PageMax -1)
  215. self._Pages[self._PageIndex]._OnShow = True
  216. self._CurrentPage = self._Pages[self._PageIndex]
  217. def EasingAllPageRight(self):
  218. current_time = 0.0
  219. start_posx = 0.0
  220. current_posx = start_posx
  221. final_posx = float(Width)
  222. posx_init = 0
  223. dur = 30
  224. last_posx = 0.0
  225. all_last_posx = []
  226. if self._PageIndex <= 0:
  227. return
  228. for i in range(0,Width*dur):
  229. current_posx = easing.SineIn(current_time,start_posx,final_posx-start_posx,float(dur))
  230. if current_posx >= final_posx:
  231. current_posx = final_posx
  232. dx = current_posx - last_posx
  233. all_last_posx.append(int(dx))
  234. current_time+=1
  235. last_posx = current_posx
  236. if current_posx >= final_posx:
  237. break
  238. c = 0
  239. for i in all_last_posx:
  240. c+=i
  241. if c < final_posx - start_posx:
  242. all_last_posx.append( final_posx - c )
  243. for i in all_last_posx:
  244. self.ClearCanvas()
  245. for j in reversed(self._Pages):
  246. j._PosX += i
  247. j.DrawIcons()
  248. j._Screen.SwapAndShow()
  249. self._Pages[self._PageIndex]._OnShow = False
  250. self._PageIndex-=1
  251. if self._PageIndex < 0:
  252. self._PageIndex = 0
  253. self._Pages[self._PageIndex]._OnShow = True
  254. self._CurrentPage = self._Pages[self._PageIndex]
  255. def CurPage(self):
  256. return self._CurrentPage
  257. def PushCurPage(self):
  258. self._MyPageStack.Push(self._CurrentPage)
  259. def SetCurPage(self,page):
  260. self._CurrentPage = page
  261. on_load_cb = getattr(self._CurrentPage,"OnLoadCb",None)
  262. if on_load_cb != None:
  263. if callable( on_load_cb ):
  264. self._CurrentPage.OnLoadCb()
  265. def PushPage(self,page):
  266. self.PushCurPage()
  267. self.SetCurPage(page)
  268. def AppendPage(self,Page):
  269. self._Pages.append(Page)
  270. def ClearCanvas(self):
  271. self._CanvasHWND.fill((255,255,255))
  272. def SwapAndShow(self):
  273. if self._Closed == True:
  274. return
  275. if self._HWND != None:
  276. self._HWND.blit(self._CanvasHWND,(self._PosX,self._PosY,self._Width,self._Height))
  277. pygame.display.update()
  278. def ExtraName(self,name):
  279. ## extra name like 1_xxx to be => xxx,
  280. parts = name.split("_")
  281. if len(parts) > 1:
  282. return parts[1]
  283. elif len(parts) == 1:
  284. return parts[0]
  285. else:
  286. return name
  287. def IsExecPackage(self,dirname):
  288. files = os.listdir(dirname)
  289. bname = os.path.basename(dirname)
  290. bname = self.ExtraName(bname)
  291. for i in sorted(files):
  292. if i == bname+".sh":
  293. return True
  294. return False
  295. def IsEmulatorPackage(self,dirname):
  296. files = os.listdir(dirname)
  297. for i in sorted(files):
  298. if i.endswith(emulator_flag):
  299. return True
  300. return False
  301. def IsPythonPackage(self,dirname):
  302. files = os.listdir(dirname)
  303. for i in sorted(files):
  304. if i.endswith(python_package_flag):
  305. return True
  306. return False
  307. def ReadTheDirIntoPages(self,_dir,pglevel,cur_page):
  308. if FileExists(_dir) == False and os.path.isdir(_dir) == False:
  309. return
  310. files = os.listdir(_dir)
  311. for i in sorted(files):
  312. if os.path.isdir(_dir+"/"+i): # TOPLEVEL only is dir
  313. if pglevel == 0:
  314. page = Page()
  315. page._Name = self.ExtraName(i)
  316. page._Icons = []
  317. self._Pages.append(page)
  318. self.ReadTheDirIntoPages(_dir+"/"+i, pglevel+1 ,self._Pages[ len(self._Pages) -1])
  319. else: ## On CurPage now
  320. i2 = self.ExtraName(i)
  321. iconitem = IconItem()
  322. iconitem._CmdPath = ""
  323. iconitem.AddLabel(i2,self._IconFont)
  324. if FileExists( _dir+"/"+i+"/"+i2+".png"): ### 20_Prog/Prog.png , cut 20_
  325. iconitem._ImageName = _dir+"/"+i+"/"+i2+".png"
  326. elif FileExists( SkinMap(_dir+"/"+i2+".png") ):
  327. iconitem._ImageName = SkinMap(_dir+"/"+i2+".png")
  328. else:
  329. untitled = UntitledIcon()
  330. untitled.Init()
  331. if len(i2) > 1:
  332. untitled.SetWords(i2[:2])
  333. elif len(i2) == 1:
  334. untitled.SetWords([i2[0],i2[0]])
  335. else:
  336. untitled.SetWords(["G","s"])
  337. iconitem._ImgSurf = untitled.Surface()
  338. iconitem._ImageName = ""
  339. if self.IsPythonPackage(_dir+"/"+i):
  340. iconitem._MyType = ICON_TYPES["FUNC"]
  341. sys.path.append(_dir)
  342. iconitem._CmdPath = __import__(i)
  343. init_cb = getattr(iconitem._CmdPath,"Init",None)
  344. if init_cb != None:
  345. if callable(init_cb):
  346. iconitem._CmdPath.Init(self)
  347. cur_page._Icons.append(iconitem)
  348. elif self.IsEmulatorPackage(_dir+"/"+i):
  349. obj = {}
  350. obj["ROM"] = ""
  351. obj["ROM_SO"] =""
  352. obj["EXT"] = []
  353. obj["FILETYPE"] = "file"
  354. obj["LAUNCHER"] = ""
  355. obj["TITLE"] = "Game"
  356. obj["SO_URL"] = ""
  357. obj["RETRO_CONFIG"] = "" ##
  358. try:
  359. f = open(_dir+"/"+i+"/"+emulator_flag)
  360. except IOError:
  361. print("action config open failed")
  362. return
  363. else:
  364. with f:
  365. content = f.readlines()
  366. content = [x.strip() for x in content]
  367. for i in content:
  368. pis = i.split("=")
  369. if len(pis) > 1:
  370. if "EXT" in pis[0]:
  371. obj[pis[0]] = pis[1].split(",")
  372. else:
  373. obj[pis[0]] = pis[1]
  374. em = MyEmulator()
  375. em._Emulator = obj
  376. em.Init(self)
  377. iconitem._CmdPath = em
  378. iconitem._MyType = ICON_TYPES["Emulator"]
  379. cur_page._Icons.append(iconitem)
  380. elif self.IsExecPackage(_dir+"/"+i):
  381. iconitem._MyType = ICON_TYPES["EXE"]
  382. iconitem._CmdPath = os.path.realpath(_dir+"/"+i+"/"+i2+".sh")
  383. MakeExecutable(iconitem._CmdPath)
  384. cur_page._Icons.append(iconitem)
  385. else:
  386. iconitem._MyType = ICON_TYPES["DIR"]
  387. iconitem._LinkPage = Page()
  388. iconitem._LinkPage._Name = i2
  389. cur_page._Icons.append(iconitem)
  390. self.ReadTheDirIntoPages(_dir+"/"+i,pglevel+1,iconitem._LinkPage)
  391. elif os.path.isfile(_dir+"/"+i) and pglevel > 0:
  392. if i.lower().endswith(icon_ext):
  393. i2 = self.ExtraName(i)
  394. #cmd = ReadTheFileContent(_dir+"/"+i)
  395. iconitem = IconItem()
  396. iconitem._CmdPath = os.path.realpath(_dir+"/"+i)
  397. MakeExecutable(iconitem._CmdPath)
  398. iconitem._MyType = ICON_TYPES["EXE"]
  399. if FileExists( SkinMap( _dir+"/"+ReplaceSuffix(i2,"png"))):
  400. iconitem._ImageName = SkinMap(_dir+"/"+ReplaceSuffix(i2,"png"))
  401. else:
  402. untitled = UntitledIcon()
  403. untitled.Init()
  404. if len(i2) > 1:
  405. untitled.SetWords(i2[:2])
  406. elif len(i2) == 1:
  407. untitled.SetWords([i2[0],i2[0]])
  408. else:
  409. untitled.SetWords(["G","s"])
  410. iconitem._ImgSurf = untitled.Surface()
  411. iconitem._ImageName = ""
  412. iconitem.AddLabel(i2.split(".")[0],self._IconFont)
  413. iconitem._LinkPage = None
  414. cur_page._Icons.append(iconitem)
  415. def RunEXE(self,cmdpath):
  416. self.DrawRun()
  417. self.SwapAndShow()
  418. pygame.time.delay(1000)
  419. cmdpath = cmdpath.strip()
  420. cmdpath = CmdClean(cmdpath)
  421. pygame.event.post( pygame.event.Event(RUNEVT, message=cmdpath))
  422. def OnExitCb(self,event):
  423. ## leave rest to Pages
  424. on_exit_cb = getattr(self._CurrentPage,"OnExitCb",None)
  425. if on_exit_cb != None:
  426. if callable( on_exit_cb ):
  427. self._CurrentPage.OnExitCb(event)
  428. return
  429. def KeyDown(self,event):
  430. """
  431. if event.key == pygame.K_PAGEUP:
  432. self.EasingAllPageLeft()
  433. #self.SwapAndShow()
  434. if event.key == pygame.K_PAGEDOWN:
  435. self.EasingAllPageRight()
  436. #self.SwapAndShow()
  437. """
  438. if event.key == pygame.K_t:
  439. self.DrawRun()
  440. self.SwapAndShow()
  441. """
  442. if event.key == CurKeys["Space"]:
  443. self._CounterScreen.Draw()
  444. self._CounterScreen.SwapAndShow()
  445. self._CounterScreen.StartCounter()
  446. """
  447. ## leave rest to Pages
  448. current_page_key_down_cb = getattr(self._CurrentPage,"KeyDown",None)
  449. if current_page_key_down_cb != None:
  450. if callable( current_page_key_down_cb ):
  451. self._CurrentPage.KeyDown(event)
  452. def DrawRun(self):
  453. self._MsgBox.SetText("Launching....")
  454. self._MsgBox.Draw()
  455. def Draw(self):
  456. if self._Closed == True:
  457. return
  458. self._CurrentPage.Draw()
  459. #if self._HWND != None:
  460. # self._HWND.blit(self._CanvasHWND,(self._PosX,self._PosY,self._Width,self._Height))
  461. if self._TitleBar != None:
  462. self._TitleBar.Draw(self._CurrentPage._Name)
  463. if self._FootBar != None:
  464. if hasattr(self._CurrentPage,"_FootMsg"):
  465. self._FootBar.SetLabelTexts(self._CurrentPage._FootMsg)
  466. self._FootBar.Draw()