-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathwidget_library.py
More file actions
195 lines (156 loc) · 7.03 KB
/
widget_library.py
File metadata and controls
195 lines (156 loc) · 7.03 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
"""
Widget Library for LVGL Editor
"""
import tkinter as tk
from tkinter import ttk
from typing import Dict, List, Any, Callable
from widgets import LVGL_WIDGETS
class WidgetLibrary:
"""Widget library panel for selecting widgets to place"""
def __init__(self, parent, selection_callback: Callable):
self.parent = parent
self.selection_callback = selection_callback
# State
self.selected_widget = None
# Create UI
self.create_ui()
def create_ui(self):
"""Create the widget library UI"""
# Main frame
main_frame = ttk.LabelFrame(self.parent, text="Widget Library", padding=5)
main_frame.pack(fill=tk.BOTH, expand=True, pady=(0, 5))
# Search frame
search_frame = ttk.Frame(main_frame)
search_frame.pack(fill=tk.X, pady=(0, 5))
ttk.Label(search_frame, text="Search:").pack(side=tk.LEFT)
self.search_var = tk.StringVar()
search_entry = ttk.Entry(search_frame, textvariable=self.search_var)
search_entry.pack(side=tk.RIGHT, fill=tk.X, expand=True, padx=(5, 0))
self.search_var.trace('w', self.on_search_changed)
# Widget categories notebook
self.notebook = ttk.Notebook(main_frame)
self.notebook.pack(fill=tk.BOTH, expand=True)
# Create category tabs
self.category_frames = {}
self.widget_buttons = {}
for category_name, widgets in LVGL_WIDGETS.items():
self.create_category_tab(category_name, widgets)
def create_category_tab(self, category_name: str, widgets: Dict[str, Dict]):
"""Create a tab for a widget category"""
# Create scrollable frame
tab_frame = ttk.Frame(self.notebook)
self.notebook.add(tab_frame, text=category_name)
# Canvas for scrolling
canvas = tk.Canvas(tab_frame)
scrollbar = ttk.Scrollbar(tab_frame, orient="vertical", command=canvas.yview)
scrollable_frame = ttk.Frame(canvas)
scrollable_frame.bind(
"<Configure>",
lambda e: canvas.configure(scrollregion=canvas.bbox("all"))
)
canvas.create_window((0, 0), window=scrollable_frame, anchor="nw")
canvas.configure(yscrollcommand=scrollbar.set)
canvas.pack(side="left", fill="both", expand=True)
scrollbar.pack(side="right", fill="y")
# Store references
self.category_frames[category_name] = scrollable_frame
self.widget_buttons[category_name] = {}
# Create widget buttons
for widget_type, widget_info in widgets.items():
self.create_widget_button(scrollable_frame, category_name, widget_type, widget_info)
# Bind mousewheel
def _on_mousewheel(event):
canvas.yview_scroll(int(-1*(event.delta/120)), "units")
canvas.bind("<MouseWheel>", _on_mousewheel)
def create_widget_button(self, parent, category: str, widget_type: str, widget_info: Dict):
"""Create a button for a widget type"""
# Button frame
button_frame = ttk.Frame(parent, relief='ridge', borderwidth=1)
button_frame.pack(fill=tk.X, pady=2, padx=2)
# Main button
button = tk.Button(
button_frame,
text=f"{widget_info.get('icon', '◼')} {widget_info['name']}",
font=('Arial', 10),
anchor='w',
bg='white',
relief='flat',
cursor='hand2',
command=lambda: self.select_widget(widget_type)
)
button.pack(fill=tk.X, pady=2, padx=2)
# Description label
desc_label = ttk.Label(
button_frame,
text=widget_info.get('description', ''),
font=('Arial', 8),
foreground='gray'
)
desc_label.pack(fill=tk.X, padx=4, pady=(0, 2))
# Store button reference
self.widget_buttons[category][widget_type] = {
'frame': button_frame,
'button': button,
'info': widget_info
}
# Bind hover effects
def on_enter(event):
if self.selected_widget != widget_type:
button.config(bg='#e6f3ff')
def on_leave(event):
if self.selected_widget != widget_type:
button.config(bg='white')
button.bind("<Enter>", on_enter)
button.bind("<Leave>", on_leave)
def select_widget(self, widget_type: str):
"""Select a widget type"""
# Clear previous selection
if self.selected_widget:
self.clear_selection()
# Set new selection
self.selected_widget = widget_type
# Highlight selected button
for category_buttons in self.widget_buttons.values():
if widget_type in category_buttons:
button = category_buttons[widget_type]['button']
button.config(bg='#0078d4', fg='white')
break
# Notify callback
self.selection_callback(widget_type)
def clear_selection(self):
"""Clear widget selection"""
if self.selected_widget:
# Find and unhighlight the selected button
for category_buttons in self.widget_buttons.values():
if self.selected_widget in category_buttons:
button = category_buttons[self.selected_widget]['button']
button.config(bg='white', fg='black')
break
self.selected_widget = None
def on_search_changed(self, *args):
"""Handle search text changes"""
search_text = self.search_var.get().lower()
for category_name, category_buttons in self.widget_buttons.items():
for widget_type, button_info in category_buttons.items():
widget_info = button_info['info']
frame = button_info['frame']
# Check if widget matches search
matches = (
search_text in widget_type.lower() or
search_text in widget_info['name'].lower() or
search_text in widget_info.get('description', '').lower()
)
# Show/hide based on search
if search_text == '' or matches:
frame.pack(fill=tk.X, pady=2, padx=2)
else:
frame.pack_forget()
def get_widget_info(self, widget_type: str) -> Dict[str, Any]:
"""Get information about a widget type"""
for category_widgets in LVGL_WIDGETS.values():
if widget_type in category_widgets:
return category_widgets[widget_type]
return {}
def get_selected_widget(self) -> str:
"""Get the currently selected widget type"""
return self.selected_widget