reflexion 0.5.2 → 0.6.0

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.
Files changed (145) hide show
  1. checksums.yaml +4 -4
  2. data/.doc/ext/reflex/application.cpp +19 -1
  3. data/.doc/ext/reflex/chase_constraint.cpp +84 -0
  4. data/.doc/ext/reflex/clipboard.cpp +65 -0
  5. data/.doc/ext/reflex/constraint.cpp +135 -0
  6. data/.doc/ext/reflex/key_event.cpp +6 -6
  7. data/.doc/ext/reflex/link_constraint.cpp +178 -0
  8. data/.doc/ext/reflex/menu.cpp +302 -0
  9. data/.doc/ext/reflex/native.cpp +22 -4
  10. data/.doc/ext/reflex/pin.cpp +156 -0
  11. data/.doc/ext/reflex/pointer.cpp +2 -0
  12. data/.doc/ext/reflex/pointer_event.cpp +1 -1
  13. data/.doc/ext/reflex/reflex.cpp +42 -7
  14. data/.doc/ext/reflex/selector.cpp +4 -4
  15. data/.doc/ext/reflex/snap_constraint.cpp +125 -0
  16. data/.doc/ext/reflex/style_length.cpp +3 -2
  17. data/.doc/ext/reflex/view.cpp +96 -23
  18. data/.doc/ext/reflex/wheel_constraint.cpp +142 -0
  19. data/.doc/ext/reflex/window.cpp +59 -17
  20. data/.github/workflows/release-gem.yml +10 -1
  21. data/.github/workflows/test.yml +9 -0
  22. data/ChangeLog.md +30 -0
  23. data/README.md +1 -0
  24. data/VERSION +1 -1
  25. data/ext/reflex/application.cpp +21 -1
  26. data/ext/reflex/chase_constraint.cpp +89 -0
  27. data/ext/reflex/clipboard.cpp +69 -0
  28. data/ext/reflex/constraint.cpp +146 -0
  29. data/ext/reflex/key_event.cpp +6 -6
  30. data/ext/reflex/link_constraint.cpp +194 -0
  31. data/ext/reflex/menu.cpp +330 -0
  32. data/ext/reflex/native.cpp +22 -4
  33. data/ext/reflex/pin.cpp +165 -0
  34. data/ext/reflex/pointer.cpp +2 -0
  35. data/ext/reflex/pointer_event.cpp +1 -1
  36. data/ext/reflex/reflex.cpp +42 -7
  37. data/ext/reflex/selector.cpp +4 -4
  38. data/ext/reflex/selector.h +1 -1
  39. data/ext/reflex/snap_constraint.cpp +135 -0
  40. data/ext/reflex/style_length.cpp +3 -2
  41. data/ext/reflex/view.cpp +117 -37
  42. data/ext/reflex/wheel_constraint.cpp +154 -0
  43. data/ext/reflex/window.cpp +65 -18
  44. data/include/reflex/application.h +9 -0
  45. data/include/reflex/clipboard.h +53 -0
  46. data/include/reflex/constraint.h +275 -0
  47. data/include/reflex/defs.h +204 -195
  48. data/include/reflex/event.h +2 -0
  49. data/include/reflex/menu.h +120 -0
  50. data/include/reflex/pin.h +68 -0
  51. data/include/reflex/pointer.h +4 -0
  52. data/include/reflex/ruby/clipboard.h +23 -0
  53. data/include/reflex/ruby/constraint.h +94 -0
  54. data/include/reflex/ruby/menu.h +103 -0
  55. data/include/reflex/ruby/pin.h +40 -0
  56. data/include/reflex/ruby/view.h +36 -0
  57. data/include/reflex/ruby/window.h +36 -18
  58. data/include/reflex/view.h +39 -12
  59. data/include/reflex/window.h +17 -4
  60. data/include/reflex.h +5 -0
  61. data/lib/reflex/chase_constraint.rb +15 -0
  62. data/lib/reflex/clipboard.rb +19 -0
  63. data/lib/reflex/constraint.rb +29 -0
  64. data/lib/reflex/extension.rb +1 -1
  65. data/lib/reflex/helper.rb +28 -0
  66. data/lib/reflex/key_event.rb +7 -12
  67. data/lib/reflex/link_constraint.rb +31 -0
  68. data/lib/reflex/menu.rb +76 -0
  69. data/lib/reflex/pin.rb +39 -0
  70. data/lib/reflex/pointer.rb +18 -0
  71. data/lib/reflex/pointer_event.rb +1 -1
  72. data/lib/reflex/snap_constraint.rb +28 -0
  73. data/lib/reflex/view.rb +56 -4
  74. data/lib/reflex/wheel_constraint.rb +28 -0
  75. data/lib/reflex/wheel_event.rb +9 -0
  76. data/lib/reflex.rb +15 -6
  77. data/pod.rake +4 -2
  78. data/reflex.gemspec +3 -3
  79. data/samples/constraint.rb +152 -0
  80. data/samples/menu.rb +29 -0
  81. data/src/application.cpp +21 -2
  82. data/src/application.h +5 -0
  83. data/src/clipboard.cpp +81 -0
  84. data/src/constraint.cpp +1662 -0
  85. data/src/constraint.h +64 -0
  86. data/src/event.cpp +7 -1
  87. data/src/event.h +1 -2
  88. data/src/ios/application.mm +5 -0
  89. data/src/ios/clipboard.mm +44 -0
  90. data/src/ios/event.h +6 -2
  91. data/src/ios/event.mm +31 -12
  92. data/src/ios/menu.mm +36 -0
  93. data/src/ios/view_controller.mm +45 -12
  94. data/src/ios/window.mm +6 -0
  95. data/src/menu.cpp +325 -0
  96. data/src/menu.h +65 -0
  97. data/src/osx/app_delegate.mm +74 -125
  98. data/src/osx/application.mm +16 -0
  99. data/src/osx/clipboard.mm +45 -0
  100. data/src/osx/event.mm +40 -10
  101. data/src/osx/menu.h +25 -0
  102. data/src/osx/menu.mm +372 -0
  103. data/src/osx/native_window.mm +27 -0
  104. data/src/osx/opengl_view.mm +51 -0
  105. data/src/osx/window.mm +11 -0
  106. data/src/pin.cpp +137 -0
  107. data/src/pointer.cpp +27 -16
  108. data/src/pointer.h +6 -0
  109. data/src/sdl/application.cpp +5 -0
  110. data/src/sdl/clipboard.cpp +39 -0
  111. data/src/sdl/event.cpp +20 -3
  112. data/src/sdl/event.h +6 -3
  113. data/src/sdl/menu.cpp +35 -0
  114. data/src/sdl/window.cpp +26 -8
  115. data/src/view.cpp +313 -52
  116. data/src/view.h +18 -2
  117. data/src/win32/application.cpp +5 -0
  118. data/src/win32/clipboard.cpp +210 -0
  119. data/src/win32/event.cpp +11 -1
  120. data/src/win32/event.h +2 -0
  121. data/src/win32/menu.cpp +352 -0
  122. data/src/win32/menu.h +27 -0
  123. data/src/win32/window.cpp +62 -0
  124. data/src/win32/window.h +3 -0
  125. data/src/window.cpp +235 -22
  126. data/src/window.h +13 -2
  127. data/src/world.cpp +77 -14
  128. data/src/world.h +9 -2
  129. data/test/helper.rb +7 -0
  130. data/test/test_application.rb +11 -0
  131. data/test/test_chase_constraint.rb +124 -0
  132. data/test/test_clipboard.rb +54 -0
  133. data/test/test_constraint.rb +186 -0
  134. data/test/test_key_event.rb +6 -0
  135. data/test/test_link_constraint.rb +239 -0
  136. data/test/test_menu.rb +207 -0
  137. data/test/test_pin.rb +65 -0
  138. data/test/test_pointer.rb +23 -9
  139. data/test/test_pointer_event.rb +1 -1
  140. data/test/test_snap_constraint.rb +142 -0
  141. data/test/test_view.rb +113 -23
  142. data/test/test_wheel_constraint.rb +127 -0
  143. data/test/test_wheel_event.rb +15 -9
  144. data/test/test_window.rb +10 -0
  145. metadata +82 -8
@@ -1,6 +1,7 @@
1
1
  require 'xot/bit_flag_accessor'
2
2
  require 'xot/const_symbol_accessor'
3
3
  require 'reflex/ext'
4
+ require 'reflex/helper'
4
5
 
5
6
 
6
7
  module Reflex
@@ -16,18 +17,12 @@ module Reflex
16
17
  up: UP
17
18
  }
18
19
 
19
- bit_flag_reader :modifiers, **{
20
- shift: MOD_SHIFT,
21
- control: MOD_CONTROL,
22
- alt: MOD_ALT,
23
- win: MOD_WIN,
24
- option: MOD_OPTION,
25
- command: MOD_COMMAND,
26
- help: MOD_HELP,
27
- function: MOD_FUNCTION,
28
- numpad: MOD_NUMPAD,
29
- caps: MOD_CAPS,
30
- }
20
+ bit_flag_reader :modifiers, **MODIFIER_SYMBOLS
21
+ private alias_method :get_modifiers!, :modifiers
22
+
23
+ def modifiers(locks: true)
24
+ locks ? get_modifiers! : (get_modifiers! - LOCK_MODIFIER_SYMBOLS.keys)
25
+ end
31
26
 
32
27
  def down?()
33
28
  get_action == DOWN
@@ -0,0 +1,31 @@
1
+ require 'reflex/ext'
2
+ require 'reflex/constraint'
3
+
4
+
5
+ module Reflex
6
+
7
+
8
+ class LinkConstraint < Constraint
9
+
10
+ def range=(range)
11
+ case range
12
+ when nil then clear_range!
13
+ when Range then set_range! range.begin, range.end
14
+ when Numeric then set_range! range, range
15
+ else raise ArgumentError, "invalid range: #{range.inspect}"
16
+ end
17
+ end
18
+
19
+ def range()
20
+ has_range! ? Range.new(range_min!, range_max!) : nil
21
+ end
22
+
23
+ universal_accessor :axis, :distance, :range, :motor, :force
24
+
25
+ alias dist= distance=
26
+ alias dist distance
27
+
28
+ end# LinkConstraint
29
+
30
+
31
+ end# Reflex
@@ -0,0 +1,76 @@
1
+ require 'forwardable'
2
+ require 'xot/setter'
3
+ require 'xot/bit_flag_accessor'
4
+ require 'xot/universal_accessor'
5
+ require 'xot/hookable'
6
+ require 'xot/block_util'
7
+ require 'reflex/ext'
8
+ require 'reflex/helper'
9
+
10
+
11
+ module Reflex
12
+
13
+
14
+ class Menu
15
+
16
+ include Enumerable
17
+ include Xot::Setter
18
+ include Xot::Hookable
19
+
20
+ def initialize(label = nil, **options, &block)
21
+ super()
22
+ self.label = label if label
23
+ set **options unless options.empty?
24
+ Xot::BlockUtil.instance_eval_or_block_call self, &block if block
25
+ end
26
+
27
+ def add_child(child, index: nil)
28
+ add_child! child, index
29
+ end
30
+
31
+ alias add add_child
32
+ alias remove remove_child
33
+
34
+ def enable(bool = true)
35
+ enable! bool
36
+ end
37
+
38
+ def disable()
39
+ enable! false
40
+ end
41
+
42
+ def check(bool = true)
43
+ check! bool
44
+ end
45
+
46
+ def uncheck()
47
+ check! false
48
+ end
49
+
50
+ def shortcut=(key_and_modifiers)
51
+ key, *mods = key_and_modifiers
52
+ self.shortcut_key = key
53
+ self.shortcut_modifiers = mods
54
+ end
55
+
56
+ bit_flag_accessor :shortcut_modifiers, **SHORTCUT_MODIFIER_SYMBOLS
57
+
58
+ universal_accessor :label, :image, :shortcut_key, :shortcut_modifiers
59
+
60
+ def each(&block)
61
+ return enum_for :each unless block
62
+ each!(&block)
63
+ end
64
+
65
+ def children()
66
+ to_a
67
+ end
68
+
69
+ def inspect()
70
+ "#<Reflex::Menu label:#{label.inspect} size:#{size}>"
71
+ end
72
+
73
+ end# Menu
74
+
75
+
76
+ end# Reflex
data/lib/reflex/pin.rb ADDED
@@ -0,0 +1,39 @@
1
+ require 'xot/block_util'
2
+ require 'reflex/ext'
3
+
4
+
5
+ module Reflex
6
+
7
+
8
+ class Pin
9
+
10
+ def snap(*args, **options, &block)
11
+ setup__ snap!(*args), options, block
12
+ end
13
+
14
+ def link(*args, **options, &block)
15
+ setup__ link!(*args), options, block
16
+ end
17
+
18
+ def wheel(*args, **options, &block)
19
+ setup__ wheel!(*args), options, block
20
+ end
21
+
22
+ def chase(*args, **options, &block)
23
+ setup__ chase!(*args), options, block
24
+ end
25
+
26
+ alias pos position
27
+
28
+ private
29
+
30
+ def setup__(constraint, options, block)
31
+ constraint.set options unless options.empty?
32
+ Xot::BlockUtil.instance_eval_or_block_call constraint, &block if block
33
+ constraint
34
+ end
35
+
36
+ end# Pin
37
+
38
+
39
+ end# Reflex
@@ -1,6 +1,7 @@
1
1
  require 'xot/bit_flag_accessor'
2
2
  require 'xot/const_symbol_accessor'
3
3
  require 'reflex/ext'
4
+ require 'reflex/helper'
4
5
 
5
6
 
6
7
  module Reflex
@@ -29,9 +30,18 @@ module Reflex
29
30
  up: UP,
30
31
  move: MOVE,
31
32
  cancel: CANCEL,
33
+ enter: ENTER,
34
+ leave: LEAVE,
32
35
  stay: STAY
33
36
  }
34
37
 
38
+ bit_flag_reader :modifiers, **MODIFIER_SYMBOLS
39
+ private alias_method :get_modifiers!, :modifiers
40
+
41
+ def modifiers(locks: true)
42
+ locks ? get_modifiers! : (get_modifiers! - LOCK_MODIFIER_SYMBOLS.keys)
43
+ end
44
+
35
45
  def mouse?()
36
46
  (get_types & MOUSE) != 0
37
47
  end
@@ -76,6 +86,14 @@ module Reflex
76
86
  get_action == CANCEL
77
87
  end
78
88
 
89
+ def enter?()
90
+ get_action == ENTER
91
+ end
92
+
93
+ def leave?()
94
+ get_action == LEAVE
95
+ end
96
+
79
97
  def stay?()
80
98
  get_action == STAY
81
99
  end
@@ -15,7 +15,7 @@ module Reflex
15
15
  :id,
16
16
  :types, :mouse?, :touch?, :pen?,
17
17
  :mouse_left?, :left?, :mouse_right?, :right?, :mouse_middle?, :middle?,
18
- :action, :down?, :up?, :move?, :cancel?, :stay?,
18
+ :action, :down?, :up?, :move?, :cancel?, :enter?, :leave?, :stay?,
19
19
  :position, :pos, :x, :y, :modifiers, :click_count, :drag?,
20
20
  :time, :prev, :down
21
21
 
@@ -0,0 +1,28 @@
1
+ require 'reflex/ext'
2
+ require 'reflex/constraint'
3
+
4
+
5
+ module Reflex
6
+
7
+
8
+ class SnapConstraint < Constraint
9
+
10
+ def angle=(angle)
11
+ case angle
12
+ when nil then clear_angle!
13
+ when Range then set_angle! angle.begin, angle.end
14
+ when Numeric then set_angle! angle, angle
15
+ else raise ArgumentError, "invalid angle: #{angle.inspect}"
16
+ end
17
+ end
18
+
19
+ def angle()
20
+ has_angle! ? Range.new(angle_min!, angle_max!) : nil
21
+ end
22
+
23
+ universal_accessor :angle, :motor, :force
24
+
25
+ end# SnapConstraint
26
+
27
+
28
+ end# Reflex
data/lib/reflex/view.rb CHANGED
@@ -60,7 +60,7 @@ module Reflex
60
60
  end
61
61
 
62
62
  def timeout(seconds = 0, count: 1, &block)
63
- timer = start_timer seconds, count
63
+ timer = start_timer! seconds, count
64
64
  timer.block = block if block
65
65
  timer
66
66
  end
@@ -73,6 +73,10 @@ module Reflex
73
73
  timeout seconds, &block
74
74
  end
75
75
 
76
+ def add_child(child, index: nil)
77
+ add_child! child, index
78
+ end
79
+
76
80
  def remove_self()
77
81
  parent.remove self if parent
78
82
  end
@@ -81,12 +85,22 @@ module Reflex
81
85
  find_children(*args).first
82
86
  end
83
87
 
88
+ def each_child(&block)
89
+ return enum_for :each_child unless block
90
+ each_child!(&block)
91
+ end
92
+
84
93
  def children()
85
- to_enum :each_child
94
+ each_child.to_a
95
+ end
96
+
97
+ def each_style(&block)
98
+ return enum_for :each_style unless block
99
+ each_style!(&block)
86
100
  end
87
101
 
88
102
  def styles()
89
- to_enum :each_style
103
+ each_style.to_a
90
104
  end
91
105
 
92
106
  def style(*args, &block)
@@ -95,8 +109,46 @@ module Reflex
95
109
  s
96
110
  end
97
111
 
112
+ def each_shape(&block)
113
+ return enum_for :each_shape unless block
114
+ each_shape!(&block)
115
+ end
116
+
117
+ def add_shape(shape, index: nil)
118
+ add_shape! shape, index
119
+ end
120
+
98
121
  def shapes()
99
- to_enum :each_shape
122
+ each_shape.to_a
123
+ end
124
+
125
+ def pin(*args)
126
+ Pin.new self, *args
127
+ end
128
+
129
+ def snap(*args, **options, &block)
130
+ pin.snap(*args, **options, &block)
131
+ end
132
+
133
+ def link(*args, **options, &block)
134
+ pin.link(*args, **options, &block)
135
+ end
136
+
137
+ def wheel(*args, **options, &block)
138
+ pin.wheel(*args, **options, &block)
139
+ end
140
+
141
+ def chase(*args, **options, &block)
142
+ pin.chase(*args, **options, &block)
143
+ end
144
+
145
+ def each_constraint(&block)
146
+ return enum_for :each_constraint unless block
147
+ each_constraint!(&block)
148
+ end
149
+
150
+ def constraints()
151
+ each_constraint.to_a
100
152
  end
101
153
 
102
154
  def capturing?(*args)
@@ -0,0 +1,28 @@
1
+ require 'reflex/ext'
2
+ require 'reflex/constraint'
3
+
4
+
5
+ module Reflex
6
+
7
+
8
+ class WheelConstraint < Constraint
9
+
10
+ def range=(range)
11
+ case range
12
+ when nil then clear_range!
13
+ when Range then set_range! range.begin, range.end
14
+ when Numeric then set_range! range, range
15
+ else raise ArgumentError, "invalid range: #{range.inspect}"
16
+ end
17
+ end
18
+
19
+ def range()
20
+ has_range! ? Range.new(range_min!, range_max!) : nil
21
+ end
22
+
23
+ universal_accessor :axis, :range, :motor, :force
24
+
25
+ end# WheelConstraint
26
+
27
+
28
+ end# Reflex
@@ -1,4 +1,6 @@
1
+ require 'xot/bit_flag_accessor'
1
2
  require 'reflex/ext'
3
+ require 'reflex/helper'
2
4
 
3
5
 
4
6
  module Reflex
@@ -6,6 +8,13 @@ module Reflex
6
8
 
7
9
  class WheelEvent < Event
8
10
 
11
+ bit_flag_reader :modifiers, **MODIFIER_SYMBOLS
12
+ private alias_method :get_modifiers!, :modifiers
13
+
14
+ def modifiers(locks: true)
15
+ locks ? get_modifiers! : (get_modifiers! - LOCK_MODIFIER_SYMBOLS.keys)
16
+ end
17
+
9
18
  def inspect()
10
19
  "#<Reflex::WheelEvent x:#{x} y:#{y} z:#{z} dx:#{dx} dy:#{dy} dz:#{dz} mod:#{modifiers}>"
11
20
  end
data/lib/reflex.rb CHANGED
@@ -25,12 +25,6 @@ require 'reflex/style_length'
25
25
  require 'reflex/timer'
26
26
  require 'reflex/filter'
27
27
 
28
- require 'reflex/shape'
29
- require 'reflex/polygon_shape'
30
- require 'reflex/line_shape'
31
- require 'reflex/rect_shape'
32
- require 'reflex/ellipse_shape'
33
-
34
28
  require 'reflex/update_event'
35
29
  require 'reflex/draw_event'
36
30
  require 'reflex/frame_event'
@@ -45,13 +39,28 @@ require 'reflex/capture_event'
45
39
  require 'reflex/timer_event'
46
40
  require 'reflex/contact_event'
47
41
 
42
+ require 'reflex/shape'
43
+ require 'reflex/polygon_shape'
44
+ require 'reflex/line_shape'
45
+ require 'reflex/rect_shape'
46
+ require 'reflex/ellipse_shape'
47
+
48
+ require 'reflex/pin'
49
+ require 'reflex/constraint'
50
+ require 'reflex/snap_constraint'
51
+ require 'reflex/link_constraint'
52
+ require 'reflex/wheel_constraint'
53
+ require 'reflex/chase_constraint'
54
+
48
55
  require 'reflex/model'
49
56
  require 'reflex/model_owner'
50
57
 
51
58
  require 'reflex/application'
52
59
  require 'reflex/window'
53
60
  require 'reflex/view'
61
+ require 'reflex/menu'
54
62
  require 'reflex/screen'
63
+ require 'reflex/clipboard'
55
64
 
56
65
  require 'reflex/button'
57
66
  require 'reflex/text_view'
data/pod.rake CHANGED
@@ -3,7 +3,7 @@
3
3
 
4
4
  github = 'https://github.com/xord'
5
5
  renames = {reflexion: 'reflex'}
6
- regexp = /add\w+dependency.*['"](\w+)['"].*['"]\s*~>\s*([\d\.]+)\s*['"]/
6
+ regexp = /add\w+dependency.*['"]([\w\-]+)['"].*['"]\s*~>\s*([\d\.]+)\s*['"]/
7
7
  repos = File.readlines('reflex.gemspec', chomp: true)
8
8
  .map {|s| regexp.match(s)&.values_at 1, 2}
9
9
  .compact
@@ -15,7 +15,9 @@ task :clobber do
15
15
  sh %( rm -rf #{repos.keys.join ' '} )
16
16
  end
17
17
 
18
- task :setup
18
+ task :setup do
19
+ sh %( VENDOR_NOCOMPILE=1 rake vendor erb )
20
+ end
19
21
 
20
22
  repos.each do |repo, ver|
21
23
  rakefile = "#{repo}/Rakefile"
data/reflex.gemspec CHANGED
@@ -25,9 +25,9 @@ Gem::Specification.new do |s|
25
25
  s.platform = Gem::Platform::RUBY
26
26
  s.required_ruby_version = '>= 3.0.0'
27
27
 
28
- s.add_dependency 'xot', '~> 0.3.15'
29
- s.add_dependency 'rucy', '~> 0.3.15'
30
- s.add_dependency 'rays', '~> 0.3.16'
28
+ s.add_dependency 'xot', '~> 0.4.0'
29
+ s.add_dependency 'rucy', '~> 0.4.0'
30
+ s.add_dependency 'rays', '~> 0.4.0'
31
31
 
32
32
  s.files = `git ls-files`.split $/
33
33
  s.executables = s.files.grep(%r{^bin/}) {|f| File.basename f}
@@ -0,0 +1,152 @@
1
+ %w[xot rays reflex]
2
+ .map {|s| File.expand_path "../../#{s}/lib", __dir__}
3
+ .each {|s| $:.unshift s if !$:.include?(s) && File.directory?(s)}
4
+
5
+ require 'reflex'
6
+
7
+
8
+ Reflex.start name: "Constraint" do |app|
9
+ Reflex::Window.show title: app.name, frame: [100, 100, 500, 500] do
10
+ gravity 0, 9.8 * meter
11
+ #debug true
12
+
13
+ ball = -> x, y, size_ = 30, color = :red do
14
+ Reflex::View.new {
15
+ pos x, y
16
+ size size_
17
+ background color
18
+ dynamic true
19
+ shape Reflex::EllipseShape.new(density: 1)
20
+ }
21
+ end
22
+
23
+ anchor = -> x, y do
24
+ Reflex::View.new {
25
+ pos x, y
26
+ size 10
27
+ background :darkgray
28
+ static true
29
+ }
30
+ end
31
+
32
+ # pendulum: snap the hanging ball to the anchor center
33
+ pivot = add anchor.call(100, 100)
34
+ weight = add ball.call(160, 100, 30, :orange)
35
+ pivot.snap weight
36
+
37
+ # motored arm: snap with angle range and a motor
38
+ hinge = add anchor.call(250, 100)
39
+ arm = add ball.call(250, 140, 20, :peach)
40
+ hinge.snap arm, angle: -60..60, motor: 90
41
+
42
+ # ground: a bumpy line the car drives over
43
+ ground = [[0, 480], [70, 465], [140, 482], [210, 462],
44
+ [280, 480], [350, 465], [420, 482], [500, 470]]
45
+ add Reflex::View.new {
46
+ pos 0, 0; size 500, 500
47
+ static true
48
+ shape Reflex::LineShape.new.tap {|line| line.add_points(*ground.flatten)}
49
+ }
50
+
51
+ # car: each wheel rides on the body with a wheel joint -- a vertical rail
52
+ # gives suspension (spring) while the wheel spins freely, driven by a
53
+ # motor, so it rolls over the bumpy ground
54
+ body = add Reflex::View.new {
55
+ pos 50, 400; size 70, 16
56
+ background :white
57
+ dynamic true
58
+ shape Reflex::RectShape.new(density: 1)
59
+ }
60
+ wheels, axles = [], []
61
+ [14, 56].each do |x|
62
+ tire = add ball.call(40 + x, 415, 20, :gray)
63
+ wheels << tire
64
+ axles << tire.pin(10, 10).wheel(body.pin(x, 20),
65
+ axis: [0, 1], spring: 6, damping: 0.7, motor: 360)
66
+ end
67
+
68
+ # reverse the drive each time the car reaches a wall. a wheel or a body
69
+ # corner may touch first, so watch them all; the side check ignores the
70
+ # second touch when two parts hit the same wall together.
71
+ edge = wall
72
+ mid, side = body.parent.center.x, nil
73
+ reverse = lambda do |e|
74
+ left = body.center.x < mid
75
+ next if e.view != edge || left == side
76
+ side = left
77
+ axles.each {|a| a.motor = -a.motor}
78
+ end
79
+ [body, *wheels].each {|part| part.on :contact_begin, &reverse}
80
+
81
+ # spring chain: balls linked with springs
82
+ # (collide: true lets the nodes bump each other instead of overlapping)
83
+ top = add anchor.call(400, 50)
84
+ prev = top
85
+ 4.times do |i|
86
+ node = add ball.call(400, 90 + i * 40, 20, :green)
87
+ node.link prev, spring: 4, damping: 0.5, collide: true
88
+ prev = node
89
+ end
90
+
91
+ # elevator: a platform rails up and down the world on a vertical axis
92
+ # (a link with an axis), ping-ponging between the ends of its range
93
+ elevator = add Reflex::View.new {
94
+ pos 220, 320; size 60, 10
95
+ background :brown
96
+ dynamic true
97
+ shape Reflex::RectShape.new(density: 1)
98
+ }
99
+ elevator.gravity_scale = 0# the motor moves it, not the gravity
100
+ lift = elevator.pin.link axis: [0, 1], range: -60..60, motor: 30
101
+
102
+ # chaser: follows the pendulum weight with a soft spring
103
+ chaser = add ball.call(100, 400, 25, :blue)
104
+ chaser.gravity_scale = 0
105
+ chaser.sensor = true# do not bump the pendulum
106
+ chaser.chase weight, spring: 2, damping: 1
107
+
108
+ # drag any ball with a chase constraint
109
+ drag = nil
110
+ on :pointer do |e|
111
+ case
112
+ when e.down?
113
+ # hit test in each view's local space to respect rotation, and
114
+ # prefer the topmost (= last added) view
115
+ hit = children.to_a.reverse.find do |c|
116
+ next false unless c.dynamic?
117
+ p = c.from_parent e.pos
118
+ p.x.between?(0, c.frame.w) && p.y.between?(0, c.frame.h)
119
+ end
120
+ if hit
121
+ # pause the elevator drive, or the motor overpowers the drag
122
+ lift.motor = nil if hit == elevator
123
+ # grab the view at the clicked point, not at its center
124
+ drag = hit.pin(hit.from_parent e.pos).chase e.pos,
125
+ spring: 5, damping: 0.7
126
+ end
127
+ when e.drag?
128
+ drag.target = e.pos if drag
129
+ when e.up?
130
+ drag&.remove
131
+ drag = nil
132
+ lift.motor ||= 30# resume the elevator drive
133
+ end
134
+ end
135
+
136
+ after :on_draw do |e|
137
+ # reverse the elevator at the ends of its range (nil while dragging)
138
+ if lift.motor
139
+ lift.motor = -lift.motor.abs if lift.current_distance >= 55
140
+ lift.motor = lift.motor.abs if lift.current_distance <= -55
141
+ end
142
+
143
+ e.painter.push do
144
+ stroke :gray
145
+ ground.each_cons(2) {|a, b| line a[0], a[1], b[0], b[1]}
146
+ no_stroke
147
+ fill :white
148
+ text "#{e.fps.to_i} FPS - drag a ball to chase the pointer", 10, 10
149
+ end
150
+ end
151
+ end
152
+ end
data/samples/menu.rb ADDED
@@ -0,0 +1,29 @@
1
+ %w[xot rays reflex]
2
+ .map {|s| File.expand_path "../../#{s}/lib", __dir__}
3
+ .each {|s| $:.unshift s if !$:.include?(s) && File.directory?(s)}
4
+
5
+ require 'xot/util'
6
+ require 'reflex'
7
+
8
+ icon = Rays::Image.new(8, 8).paint {fill :red; ellipse 0, 0, 8}
9
+
10
+ Reflex.start do
11
+ app_menu = Reflex::Application.instance.menu || Reflex::Menu.new
12
+ file = app_menu.add Reflex::Menu.new('File'), index: 1
13
+ hello = file .add Reflex::Menu.new('Hello', image: icon)
14
+
15
+ popup_menu = Reflex::Menu.new
16
+ cut = popup_menu.add Reflex::Menu.new('Cut')
17
+ copy = popup_menu.add Reflex::Menu.new('Copy')
18
+ paste = popup_menu.add Reflex::Menu.new('Paste')
19
+
20
+ hello.on(:click) {|e| p :hello}
21
+ cut .on(:click) {|e| p :cut}
22
+ copy .on(:click) {|e| p :copy}
23
+ paste.on(:click) {|e| p :paste}
24
+
25
+ win = Reflex::Window.new title: 'Menu Test', frame: [100, 100, 400, 300]
26
+ win.menu = app_menu if Xot.win32?
27
+ win.on(:pointer_down) {|e| popup_menu.popup win.root, e.x, e.y if e.right?}
28
+ win.show
29
+ end
data/src/application.cpp CHANGED
@@ -32,8 +32,8 @@ namespace Reflex
32
32
  static void
33
33
  close_all_windows (Application* app)
34
34
  {
35
- for (auto it = app->window_begin(), end = app->window_end(); it != end; ++it)
36
- (*it)->close(true);
35
+ for (auto& window : Application::WindowList(app->window_begin(), app->window_end()))
36
+ window->close(true);
37
37
  }
38
38
 
39
39
  void
@@ -101,6 +101,25 @@ namespace Reflex
101
101
  return self->name.c_str();
102
102
  }
103
103
 
104
+ void
105
+ Application::set_menu (Menu* menu)
106
+ {
107
+ self->menu = menu;
108
+ Application_set_menu(this, menu);
109
+ }
110
+
111
+ Menu*
112
+ Application::menu ()
113
+ {
114
+ return self->menu.get();
115
+ }
116
+
117
+ const Menu*
118
+ Application::menu () const
119
+ {
120
+ return const_cast<Application*>(this)->menu();
121
+ }
122
+
104
123
  Application::window_iterator
105
124
  Application::window_begin ()
106
125
  {