diff --git a/app_state.py b/app_state.py index d573ecd..faf5306 100644 --- a/app_state.py +++ b/app_state.py @@ -8,7 +8,7 @@ so later rebinding would only ever be seen by the module that did it. import configparser import os -VERSION = "0.0.0.057" +VERSION = "0.0.0.058" PROPERTIES_FILE = os.path.join(os.path.dirname(os.path.abspath(__file__)), "editor.properties") DEFAULT_GRID_SIZE = 10 DEFAULT_ADD_TIMESTAMP = True diff --git a/main.py b/main.py index 8f8158c..4e12362 100644 --- a/main.py +++ b/main.py @@ -28,6 +28,36 @@ TREE_MIN_COLUMN_WIDTH = 40 # panes in proportion to their weights. Left at the ten-row default the palette asked for # so much that the tree, carrying the larger weight, gave up all of its height first. TREE_REQUESTED_ROWS = 6 + + +class _ToolTip: + """Minimal hover tooltip for toolbar widgets.""" + + def __init__(self, widget, text): + self._widget = widget + self._text = text + self._tw = None + widget.bind("", self._show, add="+") + widget.bind("", self._hide, add="+") + + def _show(self, _event=None): + x = self._widget.winfo_rootx() + self._widget.winfo_width() // 2 + y = self._widget.winfo_rooty() + self._widget.winfo_height() + 4 + tw = tk.Toplevel(self._widget) + tw.wm_overrideredirect(True) + tw.wm_geometry(f"+{x}+{y}") + label = tk.Label( + tw, text=self._text, background="#ffffe0", foreground="#000000", + relief="solid", borderwidth=1, padx=4, pady=2, + font=("Segoe UI", 8), + ) + label.pack() + self._tw = tw + + def _hide(self, _event=None): + if self._tw: + self._tw.destroy() + self._tw = None PALETTE_REQUESTED_ROWS = 5 # Below this the shortfall is deep enough to shrink the tree past a usable few rows, and @@ -76,6 +106,7 @@ _history_file_path = None # the file view_history was recorded against # function that touches them checks first. btn_back = None btn_forward = None +btn_toggle_pane = None zoom_label = None menu_view = None show_left_column_var = None @@ -1278,6 +1309,8 @@ def apply_left_column_visibility(): elif is_shown: paned_window.forget(left_pane) + _sync_pane_toggle_button() + def toggle_left_column(event=None): """Keyboard route to the same toggle. The menu flips the variable for itself.""" @@ -1287,6 +1320,12 @@ def toggle_left_column(event=None): return "break" +def _sync_pane_toggle_button(): + """Update the toggle button icon to reflect the pane state.""" + if btn_toggle_pane is not None and show_left_column_var is not None: + btn_toggle_pane.configure(text="◧" if show_left_column_var.get() else "▯") + + # --- Sheet view history --- def _tree_item_for_element(element): @@ -1904,21 +1943,41 @@ app_state.status_label = status_label toolbar = ttk.Frame(window) toolbar.pack(side=tk.TOP, fill=tk.X, padx=8, pady=(4, 0)) -btn_back = ttk.Button(toolbar, text="◀", width=3, command=go_back, state="disabled") -btn_back.pack(side=tk.LEFT) - -btn_forward = ttk.Button(toolbar, text="▶", width=3, command=go_forward, state="disabled") -btn_forward.pack(side=tk.LEFT, padx=(3, 0)) +# U+25E7: a square with left half filled — suggests a visible side panel. +btn_toggle_pane = ttk.Button(toolbar, text="◧", width=3, command=toggle_left_column) +btn_toggle_pane.pack(side=tk.LEFT) +_ToolTip(btn_toggle_pane, "Tree / Palette (Ctrl+B)") ttk.Separator(toolbar, orient=tk.VERTICAL).pack(side=tk.LEFT, fill=tk.Y, padx=8, pady=2) -ttk.Button(toolbar, text="−", width=3, command=do_zoom_out).pack(side=tk.LEFT) +btn_back = ttk.Button(toolbar, text="◀", width=3, command=go_back, state="disabled") +btn_back.pack(side=tk.LEFT) +_ToolTip(btn_back, "Back (Alt+Left)") + +btn_forward = ttk.Button(toolbar, text="▶", width=3, command=go_forward, state="disabled") +btn_forward.pack(side=tk.LEFT, padx=(3, 0)) +_ToolTip(btn_forward, "Forward (Alt+Right)") + +ttk.Separator(toolbar, orient=tk.VERTICAL).pack(side=tk.LEFT, fill=tk.Y, padx=8, pady=2) + +_btn_zoom_out = ttk.Button(toolbar, text="−", width=3, command=do_zoom_out) +_btn_zoom_out.pack(side=tk.LEFT) +_ToolTip(_btn_zoom_out, "Zoom Out (Ctrl+−)") + zoom_label = ttk.Label(toolbar, text="100%", width=6, anchor="center") zoom_label.pack(side=tk.LEFT, padx=1) -ttk.Button(toolbar, text="+", width=3, command=do_zoom_in).pack(side=tk.LEFT) -# U+26F6, the four-corners frame every other editor marks "fit to window" with. -ttk.Button(toolbar, text="⛶", width=3, command=do_zoom_fit).pack(side=tk.LEFT, padx=(3, 0)) +_btn_zoom_in = ttk.Button(toolbar, text="+", width=3, command=do_zoom_in) +_btn_zoom_in.pack(side=tk.LEFT) +_ToolTip(_btn_zoom_in, "Zoom In (Ctrl++)") + +_btn_zoom_fit = ttk.Button(toolbar, text="⛶", width=3, command=do_zoom_fit) +_btn_zoom_fit.pack(side=tk.LEFT, padx=(3, 0)) +_ToolTip(_btn_zoom_fit, "Zoom to Fit (Ctrl+9)") + +_btn_tidy = ttk.Button(toolbar, text="⊞", width=3, command=do_tidy_layout) +_btn_tidy.pack(side=tk.LEFT, padx=(3, 0)) +_ToolTip(_btn_tidy, "Tidy Layout (Ctrl+W)") paned_window = ttk.PanedWindow(window, orient=tk.HORIZONTAL) paned_window.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)