rom_list_page.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559
  1. package Emulator
  2. import (
  3. "fmt"
  4. "os"
  5. "strings"
  6. //"regexp"
  7. "errors"
  8. "github.com/clockworkpi/LauncherGoDev/sysgo/UI"
  9. "github.com/cuu/gogame/color"
  10. "github.com/cuu/gogame/event"
  11. //"github.com/cuu/gogame/time"
  12. "github.com/veandco/go-sdl2/ttf"
  13. "os/exec"
  14. "path/filepath"
  15. gotime "time"
  16. )
  17. type RomListPage struct {
  18. UI.Page
  19. Icons map[string]UI.IconItemInterface
  20. ListFont *ttf.Font
  21. MyStack *UI.FolderStack
  22. EmulatorConfig *ActionConfig
  23. RomSoConfirmDownloadPage *RomSoConfirmPage
  24. MyList []UI.ListItemInterface
  25. BGwidth int
  26. BGheight int //70
  27. Scroller *UI.ListScroller
  28. Scrolled int
  29. Leader *MyEmulator
  30. }
  31. func NewRomListPage() *RomListPage {
  32. p := &RomListPage{}
  33. p.PageIconMargin = 20
  34. p.SelectedIconTopOffset = 20
  35. p.EasingDur = 10
  36. p.Align = UI.ALIGN["SLeft"]
  37. p.FootMsg = [5]string{"Nav", "Scan", "Del", "AddFav", "Run"}
  38. p.Icons = make(map[string]UI.IconItemInterface)
  39. p.ListFont = UI.Fonts["notosanscjk15"]
  40. p.MyStack = UI.NewFolderStack()
  41. p.BGwidth = 56
  42. p.BGheight = 70
  43. p.ScrollStep = 1
  44. return p
  45. }
  46. func (self *RomListPage) GetMyList() []UI.ListItemInterface {
  47. return self.MyList
  48. }
  49. func (self *RomListPage) GetMapIcons() map[string]UI.IconItemInterface {
  50. return self.Icons
  51. }
  52. func (self *RomListPage) GetEmulatorConfig() *ActionConfig {
  53. return self.EmulatorConfig
  54. }
  55. func (self *RomListPage) GeneratePathList(path string) ([]map[string]string, error) {
  56. if UI.IsDirectory(path) == false {
  57. return nil, errors.New("Path is not a folder")
  58. }
  59. var ret []map[string]string
  60. file_paths, err := filepath.Glob(path + "/*") //sorted
  61. if err != nil {
  62. fmt.Println(err)
  63. return ret, err
  64. }
  65. for _, v := range file_paths {
  66. dirmap := make(map[string]string)
  67. if UI.IsDirectory(v) && self.EmulatorConfig.FILETYPE == "dir" { // like DOSBOX
  68. gameshell_bat := self.EmulatorConfig.EXT[0]
  69. if UI.GetGid(v) == FavGID { // skip fav roms
  70. continue
  71. }
  72. if UI.FileExists(filepath.Join(v, gameshell_bat)) == true {
  73. dirmap["gamedir"] = v
  74. ret = append(ret, dirmap)
  75. }
  76. }
  77. if UI.IsAFile(v) && self.EmulatorConfig.FILETYPE == "file" {
  78. if UI.GetGid(v) == FavGID {
  79. continue
  80. }
  81. bname := filepath.Base(v)
  82. if len(bname) > 1 {
  83. is_excluded := false
  84. for _, exclude_ext := range self.EmulatorConfig.EXCLUDE {
  85. exclude_ext2 := strings.Trim(exclude_ext, "\r\n ")
  86. if len(exclude_ext2) > 1 && strings.HasSuffix(bname, exclude_ext2) {
  87. is_excluded = true
  88. break
  89. }
  90. }
  91. if is_excluded == false {
  92. pieces := strings.Split(bname, ".")
  93. if len(pieces) > 1 {
  94. pieces_ext := strings.ToLower(pieces[len(pieces)-1])
  95. for _, u := range self.EmulatorConfig.EXT {
  96. if pieces_ext == u {
  97. dirmap["file"] = v
  98. ret = append(ret, dirmap)
  99. break
  100. }
  101. }
  102. }
  103. }
  104. }
  105. }
  106. }
  107. return ret, nil
  108. }
  109. func (self *RomListPage) SyncList(path string) {
  110. alist, err := self.GeneratePathList(path)
  111. if err != nil {
  112. fmt.Println(err)
  113. return
  114. }
  115. self.MyList = nil
  116. start_x := 0
  117. start_y := 0
  118. hasparent := 0
  119. if self.MyStack.Length() > 0 {
  120. hasparent = 1
  121. li := NewEmulatorListItem()
  122. li.Parent = self
  123. li.PosX = start_x
  124. li.PosY = start_y
  125. li.Width = UI.Width
  126. li.Fonts["normal"] = self.ListFont
  127. li.MyType = UI.ICON_TYPES["DIR"]
  128. li.Init("[..]")
  129. self.MyList = append(self.MyList, li)
  130. }
  131. for i, v := range alist {
  132. li := NewEmulatorListItem()
  133. li.Parent = self
  134. li.PosX = start_x
  135. li.PosY = start_y + (i+hasparent)*li.Height
  136. li.Width = UI.Width
  137. li.Fonts["normal"] = self.ListFont
  138. li.MyType = UI.ICON_TYPES["FILE"]
  139. init_val := "NoName"
  140. if val, ok := v["directory"]; ok {
  141. li.MyType = UI.ICON_TYPES["DIR"]
  142. init_val = val
  143. }
  144. if val, ok := v["file"]; ok {
  145. init_val = val
  146. }
  147. if val, ok := v["gamedir"]; ok {
  148. init_val = val
  149. }
  150. li.Init(init_val)
  151. self.MyList = append(self.MyList, li)
  152. }
  153. }
  154. func (self *RomListPage) Init() {
  155. self.PosX = self.Index * self.Screen.Width
  156. self.Width = self.Screen.Width
  157. self.Height = self.Screen.Height
  158. self.CanvasHWND = self.Screen.CanvasHWND
  159. ps := UI.NewInfoPageSelector()
  160. ps.Width = UI.Width - 12
  161. ps.PosX = 2
  162. ps.Parent = self
  163. self.Ps = ps
  164. self.PsIndex = 0
  165. self.MyStack.SetRootPath(self.EmulatorConfig.ROM)
  166. self.SyncList(self.EmulatorConfig.ROM)
  167. err := os.MkdirAll(self.EmulatorConfig.ROM+"/.Trash", 0700)
  168. if err != nil {
  169. panic(err)
  170. }
  171. err = os.MkdirAll(self.EmulatorConfig.ROM+"/.Fav", 0700)
  172. if err != nil {
  173. panic(err)
  174. }
  175. icon_for_list := UI.NewMultiIconItem()
  176. icon_for_list.ImgSurf = UI.MyIconPool.GetImgSurf("sys")
  177. icon_for_list.MyType = UI.ICON_TYPES["STAT"]
  178. icon_for_list.Parent = self
  179. icon_for_list.Adjust(0, 0, 18, 18, 0)
  180. self.Icons["sys"] = icon_for_list
  181. bgpng := UI.NewIconItem()
  182. bgpng.ImgSurf = UI.MyIconPool.GetImgSurf("empty")
  183. bgpng.MyType = UI.ICON_TYPES["STAT"]
  184. bgpng.Parent = self
  185. bgpng.AddLabel("Please upload data over Wi-Fi", UI.Fonts["varela22"])
  186. bgpng.SetLabelColor(&color.Color{204, 204, 204, 255})
  187. bgpng.Adjust(0, 0, self.BGwidth, self.BGheight, 0)
  188. self.Icons["bg"] = bgpng
  189. self.Scroller = UI.NewListScroller()
  190. self.Scroller.Parent = self
  191. self.Scroller.PosX = self.Width - 10
  192. self.Scroller.PosY = 2
  193. self.Scroller.Init()
  194. rom_so_confirm_page := NewRomSoConfirmPage()
  195. rom_so_confirm_page.Screen = self.Screen
  196. rom_so_confirm_page.Name = "Download Confirm"
  197. rom_so_confirm_page.Parent = self
  198. rom_so_confirm_page.Init()
  199. self.RomSoConfirmDownloadPage = rom_so_confirm_page
  200. }
  201. func (self *RomListPage) ScrollUp() {
  202. if len(self.MyList) == 0 {
  203. return
  204. }
  205. tmp := self.PsIndex
  206. self.PsIndex -= self.ScrollStep
  207. dy := 0
  208. if self.PsIndex < 0 {
  209. self.PsIndex = len(self.MyList) - 1
  210. }
  211. dy = tmp - self.PsIndex
  212. cur_li := self.MyList[self.PsIndex]
  213. x, y := cur_li.Coord()
  214. _, h := cur_li.Size()
  215. {
  216. for i, _ := range self.MyList {
  217. x, y = self.MyList[i].Coord()
  218. _, h = self.MyList[i].Size()
  219. self.MyList[i].NewCoord(x, y+h*dy)
  220. }
  221. self.Scrolled += dy
  222. }
  223. }
  224. func (self *RomListPage) ScrollDown() {
  225. if len(self.MyList) == 0 {
  226. return
  227. }
  228. tmp := self.PsIndex
  229. self.PsIndex += self.ScrollStep
  230. if self.PsIndex >= len(self.MyList) {
  231. self.PsIndex = 0
  232. }
  233. dy := self.PsIndex - tmp
  234. cur_li := self.MyList[self.PsIndex]
  235. x, y := cur_li.Coord()
  236. _, h := cur_li.Size()
  237. {
  238. for i, _ := range self.MyList {
  239. x, y = self.MyList[i].Coord()
  240. _, h = self.MyList[i].Size()
  241. self.MyList[i].NewCoord(x, y-h*dy)
  242. }
  243. self.Scrolled -= dy
  244. }
  245. }
  246. func (self *RomListPage) SyncScroll() {
  247. if self.Scrolled == 0 {
  248. return
  249. }
  250. if self.PsIndex < len(self.MyList) {
  251. cur_li := self.MyList[self.PsIndex]
  252. x, y := cur_li.Coord()
  253. _, h := cur_li.Size()
  254. if self.Scrolled > 0 {
  255. if y < 0 {
  256. for i, _ := range self.MyList {
  257. x, y = self.MyList[i].Coord()
  258. _, h = self.MyList[i].Size()
  259. self.MyList[i].NewCoord(x, y+self.Scrolled*h)
  260. }
  261. }
  262. } else if self.Scrolled < 0 {
  263. if y+h > self.Height {
  264. for i, _ := range self.MyList {
  265. x, y = self.MyList[i].Coord()
  266. _, h = self.MyList[i].Size()
  267. self.MyList[i].NewCoord(x, y+self.Scrolled*h)
  268. }
  269. }
  270. }
  271. }
  272. }
  273. func (self *RomListPage) Click() {
  274. if len(self.MyList) == 0 {
  275. return
  276. }
  277. if self.PsIndex > len(self.MyList)-1 {
  278. return
  279. }
  280. cur_li := self.MyList[self.PsIndex]
  281. if cur_li.(*EmulatorListItem).MyType == UI.ICON_TYPES["DIR"] {
  282. if cur_li.(*EmulatorListItem).Path == "[..]" {
  283. self.MyStack.Pop()
  284. self.SyncList(self.MyStack.Last())
  285. self.PsIndex = 0
  286. } else {
  287. self.MyStack.Push(self.MyList[self.PsIndex].(*EmulatorListItem).Path)
  288. self.SyncList(self.MyStack.Last())
  289. self.PsIndex = 0
  290. }
  291. }
  292. if cur_li.(*EmulatorListItem).MyType == UI.ICON_TYPES["FILE"] {
  293. self.Screen.MsgBox.SetText("Launching")
  294. self.Screen.MsgBox.Draw()
  295. self.Screen.SwapAndShow()
  296. path := ""
  297. if self.EmulatorConfig.FILETYPE == "dir" {
  298. path = filepath.Join(cur_li.(*EmulatorListItem).Path, self.EmulatorConfig.EXT[0])
  299. } else {
  300. path = cur_li.(*EmulatorListItem).Path
  301. }
  302. fmt.Println("Run ", path)
  303. escaped_path := UI.CmdClean(path)
  304. if self.EmulatorConfig.FILETYPE == "dir" {
  305. escaped_path = UI.CmdClean(path)
  306. }
  307. custom_config := ""
  308. if self.EmulatorConfig.RETRO_CONFIG != "" && len(self.EmulatorConfig.RETRO_CONFIG) > 5 {
  309. custom_config = " -c " + self.EmulatorConfig.RETRO_CONFIG
  310. }
  311. partsofpath := []string{self.EmulatorConfig.LAUNCHER, self.EmulatorConfig.ROM_SO, custom_config, escaped_path}
  312. cmdpath := strings.Join(partsofpath, " ")
  313. if self.EmulatorConfig.ROM_SO == "" { //empty means No needs for rom so
  314. event.Post(UI.RUNEVT, cmdpath)
  315. } else {
  316. if UI.FileExists(strings.Split(self.EmulatorConfig.ROM_SO, " ")[0]) == true {
  317. event.Post(UI.RUNEVT, cmdpath)
  318. } else {
  319. self.Screen.PushCurPage()
  320. self.Screen.SetCurPage(self.RomSoConfirmDownloadPage)
  321. self.Screen.Refresh()
  322. }
  323. }
  324. return
  325. }
  326. self.Screen.Refresh()
  327. }
  328. func (self *RomListPage) ReScan() {
  329. //fmt.Println("RomListPage ReScan ",self.EmulatorConfig.ROM)
  330. if self.MyStack.Length() == 0 {
  331. self.SyncList(self.EmulatorConfig.ROM)
  332. } else {
  333. self.SyncList(self.MyStack.Last())
  334. }
  335. self.PsIndex = 0 //sync PsIndex
  336. self.Scrolled = 0
  337. self.SyncScroll()
  338. }
  339. func (self *RomListPage) OnReturnBackCb() {
  340. self.ReScan()
  341. self.Screen.Refresh()
  342. }
  343. func (self *RomListPage) SpeedScroll(thekey string) {
  344. if self.Screen.LastKey == thekey {
  345. self.ScrollStep += 1
  346. if self.ScrollStep >= self.Leader.SpeedMax {
  347. self.ScrollStep = self.Leader.SpeedMax
  348. }
  349. } else {
  350. self.ScrollStep = 1
  351. }
  352. cur_time := gotime.Now()
  353. if cur_time.Sub(self.Screen.LastKeyDown) > gotime.Duration(self.Leader.SpeedTimeInter)*gotime.Millisecond {
  354. self.ScrollStep = 1
  355. }
  356. }
  357. func (self *RomListPage) KeyDown(ev *event.Event) {
  358. if ev.Data["Key"] == UI.CurKeys["Menu"] {
  359. self.ReturnToUpLevelPage()
  360. self.Screen.Refresh()
  361. }
  362. if ev.Data["Key"] == UI.CurKeys["Right"] {
  363. self.Screen.PushCurPage()
  364. self.Screen.SetCurPage(self.Leader.FavPage)
  365. self.Screen.Refresh()
  366. }
  367. if ev.Data["Key"] == UI.CurKeys["Up"] {
  368. self.SpeedScroll(ev.Data["Key"])
  369. self.ScrollUp()
  370. self.Screen.Refresh()
  371. }
  372. if ev.Data["Key"] == UI.CurKeys["Down"] {
  373. self.SpeedScroll(ev.Data["Key"])
  374. self.ScrollDown()
  375. self.Screen.Refresh()
  376. }
  377. if ev.Data["Key"] == UI.CurKeys["Enter"] {
  378. self.Click()
  379. }
  380. if ev.Data["Key"] == UI.CurKeys["A"] {
  381. if len(self.MyList) == 0 {
  382. return
  383. }
  384. cur_li := self.MyList[self.PsIndex]
  385. if cur_li.(*EmulatorListItem).IsFile() {
  386. cmd := exec.Command("chgrp", FavGname, UI.CmdClean(cur_li.(*EmulatorListItem).Path))
  387. err := cmd.Run()
  388. if err != nil {
  389. fmt.Println(err)
  390. }
  391. self.Screen.ShowMsg("Add to favourite list",600)
  392. self.ReScan()
  393. self.Screen.Refresh()
  394. }
  395. }
  396. if ev.Data["Key"] == UI.CurKeys["X"] { //Scan current
  397. self.ReScan()
  398. self.Screen.Refresh()
  399. }
  400. if ev.Data["Key"] == UI.CurKeys["Y"] { // del
  401. if len(self.MyList) == 0 {
  402. return
  403. }
  404. cur_li := self.MyList[self.PsIndex]
  405. if cur_li.(*EmulatorListItem).IsFile() {
  406. self.Leader.DeleteConfirmPage.SetFileName(cur_li.(*EmulatorListItem).Path)
  407. self.Leader.DeleteConfirmPage.SetTrashDir(filepath.Join(self.EmulatorConfig.ROM, "/.Trash"))
  408. self.Screen.PushCurPage()
  409. self.Screen.SetCurPage(self.Leader.DeleteConfirmPage)
  410. self.Screen.Refresh()
  411. }
  412. }
  413. }
  414. func (self *RomListPage) Draw() {
  415. self.ClearCanvas()
  416. if len(self.MyList) == 0 {
  417. self.Icons["bg"].NewCoord(self.Width/2, self.Height/2)
  418. self.Icons["bg"].Draw()
  419. } else {
  420. _, h := self.Ps.Size()
  421. if len(self.MyList)*UI.HierListItemDefaultHeight > self.Height {
  422. self.Ps.NewSize(self.Width-10, h)
  423. self.Ps.Draw()
  424. for _, v := range self.MyList {
  425. _, y := v.Coord()
  426. if y > (self.Height + self.Height/2) {
  427. break
  428. }
  429. v.Draw()
  430. }
  431. self.Scroller.UpdateSize(len(self.MyList)*UI.HierListItemDefaultHeight,
  432. self.PsIndex*UI.HierListItemDefaultHeight)
  433. self.Scroller.Draw()
  434. } else {
  435. self.Ps.NewSize(self.Width, h)
  436. self.Ps.Draw()
  437. for _, v := range self.MyList {
  438. v.Draw()
  439. }
  440. }
  441. }
  442. }