9.7 KiB
9.7 KiB
ARTOS Docking System
Tkinter-based Modular GUI Framework
Status: ✅ First iteration complete
Created: 2026-01-09
Version: 0.1.0
Overview
Custom docking system for ARTOS built with Tkinter, providing a modular GUI where each subsystem (MCS, Navigation, IRST, etc.) lives in its own dockable panel.
Key Features
- ✅ Dockable panels with title bars
- ✅ Minimize/maximize/close controls
- ✅ Resizable splits (PanedWindow)
- ✅ Save/load workspace layouts (JSON)
- ✅ Zero external dependencies (stdlib only)
- ✅ Dark theme using ttk 'clam' style
Architecture
pymsc/gui/docking/
├── __init__.py # Package exports
├── dock_frame.py # Base class for dockable panels
├── workspace_manager.py # Layout and lifecycle management
├── mcs_dock.py # MCS module dock (full implementation)
├── placeholder_dock.py # Generic placeholder for future modules
└── main_docking_window.py # Main application window
Class Hierarchy
DockFrame (base)
├── title_bar (Frame)
│ ├── title_label
│ └── buttons (minimize, close)
└── content_frame (to be populated by subclasses)
MCSDock (DockFrame)
└── content_frame
└── Notebook (tabs)
├── Page01 (Command)
├── Page02 (Radar Settings)
├── ...
└── Page07 (Advanced)
PlaceholderDock (DockFrame)
└── content_frame
└── Label ("Not yet implemented")
Usage
Quick Start
# Activate venv
.venv\Scripts\Activate.ps1
# Launch docking GUI
python scripts\launch_docking_gui.py
Layout Structure
┌─────────────┬──────────────────────────┐
│ │ Right Top │
│ │ ┌────────────────────┐ │
│ MCS │ │ Navigation │ │
│ Dock │ │ (Placeholder) │ │
│ │ └────────────────────┘ │
│ │ ┌────────────────────┐ │
│ │ │ IRST Module │ │
│ │ │ (Placeholder) │ │
│ │ └────────────────────┘ │
│ ├──────────────────────────┤
│ │ Right Bottom │
│ │ ┌────────────────────┐ │
│ │ │ Logger & Status │ │
│ │ │ (Placeholder) │ │
│ │ └────────────────────┘ │
└─────────────┴──────────────────────────┘
Creating a New Dock
Step 1: Subclass DockFrame
from pymsc.gui.docking import DockFrame
import tkinter as tk
from tkinter import ttk
class MyModuleDock(DockFrame):
def __init__(self, parent, my_data, **kwargs):
self.my_data = my_data
super().__init__(parent, title="My Module", **kwargs)
def populate_content(self):
"""Called after __init__ to populate content_frame."""
label = ttk.Label(self.content_frame, text="My module content")
label.pack()
Step 2: Register in MainDockingWindow
# In main_docking_window.py -> _create_docks()
my_dock = MyModuleDock(
self.workspace.left_container,
my_data=some_data
)
self.workspace.add_dock('my_module', my_dock, position='left')
Step 3: Add View menu entry
# In _create_menu()
view_menu.add_command(
label="Toggle My Module",
command=lambda: self.workspace.toggle_dock_visibility('my_module')
)
Configuration
Workspace Layouts
Layouts are saved in layouts/ directory as JSON files:
{
"main_sash_position": [400, 0],
"right_sash_position": [0, 600],
"docks": {
"mcs": {
"visible": true,
"minimized": false
},
"nav": {
"visible": true,
"minimized": true
}
}
}
Saving/Loading
- Save: File → Save Layout
- Load: File → Load Layout
- Default:
layouts/user_layout.json
API Reference
DockFrame
Base class for all dockable panels.
Constructor:
DockFrame(parent, title, on_close=None, closable=True, **kwargs)
Methods:
populate_content()- Override to add widgets tocontent_frameminimize()- Hide content, keep title barrestore()- Restore from minimized stateclose()- Hide entire dockshow()- Show dock if hiddenset_title(new_title)- Update dock title
Attributes:
content_frame- ttk.Frame for dock contentis_minimized- boolis_visible- bool
WorkspaceManager
Manages dock lifecycle and layout.
Constructor:
WorkspaceManager(root, layouts_dir="layouts")
Methods:
add_dock(dock_id, dock, position)- Register and place dock- Positions:
'left','right_top','right_bottom'
- Positions:
get_dock(dock_id)- Retrieve dock by IDremove_dock(dock_id)- Unregister docktoggle_dock_visibility(dock_id)- Show/hide docksave_layout(name)- Save layout to JSONload_layout(name)- Load layout from JSON
Attributes:
docks- Dict[str, DockFrame]main_pane- tk.PanedWindow (horizontal split)right_pane- tk.PanedWindow (vertical split)
Current Modules
| Dock ID | Title | Status | Position |
|---|---|---|---|
mcs |
Mission Control System | ✅ Full implementation | Left |
nav |
Navigation System | 🔲 Placeholder | Right Top |
irst |
IRST Module | 🔲 Placeholder | Right Top |
logger |
System Logger & Status | 🔲 Placeholder | Right Bottom |
Planned Modules (Future Phases)
Phase 3: Navigation & Algorithms
- Navigation Dock: Real-time navigation algorithms and data processing
- Trajectory Dock: Track prediction and analysis
Phase 4: Video & IRST
- Video Dock: Camera feeds with PIL/Pillow rendering
- IRST Dock: Infrared search and track visualization
Phase 5: Test Execution
- Test Control Dock: Script selection and execution
- Report Viewer Dock: Real-time test results and logs
Theming
Current Theme
The GUI uses Tkinter's native 'clam' theme with custom dark color scheme:
- Background: Dark blue-grey (#2b3e50)
- Text: Light grey (#ecf0f1)
- Accent: Blue (#3498db)
Changing Colors
Edit main_docking_window.py in __init__():
# Dark theme configuration
bg_dark = '#2b3e50' # Main background
bg_darker = '#1a252f' # Darker backgrounds
fg_light = '#ecf0f1' # Text color
accent = '#3498db' # Accent color (buttons)
Alternative Themes
You can use other ttk themes by changing:
style.theme_use('clam') # Options: clam, alt, default, classic
Known Issues & Limitations
Current Limitations
- ⚠️ Docks cannot be dragged between positions (fixed slots)
- ⚠️ No floating/undocked panels
- ⚠️ Sash positions are absolute pixels (not percentages)
Future Improvements
- Drag-and-drop dock repositioning
- Floating window support
- Tabbed docking (multiple docks in same slot)
- Dock state persistence per user
- Keyboard shortcuts for dock operations
Testing
Manual Testing
- Launch GUI:
python scripts\launch_docking_gui.py - Verify MCS tabs load (Page 01-07)
- Test minimize buttons on each dock
- Test close/restore via View menu
- Resize splitters (drag sash)
- Save layout (File → Save Layout)
- Close and relaunch
- Load layout (File → Load Layout)
Unit Tests (TODO)
pytest tests/test_docking_system.py
Migration Guide
From old main_window.py to docking system
Old approach:
# All tabs in one Notebook
notebook = ttk.Notebook(root)
page01 = Page01(notebook, bus_module)
notebook.add(page01, text="Command")
New approach:
# MCS dock with tabs
mcs_dock = MCSDock(parent, bus_module)
workspace.add_dock('mcs', mcs_dock, position='left')
Benefits:
- Independent refresh loops per dock
- Each module can be hidden/minimized independently
- Easier parallel development (one developer per dock)
- Better separation of concerns
Contributing
Adding a New Dock Module
- Create
pymsc/gui/docking/my_module_dock.py - Subclass
DockFrame - Implement
populate_content() - Register in
MainDockingWindow._create_docks() - Add View menu toggle
- Update this README with dock info
Code Style
- Follow PEP 8
- Type hints for public methods
- Docstrings for classes and public methods
- Comments for complex logic Tkinter ttk Styling](https://docs.python.org/3/library/tkinter.ttk.html#tkinter.ttk.Style
References
Changelog
v0.1.0 - 2026-01-09
- ✅ Initial docking system implementation
- ✅ DockFrame base class with minimize/close
- ✅ WorkspaceManager with PanedWindow layouts
- ✅ MCSDock with Control and Mission pages
- ✅ PlaceholderDock for future modules
- ✅ MainDockingWindow with menu system
- ✅ Save/load layout functionality
- ✅ Dark theme using ttk 'clam' style (zero external dependencies)
License
© 2025 - Internal project