SXXXXXXX_PyMsc/pymsc/PyBusMonitor1553/gui/details_pane.py

107 lines
4.6 KiB
Python

"""Details pane widget: encapsulates the Details LabelFrame, scrollable canvas,
Treeview and editable form container. Assigns key attributes onto the parent
MonitorApp so existing code in `monitor.py` can keep referencing
`self.detail_tree`, `self.detail_form_container`, etc.
"""
import tkinter as tk
from tkinter import ttk
class DetailsPane:
def __init__(self, parent, app, width=520, height=540, title='Details'):
self.app = app
self.parent = parent
self.frame = tk.LabelFrame(parent, text=title)
self.frame.pack(side=tk.RIGHT, fill=tk.Y, expand=False, padx=6)
self.frame.config(width=width, height=height)
try:
self.frame.pack_propagate(False)
except Exception:
pass
tk.Label(self.frame, text="Message details:").pack(anchor=tk.W)
# canvas + scrollbars
self._details_canvas = tk.Canvas(self.frame, highlightthickness=0)
self._details_canvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=True, padx=(6,0), pady=6)
vsb = ttk.Scrollbar(self.frame, orient=tk.VERTICAL, command=self._details_canvas.yview)
hsb = ttk.Scrollbar(self.frame, orient=tk.HORIZONTAL, command=self._details_canvas.xview)
self._details_canvas.configure(yscrollcommand=vsb.set, xscrollcommand=hsb.set)
vsb.pack(side=tk.RIGHT, fill=tk.Y)
hsb.pack(side=tk.BOTTOM, fill=tk.X)
self._details_canvas_frame = tk.Frame(self._details_canvas)
self._details_canvas_window = self._details_canvas.create_window((0, 0), window=self._details_canvas_frame, anchor='nw')
def _on_frame_configure(event):
try:
self._details_canvas.configure(scrollregion=self._details_canvas.bbox('all'))
except Exception:
pass
def _on_canvas_configure(event):
try:
canvas_width = event.width
self._details_canvas.itemconfigure(self._details_canvas_window, width=canvas_width)
except Exception:
pass
self._details_canvas_frame.bind('<Configure>', _on_frame_configure)
self._details_canvas.bind('<Configure>', _on_canvas_configure)
# details Treeview (kept for backwards compatibility but not packed)
self.detail_tree = ttk.Treeview(self._details_canvas_frame, columns=("param", "value"), show="headings", height=18)
self.detail_tree.heading("param", text="Parameter")
self.detail_tree.heading("value", text="Value")
self.detail_tree.column("param", width=260)
self.detail_tree.column("value", width=420)
try:
self.detail_tree.configure() # placeholder to satisfy possible callers
except Exception:
pass
# form container in the interior frame so it scrolls with canvas
self.detail_form_container = tk.Frame(self._details_canvas_frame)
# ensure the form container is visible by default (the form builder will
# populate it). We do not pack the Treeview to avoid an empty tree
# overlaying the form; the form is the primary details UI.
try:
self.detail_form_container.pack(side=tk.LEFT, fill=tk.BOTH, expand=True, padx=2, pady=2)
except Exception:
pass
# assign attributes onto the app so existing MonitorApp code works
setattr(app, 'detail_tree', self.detail_tree)
setattr(app, '_details_canvas', self._details_canvas)
setattr(app, '_details_canvas_frame', self._details_canvas_frame)
setattr(app, '_details_canvas_window', self._details_canvas_window)
setattr(app, 'detail_form_container', self.detail_form_container)
# default holders
setattr(app, 'form_widgets', {})
setattr(app, 'current_form_label', None)
setattr(app, 'current_msg_wrapper', None)
setattr(app, 'detail_rows', {})
setattr(app, 'detail_selected_label', None)
setattr(app, 'detail_accessors', {})
setattr(app, '_flash_items', {})
setattr(app, '_last_detail_update', 0.0)
# bind double-click to parent's handler if present
try:
if hasattr(app, 'on_detail_double_click'):
self.detail_tree.bind('<Double-1>', app.on_detail_double_click)
except Exception:
pass
# expose convenience attributes
self.vsb = vsb
self.hsb = hsb
# small helper to pack the form container when needed
def show_form_container(self):
try:
self.detail_form_container.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
except Exception:
pass
__all__ = ['DetailsPane']