libtk.py 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456
  1. #!/usr/bin/python3
  2. import os
  3. import time
  4. import sys
  5. sys.path.insert(0,"/opt/LibreLight/Xdesk/")
  6. import tkinter
  7. tk = tkinter
  8. import __main__ as MAIN
  9. from lib.cprint import cprint
  10. import lib.libwin as libwin
  11. import lib.baselib as baselib
  12. import json
  13. _config = []
  14. try:
  15. h = os.environ["HOME"]
  16. lines = [{}]
  17. try:
  18. f = open(h +"/LibreLight/config.json")
  19. lines = f.readlines()
  20. except FileNotFoundError as e: #Exception as e:
  21. f = open(h +"/LibreLight/config.json","w")
  22. f.write('{"POS_TOP":0}\n{"POS_LEFT":0}')
  23. f.close()
  24. cprint("Exception:",e)
  25. cprint("config read")
  26. for line in lines:
  27. line=line.strip()
  28. print(" config:",line)
  29. row = json.loads(line)
  30. _config.append(row)
  31. except Exception as e:
  32. cprint("Exception:",e)
  33. _POS_LEFT = 0
  34. _POS_TOP = 15
  35. try:
  36. for row in _config:
  37. #print(" config:",row)
  38. if "POS_LEFT" in row:
  39. _POS_LEFT = int(row["POS_LEFT"])
  40. if "POS_TOP" in row:
  41. _POS_TOP = int(row["POS_TOP"])
  42. except Exception as e:
  43. cprint("Exception:",e)
  44. def frame_of_show_list(frame,cb=None):
  45. c=0
  46. r=0
  47. base = baselib.Base()
  48. for i in ["name","stamp"]: #,"create"]:
  49. b = tk.Label(frame,bg="grey",text=i)
  50. b.grid(row=r, column=c, sticky=tk.W+tk.E)
  51. c+=1
  52. r+=1
  53. blist = baselib.list_shows()
  54. for i in range(10):
  55. blist.append(["",""])
  56. if cb is None:
  57. cb = DummyCallback #("load_show_list.cb")
  58. for i in blist:
  59. #print(i)
  60. c=0
  61. for j in i:
  62. bg="lightgrey"
  63. dbg="lightgrey"
  64. if i[1] > time.strftime("%Y-%m-%d %X", time.localtime(time.time()-3600*4)):
  65. dbg = "lightgreen"
  66. elif i[1] > time.strftime("%Y-%m-%d %X", time.localtime(time.time()-3600*24*7)):
  67. dbg = "green"
  68. if c > 0:
  69. b = tk.Button(frame,text=j,anchor="w",bg=dbg,relief="sunken")
  70. b.config(activebackground=dbg)
  71. b.grid(row=r, column=c, sticky=tk.W+tk.E)
  72. else:
  73. if base.show_name == i[0]:
  74. bg="green"
  75. _cb = cb(j)
  76. b = tk.Button(frame,text=j,anchor="w",height=1,bg=bg,command=_cb.cb)
  77. if base.show_name == i[0]:
  78. b.config(activebackground=bg)
  79. b.grid(row=r, column=c, sticky=tk.W+tk.E)
  80. c+=1
  81. r+=1
  82. class BLINKI():
  83. def __init__(self,e):
  84. self.e = e
  85. def blink(self):
  86. e = self.e
  87. e.config(bg='green')
  88. duration = 150
  89. for i in range(8):
  90. d = i * duration
  91. if i % 2 == 0:
  92. e.after(d, lambda: e.config(bg='white')) # after 1000ms
  93. e.after(d, lambda: e.config(activebackground='white')) # after 1000ms
  94. else:
  95. e.after(d, lambda: e.config(bg='orange')) # after 1000ms
  96. e.after(d, lambda: e.config(activebackground='orange')) # after 1000ms
  97. i+=1
  98. duration = 150
  99. e.after(d, lambda: e.config(bg='white')) # after 1000ms
  100. e.after(d, lambda: e.config(activebackground='white')) # after 1000ms
  101. class on_focus():
  102. def __init__(self,name,mode):
  103. self.name = name
  104. self.mode = mode
  105. def cb(self,event=None):
  106. #print("on_focus",event,self.name,self.mode)
  107. try:
  108. e = MAIN.master.commands.elem["."]
  109. except:pass
  110. if self.mode == "Out":
  111. cmd="xset -display :0.0 r rate 240 20"
  112. #print(cmd)
  113. os.system(cmd)
  114. try:
  115. e["bg"] = "#aaa"
  116. e["activebackground"] = "#aaa"
  117. except:pass
  118. if self.mode == "In":
  119. cmd = "xset -display :0.0 r off"
  120. #print(cmd)
  121. os.system(cmd)
  122. try:
  123. e["bg"] = "#fff"
  124. e["activebackground"] = "#fff"
  125. except:pass
  126. class DummyCallback():
  127. def __init__(self,name="name"):
  128. self.name = name
  129. def cb(self,event=None):
  130. cprint("DummyCallback.cb",[self.name,event])
  131. class Window():
  132. def __init__(self,args): #title="title",master=0,width=100,height=100,left=None,top=None,exit=0,cb=None,resize=1):
  133. global MAIN #lf_nr
  134. self.args = {"title":"title","master":0,"width":100,"height":100,"left":None,"top":None,"exit":0,"cb":None,"resize":1}
  135. self.args.update(args)
  136. cprint("Window.init()",self.args["title"],color="yellow")
  137. #cprint("Window.init()",id(self.args),color="yellow")
  138. #cprint(" ",self.args,color="yellow")
  139. ico_path="./icon/"
  140. self.cb = MAIN.cb
  141. if self.args["master"]:
  142. self.tk = tkinter.Tk()
  143. self.tk.protocol("WM_DELETE_WINDOW", self.close)
  144. self.tk.withdraw() # do not draw
  145. self.tk.resizable(self.args["resize"],self.args["resize"])
  146. self.tk.tk_setPalette(background='#bbb', foreground='black', activeBackground='#aaa', activeForeground="black")
  147. defaultFont = tkinter.font.nametofont("TkDefaultFont")
  148. cprint(defaultFont)
  149. defaultFont.configure(family="FreeSans",
  150. size=10,
  151. weight="bold")
  152. # MAIN MENUE
  153. try:
  154. self.tk.iconphoto(False, tk.PhotoImage(file=ico_path+"main.png"))
  155. except Exception as e:
  156. cprint(" Exception GUIWindow.__init__",e)
  157. else:
  158. # addtional WINDOW
  159. self.tk = tkinter.Toplevel()
  160. self.tk.iconify()
  161. #self.tk.withdraw() # do not draw
  162. self.tk.protocol("WM_DELETE_WINDOW", self.close)
  163. self.tk.resizable(self.args["resize"],self.args["resize"])
  164. try:
  165. if "COLORPICKER" in self.args["title"]:
  166. self.tk.iconphoto(False, tk.PhotoImage(file=ico_path+"picker.png"))
  167. elif "ENCODER" in self.args["title"]:
  168. self.tk.iconphoto(False, tk.PhotoImage(file=ico_path+"enc.png"))
  169. elif "EXEC" in self.args["title"]:
  170. self.tk.iconphoto(False, tk.PhotoImage(file=ico_path+"exec.png"))
  171. elif "FX" in self.args["title"]:
  172. self.tk.iconphoto(False, tk.PhotoImage(file=ico_path+"fx.png"))
  173. else:
  174. self.tk.iconphoto(False, tk.PhotoImage(file=ico_path+"scribble.png"))
  175. except Exception as e:
  176. cprint(" Exception on load window icon",self.args["title"])
  177. cprint(" Exception:",e)
  178. #time.sleep(3)
  179. self.tk.deiconify()
  180. self.tk["bg"] = "black"
  181. self.tk.bind("<Button>",self.callback)
  182. self.tk.bind("<Key>",self.callback)
  183. self.tk.bind("<KeyRelease>",self.callback)
  184. self.tk.bind("<FocusIn>", on_focus(self.args["title"],"In").cb)
  185. self.tk.bind("<FocusOut>", on_focus(self.args["title"],"Out").cb)
  186. self.tk.title(""+str(self.args["title"])+" "+str(MAIN.lf_nr)+":"+str(MAIN.rnd_id))
  187. MAIN.lf_nr+=1
  188. #self.tk.geometry("270x600+0+65")
  189. geo ="{}x{}".format(self.args["width"],self.args["height"])
  190. if self.args["left"] is not None:
  191. geo += "+{}".format(self.args["left"])
  192. if self.args["top"] is not None:
  193. geo += "+{}".format(self.args["top"])
  194. #self._event_clear = MAIN.tk_event(fix=0,elem=None,attr="CLEAR",data=self,mode="ROOT").cb
  195. self.tk.geometry(geo)
  196. self.show()
  197. def update_idle_task(self):
  198. if MAIN.INIT_OK:
  199. tkinter.Tk.update_idletasks(MAIN.gui_menu_gui.tk)
  200. def close(self,event=None):
  201. cprint("Window.close",self.args["title"],color="red")
  202. #cprint(" ",self.title)
  203. #cprint(" ",self.args)
  204. if self.args["title"] == "MAIN":
  205. MAIN.save_show()
  206. self.tk.destroy()
  207. try:
  208. self.tk.destroy()
  209. except Exception as e:
  210. cprint("Window.close err",e,color="red")
  211. def title(self,title=None):
  212. if title is None:
  213. return self.tk.title()
  214. else:
  215. #return self.tk.title(title)
  216. self.args["title"] = title
  217. return self.tk.title(""+str(self.args["title"])+" "+str(MAIN.lf_nr)+":"+str(MAIN.rnd_id))
  218. def show(self):
  219. self.tk.deiconify()
  220. pass
  221. def mainloop(self):
  222. #save_window_position_loop() #like autosave
  223. try:
  224. self.tk.mainloop()
  225. finally:
  226. self.tk.quit()
  227. cmd="xset -display :0.0 r rate 240 15"
  228. #print(cmd)
  229. os.system(cmd)
  230. def callback(self,event,data={}):#value=255):
  231. #global MAIN._global_short_key
  232. sstart = time.time()
  233. #time.sleep(0.1)
  234. if not MAIN._global_short_key:
  235. return 1
  236. #global MAIN #_shift_key
  237. #cprint("<GUI>",event,color="yellow")
  238. value = 255
  239. if "Release" in str(event.type) or str(event.type) == '5' or str(event.type) == '3':
  240. value = 0
  241. cprint("<GUI>",event.state,data,value,[event.type,event.keysym],color="yellow")
  242. #print(event)
  243. if "state" in dir(event) and "keysym" in dir(event):
  244. #print([event.state,event.keysym,event.type])
  245. if event.state == 4 and str(2) == str(event.type): # strg + s
  246. if str(event.keysym) == "s":
  247. MAIN.save_show()
  248. e = MAIN.master.setup_elem["SAVE\nSHOW"]
  249. b = BLINKI(e)
  250. b.blink()
  251. if str(event.keysym) == "c":
  252. if MAIN.save_show():
  253. MAIN.LOAD_SHOW_AND_RESTART("").cb(force=1)
  254. return
  255. if "keysym" in dir(event):
  256. if "Escape" == event.keysym:
  257. MAIN.FIXTURES.clear()
  258. MAIN.modes.val("ESC",1)
  259. MAIN.master.refresh_fix()
  260. elif event.keysym in ["Shift_L","Shift_R"]:
  261. #cprint(event.type)
  262. if "KeyRelease" in str(event.type) or str(event.type) in ["3"]:
  263. MAIN._shift_key = 0
  264. else:
  265. MAIN._shift_key = 1
  266. #cprint("SHIFT_KEY",_shift_key,"??????????")
  267. #cprint("SHIFT_KEY",_shift_key,"??????????")
  268. #global MAIN #_ENCODER_WINDOW
  269. try:
  270. if MAIN._shift_key:
  271. MAIN._ENCODER_WINDOW.title("SHIFT/FINE ")
  272. else:
  273. MAIN._ENCODER_WINDOW.title("ENCODER")
  274. except Exception as e:
  275. cprint("exc9800",e)
  276. #raise e
  277. elif event.keysym in "ebfclrmsRx" and value:
  278. if "e" == event.keysym:
  279. MAIN.modes.val("EDIT",1)
  280. elif "b" == event.keysym:
  281. MAIN.modes.val("BLIND",1)
  282. elif "f" == event.keysym:
  283. MAIN.modes.val("FLASH",1)
  284. elif "c" == event.keysym:
  285. MAIN.modes.val("CFG-BTN",1)
  286. elif "l" == event.keysym:
  287. MAIN.modes.val("LABEL",1)
  288. elif "r" == event.keysym:
  289. MAIN.modes.val("REC",1)
  290. elif "R" == event.keysym:
  291. MAIN.modes.val("REC-FX",1)
  292. elif "x" == event.keysym:
  293. MAIN.modes.val("REC-FX",1)
  294. elif "m" == event.keysym:
  295. x=MAIN.modes.val("MOVE",1)
  296. if not x:
  297. MAIN.PRESETS.clear_move()
  298. elif "s" == event.keysym:
  299. MAIN.modes.val("SELECT",1)
  300. elif event.keysym in ["F1","F2","F3","F4","F5","F6","F7","F8","F9","F10","F11","F12"]:
  301. nr = int( event.keysym[1:]) # F:1-12
  302. nr = nr-1+81
  303. cprint("F-KEY",value,nr,event.keysym)
  304. #print(event)
  305. MAIN.master.preset_go(nr-1,xfade=None,val=value)
  306. elif event.keysym in ["1","2","3","4","5","6","7","8","9","0"]:
  307. nr = int( event.keysym)
  308. if nr == 0:
  309. nr = 10
  310. nr = nr-1+161
  311. cprint("NUM-KEY",value,nr)
  312. MAIN.master.preset_go(nr-1,xfade=None,val=value)
  313. elif "numbersign" == event.keysym and value: # is char "#"
  314. cprint("numbersign !!")
  315. MAIN.save_show()
  316. for e in MAIN.master.setup_cmd:
  317. cprint(e)
  318. e = MAIN.master.setup_elem["SAVE\nSHOW"]
  319. cprint(e)
  320. b = BLINKI(e)
  321. b.blink()
  322. #e = MAIN.tk_event(fix=0,elem=None,attr="SAVE\nSHOW",mode="SETUP")
  323. #e.cb(event=event)
  324. elif "End" == event.keysym:
  325. MAIN.FIXTURES.fx_off("all")
  326. CONSOLE.fx_off("all")
  327. CONSOLE.flash_off("all")
  328. elif "Delete" == event.keysym:
  329. #MAIN.PRESETS.delete(nr)
  330. if value:
  331. MAIN.modes.val("DEL",1)
  332. #cprint("oipo "*10,round(int(time.time()-sstart)*1000,2))
  333. class PopupList():
  334. def __init__(self,name="<NAME>",master=0,width=400,height=450,exit=1,left=_POS_LEFT+400,top=_POS_TOP+100,cb=None,bg="black"):
  335. self.name = name
  336. self.frame = None
  337. self.bg=bg
  338. self.cb = cb
  339. if cb is None:
  340. cb = DummyCallback #("load_show_list.cb")
  341. #w = Window(self.name,master=master,width=width,height=height,exit=exit,left=left,top=top,cb=cb)
  342. args = {"title":self.name,"master":master,"width":width,"height":height,"exit":exit,"left":left,"top":top,"cb":cb}
  343. w = Window(args)
  344. self.w = w
  345. w.show()
  346. def sframe(self,line1="<line1>",line2="<line2>",data=[]):
  347. xframe=self.w.tk
  348. if self.bg:
  349. xframe.configure(bg=self.bg)
  350. self.w.tk.configure(bg=self.bg)
  351. c=0
  352. r=0
  353. b = tk.Label(xframe,bg="grey",text=line1,anchor="w")
  354. b.pack(side="top",expand=0,fill="x" )
  355. b = tk.Label(xframe,bg="grey",text=line2,anchor="w")
  356. b.pack(side="top",expand=0,fill="x" )
  357. b = tk.Label(xframe,bg="black",fg="black",text="")
  358. if self.bg:
  359. b.configure(fg=self.bg)
  360. b.configure(bg=self.bg)
  361. b.pack(side="top")
  362. b = tk.Entry(xframe,width=10,text="")#,anchor="w")
  363. b.pack(side="top",expand=0,fill="x")
  364. b["state"] = "readonly"
  365. b.focus()
  366. #frame = tk.Frame(xframe,heigh=2800)
  367. #frame.pack(fill=tk.BOTH,expand=1, side=tk.TOP)
  368. frame = MAIN.ScrollFrame(xframe,width=300,height=500,bd=1,bg=self.bg)
  369. #frame.pack(side="left") #fill=tk.BOTH,expand=1, side=tk.TOP)
  370. #self.frame = frame
  371. self.w.tk.state(newstate='normal')
  372. self.w.tk.attributes('-topmost',True)
  373. return frame
  374. def showwarning(msg="<ERROR>",title="<TITLE>"):
  375. cprint("showwarning","MSG:",msg,"tilte:",title)
  376. if IS_GUI:
  377. _main = tkinter.Tk()
  378. defaultFont = tkinter.font.nametofont("TkDefaultFont")
  379. cprint("showwarning",defaultFont)
  380. if IS_GUI:
  381. defaultFont.configure(family="FreeSans",
  382. size=10,
  383. weight="normal")
  384. geo ="{}x{}".format(20,20)
  385. _main.geometry(geo)
  386. def _quit():
  387. time.sleep(1/10)
  388. _main.quit()
  389. thread.start_new_thread(_main.mainloop,())
  390. r=tkinter.messagebox.showwarning(message=msg,title=title,parent=None)