366 lines
9.7 KiB
Markdown
366 lines
9.7 KiB
Markdown
# 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
|
|
```powershell
|
|
# 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
|
|
```python
|
|
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
|
|
```python
|
|
# 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
|
|
```python
|
|
# 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:
|
|
```json
|
|
{
|
|
"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:**
|
|
```python
|
|
DockFrame(parent, title, on_close=None, closable=True, **kwargs)
|
|
```
|
|
|
|
**Methods:**
|
|
- `populate_content()` - Override to add widgets to `content_frame`
|
|
- `minimize()` - Hide content, keep title bar
|
|
- `restore()` - Restore from minimized state
|
|
- `close()` - Hide entire dock
|
|
- `show()` - Show dock if hidden
|
|
- `set_title(new_title)` - Update dock title
|
|
|
|
**Attributes:**
|
|
- `content_frame` - ttk.Frame for dock content
|
|
- `is_minimized` - bool
|
|
- `is_visible` - bool
|
|
|
|
---
|
|
|
|
### WorkspaceManager
|
|
Manages dock lifecycle and layout.
|
|
|
|
**Constructor:**
|
|
```python
|
|
WorkspaceManager(root, layouts_dir="layouts")
|
|
```
|
|
|
|
**Methods:**
|
|
- `add_dock(dock_id, dock, position)` - Register and place dock
|
|
- Positions: `'left'`, `'right_top'`, `'right_bottom'`
|
|
- `get_dock(dock_id)` - Retrieve dock by ID
|
|
- `remove_dock(dock_id)` - Unregister dock
|
|
- `toggle_dock_visibility(dock_id)` - Show/hide dock
|
|
- `save_layout(name)` - Save layout to JSON
|
|
- `load_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](main_docking_window.py) in `__init__()`:
|
|
```python
|
|
# 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:
|
|
```python
|
|
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
|
|
1. Launch GUI: `python scripts\launch_docking_gui.py`
|
|
2. Verify MCS tabs load (Page 01-07)
|
|
3. Test minimize buttons on each dock
|
|
4. Test close/restore via View menu
|
|
5. Resize splitters (drag sash)
|
|
6. Save layout (File → Save Layout)
|
|
7. Close and relaunch
|
|
8. Load layout (File → Load Layout)
|
|
|
|
### Unit Tests (TODO)
|
|
```powershell
|
|
pytest tests/test_docking_system.py
|
|
```
|
|
|
|
---
|
|
|
|
## Migration Guide
|
|
|
|
### From old main_window.py to docking system
|
|
|
|
**Old approach:**
|
|
```python
|
|
# All tabs in one Notebook
|
|
notebook = ttk.Notebook(root)
|
|
page01 = Page01(notebook, bus_module)
|
|
notebook.add(page01, text="Command")
|
|
```
|
|
|
|
**New approach:**
|
|
```python
|
|
# 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
|
|
1. Create `pymsc/gui/docking/my_module_dock.py`
|
|
2. Subclass `DockFrame`
|
|
3. Implement `populate_content()`
|
|
4. Register in `MainDockingWindow._create_docks()`
|
|
5. Add View menu toggle
|
|
6. 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
|
|
- [Tkinter PanedWindow](https://docs.python.org/3/library/tkinter.ttk.html#tkinter.ttk.PanedWindow)
|
|
- [ttkbootstrap Themes](https://ttkbootstrap.readthedocs.io/en/latest/themes/)
|
|
- [ARTOS Architecture Decisions](../doc/ARTOS_Architecture_Decisions.md)
|
|
|
|
---
|
|
|
|
## 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
|