1515import tkinter as tk
1616import warnings
1717
18- from tkinter import ttk
18+ from tkinter import EventType , ttk
1919
2020from collections import deque
2121from logging import getLogger
2222from typing import Any , Callable , Dict , Union
2323from xml .etree import ElementTree as ET
2424
25+ from openlcb .cdivar import CLASSNAME_TYPES , CDIVar
26+
2527
2628if __name__ == "__main__" :
2729 logger = getLogger (__file__ )
@@ -75,10 +77,19 @@ def __init__(self, *args, **kwargs):
7577 if hasattr (self .parent , 'root' ):
7678 self .root = self .parent .root
7779 self ._container = self # where to put visible widgets
78- self ._treeview = None # type: ttk.Treeview
80+ self ._treeview = None # type: ttk.Treeview|None
81+ self ._treeMemos = {} # type: Dict[str, CDIMemo]
82+
7983 self ._gui (self ._container )
8084 self .cursorCol = 0
8185
86+ self .cdiSettingWidgets = [] # type: list[tk.Widget]
87+ self .cdiSettingRow = 0
88+ self .cdiSettingFrame = None # type: Union[ttk.Frame, tk.Frame, None]
89+
90+ def setSettingsContainer (self , container : Union [ttk .Frame , tk .Frame ]):
91+ self .cdiSettingFrame = container
92+
8293 def _gui (self , container : tk .Widget ):
8394 if self ._top_widgets :
8495 raise RuntimeError ("gui can only be called once unless reset" )
@@ -92,10 +103,94 @@ def _gui(self, container: tk.Widget):
92103 self ._top_widgets .append (self ._overview )
93104 self ._treeview = ttk .Treeview (container )
94105 self ._treeview .grid (sticky = tk .NSEW , row = len (self ._top_widgets ))
106+ self ._treeview .bind ("<<TreeviewSelect>>" , self .onTreeSelect )
95107 self .rowconfigure (len (self ._top_widgets ), weight = 1 ) # weight=1: expand
96108 self ._top_widgets .append (self ._treeview )
97109 self ._current_iid = 0 # id of Treeview element
98110
111+ def onTreeSelect (self , event : tk .Event ):
112+ # print(f"event={event}")
113+ # print(f"dir(event)={dir(event)}")
114+ # print(f"event.__dict__={event.__dict__}")
115+ # ^ {'serial': 794, 'num': '??', 'height': '??', 'keycode':
116+ # '??', 'state': 0, 'time': 0, 'width': '??', 'x': 0, 'y': 0,
117+ # 'char': '??', 'send_event': False, 'keysym': '??',
118+ # 'keysym_num': '??', 'type': <EventType.VirtualEvent: '35'>,
119+ # 'widget': <tkinter.ttk.Treeview object
120+ # .!mainform.!notebook.!frame.!cdiform.!treeview>, 'x_root':
121+ # 0, 'y_root': 0, 'delta': 0}
122+ for iid in event .widget .selection ():
123+ item = event .widget .item (iid ) # type: dict
124+ # ^ such as {'text': 'Track Output', 'image': '',
125+ # 'values': [CDIMemo], 'open': 0, 'tags': ''}
126+ cm = self ._treeMemos [iid ]
127+ # print(f"type(item)={type(item)}")
128+ # raise NotImplementedError(item)
129+ # print(f"cm={cm}")
130+ self .clearSettingWidgets ()
131+ if cm .tag not in CLASSNAME_TYPES :
132+ # Non-value (such as segment or group)
133+ # So there is nothing to do.
134+ return
135+
136+ name = cm .getChildContent ("name" )
137+ if name is None :
138+ # self.setStatus("Selected element has no name.")
139+ break
140+
141+ nameLabel = ttk .Label (self .cdiSettingFrame , text = name )
142+ nameLabel .tip = cm .getChildContent ("description" )
143+ nameLabel .grid (column = 0 , row = self .cdiSettingRow )
144+ self .cdiSettingWidgets .append (nameLabel )
145+ # self.cdiSettingRow += 1
146+ cdivar = cm .toCDIVar ()
147+ tkvar = None
148+ v_widget = None
149+ if cdivar .max :
150+ if cdivar .className == "int" :
151+ tkvar = tk .IntVar (self .root )
152+ elif cdivar .className == "float" :
153+ tkvar = tk .DoubleVar (self .root )
154+ else :
155+ raise TypeError ("Device should not specify max for {}"
156+ .format (cdivar .className ))
157+
158+ v_widget = ttk .LabeledScale (self .cdiSettingFrame , variable = tkvar )
159+ # ^ widget.scale is ttk.Scale, widget.label is ttk.Label
160+ v_widget .scale .cdivar = cdivar
161+ v_widget .scale .tip = nameLabel .tip
162+ else :
163+ tkvar = tk .StringVar (self .root )
164+ v_widget = ttk .Entry (self .cdiSettingFrame , textvariable = tkvar )
165+ v_widget .grid (column = 1 , row = self .cdiSettingRow )
166+ self .cdiSettingRow += 1
167+ self .cdiSettingWidgets .append (v_widget )
168+ if cdivar .default is not None :
169+ tkvar .set (cdivar .default )
170+ v_widget .cdivar = cdivar
171+ v_widget .tip = nameLabel .tip
172+
173+
174+ address_str = ""
175+ if address_str is not None :
176+ address_str = str (cm .address )
177+ a_widget = ttk .Label (self .cdiSettingFrame , text = "(Address:" )
178+ a_widget .grid (column = 0 , row = self .cdiSettingRow , sticky = tk .W )
179+ av_widget = ttk .Label (self .cdiSettingFrame , text = address_str + ")" )
180+ av_widget .grid (column = 1 , row = self .cdiSettingRow )
181+ self .cdiSettingWidgets .append (a_widget )
182+ self .cdiSettingWidgets .append (av_widget )
183+ self .cdiSettingRow += 1
184+
185+ break
186+
187+ def clearSettingWidgets (self ):
188+ for widget in self .cdiSettingWidgets :
189+ widget .grid_forget ()
190+ widget .destroy ()
191+ del self .cdiSettingWidgets [:]
192+ self .cdiSettingRow = 0
193+
99194 def clear (self ):
100195 while self ._top_widgets :
101196 widget = self ._top_widgets .pop ()
@@ -337,6 +432,7 @@ def _onPushScope(self, cm: CDIMemo):
337432 iid = self ._current_iid ,
338433 text = content ,
339434 )
435+ self ._treeMemos [new_branch ] = cm
340436 # values=(), image=None
341437 # self._tag_stack[-1].iid = new_branch
342438 # NOTE: ^ _tag_stack is unreliable due to race condition!
@@ -358,6 +454,7 @@ def _onPushScope(self, cm: CDIMemo):
358454 iid = self ._current_iid ,
359455 text = content ,
360456 )
457+ self ._treeMemos [new_branch ] = cm
361458 # values=(), image=None
362459 # self._tag_stack[-1].iid = new_branch
363460 # NOTE: ^ _tag_stack is unreliable due to race condition!
0 commit comments