title_bar.go 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512
  1. package UI
  2. import (
  3. "fmt"
  4. "os"
  5. "log"
  6. "strconv"
  7. "bufio"
  8. "strings"
  9. "os/exec"
  10. "io/ioutil"
  11. gotime "time"
  12. "github.com/veandco/go-sdl2/sdl"
  13. "github.com/veandco/go-sdl2/ttf"
  14. "github.com/cuu/gogame/surface"
  15. "github.com/cuu/gogame/rect"
  16. "github.com/cuu/gogame/font"
  17. "github.com/cuu/gogame/draw"
  18. "github.com/itchyny/volume-go"
  19. "github.com/vjeantet/jodaTime"
  20. "github.com/clockworkpi/LauncherGoDev/sysgo/DBUS"
  21. "github.com/clockworkpi/LauncherGoDev/sysgo"
  22. )
  23. var TitleBar_BarHeight = 24
  24. type TitleBarIconItem struct {
  25. MultiIconItem
  26. Parent *TitleBar
  27. }
  28. func NewTitleBarIconItem() *TitleBarIconItem {
  29. m := &TitleBarIconItem{}
  30. m.IconIndex = 0
  31. m.IconWidth = 18
  32. m.IconHeight = 18
  33. m.Align = ALIGN["VCenter"]
  34. return m
  35. }
  36. func (self *TitleBarIconItem) Adjust(x,y,w,h,at int) {
  37. self.PosX = x
  38. self.PosY = y
  39. self.Width = w
  40. self.Height = h
  41. self.AnimationTime = at
  42. if self.Label != nil {
  43. self.Label.SetCanvasHWND(self.Parent.CanvasHWND)
  44. }
  45. self.CreateImgSurf()
  46. // self.AdjustLinkPage()
  47. }
  48. func (self *TitleBarIconItem) Draw() {
  49. parent_x,parent_y := self.Parent.PosX,self.Parent.PosY
  50. if self.Label != nil {
  51. // lab_x,lab_y := self.Label.Coord()
  52. lab_w,lab_h:= self.Label.Size()
  53. if self.Align == ALIGN["VCenter"] {
  54. self.Label.NewCoord( self.PosX - lab_w/2 + parent_x, self.PosY + self.Height/2+6 + parent_y)
  55. }else if self.Align == ALIGN["HLeft"] {
  56. self.Label.NewCoord( self.PosX + self.Width/2+3 + parent_x, self.PosY - lab_h/2 + parent_y )
  57. }
  58. self.Label.Draw()
  59. }
  60. if self.ImgSurf != nil {
  61. portion := rect.Rect(0,self.IconIndex*self.IconHeight,self.IconWidth,self.IconHeight)
  62. surface.Blit(self.Parent.CanvasHWND,
  63. self.ImgSurf,draw.MidRect(self.PosX + parent_x, self.PosY + parent_y,
  64. self.Width,self.Height, Width, Height),&portion)
  65. }
  66. }
  67. type TitleBar struct {
  68. Widget
  69. BarHeight int
  70. LOffset int
  71. ROffset int
  72. Icons map[string]IconItemInterface
  73. IconWidth int
  74. IconHeight int
  75. BorderWidth int
  76. CanvasHWND *sdl.Surface
  77. HWND *sdl.Surface
  78. Title string
  79. InLowBackLight int
  80. InAirPlaneMode bool
  81. SkinManager *SkinManager //set by MainScreen
  82. DBusManager DBUS.DBusInterface
  83. icon_base_path string /// SkinMap("gameshell/titlebar_icons/")
  84. MyTimeLocation *gotime.Location
  85. TitleFont *ttf.Font
  86. TimeFont *ttf.Font
  87. }
  88. func NewTitleBar() *TitleBar {
  89. t := &TitleBar{}
  90. t.BorderWidth = 1
  91. t.BarHeight = TitleBar_BarHeight
  92. t.Height = t.BarHeight + t.BorderWidth
  93. t.Width = Width
  94. t.IconWidth = 18
  95. t.IconHeight = 18
  96. t.LOffset = 3
  97. t.ROffset = 3
  98. t.Icons = make(map[string]IconItemInterface)
  99. t.icon_base_path = SkinMap("sysgo/gameshell/titlebar_icons/")
  100. t.TitleFont = Fonts["varela16"]
  101. t.TimeFont = Fonts["varela12"]
  102. t.InLowBackLight = -1
  103. return t
  104. }
  105. func (self *TitleBar) RoundRobinCheck() {
  106. for {
  107. if self.InLowBackLight < 0 {
  108. self.CheckBatteryStat()
  109. self.CheckBluetooth()
  110. self.UpdateWifiStrength()
  111. SwapAndShow()
  112. }else if self.InLowBackLight >= 0 {
  113. self.InLowBackLight +=1
  114. if self.InLowBackLight > 10 {
  115. self.CheckBatteryStat()
  116. self.CheckBluetooth()
  117. self.UpdateWifiStrength()
  118. self.InLowBackLight = 0 // reset
  119. }
  120. }
  121. gotime.Sleep(3000 * gotime.Millisecond)
  122. }
  123. }
  124. func (self *TitleBar) UpdateWifiStrength() {
  125. self.Draw(self.Title)
  126. }
  127. func (t *TitleBar) GetWifiStrength(stren int) int {
  128. segs := [][]int{ []int{-2,-1}, []int{0,25}, []int{25,50}, []int{50,75},[]int{75,100}}
  129. stren_number := stren
  130. ge := 0
  131. if stren_number == 0 {
  132. return ge
  133. }
  134. for i,v := range segs {
  135. if stren_number >= v[0] && stren_number <= v[1] {
  136. ge = i
  137. break
  138. }
  139. }
  140. return ge
  141. }
  142. func (self *TitleBar) SyncSoundVolume() {
  143. vol, err := volume.GetVolume()
  144. if err != nil {
  145. log.Fatalf("TitleBar SyncSoundVolume get volume failed: %+v", err)
  146. vol = 0
  147. }
  148. fmt.Printf("TitleBar SyncSoundVolume current volume: %d\n", vol)
  149. snd_segs := [][]int{ []int{0,10}, []int{10,30}, []int{30,70},[]int{70,100} }
  150. ge := 0
  151. for i,v := range snd_segs {
  152. if vol >= v[0] && vol <= v[1] {
  153. ge = i
  154. break
  155. }
  156. }
  157. self.Icons["soundvolume"].SetIconIndex(ge)
  158. self.Icons["sound"] = self.Icons["soundvolume"]
  159. //
  160. }
  161. // for outside widget to update sound icon
  162. func (self *TitleBar) SetSoundVolume(vol int) {
  163. snd_segs := [][]int{ []int{0,10}, []int{10,30}, []int{30,70},[]int{70,100} }
  164. ge := 0
  165. for i,v := range snd_segs {
  166. if vol >= v[0] && vol <= v[1] {
  167. ge = i
  168. break
  169. }
  170. }
  171. self.Icons["soundvolume"].SetIconIndex(ge)
  172. self.Icons["sound"] = self.Icons["soundvolume"]
  173. }
  174. func (self *TitleBar) CheckBatteryStat() {
  175. bat_segs:= [][]int{[]int{0,6},[]int{7,15},[]int{16,20},[]int{21,30},[]int{31,50},[]int{51,60},[]int{61,80},[]int{81,90},[]int{91,100}}
  176. file, err := os.Open( sysgo.Battery )
  177. if err != nil {
  178. fmt.Println("Could not open file ", sysgo.Battery)
  179. self.Icons["battery"] = self.Icons["battery_unknown"]
  180. return
  181. }
  182. defer file.Close()
  183. bat_uevent := make(map[string]string)
  184. scanner := bufio.NewScanner(file)
  185. scanner.Split(bufio.ScanLines)
  186. for scanner.Scan() {
  187. line := scanner.Text()
  188. line = strings.Trim(line," ")
  189. pis := strings.Split(line,"=")
  190. if len(pis) > 1 {
  191. bat_uevent[ pis[0] ] = pis[1]
  192. }
  193. }
  194. cur_cap := 0
  195. if val, ok := bat_uevent["POWER_SUPPLY_CAPACITY"]; ok {
  196. cur_cap,_ = strconv.Atoi(val)
  197. }else {
  198. cur_cap = 0
  199. }
  200. cap_ge := 0
  201. for i,v := range bat_segs {
  202. if cur_cap >= v[0] && cur_cap <= v[1] {
  203. cap_ge = i
  204. break
  205. }
  206. }
  207. if val, ok := bat_uevent["POWER_SUPPLY_STATUS"]; ok {
  208. if val == "Charging" {
  209. self.Icons["battery_charging"].SetIconIndex(cap_ge)
  210. self.Icons["battery"] = self.Icons["battery_charging"]
  211. }else {
  212. self.Icons["battery_charging"].SetIconIndex(cap_ge)
  213. self.Icons["battery"] = self.Icons["battery_discharging"]
  214. }
  215. }
  216. }
  217. func (self *TitleBar) SetBatteryStat( bat int) {
  218. }
  219. func (self *TitleBar) CheckBluetooth() {
  220. out := System("hcitool dev | grep hci0 |cut -f3")
  221. if len(out) < 17 {
  222. fmt.Println("Titlebar CheckBluetooth: no bluetooth",out)
  223. self.Icons["bluetooth"].SetIconIndex(2)
  224. return
  225. }else {
  226. out = System("sudo rfkill list | grep hci0 -A 2 | grep yes")
  227. if len(out) > 10 {
  228. self.Icons["bluetooth"].SetIconIndex(1)
  229. return
  230. }
  231. }
  232. self.Icons["bluetooth"].SetIconIndex(0)
  233. }
  234. func (self *TitleBar) Init(main_screen *MainScreen) {
  235. start_x := 0
  236. self.CanvasHWND = surface.Surface(self.Width,self.Height)
  237. self.HWND = main_screen.HWND
  238. self.SkinManager = main_screen.SkinManager
  239. self.DBusManager = main_screen.DBusManager
  240. icon_wifi_status := NewTitleBarIconItem()
  241. icon_wifi_status.MyType = ICON_TYPES["STAT"]
  242. icon_wifi_status.ImageName = self.icon_base_path+"wifi.png"
  243. icon_wifi_status.Parent = self
  244. icon_wifi_status.Adjust(start_x+self.IconWidth+5,self.IconHeight/2+(self.BarHeight-self.IconHeight)/2,self.IconWidth,self.IconHeight,0)
  245. self.Icons["wifistatus"] = icon_wifi_status
  246. battery_charging := NewTitleBarIconItem()
  247. battery_charging.MyType = ICON_TYPES["STAT"]
  248. battery_charging.Parent = self
  249. battery_charging.ImageName = self.icon_base_path+"withcharging.png"
  250. battery_charging.Adjust(start_x+self.IconWidth+self.IconWidth+8,self.IconHeight/2+(self.BarHeight-self.IconHeight)/2,self.IconWidth,self.IconHeight,0)
  251. self.Icons["battery_charging"] = battery_charging
  252. battery_discharging := NewTitleBarIconItem()
  253. battery_discharging.MyType = ICON_TYPES["STAT"]
  254. battery_discharging.Parent = self
  255. battery_discharging.ImageName = self.icon_base_path+"without_charging.png"
  256. battery_discharging.Adjust(start_x+self.IconWidth+self.IconWidth+8,self.IconHeight/2+(self.BarHeight-self.IconHeight)/2,self.IconWidth,self.IconHeight,0)
  257. self.Icons["battery_discharging"] = battery_discharging
  258. battery_unknown := NewTitleBarIconItem()
  259. battery_unknown.MyType = ICON_TYPES["STAT"]
  260. battery_unknown.Parent = self
  261. battery_unknown.ImageName = self.icon_base_path+"battery_unknown.png"
  262. battery_unknown.Adjust(start_x+self.IconWidth+self.IconWidth+8,self.IconHeight/2+(self.BarHeight-self.IconHeight)/2,self.IconWidth,self.IconHeight,0)
  263. self.Icons["battery_unknown"] = battery_unknown
  264. self.CheckBatteryStat()
  265. sound_volume := NewTitleBarIconItem()
  266. sound_volume.MyType = ICON_TYPES["STAT"]
  267. sound_volume.Parent = self
  268. sound_volume.ImageName = self.icon_base_path+"soundvolume.png"
  269. sound_volume.Adjust(start_x+self.IconWidth+self.IconWidth+8,self.IconHeight/2+(self.BarHeight-self.IconHeight)/2,self.IconWidth,self.IconHeight,0)
  270. self.Icons["soundvolume"] = sound_volume
  271. self.SyncSoundVolume()
  272. bluetooth := NewTitleBarIconItem()
  273. bluetooth.MyType = ICON_TYPES["STAT"]
  274. bluetooth.Parent = self
  275. bluetooth.ImageName = self.icon_base_path+"bluetooth.png"
  276. bluetooth.Adjust(start_x+self.IconWidth+self.IconWidth+8,self.IconHeight/2+(self.BarHeight-self.IconHeight)/2,self.IconWidth,self.IconHeight,0)
  277. self.Icons["bluetooth"] = bluetooth
  278. self.CheckBluetooth()
  279. round_corners := NewTitleBarIconItem()
  280. round_corners.IconWidth = 10
  281. round_corners.IconHeight = 10
  282. round_corners.MyType = ICON_TYPES["STAT"]
  283. round_corners.Parent = self
  284. round_corners.ImgSurf = MyIconPool.GetImgSurf("roundcorners")
  285. round_corners.Adjust(0,0,10,10,0)
  286. self.Icons["round_corners"] = round_corners
  287. if self.DBusManager.IsWifiConnectedNow() {
  288. print("wifi is connected")
  289. print( self.DBusManager.WifiStrength())
  290. }else {
  291. cmd := "sudo rfkill list | grep yes | cut -d \" \" -f3" //make sure sudo rfkill needs no password
  292. out, err := exec.Command("bash", "-c", cmd).Output()
  293. if err != nil {
  294. fmt.Printf("Failed to execute command: %s\n", cmd)
  295. }else {
  296. outs := strings.Split(string(out),"\n")
  297. if len(outs) > 0 && outs[0] == "yes" {
  298. self.InAirPlaneMode = true
  299. }else{
  300. self.InAirPlaneMode = false
  301. }
  302. }
  303. }
  304. self.UpdateTimeLocation()
  305. }
  306. func (self *TitleBar) ClearCanvas() {
  307. surface.Fill(self.CanvasHWND, self.SkinManager.GiveColor("TitleBg"))
  308. self.Icons["round_corners"].NewCoord(5,5)
  309. self.Icons["round_corners"].SetIconIndex(0)
  310. self.Icons["round_corners"].Draw()
  311. self.Icons["round_corners"].NewCoord(self.Width-5, 5)
  312. self.Icons["round_corners"].SetIconIndex(1)
  313. self.Icons["round_corners"].Draw()
  314. }
  315. func (self *TitleBar) UpdateTimeLocation() {
  316. d,err := ioutil.ReadFile("/etc/localtime")
  317. if err != nil {
  318. return
  319. }
  320. self.MyTimeLocation,err = gotime.LoadLocationFromTZData("local", d)
  321. if err != nil {
  322. fmt.Println(err)
  323. self.MyTimeLocation = nil
  324. }
  325. }
  326. func (self *TitleBar) GetLocalTime() gotime.Time {
  327. if self.MyTimeLocation == nil {
  328. return gotime.Now()
  329. }else {
  330. return gotime.Now().In(self.MyTimeLocation)
  331. }
  332. }
  333. func (self *TitleBar) Draw(title string) {
  334. self.ClearCanvas()
  335. self.Title = title
  336. cur_time := jodaTime.Format("HH:mm", self.GetLocalTime())
  337. time_text_w, time_text_h := font.Size(self.TimeFont, cur_time)
  338. title_text_w, title_text_h := font.Size(self.TitleFont, self.Title)
  339. title_text_surf := font.Render(self.TitleFont, self.Title, true, self.SkinManager.GiveColor("Text"),nil)
  340. surface.Blit(self.CanvasHWND,title_text_surf, draw.MidRect(title_text_w/2+self.LOffset,title_text_h/2+(self.BarHeight-title_text_h)/2,title_text_w,title_text_h,Width,Height),nil)
  341. time_text_surf := font.Render(self.TimeFont, cur_time,true,self.SkinManager.GiveColor("Text"),nil)
  342. surface.Blit(self.CanvasHWND, time_text_surf, draw.MidRect(Width-time_text_w/2-self.ROffset, time_text_h/2+(self.BarHeight-time_text_h)/2, time_text_w,time_text_h,Width,Height),nil)
  343. start_x := Width - time_text_w - self.ROffset - self.IconWidth*3 // close to the time_text
  344. self.Icons["bluetooth"].NewCoord(start_x - self.IconWidth,self.IconHeight/2+(self.BarHeight-self.IconHeight)/2)
  345. self.Icons["sound"].NewCoord( start_x, self.IconHeight/2+ (self.BarHeight-self.IconHeight)/2)
  346. self.Icons["battery"].NewCoord(start_x+self.IconWidth+self.IconWidth+8, self.IconHeight/2+(self.BarHeight-self.IconHeight)/2)
  347. if self.DBusManager.IsWifiConnectedNow() == true {
  348. ge := self.GetWifiStrength( self.DBusManager.WifiStrength() )
  349. //fmt.Println("wifi ge: ",ge)
  350. if ge > 0 {
  351. self.Icons["wifistatus"].SetIconIndex(ge)
  352. self.Icons["wifistatus"].NewCoord(start_x+self.IconWidth+5, self.IconHeight/2+(self.BarHeight-self.IconHeight)/2 )
  353. self.Icons["wifistatus"].Draw()
  354. }else {
  355. self.Icons["wifistatus"].SetIconIndex(0)
  356. self.Icons["wifistatus"].Draw()
  357. }
  358. }else {
  359. self.Icons["wifistatus"].SetIconIndex(0)
  360. self.Icons["wifistatus"].NewCoord(start_x+self.IconWidth+5, self.IconHeight/2+(self.BarHeight-self.IconHeight)/2)
  361. self.Icons["wifistatus"].Draw()
  362. }
  363. self.Icons["sound"].Draw()
  364. self.Icons["battery"].Draw()
  365. self.Icons["bluetooth"].Draw()
  366. draw.Line(self.CanvasHWND,self.SkinManager.GiveColor("Line"), 0,self.BarHeight,self.Width,self.BarHeight, self.BorderWidth)
  367. if self.HWND != nil {
  368. rect_ := rect.Rect(self.PosX,self.PosY, self.Width,self.Height)
  369. surface.Blit(self.HWND, self.CanvasHWND, &rect_, nil)
  370. }
  371. }