main_screen.go 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483
  1. package UI
  2. import (
  3. "fmt"
  4. "io/ioutil"
  5. "log"
  6. "strings"
  7. //"encoding/json"
  8. "github.com/veandco/go-sdl2/sdl"
  9. "github.com/veandco/go-sdl2/ttf"
  10. "path/filepath"
  11. gotime "time"
  12. "github.com/cuu/gogame/color"
  13. "github.com/cuu/gogame/display"
  14. "github.com/cuu/gogame/draw"
  15. "github.com/cuu/gogame/font"
  16. "github.com/cuu/gogame/rect"
  17. "github.com/cuu/gogame/surface"
  18. "github.com/cuu/gogame/time"
  19. "github.com/cuu/gogame/event"
  20. "github.com/clockworkpi/LauncherGoDev/sysgo"
  21. )
  22. //eg: MainScreen
  23. type ScreenInterface interface {
  24. AppendPage(pg PageInterface)
  25. ClearCanvas()
  26. CurPage() PageInterface
  27. Draw()
  28. ExtraName(name string) string
  29. FartherPages()
  30. Init()
  31. IsEmulatorPackage(dirname string) bool
  32. IsExecPackage(dirname string) bool
  33. IsPluginPackage(dirname string) bool
  34. KeyDown(ev *event.Event)
  35. OnExitCb()
  36. HookExitCb()
  37. PushCurPage()
  38. PushPage(pg PageInterface)
  39. RunEXE(cmdpath string)
  40. SetCurPage(pg PageInterface)
  41. SwapAndShow()
  42. IsWifiConnectedNow()
  43. Refresh()
  44. }
  45. type PluginConfig struct {
  46. NAME string `json:"NAME"` // plugin name,default could be the same as Plugin Folder's name
  47. SO_FILE string `json:"SO_FILE"`
  48. }
  49. type MessageBox struct {
  50. Label
  51. Parent *sdl.Surface
  52. ParentWidth int
  53. ParentHeight int
  54. HWND *sdl.Surface
  55. }
  56. func NewMessageBox() *MessageBox {
  57. m := &MessageBox{}
  58. m.Color = &color.Color{83, 83, 83, 255}
  59. return m
  60. }
  61. func (self *MessageBox) Init(text string, font_obj *ttf.Font, col *color.Color,w int, h int) {
  62. if col != nil {
  63. self.Color = col
  64. }
  65. self.Text = text
  66. self.FontObj = font_obj
  67. self.Width = 0
  68. self.Height = 0
  69. if w == 0 || h == 0 {
  70. self.CanvasHWND = surface.Surface(Width,Height)
  71. self.ParentWidth = Width
  72. self.ParentHeight = Height
  73. }else{
  74. self.CanvasHWND = surface.Surface(w,h)
  75. self.ParentWidth = w
  76. self.ParentHeight = h
  77. }
  78. self.HWND = self.Parent
  79. }
  80. func (self *MessageBox) SetText(text string) {
  81. self.Text = text
  82. }
  83. func (self *MessageBox) Draw() {
  84. self.Width = 0
  85. self.Height = 0
  86. surface.Fill(self.CanvasHWND, &color.Color{255, 255, 255, 255})
  87. words := strings.Split(self.Text, " ")
  88. space, _ := font.Size(self.FontObj, " ")
  89. max_width := self.ParentWidth - 40
  90. x := 0
  91. y := 0
  92. row_total_width := 0
  93. lines := 0
  94. for _, word := range words {
  95. word_surface := font.Render(self.FontObj, word, true, self.Color, nil)
  96. word_width := int(word_surface.W)
  97. word_height := int(word_surface.H)
  98. row_total_width += word_width
  99. if lines == 0 {
  100. lines += word_height
  101. }
  102. if (row_total_width + space) >= max_width {
  103. x = 0
  104. y += word_height
  105. row_total_width = word_width
  106. lines += word_height
  107. }
  108. dest_rect := rect.Rect(x, y, word_width, word_height)
  109. surface.Blit(self.CanvasHWND, word_surface, &dest_rect, nil)
  110. word_surface.Free()
  111. if len(words) == 1 {
  112. x += word_width
  113. } else {
  114. x += word_width + space
  115. }
  116. if x > self.Width {
  117. self.Width = x
  118. }
  119. if lines >= self.ParentHeight-40 {
  120. break
  121. }
  122. }
  123. self.Height = lines
  124. padding := 5
  125. x = (self.ParentWidth - self.Width) / 2
  126. y = (self.ParentHeight - self.Height) / 2
  127. rect_ := rect.Rect(x-padding, y-padding, self.Width+padding*2, self.Height+padding*2)
  128. if self.HWND != nil {
  129. draw.Rect(self.HWND, &color.Color{255, 255, 255, 255}, &rect_, 0)
  130. rect__ := draw.MidRect(self.ParentWidth/2, self.ParentHeight/2, self.Width, self.Height, Width, Height)
  131. dest_rect := rect.Rect(0, 0, self.Width, self.Height)
  132. surface.Blit(self.HWND, self.CanvasHWND, rect__, &dest_rect)
  133. draw.Rect(self.HWND, &color.Color{0, 0, 0, 255}, &rect_, 1)
  134. }
  135. }
  136. type MainScreen struct {
  137. Widget
  138. Pages []PageInterface
  139. Child []PageInterface
  140. PageMax int
  141. PageIndex int
  142. MyPageStack *PageStack
  143. CurrentPage PageInterface
  144. CanvasHWND *sdl.Surface
  145. HWND *sdl.Surface
  146. TitleBar *TitleBar
  147. FootBar *FootBar
  148. MsgBox *MessageBox
  149. MsgBoxFont *ttf.Font
  150. IconFont *ttf.Font
  151. SkinManager *SkinManager
  152. CounterScreen *CounterScreen
  153. Closed bool
  154. UIPluginList []*UIPlugin
  155. LastKey string
  156. LastKeyDown gotime.Time
  157. updateScreen chan bool
  158. }
  159. func NewMainScreen() *MainScreen {
  160. m := &MainScreen{}
  161. m.PosY = TitleBar_BarHeight + 1
  162. m.Width = Width
  163. m.Height = Height - FootBar_BarHeight - TitleBar_BarHeight - 1
  164. m.MyPageStack = NewPageStack()
  165. m.MsgBoxFont = Fonts["veramono20"]
  166. m.IconFont = Fonts["varela15"]
  167. m.Closed = false
  168. m.updateScreen = make(chan bool,1)
  169. return m
  170. }
  171. func (self *MainScreen) Init() {
  172. self.CanvasHWND = surface.Surface(self.Width, self.Height)
  173. self.MsgBox = NewMessageBox()
  174. self.MsgBox.Parent = self.CanvasHWND
  175. self.MsgBox.Init(" ", self.MsgBoxFont, &color.Color{83, 83, 83, 255},self.Width,self.Height)
  176. self.SkinManager = NewSkinManager()
  177. self.SkinManager.Init()
  178. self.CounterScreen = NewCounterScreen()
  179. self.CounterScreen.HWND = self.HWND
  180. self.CounterScreen.Init()
  181. //self.GenList() // load predefined plugin list,ready to be injected ,or ,as a .so for dynamic loading
  182. go func() {
  183. self.RefreshLoop()
  184. }()
  185. }
  186. func (self *MainScreen) FartherPages() { // right after ReadTheDirIntoPages
  187. self.PageMax = len(self.Pages)
  188. for i := 0; i < self.PageMax; i++ {
  189. self.Pages[i].SetIndex(i)
  190. self.Pages[i].SetCanvasHWND(self.CanvasHWND)
  191. self.Pages[i].UpdateIconNumbers() // IconNumbers always == len(Pages[i].Icons)
  192. self.Pages[i].SetScreen(self)
  193. self.Pages[i].Adjust()
  194. if self.Pages[i].GetIconNumbers() > 1 {
  195. self.Pages[i].SetPsIndex(1)
  196. self.Pages[i].SetIconIndex(1)
  197. }
  198. }
  199. self.CurrentPage = self.Pages[self.PageIndex]
  200. self.CurrentPage.SetOnShow(true)
  201. }
  202. func (self *MainScreen) CurPage() PageInterface {
  203. return self.CurrentPage
  204. }
  205. func (self *MainScreen) PushCurPage() {
  206. self.MyPageStack.Push(self.CurrentPage)
  207. }
  208. func (self *MainScreen) SetCurPage(pg PageInterface) {
  209. self.CurrentPage = pg
  210. pg.OnLoadCb()
  211. }
  212. func (self *MainScreen) PushPage(pg PageInterface) {
  213. self.PushCurPage()
  214. self.SetCurPage(pg)
  215. }
  216. func (self *MainScreen) AppendPage(pg PageInterface) {
  217. self.Pages = append(self.Pages, pg)
  218. }
  219. func (self *MainScreen) ClearCanvas() {
  220. surface.Fill(self.CanvasHWND, &color.Color{255, 255, 255, 255})
  221. }
  222. func (self *MainScreen) SwapAndShow() {
  223. if self.HWND != nil {
  224. rect_ := rect.Rect(self.PosX, self.PosY, self.Width, self.Height)
  225. surface.Blit(self.HWND, self.CanvasHWND, &rect_, nil)
  226. }
  227. display.Flip()
  228. }
  229. func (self *MainScreen) ExtraName(name string) string {
  230. parts := strings.Split(name, "_")
  231. if len(parts) > 1 {
  232. return parts[1]
  233. } else if len(parts) == 1 {
  234. return parts[0]
  235. } else {
  236. return name
  237. }
  238. }
  239. //ExecPackage is all-in-one folder ,Name.sh,Name.png,etc
  240. func (self *MainScreen) IsExecPackage(dirname string) bool {
  241. files, err := ioutil.ReadDir(dirname)
  242. if err != nil {
  243. log.Println(err)
  244. return false
  245. }
  246. bname := filepath.Base(dirname)
  247. bname = self.ExtraName(bname)
  248. for _, v := range files {
  249. if v.Name() == bname+".sh" {
  250. return true
  251. }
  252. }
  253. return false
  254. }
  255. func (self *MainScreen) IsPluginPackage(dirname string) bool {
  256. ret := false
  257. files, err := ioutil.ReadDir(dirname)
  258. if err != nil {
  259. log.Println(err)
  260. return false
  261. }
  262. for _, f := range files {
  263. if f.IsDir() {
  264. //pass
  265. } else {
  266. if strings.HasSuffix(f.Name(), Plugin_flag) == true {
  267. ret = true
  268. break
  269. }
  270. }
  271. }
  272. return ret
  273. }
  274. func (self *MainScreen) IsEmulatorPackage(dirname string) bool {
  275. ret := false
  276. files, err := ioutil.ReadDir(dirname)
  277. if err != nil {
  278. log.Println(err)
  279. return false
  280. }
  281. for _, f := range files {
  282. if f.IsDir() {
  283. //pass
  284. } else {
  285. if strings.HasSuffix(f.Name(), Emulator_flag) == true {
  286. ret = true
  287. break
  288. }
  289. }
  290. }
  291. return ret
  292. }
  293. func (self *MainScreen) IsWifiConnectedNow() bool {
  294. cli := fmt.Sprintf("ip -4 addr show %s | grep -oP '(?<=inet\\s)\\d+(\\.\\d+){3}'", sysgo.WifiDev)
  295. out := System(cli)
  296. if len(out) < 6 {
  297. return false
  298. }
  299. return true
  300. }
  301. func (self *MainScreen) GetWirelessIP() string {
  302. cli := fmt.Sprintf("ip -4 addr show %s | grep -oP '(?<=inet\\s)\\d+(\\.\\d+){3}'", sysgo.WifiDev)
  303. out := SystemTrim(cli)
  304. return out
  305. }
  306. func (self *MainScreen) RunEXE(cmdpath string) {
  307. self.DrawRun()
  308. self.SwapAndShow()
  309. time.BlockDelay(1000)
  310. cmdpath = strings.Trim(cmdpath, " ")
  311. cmdpath = CmdClean(cmdpath)
  312. event.Post(RUNEVT, cmdpath)
  313. }
  314. func (self *MainScreen) HookExitCb( page PageInterface) {
  315. self.Child = append(self.Child,page)
  316. }
  317. func (self *MainScreen) OnExitCb() {
  318. PageLen := len(self.Child)
  319. for i := 0; i < PageLen; i++ {
  320. self.Child[i].OnExitCb()
  321. }
  322. }
  323. func (self *MainScreen) KeyDown(ev *event.Event) {
  324. if ev.Data["Key"] == "T" {
  325. self.DrawRun()
  326. self.SwapAndShow()
  327. return
  328. }
  329. if ev.Data["Key"] == "Space" {
  330. self.Draw()
  331. self.SwapAndShow()
  332. }
  333. self.CurrentPage.KeyDown(ev)
  334. self.LastKey = ev.Data["Key"]
  335. }
  336. func (self *MainScreen) ShowMsg(content string, blocktime int) {
  337. self.MsgBox.SetText(content)
  338. self.MsgBox.Draw()
  339. self.SwapAndShow()
  340. if blocktime > 0 {
  341. time.BlockDelay(blocktime)
  342. self.CurrentPage.Draw()
  343. self.SwapAndShow()
  344. }
  345. }
  346. func (self *MainScreen) DrawRun() {
  347. self.MsgBox.SetText("Launching....")
  348. self.MsgBox.Draw()
  349. }
  350. func (self *MainScreen) Draw() {
  351. if self.CurrentPage != nil {
  352. self.CurrentPage.Draw()
  353. }
  354. if self.TitleBar != nil {
  355. //every plugin_init should not do any Draw actions since CurrentPage might be nil at that time
  356. self.TitleBar.Draw(self.CurrentPage.GetName())
  357. }
  358. if self.FootBar != nil {
  359. self.FootBar.SetLabelTexts(self.CurrentPage.GetFootMsg())
  360. self.FootBar.Draw()
  361. }
  362. }
  363. func (self *MainScreen) Refresh() {
  364. self.updateScreen <- true
  365. }
  366. func (self *MainScreen) RefreshLoop() {
  367. L:
  368. for {
  369. select {
  370. case v:= <- self.updateScreen:
  371. if v == true {
  372. self.Draw()
  373. self.SwapAndShow()
  374. }
  375. if v== false {
  376. break L
  377. }
  378. }
  379. }
  380. }