grid_gui.py
directory : D:\2018_py_proj\TkGridGUI\tkgridgui
Line Count : 1003
Line Clip Size : No Clipping
tab_of_notebook_changed Word MatchCase (5) 161 495 498 788 910
1
2
3 from __future__ import print_function
4 from __future__ import unicode_literals
5 from future import standard_library
6 standard_library.install_aliases()
7 from builtins import str
8 from builtins import range
9 from builtins import object
10 r"""
11 tkGridGUI builds a target python Tkinter GUI graphic user interface using
12 the grid geometry manager.
13
14 The main idea behind tkGridGUI is to allow a fully "wired" python
15 Tkinter GUI application to be created in minutes. The users main
16 responsibility is to add logic to the Tkinter framework created by tkGridGUI.
17 tkGridGUI holds structures to create items such as menus, toolbars and statusbars.
18
19 TkGridGUI
20 Copyright (C) 2018 Charlie Taylor
21
22 This program is free software: you can redistribute it and/or modify
23 it under the terms of the GNU General Public License as published by
24 the Free Software Foundation, either version 3 of the License, or
25 (at your option) any later version.
26
27 This program is distributed in the hope that it will be useful,
28 but WITHOUT ANY WARRANTY; without even the implied warranty of
29 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 GNU General Public License for more details.
31
32 You should have received a copy of the GNU General Public License
33 along with this program. If not, see <http://www.gnu.org/licenses/>.
34
35 -----------------------
36
37 """
38 import os
39 here = os.path.abspath(os.path.dirname(__file__))
40
41 __author__ = 'Charlie Taylor'
42 __copyright__ = 'Copyright (c) 2018 Charlie Taylor'
43 __license__ = 'GPL-3'
44 exec( open(os.path.join( here,'_version.py' )).read() )
45 __email__ = "cet@appliedpython.com"
46 __status__ = "3 - Alpha"
47
48
49 import sys
50 from sys import platform
51
52 if sys.version_info < (3,):
53 from tkSimpleDialog import Dialog
54 else:
55 from tkinter.simpledialog import Dialog
56
57 from tkinter import *
58 import tkinter.messagebox
59 import tkinter.filedialog
60 import tkinter.colorchooser
61 from tkinter import Button, Canvas, Checkbutton, Entry, Frame, Label, LabelFrame
62 from tkinter import Listbox, Message, Radiobutton, Spinbox, Text
63 from tkinter import OptionMenu
64 from tkinter.ttk import Combobox, Progressbar, Separator, Treeview, Style, Notebook
65
66 from tkgridgui.tkfontchooser import askfont
67
68 from tkgridgui.grid_notebook import NotebookGridDes, CONTROLS, ContainerControlsL, CONTROL_NEXT_NUMBER_D, CONTROL_COLOR_D
69 from tkgridgui.target_tk_app_def import TargetTkAppDef
70 from tkgridgui.preview_win import PreviewWin
71
72 from tkgridgui.menu_maker_Dialog import Menumaker
73 from tkgridgui.make_py_src import FormSource
74 from tkgridgui.make_menu_src import buildMenuSource, getMenuSource
75
76 from tkgridgui.maybe_save_Dialog import maybe_save_dialog
77
78 class GridGUI(object):
79 """
80 tkGridGUI builds a python Tkinter GUI graphic user interface using the grid geometry manager.
81 """
82
83 def __init__(self, MainWin):
84 """Inits Tkinter window of GridGUI."""
85
86 self.root = MainWin
87
88 MainWin.geometry( '+10+30' )
89
90 try:
91 style = Style(self.root)
92 if "win" == platform[:3]:
93 style.theme_use('vista')
94 elif "darwin" in platform:
95 style.theme_use('clam')
96 else:
97 style.theme_use('clam')
98 bg = style.lookup("TLabel", "background")
99 self.root.configure(bg=bg)
100 except:
101 print("OOPS... failed to set style.theme_use... Let's press on.")
102
103 self.MainWin = MainWin
104
105 MainWin.protocol('WM_DELETE_WINDOW', self.cleanupOnQuit)
106 MainWin.allow_subWindows_to_close = 0
107
108 self.add_menu_to_MainWin()
109
110 topFrame = Frame( MainWin )
111
112
113 frame1 = LabelFrame(topFrame, text="Widgets")
114 self.place_widget_selection_listbox( frame1 )
115 frame1.pack(anchor=NW, side=LEFT)
116
117 frame2 = Frame( topFrame )
118 self.place_gui_definition_controls( frame2, MainWin )
119 frame2.pack(anchor=N, side=LEFT)
120
121 self.grid_frame = Frame(topFrame)
122 self.grid_notebook = NotebookGridDes(self, self.grid_frame, MainWin, num_cols=5, num_rows=8)
123 self.grid_frame.pack(anchor=N, side=LEFT)
124
125 topFrame.pack(fill=BOTH, expand=Y)
126
127
128 statframe = Frame(MainWin)
129 MainWin.statusMessage = StringVar()
130 MainWin.statusMessage.set('Welcome to TkGridGUI')
131 self.statusbar = Label(statframe, textvariable=MainWin.statusMessage,
132 relief=SUNKEN, anchor=W)
133 self.statusbar.pack(anchor=SW, fill=X, side=BOTTOM)
134 statframe.pack(anchor=SW, fill=X, side=BOTTOM)
135
136
137
138 self.current_fileFullName = ''
139 self.current_filePath = ''
140 self.current_fileName = ''
141
142 self.target_app = TargetTkAppDef( name='myApp')
143 self.PreviewWin = None
144
145 self.Listbox_1_Click( None )
146
147
148 self.in_reading_mode = False
149 if len( sys.argv ) == 2:
150 fName = sys.argv[1]
151 if fName.find('.')<0:
152 fName += '.def'
153
154 fullpath = os.path.abspath(fName)
155
156 if os.path.isfile( fullpath ):
157 self.openFile( fName=fullpath )
158 else:
159 self.MainWin.statusMessage.set('file "%s" does not exist'%fName)
160
161 self.grid_notebook.notebook.bind("<<NotebookTabChanged>>", self.tab_of_notebook_changed)
162
163 self.mouse_location = ''
164 self.MainWin.bind("<Enter>", self.onMainWindowEnter)
165
166 def onMainWindowEnter(self, event):
167 """Only track Enter... Want last known location."""
168 if self.mouse_location != 'main_window':
169 print('mouse_location = main_window')
170 self.mouse_location = 'main_window'
171
172 def refresh_preview_win(self, allow_destroy_children=True):
173 """
174 Place all of the widgets from grid_notebook onto PreviewWin.
175 May need to delete and rebuild current widgets on PreviewWin.
176 """
177
178 if self.PreviewWin is None:
179 self.PreviewWin = PreviewWin( self.MainWin, grid_gui=self )
180 self.target_app.set_PreviewWin( self.PreviewWin )
181 self.target_app.set_Notebook( self.grid_notebook )
182 else:
183 if allow_destroy_children:
184 self.PreviewWin.destroy_all_children()
185 self.target_app.destroy_all_preview_widgets()
186
187
188 widgetL = self.grid_notebook.make_complete_list_of_widgets()
189
190 for w in widgetL:
191
192 (widget_type, widget_name, tab_label, row_target, col_target) = w
193
194 self.target_app.maybe_add_component( widget_type=widget_type,
195 widget_name=widget_name,
196 tab_label=tab_label,
197 row=row_target, col=col_target)
198 self.target_app.show_preview()
199
200
201
202
203
204 def add_menu_to_MainWin(self):
205
206
207 self.menuBar = Menu(self.MainWin, relief = 'raised', bd=2)
208
209
210 fileMenu = Menu(self.menuBar, tearoff=0)
211 fileMenu.add('command', label = 'New', command=self.newForm, underline=0,accelerator="Ctrl+N")
212 fileMenu.add('command', label = 'Open', command=self.openFile, underline=0,accelerator="Ctrl+O")
213 fileMenu.add('command', label = 'Save', command=self.saveasFile, underline=0,accelerator="Ctrl+S")
214
215 fileMenu.add('command', label = 'Exit', command=self.cleanupOnQuit, underline=0,accelerator="Ctrl+X")
216 self.menuBar.add('cascade', label="File", menu=fileMenu)
217
218
219 optMenu = Menu(self.menuBar, tearoff=0)
220 optMenu.add('command', label = 'Font to Clipboard', command =self.FontPickButton_Select, underline=0,accelerator="Ctrl+F")
221 optMenu.add('command', label = 'Color to Clipboard', command = self.ColorPickButton_Select, underline=0,accelerator="Ctrl+C")
222 self.menuBar.add('cascade', label="Options", menu=optMenu)
223
224
225 self.root.bind("<Control-N>", lambda event: self.newForm())
226 self.root.bind("<Control-n>", lambda event: self.newForm())
227
228 self.root.bind("<Control-O>", lambda event: self.openFile())
229 self.root.bind("<Control-o>", lambda event: self.openFile())
230
231 self.root.bind("<Control-S>", lambda event: self.saveasFile())
232 self.root.bind("<Control-s>", lambda event: self.saveasFile())
233
234 self.root.bind("<Control-X>", lambda event: self.cleanupOnQuit())
235 self.root.bind("<Control-x>", lambda event: self.cleanupOnQuit())
236
237
238 self.menuBar.add('command', label="About", command = self.About)
239
240
241 self.menuBar.add('command', label="Help", command = self.Help)
242
243 self.root.config(menu=self.menuBar)
244
245 def mainOrDialog_Callback(self, varName, index, mode):
246
247
248
249 self.refresh_preview_win()
250 if self.MainWin.mainOrDialog.get() == 'dialog':
251 if self.MainWin.hideOkChkBox_StringVar.get() == "yes":
252 self.PreviewWin.remove_mock_OK_Cancel_Buttons()
253 else:
254 self.PreviewWin.add_mock_OK_Cancel_Buttons()
255 else:
256 self.PreviewWin.remove_mock_OK_Cancel_Buttons()
257
258 def place_gui_definition_controls(self, frame2, MainWin ):
259
260
261 MainWin.mainOrDialog=StringVar()
262 lbframe = LabelFrame(frame2, text="GUI Type")
263 lbframe.pack(anchor=W)
264
265 b = Radiobutton(lbframe, text="Main Window", value='main', variable=MainWin.mainOrDialog)
266 b.pack(anchor=W)
267 b = Radiobutton(lbframe, text="Dialog", value='dialog', variable=MainWin.mainOrDialog)
268 b.pack(anchor=W)
269 MainWin.mainOrDialog.set('main')
270 self.mainOrDialog_traceName = MainWin.mainOrDialog.trace_variable("w", self.mainOrDialog_Callback)
271
272 MainWin.hideOkChkBox = Checkbutton(lbframe, text="Hide OK Btn", width="15")
273 MainWin.hideOkChkBox.pack(anchor=E, side=TOP)
274 MainWin.hideOkChkBox_StringVar = StringVar()
275 MainWin.hideOkChkBox_StringVar.set("no")
276 MainWin.hideOkChkBox.configure(variable=MainWin.hideOkChkBox_StringVar, onvalue="yes", offvalue="no")
277 self.hideOkChkBox_traceName = MainWin.hideOkChkBox_StringVar.trace_variable("w", self.hideOkChkBox_Callback)
278
279
280 lbframe = LabelFrame(frame2, text="Window Options")
281 lbframe.pack(anchor=W)
282
283 MainWin.menuChkBox = Checkbutton(lbframe, text="Main Menu", width="15")
284 MainWin.menuChkBox.pack(anchor=W, side=TOP)
285 MainWin.menuChkBox_StringVar = StringVar()
286 MainWin.menuChkBox_StringVar.set("no")
287 MainWin.menuChkBox.configure(variable=MainWin.menuChkBox_StringVar, onvalue="yes", offvalue="no")
288 self.menuChkBox_traceName = MainWin.menuChkBox_StringVar.trace_variable("w", self.menuChkBox_Callback)
289
290 MainWin.statusBarChkBox = Checkbutton(lbframe, text="Status Bar", width="15")
291 MainWin.statusBarChkBox.pack(anchor=W, side=TOP)
292 MainWin.statusBarChkBox_StringVar = StringVar()
293 MainWin.statusBarChkBox_StringVar.set("no")
294 MainWin.statusBarChkBox.configure(variable=MainWin.statusBarChkBox_StringVar, onvalue="yes", offvalue="no")
295 self.statusBarChkBox_traceName = MainWin.statusBarChkBox_StringVar.trace_variable("w", self.statusBarChkBox_Callback)
296
297 MainWin.resizableChkBox = Checkbutton(lbframe, text="Resizable", width="15")
298 MainWin.resizableChkBox.pack(anchor=W, side=TOP)
299 MainWin.resizableChkBox_StringVar = StringVar()
300 MainWin.resizableChkBox_StringVar.set("yes")
301 MainWin.resizableChkBox.configure(variable=MainWin.resizableChkBox_StringVar, onvalue="yes", offvalue="no")
302 self.resizableChkBox_traceName = MainWin.resizableChkBox_StringVar.trace_variable("w", self.resizableChkBox_Callback)
303
304
305 lbframe = LabelFrame(frame2, text="Standard Dialogs")
306 lbframe.pack(anchor=W)
307
308 MainWin.stdDialMessChkBox = Checkbutton(lbframe, text="Messages", width="15")
309 MainWin.stdDialMessChkBox.pack(anchor=E, side=TOP)
310 MainWin.stdDialMessChkBox_StringVar = StringVar()
311 MainWin.stdDialMessChkBox_StringVar.set("no")
312 MainWin.stdDialMessChkBox.configure(variable=MainWin.stdDialMessChkBox_StringVar, onvalue="yes", offvalue="no")
313
314
315 MainWin.stdDialColorChkBox = Checkbutton(lbframe, text="Color Choose", width="15")
316 MainWin.stdDialColorChkBox.pack(anchor=E, side=TOP)
317 MainWin.stdDialColorChkBox_StringVar = StringVar()
318 MainWin.stdDialColorChkBox_StringVar.set("no")
319 MainWin.stdDialColorChkBox.configure(variable=MainWin.stdDialColorChkBox_StringVar, onvalue="yes", offvalue="no")
320
321 MainWin.stdDialFileChkBox = Checkbutton(lbframe, text="File Open/Save", width="15")
322 MainWin.stdDialFileChkBox.pack(anchor=E, side=TOP)
323 MainWin.stdDialFileChkBox_StringVar = StringVar()
324 MainWin.stdDialFileChkBox_StringVar.set("no")
325 MainWin.stdDialFileChkBox.configure(variable=MainWin.stdDialFileChkBox_StringVar, onvalue="yes", offvalue="no")
326
327 MainWin.stdAlarmChkBox = Checkbutton(lbframe, text="Alarm Handler", width="15")
328 MainWin.stdAlarmChkBox.pack(anchor=E, side=TOP)
329 MainWin.stdAlarmChkBox_StringVar = StringVar()
330 MainWin.stdAlarmChkBox_StringVar.set("no")
331 MainWin.stdAlarmChkBox.configure(variable=MainWin.stdAlarmChkBox_StringVar, onvalue="yes", offvalue="no")
332
333
334 self.ColorPickButton = Button(frame2, text="Put Color on Clipboard", width=18)
335 self.ColorPickButton.pack(anchor=W, side=TOP)
336 self.ColorPickButton.bind("<ButtonRelease-1>", self.ColorPickButton_Click)
337
338
339 self.FontPickButton = Button(frame2, text="Put Font on Clipboard", width=18)
340 self.FontPickButton.pack(anchor=W, side=TOP)
341 self.FontPickButton.bind("<ButtonRelease-1>", self.FontPickButton_Click)
342
343
344
345
346
347
348
349 add_frame = Frame( frame2 )
350 self.AddNewRowButton = Button(add_frame, text="Add Row", width=8)
351 self.AddNewRowButton.pack(anchor=W, side=LEFT)
352 self.AddNewRowButton.bind("<ButtonRelease-1>", self.AddNewRowButton_Click)
353
354 self.AddNewColButton = Button(add_frame, text="Add Col", width=8)
355 self.AddNewColButton.pack(anchor=W, side=LEFT)
356 self.AddNewColButton.bind("<ButtonRelease-1>", self.AddNewColButton_Click)
357 add_frame.pack(anchor=W, side=TOP)
358
359
360 self.dup_widget_label_desc = Label(frame2, width=16)
361 self.dup_widget_label_desc["text" ] = "\nduplicate widget\nand its properties"
362 self.dup_widget_label_desc.pack(anchor=W)
363
364 self.dup_widget_label = Label(frame2, width=16)
365 self.dup_widget_label["text" ] = "\n\n"
366 self.dup_widget_label["font" ] = ("Courier", 8, "normal")
367 self.dup_widget_label["relief"] = "groove"
368 self.dup_widget_label.pack(anchor=W)
369 self.dup_widget_label_plain_bg = self.dup_widget_label["background"]
370 self.dup_widget_label["background"] = "#FFFACD"
371
372
373
374
375
376
377 def GeneralDebugButton_Click(self, event):
378 self.grid_notebook.repaint_all_labels()
379 self.refresh_preview_win()
380
381 def AddNewRowButton_Click(self, event):
382 self.grid_notebook.append_row()
383
384 def AddNewColButton_Click(self, event):
385 self.grid_notebook.append_column()
386
387
388 def PlaceAllWidgetsButton_Click(self, event):
389 """As debug tool, show all widgets in Notebook"""
390
391 saved_sel = self.MainWin.placementWidgetType_svar.get()
392 saved_tab = self.grid_notebook.current_tab_label()
393
394 row = 1
395 col = 1
396
397 self.grid_notebook.set_current_tab_by_label( "Main" )
398
399 for wname, wcolor in CONTROLS:
400 self.MainWin.placementWidgetType_svar.set( wname )
401 event.widget = self.grid_notebook.interface_gridBoxWidgetD[("Main", row, col)]
402 self.grid_notebook.onGridBoxClicked( event )
403
404 if wname in ContainerControlsL:
405 new_tab_name = wname + "_%i"%(CONTROL_NEXT_NUMBER_D[wname] -1,)
406 self.grid_notebook.set_current_tab_by_label( new_tab_name )
407
408
409 if wname == 'RadioGroup':
410 self.MainWin.placementWidgetType_svar.set( "Label" )
411 event.widget = self.grid_notebook.interface_gridBoxWidgetD[(new_tab_name, 2, 2)]
412 self.grid_notebook.onGridBoxClicked( event )
413
414 for n_radio in range(3):
415 self.MainWin.placementWidgetType_svar.set( "Radiobutton" )
416 event.widget = self.grid_notebook.interface_gridBoxWidgetD[(new_tab_name, 3+n_radio, 2)]
417 self.grid_notebook.onGridBoxClicked( event )
418
419
420 else:
421 self.MainWin.placementWidgetType_svar.set( "Button" )
422 event.widget = self.grid_notebook.interface_gridBoxWidgetD[(new_tab_name, 2, 2)]
423 self.grid_notebook.onGridBoxClicked( event )
424
425 self.MainWin.placementWidgetType_svar.set( "Label" )
426 event.widget = self.grid_notebook.interface_gridBoxWidgetD[(new_tab_name, 3, 2)]
427 self.grid_notebook.onGridBoxClicked( event )
428
429 self.MainWin.placementWidgetType_svar.set( "Entry" )
430 event.widget = self.grid_notebook.interface_gridBoxWidgetD[(new_tab_name, 4, 2)]
431 self.grid_notebook.onGridBoxClicked( event )
432
433
434 self.grid_notebook.set_current_tab_by_label( "Main" )
435
436
437 col += 1
438 if col % 5 == 0:
439 col = 1
440 row += 1
441
442
443 self.MainWin.placementWidgetType_svar.set( saved_sel )
444 self.grid_notebook.set_current_tab_by_label( saved_tab )
445
446 def set_status_msg(self, msg):
447 self.MainWin.statusMessage.set( msg )
448
449 def gray_out_listbox(self, omit_list=None):
450 """if omit_list is None, gray all."""
451 if omit_list is None:
452 omit_list = []
453
454 n = -1
455 for index, (wname, wcolor) in enumerate(CONTROLS):
456 if wname in omit_list:
457 self.Listbox_1.itemconfig(index, fg="black")
458 n = index
459 else:
460 self.Listbox_1.itemconfig(index, fg="gray")
461 self.Listbox_1.selection_clear(index)
462
463 if n >= 0:
464 self.Listbox_1.selection_set(n)
465 self.Listbox_1_Click( None )
466
467 def restore_black_listbox(self):
468 """Make sure all listbox options show up for all other tabs."""
469
470 n = 0
471 for i in self.Listbox_1.curselection():
472 n = i
473 break
474
475 for index, (wname, wcolor) in enumerate(CONTROLS):
476 self.Listbox_1.itemconfig(index, fg="black")
477 self.Listbox_1.selection_clear(index)
478
479 self.Listbox_1.selection_set(n)
480 self.Listbox_1_Click( None )
481
482 def select_preview_tab(self, tab_name_inp):
483
484 if not self.PreviewWin:
485 self.refresh_preview_win()
486
487 tab_comp = self.target_app.compObjD[tab_name_inp]
488 notebook_name = tab_comp.tab_label
489 nb_obj = self.target_app.compObjD[ notebook_name ]
490
491
492 for itab, (row, col, tab_name, tab_label) in enumerate( nb_obj.tab_nameL ):
493 if tab_name_inp == tab_name:
494 nb_obj.pw_widget.native_widget.select( itab )
495
496 break
497
498 def tab_of_notebook_changed(self, event):
499 nb = self.grid_notebook.notebook
500
501 text = nb.tab(nb.select(), "text")
502
503
504 self.Listbox_1.config( state=NORMAL )
505
506
507 if text.startswith('RadioGroup'):
508 self.gray_out_listbox( omit_list=("Radiobutton","Label") )
509
510 elif text.startswith('Notebook'):
511
512
513 self.gray_out_listbox( omit_list=None )
514 self.set_placement_widget_label( 'Tab' )
515 self.set_status_msg( "Only Tabs can be added to Notebook" )
516
517 else:
518
519 self.restore_black_listbox()
520
521
522 if text.startswith('Tab_'):
523 self.select_preview_tab( text )
524
525
526 def place_widget_selection_listbox(self, frame1):
527 """frame1 in topFrame contains Widgets selection ListBox"""
528
529 self.MainWin.placementWidgetType_svar=StringVar()
530 self.MainWin.placementWidgetType_svar.set('Button')
531
532
533
534 self.Listbox_1 = Listbox(frame1,width=15 ,height=str(len(CONTROLS)), selectmode='single')
535 self.Listbox_1.bind("<ButtonRelease-1>", self.Listbox_1_Click)
536
537 for wname, wcolor in CONTROLS:
538
539
540
541 self.Listbox_1.insert(END, wname)
542
543 self.Listbox_1.pack(anchor=W)
544 self.Listbox_1.select_set(0)
545
546 def cleanupOnQuit(self):
547
548 if self.target_app.model_has_changed():
549 dialog = maybe_save_dialog(self.MainWin, "Save Before Exit?")
550
551 if (dialog.result is not None) and ( dialog.result['save_file'] == "yes"):
552 self.saveasFile()
553 return
554 else:
555
556 self.target_app.reset_crc_reference()
557
558
559
560 self.MainWin.allow_subWindows_to_close = 1
561 self.MainWin.destroy()
562
563 def set_duplication_widget_label(self, label_obj):
564 """Given the widget Label object, set up for making duplicates."""
565
566 self.dup_widget_label["text" ] = label_obj["text"]
567 self.dup_widget_label["background"] = label_obj["background"]
568 self.dup_widget_label_desc["text" ] = "\nduplicate widget\nand its properties"
569
570 def set_placement_widget_label(self, widget_type):
571 """Sets dup_widget_label for a simple Place of widget_type."""
572
573 self.dup_widget_label["text" ] = "\n%s\n"%widget_type
574
575 self.dup_widget_label["background"] = CONTROL_COLOR_D[widget_type]
576 self.dup_widget_label_desc["text" ] = "\n\nPlace %s"%widget_type
577
578 self.grid_notebook.dup_source_widget_name = ''
579
580
581 def Listbox_1_Click(self, event):
582
583 val = 'Button'
584 for i in self.Listbox_1.curselection():
585 val = self.Listbox_1.get(i)
586 self.set_status_msg("Selected Widget: "+self.Listbox_1.get(i) )
587
588 self.MainWin.placementWidgetType_svar.set(val)
589
590 tab_label = self.grid_notebook.current_tab_label()
591 if not tab_label.startswith('Notebook'):
592
593 self.set_placement_widget_label( val )
594
595 def hideOkChkBox_Callback(self, varName, index, mode):
596
597
598 try:
599 self.target_app.setSpecialOption('hideokbutton', self.MainWin.hideOkChkBox_StringVar.get())
600 except:
601 pass
602
603 if self.MainWin.hideOkChkBox_StringVar.get() == "yes":
604 self.PreviewWin.remove_mock_OK_Cancel_Buttons()
605 else:
606 self.PreviewWin.add_mock_OK_Cancel_Buttons()
607
608 def menuChkBox_Callback(self, varName, index, mode):
609
610
611 try:
612 self.target_app.setSpecialOption('hasmenu', self.MainWin.menuChkBox_StringVar.get())
613
614 except:
615 print('WARNING... Failed To Properly Set "hasmenu" Option.')
616
617 if not self.in_reading_mode:
618 if self.MainWin.menuChkBox_StringVar.get()=='yes' and self.target_app:
619 dialog = Menumaker(self.MainWin, "Define Menu Structure",
620 self.target_app.getSpecialOption('menu'))
621
622
623 if type(dialog.result) == type({}):
624
625 add_menu_ctrl_keys = dialog.result.get('add_menu_ctrl_keys','yes')
626 self.target_app.setSpecialOption('add_menu_ctrl_keys', add_menu_ctrl_keys)
627
628 menuStr = dialog.result.get('menu','').strip()
629 if len( menuStr ) > 0:
630 self.target_app.setSpecialOption('menu',menuStr)
631
632
633
634 if not self.PreviewWin:
635 self.refresh_preview_win()
636
637
638 if self.MainWin.menuChkBox_StringVar.get()=='no' and self.target_app:
639 if (self.PreviewWin is not None):
640 if self.PreviewWin.menuBar:
641 self.PreviewWin.delete_menu()
642
643
644 if self.MainWin.menuChkBox_StringVar.get()=='yes' and self.target_app:
645 if (self.PreviewWin is not None):
646 if self.PreviewWin.menuBar:
647 self.PreviewWin.delete_menu()
648
649 menuL = buildMenuSource( self.target_app.getSpecialOption( 'menu' ) )
650 menuSrcL = getMenuSource( menuL, rootName='self' )
651
652 self.PreviewWin.add_menu( menuSrcL )
653
654 self.refresh_preview_win()
655
656
657 def statusBarChkBox_Callback(self, varName, index, mode):
658
659
660 try:
661 self.target_app.setSpecialOption('hasstatusbar', self.MainWin.statusBarChkBox_StringVar.get())
662 except:
663 pass
664
665 if not self.PreviewWin:
666 self.refresh_preview_win()
667
668
669 if self.MainWin.statusBarChkBox_StringVar.get()=='yes' and self.target_app:
670 if (self.PreviewWin is not None):
671 if not self.PreviewWin.statusbar:
672 self.PreviewWin.add_mock_statusbar()
673
674
675 if self.MainWin.statusBarChkBox_StringVar.get()=='no' and self.target_app:
676 if (self.PreviewWin is not None):
677 if self.PreviewWin.statusbar:
678 self.PreviewWin.remove_mock_statusbar()
679
680 self.refresh_preview_win()
681
682 def resizableChkBox_Callback(self, varName, index, mode):
683
684
685 try:
686 self.target_app.setSpecialOption('resizable', self.MainWin.resizableChkBox_StringVar.get())
687 except:
688 pass
689
690 self.refresh_preview_win()
691
692
693 def ColorPickButton_Click(self, event):
694 self.ColorPickButton_Select()
695
696 def ColorPickButton_Select(self):
697 self.set_status_msg('Place Selected Color on Clipboard')
698 ctup,cstr = tkinter.colorchooser.askcolor(title='Place Selected Color on Clipboard')
699 if cstr != None:
700 self.set_status_msg('%s is on Clipboard'%cstr)
701 self.ColorPickButton.clipboard_clear()
702 self.ColorPickButton.clipboard_append(cstr)
703
704
705
706 def FontPickButton_Click(self, event):
707 self.FontPickButton_Select()
708
709 def FontPickButton_Select(self):
710 self.set_status_msg('Place Selected Font on Clipboard')
711 font = askfont(self.root)
712 if font:
713
714 font['family'] = font['family'].replace(' ', '\ ')
715 font_str = "%(family)s %(size)i %(weight)s %(slant)s" % font
716 if font['underline']:
717 font_str += ' underline'
718 if font['overstrike']:
719 font_str += ' overstrike'
720
721 self.set_status_msg('%s is on Clipboard'%font_str)
722 self.ColorPickButton.clipboard_clear()
723 self.ColorPickButton.clipboard_append(font_str)
724
725
726
727
728 def Help(self):
729
730 usage = """
731
732 Basic Usage:
733 Select Widget in Listbox with Left Click.
734 Place Widget with Left Click in grid.
735
736 Edit Widget:
737 Right Click Widget in Grid or Preview Window.
738
739 Move Widget:
740 Left Button Drag and Drop in Grid.
741
742 Duplicate Widget:
743 Left Click Widget in Grid.
744 Left Click in grid to place the duplicate.
745
746 Insert Row or Column with Left Click on "+" control.
747
748 Add Weight to row or column with "wt" control.
749
750 Select Corresponding Tab for Widgets in Frames, RadioGroups etc.
751 """
752
753 tkinter.messagebox.showinfo(
754 "Help for TkGridGUI",
755 usage)
756
757 def About(self):
758 tkinter.messagebox.showinfo(
759 "About TkGridGUI",
760 "TkGridGUI is:\n\n"+\
761 "A quick approach to\n"+\
762 "building Tkinter applications.\n"+\
763 "Written by Charlie Taylor\n"
764 )
765
766 def newForm(self):
767
768
769 if self.target_app.model_has_changed():
770 dialog = maybe_save_dialog(self.MainWin, "Save Current File?")
771
772 if (dialog.result is not None) and ( dialog.result['save_file'] == "yes" ):
773 self.saveasFile()
774 return
775
776 self.current_fileFullName = ''
777 self.current_filePath = ''
778 self.current_fileName = ''
779
780 self.MainWin.title( 'TkGridGUI: ' + self.current_fileName )
781
782 if self.PreviewWin:
783 self.PreviewWin.delete_menu()
784 self.PreviewWin.remove_mock_statusbar()
785
786 self.target_app.reinitialize()
787 self.grid_notebook.initialize_NotebookGridDes()
788 self.grid_notebook.notebook.bind("<<NotebookTabChanged>>", self.tab_of_notebook_changed)
789
790 self.refresh_preview_win()
791
792
793 self.target_app.reset_crc_reference()
794
795
796 def openFile(self, fName=None):
797
798
799 if self.target_app.model_has_changed():
800 dialog = maybe_save_dialog(self.MainWin, "Save Current File?")
801
802 if (dialog.result is not None) and (dialog.result['save_file'] == "yes"):
803 self.saveasFile()
804 return
805 else:
806
807 self.target_app.reset_crc_reference()
808
809
810 self.in_reading_mode = True
811 if fName is None:
812 filetypes = [
813 ('tkGridGUI definition','*.def'),
814 ('Any File','*.*')]
815 self.pathopen = tkinter.filedialog.askopenfilename(parent=self.MainWin, title='Open tkGridGUI file',
816 filetypes=filetypes)
817
818 else:
819 self.pathopen = os.path.abspath(fName)
820
821 if self.pathopen:
822
823 self.newForm()
824
825 full_fname = os.path.abspath( self.pathopen )
826 head,tail = os.path.split( full_fname )
827
828 self.current_fileFullName = full_fname
829 self.current_filePath = head
830 self.current_fileName = tail
831
832 self.target_app.readAppDefFile( self.pathopen )
833
834
835 self.MainWin.menuChkBox_StringVar.set( self.target_app.getSpecialOption( 'hasmenu' ) )
836
837
838 self.MainWin.statusBarChkBox_StringVar.set( self.target_app.getSpecialOption( 'hasstatusbar' ) )
839
840
841 self.MainWin.resizableChkBox_StringVar.set( self.target_app.getSpecialOption( 'resizable' ) )
842
843
844 self.MainWin.hideOkChkBox_StringVar.set( self.target_app.getSpecialOption( 'hideokbutton' ) )
845
846
847 self.MainWin.mainOrDialog.set( self.target_app.getSpecialOption( 'guitype' ) )
848
849
850 self.MainWin.stdDialMessChkBox_StringVar.set( self.target_app.getSpecialOption( 'hasstddialmess' ) )
851
852
853 self.MainWin.stdDialColorChkBox_StringVar.set( self.target_app.getSpecialOption( 'hasstddialcolor' ) )
854
855
856 self.MainWin.stdDialFileChkBox_StringVar.set( self.target_app.getSpecialOption( 'hasstddialfile' ) )
857
858
859 self.MainWin.stdAlarmChkBox_StringVar.set( self.target_app.getSpecialOption( 'hasstdalarm' ) )
860
861
862
863
864
865 widgetL = [(c.widget_type, widget_name, c.tab_label, c.row, c.col) for widget_name,c in list(self.target_app.compObjD.items())]
866 self.grid_notebook.set_complete_list_of_widgets( widgetL )
867
868 if not self.PreviewWin:
869 self.refresh_preview_win()
870
871
872 if self.MainWin.menuChkBox_StringVar.get()=='yes' and self.target_app:
873 if (self.PreviewWin is not None):
874 if self.PreviewWin.menuBar:
875 self.PreviewWin.delete_menu()
876
877 menuL = buildMenuSource( self.target_app.getSpecialOption( 'menu' ) )
878 menuSrcL = getMenuSource( menuL, rootName='self' )
879
880 self.PreviewWin.add_menu( menuSrcL )
881
882
883
884 if self.MainWin.statusBarChkBox_StringVar.get()=='yes' and self.target_app:
885 if (self.PreviewWin is not None):
886 if not self.PreviewWin.statusbar:
887 self.PreviewWin.add_mock_statusbar()
888
889 if self.PreviewWin:
890 w = self.target_app.getSpecialOption( 'width' )
891 h = self.target_app.getSpecialOption( 'height' )
892 x = self.target_app.getSpecialOption( 'x' )
893 y = self.target_app.getSpecialOption( 'y' )
894
895 if self.PreviewWin.statusbar:
896 y += 30
897
898 self.PreviewWin.geometry( '%ix%i+%i+%i'%(w,h,x,y))
899
900 self.PreviewWin.update_idletasks()
901
902 self.MainWin.title( 'TkGridGUI: ' + self.current_fileName )
903
904 self.target_app.reset_crc_reference()
905
906 self.in_reading_mode = False
907
908 self.refresh_preview_win()
909
910 self.grid_notebook.notebook.bind("<<NotebookTabChanged>>", self.tab_of_notebook_changed)
911
912
913
914 def saveasFile(self):
915
916 self.set_status_msg('Save File to Disk')
917
918 filetypes = [
919 ('TkGridGUI','*.def'),
920 ('Any File','*.*')]
921
922 if self.current_fileName:
923 fname = self.current_fileName
924 else:
925 fname = ''
926
927
928 fsave = tkinter.filedialog.asksaveasfilename(parent=self.MainWin, title='Saving TkGridGUI Definition File',
929 initialfile=fname, filetypes=filetypes)
930
931 if fsave:
932 if not fsave.lower().endswith('.def'):
933 fsave += '.def'
934
935 full_fname = os.path.abspath( fsave )
936 head,tail = os.path.split( full_fname )
937
938 self.current_fileFullName = full_fname
939 self.current_filePath = head
940 self.current_fileName = tail
941
942
943
944
945 self.target_app.setSpecialOption( 'hasmenu', self.MainWin.menuChkBox_StringVar.get() )
946
947
948 self.target_app.setSpecialOption( 'hasstatusbar' , self.MainWin.statusBarChkBox_StringVar.get() )
949
950
951 self.target_app.setSpecialOption( 'resizable', self.MainWin.resizableChkBox_StringVar.get() )
952
953
954 self.target_app.setSpecialOption( 'guitype', self.MainWin.mainOrDialog.get() )
955
956
957 self.target_app.setSpecialOption( 'hideokbutton', self.MainWin.hideOkChkBox_StringVar.get() )
958
959
960 self.target_app.setSpecialOption( 'hasstddialmess', self.MainWin.stdDialMessChkBox_StringVar.get() )
961
962
963 self.target_app.setSpecialOption( 'hasstddialcolor', self.MainWin.stdDialColorChkBox_StringVar.get() )
964
965
966 self.target_app.setSpecialOption( 'hasstddialfile', self.MainWin.stdDialFileChkBox_StringVar.get() )
967
968
969 self.target_app.setSpecialOption( 'hasstdalarm', self.MainWin.stdAlarmChkBox_StringVar.get() )
970
971
972 if self.target_app.saveAppDefFile( savePathName=self.current_fileFullName ):
973
974
975 self.MainWin.title( 'TkGridGUI: ' + self.current_fileName )
976
977 sf = FormSource( self.target_app, self.MainWin, self )
978 sf.saveToFile()
979
980
981 self.set_status_msg('Saved File: "%s"'%self.current_fileName)
982
983 self.target_app.reset_crc_reference()
984
985 else:
986 self.set_status_msg("WARNING... *.def file save failed. NO SAVE PERFORMED.")
987
988
989 def main():
990
991 root = Tk()
992 MainWin = root
993 MainWin.title('Main Window')
994
995 MainWin.config(background='#FFFACD')
996
997 grid_gui = GridGUI( MainWin )
998
999 MainWin.mainloop()
1000
1001 if __name__=="__main__":
1002
1003 main()