Skip to content

Commit 1e08cbb

Browse files
committed
Add an example of creating custom widgets using a canvas
1 parent c6819e9 commit 1e08cbb

File tree

1 file changed

+159
-0
lines changed

1 file changed

+159
-0
lines changed

Custom Widgets.lua

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
----------------------------------------------------------------------
2+
-- This example shows how to create custom widgets using the canvas.
3+
---------------------------------------------------------------------
4+
5+
local dlg = Dialog("Custom Widgets")
6+
7+
local mouse = {position = Point(0, 0), leftClick = false}
8+
9+
local focusedWidget = nil
10+
11+
local customButton = {
12+
bounds = Rectangle(5, 5, 80, 40),
13+
state = {
14+
normal = {part = "button_normal", color = "button_normal_text"},
15+
hot = {part = "button_hot", color = "button_hot_text"},
16+
selected = {part = "button_selected", color = "button_selected_text"},
17+
focused = {part = "button_focused", color = "button_normal_text"}
18+
},
19+
text = "Custom Button",
20+
onclick = function() print("Clicked <Custom Button>") end
21+
}
22+
23+
local doubleButtonLeft = {
24+
bounds = Rectangle(5, 50, 60, 20),
25+
state = {
26+
normal = {
27+
part = "drop_down_button_left_normal",
28+
color = "button_normal_text"
29+
},
30+
hot = {part = "drop_down_button_left_hot", color = "button_hot_text"},
31+
selected = {
32+
part = "drop_down_button_left_selected",
33+
color = "button_selected_text"
34+
},
35+
focused = {
36+
part = "drop_down_button_left_focused",
37+
color = "button_normal_text"
38+
}
39+
},
40+
text = "Search",
41+
onclick = function() print("Clicked <Search Button Left>") end
42+
}
43+
44+
local doubleButtonRight = {
45+
bounds = Rectangle(65, 50, 20, 20),
46+
state = {
47+
normal = {
48+
part = "drop_down_button_right_normal",
49+
color = "button_normal_text"
50+
},
51+
hot = {part = "drop_down_button_right_hot", color = "button_hot_text"},
52+
selected = {
53+
part = "drop_down_button_right_selected",
54+
color = "button_selected_text"
55+
},
56+
focused = {
57+
part = "drop_down_button_right_focused",
58+
color = "button_normal_text"
59+
}
60+
},
61+
icon = "tool_zoom",
62+
onclick = function() print("Clicked <Search Button Right>") end
63+
}
64+
65+
local sunkenMagicWand = {
66+
bounds = Rectangle(90, 5, 65, 65),
67+
state = {
68+
normal = {part = "sunken_normal", color = "button_normal_text"},
69+
selected = {part = "sunken_focused", color = "button_normal_text"},
70+
focused = {part = "sunken_focused", color = "button_normal_text"}
71+
},
72+
icon = "tool_magic_wand",
73+
onclick = function() print("Clicked <Sunken Magic Wand>") end
74+
}
75+
76+
local customWidgets = {
77+
customButton, doubleButtonLeft, doubleButtonRight, sunkenMagicWand
78+
}
79+
80+
dlg:canvas{
81+
id = "canvas",
82+
width = 160,
83+
height = 75,
84+
onpaint = function(ev)
85+
local ctx = ev.context
86+
87+
-- Draw each custom widget
88+
for _, widget in ipairs(customWidgets) do
89+
local state = widget.state.normal
90+
91+
if widget == focusedWidget then
92+
state = widget.state.focused
93+
end
94+
95+
local isMouseOver = widget.bounds:contains(mouse.position)
96+
97+
if isMouseOver then
98+
state = widget.state.hot or state
99+
100+
if mouse.leftClick then
101+
state = widget.state.selected
102+
end
103+
end
104+
105+
ctx:drawThemeRect(state.part, widget.bounds)
106+
107+
local center = Point(widget.bounds.x + widget.bounds.width / 2,
108+
widget.bounds.y + widget.bounds.height / 2)
109+
110+
if widget.icon then
111+
-- Assuming default icon size of 16x16 pixels
112+
local size = Rectangle(0, 0, 16, 16)
113+
114+
ctx:drawThemeImage(widget.icon, center.x - size.width / 2,
115+
center.y - size.height / 2)
116+
elseif widget.text then
117+
local size = ctx:measureText(widget.text)
118+
119+
ctx.color = app.theme.color[state.color]
120+
ctx:fillText(widget.text, center.x - size.width / 2,
121+
center.y - size.height / 2)
122+
end
123+
end
124+
end,
125+
onmousemove = function(ev)
126+
-- Update the mouse position
127+
mouse.position = Point(ev.x, ev.y)
128+
129+
dlg:repaint()
130+
end,
131+
onmousedown = function(ev)
132+
-- Update information about left mouse button being pressed
133+
mouse.leftClick = ev.button == MouseButton.LEFT
134+
135+
dlg:repaint()
136+
end,
137+
onmouseup = function(ev)
138+
-- When releasing left mouse button over a widget, call `onclick` method
139+
if mouse.leftClick then
140+
for _, widget in ipairs(customWidgets) do
141+
local isMouseOver = widget.bounds:contains(mouse.position)
142+
143+
if isMouseOver then
144+
widget.onclick()
145+
146+
-- Last clicked widget has focus on it
147+
focusedWidget = widget
148+
end
149+
end
150+
end
151+
152+
-- Update information about left mouse button being released
153+
mouse.leftClick = false
154+
155+
dlg:repaint()
156+
end
157+
}
158+
159+
dlg:show{wait = false}

0 commit comments

Comments
 (0)