fidgit 0.0.2alpha

Sign up to get free protection for your applications and to get access to all the features.
Files changed (87) hide show
  1. data/.gitignore +8 -0
  2. data/.rspec +2 -0
  3. data/COPYING.txt +674 -0
  4. data/Gemfile +4 -0
  5. data/README.textile +138 -0
  6. data/Rakefile +38 -0
  7. data/config/default_schema.yml +180 -0
  8. data/examples/_all_examples.rb +9 -0
  9. data/examples/align_example.rb +56 -0
  10. data/examples/button_and_toggle_button_example.rb +27 -0
  11. data/examples/color_picker_example.rb +17 -0
  12. data/examples/color_well_example.rb +25 -0
  13. data/examples/combo_box_example.rb +24 -0
  14. data/examples/file_dialog_example.rb +42 -0
  15. data/examples/grid_packer_example.rb +29 -0
  16. data/examples/helpers/example_window.rb +17 -0
  17. data/examples/label_example.rb +17 -0
  18. data/examples/list_example.rb +23 -0
  19. data/examples/media/images/head_icon.png +0 -0
  20. data/examples/menu_pane_example.rb +27 -0
  21. data/examples/message_dialog_example.rb +65 -0
  22. data/examples/radio_button_example.rb +37 -0
  23. data/examples/readme_example.rb +32 -0
  24. data/examples/scroll_window_example.rb +49 -0
  25. data/examples/slider_example.rb +30 -0
  26. data/examples/splash_example.rb +42 -0
  27. data/examples/text_area_example.rb +28 -0
  28. data/fidgit.gemspec +28 -0
  29. data/lib/fidgit.rb +4 -0
  30. data/lib/fidgit/chingu_ext/window.rb +6 -0
  31. data/lib/fidgit/clipboard.rb +23 -0
  32. data/lib/fidgit/cursor.rb +38 -0
  33. data/lib/fidgit/elements/button.rb +68 -0
  34. data/lib/fidgit/elements/color_picker.rb +63 -0
  35. data/lib/fidgit/elements/color_well.rb +39 -0
  36. data/lib/fidgit/elements/combo_box.rb +85 -0
  37. data/lib/fidgit/elements/composite.rb +17 -0
  38. data/lib/fidgit/elements/container.rb +187 -0
  39. data/lib/fidgit/elements/element.rb +252 -0
  40. data/lib/fidgit/elements/file_browser.rb +152 -0
  41. data/lib/fidgit/elements/grid_packer.rb +219 -0
  42. data/lib/fidgit/elements/group.rb +66 -0
  43. data/lib/fidgit/elements/horizontal_packer.rb +12 -0
  44. data/lib/fidgit/elements/label.rb +77 -0
  45. data/lib/fidgit/elements/list.rb +47 -0
  46. data/lib/fidgit/elements/menu_pane.rb +149 -0
  47. data/lib/fidgit/elements/packer.rb +42 -0
  48. data/lib/fidgit/elements/radio_button.rb +86 -0
  49. data/lib/fidgit/elements/scroll_area.rb +75 -0
  50. data/lib/fidgit/elements/scroll_bar.rb +114 -0
  51. data/lib/fidgit/elements/scroll_window.rb +92 -0
  52. data/lib/fidgit/elements/slider.rb +119 -0
  53. data/lib/fidgit/elements/text_area.rb +351 -0
  54. data/lib/fidgit/elements/toggle_button.rb +67 -0
  55. data/lib/fidgit/elements/tool_tip.rb +35 -0
  56. data/lib/fidgit/elements/vertical_packer.rb +12 -0
  57. data/lib/fidgit/event.rb +99 -0
  58. data/lib/fidgit/gosu_ext/color.rb +123 -0
  59. data/lib/fidgit/history.rb +85 -0
  60. data/lib/fidgit/redirector.rb +83 -0
  61. data/lib/fidgit/schema.rb +123 -0
  62. data/lib/fidgit/selection.rb +106 -0
  63. data/lib/fidgit/standard_ext/hash.rb +21 -0
  64. data/lib/fidgit/states/dialog_state.rb +42 -0
  65. data/lib/fidgit/states/file_dialog.rb +24 -0
  66. data/lib/fidgit/states/gui_state.rb +301 -0
  67. data/lib/fidgit/states/message_dialog.rb +61 -0
  68. data/lib/fidgit/thumbnail.rb +29 -0
  69. data/lib/fidgit/version.rb +5 -0
  70. data/lib/fidgit/window.rb +19 -0
  71. data/media/images/arrow.png +0 -0
  72. data/media/images/file_directory.png +0 -0
  73. data/media/images/file_file.png +0 -0
  74. data/media/images/pixel.png +0 -0
  75. data/spec/fidgit/elements/helpers/helper.rb +3 -0
  76. data/spec/fidgit/elements/label_spec.rb +49 -0
  77. data/spec/fidgit/event_spec.rb +149 -0
  78. data/spec/fidgit/gosu_ext/color_spec.rb +130 -0
  79. data/spec/fidgit/gosu_ext/helpers/helper.rb +3 -0
  80. data/spec/fidgit/helpers/helper.rb +4 -0
  81. data/spec/fidgit/helpers/tex_play_helper.rb +9 -0
  82. data/spec/fidgit/history_spec.rb +144 -0
  83. data/spec/fidgit/redirector_spec.rb +78 -0
  84. data/spec/fidgit/schema_spec.rb +67 -0
  85. data/spec/fidgit/schema_test.yml +32 -0
  86. data/spec/fidgit/thumbnail_spec.rb +50 -0
  87. metadata +177 -0
@@ -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
@@ -0,0 +1,75 @@
1
+ # encoding: utf-8
2
+
3
+ module Fidgit
4
+ # A basic scrolling area. It is not managed in any way (use ScrollWindow for that).
5
+ class ScrollArea < Container
6
+ # @return [VerticalPacker] The content shown within this ScrollArea
7
+ attr_reader :content
8
+
9
+ def offset_x; x - @content.x; end
10
+ def offset_y; y - @content.y; end
11
+
12
+ def offset_x=(value)
13
+ @content.x = x - [[@content.width - width, value].min, 0].max
14
+ end
15
+
16
+ def offset_y=(value)
17
+ @content.y = y - [[@content.height - height, value].min, 0].max
18
+ end
19
+
20
+ # @option options [Number] :offset (0)
21
+ # @option options [Number] :offset_x (value of :offset option)
22
+ # @option options [Number] :offset_y (value of :offset option)
23
+ # @option options [Element] :owner The owner of the content, such as the scroll-window containing the content.
24
+ def initialize(options = {})
25
+ options = {
26
+ offset: 0,
27
+ owner: nil,
28
+ }.merge! options
29
+
30
+ @owner = options[:owner]
31
+
32
+ super(options)
33
+
34
+ @content = VerticalPacker.new(parent: self, padding: 0)
35
+
36
+ self.offset_x = options[:offset_x] || options[:offset]
37
+ self.offset_y = options[:offset_y] || options[:offset]
38
+ end
39
+
40
+ def hit_element(x, y)
41
+ # Only pass on mouse events if they are inside the window.
42
+ if hit?(x, y)
43
+ @content.hit_element(x, y) || self
44
+ else
45
+ nil
46
+ end
47
+ end
48
+
49
+ def recalc
50
+ super
51
+ # Always recalc our owner if our content resizes, even though our size can't change even if the content changes
52
+ # (may encourage ScrollWindow to show/hide scroll-bars, for example)
53
+ @owner.recalc if @owner
54
+ end
55
+
56
+ protected
57
+ def draw_foreground
58
+ $window.clip_to(*rect) do
59
+ @content.draw
60
+ end
61
+ end
62
+
63
+ protected
64
+ def post_init_block(&block)
65
+ case block.arity
66
+ when 1
67
+ yield @content
68
+ when 0
69
+ @content.instance_methods_eval &block
70
+ else
71
+ raise "block arity must be 0 or 1"
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,114 @@
1
+ # encoding: utf-8
2
+
3
+ module Fidgit
4
+ # @abstract
5
+ class ScrollBar < Composite
6
+ class Handle < Element
7
+ event :begin_drag
8
+ event :update_drag
9
+ event :end_drag
10
+
11
+ def drag?(button); button == :left; end
12
+
13
+ def initialize(options = {})
14
+ super options
15
+
16
+ subscribe :begin_drag do |sender, x, y|
17
+ # Store position of the handle when it starts to drag.
18
+ @drag_start_pos = [x - self.x, y - self.y]
19
+ end
20
+
21
+ subscribe :update_drag do |sender, x, y|
22
+ parent.parent.handle_dragged_to x - @drag_start_pos[0], y - @drag_start_pos[1]
23
+ end
24
+
25
+ subscribe :end_drag do
26
+ @drag_start_pos = nil
27
+ end
28
+ end
29
+ end
30
+
31
+ def initialize(options = {})
32
+ options = {
33
+ background_color: default(:background_color),
34
+ border_color: default(:border_color),
35
+ rail_width: default(:rail_width),
36
+ rail_color: default(:rail_color),
37
+ handle_color: default(:handle_color),
38
+ owner: nil,
39
+ }.merge! options
40
+
41
+ @owner = options[:owner]
42
+ @rail_thickness = options[:rail_width]
43
+ @rail_color = options[:rail_color]
44
+
45
+ super options
46
+
47
+ @handle_container = Container.new(parent: self, width: options[:width], height: options[:height]) do
48
+ @handle = Handle.new(parent: self, x: x, y: y, background_color: options[:handle_color])
49
+ end
50
+ end
51
+ end
52
+
53
+ class HorizontalScrollBar < ScrollBar
54
+ attr_reader :owner
55
+
56
+ def initialize(options = {})
57
+ super options
58
+
59
+ @handle.height = height
60
+
61
+ @handle_container.subscribe :left_mouse_button do |sender, x, y|
62
+ distance = @owner.view_width
63
+ @owner.offset_x += (x > @handle.x)? +distance : -distance
64
+ end
65
+ end
66
+
67
+ def update
68
+ window = parent.parent
69
+
70
+ # Resize and re-locate the handles based on changes to the scroll-window.
71
+ content_width = window.content_width.to_f
72
+ @handle.width = (window.view_width * width) / content_width
73
+ @handle.x = x + (window.offset_x * width) / content_width
74
+ end
75
+
76
+ def draw_foreground
77
+ draw_rect x + padding_left, y + (height - @rail_thickness) / 2, width, @rail_thickness, z, @rail_color
78
+ super
79
+ end
80
+
81
+ def handle_dragged_to(x, y)
82
+ @owner.offset_x = @owner.content_width * ((x - self.x) / width.to_f)
83
+ end
84
+ end
85
+
86
+ class VerticalScrollBar < ScrollBar
87
+ def initialize(options = {})
88
+ super options
89
+
90
+ @handle.width = width
91
+
92
+ @handle_container.subscribe :left_mouse_button do |sender, x, y|
93
+ distance = @owner.view_height
94
+ @owner.offset_y += (y > @handle.y)? +distance : -distance
95
+ end
96
+ end
97
+
98
+ def update
99
+ window = parent.parent
100
+ content_height = window.content_height.to_f
101
+ @handle.height = (window.view_height * height) / content_height
102
+ @handle.y = y + (window.offset_y * height) / content_height
103
+ end
104
+
105
+ def draw_foreground
106
+ draw_rect x + (width - @rail_thickness) / 2, y + padding_top, @rail_thickness, height, z, @rail_color
107
+ super
108
+ end
109
+
110
+ def handle_dragged_to(x, y)
111
+ @owner.offset_y = @owner.content_height * ((y - self.y) / height.to_f)
112
+ end
113
+ end
114
+ end
@@ -0,0 +1,92 @@
1
+ # encoding: utf-8
2
+
3
+ module Fidgit
4
+ class ScrollWindow < Composite
5
+ def content; @view.content; end
6
+
7
+ def offset_x; @view.offset_x; end
8
+ def offset_x=(value); @view.offset_x = value; end
9
+ def offset_y; @view.offset_y; end
10
+ def offset_y=(value); @view.offset_y = value; end
11
+
12
+ def view_width; @view.width; end
13
+ def view_height; @view.height; end
14
+ def content_width; @view.content.width; end
15
+ def content_height; @view.content.height; end
16
+
17
+ def width=(value); super(value); end
18
+ def height=(value); super(value); end
19
+
20
+ def initialize(options = {})
21
+ options = {
22
+ scroll_bar_thickness: default(:scroll_bar_thickness),
23
+ }.merge! options
24
+
25
+ super(options)
26
+
27
+ @grid = pack :grid, num_columns: 2, padding: 0, spacing: 0 do
28
+ @view = scroll_area(owner: self, width: options[:width], height: options[:height])
29
+ @spacer = label '', padding: 0, width: 0, height: 0
30
+ end
31
+
32
+ @scroll_bar_v = VerticalScrollBar.new(owner: self, width: options[:scroll_bar_thickness], align_v: :fill)
33
+ @scroll_bar_h = HorizontalScrollBar.new(owner: self, height: options[:scroll_bar_thickness], align_h: :fill)
34
+ end
35
+
36
+ protected
37
+ def layout
38
+ # Prevent recursive layouts.
39
+ return if @in_layout
40
+
41
+ @in_layout = true
42
+
43
+ if @view
44
+ # Constrain the values of the offsets.
45
+ @view.offset_x = @view.offset_x
46
+ @view.offset_y = @view.offset_y
47
+
48
+ if content_height > view_height
49
+ unless @scroll_bar_v.parent
50
+ @view.send(:rect).width -= @scroll_bar_v.width
51
+ @grid.remove @spacer
52
+ @grid.insert 1, @scroll_bar_v
53
+ end
54
+ else
55
+ if @scroll_bar_v.parent
56
+ @view.send(:rect).width += @scroll_bar_v.width
57
+ @grid.remove @scroll_bar_v
58
+ @grid.insert 1, @spacer
59
+ end
60
+ end
61
+
62
+ if content_width > view_width
63
+ unless @scroll_bar_h.parent
64
+ @view.send(:rect).height -= @scroll_bar_h.height
65
+ @grid.add @scroll_bar_h
66
+ end
67
+ else
68
+ if @scroll_bar_h.parent
69
+ @view.send(:rect).height += @scroll_bar_h.height
70
+ @grid.remove @scroll_bar_h
71
+ end
72
+ end
73
+ end
74
+
75
+ super
76
+
77
+ @in_layout = false
78
+ end
79
+
80
+ protected
81
+ def post_init_block(&block)
82
+ case block.arity
83
+ when 1
84
+ yield @view.content
85
+ when 0
86
+ @view.content.instance_methods_eval &block
87
+ else
88
+ raise "block arity must be 0 or 1"
89
+ end
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,119 @@
1
+ # encoding: utf-8
2
+
3
+ module Fidgit
4
+ class Slider < Composite
5
+ # @private
6
+ class Handle < Element
7
+ event :begin_drag
8
+ event :end_drag
9
+ event :update_drag
10
+
11
+ def drag?(button); button == :left; end
12
+
13
+ # @param (see Element#initialize)
14
+ #
15
+ # @option (see Element#initialize)
16
+ def initialize(options = {}, &block)
17
+ options = {
18
+ background_color: default(:background_color),
19
+ border_color: default(:border_color),
20
+ }.merge! options
21
+
22
+ super options
23
+
24
+ subscribe :begin_drag do |sender, x, y|
25
+ # Store position of the handle when it starts to drag.
26
+ @drag_start_pos = [x - self.x, y - self.y]
27
+ end
28
+
29
+ subscribe :update_drag do |sender, x, y|
30
+ parent.handle_dragged_to x - @drag_start_pos[0], y - @drag_start_pos[1]
31
+ end
32
+
33
+ subscribe :end_drag do
34
+ @drag_start_pos = nil
35
+ end
36
+ end
37
+ end
38
+
39
+ event :changed
40
+
41
+ attr_reader :value, :range
42
+
43
+ # @param (see Composite#initialize)
44
+ #
45
+ # @option (see Composite#initialize)
46
+ # @option options [Range] :range (0.0..1.0)
47
+ # @option options [Range] :value (minimum of :range)
48
+ def initialize(options = {}, &block)
49
+ options = {
50
+ range: 0.0..1.0,
51
+ height: 25,
52
+ background_color: default(:background_color),
53
+ border_color: default(:border_color),
54
+ groove_color: default(:groove_color),
55
+ handle_color: default(:handle_color),
56
+ groove_thickness: 5,
57
+ }.merge! options
58
+
59
+ @range = options[:range].dup
60
+ @groove_color = options[:groove_color].dup
61
+ @groove_thickness = options[:groove_thickness]
62
+ @continuous = @range.min.is_a?(Float) or @range.max.is_a?(Float)
63
+
64
+ super(options)
65
+
66
+ @handle = Handle.new(parent: self, width: (height / 2 - padding_left), height: height - padding_top + padding_bottom,
67
+ background_color: options[:handle_color])
68
+
69
+ self.value = options.has_key?(:value) ? options[:value] : @range.min
70
+ end
71
+
72
+ def value=(value)
73
+ @value = @continuous ? value.to_f : value.round
74
+ @value = [[@value, @range.min].max, @range.max].min
75
+ @handle.x = x + padding_left + ((width - @handle.width) * (@value - @range.min) / (@range.max - @range.min).to_f)
76
+ publish :changed, @value
77
+
78
+ @value
79
+ end
80
+
81
+ def tip
82
+ tip = super
83
+ tip.empty? ? @value.to_s : "#{tip}: #{@value}"
84
+ end
85
+
86
+ def left_mouse_button(sender, x, y)
87
+ # In this case, x should be the centre of the handle after it has moved.
88
+ self.value = ((x - (@handle.width / 2) - self.x) / (width - @handle.width)) * (@range.max - @range.min) + @range.min
89
+ @mouse_down = true
90
+
91
+ nil
92
+ end
93
+
94
+ def handle_dragged_to(x, y)
95
+ # In this case, x is the left-hand side fo the handle.
96
+ self.value = ((x - self.x) / (width - @handle.width)) * (@range.max - @range.min) + @range.min
97
+ end
98
+
99
+ protected
100
+ # Prevent standard packing layout change.
101
+ def layout
102
+ nil
103
+ end
104
+
105
+ protected
106
+ def draw_background
107
+ super
108
+ # Draw a groove for the handle to move along.
109
+ draw_rect x + (@handle.width / 2), y + (height - @groove_thickness) / 2, width - @handle.width, @groove_thickness, z, @groove_color
110
+ nil
111
+ end
112
+
113
+ protected
114
+ # Use block as an event handler.
115
+ def post_init_block(&block)
116
+ subscribe :changed, &block
117
+ end
118
+ end
119
+ end