rubygoo 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
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,:width=>600,:height=>480,:data_dir=>File.join(File.dirname(__FILE__),"..","..","themes"),:mouse_cursor => true}
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
- @tabbed_widgets = []
11
- @focussed_widget = 0
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
- @mouse_opt = merged_opts[:mouse_cursor]
21
- if @mouse_opt
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 @mouse_opt
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
- w.focus_priority = @tabbed_widgets.size unless w.focus_priority
47
- @focussed_widget = 1
48
- w.focus if @tabbed_widgets.empty?
49
- @tabbed_widgets << w
50
- @tabbed_widgets.sort_by {|w| w.focus_priority}
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
- @tabbed_widgets[@focussed_widget].unfocus
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
- @tabbed_widgets[@focussed_widget].unfocus
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
- # ALL mouse events go here
84
- modal_mouse_call event.event_type, event
135
+ @modal_widgets.last.send meth, event
136
+ end
137
+ end
85
138
 
86
- if event.event_type == :mouse_motion
87
- @mouse.mouse_motion event if @mouse_opt
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
 
@@ -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
- @rect = Rect.new [@x-@x_pad,@y-@y_pad,@rendered_text.width+2*@x_pad,@rendered_text.height+2*@y_pad]
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 @focus_color, @rect
55
+ adapter.fill x1, y1, x2, y2, @focus_color
38
56
  elsif @bg_color
39
- adapter.fill @bg_color, @rect
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
@@ -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(screen)
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
- screen.fill @focus_color, @rect
66
+ adapter.fill x1, y1, x2, y2, @focus_color
58
67
  elsif @bg_color
59
- screen.fill @bg_color, @rect
68
+ adapter.fill x1, y1, x2, y2, @bg_color
60
69
  end
61
70
 
62
71
  if @checked
63
- screen.fill @checked_color, @rect.inflate(-@x_pad,-@y_pad)
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 = @rect[0]
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
@@ -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.app.add_tabbed_widget 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(screen)
67
+ def draw(adapter)
59
68
  # any container specific code here (border_colors?)
60
69
  if @bg_color
61
70
  if app == self
62
- screen.fill @bg_color
71
+ adapter.fill_screen @bg_color
63
72
  else
64
- screen.fill @bg_color, @rect
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 screen
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
 
@@ -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(screen)
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
- screen.fill @focus_color, @rect
33
+ adapter.fill x1, y1, x2, y2, @focus_color
29
34
  elsif @bg_color
30
- screen.fill @bg_color, @rect
35
+ adapter.fill x1, y1, x2, y2, @bg_color
31
36
  end
32
37
 
33
38
  if @border_color
34
- x1 = @rect[0]
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
- screen.draw_image @rendered_text, @x, @y, @color
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