-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathwidgets.nim
155 lines (141 loc) · 4.59 KB
/
widgets.nim
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
import vecmath
import colors
import cairo
import input
type
TWidget* = object of TObject
pos*: TVec2f
size*: TVec2f
TLabel* = object of TWidget
text*: string
TButton* = object of TWidget
label*: ref TLabel
color*: TColor
ucolor*: TColor
acolor*: TColor
onClick*: proc(btn: ref TButton)
TListBox* = object of TWidget
color*: TColor
items*: seq[ref TWidget]
TScrollBar* = object of TWidget
offset*: float ## how far down have we scrolled
span*: float ## how big is the area we are covering
#{{{ forward declearations
#{{{ initialization functions
proc initButton*(pos: TVec2f, name: string): TButton
proc initListBox*(pos: TVec2f = vec2f(0,0),
size: TVec2f = vec2f(100,100),
color: TColor = colDarkRed): TListBox
#}}}
#{{{ list layout
proc layoutList(elms: var seq[ref TWidget], anchor: ref TWidget)
#}}}
#}}}
proc initButton*(pos: TVec2f, name: string = ""): TButton =
result.pos = pos
result.size = vec2f(100, 50)
new(result.label)
result.label.text = name
result.label.pos = vec2f(0,0)
# snazzy!
result.ucolor = colAqua ##un-active color
result.acolor = colDarkMagenta ##active-color
result.color = result.ucolor
#-------- LIST BOX NONVIRTUAL
proc initListBox*(pos,size: TVec2f, color: TColor): TListBox =
result.pos = pos
result.size = size
result.color = color
result.items = @[]
proc add*(self: ref TListBox, elm: ref TWidget) =
self.items.add(elm)
layoutList(self.items, self)
proc add*(self: ref TListBox, name: string, action: proc()) =
var btn: ref TButton
new(btn)
btn[] = initButton(vec2f(0,0), name)
btn.onClick = proc(elm: ref TButton) = action()
self.items.add(btn)
layoutList(self.items, self)
#-------- END LIST BOX NONVIRTUAL
method draw*(ctx: PContext, elm: ref TWidget) =
quit("need to override draw")
method draw*(ctx: PContext, btn: ref TButton) =
using ctx
save()
var (r,g,b) = extractRGB(btn.color)
set_source_rgb(r.float / 255.0, g.float / 255.0, b.float / 255.0)
rectangle(btn.pos.x, btn.pos.y, btn.size.x, btn.size.y)
fill()
translate(btn.pos.x + 2, btn.pos.y + 10)
draw(ctx, btn.label)
restore()
method draw*(ctx: PContext, lbl: ref TLabel) =
using ctx
save()
move_to(lbl.pos.x, lbl.pos.y)
select_font_face("monospace", FONT_SLANT_NORMAL, FONT_WEIGHT_NORMAL)
set_font_size(12)
set_source_rgb(0,0,0)
show_text(lbl.text)
restore()
method draw*(ctx: PContext, lb: ref TListBox) =
using ctx
save()
var (r,g,b) = extractRGB(lb.color)
set_source_rgb(r.float/255.0, g.float/255.0, b.float/255.0)
rectangle(lb.pos.x, lb.pos.y, lb.size.x, lb.size.y)
fill()
for elm in lb.items: draw(ctx, elm)
restore()
proc DrawWidgets*(ctx: PContext, group: seq[ref TWidget]) =
for elm in group:
draw(ctx, elm)
#{{{ ------ update functions
method onMouseMove*(self: ref TWidget, mouse: TMouse) = discard
method onMouseEnter*(self: ref TWidget, mouse: TMouse) = discard
method onMouseLeave*(self: ref TWidget, mouse: TMouse) = discard
method onMouseButton*(self: ref TWidget, mouse: TMouse) = discard
proc checkOverlap(self: ref TWidget, point: TVec2f): bool =
if point.x > self.pos.x and point.x < self.pos.x+self.size.x and
point.y > self.pos.y and point.y < self.pos.y+self.size.y:
result = true
else:
result = false
proc checkOverlap(self: ref TWidget, mouse: TMouse): bool =
result = checkOverlap(self, vec2f(mouse.x, mouse.y))
method handleInput*(self: ref TWidget, inp: TInput, last: TInput) =
if checkOverlap(self, inp.mouse):
if not checkOverlap(self, last.mouse):
self.onMouseEnter(inp.mouse)
self.onMouseMove(inp.mouse)
if inp.mouse.buttons.card > 0:
self.onMouseButton(inp.mouse)
else:
if checkOverlap(self, last.mouse):
self.onMouseLeave(inp.mouse)
method handleInput(self: ref TListBox, inp: TInput, last: TInput) =
for elm in self.items:
elm.handleInput(inp, last)
proc handleAllInput*(group: seq[ref TWidget], inp: TInput) =
var last {.global.}: TInput
for elm in group:
handleInput(elm, inp, last)
last = inp
method onMouseEnter*(self: ref TButton, mouse: TMouse) =
self.color = self.acolor
method onMouseLeave*(self: ref TButton, mouse: TMouse) =
self.color = self.ucolor
method onMouseButton*(self: ref TButton, mouse: TMouse) =
if self.onCLick != nil:
self.onClick(self)
#}}}
#{{{ layout functions for lists
proc layoutList(elms: var seq[ref TWidget], anchor: ref TWidget) =
var ystep = anchor.size.y / elms.len.float
for i,elm in elms.pairs():
elm.size.x = anchor.size.x
elm.size.y = ystep
elm.pos.x = anchor.pos.x
elm.pos.y = anchor.pos.y + (i.float * ystep)
#}}}