rubygoo 0.0.5 → 0.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.txt +8 -0
- data/Manifest.txt +9 -0
- data/README.txt +84 -25
- data/Rakefile +36 -2
- data/TODO +5 -4
- data/lib/rubygoo/adapters/gosu_app_adapter.rb +216 -220
- data/lib/rubygoo/adapters/gosu_render_adapter.rb +45 -17
- data/lib/rubygoo/adapters/rubygame_render_adapter.rb +14 -7
- data/lib/rubygoo/app.rb +82 -24
- data/lib/rubygoo/button.rb +29 -10
- data/lib/rubygoo/check_box.rb +21 -11
- data/lib/rubygoo/container.rb +53 -33
- data/lib/rubygoo/dialog.rb +4 -9
- data/lib/rubygoo/label.rb +14 -9
- data/lib/rubygoo/radio_button.rb +29 -0
- data/lib/rubygoo/radio_group.rb +40 -0
- data/lib/rubygoo/tab_group.rb +67 -0
- data/lib/rubygoo/text_field.rb +49 -31
- data/lib/rubygoo/widget.rb +53 -7
- data/lib/rubygoo.rb +4 -0
- data/samples/create_gui.rb +67 -0
- data/samples/gosu_app.rb +8 -61
- data/samples/icon.png +0 -0
- data/samples/rubygame_app.rb +5 -56
- data/test/app_spec.rb +24 -0
- data/test/test_rubygoo.rb +1 -0
- data/test/test_setup.rb +4 -0
- data/test/widget_spec.rb +19 -0
- data/themes/default/config.yml +2 -0
- metadata +25 -5
data/lib/rubygoo/app.rb
CHANGED
@@ -1,14 +1,15 @@
|
|
1
1
|
module Rubygoo
|
2
2
|
class App < Container
|
3
3
|
|
4
|
-
DEFAULT_PARAMS = {:theme=>'default',:x=>10,:y=>10,:
|
5
|
-
attr_accessor :theme_name, :theme, :data_dir, :theme_dir, :renderer
|
4
|
+
DEFAULT_PARAMS = {:theme=>'default',:x=>10,:y=>10,:data_dir=>File.join(File.dirname(__FILE__),"..","..","themes"),:mouse_cursor => true}
|
5
|
+
attr_accessor :theme_name, :theme, :data_dir, :theme_dir, :renderer, :tab_groups
|
6
6
|
|
7
7
|
def initialize(opts={})
|
8
8
|
merged_opts = DEFAULT_PARAMS.merge opts
|
9
9
|
@widgets = []
|
10
|
-
@
|
11
|
-
@
|
10
|
+
@tab_groups = []
|
11
|
+
@tab_groups << TabGroup.new
|
12
|
+
|
12
13
|
theme_name = merged_opts[:theme]
|
13
14
|
@data_dir = merged_opts[:data_dir]
|
14
15
|
@theme_name = theme_name
|
@@ -17,13 +18,14 @@ module Rubygoo
|
|
17
18
|
super merged_opts
|
18
19
|
|
19
20
|
# should this go here?
|
20
|
-
@
|
21
|
-
if @
|
21
|
+
@mouse_cursor = merged_opts[:mouse_cursor]
|
22
|
+
if @mouse_cursor
|
22
23
|
@mouse = MouseCursor.new
|
23
24
|
@mouse.parent = self
|
24
25
|
@mouse.app = self.app
|
25
26
|
@mouse.added
|
26
27
|
end
|
28
|
+
@mouse_dragging = false
|
27
29
|
end
|
28
30
|
|
29
31
|
def app()
|
@@ -38,30 +40,28 @@ module Rubygoo
|
|
38
40
|
def draw(screen)
|
39
41
|
@renderer.start_drawing
|
40
42
|
super @renderer
|
41
|
-
@mouse.draw @renderer if @
|
43
|
+
@mouse.draw @renderer if @mouse_cursor
|
42
44
|
@renderer.finish_drawing
|
43
45
|
end
|
44
46
|
|
47
|
+
def focus(w)
|
48
|
+
@tab_groups.last.focus w
|
49
|
+
end
|
50
|
+
|
45
51
|
def add_tabbed_widget(w)
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
@
|
52
|
+
@tab_groups[0].add w
|
53
|
+
end
|
54
|
+
|
55
|
+
def add_tab_group(tg)
|
56
|
+
@tab_groups << tg
|
51
57
|
end
|
52
58
|
|
53
59
|
def focus_back()
|
54
|
-
@
|
55
|
-
@focussed_widget += 1
|
56
|
-
@focussed_widget %= @tabbed_widgets.size
|
57
|
-
@tabbed_widgets[@focussed_widget].focus
|
60
|
+
@tab_groups.last.previous
|
58
61
|
end
|
59
62
|
|
60
63
|
def focus_forward()
|
61
|
-
@
|
62
|
-
@focussed_widget -= 1
|
63
|
-
@focussed_widget %= @tabbed_widgets.size
|
64
|
-
@tabbed_widgets[@focussed_widget].focus
|
64
|
+
@tab_groups.last.next
|
65
65
|
end
|
66
66
|
|
67
67
|
def on_event(event)
|
@@ -79,13 +79,71 @@ module Rubygoo
|
|
79
79
|
else
|
80
80
|
modal_keyboard_call :key_pressed, event
|
81
81
|
end
|
82
|
+
when :mouse_down
|
83
|
+
modal_mouse_call :mouse_down, event
|
84
|
+
# TODO: I know this is simplistic and doesn't account for which button
|
85
|
+
# is being pressed/released
|
86
|
+
@mouse_start_x = event.data[:x]
|
87
|
+
@mouse_start_y = event.data[:y]
|
88
|
+
when :mouse_up
|
89
|
+
x = event.data[:x]
|
90
|
+
y = event.data[:y]
|
91
|
+
if @mouse_start_x == x and @mouse_start_y == y
|
92
|
+
modal_mouse_call :mouse_up, event
|
93
|
+
else
|
94
|
+
modal_mouse_call :mouse_drag, event
|
95
|
+
end
|
96
|
+
@mouse_start_x = nil
|
97
|
+
@mouse_start_y = nil
|
98
|
+
when :mouse_motion
|
99
|
+
x = event.data[:x]
|
100
|
+
y = event.data[:y]
|
101
|
+
if @mouse_start_x
|
102
|
+
modal_mouse_call :mouse_dragging, event
|
103
|
+
else
|
104
|
+
modal_mouse_call :mouse_motion, event
|
105
|
+
end
|
106
|
+
@mouse.mouse_motion event if @mouse_cursor
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
# redirects all events to this widget
|
111
|
+
def add_modal(widget)
|
112
|
+
@modal_widgets << widget
|
113
|
+
tg = TabGroup.new
|
114
|
+
tg.add(widget)
|
115
|
+
self.app.add_tab_group tg
|
116
|
+
add widget
|
117
|
+
end
|
118
|
+
|
119
|
+
def remove_modal(widget)
|
120
|
+
self.app.pop_tab_group
|
121
|
+
remove widget
|
122
|
+
end
|
123
|
+
|
124
|
+
def pop_tab_group()
|
125
|
+
@tab_groups.pop
|
126
|
+
end
|
127
|
+
|
128
|
+
# distribute our mouse events to our modals first
|
129
|
+
def modal_mouse_call(meth, event)
|
130
|
+
if @modal_widgets.empty?
|
131
|
+
@widgets.each do |w|
|
132
|
+
w.send meth, event if w.contains? [event.data[:x],event.data[:y]]
|
133
|
+
end
|
82
134
|
else
|
83
|
-
|
84
|
-
|
135
|
+
@modal_widgets.last.send meth, event
|
136
|
+
end
|
137
|
+
end
|
85
138
|
|
86
|
-
|
87
|
-
|
139
|
+
# distribute our keyboard events to our modals first
|
140
|
+
def modal_keyboard_call(meth, event)
|
141
|
+
if @modal_widgets.empty?
|
142
|
+
@widgets.each do |w|
|
143
|
+
w.send meth, event if w.focussed?
|
88
144
|
end
|
145
|
+
else
|
146
|
+
@modal_widgets.last.send meth, event
|
89
147
|
end
|
90
148
|
end
|
91
149
|
|
data/lib/rubygoo/button.rb
CHANGED
@@ -3,6 +3,9 @@ module Rubygoo
|
|
3
3
|
can_fire :pressed
|
4
4
|
def initialize(text, opts={})
|
5
5
|
super opts
|
6
|
+
|
7
|
+
@icon = opts[:icon]
|
8
|
+
|
6
9
|
@text = text
|
7
10
|
end
|
8
11
|
|
@@ -14,9 +17,13 @@ module Rubygoo
|
|
14
17
|
@border_color = theme_property :border_color
|
15
18
|
@focus_color = theme_property :focus_color
|
16
19
|
@font_file = File.join(@app.theme_dir,font)
|
17
|
-
|
18
20
|
@rendered_text ||= @app.renderer.render_text @text, @font_file, @font_size, @color
|
19
|
-
@
|
21
|
+
@w = @rendered_text.width+2*@x_pad
|
22
|
+
@h = @rendered_text.height+2*@y_pad
|
23
|
+
@x = @x - @x_pad
|
24
|
+
@y = @y - @y_pad
|
25
|
+
|
26
|
+
update_rect
|
20
27
|
end
|
21
28
|
|
22
29
|
# called when there is a mouse click
|
@@ -24,6 +31,11 @@ module Rubygoo
|
|
24
31
|
fire :pressed, event
|
25
32
|
end
|
26
33
|
|
34
|
+
# called when there is a mouse click at the end of a drag
|
35
|
+
def mouse_drag(event)
|
36
|
+
fire :pressed, event
|
37
|
+
end
|
38
|
+
|
27
39
|
# called when a key press is sent to us
|
28
40
|
def key_pressed(event)
|
29
41
|
case event.data[:key]
|
@@ -33,21 +45,28 @@ module Rubygoo
|
|
33
45
|
end
|
34
46
|
|
35
47
|
def draw(adapter)
|
48
|
+
x1 = @rect[0]
|
49
|
+
y1 = @rect[1]
|
50
|
+
x2 = @rect[2] + x1
|
51
|
+
y2 = @rect[3] + y1
|
52
|
+
|
53
|
+
|
36
54
|
if @focussed
|
37
|
-
adapter.fill
|
55
|
+
adapter.fill x1, y1, x2, y2, @focus_color
|
38
56
|
elsif @bg_color
|
39
|
-
adapter.fill
|
57
|
+
adapter.fill x1, y1, x2, y2, @bg_color
|
40
58
|
end
|
41
59
|
if @border_color
|
42
|
-
x1 = @rect[0]
|
43
|
-
y1 = @rect[1]
|
44
|
-
x2 = @rect[2] + x1
|
45
|
-
y2 = @rect[3] + y1
|
46
60
|
adapter.draw_box x1, y1, x2, y2, @border_color
|
47
61
|
end
|
62
|
+
if @icon
|
63
|
+
# TODO center icon
|
64
|
+
ix = x1#+((x2-x1)-@icon.w)
|
65
|
+
iy = y1#+((y2-y1)-@icon.h)
|
66
|
+
adapter.draw_image @icon, ix+@x_pad,iy+@y_pad
|
67
|
+
end
|
48
68
|
|
49
|
-
|
50
|
-
adapter.draw_image @rendered_text, @x, @y, @color
|
69
|
+
adapter.draw_image @rendered_text, @x+@x_pad, @y+@y_pad, @color
|
51
70
|
|
52
71
|
end
|
53
72
|
end
|
data/lib/rubygoo/check_box.rb
CHANGED
@@ -31,12 +31,12 @@ module Rubygoo
|
|
31
31
|
|
32
32
|
def check()
|
33
33
|
@checked = true
|
34
|
-
fire :checked
|
34
|
+
fire :checked, self
|
35
35
|
end
|
36
36
|
|
37
37
|
def uncheck()
|
38
38
|
@checked = false
|
39
|
-
fire :checked
|
39
|
+
fire :checked, self
|
40
40
|
end
|
41
41
|
|
42
42
|
# called when there is a mouse click
|
@@ -44,6 +44,11 @@ module Rubygoo
|
|
44
44
|
toggle
|
45
45
|
end
|
46
46
|
|
47
|
+
# called when there is a mouse click at the end of a drag
|
48
|
+
def mouse_drag(event)
|
49
|
+
toggle
|
50
|
+
end
|
51
|
+
|
47
52
|
# called when a key press is sent to us
|
48
53
|
def key_pressed(event)
|
49
54
|
case event.data[:key]
|
@@ -52,23 +57,28 @@ module Rubygoo
|
|
52
57
|
end
|
53
58
|
end
|
54
59
|
|
55
|
-
def draw(
|
60
|
+
def draw(adapter)
|
61
|
+
x1 = @rect[0]
|
62
|
+
y1 = @rect[1]
|
63
|
+
x2 = @rect[2] + x1
|
64
|
+
y2 = @rect[3] + y1
|
56
65
|
if @focussed
|
57
|
-
|
66
|
+
adapter.fill x1, y1, x2, y2, @focus_color
|
58
67
|
elsif @bg_color
|
59
|
-
|
68
|
+
adapter.fill x1, y1, x2, y2, @bg_color
|
60
69
|
end
|
61
70
|
|
62
71
|
if @checked
|
63
|
-
|
72
|
+
rect = @rect.inflate(-@x_pad,-@y_pad)
|
73
|
+
cx1 = rect[0]
|
74
|
+
cy1 = rect[1]
|
75
|
+
cx2 = rect[2] + x1
|
76
|
+
cy2 = rect[3] + y1
|
77
|
+
adapter.fill cx1, cy1, cx2, cy2, @checked_color
|
64
78
|
end
|
65
79
|
|
66
80
|
if @border_color
|
67
|
-
x1
|
68
|
-
y1 = @rect[1]
|
69
|
-
x2 = @rect[2] + x1
|
70
|
-
y2 = @rect[3] + y1
|
71
|
-
screen.draw_box x1, y1, x2, y2, @border_color
|
81
|
+
adapter.draw_box x1, y1, x2, y2, @border_color
|
72
82
|
end
|
73
83
|
end
|
74
84
|
end
|
data/lib/rubygoo/container.rb
CHANGED
@@ -1,7 +1,8 @@
|
|
1
|
+
require 'publisher'
|
1
2
|
module Rubygoo
|
2
3
|
class Container < Widget
|
3
|
-
|
4
|
-
attr_accessor :widgets, :bg_color, :rect
|
4
|
+
extend Publisher
|
5
|
+
attr_accessor :widgets, :bg_color, :rect, :queued_widgets
|
5
6
|
|
6
7
|
def initialize(opts={})
|
7
8
|
super opts
|
@@ -14,25 +15,33 @@ module Rubygoo
|
|
14
15
|
|
15
16
|
# called when we are added to another container
|
16
17
|
def added()
|
18
|
+
@bg_color = theme_property :bg_color
|
17
19
|
add *@queued_widgets
|
18
20
|
@queued_widgets = []
|
19
21
|
end
|
20
22
|
|
21
|
-
def add_modal(widget)
|
22
|
-
@modal_widgets << widget
|
23
|
-
add widget
|
24
|
-
end
|
25
|
-
|
26
23
|
# Add widget(s) to the container.
|
27
24
|
def add(*widgets)
|
28
25
|
widgets.uniq.each do |w|
|
29
26
|
unless @widgets.include? w
|
30
27
|
if self.app
|
28
|
+
if w.relative
|
29
|
+
w.x += @x
|
30
|
+
w.y += @y
|
31
|
+
w.update_rect
|
32
|
+
end
|
31
33
|
w.container = self
|
32
34
|
w.parent = self
|
33
35
|
w.app = self.app
|
34
|
-
w.
|
36
|
+
if !modal? and w.tab_to? and !w.modal?
|
37
|
+
w.app.add_tabbed_widget w
|
38
|
+
end
|
35
39
|
w.added
|
40
|
+
|
41
|
+
w.when :resized do |resized_widget|
|
42
|
+
resize resized_widget
|
43
|
+
end
|
44
|
+
|
36
45
|
@widgets << w
|
37
46
|
else
|
38
47
|
@queued_widgets << w
|
@@ -55,19 +64,23 @@ module Rubygoo
|
|
55
64
|
end
|
56
65
|
|
57
66
|
# draw ourself and our children
|
58
|
-
def draw(
|
67
|
+
def draw(adapter)
|
59
68
|
# any container specific code here (border_colors?)
|
60
69
|
if @bg_color
|
61
70
|
if app == self
|
62
|
-
|
71
|
+
adapter.fill_screen @bg_color
|
63
72
|
else
|
64
|
-
|
73
|
+
x1 = @rect[0]
|
74
|
+
y1 = @rect[1]
|
75
|
+
x2 = @rect[2] + x1
|
76
|
+
y2 = @rect[3] + y1
|
77
|
+
adapter.fill x1, y1, x2, y2, @bg_color
|
65
78
|
end
|
66
79
|
end
|
67
80
|
|
68
81
|
# draw kiddies
|
69
82
|
@widgets.each do |w|
|
70
|
-
w.draw
|
83
|
+
w.draw adapter
|
71
84
|
end
|
72
85
|
end
|
73
86
|
|
@@ -92,6 +105,13 @@ module Rubygoo
|
|
92
105
|
end
|
93
106
|
end
|
94
107
|
|
108
|
+
# called when there is a mouse release after dragging
|
109
|
+
def mouse_drag(event)
|
110
|
+
@widgets.each do |w|
|
111
|
+
w.mouse_drag event if w.contains? [event.data[:x],event.data[:y]]
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
95
115
|
# pass on the key press to our widgets
|
96
116
|
def key_pressed(event)
|
97
117
|
@widgets.each do |w|
|
@@ -106,27 +126,6 @@ module Rubygoo
|
|
106
126
|
end
|
107
127
|
end
|
108
128
|
|
109
|
-
# distribute our mouse events to our modals first
|
110
|
-
def modal_mouse_call(meth, event)
|
111
|
-
if @modal_widgets.empty?
|
112
|
-
@widgets.each do |w|
|
113
|
-
w.send meth, event if w.contains? [event.data[:x],event.data[:y]]
|
114
|
-
end
|
115
|
-
else
|
116
|
-
@modal_widgets.last.send meth, event
|
117
|
-
end
|
118
|
-
end
|
119
|
-
|
120
|
-
# distribute our keyboard events to our modals first
|
121
|
-
def modal_keyboard_call(meth, event)
|
122
|
-
if @modal_widgets.empty?
|
123
|
-
@widgets.each do |w|
|
124
|
-
w.send meth, event if w.focussed?
|
125
|
-
end
|
126
|
-
else
|
127
|
-
@modal_widgets.last.send meth, event
|
128
|
-
end
|
129
|
-
end
|
130
129
|
|
131
130
|
# called each update cycle with the amount of time that has passed. useful
|
132
131
|
# for animations, etc
|
@@ -135,6 +134,27 @@ module Rubygoo
|
|
135
134
|
w.update time
|
136
135
|
end
|
137
136
|
end
|
137
|
+
|
138
|
+
# does this widget want tabbed focus? Containers don't usually
|
139
|
+
def tab_to?
|
140
|
+
false
|
141
|
+
end
|
142
|
+
|
143
|
+
# called when we need to update our size
|
144
|
+
def resize(w)
|
145
|
+
# check the rects of all our children?
|
146
|
+
max_w = 1
|
147
|
+
max_h = 1
|
148
|
+
@widgets.each do |w|
|
149
|
+
w_width = w.x + w.w
|
150
|
+
w_height = w.y + w.h
|
151
|
+
max_w = w_width if w_width > max_w
|
152
|
+
max_h = w_height if w_height > max_h
|
153
|
+
end
|
154
|
+
@w = max_w - @x + 2*@x_pad
|
155
|
+
@h = max_h - @y + 2*@y_pad
|
156
|
+
update_rect
|
157
|
+
end
|
138
158
|
end
|
139
159
|
end
|
140
160
|
|
data/lib/rubygoo/dialog.rb
CHANGED
@@ -19,21 +19,16 @@ module Rubygoo
|
|
19
19
|
@rect = Rect.new [@x-@x_pad,@y-@y_pad,@w+2*@x_pad,@h+2*@y_pad]
|
20
20
|
end
|
21
21
|
|
22
|
+
def modal?()
|
23
|
+
@modal_target
|
24
|
+
end
|
25
|
+
|
22
26
|
# show the dialog by adding it to the @modal_target and
|
23
27
|
# intercepting all of its events
|
24
28
|
def show()
|
25
29
|
@modal_target.add_modal self
|
26
30
|
end
|
27
31
|
|
28
|
-
# def on_mouse_dragging(x,y,event); end
|
29
|
-
# def on_mouse_motion(event); end
|
30
|
-
# def on_mouse_drag(start_x, start_y, event); end
|
31
|
-
# def on_click(event); end
|
32
|
-
# def on_key_up(event); end
|
33
|
-
# def draw(destination); end
|
34
|
-
# def on_network(event); end
|
35
|
-
# def update(time);end
|
36
|
-
|
37
32
|
end
|
38
33
|
end
|
39
34
|
|
data/lib/rubygoo/label.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'publisher'
|
1
2
|
module Rubygoo
|
2
3
|
class Label < Widget
|
3
4
|
def initialize(text, opts={})
|
@@ -23,22 +24,26 @@ module Rubygoo
|
|
23
24
|
@rect = Rect.new [@x,@y,@rendered_text.width+@x_pad,@rendered_text.height+@y_pad]
|
24
25
|
end
|
25
26
|
|
26
|
-
def draw(
|
27
|
+
def draw(adapter)
|
28
|
+
x1 = @rect[0]
|
29
|
+
y1 = @rect[1]
|
30
|
+
x2 = @rect[2] + x1
|
31
|
+
y2 = @rect[3] + y1
|
27
32
|
if @focussed
|
28
|
-
|
33
|
+
adapter.fill x1, y1, x2, y2, @focus_color
|
29
34
|
elsif @bg_color
|
30
|
-
|
35
|
+
adapter.fill x1, y1, x2, y2, @bg_color
|
31
36
|
end
|
32
37
|
|
33
38
|
if @border_color
|
34
|
-
x1
|
35
|
-
y1 = @rect[1]
|
36
|
-
x2 = @rect[2] + x1
|
37
|
-
y2 = @rect[3] + y1
|
38
|
-
screen.draw_box x1, y1, x2, y2, @border_color
|
39
|
+
adapter.draw_box x1, y1, x2, y2, @border_color
|
39
40
|
end
|
40
41
|
|
41
|
-
|
42
|
+
adapter.draw_image @rendered_text, @x, @y, @color
|
43
|
+
end
|
44
|
+
|
45
|
+
def tab_to?()
|
46
|
+
false
|
42
47
|
end
|
43
48
|
end
|
44
49
|
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Rubygoo
|
2
|
+
# this is basically a round checkbox
|
3
|
+
class RadioButton < CheckBox
|
4
|
+
|
5
|
+
def draw(adapter)
|
6
|
+
x1 = @rect[0]
|
7
|
+
y1 = @rect[1]
|
8
|
+
x2 = @rect[2] + x1
|
9
|
+
y2 = @rect[3] + y1
|
10
|
+
|
11
|
+
radius = (@rect[2]/2.0).ceil
|
12
|
+
|
13
|
+
if @focussed
|
14
|
+
adapter.draw_circle @rect.centerx, @rect.centery, radius, @focus_color
|
15
|
+
elsif @bg_color
|
16
|
+
adapter.draw_circle @rect.centerx, @rect.centery, radius, @bg_color
|
17
|
+
end
|
18
|
+
|
19
|
+
if @checked
|
20
|
+
adapter.draw_circle_filled @rect.centerx, @rect.centery, radius-@x_pad, @checked_color
|
21
|
+
end
|
22
|
+
|
23
|
+
if @border_color
|
24
|
+
adapter.draw_circle @rect.centerx, @rect.centery, radius, @border_color
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'publisher'
|
2
|
+
module Rubygoo
|
3
|
+
# contains radio buttons, allowing only one to be checked at a time
|
4
|
+
class RadioGroup < Container
|
5
|
+
|
6
|
+
def initialize(opts={})
|
7
|
+
# TODO add label, border
|
8
|
+
super opts
|
9
|
+
end
|
10
|
+
|
11
|
+
def add(*widgets)
|
12
|
+
widgets.uniq.each do |w|
|
13
|
+
if w.respond_to? :checked?
|
14
|
+
w.when :checked do |*opts|
|
15
|
+
widget = opts.first
|
16
|
+
if widget.checked?
|
17
|
+
update_group_selection widget
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
super *widgets
|
24
|
+
end
|
25
|
+
|
26
|
+
def update_group_selection(selected_widget)
|
27
|
+
@widgets.each do |w|
|
28
|
+
if w.respond_to? :checked?
|
29
|
+
if w.checked?
|
30
|
+
unless selected_widget == w
|
31
|
+
w.uncheck
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module Rubygoo
|
2
|
+
# this class represents a collection of widgets that can be
|
3
|
+
# tabbed through
|
4
|
+
class TabGroup
|
5
|
+
attr_accessor :selected_index, :widgets
|
6
|
+
|
7
|
+
def initialize()
|
8
|
+
@widgets = []
|
9
|
+
@selected_index = 1
|
10
|
+
end
|
11
|
+
|
12
|
+
def add(*widgets)
|
13
|
+
|
14
|
+
widgets.uniq.each do |w|
|
15
|
+
unless @widgets.include? w
|
16
|
+
if w.tab_to?
|
17
|
+
@widgets << w
|
18
|
+
w.focus_priority = @widgets.size unless w.focus_priority
|
19
|
+
else
|
20
|
+
if w.respond_to? :widgets and w.widgets.size > 0
|
21
|
+
add *w.widgets
|
22
|
+
end
|
23
|
+
if w.respond_to? :queued_widgets and w.queued_widgets.size > 0
|
24
|
+
add *w.queued_widgets
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
@widgets.sort_by {|w| w.focus_priority}
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
def remove(*widgets)
|
35
|
+
widgets.uniq.each do |w|
|
36
|
+
@widgets.delete(w)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def next()
|
41
|
+
rotate 1
|
42
|
+
end
|
43
|
+
|
44
|
+
def previous()
|
45
|
+
rotate -1
|
46
|
+
end
|
47
|
+
|
48
|
+
def focus(w)
|
49
|
+
index = @widgets.index w
|
50
|
+
if index
|
51
|
+
@widgets[@selected_index].unfocus if @widgets[@selected_index]
|
52
|
+
@selected_index = index
|
53
|
+
@widgets[@selected_index].focus
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def rotate(dir)
|
58
|
+
if @widgets.size > 0
|
59
|
+
@widgets[@selected_index].unfocus if @widgets[@selected_index]
|
60
|
+
@selected_index += dir
|
61
|
+
@selected_index %= @widgets.size
|
62
|
+
@widgets[@selected_index].focus
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
end
|