colstrom-fidgit 0.2.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +8 -0
- data/.rspec +2 -0
- data/CHANGELOG.md +31 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +20 -0
- data/README.md +154 -0
- data/Rakefile +38 -0
- data/config/default_schema.yml +216 -0
- data/examples/_all_examples.rb +9 -0
- data/examples/align_example.rb +56 -0
- data/examples/button_and_toggle_button_example.rb +38 -0
- data/examples/color_picker_example.rb +17 -0
- data/examples/color_well_example.rb +25 -0
- data/examples/combo_box_example.rb +24 -0
- data/examples/file_dialog_example.rb +42 -0
- data/examples/grid_packer_example.rb +29 -0
- data/examples/helpers/example_window.rb +17 -0
- data/examples/label_example.rb +23 -0
- data/examples/list_example.rb +23 -0
- data/examples/media/images/head_icon.png +0 -0
- data/examples/menu_pane_example.rb +27 -0
- data/examples/message_dialog_example.rb +65 -0
- data/examples/radio_button_example.rb +37 -0
- data/examples/readme_example.rb +32 -0
- data/examples/scroll_window_example.rb +49 -0
- data/examples/slider_example.rb +34 -0
- data/examples/splash_example.rb +42 -0
- data/examples/text_area_example.rb +33 -0
- data/fidgit.gemspec +35 -0
- data/lib/fidgit.rb +51 -0
- data/lib/fidgit/chingu_ext/window.rb +6 -0
- data/lib/fidgit/cursor.rb +38 -0
- data/lib/fidgit/elements/button.rb +113 -0
- data/lib/fidgit/elements/color_picker.rb +63 -0
- data/lib/fidgit/elements/color_well.rb +39 -0
- data/lib/fidgit/elements/combo_box.rb +115 -0
- data/lib/fidgit/elements/composite.rb +17 -0
- data/lib/fidgit/elements/container.rb +210 -0
- data/lib/fidgit/elements/element.rb +298 -0
- data/lib/fidgit/elements/file_browser.rb +152 -0
- data/lib/fidgit/elements/grid.rb +227 -0
- data/lib/fidgit/elements/group.rb +64 -0
- data/lib/fidgit/elements/horizontal.rb +12 -0
- data/lib/fidgit/elements/image_frame.rb +65 -0
- data/lib/fidgit/elements/label.rb +85 -0
- data/lib/fidgit/elements/list.rb +47 -0
- data/lib/fidgit/elements/main_packer.rb +25 -0
- data/lib/fidgit/elements/menu_pane.rb +163 -0
- data/lib/fidgit/elements/packer.rb +42 -0
- data/lib/fidgit/elements/radio_button.rb +86 -0
- data/lib/fidgit/elements/scroll_area.rb +68 -0
- data/lib/fidgit/elements/scroll_bar.rb +128 -0
- data/lib/fidgit/elements/scroll_window.rb +83 -0
- data/lib/fidgit/elements/slider.rb +125 -0
- data/lib/fidgit/elements/text_area.rb +494 -0
- data/lib/fidgit/elements/text_line.rb +92 -0
- data/lib/fidgit/elements/toggle_button.rb +67 -0
- data/lib/fidgit/elements/tool_tip.rb +35 -0
- data/lib/fidgit/elements/vertical.rb +12 -0
- data/lib/fidgit/event.rb +159 -0
- data/lib/fidgit/gosu_ext/color.rb +136 -0
- data/lib/fidgit/gosu_ext/gosu_module.rb +25 -0
- data/lib/fidgit/history.rb +91 -0
- data/lib/fidgit/redirector.rb +83 -0
- data/lib/fidgit/schema.rb +123 -0
- data/lib/fidgit/selection.rb +106 -0
- data/lib/fidgit/standard_ext/hash.rb +21 -0
- data/lib/fidgit/states/dialog_state.rb +52 -0
- data/lib/fidgit/states/file_dialog.rb +24 -0
- data/lib/fidgit/states/gui_state.rb +331 -0
- data/lib/fidgit/states/message_dialog.rb +61 -0
- data/lib/fidgit/version.rb +5 -0
- data/lib/fidgit/window.rb +19 -0
- data/media/images/arrow.png +0 -0
- data/media/images/combo_arrow.png +0 -0
- data/media/images/file_directory.png +0 -0
- data/media/images/file_file.png +0 -0
- data/media/images/pixel.png +0 -0
- data/spec/fidgit/elements/helpers/helper.rb +3 -0
- data/spec/fidgit/elements/helpers/tex_play_helper.rb +9 -0
- data/spec/fidgit/elements/image_frame_spec.rb +69 -0
- data/spec/fidgit/elements/label_spec.rb +37 -0
- data/spec/fidgit/event_spec.rb +210 -0
- data/spec/fidgit/gosu_ext/color_spec.rb +130 -0
- data/spec/fidgit/gosu_ext/helpers/helper.rb +3 -0
- data/spec/fidgit/helpers/helper.rb +4 -0
- data/spec/fidgit/history_spec.rb +153 -0
- data/spec/fidgit/redirector_spec.rb +78 -0
- data/spec/fidgit/schema_spec.rb +67 -0
- data/spec/fidgit/schema_test.yml +32 -0
- metadata +320 -0
@@ -0,0 +1,65 @@
|
|
1
|
+
module Fidgit
|
2
|
+
# A wrapper around a Gosu::Image to show it in the GUI.
|
3
|
+
class ImageFrame < Element
|
4
|
+
ENABLED_COLOR = Gosu::Color::WHITE
|
5
|
+
DISABLED_COLOR = Gosu::Color.rgb(150, 150, 150)
|
6
|
+
|
7
|
+
attr_reader :image, :factor_x, :factor_y
|
8
|
+
|
9
|
+
def thumbnail?; @thumbnail; end
|
10
|
+
|
11
|
+
# @param (see Element#initialize)
|
12
|
+
# @param [Gosu::Image] image Gosu image to display.
|
13
|
+
#
|
14
|
+
# @option (see Element#initialize)
|
15
|
+
# @option options [Boolean] :thumbnail (false) Is the image expanded to be square?
|
16
|
+
def initialize(image, options = {})
|
17
|
+
options = {
|
18
|
+
thumbnail: false,
|
19
|
+
factor: 1,
|
20
|
+
}.merge! options
|
21
|
+
|
22
|
+
@thumbnail = options[:thumbnail]
|
23
|
+
@factor_x = options[:factor_x] || options[:factor]
|
24
|
+
@factor_y = options[:factor_y] || options[:factor]
|
25
|
+
|
26
|
+
super(options)
|
27
|
+
|
28
|
+
self.image = image
|
29
|
+
end
|
30
|
+
|
31
|
+
def image=(image)
|
32
|
+
@image = image
|
33
|
+
|
34
|
+
recalc
|
35
|
+
|
36
|
+
image
|
37
|
+
end
|
38
|
+
|
39
|
+
|
40
|
+
def draw_foreground
|
41
|
+
@image.draw(x + padding_left, y + padding_top, z, factor_x, factor_y, enabled? ? ENABLED_COLOR : DISABLED_COLOR) if @image
|
42
|
+
end
|
43
|
+
|
44
|
+
protected
|
45
|
+
def layout
|
46
|
+
if @image
|
47
|
+
if @thumbnail
|
48
|
+
size = [@image.width, @image.height].max
|
49
|
+
rect.width = size * @factor_x
|
50
|
+
rect.height = size * @factor_y
|
51
|
+
else
|
52
|
+
rect.width = @image.width * @factor_x
|
53
|
+
rect.height = @image.height * @factor_y
|
54
|
+
end
|
55
|
+
else
|
56
|
+
rect.width = rect.height = 0
|
57
|
+
end
|
58
|
+
|
59
|
+
rect.width += padding_left + padding_right
|
60
|
+
rect.height += padding_top + padding_bottom
|
61
|
+
|
62
|
+
nil
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Fidgit
|
4
|
+
class Label < Composite
|
5
|
+
ICON_POSITIONS = [:top, :bottom, :left, :right]
|
6
|
+
|
7
|
+
attr_reader :icon_position
|
8
|
+
|
9
|
+
attr_accessor :background_color, :border_color
|
10
|
+
|
11
|
+
def_delegators :@text, :text, :color, :font, :color=, :text=
|
12
|
+
|
13
|
+
def icon; @icon ? @icon.image : nil; end
|
14
|
+
|
15
|
+
def hit_element(x, y)
|
16
|
+
# The sub-elements should never get events.
|
17
|
+
hit?(x, y) ? self : nil
|
18
|
+
end
|
19
|
+
|
20
|
+
def icon=(icon)
|
21
|
+
raise ArgumentError.new("Icon must be a Gosu::Image") unless icon.is_a? Gosu::Image or icon.nil?
|
22
|
+
|
23
|
+
@contents.remove(@icon) if @icon.image
|
24
|
+
@icon.image = icon
|
25
|
+
position = [:left, :top].include?(icon_position) ? 0 : 1
|
26
|
+
@contents.insert(position, @icon) if @icon.image
|
27
|
+
|
28
|
+
icon
|
29
|
+
end
|
30
|
+
|
31
|
+
# Set the position of the icon, respective to the text.
|
32
|
+
def icon_position=(position)
|
33
|
+
raise ArgumentError.new("icon_position must be one of #{ICON_POSITIONS}") unless ICON_POSITIONS.include? position
|
34
|
+
|
35
|
+
@icon_position = position
|
36
|
+
|
37
|
+
case @icon_position
|
38
|
+
when :top, :bottom
|
39
|
+
@contents.instance_variable_set :@type, :fixed_columns
|
40
|
+
@contents.instance_variable_set :@num_columns, 1
|
41
|
+
when :left, :right
|
42
|
+
@contents.instance_variable_set :@type, :fixed_rows
|
43
|
+
@contents.instance_variable_set :@num_rows, 1
|
44
|
+
end
|
45
|
+
|
46
|
+
self.icon = @icon.image if @icon.image # Force the icon into the correct position.
|
47
|
+
|
48
|
+
position
|
49
|
+
end
|
50
|
+
|
51
|
+
# @param (see Element#initialize)
|
52
|
+
# @param [String] text The string to display in the label.
|
53
|
+
#
|
54
|
+
# @option (see Element#initialize)
|
55
|
+
# @option options [Gosu::Image, nil] :icon (nil)
|
56
|
+
# @option options [:left, :right, :center] :justify (:left) Text justification.
|
57
|
+
def initialize(text, options = {})
|
58
|
+
options = {
|
59
|
+
color: default(:color),
|
60
|
+
justify: default(:justify),
|
61
|
+
background_color: default(:background_color),
|
62
|
+
border_color: default(:border_color),
|
63
|
+
icon_options: {},
|
64
|
+
font_name: default(:font_name),
|
65
|
+
font_height: default(:font_height),
|
66
|
+
icon_position: default(:icon_position),
|
67
|
+
}.merge! options
|
68
|
+
|
69
|
+
super(options)
|
70
|
+
|
71
|
+
# Bit of a fudge since font info is managed circularly here!
|
72
|
+
# By using a grid, we'll be able to turn it around easily (in theory).
|
73
|
+
@contents = grid num_rows: 1, padding: 0, spacing_h: spacing_h, spacing_v: spacing_v, width: options[:width], height: options[:height], z: z do |contents|
|
74
|
+
@text = TextLine.new(text, parent: contents, justify: options[:justify], color: options[:color], padding: 0, z: z,
|
75
|
+
font_name: options[:font_name], font_height: options[:font_height], align_h: :fill, align_v: :center)
|
76
|
+
end
|
77
|
+
|
78
|
+
# Create an image frame, but don't show it unless there is an image in it.
|
79
|
+
@icon = ImageFrame.new(nil, options[:icon_options].merge(z: z, align: :center))
|
80
|
+
@icon.image = options[:icon]
|
81
|
+
|
82
|
+
self.icon_position = options[:icon_position]
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Fidgit
|
4
|
+
class List < Composite
|
5
|
+
class Item < RadioButton
|
6
|
+
end
|
7
|
+
|
8
|
+
event :changed
|
9
|
+
|
10
|
+
def size; @items.size; end
|
11
|
+
def clear; @items.clear; end
|
12
|
+
|
13
|
+
def initialize(options = {})
|
14
|
+
options = {
|
15
|
+
background_color: default(:background_color),
|
16
|
+
border_color: default(:border_color),
|
17
|
+
}.merge! options
|
18
|
+
|
19
|
+
super options
|
20
|
+
|
21
|
+
group do
|
22
|
+
subscribe :changed do |sender, value|
|
23
|
+
publish :changed, value
|
24
|
+
end
|
25
|
+
|
26
|
+
@items = vertical spacing: 0
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# @param [String] text
|
31
|
+
# @option options [Gosu::Image] :icon
|
32
|
+
def item(text, value, options = {}, &block)
|
33
|
+
Item.new(text, value, { parent: @items }.merge!(options), &block)
|
34
|
+
end
|
35
|
+
|
36
|
+
protected
|
37
|
+
def layout
|
38
|
+
super
|
39
|
+
if @items
|
40
|
+
max_width = @items.each.to_a.map {|c| c.width }.max || 0
|
41
|
+
@items.each {|c| c.rect.width = max_width }
|
42
|
+
end
|
43
|
+
|
44
|
+
nil
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require_relative "vertical"
|
2
|
+
|
3
|
+
module Fidgit
|
4
|
+
# Main container that can contains a single "proper" packing element.
|
5
|
+
class MainPacker < Vertical
|
6
|
+
def initialize(options = {})
|
7
|
+
options = {
|
8
|
+
width: $window.width,
|
9
|
+
height: $window.height,
|
10
|
+
}.merge! options
|
11
|
+
|
12
|
+
super options
|
13
|
+
end
|
14
|
+
|
15
|
+
def width; $window.width; end
|
16
|
+
def height; $window.height; end
|
17
|
+
def width=(value); ; end
|
18
|
+
def height=(value); ; end
|
19
|
+
|
20
|
+
def add(element)
|
21
|
+
raise "MainPacker can only contain packing elements" unless element.is_a? Packer
|
22
|
+
super(element)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,163 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
|
3
|
+
module Fidgit
|
4
|
+
class MenuPane < Composite
|
5
|
+
# An item within the menu.
|
6
|
+
class Item < Button
|
7
|
+
attr_reader :value, :shortcut_text
|
8
|
+
|
9
|
+
# @param (see Button#initialize)
|
10
|
+
#
|
11
|
+
# @option (see Button#initialize)
|
12
|
+
# @param [any] value Value if the user picks this item
|
13
|
+
# @option options [String] :shortcut_text ('')
|
14
|
+
def initialize(text, value, options = {})
|
15
|
+
options = {
|
16
|
+
enabled: true,
|
17
|
+
border_color: default(:border_color),
|
18
|
+
shortcut_text: '',
|
19
|
+
}.merge! options
|
20
|
+
|
21
|
+
@value = value
|
22
|
+
@shortcut_text = options[:shortcut_text]
|
23
|
+
|
24
|
+
super(text, options)
|
25
|
+
end
|
26
|
+
|
27
|
+
def draw_foreground
|
28
|
+
super
|
29
|
+
|
30
|
+
unless @shortcut_text.empty?
|
31
|
+
font.draw_rel("#{@shortcut_text}", rect.right - padding_right, y + ((height - font.height) / 2).floor, z, 1, 0, 1, 1, color)
|
32
|
+
end
|
33
|
+
|
34
|
+
nil
|
35
|
+
end
|
36
|
+
|
37
|
+
protected
|
38
|
+
def layout
|
39
|
+
super
|
40
|
+
|
41
|
+
# Ignore layout request when asked before TextLine has been created.
|
42
|
+
rect.width += font.text_width(" #{@shortcut_text}") unless @shortcut_text.empty? or @text.nil?
|
43
|
+
|
44
|
+
nil
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
class Separator < Label
|
49
|
+
# @param (see Item#initialize)
|
50
|
+
#
|
51
|
+
# @option (see Item#initialize)
|
52
|
+
def initialize(options = {})
|
53
|
+
options = {
|
54
|
+
height: default(:line_height),
|
55
|
+
background_color: default(:background_color),
|
56
|
+
padding: 0,
|
57
|
+
}.merge! options
|
58
|
+
|
59
|
+
super '', options
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
extend Forwardable
|
64
|
+
|
65
|
+
def_delegators :@items, :each, :clear, :size, :[]
|
66
|
+
|
67
|
+
event :selected
|
68
|
+
|
69
|
+
def index(value); @items.index find(value); end
|
70
|
+
def x=(value); super(value); recalc; end
|
71
|
+
def y=(value); super(value); recalc; end
|
72
|
+
|
73
|
+
# @option (see Composite#initialize)
|
74
|
+
# @option options [Float] :x (cursor x, if in a GuiState)
|
75
|
+
# @option options [Float] :y (cursor y, if in a GuiState)
|
76
|
+
# @option options [Boolean] :show (true) Whether to show immediately (show later with #show).
|
77
|
+
def initialize(options = {}, &block)
|
78
|
+
options = {
|
79
|
+
background_color: default(:color),
|
80
|
+
z: Float::INFINITY,
|
81
|
+
show: true,
|
82
|
+
}.merge! options
|
83
|
+
|
84
|
+
state = $window.current_game_state
|
85
|
+
if state.is_a? GuiState
|
86
|
+
cursor = $window.current_game_state.cursor
|
87
|
+
options = {
|
88
|
+
x: cursor.x,
|
89
|
+
y: cursor.y,
|
90
|
+
}.merge! options
|
91
|
+
end
|
92
|
+
|
93
|
+
@items = nil
|
94
|
+
|
95
|
+
super(options)
|
96
|
+
|
97
|
+
@items = vertical spacing: 0, padding: 0
|
98
|
+
|
99
|
+
if options[:show] and state.is_a? GuiState
|
100
|
+
show
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def find(value)
|
105
|
+
@items.find {|c| c.value == value }
|
106
|
+
end
|
107
|
+
|
108
|
+
def separator(options = {})
|
109
|
+
options[:z] = z
|
110
|
+
|
111
|
+
Separator.new({ parent: @items }.merge!(options))
|
112
|
+
end
|
113
|
+
|
114
|
+
def item(text, value, options = {}, &block)
|
115
|
+
options = options.merge({
|
116
|
+
parent: @items,
|
117
|
+
z: z,
|
118
|
+
})
|
119
|
+
item = Item.new(text, value, options, &block)
|
120
|
+
|
121
|
+
item.subscribe :left_mouse_button, method(:item_selected)
|
122
|
+
item.subscribe :right_mouse_button, method(:item_selected)
|
123
|
+
|
124
|
+
item
|
125
|
+
end
|
126
|
+
|
127
|
+
def item_selected(sender, x, y)
|
128
|
+
publish(:selected, sender.value)
|
129
|
+
|
130
|
+
$window.game_state_manager.current_game_state.hide_menu
|
131
|
+
|
132
|
+
nil
|
133
|
+
end
|
134
|
+
|
135
|
+
def show
|
136
|
+
$window.game_state_manager.current_game_state.show_menu self
|
137
|
+
nil
|
138
|
+
end
|
139
|
+
|
140
|
+
protected
|
141
|
+
def layout
|
142
|
+
super
|
143
|
+
|
144
|
+
if @items
|
145
|
+
# Ensure the menu can't go over the edge of the screen. If it can't be avoided, align with top-left edge of screen.
|
146
|
+
rect.x = [[x, $window.width - width - padding_right].min, 0].max
|
147
|
+
rect.y = [[y, $window.height - height - padding_bottom].min, 0].max
|
148
|
+
|
149
|
+
# Move the actual list if the menu has moved to keep on the screen.
|
150
|
+
@items.x = x + padding_left
|
151
|
+
@items.y = y + padding_top
|
152
|
+
|
153
|
+
# Ensure that all items are of the same width.
|
154
|
+
max_width = @items.map(&:width).max || 0
|
155
|
+
@items.each {|c| c.rect.width = max_width }
|
156
|
+
|
157
|
+
@items.recalc # Move all the items inside the packer to correct ones.
|
158
|
+
end
|
159
|
+
|
160
|
+
nil
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Fidgit
|
4
|
+
# Container that auto-packs elements.
|
5
|
+
#
|
6
|
+
# @abstract
|
7
|
+
class Packer < Container
|
8
|
+
attr_reader :spacing_h, :spacing_v
|
9
|
+
|
10
|
+
# @param (see Container#initialize)
|
11
|
+
#
|
12
|
+
# @option (see Container#initialize)
|
13
|
+
def initialize(options = {})
|
14
|
+
options = {
|
15
|
+
}.merge! options
|
16
|
+
|
17
|
+
@spacing_h = options[:spacing_h] || options[:spacing] || default(:spacing_h)
|
18
|
+
@spacing_v = options[:spacing_v] || options[:spacing] || default(:spacing_v)
|
19
|
+
|
20
|
+
super(options)
|
21
|
+
end
|
22
|
+
|
23
|
+
protected
|
24
|
+
# Recalculate the size of the container.
|
25
|
+
# Should be overridden by any descendant that manages the positions of its children.
|
26
|
+
def layout
|
27
|
+
# This assumes that the container overlaps all the children.
|
28
|
+
|
29
|
+
# Move all children if we have moved.
|
30
|
+
@children.each.with_index do |child, index|
|
31
|
+
child.x = padding_left + x
|
32
|
+
child.y = padding_top + y
|
33
|
+
end
|
34
|
+
|
35
|
+
# Make us as wrap around the largest child.
|
36
|
+
rect.width = (@children.map {|c| c.width }.max || 0) + padding_left + padding_right
|
37
|
+
rect.height = (@children.map {|c| c.height }.max || 0) + padding_top + padding_bottom
|
38
|
+
|
39
|
+
super
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Fidgit
|
4
|
+
class RadioButton < Button
|
5
|
+
attr_reader :group, :value
|
6
|
+
|
7
|
+
event :changed
|
8
|
+
|
9
|
+
def checked?; @checked; end
|
10
|
+
|
11
|
+
# @param (see Button#initialize)
|
12
|
+
# @param [Object] value
|
13
|
+
#
|
14
|
+
# @option (see Button#initialize)
|
15
|
+
# @option options [Boolean] :checked
|
16
|
+
def initialize(text, value, options = {}, &block)
|
17
|
+
options = {
|
18
|
+
checked: false,
|
19
|
+
checked_border_color: default(:checked, :border_color),
|
20
|
+
}.merge! options
|
21
|
+
|
22
|
+
@checked = options[:checked]
|
23
|
+
@value = value
|
24
|
+
|
25
|
+
super(text, options)
|
26
|
+
|
27
|
+
@checked_border_color = options[:checked_border_color].dup
|
28
|
+
@unchecked_border_color = border_color
|
29
|
+
add_to_group
|
30
|
+
|
31
|
+
@border_color = (checked? ? @checked_border_color : @unchecked_border_color).dup
|
32
|
+
end
|
33
|
+
|
34
|
+
def clicked_left_mouse_button(sender, x, y)
|
35
|
+
super
|
36
|
+
check
|
37
|
+
nil
|
38
|
+
end
|
39
|
+
|
40
|
+
# Check the button and update its group. This may uncheck another button in the group if one is selected.
|
41
|
+
def check
|
42
|
+
return if checked?
|
43
|
+
|
44
|
+
@checked = true
|
45
|
+
@group.value = value
|
46
|
+
@border_color = @checked_border_color.dup
|
47
|
+
publish :changed, @checked
|
48
|
+
|
49
|
+
nil
|
50
|
+
end
|
51
|
+
|
52
|
+
# Uncheck the button and update its group.
|
53
|
+
def uncheck
|
54
|
+
return unless checked?
|
55
|
+
|
56
|
+
@checked = false
|
57
|
+
@group.value = value
|
58
|
+
@border_color = @unchecked_border_color.dup
|
59
|
+
publish :changed, @checked
|
60
|
+
|
61
|
+
nil
|
62
|
+
end
|
63
|
+
|
64
|
+
protected
|
65
|
+
def parent=(parent)
|
66
|
+
@group.remove_button self if @parent
|
67
|
+
super(parent)
|
68
|
+
add_to_group if parent
|
69
|
+
parent
|
70
|
+
end
|
71
|
+
|
72
|
+
protected
|
73
|
+
def add_to_group
|
74
|
+
container = parent
|
75
|
+
while container and not container.is_a? Group
|
76
|
+
container = container.parent
|
77
|
+
end
|
78
|
+
|
79
|
+
raise "#{self.class.name} must be placed inside a group element" unless container
|
80
|
+
|
81
|
+
@group = container
|
82
|
+
@group.add_button self
|
83
|
+
nil
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|