Table of Contents
- Helper Functions Documentation v2.3.0
- State Management Helpers
- Display Formatting Helpers
- format_value_for_display(value) - UPDATED v2.3.0
- flatten_json_if_valid(value) - NEW v2.3.0
- truncate_value(value, max_length=80)
- Theme System Helpers - NEW v2.3.0
- Image Browser Helpers - NEW v2.3.0
- scroll_to_thumbnail(filepath)
- bind_mousewheel(widget)
- on_mousewheel(event)
- on_thumb_frame_configure(event)
- UI Management Helpers
- Event Handling Helpers
- Utility Helpers
- Helper Function Best Practices v2.3.0
- State Management
- JSON Handling (NEW)
- Display Formatting
- Theme Integration (NEW)
- Image Browser (NEW)
- UI Feedback
- File Handle Management (NEW)
- v2.3.0 Helper Function Summary
Helper Functions Documentation v2.3.0
State Management Helpers
mark_as_modified()
Purpose: Tracks when metadata has been modified but not saved
Behavior:
- Sets has_unsaved_changes flag to True
- Updates window title with asterisk (*)
- Shows "Unsaved changes" indicator in UI
- 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:
- Clears has_unsaved_changes flag
- Removes asterisk from window title
- 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:
- Attempts to parse value as JSON
- If successful, returns pretty-printed with 2-space indentation
- Falls back to original value if parsing fails
- 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:
- Attempts to parse value as JSON
- If successful, returns flattened single-line JSON
- Uses separators=(',', ':') for compact format (no spaces)
- Falls back to original value if parsing fails
- 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:
- Converts value to string
- Checks if length exceeds max_length
- Truncates with ellipsis (...) if too long
- 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:
- Checks platform (macOS, Windows, Linux)
- Executes platform-specific command/registry read
- Returns True for dark mode, False for light mode
- Falls back to light mode on any error
- 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:
- Checks if filepath has a thumbnail frame
- Calculates frame position and canvas dimensions
- Computes center position for thumbnail
- Normalizes position to 0-1 range
- 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:
- Detects operating system platform
- Binds appropriate scroll events for platform
- Sets focus on mouse enter for scroll capture
- 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:
- Detects platform from event
- Calculates scroll delta based on platform
- 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:
- Triggered when thumbnail container changes size
- Calculates bounding box of all canvas items
- 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:
- Cancels any existing status timer
- Updates status label with new message and color
- Schedules automatic clearing after duration
- 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:
- Constructs base title with app name and version
- Appends filename when file is loaded
- Adds asterisk (*) for unsaved changes
- 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:
- Gets currently selected item from tree
- Extracts key from selection values
- Retrieves full value from metadata_dict
- Formats value for display via format_value_for_display()
- Updates detail text widget
- 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:
- Constructs about text with app metadata
- Shows modal dialog using messagebox.showinfo()
- 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.