123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675 |
- # -*- coding: utf-8 -*-
- import pygame
- from pygame.locals import *
- from sys import exit
- import os
- import sys
- import math
- import fnmatch
- import random
- from libs import easing
- # import base64
- # from beeprint import pp
- # local import
- from constants import ALIGN, icon_width, icon_height, Width, Height, ICON_TYPES
- from util_funcs import midRect,FileExists
- from keys_def import CurKeys, IsKeyStartOrA, IsKeyMenuOrB
- from icon_pool import MyIconPool
- from lang_manager import MyLangManager
- from widget import Widget
- import config
- class PageStack:
- def __init__(self):
- self.stack = list()
- def Push(self, data):
- if data not in self.stack:
- self.stack.append(data)
- return True
- return False
- def Pop(self):
- if len(self.stack) <= 0:
- return None, False
- return self.stack.pop(), True
- def Length(self):
- return len(self.stack)
- class PageSelector(Widget):
- _Parent = None
- _Alpha = 0
- _OnShow = True
- _IconSurf = None
- def __init__(self):
- pass
- def Init(self, x, y, w, h, alpha):
- self._PosX = x
- self._PosY = y
- self._Width = w
- self._Height = h
- self._Alpha = alpha
- def Adjust(self, x, y, w, h, alpha):
- self._PosX = x
- self._PosY = y
- self._Width = w
- self._Height = h
- self._Alpha = alpha
- def Draw(self):
- canvas = self._Parent._CanvasHWND
- idx = self._Parent._PsIndex
- iconidx = self._Parent._IconIndex
- if idx < len(self._Parent._Icons):
- x = self._Parent._Icons[idx]._PosX+self._Parent._PosX
- # only use current icon's PosY
- y = self._Parent._Icons[iconidx]._PosY
- rect = midRect(x, y, self._Width, self._Height,
- self._Parent._Width, self._Parent._Height)
- if rect.width <= 0 or rect.height <= 0:
- return
- # color = (244,197,66,50)
- # pygame.draw.rect(canvas,color,rect,1)
- if self._IconSurf != None:
- self._Parent._CanvasHWND.blit(self._IconSurf, rect)
- class Page(Widget):
- _Icons = []
- _Ps = None
- _PsIndex = 0
- _IconNumbers = 0
- _IconIndex = 0 # shows which icon current selected, the Selector can not move here
- _PrevIconIndex = 0 # for remember the Highlighted Icon ,restore it's PosY to average
- _Index = 0
- _Align = ALIGN["SLeft"]
- _CanvasHWND = None
- _HWND = None
- _OnShow = False
- _Name = ""
- _Screen = None # Should be the Screen Class
- _PageIconMargin = 20
- _FootMsg = ["Nav", "", "", "", "Enter"] # Default Page Foot info
- _Wallpaper = None
- _SelectedIconTopOffset = 20
- _EasingDur = 20/config.GlobalScale
- _Padding = pygame.Rect(0, 0, 0, 0) # x,y,w,h
- _Margin = pygame.Rect(0, 0, 0, 0)
- _ScrollStep = 1
- def __init__(self):
- self._Icons = []
- ## so every theme can have a background.png for displaying as the background of the launcher,except the topbar and footbar
- ## https://forum.clockworkpi.com/t/give-your-gs-a-custom-wallpaper/3724
- bg_img_path = config.SKIN+"/background.png"
- if FileExists(bg_img_path):
- self._Wallpaper = pygame.transform.scale(pygame.image.load(bg_img_path).convert(), (320,240))
-
- def AdjustHLeftAlign(self): ## adjust coordinator and append the PageSelector
- self._PosX = self._Index*self._Screen._Width
- self._Width = self._Screen._Width
- self._Height = self._Screen._Height
-
- cols = int(Width /icon_width)
- rows = int( (self._IconNumbers * icon_width)/Width + 1)
- if rows < 1:
- rows = 1
- cnt = 0
- for i in range(0,rows):
- for j in range(0,cols):
- start_x = icon_width/2 + j*icon_width
- start_y = icon_height/2 + i*icon_height
- icon = self._Icons[cnt]
- icon.Adjust(start_x,start_y,icon_width-4,icon_height-4,0)
- icon._Index = cnt
- icon._Parent = self
- if cnt >= (self._IconNumbers -1):
- break
- cnt+=1
-
- ps = PageSelector()
- ps._IconSurf = MyIconPool.GiveIconSurface("blueselector")
- ps._Parent = self
- ps.Init(icon_width/2, TitleBar._BarHeight+icon_height/2,92,92,128)
- self._Ps = ps
- self._PsIndex = 0
- self._OnShow = False
- def AdjustSLeftAlign(self): ## adjust coordinator and append the PageSelector
- self._PosX = self._Index*self._Screen._Width
- self._Width = self._Screen._Width
- self._Height = self._Screen._Height
-
- start_x = (self._PageIconMargin + icon_width+self._PageIconMargin) /2
- start_y = self._Height/2
-
- for i in range(0,self._IconNumbers):
- it = self._Icons[i]
- it._Parent = self
- it._Index = i
- it.Adjust(start_x+i*self._PageIconMargin+i*icon_width,start_y,icon_width-6,icon_height-6,0)
- it._ImgSurf = pygame.transform.smoothscale(it._ImgSurf,(it._Width,it._Height))
- ps = PageSelector()
- ps._IconSurf = MyIconPool.GiveIconSurface("blueselector")
- ps._Parent = self
- ps.Init(start_x,start_y,92,92,128)
-
- self._Ps = ps
- self._PsIndex = 0
- self._OnShow = False
-
- if self._IconNumbers > 1:
- self._PsIndex = 1
- self._IconIndex = self._PsIndex
- self._PrevIconIndex = self._IconIndex
- self._Icons[self._IconIndex]._PosY -= self._SelectedIconTopOffset
- def AdjustSAutoLeftAlign(self): ## adjust coordinator and append the PageSelector
- self._PosX = self._Index*self._Screen._Width
- self._Width = self._Screen._Width
- self._Height = self._Screen._Height
-
- start_x = (self._PageIconMargin + icon_width+self._PageIconMargin) /2
- start_y = self._Height/2
- if self._IconNumbers == 1:
- start_x = self._Width / 2
- start_y = self._Height/2
-
- it = self._Icons[0]
- it._Parent = self
- it._Index = 0
- it.Adjust(start_x,start_y,icon_width,icon_height,0)
- # it._ImgSurf = pygame.transform.smoothscale(it._ImgSurf,(it._Width,it._Height))
- elif self._IconNumbers == 2:
- start_x = (self._Width - self._PageIconMargin - self._IconNumbers*icon_width) / 2 + icon_width/2
- start_y = self._Height /2
- for i in range(0,self._IconNumbers):
- it = self._Icons[i]
- it._Parent = self
- it._Index = i
- it.Adjust(start_x+i*self._PageIconMargin + i*icon_width,start_y, icon_width, icon_height,0)
- # it._ImgSurf = pygame.transform.smoothscale(it._ImgSurf,(it._Width,it._Height))
-
- elif self._IconNumbers > 2:
- for i in range(0,self._IconNumbers):
- it = self._Icons[i]
- it._Parent = self
- it._Index = i
- it.Adjust(start_x+i*self._PageIconMargin + i*icon_width,start_y,icon_width,icon_height,0)
- # it._ImgSurf = pygame.transform.smoothscale(it._ImgSurf,(it._Width,it._Height))
- ps = PageSelector()
- ps._IconSurf = MyIconPool.GiveIconSurface("blueselector")
- ps._Parent = self
- ps.Init(start_x,start_y,92,92,128)
-
- self._Ps = ps
- self._PsIndex = 0
- self._OnShow = False
- if self._IconNumbers > 1:
- self._PsIndex = 1
- self._IconIndex = self._PsIndex
- self._PrevIconIndex = self._IconIndex
- self._Icons[self._IconIndex]._PosY -= self._SelectedIconTopOffset
- def InitLeftAlign(self):
- self._PosX = self._Index*Width
- self._Width = self._Screen._Width
- self._Height = self._Screen._Height
-
- cols = int(self._Width /icon_width)
- rows = int((self._IconNumbers * icon_width)/self._Width + 1)
- if rows < 1:
- rows = 1
- cnt = 0
- for i in range(0,rows):
- for j in range(0,cols):
- start_x = icon_width/2 + j*icon_width
- start_y = TitleBar._BarHeight + icon_height/2 + i*icon_height
- icon = IconItem()
- icon.Init(start_x,start_y,icon_width-4,icon_height-4,0)
- icon._Index = cnt
- icon._Parent = self
- self._Icons.append(icon)
- if cnt >= (self._IconNumbers -1):
- break
- cnt+=1
-
- ps = PageSelector()
- ps._IconSurf = MyIconPool.GiveIconSurface("blueselector")
- ps._Parent = self
- ps.Init(icon_width/2,icon_height/2,92,92,128)
- self._Ps = ps
- self._PsIndex = 0
- self._OnShow = False
- def Adjust(self): ## default init way,
- self._PosX = self._Index*self._Screen._Width
- self._Width = self._Screen._Width ## equal to screen width
- self._Height = self._Screen._Height
- if self._Align == ALIGN["HLeft"]:
- start_x = (self._Width - self._IconNumbers*icon_width)/2 + icon_width/2
- start_y = self._Height/2
- for i in range(0,self._IconNumbers):
- it = self._Icons[i]
- it._Parent = self
- it._Index = i
- it.Adjust(start_x+i*icon_width,start_y,icon_width,icon_height,0)
- ps = PageSelector()
- ps._IconSurf = MyIconPool.GiveIconSurface("blueselector")
- ps._Parent = self
- ps.Init(start_x,start_y,92,92,128)
- self._Ps = ps
- self._PsIndex = 0
- self._OnShow = False
- elif self._Align == ALIGN["SLeft"]:
- start_x = (self._PageIconMargin + icon_width+self._PageIconMargin) /2
- start_y = self._Height/2
-
- for i in range(0,self._IconNumbers):
- it = self._Icons[i]
- it._Parent = self
- it._Index = i
- it.Adjust(start_x+i*self._PageIconMargin+i*icon_width,start_y,icon_width,icon_height,0)
-
-
- ps = PageSelector()
- ps._IconSurf = MyIconPool.GiveIconSurface("blueselector")
- ps._Parent = self
- ps.Init(start_x,start_y-self._SelectedIconTopOffset,92,92,128)
-
- self._Ps = ps
- self._PsIndex = 0
- self._OnShow = False
-
- if self._IconNumbers > 1:
- self._PsIndex = 1
- self._IconIndex = self._PsIndex
- self._PrevIconIndex = self._IconIndex
- self._Icons[self._IconIndex]._PosY -= self._SelectedIconTopOffset
-
-
- def Init(self): ## default init way,
- if self._Screen != None:
- if self._Screen._CanvasHWND != None and self._CanvasHWND == None:
- self._CanvasHWND = self._Screen._CanvasHWND
- self._PosX = self._Index*self._Screen._Width
- self._Width = self._Screen._Width ## equal to screen width
- self._Height = self._Screen._Height
- start_x = (self._Width - self._IconNumbers*icon_width)/2 + icon_width/2
- start_y = self._Height/2
- for i in range(0,self._IconNumbers):
- it = IconItem()
- it._Parent = self
- it._Index = i
- it.Init(start_x+i*icon_width,start_y,icon_width,icon_height,0)
- self._Icons.append(it)
-
- if self._IconNumbers > 0:
- ps = PageSelector()
- ps._IconSurf = MyIconPool.GiveIconSurface("blueselector")
- ps._Parent = self
- ps.Init(start_x,start_y,icon_width+4,icon_height+4,128)
- self._Ps = ps
- self._PsIndex = 0
- self._OnShow = False
-
- def IconStepMoveData(self,icon_eh,cuts):## no Sine,No curve,plain movement steps data
- all_pieces = []
- piece = icon_eh / cuts
- c = 0.0
- prev = 0.0
- for i in range(0,cuts):
- c+=piece
- dx = c-prev
- if dx < 0.5:
- dx = 1.0
-
- all_pieces.append( math.ceil(dx) )
- if c >= icon_eh:
- break
- c = 0
- bidx = 0
- for i in all_pieces:
- c+=i
- bidx+=1
- if c >= icon_eh:
- break
- all_pieces = all_pieces[0:bidx]
- if len(all_pieces) < cuts:
- dff = cuts - len(all_pieces)
- diffa = []
- for i in range(0,dff):
- diffa.append(0)
- all_pieces.extend( diffa)
-
- return all_pieces
- def EasingData(self,start,distance):##generate easing steps data
- current_time = 0.0
- start_posx = 0.0
- current_posx = start_posx
- final_posx = float(distance)
- posx_init = start
- dur = self._EasingDur
- last_posx = 0.0
- all_last_posx = []
- for i in range(0,distance*dur):
- current_posx = easing.SineIn(current_time,start_posx,final_posx-start_posx,float(dur))
- if current_posx >= final_posx:
- current_posx = final_posx
- dx = current_posx - last_posx
- all_last_posx.append(int(dx))
- current_time+=1
- last_posx = current_posx
- if current_posx >= final_posx:
- break
- c = 0
- for i in all_last_posx:
- c+=i
- if c < final_posx -start_posx:
- all_last_posx.append(final_posx - c)
- return all_last_posx
- def IconSmoothUp(self,icon_ew):
- data = self.EasingData(self._PosX,icon_ew)
- data2 = self.IconStepMoveData(self._SelectedIconTopOffset,len(data))
-
- for i,v in enumerate(data):
-
- self.ClearCanvas()
-
- self._Icons[self._IconIndex]._PosY -= data2[i]
-
- if self._Icons[self._PrevIconIndex]._PosY < self._Height/2:
- self._Icons[self._PrevIconIndex]._PosY+=data2[i]
- self.DrawIcons()
- self._Screen.SwapAndShow()
-
- def IconsEasingLeft(self,icon_ew):
- data = self.EasingData(self._PosX,icon_ew)
- data2 = self.IconStepMoveData(self._SelectedIconTopOffset,len(data))
-
- for i,v in enumerate(data):
-
- self.ClearCanvas()
- self._PosX -= v
-
- self._Icons[self._IconIndex]._PosY -= data2[i]
-
- if self._Icons[self._PrevIconIndex]._PosY < self._Height/2:
- self._Icons[self._PrevIconIndex]._PosY+=data2[i]
- self.DrawIcons()
- self._Screen.SwapAndShow()
-
- def IconsEasingRight(self,icon_ew):
-
- data = self.EasingData(self._PosX,icon_ew)
- data2 = self.IconStepMoveData(self._SelectedIconTopOffset,len(data))
-
- for i,v in enumerate(data):
- self.ClearCanvas()
- self._PosX += v
-
- self._Icons[self._IconIndex]._PosY-=data2[i]
-
- if self._Icons[self._PrevIconIndex]._PosY < self._Height/2:
- self._Icons[self._PrevIconIndex]._PosY+=data2[i]
-
- self.DrawIcons()
- self._Screen.SwapAndShow()
-
- def EasingLeft(self,ew): #ew int
- data = self.EasingData(self._PosX,ew)
-
- for i in data:
- self._PosX -=i
- self.Draw()
- self._Screen.SwapAndShow()
-
- def EasingRight(self,ew):
- data = self.EasingData(self._PosX,ew)
-
- for i in data:
- self._PosX += i
- self.Draw()
- self._Screen.SwapAndShow()
-
- def MoveLeft(self,ew):
- self._PosX -= ew
- def MoveRight(self,ew):
- self._PosX += ew
-
- def ResetPageSelector(self):
- self._PsIndex = 0
- self._IconIndex = 0
- self._Ps._OnShow = True
- def DrawPageSelector(self):
- if self._Ps._OnShow == True:
- self._Ps.Draw()
-
- def MoveIconIndexPrev(self):
- self._PrevIconIndex = self._IconIndex
- self._IconIndex-=1
- if self._IconIndex < 0:
- self._IconIndex = max(0, self._IconNumbers - 1) # Wrap Icon Index
- return False
- return True
-
- def MoveIconIndexNext(self):
- self._PrevIconIndex = self._IconIndex
- self._IconIndex+=1
- if self._IconIndex > (self._IconNumbers - 1):
- self._IconIndex = 0 # Wrap Icon Index
- return False
- return True
-
- def IconClick(self):
-
- if self._IconIndex > (len(self._Icons) -1):
- return
- cur_icon = self._Icons[self._IconIndex]
- if self._Ps._OnShow == False:
- return
- if cur_icon._MyType == ICON_TYPES["EXE"]:
- print("IconClick: %s %d"%(cur_icon._CmdPath,cur_icon._Index))
- self._Screen.RunEXE(cur_icon._CmdPath)
-
- elif cur_icon._MyType == ICON_TYPES["DIR"]:
- child_page = self._Icons[self._IconIndex]._LinkPage
- if child_page != None:
- child_page.Draw()
- self._Screen._MyPageStack.Push(self._Screen._CurrentPage)
- self._Screen._CurrentPage = child_page
- elif cur_icon._MyType == ICON_TYPES["FUNC"]:
- print("IconClick API: %d"%(cur_icon._Index))
- # print("%s"% cur_icon._CmdPath)
- api_cb = getattr(cur_icon._CmdPath,"API",None)
- if api_cb != None:
- if callable(api_cb):
- cur_icon._CmdPath.API(self._Screen)
- elif cur_icon._MyType == ICON_TYPES["Emulator"] or cur_icon._MyType == ICON_TYPES["Commercial"]:
- cur_icon._CmdPath.API(self._Screen)
-
- def ReturnToUpLevelPage(self):
- pop_page,ok = self._Screen._MyPageStack.Pop()
- if ok == True:
- # self._Screen._CurrentPage.ResetPageSelector()
- pop_page.Draw()
- self._Screen._CurrentPage = pop_page
- on_return_back_cb = getattr(self._Screen._CurrentPage,"OnReturnBackCb",None)
- if on_return_back_cb != None:
- if callable(on_return_back_cb):
- self._Screen._CurrentPage.OnReturnBackCb()
- else:
- if self._Screen._MyPageStack.Length() == 0:
- if len(self._Screen._Pages) > 0:
- self._Screen._CurrentPage = self._Screen._Pages[self._Screen._PageIndex]
- self._Screen._CurrentPage.Draw()
- print("OnTopLevel ",self._Screen._PageIndex)
- def ClearCanvas(self):
- if self._Wallpaper:
- self._CanvasHWND.blit(self._Wallpaper,(0,0))
- else:
- self._CanvasHWND.fill(self._Screen._SkinManager.GiveColor("White"))
-
-
- def ClearIcons(self):
- for i in range(0,self._IconNumbers):
- self._Icons[i].Clear()
- def DrawIcons(self):
- for i in range(0,self._IconNumbers):
- self._Icons[i].Draw()
- # make sure the Class has the _MyList
- def ScrollDown(self):
- if len(self._MyList) == 0:
- return
- self._PsIndex +=1
- if self._PsIndex >= len(self._MyList):
- self._PsIndex = len(self._MyList) -1
- cur_li = self._MyList[self._PsIndex]
- if cur_li._PosY +cur_li._Height > self._Height:
- for i in range(0,len(self._MyList)):
- self._MyList[i]._PosY -= self._MyList[i]._Height
-
- def ScrollUp(self):
- if len(self._MyList) == 0:
- return
- self._PsIndex -= 1
- if self._PsIndex < 0:
- self._PsIndex = 0
- cur_li = self._MyList[self._PsIndex]
- if cur_li._PosY < 0:
- for i in range(0, len(self._MyList)):
- self._MyList[i]._PosY += self._MyList[i]._Height
- def FScrollUp(self,Step=1):
- if len(self._MyList) == 0:
- return
- tmp = self._PsIndex
- self._PsIndex -= Step
-
- if self._PsIndex < 0:
- self._PsIndex = 0
- dy = tmp-self._PsIndex
- cur_li = self._MyList[self._PsIndex]
- if cur_li._PosY < 0:
- for i in range(0, len(self._MyList)):
- self._MyList[i]._PosY += self._MyList[i]._Height*dy
-
- def RefreshPsIndex(self):
- if len(self._MyList) == 0:
- self._PsIndex = 0
- if self._PsIndex > (len(self._MyList) -1):
- self._PsIndex = len(self._MyList) -1
-
- def FScrollDown(self,Step=1):
- if len(self._MyList) == 0:
- return
- tmp = self._PsIndex
- self._PsIndex +=Step
- if self._PsIndex >= len(self._MyList):
- self._PsIndex = len(self._MyList) -1
- dy = self._PsIndex - tmp
- cur_li = self._MyList[self._PsIndex]
- if cur_li._PosY +cur_li._Height > self._Height:
- for i in range(0,len(self._MyList)):
- self._MyList[i]._PosY -= self._MyList[i]._Height*dy
-
- def KeyDown(self,event):##default keydown,every inherited page class should have it's own KeyDown
- if IsKeyMenuOrB(event.key):
- self.ReturnToUpLevelPage()
- self._Screen.Draw()
- self._Screen.SwapAndShow()
- if event.key == CurKeys["Right"]:
- if self.MoveIconIndexNext() == True:
- if self._IconIndex == (self._IconNumbers -1) or self._PrevIconIndex == 0:
- self.IconSmoothUp(icon_width + self._PageIconMargin)
- else:
- self.IconsEasingLeft(icon_width + self._PageIconMargin)
- else:
- screen_icons = int(math.floor(self._Screen._Width / (icon_width + self._PageIconMargin)))
- if self._IconNumbers > screen_icons:
- self.IconsEasingRight((icon_width + self._PageIconMargin) * (self._IconNumbers - screen_icons))
- elif self._IconNumbers > 0:
- self.IconSmoothUp(icon_width+ self._PageIconMargin)
- self._PsIndex = self._IconIndex
- self._Screen.Draw()
- self._Screen.SwapAndShow()
-
- if event.key == CurKeys["Left"]:
- if self.MoveIconIndexPrev() == True:
- if self._IconIndex == 0 or self._PrevIconIndex == (self._IconNumbers -1):
- self.IconSmoothUp(icon_width + self._PageIconMargin)
- else:
- self.IconsEasingRight(icon_width + self._PageIconMargin)
- else:
- screen_icons = int(math.floor(self._Screen._Width / (icon_width + self._PageIconMargin)))
- if self._IconNumbers > screen_icons:
- self.IconsEasingLeft((icon_width + self._PageIconMargin) * (self._IconNumbers - screen_icons))
- elif self._IconNumbers > 0:
- self.IconSmoothUp(icon_width+ self._PageIconMargin)
- self._PsIndex = self._IconIndex
- self._Screen.Draw()
- self._Screen.SwapAndShow()
-
- if IsKeyStartOrA(event.key):
- self.IconClick()
- self._Screen.Draw()
- self._Screen.SwapAndShow()
- def Draw(self):
- self.ClearCanvas()
- self.DrawIcons()
- self.DrawPageSelector()
|