cura 0.0.1 → 0.0.2
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.
- checksums.yaml +4 -4
- data/README.md +45 -21
- data/cura.gemspec +1 -1
- data/examples/hello_world/lib/hello_world.rb +10 -10
- data/examples/mruby-examples/mrbgem.rake +5 -6
- data/examples/todo_list/data.db +0 -0
- data/examples/todo_list/lib/todo_list/application.rb +24 -18
- data/lib/cura/adapter.rb +13 -20
- data/lib/cura/application.rb +47 -51
- data/lib/cura/attributes/has_ancestry.rb +4 -8
- data/lib/cura/attributes/has_application.rb +3 -7
- data/lib/cura/attributes/has_attributes.rb +1 -9
- data/lib/cura/attributes/has_children.rb +14 -20
- data/lib/cura/attributes/has_colors.rb +14 -18
- data/lib/cura/attributes/has_coordinates.rb +9 -15
- data/lib/cura/attributes/has_dimensions.rb +12 -18
- data/lib/cura/attributes/has_events.rb +10 -18
- data/lib/cura/attributes/has_focusability.rb +5 -11
- data/lib/cura/attributes/has_initialize.rb +1 -5
- data/lib/cura/attributes/has_offsets.rb +16 -20
- data/lib/cura/attributes/has_orientation.rb +12 -18
- data/lib/cura/attributes/has_relative_coordinates.rb +4 -8
- data/lib/cura/attributes/has_root.rb +18 -22
- data/lib/cura/attributes/has_side_attributes.rb +18 -24
- data/lib/cura/attributes/has_windows.rb +13 -19
- data/lib/cura/borders.rb +0 -4
- data/lib/cura/color.rb +84 -91
- data/lib/cura/component/base.rb +29 -33
- data/lib/cura/component/button.rb +10 -16
- data/lib/cura/component/group.rb +14 -18
- data/lib/cura/component/label.rb +44 -48
- data/lib/cura/component/listbox.rb +24 -28
- data/lib/cura/component/pack.rb +14 -18
- data/lib/cura/component/scrollbar.rb +41 -45
- data/lib/cura/component/textbox.rb +21 -25
- data/lib/cura/cursor.rb +15 -23
- data/lib/cura/error/base.rb +0 -3
- data/lib/cura/error/invalid_adapter.rb +1 -7
- data/lib/cura/error/invalid_application.rb +1 -7
- data/lib/cura/error/invalid_color.rb +1 -7
- data/lib/cura/error/invalid_component.rb +1 -7
- data/lib/cura/error/invalid_middleware.rb +1 -7
- data/lib/cura/event.rb +4 -8
- data/lib/cura/event/base.rb +17 -24
- data/lib/cura/event/click.rb +1 -6
- data/lib/cura/event/dispatcher.rb +20 -26
- data/lib/cura/event/focus.rb +1 -6
- data/lib/cura/event/handler.rb +16 -24
- data/lib/cura/event/key_down.rb +11 -17
- data/lib/cura/event/middleware/aimer/base.rb +4 -10
- data/lib/cura/event/middleware/aimer/dispatcher_target.rb +2 -8
- data/lib/cura/event/middleware/aimer/mouse_focus.rb +6 -11
- data/lib/cura/event/middleware/aimer/target_option.rb +4 -10
- data/lib/cura/event/middleware/base.rb +0 -4
- data/lib/cura/event/middleware/dispatch.rb +0 -4
- data/lib/cura/event/middleware/translator/base.rb +4 -10
- data/lib/cura/event/middleware/translator/mouse_click.rb +4 -8
- data/lib/cura/event/mouse.rb +5 -11
- data/lib/cura/event/mouse_button.rb +21 -27
- data/lib/cura/event/mouse_wheel_down.rb +1 -6
- data/lib/cura/event/mouse_wheel_up.rb +1 -6
- data/lib/cura/event/resize.rb +0 -4
- data/lib/cura/event/selected.rb +1 -6
- data/lib/cura/event/unfocus.rb +1 -6
- data/lib/cura/focus_controller.rb +19 -23
- data/lib/cura/key.rb +277 -283
- data/lib/cura/margins.rb +0 -4
- data/lib/cura/offsets.rb +14 -18
- data/lib/cura/padding.rb +0 -4
- data/lib/cura/pencil.rb +3 -7
- data/lib/cura/version.rb +1 -3
- data/lib/cura/window.rb +11 -16
- data/spec/cura/attributes/has_ancestry_spec.rb +39 -39
- data/spec/cura/attributes/has_application_spec.rb +20 -20
- data/spec/cura/attributes/has_attributes_spec.rb +26 -26
- data/spec/cura/attributes/has_children_spec.rb +54 -54
- data/spec/cura/attributes/has_colors_spec.rb +4 -4
- data/spec/cura/attributes/has_coordinates_spec.rb +4 -4
- data/spec/cura/attributes/has_dimensions_spec.rb +4 -4
- data/spec/cura/attributes/has_events_spec.rb +4 -4
- data/spec/cura/attributes/has_focusability_spec.rb +18 -18
- data/spec/cura/attributes/has_offsets_spec.rb +4 -4
- data/spec/cura/attributes/has_orientation_spec.rb +38 -38
- data/spec/cura/attributes/has_relative_coordinates_spec.rb +4 -4
- data/spec/cura/attributes/has_side_attributes_spec.rb +4 -4
- data/spec/spec_helper.rb +1 -1
- data/spec/support/shared_examples_for_attributes.rb +41 -41
- metadata +1 -1
data/lib/cura/event/click.rb
CHANGED
@@ -3,57 +3,53 @@ if Kernel.respond_to?(:require)
|
|
3
3
|
require "cura/attributes/has_attributes"
|
4
4
|
require "cura/attributes/has_application"
|
5
5
|
require "cura/attributes/has_events"
|
6
|
-
|
7
6
|
require "cura/event/base"
|
8
|
-
|
9
7
|
require "cura/error/invalid_middleware"
|
10
8
|
end
|
11
9
|
|
12
10
|
module Cura
|
13
11
|
module Event
|
14
|
-
|
15
12
|
# Polls or peeks for events since the last execution and dispatches them to the appropriate component.
|
16
13
|
class Dispatcher
|
17
|
-
|
18
14
|
include Attributes::HasInitialize
|
19
15
|
include Attributes::HasAttributes
|
20
16
|
include Attributes::HasApplication
|
21
|
-
|
17
|
+
|
22
18
|
def initialize(attributes={})
|
23
19
|
super
|
24
|
-
|
20
|
+
|
25
21
|
raise ArgumentError, "application must be set" if @application.nil?
|
26
|
-
|
22
|
+
|
27
23
|
@wait_time = 100
|
28
24
|
@target = @application if @target.nil?
|
29
25
|
@middleware = []
|
30
26
|
end
|
31
|
-
|
27
|
+
|
32
28
|
# @method wait_time
|
33
29
|
# Get the time to wait for events in milliseconds in the run loop.
|
34
30
|
#
|
35
31
|
# @return [Integer]
|
36
|
-
|
32
|
+
|
37
33
|
# @method wait_time=(value)
|
38
34
|
# Set the time to wait for events in milliseconds in the run loop.
|
39
35
|
# Set to 0 to wait forever (poll instead of peek).
|
40
36
|
#
|
41
37
|
# @param [#to_i] value
|
42
38
|
# @return [Integer]
|
43
|
-
|
39
|
+
|
44
40
|
attribute(:wait_time) do |value|
|
45
41
|
value = value.to_i
|
46
42
|
value = 0 if value < 0
|
47
|
-
|
43
|
+
|
48
44
|
value
|
49
45
|
end
|
50
|
-
|
46
|
+
|
51
47
|
# @method target
|
52
48
|
# Get the object with an event handler to dispatch events to.
|
53
49
|
#
|
54
50
|
# @return [Cura::Attributes::HasEvents]
|
55
51
|
attr_reader :target # TODO: use .attribute() { |value| ... }
|
56
|
-
|
52
|
+
|
57
53
|
# @method target=(value)
|
58
54
|
# Set the object with an event handler to dispatch events to.
|
59
55
|
# Setting to nil will automatially set the target to the application.
|
@@ -62,36 +58,36 @@ module Cura
|
|
62
58
|
# @return [Cura::Attributes::HasEvents]
|
63
59
|
def target=(value)
|
64
60
|
raise TypeError, "target must be a Cura::Attributes::HasEvents or nil" unless value.nil? || value.is_a?(Attributes::HasEvents)
|
65
|
-
|
61
|
+
|
66
62
|
dispatch_event(:unfocus)
|
67
63
|
@target = value.nil? ? @application : value
|
68
64
|
dispatch_event(:focus)
|
69
|
-
|
65
|
+
|
70
66
|
value
|
71
67
|
end
|
72
|
-
|
68
|
+
|
73
69
|
# The middleware stack which an event will pass through before being dispatched.
|
74
70
|
# Middleware must be an object responding to #call.
|
75
71
|
#
|
76
72
|
# @return [Array]
|
77
73
|
attr_reader :middleware
|
78
|
-
|
74
|
+
|
79
75
|
# Poll or peek for events and dispatch it if one was found.
|
80
76
|
#
|
81
77
|
# @return [Event::Dispatcher]
|
82
78
|
def run
|
83
79
|
event = @wait_time == 0 ? poll : peek(@wait_time)
|
84
|
-
|
80
|
+
|
85
81
|
dispatch_event(event) unless event.nil?
|
86
82
|
end
|
87
|
-
|
83
|
+
|
88
84
|
# Wait forever for an event.
|
89
85
|
#
|
90
86
|
# @return [Event::Base]
|
91
87
|
def poll
|
92
88
|
@application.adapter.poll_event
|
93
89
|
end
|
94
|
-
|
90
|
+
|
95
91
|
# Wait a set amount of time for an event.
|
96
92
|
#
|
97
93
|
# @param [#to_i] milliseconds The amount of time to wait in milliseconds.
|
@@ -99,7 +95,7 @@ module Cura
|
|
99
95
|
def peek(milliseconds=100)
|
100
96
|
@application.adapter.peek_event(milliseconds.to_i)
|
101
97
|
end
|
102
|
-
|
98
|
+
|
103
99
|
# Dispatch an event to the target or application, if the target is nil.
|
104
100
|
#
|
105
101
|
# @param [#to_sym] event The name of the event class to create an instance of or an event instance.
|
@@ -108,15 +104,13 @@ module Cura
|
|
108
104
|
def dispatch_event(event, options={})
|
109
105
|
event = Event.new_from_name(event, options) if event.respond_to?(:to_sym)
|
110
106
|
raise TypeError, "event must be an Event::Base" unless event.is_a?(Event::Base)
|
111
|
-
|
107
|
+
|
112
108
|
options = { dispatcher: self, event: event, dispatch_queue: [] }.merge(options.to_h)
|
113
|
-
|
109
|
+
|
114
110
|
@middleware.each { |middleware| middleware.call(options) }
|
115
|
-
|
111
|
+
|
116
112
|
options[:dispatch_queue].each(&:dispatch)
|
117
113
|
end
|
118
|
-
|
119
114
|
end
|
120
|
-
|
121
115
|
end
|
122
116
|
end
|
data/lib/cura/event/focus.rb
CHANGED
data/lib/cura/event/handler.rb
CHANGED
@@ -1,74 +1,66 @@
|
|
1
|
-
if Kernel.respond_to?(:require)
|
2
|
-
require "cura/attributes/has_events"
|
3
|
-
end
|
1
|
+
require "cura/attributes/has_events" if Kernel.respond_to?(:require)
|
4
2
|
|
5
3
|
module Cura
|
6
4
|
module Event
|
7
|
-
|
8
5
|
# The event handler.
|
9
|
-
# Each {Cura::Component} as well as several other class's instances have an instance of this handler.
|
6
|
+
# Each {Cura::Component} as well as several other class's instances have an instance of this handler.
|
10
7
|
# The handler can have multiple callbacks defined for an arbitrary event name.
|
11
8
|
class Handler
|
12
|
-
|
13
9
|
# @param [Cura::Attributes::HasEvents] host The object this handler is attached to.
|
14
10
|
def initialize(host)
|
15
11
|
raise TypeError, "host must be a Cura::Attributes::HasEvents" unless host.is_a?(Cura::Attributes::HasEvents)
|
16
|
-
|
12
|
+
|
17
13
|
@host = host
|
18
14
|
@callbacks = { default: [] }
|
19
15
|
end
|
20
|
-
|
16
|
+
|
21
17
|
# Get the object this handler is attached to.
|
22
|
-
#
|
18
|
+
#
|
23
19
|
# @return [Object]
|
24
20
|
attr_reader :host
|
25
|
-
|
21
|
+
|
26
22
|
# The callbacks defined on this handler.
|
27
23
|
# Key is the event name and the value is an Array of Proc instances.
|
28
|
-
#
|
24
|
+
#
|
29
25
|
# @return [Hash<Symbol,Array>]
|
30
26
|
attr_reader :callbacks
|
31
|
-
|
27
|
+
|
32
28
|
# Add a callback to the event chain.
|
33
29
|
# The first registered callback will be the first one called (FIFO).
|
34
30
|
# If no event_name is given, the callback is registered to the `:default` name, which are called before all others.
|
35
31
|
def register(event_name=:default, *arguments, &block)
|
36
32
|
(@callbacks[event_name] ||= []) << { block: block, arguments: arguments }
|
37
33
|
end
|
38
|
-
|
34
|
+
|
39
35
|
# Run all callbacks registered on this instance for the given event.
|
40
36
|
# The event object is given as a block argument to the callbacks.
|
41
37
|
# TODO: These should be able to break the callback chain by returning false in the callback (which would also break the delegation chain).
|
42
38
|
# TODO: The event should be delegated to the host's #parent if there are no callbacks registered for it, if it responds to #parent, and it's not nil.
|
43
39
|
def handle(event)
|
44
40
|
callbacks = @callbacks[:default] + @callbacks[event.class.name].to_a
|
45
|
-
|
41
|
+
|
46
42
|
chain_broken = false
|
47
43
|
callbacks.each do |callback|
|
48
|
-
|
49
44
|
result = host.instance_exec(event, *callback[:arguments], &callback[:block])
|
50
|
-
|
45
|
+
|
51
46
|
# TODO: Optional event consumption
|
52
47
|
if result == false
|
53
|
-
# chain_broken = true # TODO TODO TODO TODO TODO
|
54
|
-
|
48
|
+
# chain_broken = true # TODO TODO TODO TODO TODO
|
49
|
+
|
55
50
|
break
|
56
51
|
end
|
57
|
-
|
58
52
|
end
|
59
|
-
|
53
|
+
|
60
54
|
delegate_event(event) unless chain_broken
|
61
55
|
end
|
62
|
-
|
56
|
+
|
63
57
|
protected
|
64
|
-
|
58
|
+
|
65
59
|
# Propagate the event to the host's applicable #parent or #application.
|
66
60
|
# TODO: Why is the handler responsible for propagation? Should the component or a Event::Propagator be responsible?
|
67
61
|
def delegate_event(event)
|
68
62
|
host.parent.event_handler.handle(event) if host.respond_to?(:parent) && host.parent.respond_to?(:event_handler)
|
69
63
|
end
|
70
|
-
|
71
64
|
end
|
72
|
-
|
73
65
|
end
|
74
66
|
end
|
data/lib/cura/event/key_down.rb
CHANGED
@@ -1,51 +1,47 @@
|
|
1
|
-
if Kernel.respond_to?(:require)
|
2
|
-
require "cura/event/base"
|
3
|
-
end
|
1
|
+
require "cura/event/base" if Kernel.respond_to?(:require)
|
4
2
|
|
5
3
|
module Cura
|
6
4
|
module Event
|
7
|
-
|
8
5
|
# Dispatched when a key's state changes from up to down.
|
9
6
|
class KeyDown < Base
|
10
|
-
|
11
7
|
def initialize(attributes={})
|
12
8
|
@control = false
|
13
|
-
|
9
|
+
|
14
10
|
super
|
15
|
-
|
11
|
+
|
16
12
|
raise ArgumentError, "name must be set" if @name.nil?
|
17
13
|
end
|
18
|
-
|
14
|
+
|
19
15
|
# Get whether the key was pressed while holding the control key.
|
20
16
|
#
|
21
17
|
# @return [Boolean]
|
22
18
|
def control?
|
23
19
|
@control
|
24
20
|
end
|
25
|
-
|
21
|
+
|
26
22
|
# Get the key name.
|
27
23
|
#
|
28
24
|
# @return [Integer]
|
29
25
|
attr_reader :name
|
30
|
-
|
26
|
+
|
31
27
|
# Get whether the key is printable.
|
32
28
|
#
|
33
29
|
# @return [Boolean]
|
34
30
|
def printable?
|
35
31
|
return false if @control
|
36
|
-
|
32
|
+
|
37
33
|
Key.name_is_printable?(@name)
|
38
34
|
end
|
39
|
-
|
35
|
+
|
40
36
|
# Get the printable character for the key.
|
41
37
|
#
|
42
38
|
# @return [nil, String]
|
43
39
|
def character
|
44
40
|
Key.character_from_name(@name)
|
45
41
|
end
|
46
|
-
|
42
|
+
|
47
43
|
protected
|
48
|
-
|
44
|
+
|
49
45
|
# Set if the key was pressed while holding the control key.
|
50
46
|
#
|
51
47
|
# @param [Boolean] value
|
@@ -53,7 +49,7 @@ module Cura
|
|
53
49
|
def control=(value)
|
54
50
|
@control = !!value
|
55
51
|
end
|
56
|
-
|
52
|
+
|
57
53
|
# Set the key name.
|
58
54
|
#
|
59
55
|
# @param [#to_sym] value
|
@@ -61,8 +57,6 @@ module Cura
|
|
61
57
|
def name=(value)
|
62
58
|
@name = value.to_sym
|
63
59
|
end
|
64
|
-
|
65
60
|
end
|
66
|
-
|
67
61
|
end
|
68
62
|
end
|
@@ -1,15 +1,11 @@
|
|
1
|
-
if Kernel.respond_to?(:require)
|
2
|
-
require "cura/event/middleware/base"
|
3
|
-
end
|
1
|
+
require "cura/event/middleware/base" if Kernel.respond_to?(:require)
|
4
2
|
|
5
3
|
module Cura
|
6
4
|
module Event
|
7
5
|
module Middleware
|
8
6
|
module Aimer
|
9
|
-
|
10
7
|
# The base class for event middleware which set's a target, if needed.
|
11
8
|
class Base
|
12
|
-
|
13
9
|
# Call this middleware.
|
14
10
|
#
|
15
11
|
# @param [#to_h] options
|
@@ -19,19 +15,17 @@ module Cura
|
|
19
15
|
def call(options={})
|
20
16
|
set_target(options) if should_aim?(options)
|
21
17
|
end
|
22
|
-
|
18
|
+
|
23
19
|
protected
|
24
|
-
|
20
|
+
|
25
21
|
def should_aim?(options={})
|
26
22
|
options[:event].target.nil?
|
27
23
|
end
|
28
|
-
|
24
|
+
|
29
25
|
def set_target(_options={})
|
30
26
|
# Does nothing on purpose
|
31
27
|
end
|
32
|
-
|
33
28
|
end
|
34
|
-
|
35
29
|
end
|
36
30
|
end
|
37
31
|
end
|
@@ -1,23 +1,17 @@
|
|
1
|
-
if Kernel.respond_to?(:require)
|
2
|
-
require "cura/event/middleware/aimer/base"
|
3
|
-
end
|
1
|
+
require "cura/event/middleware/aimer/base" if Kernel.respond_to?(:require)
|
4
2
|
|
5
3
|
module Cura
|
6
4
|
module Event
|
7
5
|
module Middleware
|
8
6
|
module Aimer
|
9
|
-
|
10
7
|
# Sets the event's target to the dispatcher's target, if it isn't already set.
|
11
8
|
class DispatcherTarget < Base
|
12
|
-
|
13
9
|
protected
|
14
|
-
|
10
|
+
|
15
11
|
def set_target(options={})
|
16
12
|
options[:event].target ||= options[:dispatcher].target
|
17
13
|
end
|
18
|
-
|
19
14
|
end
|
20
|
-
|
21
15
|
end
|
22
16
|
end
|
23
17
|
end
|
@@ -1,6 +1,5 @@
|
|
1
1
|
if Kernel.respond_to?(:require)
|
2
2
|
require "cura/event/mouse_button"
|
3
|
-
|
4
3
|
require "cura/event/middleware/aimer/base"
|
5
4
|
end
|
6
5
|
|
@@ -8,22 +7,20 @@ module Cura
|
|
8
7
|
module Event
|
9
8
|
module Middleware
|
10
9
|
module Aimer
|
11
|
-
|
12
10
|
# Sets the dispatcher's target to the component underneath the cursor on mouse button events.
|
13
11
|
class MouseFocus < Base
|
14
|
-
|
15
12
|
protected
|
16
|
-
|
13
|
+
|
17
14
|
def should_aim?(options={})
|
18
15
|
options[:event].is_a?(Event::MouseButton) && options[:event].down?
|
19
16
|
end
|
20
|
-
|
17
|
+
|
21
18
|
def set_target(options={})
|
22
19
|
component = nearest_focusable_ancestor(top_most_component_at(options))
|
23
|
-
|
20
|
+
|
24
21
|
options[:dispatcher].target = component unless options[:dispatcher].target == component
|
25
22
|
end
|
26
|
-
|
23
|
+
|
27
24
|
# TODO: Some kind of hit tester class that initializes with a Window to get it's root element and determines
|
28
25
|
# if a set of coordinates are within the bounds of which component in the view tree.
|
29
26
|
def top_most_component_at(options={})
|
@@ -31,17 +28,15 @@ module Cura
|
|
31
28
|
window = options[:dispatcher].application.windows.first # TODO: Should be getting the screen coordinates from the event, not relevent to the window
|
32
29
|
window.children(true).reverse.find { |child| child.contains_coordinates?(x: options[:event].x, y: options[:event].y) }
|
33
30
|
end
|
34
|
-
|
31
|
+
|
35
32
|
def nearest_focusable_ancestor(component)
|
36
33
|
return nil unless component.respond_to?(:focusable?)
|
37
34
|
return component if component.focusable?
|
38
35
|
return nil unless component.respond_to?(:parent)
|
39
|
-
|
36
|
+
|
40
37
|
nearest_focusable_ancestor(component.parent)
|
41
38
|
end
|
42
|
-
|
43
39
|
end
|
44
|
-
|
45
40
|
end
|
46
41
|
end
|
47
42
|
end
|