Rotary Selector Switch (SelectorSwitch)
The `SelectorSwitch` is a high-fidelity Tkinter Canvas-based widget designed to model discrete multi-position controls. It mimics the behavior of physical rotary switches found on industrial equipment, laboratory instruments, and high-end audio gear.
## ๐ Parameters (JSON Configuration)
| Parameter | Type | Default | Description |
| :— | :— | :— | :— |
| `type` | string | `SelectorSwitch` | The widget identifier. Can also be `_SelectorSwitch`. |
| `label_active` | string | `””` | The title text displayed above or below the switch. |
| `show_label` | boolean | `true` | Whether to display the `label_active`. |
| `label_Text_position` | string | `”top”` | Placement of the main label (`”top”` or `”bottom”`). |
| `positions` | array | `[“OFF”, “ON”]` | List of string labels for each discrete switch position. |
| `continuous` | boolean | `false` | `true`: 360ยฐ rotation (encoders). `false`: Hard stops with a visual gap (selectors). |
| `value_default` | mixed | `0` | Initial state. Can be an integer index or a string matching a position. |
| `indicator_color` | hex | Theme Accent | Color of the pointer and the currently selected label. |
| `width` / `height` | integer | `100` | Pixel dimensions of the canvas area. |
| `shape` | string | `”circle”` | Visual shape of the knob: `”circle”`, `”octagon”`, or `”gear”`. |
| `pointer_style` | string | `”line”` | Style of the pointer: `”line”`, `”triangle”`, or `”notch”`. |
| `no_center` | boolean | `false` | If `true`, the central pivot dot is hidden. |
—
## ๐น How It Works
### Interaction
* **Vertical Drag:** Click and drag up/down to rotate the switch. The switch snaps to the nearest integer position upon release.
* **Mousewheel:** Scroll up or down to step through positions one by one.
* **Visual Cues:**
* If `continuous` is `false`, a 60ยฐ gap is rendered at the bottom of the track to indicate the hard stops.
* The pointer is oversized (`radius + 14`) to reach past the track and cover the tick marks of the active selection.
### State Mirroring (MQTT)
The `SelectorSwitch` is fully integrated with the `StateMirrorEngine`. It provides a dual-key payload for both logic and human-readable monitoring:
* **`val`**: The **Integer Index** (0, 1, 2…). This is the primary key used for GUI synchronization.
* **`pos`**: The **String Label** (e.g., “STANDBY”). Used for human-readable logs and remote monitoring.
**Engine Intelligence:** The system is smart enough to handle remote updates using either key. If a remote device sends `{“val”: “VAC”}`, the engine automatically maps that label back to the correct index for the switch.
—
## ๐งช Demo Capabilities
The Petting Zoo demo (`gui_rotary_selector_demo.json`) showcases the widget’s versatility:
1. **Multimeter Dial:** Classic hard-stop selector with string-based labels.
2. **High-Res Encoder:** 20-position continuous encoder with no visual gap.
3. **Industrial Switch:** Large-scale (250px) high-contrast emergency control.
4. **Audio Gear:** Unique pointer styles like “notch” and “triangle” with gear-shaped bodies.
—
## ๐ Use Case Examples
### 1. Simple 3-Way Mode Selector
“`json
“Mode_Select”: {
“type”: “SelectorSwitch”,
“label_active”: “Operation Mode”,
“positions”: [“Manual”, “Auto”, “Override”],
“value_default”: “Auto”,
“indicator_color”: “#00FF00”
}
“`
### 2. Continuous 20-Position Encoder
“`json
“Fine_Tune”: {
“type”: “SelectorSwitch”,
“label_active”: “Channel Select”,
“positions”: [“1″,”2″,”3″,”4″,”5″,”6″,”7″,”8″,”9″,”10″,”11″,”12″,”13″,”14″,”15″,”16″,”17″,”18″,”19″,”20”],
“continuous”: true,
“shape”: “gear”,
“width”: 150,
“height”: 150
}
“`
—
## ๐ How to Use It
1. **Define your blueprint:** Create a `.json` file in your display directory.
2. **Add the widget:** Define a field with `type: “SelectorSwitch”`.
3. **Set Positions:** Define the `positions` array with your required labels.
4. **Customize:** Adjust `shape`, `pointer_style`, and `indicator_color` to match your equipment’s aesthetic.
5. **Watch the Traffic:** Monitor your MQTT broker. You will see clean integer indices in the `val` field and your labels in the `pos` field.
