make_py_src.py


directory : D:\2018_py_proj\TkGridGUI\tkgridgui
Line Count : 373
Line Clip Size : No Clipping

tab_of_notebook_changed  Word MatchCase (0) 
1 #!/usr/bin/env python 2 # -*- coding: ascii -*- 3 from __future__ import print_function 4 from __future__ import unicode_literals 5 6 from builtins import object 7 from tkgridgui.src_templates import * 8 import tkgridgui.SourceCode as SourceCode 9 import tkgridgui.make_menu_src as make_menu_src 10 #from tkgridgui.src_templates import legalPythonIdentifier 11 from tkgridgui.comp_tree import CNode, ComponentTree 12 from tkgridgui.component_src_gen import CompSrcGen 13 14 class FormSource( object ): 15 16 def __init__(self, target_app, MainWin, grid_gui): 17 self.target_app = target_app 18 self.MainWin = MainWin 19 self.grid_gui = grid_gui 20 21 if self.MainWin.mainOrDialog.get() == "dialog": 22 self.pyFile = grid_gui.current_fileFullName[:-4] + '_Dialog.py' 23 self.imADialog = 1 24 else: 25 self.pyFile = grid_gui.current_fileFullName[:-3] + 'py' 26 self.imADialog = 0 27 self.sourceFile = SourceCode.SourceFile( self.pyFile ) 28 self.getClassAndInit() 29 30 def saveToFile(self): 31 self.sourceFile.saveToFile() 32 33 def getClassAndInit(self): 34 35 # make class statement and top of __init__ 36 w = self.target_app.app_attrD['width'] 37 h = self.target_app.app_attrD['height'] 38 name = '_'+self.target_app.app_attrD['name'] # add underscore to beginning (preclude name collision) 39 40 #self.importSectionL = ['from Tkinter import *\n'] 41 42 # include standard dialog imports if flags are set. 43 self.importSectionL = [ get_top_imports( self.MainWin.stdDialMessChkBox_StringVar.get()=='yes', 44 self.MainWin.stdDialFileChkBox_StringVar.get()=='yes', 45 self.MainWin.stdDialColorChkBox_StringVar.get()=='yes') ] 46 47 self.classInitUserSectionL = [] 48 49 if self.imADialog: 50 if self.MainWin.hideOkChkBox_StringVar.get()=="yes": 51 self.classInitL = [beginDialogSourceFile(name, 1, w, h, self.target_app.tkOptionD)] 52 else: 53 self.classInitL = [beginDialogSourceFile(name, 0, w, h, self.target_app.tkOptionD)] 54 55 # don't let the widow be too small 56 if w<=300 and h<=200: 57 self.classInitL.append(' self.geometry("300x200")\n' ) 58 else: 59 self.classInitL = [beginSourceFile(name, w, h, self.target_app.tkOptionD)] 60 61 # don't let the widow be too small 62 if w<=300 and h<=200: 63 self.classInitL.append(' self.master.geometry("300x200")\n' ) 64 65 self.classInitL.append(' self.master.title("%s")\n'%(self.target_app.app_attrD['name'],)) 66 67 guiType = self.MainWin.mainOrDialog.get() 68 69 # make end code while name is right 70 if guiType == "dialog": 71 self.endCode = endDialogSourceFile(name) 72 else: 73 self.endCode = endSourceFile(name) 74 75 # dictionary of radio groups (need to detect and assign groups to single StringVar) 76 radio_group_D = {} 77 # ===================================================================================== 78 # sort widgets into parent dependency and alphabetical order 79 80 ct = ComponentTree() 81 for widget_name, c in list(self.target_app.compObjD.items()): 82 ct.add_node( CNode(widget_name, c.tab_label, c) ) 83 84 cnodeL = ct.get_ordered_components() 85 dependency_sorted_compL = [] 86 for cn in cnodeL: 87 c = cn.component 88 dependency_sorted_compL.append( (c.widget_type, c.widget_name, c) ) 89 90 91 # create list of source gen components 92 comp_srcgenL = [] 93 rg_svarL = [] # any radio group StringVar 94 makeL = [] # all the make calls for Widgets 95 for widget_type, widget_name, comp in dependency_sorted_compL: 96 97 c = CompSrcGen(widget_name, widget_type, guiType, 98 comp.tab_label, comp.row, comp.col, comp.user_tkOptionD, 99 target_app=self.target_app) 100 101 if comp.widget_type == "Radiobutton": 102 if comp.tab_label.startswith('RadioGroup'): 103 gName = comp.tab_label 104 else: 105 gName = 'RG_' + comp.tab_label # if not explicitly in a RadioGroup, assign to tab_label group 106 107 # set CompSrcGen StringVar name to common RadioGroup 108 c.svar_name = gName + '_StringVar' 109 110 # only create one callback routine for all of the radio buttons in the group 111 if gName not in radio_group_D: 112 radio_group_D[ gName ] = comp.widget_name.split('_')[-1] # set to 1st encountered 113 114 rg_svarL.append( ' self.%s_StringVar = StringVar()\n'%gName ) 115 116 comp_srcgenL.append( c ) # a list of all CompSrcGen objects 117 118 makeL.append( c.get_call_make_stmt() ) 119 120 if rg_svarL: 121 self.classInitL.append('\n') 122 self.classInitL.extend( rg_svarL ) 123 124 self.classInitL.append('\n') 125 self.classInitL.extend( makeL ) 126 self.classInitL.append('\n') 127 128 # add any columnconfigure(col, weight=wt) or rowconfigure(row, weight=wt) 129 wts_rowD, wts_colD = self.target_app.get_a_full_desc_of_weights() 130 131 for (tab_label, row_target), wt in list(wts_rowD.items()): 132 #print('Need to Row configure ',(tab_label, row_target),' to ',wt) 133 self.classInitL.append( createWeightStatement(guiType, tab_label, True, row_target, wt) ) 134 135 for (tab_label, col_target), wt in list(wts_colD.items()): 136 #print('Need to Column configure ',(tab_label, col_target),' to ',wt) 137 self.classInitL.append( createWeightStatement(guiType, tab_label, False, col_target, wt) ) 138 139 # if not resizable, set resizable to NO 140 if self.MainWin.resizableChkBox_StringVar.get()=='no': 141 if self.imADialog: 142 self.classInitL.append(' self.resizable(0,0) # Linux may not respect this\n') 143 else: 144 self.classInitL.append(' self.master.resizable(0,0) # Linux may not respect this\n') 145 self.classInitL.append('\n') 146 147 148 # ====================================================================================== 149 150 # add a status bar if desired 151 if self.MainWin.statusBarChkBox_StringVar.get()=='yes': 152 if self.imADialog: 153 self.classInitL.append( getDialogStatusBarSource() ) 154 else: 155 self.classInitL.append( getStatusBarSource() ) 156 157 self.classInitL.append('\n') 158 appName = self.target_app.app_attrD['name'] 159 self.classInitUserSectionL.append(' self.statusMessage.set("Welcome to %s")\n'%appName) 160 self.classInitUserSectionL.append('\n') 161 162 # import section is placed 1st 163 self.sourceFile.addSection('imports', self.importSectionL, defaultUserCodeL='# Place any user import statements here\n\n') 164 # place top_of_init sections of code 165 166 # any RadioGroup StringVar should be set 167 for gName,gValue in list(radio_group_D.items()): 168 self.classInitL.append( ' self.%s.set("%s")\n'%(gName+ '_StringVar', gValue) ) 169 170 self.classInitL.append( ' self.%s_StringVar_traceName = self.%s_StringVar.trace_variable("w", self.%s_StringVar_Callback)\n'%\ 171 (gName, gName, gName)) 172 173 # put Menu info in 174 if self.MainWin.menuChkBox_StringVar.get()=='yes': 175 self.classInitL.append('\n') 176 menuL = make_menu_src.buildMenuSource( self.target_app.getSpecialOption('menu') ) 177 178 add_ctrl_keys = self.target_app.getSpecialOption('add_menu_ctrl_keys') == 'yes' 179 menuSrcL = make_menu_src.getMenuSource( menuL, rootName='master', imADialog=self.imADialog, 180 add_ctrl_keys=add_ctrl_keys) 181 182 183 self.classInitL.extend( menuSrcL ) 184 185 #genCodeL = menuSrcL 186 #defaultUserCodeL = [] 187 #self.sourceFile.addSection('menuStructure', genCodeL, defaultUserCodeL=defaultUserCodeL) 188 189 190 191 self.sourceFile.addSection('top_of_init', self.classInitL, defaultUserCodeL=self.classInitUserSectionL) 192 193 # add make widget routines 194 for c in comp_srcgenL: # a list of all CompSrcGen objects 195 self.sourceFile.addSection( 'make_%s'%c.widget_name, c.get_top_of_make_def(), 196 defaultUserCodeL=c.get_user_part_of_make_def() ) 197 198 # add any bind routines 199 for c in comp_srcgenL: # a list of all CompSrcGen objects 200 topL = c.get_top_of_bind_def() 201 if topL: 202 methodName = c.get_click_name() 203 self.sourceFile.addSection( methodName, topL, 204 defaultUserCodeL=c.get_user_part_of_bind_def() ) 205 206 # add any StringVar trace routines 207 for c in comp_srcgenL: # a list of all CompSrcGen objects 208 if c.widget_type != "Radiobutton": # Radiobutton done by RadioGroup 209 topL = c.get_top_of_trace_def() 210 if topL: 211 methodName = c.get_trace_name() 212 self.sourceFile.addSection( methodName, topL, 213 defaultUserCodeL=c.get_user_part_of_trace_def() ) 214 215 # any RadioGroup StringVar need Callback method 216 for gName,gValue in list(radio_group_D.items()): 217 mock_radio = CompSrcGen(gName, 'Radiobutton', guiType, 218 "Main", 1, 1, {}, target_app=self.target_app) 219 # widget_name, widget_type, guiType, 220 # parent_frame, row, col, opDict=None, target_app=None): 221 mock_radio.svar_name = gName + '_StringVar' 222 223 topL = mock_radio.get_top_of_trace_def() 224 if topL: 225 methodName = mock_radio.get_trace_name() 226 self.sourceFile.addSection( methodName, topL, 227 defaultUserCodeL=mock_radio.get_user_part_of_trace_def() ) 228 229 230 if self.MainWin.menuChkBox_StringVar.get()=='yes': 231 def addMenuToSource( mItem ): 232 for s in mItem.subLabelL: 233 genCodeL = [] 234 defaultUserCodeL = [] 235 if s.lenSubmenu()==0: 236 name = legalPythonIdentifier('menu_%s_%s'%(mItem.label, s.label)) 237 genCodeL.append(' def %s(self):\n'%name) 238 genCodeL.append(' pass\n') 239 defaultUserCodeL.append(' # replace, delete, or comment-out the following\n') 240 241 if self.MainWin.statusBarChkBox_StringVar.get()=='yes': 242 defaultUserCodeL.append(' self.statusMessage.set("called %s")\n'%name) 243 244 defaultUserCodeL.append(' print( "called %s" )\n\n'%name) 245 self.sourceFile.addSection(name, genCodeL, defaultUserCodeL=defaultUserCodeL) 246 else: 247 addMenuToSource( s ) 248 249 for mItem in menuL: 250 addMenuToSource( mItem ) 251 252 if mItem.lenSubmenu()==0: 253 genCodeL = [] 254 defaultUserCodeL = [] 255 name = legalPythonIdentifier('menu_%s'%(mItem.label)) 256 genCodeL.append(' def %s(self):\n'%name) 257 genCodeL.append(' pass\n') 258 defaultUserCodeL.append(' # replace, delete, or comment-out the following\n') 259 260 if self.MainWin.statusBarChkBox_StringVar.get()=='yes': 261 defaultUserCodeL.append(' self.statusMessage.set("called %s")\n'%name) 262 defaultUserCodeL.append(' print( "called %s" )\n\n'%name) 263 264 self.sourceFile.addSection(name, genCodeL, defaultUserCodeL=defaultUserCodeL) 265 266 267 268 269 # standard message dialogs 270 if self.MainWin.stdDialMessChkBox_StringVar.get()=='yes': 271 genCodeL = [getStandardMessageDialogs()] 272 defaultUserCodeL = [] 273 self.sourceFile.addSection('standard_message_dialogs', genCodeL, defaultUserCodeL=defaultUserCodeL) 274 # standard file dialogs 275 if self.MainWin.stdDialFileChkBox_StringVar.get()=='yes': 276 genCodeL = [getStandardFileDialogs()] 277 defaultUserCodeL = [] 278 self.sourceFile.addSection('standard_file_dialogs', genCodeL, defaultUserCodeL=defaultUserCodeL) 279 # color dialog 280 if self.MainWin.stdDialColorChkBox_StringVar.get()=='yes': 281 genCodeL = [getStandardColorDialog()] 282 defaultUserCodeL = [] 283 self.sourceFile.addSection('standard_color_dialog', genCodeL, defaultUserCodeL=defaultUserCodeL) 284 # alarm logic 285 if self.MainWin.stdAlarmChkBox_StringVar.get()=='yes': 286 genCodeL = [getStandardAlarmDialog()] 287 defaultUserCodeL = [' print( "Alarm called" )\n'] 288 self.sourceFile.addSection('standard_alarm', genCodeL, defaultUserCodeL=defaultUserCodeL) 289 290 291 # if making a dialog, need to put in user-editable validate function 292 if guiType == "dialog": 293 genCodeL = [getDialogValidate()] 294 genCodeL.append('\n') 295 296 svar_set = set() 297 for c in comp_srcgenL: # a list of all CompSrcGen objects 298 if c.svar_name: 299 if c.svar_name not in svar_set:# only do each StringVar once. 300 if c.widget_type == "Radiobutton": 301 name = c.svar_name.replace("_StringVar","") # want group name, not individual radio button name 302 else: 303 name = c.widget_name 304 305 genCodeL.append( ' self.result["%s"] = self.%s.get()\n'%(name, c.svar_name) ) 306 svar_set.add( c.svar_name ) # remember this StringVar is done. 307 genCodeL.append('\n') 308 309 310 defaultUserCodeL = [' # set values in "self.result" dictionary for return\n', 311 ' # for example...\n', 312 ' # self.result["age"] = self.Entry_2_StringVar.get() \n\n', 313 ' self.result["test"] = "test message" \n', 314 ' return 1\n'] 315 self.sourceFile.addSection('dialog_validate', genCodeL, defaultUserCodeL=defaultUserCodeL) 316 317 #self.topCode = ''.join(self.classInitL) 318 self.sourceFile.addSection('end',self.endCode, allowUserCode=0) 319 320 321 if __name__ == '__main__': 322 import os 323 from tkgridgui.target_tk_app_def import TargetTkAppDef 324 325 target_app = TargetTkAppDef( 'myTestApp' ) 326 327 target_app.maybe_add_component( widget_type="Button", widget_name="Button_1", tab_label="Main", 328 row=1, col=1) 329 target_app.maybe_add_component( widget_type="Entry", widget_name="Entry_1", tab_label="Main", 330 row=2, col=1) 331 target_app.maybe_add_component( widget_type="Text", widget_name="Text_1", tab_label="Main", 332 row=3, col=1) 333 334 class GetFunc( object ): 335 def __init__(self, const): 336 self.const = const 337 def get(self): 338 return self.const 339 340 class MockMainWin( object ): 341 def __init__(self): 342 343 if 0: 344 self.mainOrDialog = GetFunc( "main" ) 345 self.menuChkBox_StringVar = GetFunc( "yes" ) 346 self.hideOkChkBox_StringVar = GetFunc( "yes" ) 347 else: 348 self.mainOrDialog = GetFunc( "dialog" ) 349 self.menuChkBox_StringVar = GetFunc( "no" ) 350 self.hideOkChkBox_StringVar = GetFunc( "no" ) 351 352 self.stdDialMessChkBox_StringVar = GetFunc( "yes" ) 353 self.stdDialFileChkBox_StringVar = GetFunc( "yes" ) 354 self.statusBarChkBox_StringVar = GetFunc( "yes" ) 355 self.stdDialColorChkBox_StringVar = GetFunc( "yes" ) 356 self.stdAlarmChkBox_StringVar = GetFunc( "yes" ) 357 self.resizableChkBox_StringVar = GetFunc( "yes" ) 358 359 class MockGridGUI( object ): 360 def __init__(self): 361 full_fname = os.path.abspath( "./mock.def" ) 362 head,tail = os.path.split( full_fname ) 363 364 self.current_fileFullName = full_fname 365 self.current_filePath = head 366 self.current_fileName = tail 367 368 sf = FormSource( target_app, MockMainWin(), MockGridGUI() ) 369 sf.saveToFile() 370 371 print() 372 #print( sf.topCode ) 373 #print( sf.endCode )