4
4
from tkinter import filedialog
5
5
from tkinter import messagebox
6
6
from tooltip import CreateToolTip
7
+ import scriptWindow
8
+ import messagePopup
7
9
8
10
import serial
9
11
import re
@@ -268,7 +270,9 @@ def sendScript(arg=None):
268
270
print (rep )
269
271
scriptpath = rep [0 ] # use first file in list
270
272
if (scriptpath == None ): return # exit if user selected no file
271
- popup_ScriptInit (scriptpath )
273
+ guiEnable ()
274
+ scriptWindow .show (win ,scriptpath ,send ,received )
275
+ guiDisable ()
272
276
273
277
def initWindow ():
274
278
global win
@@ -571,227 +575,10 @@ def popup_AllReceiveReps(receiveIdx):
571
575
winPopup .transient (win )
572
576
winPopup .grab_set () # redirect all user input to this popup
573
577
574
- #https://stackoverflow.com/questions/2785755/how-to-split-but-ignore-separators-in-quoted-strings-in-python
575
- def scriptline2tokens (scriptline ):
576
- # remove remarks
577
- if len (scriptline .strip ())== 0 : return None
578
- if scriptline .strip ()[0 ]== '#' : return None
579
- PATTERN_REMARKS = re .compile (r'''((?:[^#"']|"[^"]*"|'[^']*')+)''' )
580
- scriptline = PATTERN_REMARKS .split (scriptline )[1 ::2 ][0 ]
581
- # split in tokens which are not enclosed in double quoyes
582
- scriptline = scriptline .strip ()
583
- if len (scriptline )> 0 :
584
- PATTERN_SPACES = re .compile (r'''((?:[^ "']|"[^"]*"|'[^']*')+)''' )
585
- tokens = PATTERN_SPACES .split (scriptline )[1 ::2 ]
586
- return tokens
587
- else :
588
- return None
589
-
590
- def popup_ShowMessage (type ,title , message ):
591
- popupMsg = tk .Toplevel (win )
592
- popupMsg .transient (win .popupWait )
593
- popupMsg .wm_title (title )
594
- #backcolor=win["bg"]#"#DDDDDD"
595
- popupMsg .configure (background = 'white' )
596
-
597
- contentframe = tk .Frame (popupMsg ,bg = 'white' )
598
- contentframe .pack (side = tk .TOP ,fill = 'x' ,expand = True ,padx = (0 ,0 ),pady = (0 ,0 ))
599
- cvImg = tk .Label (contentframe ,height = 48 ,width = 48 ,bg = 'white' )
600
- imgpath = os .path .join (scriptdir ,f"{ type } 48.png" )
601
- cvImg .img = tk .PhotoImage (file = imgpath )
602
- cvImg .pack (side = tk .LEFT ,padx = (32 ,0 ),pady = (32 ,32 ))
603
- cvImg .configure (image = cvImg .img )
604
-
605
- lb = tk .Label (contentframe , anchor = 'w' ,text = message ,bg = 'white' )
606
- lb .pack (side = tk .LEFT ,padx = (16 ,32 ),pady = (32 ,32 ))
607
-
608
- # footer
609
- footerframe = tk .Frame (popupMsg ,height = 12 ,bg = 'white' )
610
- footerframe .pack (side = tk .BOTTOM ,fill = 'x' ,expand = True ,padx = (0 ,0 ),pady = (0 ,0 ))
611
- popupMsg .cmdOk = tk .Button (footerframe , text = "OK" ,command = popupMsg .destroy ,width = 10 )
612
- popupMsg .cmdOk .pack (side = tk .RIGHT ,padx = (8 ,8 ),pady = (8 ,8 ))
613
- popupMsg .cmdOk .configure (relief = tk .FLAT )
614
-
615
- popupMsg .grab_set ()
616
-
617
- def popup_ScriptClose ():
618
- guiEnable ()
619
- win .popupWait .destroy ()
620
-
621
- def popup_ScriptInit (scriptpath ):
622
- scriptname = os .path .basename (scriptpath ).split ("." )[0 ]
623
-
624
- # construct dialog
625
- popupWait = tk .Toplevel (win )
626
- popupWait .transient (win )
627
- popupWait .scriptname = scriptname
628
- popupWait .wm_title (f"Script - { scriptname } " )
629
- #popupWait.resizable(False,False)
630
- popupWait .scriptpath = scriptpath
631
- win .popupWait = popupWait
632
- backcolor = win ["bg" ]#"#DDDDDD"
633
- #popupWait.protocol("WM_DELETE_WINDOW", pass_WaitForScript) # custom function which sets winDestroyed so we can check state of win
634
-
635
- # header/message
636
- headerframe = tk .Frame (popupWait ,background = backcolor )
637
- headerframe .pack (side = tk .TOP ,fill = 'x' ,padx = (0 ,0 ),pady = (8 ,4 ))
638
- lb = tk .Label (headerframe , anchor = 'w' ,text = 'Status:' )
639
- lb .pack (side = tk .LEFT ,padx = 8 )
640
- popupWait .varInfo = tk .StringVar ()
641
- popupWait .varInfo .set (f"Loaded '{ scriptname } '" )
642
- lbInfo = tk .Label (headerframe , anchor = tk .W ,textvariable = popupWait .varInfo )
643
- lbInfo .pack (side = tk .LEFT ,padx = 8 ,fill = tk .X ,expand = True )
644
-
645
- # draw sep
646
- separator = ttk .Separator (popupWait ,orient = 'horizontal' ).pack (side = tk .TOP ,fill = 'x' ,pady = 8 )
647
-
648
- # footer
649
- footerframe = tk .Frame (popupWait ,background = backcolor )
650
- footerframe .pack (side = tk .BOTTOM ,fill = 'x' ,padx = (8 ,8 ),pady = (4 ,4 ))
651
-
652
- lb = tk .Label (footerframe , text = 'Delay' )
653
- lb .pack (side = tk .LEFT )
654
-
655
- popupWait .varDelay = tk .StringVar ()
656
- popupWait .delayList = ("No delay" ,"0.1 sec" ,"0.5 sec" ,"1 sec" ,"2 sec" ,"5 sec" )
657
- popupWait .delayTimes = (0 ,0.1 ,0.5 ,1.0 ,2.0 ,5.0 )
658
- popupWait .varDelay .set ('0.5 sec' )
659
- ddDelay = tk .OptionMenu (footerframe ,popupWait .varDelay ,* popupWait .delayList )
660
- ddDelay .pack (side = tk .LEFT ,padx = (3 ,0 ))
661
- ddDelay .configure (width = 6 )
662
- ddDelay .configure (relief = tk .FLAT )
663
- ddDelay .configure (bg = 'white' )
664
- footerbgcolor ,footersgcolor ,footerfgcolor = backcolor ,backcolor ,'#000'
665
- ddDelay .configure (background = footerbgcolor ,activebackground = footersgcolor ,foreground = footerfgcolor ,activeforeground = footerfgcolor ,highlightbackground = 'red' )
666
- ddDelay .configure (bd = 3 )
667
- ddDelay ["menu" ].configure (background = footerbgcolor ,activebackground = footersgcolor ,foreground = footerfgcolor ,activeforeground = footerfgcolor )
668
- ddDelay ["menu" ].configure (relief = tk .FLAT )
669
- ddDelay .pack (side = tk .LEFT ,padx = (3 ,0 ))
670
- ddDelay .configure (bd = '0p' )
671
- ddDelay .configure (highlightthickness = 0 )
672
-
673
- popupWait .cmdRun = tk .Button (footerframe , text = "Run" ,command = popup_ScriptProcess )
674
- popupWait .cmdRun .pack (side = tk .RIGHT )
675
- popupWait .cmdRun .configure (relief = tk .FLAT )
676
-
677
- popupWait .cmdSave = tk .Button (footerframe , text = "Save" ,command = popup_ScriptSave )
678
- popupWait .cmdSave .pack (side = tk .RIGHT )
679
- popupWait .cmdSave .configure (relief = tk .FLAT )
680
-
681
- popupWait .cmdReload = tk .Button (footerframe , text = "Reload" ,command = popup_ScriptLoad )
682
- popupWait .cmdReload .pack (side = tk .RIGHT )
683
- popupWait .cmdReload .configure (relief = tk .FLAT )
684
-
685
- popupWait .cmdHelp = tk .Button (footerframe , text = "Help" ,command = popup_ScriptHelp )
686
- popupWait .cmdHelp .pack (side = tk .RIGHT )
687
- popupWait .cmdHelp .configure (relief = tk .FLAT )
688
-
689
- # draw sep
690
- separator = ttk .Separator (popupWait ,orient = 'horizontal' ).pack (side = tk .BOTTOM ,fill = 'x' ,pady = (8 ,0 ))
691
-
692
- # tabs
693
- popupWait .tabs = ttk .Notebook (popupWait )
694
- popupWait .scriptTab = ttk .Frame (popupWait .tabs )
695
- popupWait .tabs .add (popupWait .scriptTab ,text = " Script " )#,command=showScript)
696
- popupWait .errorsTab = ttk .Frame (popupWait .tabs )
697
- popupWait .tabs .add (popupWait .errorsTab ,text = " Errors " )#,command=showErrors)
698
- popupWait .tabs .pack (side = tk .TOP , fill = tk .X ,padx = (8 ,8 ),pady = (2 ,0 ))
699
-
700
- # script area
701
- #popupWait.varScript=tk.StringVar() #use textInput.get()
702
- popupWait .scrollText = tk .Scrollbar (popupWait .scriptTab )#popupWait)
703
- popupWait .scriptText = tk .Text (popupWait .scriptTab ,bg = 'white' )#popupWait,bg="white")
704
- popupWait .scrollText .pack (side = tk .RIGHT , fill = tk .Y ,padx = (0 ,0 ),pady = (2 ,2 ))
705
- popupWait .scriptText .pack (expand = True ,padx = (2 ,0 ),pady = (2 ,0 ),fill = tk .BOTH )
706
- popupWait .scrollText .config (command = popupWait .scriptText .yview )
707
- popupWait .scriptText .config (yscrollcommand = popupWait .scrollText .set )
708
- popupWait .scriptText .configure (wrap = tk .NONE ) # needed for autoscroll (using .see) to function reliably
709
- popupWait .scriptText .configure (relief = tk .SOLID )
710
- popupWait .scrollText .configure (relief = tk .FLAT )
711
- popupWait .scrollText .configure (borderwidth = 0 )
712
- popupWait .scrollText .configure (elementborderwidth = 1 )
713
- popupWait .scrollText .configure (width = 14 )
714
- #popupWait.scrollText.configure(trough=backcolor)
715
- popupWait .scriptText .configure (wrap = tk .NONE )
716
- popupWait .scriptText .configure (font = tkf .Font (family = 'Terminal' , weight = 'normal' , size = 9 )) #TkFixedFont
717
- popupWait .scriptText .oldlinenr = 0
718
-
719
- # error area
720
- #popupWait.varScript=tk.StringVar() #use textInput.get()
721
- popupWait .scrollErrors = tk .Scrollbar (popupWait .errorsTab )#popupWait)
722
- popupWait .scriptErrors = tk .Text (popupWait .errorsTab ,bg = 'white' )#popupWait,bg="white")
723
- popupWait .scrollErrors .pack (side = tk .RIGHT , fill = tk .Y ,padx = (0 ,0 ),pady = (2 ,2 ))
724
- popupWait .scriptErrors .pack (expand = True ,padx = (2 ,0 ),pady = (2 ,0 ),fill = tk .BOTH )
725
- popupWait .scrollErrors .config (command = popupWait .scriptErrors .yview )
726
- popupWait .scriptErrors .config (yscrollcommand = popupWait .scrollErrors .set )
727
- popupWait .scriptErrors .configure (wrap = tk .NONE ) # needed for autoscroll (using .see) to function reliably
728
- popupWait .scriptErrors .configure (relief = tk .SOLID )
729
- popupWait .scrollErrors .configure (relief = tk .FLAT )
730
- popupWait .scrollErrors .configure (borderwidth = 0 )
731
- popupWait .scrollErrors .configure (elementborderwidth = 1 )
732
- popupWait .scrollErrors .configure (width = 14 )
733
- #popupWait.scrollText.configure(trough=backcolor)
734
- popupWait .scriptErrors .configure (wrap = tk .NONE )
735
- popupWait .scriptErrors .configure (font = tkf .Font (family = 'Terminal' , weight = 'normal' , size = 9 )) #TkFixedFont
736
-
737
- # show script
738
- popup_ScriptLoad ()
739
-
740
- # bindings and show
741
- popupWait .protocol ("WM_DELETE_WINDOW" , popup_ScriptClose ) # custom function which sets winDestroyed so we can check state of win
742
- guiDisable ()
743
- popupWait .update ()
744
- popupWait .grab_set () # to redirect all user input to this popup
745
-
746
- def popup_ScriptSave (event = None ):
747
- scriptpath = win .popupWait .scriptpath
748
- scriptlines = win .popupWait .scriptText .get (0.0 ,tk .END )
749
- with open (win .popupWait .scriptpath , "w" ) as writer : # open file
750
- writer .write (scriptlines )
751
-
752
- def popup_ScriptLoad (event = None ):
753
- win .popupWait .scriptText .delete (0.0 ,tk .END )
754
- with open (win .popupWait .scriptpath , "r" ) as reader : # open file
755
- scriptlines = reader .readlines () # read all lines
756
- for nr ,lineStr in enumerate (scriptlines ):
757
- tagname = f"{ nr } "
758
- taglist = (tagname ,)
759
- win .popupWait .scriptText .insert (tk .END , lineStr ,taglist )
760
- #print(f"scripText append:{nr} {lineStr}")
761
578
762
579
def tokenIsString (token ):
763
580
return ( (token [0 ]== '"' ) and (token [- 1 ]== '"' ) )
764
581
765
- import PyInterpreter as pyi
766
- from tkRTFText import RTFText
767
- def popup_ScriptHelp ():
768
- with open (os .path .join (scriptdir ,"scriptHelp.txt" ), "r" ) as reader : # open file
769
- msg = reader .readlines ()
770
-
771
- popupMdown = tk .Toplevel (win )
772
- popupMdown .transient (win .popupWait )
773
- popupMdown .wm_title ("Script Language Help" )
774
- #backcolor=win["bg"]#"#DDDDDD"
775
- popupMdown .configure (background = 'white' )
776
-
777
- # footer
778
- footerframe = tk .Frame (popupMdown ,height = 12 ,bg = 'white' )
779
- footerframe .pack (side = tk .BOTTOM ,fill = 'x' ,expand = False ,padx = (0 ,0 ),pady = (0 ,0 ))
780
- popupMdown .cmdOk = tk .Button (footerframe , text = "OK" ,command = popupMdown .destroy ,width = 10 )
781
- popupMdown .cmdOk .pack (side = tk .RIGHT ,padx = (8 ,8 ),pady = (8 ,8 ))
782
- popupMdown .cmdOk .configure (relief = tk .FLAT )
783
-
784
- # script area
785
- #popupMdown.varScript=tk.StringVar() #use textInput.get()
786
- textframe = tk .Frame (popupMdown ,height = 12 ,bg = 'white' )
787
- textframe .pack (side = tk .TOP ,fill = 'both' ,expand = True ,padx = (0 ,0 ),pady = (0 ,0 ))
788
- popupMdown .helpText = RTFText (textframe ,bg = 'white' ,relief = tk .SOLID )
789
- popupMdown .helpText .pack (side = tk .LEFT ,expand = True ,padx = (2 ,0 ),pady = (2 ,0 ),fill = tk .BOTH )
790
- popupMdown .helpText .configure (wrap = tk .NONE )
791
-
792
- popupMdown .helpText .setRTF (msg ,pad = (8 ,8 ),bg = 'white' , font = tkf .Font (family = 'Terminal' , weight = 'normal' , size = 9 ))
793
-
794
- popupMdown .grab_set ()
795
582
796
583
def received ():
797
584
if len (histReceived )> 0 :
@@ -801,80 +588,6 @@ def received():
801
588
else :
802
589
return "None"
803
590
804
- def showScriptLine (linenr ):
805
- popupWait = win .popupWait
806
- popupWait .scriptText .tag_config (f"{ popupWait .scriptText .oldlinenr } " ,background = 'white' )
807
- popupWait .scriptText .tag_config (f"{ linenr } " ,background = 'yellow' )
808
- popupWait .scriptText .see (float (linenr + 2 ))
809
- popupWait .update ()
810
- popupWait .scriptText .oldlinenr = linenr
811
-
812
- isProcessingScript = False
813
-
814
- def popup_ScriptProcess (event = None ):
815
- global isProcessingScript
816
- popupWait = win .popupWait
817
-
818
- # set flag
819
- isProcessingScript = not isProcessingScript
820
-
821
- # check if user interupted script
822
- if not isProcessingScript :
823
- pyi .stopScript ()
824
- return
825
-
826
- #disable yellow cursor from previous runs
827
- popupWait .scriptText .tag_config (f"{ popupWait .scriptText .oldlinenr } " ,background = 'white' )
828
- popupWait .scriptText .oldlinenr = 0
829
-
830
- #read script (can be edited by user)
831
- scriptpath = popupWait .scriptpath
832
- scriptlines = popupWait .scriptText .get (0.0 ,tk .END ).split ('\n ' )
833
- pyi .setScript (scriptlines )
834
-
835
- #get delay time between commands
836
- delayIndex = popupWait .delayList .index (popupWait .varDelay .get ())
837
- delayTime = popupWait .delayTimes [delayIndex ]
838
-
839
- #setup script environment
840
- # callback handler so we can follow which line the script is running
841
- pyi .setCallbackHandler (showScriptLine )
842
-
843
- #rename run button so we can use it as stop button
844
- popupWait .cmdRun .configure (text = "Stop" )
845
-
846
- # error handler should output to striptErrors widget instead of console
847
- def errhndlr (errStack ):
848
- win .popupWait .scriptErrors .delete (0.0 ,tk .END )
849
- win .popupWait .scriptErrors .insert (tk .END , '\n \n ' .join (errStack ))
850
- win .popupWait .tabs .select (win .popupWait .errorsTab )
851
- msgbox = popup_ShowMessage (type = "error" ,title = "Script failed" , message = f"Errors in script '{ popupWait .scriptname } '!" )
852
- pyi .setErrorHandler (errhndlr )
853
- # reroute print to infobos
854
- def print2InfoBox (msg ):
855
- popupWait .varInfo .set (msg )
856
- pyi .addSystemFunction ('print' ,print2InfoBox ,[[str ,int ,bool ,float ],])
857
- # add send (over serial) command
858
- pyi .addSystemFunction ('send' ,send ,[[str ,],])
859
- # add received var (to be updated each x msecs)
860
- pyi .importSystemFunction (pyi ,__name__ ,"received" )
861
-
862
- #run script
863
- scriptStart = time .time ()
864
- runSuccess = pyi .runScript (delaytime = delayTime )
865
- scriptDuration = time .time ()- scriptStart
866
- if runSuccess and isProcessingScript :
867
- msgbox = popup_ShowMessage (type = "info" ,title = "Script finished" , message = f"Script '{ popupWait .scriptname } ' finished in { scriptDuration :.4f} seconds!" )
868
-
869
- if runSuccess and not isProcessingScript :
870
- msgbox = popup_ShowMessage (type = "warning" ,title = "Script stopped" , message = f"Script '{ popupWait .scriptname } ' interupted after { scriptDuration :.4f} seconds!" )
871
-
872
- # set flag
873
- isProcessingScript = False
874
-
875
- #rename stop button so we can use it as run button
876
- popupWait .cmdRun .configure (text = "Run" )
877
-
878
591
879
592
def clearText ():
880
593
win .textReceived .config (state = tk .NORMAL )
0 commit comments