2 Helper Methods
robert edited this page 2026-01-07 23:03:20 +01:00

Helper Functions Documentation v2.3.0

State Management Helpers

mark_as_modified()

Purpose: Tracks when metadata has been modified but not saved

Behavior:

  1. Sets has_unsaved_changes flag to True
  2. Updates window title with asterisk (*)
  3. Shows "Unsaved changes" indicator in UI
  4. Only triggers once per modification session

Example Usage:

# After adding a new field
self.metadata_dict["NewKey"] = "Value"
self.mark_as_modified()

mark_as_saved()

Purpose: Resets the unsaved changes indicator and updates UI to reflect saved state

Behavior:

  1. Clears has_unsaved_changes flag
  2. Removes asterisk from window title
  3. Hides unsaved changes indicator

Example Usage:

# After successful save operation
self.mark_as_saved()
self.set_status("Metadata saved successfully", color="green")

Display Formatting Helpers

format_value_for_display(value) - UPDATED v2.3.0

Purpose: Intelligently formats metadata values for display in editor

Behavior:

  1. Attempts to parse value as JSON
  2. If successful, returns pretty-printed with 2-space indentation
  3. Falls back to original value if parsing fails
  4. Preserves Unicode characters with ensure_ascii=False

v2.3.0 Note: This function formats for display only. Values are automatically flattened before saving via flatten_json_if_valid().

Example Usage:

# JSON-formatted metadata
json_value = '{"camera":"Canon","iso":100}'
formatted = app.format_value_for_display(json_value)
# Returns pretty-printed JSON

# Plain text metadata
text_value = "Simple string value"
formatted = app.format_value_for_display(text_value)
# Returns: "Simple string value"

flatten_json_if_valid(value) - NEW v2.3.0

Purpose: Preserves original compact JSON format when saving

Behavior:

  1. Attempts to parse value as JSON
  2. If successful, returns flattened single-line JSON
  3. Uses separators=(',', ':') for compact format (no spaces)
  4. Falls back to original value if parsing fails
  5. Preserves Unicode characters

Key Feature: Automatically called during save operations to maintain the original compact format of JSON metadata.

Example Usage:

# Pretty-printed JSON from editor
formatted = '{\n  "prompt": "a cat",\n  "steps": 20\n}'
flattened = app.flatten_json_if_valid(formatted)
# Returns: '{"prompt":"a cat","steps":20}'

# Plain text (non-JSON)
text = "Simple value"
flattened = app.flatten_json_if_valid(text)
# Returns: "Simple value" (unchanged)

Workflow:

User edits -> format_value_for_display() -> Pretty JSON shown
User saves -> flatten_json_if_valid() -> Compact JSON saved

truncate_value(value, max_length=80)

Purpose: Shortens long values for compact tree view display

Parameters:

  • value: The metadata value to truncate
  • max_length (optional): Maximum length before truncation (default: 80)

Behavior:

  1. Converts value to string
  2. Checks if length exceeds max_length
  3. Truncates with ellipsis (...) if too long
  4. Returns full value if within length limit

Example Usage:

long_value = "This is a very long string that exceeds the maximum display length"
truncated = app.truncate_value(long_value)
# Returns truncated version with "..."

Theme System Helpers - NEW v2.3.0

detect_dark_mode()

Purpose: Automatically detects OS-level dark mode setting for adaptive UI theming

Behavior:

  1. Checks platform (macOS, Windows, Linux)
  2. Executes platform-specific command/registry read
  3. Returns True for dark mode, False for light mode
  4. Falls back to light mode on any error
  5. Has 1-second timeout to prevent hanging

Platform Detection:

  • macOS: Reads AppleInterfaceStyle system preference
  • Windows: Reads AppsUseLightTheme registry key (0=dark, 1=light)
  • Linux: Checks GTK theme name for "dark" keyword

Example Usage:

is_dark = app.detect_dark_mode()
if is_dark:
    print("System is in dark mode")

get_theme_colors()

Purpose: Provides consistent color scheme based on system theme

Returns: Dictionary with keys:

  • canvas_bg: Canvas background color
  • frame_bg: Frame background color
  • text_fg: Text foreground color
  • loading_fg: Loading indicator color

Color Schemes:

Dark Mode:

  • canvas_bg: #2b2b2b (dark gray)
  • frame_bg: #2b2b2b
  • text_fg: #ffffff (white)
  • loading_fg: #6bb6ff (light blue)

Light Mode:

  • canvas_bg: #f0f0f0 (light gray)
  • frame_bg: #f0f0f0
  • text_fg: #000000 (black)
  • loading_fg: #4a90d9 (blue)

Example Usage:

colors = app.get_theme_colors()
canvas = tk.Canvas(root, bg=colors['canvas_bg'])
label = tk.Label(root, fg=colors['text_fg'])

Image Browser Helpers - NEW v2.3.0

scroll_to_thumbnail(filepath)

Purpose: Automatically scrolls image browser to show selected thumbnail

Behavior:

  1. Checks if filepath has a thumbnail frame
  2. Calculates frame position and canvas dimensions
  3. Computes center position for thumbnail
  4. Normalizes position to 0-1 range
  5. Scrolls canvas to target position using yview_moveto()

Example Usage:

# After loading a file
app.load_file_from_path(filepath)
app.scroll_to_thumbnail(filepath)  # Auto-scroll to it

bind_mousewheel(widget)

Purpose: Enables trackpad and mousewheel scrolling for image browser

Behavior:

  1. Detects operating system platform
  2. Binds appropriate scroll events for platform
  3. Sets focus on mouse enter for scroll capture
  4. Restores focus on mouse leave

Platform Events:

  • macOS: MouseWheel, Button-4, Button-5
  • Windows: MouseWheel only
  • Linux: Button-4 (scroll up), Button-5 (scroll down)

Example Usage:

# During UI setup
self.bind_mousewheel(self.image_canvas)

on_mousewheel(event)

Purpose: Processes scroll events with platform-specific calculations

Behavior:

  1. Detects platform from event
  2. Calculates scroll delta based on platform
  3. Scrolls canvas by appropriate units

Platform Deltas:

  • macOS: Direct delta value (trackpad-friendly)
  • Windows: Delta divided by 120 (standard wheel units)
  • Linux: +1/-1 for button events

on_thumb_frame_configure(event)

Purpose: Dynamically updates scroll region as thumbnails are added

Behavior:

  1. Triggered when thumbnail container changes size
  2. Calculates bounding box of all canvas items
  3. Updates scrollable region to encompass all content

Example Usage:

# Bound to thumbnail container during setup
self.thumb_frame.bind("<Configure>", self.on_thumb_frame_configure)

UI Management Helpers

set_status(message, duration=3000, color="")

Purpose: Provides temporary feedback to users with auto-clear

Parameters:

  • message: Text to display in status bar
  • duration (optional): Time before auto-clear in ms (default: 3000)
  • color (optional): Text color like "green" or "red"

Behavior:

  1. Cancels any existing status timer
  2. Updates status label with new message and color
  3. Schedules automatic clearing after duration
  4. Duration=0 means permanent message

Example Usage:

# Temporary success message
app.set_status("File loaded successfully", color="green")

# Permanent error message
app.set_status("Error: File not found", duration=0, color="red")

# Custom duration
app.set_status("Processing...", duration=5000)  # 5 seconds

update_title()

Purpose: Maintains consistent window title format with unsaved indicator

Behavior:

  1. Constructs base title with app name and version
  2. Appends filename when file is loaded
  3. Adds asterisk (*) for unsaved changes
  4. Falls back to base title when no file is loaded

Example Usage:

app.current_file = "example.png"
app.update_title()
# Window title: "PNG Metadata Editor v2.3.0 - example.png"

app.has_unsaved_changes = True
app.update_title()
# Window title: "PNG Metadata Editor v2.3.0 - example.png *"

Event Handling Helpers

on_selection_change(event)

Purpose: Synchronizes detail view with tree selection

Behavior:

  1. Gets currently selected item from tree
  2. Extracts key from selection values
  3. Retrieves full value from metadata_dict
  4. Formats value for display via format_value_for_display()
  5. Updates detail text widget
  6. Disables editing of detail view (read-only)

Example Usage:

# Bound to treeview selection event
self.tree.bind("<<TreeviewSelect>>", self.on_selection_change)

Utility Helpers

show_about()

Purpose: Displays application information dialog

Behavior:

  1. Constructs about text with app metadata
  2. Shows modal dialog using messagebox.showinfo()
  3. Includes v2.3.0 feature highlights

Example Usage:

app.show_about()

Helper Function Best Practices v2.3.0

State Management

  • Always call mark_as_modified() after any metadata change
  • Call mark_as_saved() only after successful save operations
  • Ensure title updates reflect current state

JSON Handling (NEW)

  • Use format_value_for_display() for editor and detail views
  • Always call flatten_json_if_valid() before saving to file
  • Workflow: display formatted -> edit -> save flattened
  • Never skip flattening step to preserve original format

Display Formatting

  • Use format_value_for_display() for all detail view updates
  • Apply truncate_value() only to tree view values
  • Keep tree view compact, detail view readable

Theme Integration (NEW)

  • Call detect_dark_mode() once during initialization
  • Use get_theme_colors() for all theme-dependent widgets
  • Apply theme colors to canvas, frames, and labels
  • Fallback to light mode on detection failure

Image Browser (NEW)

  • Always call scroll_to_thumbnail() after loading files
  • Bind mousewheel events to enable smooth scrolling
  • Update scroll region after adding/removing thumbnails
  • Handle platform-specific scroll events correctly

UI Feedback

  • Use set_status() for temporary user feedback
  • Include appropriate color coding (green=success, red=error)
  • Keep messages concise and action-oriented
  • Use 3-second default duration for most messages

File Handle Management (NEW)

  • Always close PIL Image objects after reading
  • Critical for multi-file loading in image browser
  • Prevents file locking issues on Windows

v2.3.0 Helper Function Summary

New Helpers

  • flatten_json_if_valid() - Preserves compact JSON format
  • detect_dark_mode() - Cross-platform theme detection
  • get_theme_colors() - Adaptive color schemes
  • scroll_to_thumbnail() - Auto-scroll to selected image
  • bind_mousewheel() - Platform-specific scroll binding
  • on_mousewheel() - Scroll event processing
  • on_thumb_frame_configure() - Dynamic scroll region

Updated Helpers

  • format_value_for_display() - Enhanced for v2.3.0 JSON workflow
  • show_about() - Updated with v2.3.0 features

Critical Workflows

JSON Editing Workflow:

1. Select field -> on_selection_change()
2. Display -> format_value_for_display() (pretty JSON)
3. User edits in dialog
4. Save -> flatten_json_if_valid() (compact JSON)
5. Store in metadata_dict

Theme Detection Workflow:

1. App init -> detect_dark_mode()
2. Get colors -> get_theme_colors()
3. Apply to canvas/frames
4. Use consistently throughout UI

Image Loading Workflow:

1. User clicks thumbnail
2. load_file_from_path(filepath)
3. Open image -> Extract metadata -> img.close()
4. Update UI -> scroll_to_thumbnail(filepath)

These helper functions form the backbone of v2.3.0's enhanced functionality, handling everything from intelligent JSON management to adaptive theming and smooth image browsing.