make_menu_src.py
directory : D:\2018_py_proj\TkGridGUI\tkgridgui
Line Count : 293
Line Clip Size : No Clipping
tab_of_notebook_changed Word MatchCase (0)
1
2
3 from __future__ import print_function
4 from __future__ import unicode_literals
5
6 from builtins import range
7 from builtins import object
8 from tkgridgui.src_templates import legalPythonIdentifier, letters, digits
9 sampleMenuStr='''
10 File
11 New
12 Worksheet
13 Text File
14 Open
15 Save
16
17 Exit
18 Edit
19 Find
20 Copy
21 Cut
22 Paste
23 '''
24
25 class myMenuItem( object ):
26
27 def __init__(self, label):
28 self.label = label
29 self.subLabelL = []
30 self.parent = None
31 self.underline = -1
32 self.ctrl_char = ''
33
34 def addSubItem(self, subItem):
35 self.subLabelL.append( subItem )
36 subItem.parent = self
37 def lenSubmenu(self):
38 return len(self.subLabelL)
39
40 def getSubItemAtLevel(self, N):
41 m = self
42 for i in range(N-1):
43 if len(m.subLabelL)>0:
44 m = m.subLabelL[-1]
45 return m
46
47 def make_ctrl_key(self, taken_uc_charL):
48 """taken_uc_charL is the list of upper case characters already taken by other myMenuItem objects"""
49
50
51 if len(self.subLabelL) > 0:
52 for s in self.subLabelL:
53 s.make_ctrl_key( taken_uc_charL )
54 else:
55 for ic,c in enumerate( self.label ):
56 c = c.upper()
57 if c in letters:
58 if c not in taken_uc_charL:
59 self.underline = ic
60 self.ctrl_char = c
61 taken_uc_charL.append( c )
62 return
63
64 for ic,d in enumerate(digits):
65 if d not in taken_uc_charL:
66 self.underline = id
67 self.ctrl_char = d
68 taken_uc_charL.append( d )
69 return
70
71
72 def printSum(self):
73
74 sSubs = ''
75 for sub in self.subLabelL:
76 sSubs += sub.label + ' -- '
77
78 print( '------------ start -----------------' )
79 print( '"%s"'%self.label, 'len list =',len(self.subLabelL),sSubs )
80 print( '------------- end -----------------' )
81 for sub in self.subLabelL:
82 sub.printSum()
83 print( '----' )
84
85 def numIndentSpaces( s ):
86 return len(s) - len(s.lstrip())
87
88 def buildMenuSource( descStr ):
89
90
91
92
93 descL = descStr.split('\n')
94
95
96 for i in range( len(descL)-1, -1, -1):
97 if descL[i].strip() != '':
98 break
99 del descL[i]
100
101 for i in range( len(descL)):
102 if descL[i].strip() != '':
103 break
104 del descL[i]
105
106
107
108
109
110 if len(descL)==0:
111 return ''
112
113 i = 0
114 nspaceLast = numIndentSpaces( descL[0] )
115 indentL = []
116 for label in descL:
117
118
119 if label.strip() == '':
120 nspace = nspaceLast
121 else:
122 nspace = numIndentSpaces( label )
123
124 if nspace > nspaceLast:
125 i += 1
126 elif nspace < nspaceLast:
127 i -= 1
128
129 if i<0: i=0
130 indentL.append( [i,label.strip()] )
131 nspaceLast = nspace
132
133
134
135
136
137 menuL = []
138 for N,label in indentL:
139 m = myMenuItem(label)
140 if N==0:
141 menuL.append(m)
142 else:
143 try:
144 mtop = menuL[-1]
145 madd = mtop.getSubItemAtLevel(N)
146 madd.addSubItem(m)
147 except:
148 menuL.append(m)
149
150
151
152
153 return menuL
154
155 sMenuBar = ' self.menuBar = Menu(%s, relief = "raised", bd=2)\n'
156 sMenu = '\n top_%s = Menu(self.menuBar, tearoff=0)\n'
157 sItem = ' top_%s.add("command", label = "%s", command = self.%s)\n'
158 sItemAcc = ' top_%s.add("command", label = "%s", command=self.%s, underline=%i, accelerator="Ctrl+%s")\n'
159
160 sSpacer = ' top_%s.add_separator()\n'
161 sCascade = ' self.menuBar.add("cascade", label="%s", menu=top_%s)\n'
162 sCascade2= ' top_%s.add("cascade", label="%s", menu=top_%s)\n'
163 sMenuConfig = '\n %s.config(menu=self.menuBar)\n'
164 def getSubmenuSource( mItem ):
165 topName = legalPythonIdentifier( mItem.label )
166 sL = [sMenu%topName]
167 bindL = []
168
169 for s in mItem.subLabelL:
170 if s.lenSubmenu()==0:
171 if s.label.strip() != '':
172 name = 'menu_%s_%s'%(mItem.label, s.label)
173 name = legalPythonIdentifier( name )
174 if s.ctrl_char:
175 sL.append(sItemAcc%(topName, s.label, name, s.underline, s.ctrl_char))
176 bindL.append(' self.master.bind("<Control-%s>", lambda event: self.%s())\n'%(s.ctrl_char, name) )
177 bindL.append(' self.master.bind("<Control-%s>", lambda event: self.%s())\n'%(s.ctrl_char.lower(), name) )
178 else:
179 sL.append(sItem%(topName, s.label, name))
180 else:
181 sL.append(sSpacer%topName)
182 else:
183 s2L, b2L = getSubmenuSource(s)
184 sL.extend( s2L )
185 bindL.extend( b2L )
186
187 if mItem.parent:
188 topNameParent = legalPythonIdentifier( mItem.parent.label )
189 sL.append(sCascade2%(topNameParent, mItem.label, topName))
190 else:
191 sL.append(sCascade%(mItem.label, topName))
192 return sL, bindL
193
194
195 def getMenuSource( menuL, rootName='MainWin', add_ctrl_keys=True, imADialog=False ):
196
197 if imADialog:
198 srcList = [sMenuBar%'self']
199 else:
200 srcList = [sMenuBar%rootName]
201
202 bindL = [' # use both upper and lower characters for keyboard accelerator options.\n']
203
204 if add_ctrl_keys:
205 taken_uc_charL = []
206 for m in menuL:
207 m.make_ctrl_key( taken_uc_charL )
208
209 for m in menuL:
210
211 if m.lenSubmenu()>0:
212 s2L, b2L = getSubmenuSource(m)
213 srcList.extend( s2L )
214 bindL.extend( b2L )
215 else:
216 name = 'menu_%s'%(legalPythonIdentifier( m.label ))
217 if m.ctrl_char:
218 sTopItem= ' self.menuBar.add("command", label = "%s", command=self.%s, underline=%i, accelerator="Ctrl+%s")\n'
219 srcList.append( sTopItem%( m.label, name, m.underline, m.ctrl_char) )
220 bindL.append(' self.master.bind("<Control-%s>", lambda event: self.%s())\n'%(m.ctrl_char, name) )
221 bindL.append(' self.master.bind("<Control-%s>", lambda event: self.%s())\n'%(m.ctrl_char.lower(), name) )
222 else:
223 sTopItem= ' self.menuBar.add("command", label = "%s", command = self.%s)\n'
224 srcList.append( sTopItem%( m.label, name) )
225
226 if imADialog:
227 srcList.append( sMenuConfig%'self' )
228 else:
229 srcList.append( sMenuConfig%rootName )
230
231 srcList.append('\n\n')
232
233 if imADialog:
234 target = 'self.' + rootName
235 bindL = [b.replace(target,'self') for b in bindL]
236
237 srcList.extend( bindL )
238
239
240
241
242
243
244 return srcList
245
246
247 def getMenuFunctionSource( menuL, rootName='MainWin' ):
248 pass
249
250 if __name__ == "__main__":
251
252 descStr='''
253 File
254 New
255 Worksheet
256 Text File
257 Open
258 Save
259
260 Exit
261 Edit
262 Find
263 Copy
264 Cut
265 Paste
266 '''
267
268 menuL = buildMenuSource( descStr )
269 print( menuL )
270 print( '-'*55 )
271
272 menuSrcL = getMenuSource( menuL, rootName='master' )
273 for line in menuSrcL:
274 print(line, end='')
275 print( '======================================================' )
276
277
278 print( '''
279 from Tkinter import *
280
281 class Mytestapp:
282 def __init__(self, %s):
283 '''%'master' )
284 for line in menuSrcL:
285 print( line, end='')
286
287 print( '''root = Tk()
288 app = Mytestapp(root)
289 root.mainloop()
290 ''' )
291
292
293