charming 0.2.3 → 0.4.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.
- checksums.yaml +4 -4
- data/README.md +3 -1
- data/lib/charming/application.rb +98 -14
- data/lib/charming/application_state.rb +23 -0
- data/lib/charming/cli.rb +2 -2
- data/lib/charming/controller/action_hooks.rb +5 -1
- data/lib/charming/controller/class_methods.rb +79 -17
- data/lib/charming/controller/component_dispatch.rb +163 -0
- data/lib/charming/controller/dispatching.rb +1 -2
- data/lib/charming/controller/focus_management.rb +67 -1
- data/lib/charming/controller/key_dispatch.rb +7 -7
- data/lib/charming/controller/rendering.rb +22 -6
- data/lib/charming/controller/session_state.rb +63 -22
- data/lib/charming/controller/timers.rb +25 -0
- data/lib/charming/controller.rb +253 -60
- data/lib/charming/cross_thread_access.rb +9 -0
- data/lib/charming/double_render_error.rb +8 -0
- data/lib/charming/generators/layout_generator.rb +4 -1
- data/lib/charming/generators/migration_generator.rb +1 -1
- data/lib/charming/generators/model_generator.rb +2 -2
- data/lib/charming/generators/name.rb +1 -1
- data/lib/charming/generators/screen_generator.rb +2 -2
- data/lib/charming/generators/view_generator.rb +1 -1
- data/lib/charming/internal/deep_freeze.rb +23 -0
- data/lib/charming/internal/env_inquirer.rb +22 -0
- data/lib/charming/internal/event_loop.rb +25 -2
- data/lib/charming/internal/inflections.rb +93 -0
- data/lib/charming/internal/session_guard.rb +27 -0
- data/lib/charming/internal/terminal/cursor.rb +29 -0
- data/lib/charming/internal/terminal/size.rb +47 -0
- data/lib/charming/internal/terminal/tty_backend.rb +10 -8
- data/lib/charming/internal/timer_control.rb +48 -0
- data/lib/charming/presentation/components/autocomplete.rb +14 -6
- data/lib/charming/presentation/components/command_palette.rb +11 -9
- data/lib/charming/presentation/components/filepicker.rb +4 -4
- data/lib/charming/presentation/components/form/confirm.rb +2 -1
- data/lib/charming/presentation/components/form/field.rb +1 -1
- data/lib/charming/presentation/components/form/input.rb +3 -3
- data/lib/charming/presentation/components/form/multiselect.rb +4 -5
- data/lib/charming/presentation/components/form/select.rb +3 -3
- data/lib/charming/presentation/components/form/textarea.rb +3 -3
- data/lib/charming/presentation/components/form.rb +6 -6
- data/lib/charming/presentation/components/help_overlay.rb +2 -2
- data/lib/charming/presentation/components/keyboard_handler.rb +3 -3
- data/lib/charming/presentation/components/list.rb +14 -5
- data/lib/charming/presentation/components/modal.rb +3 -2
- data/lib/charming/presentation/components/multi_select_list.rb +14 -7
- data/lib/charming/presentation/components/result.rb +61 -0
- data/lib/charming/presentation/components/tab_bar.rb +14 -6
- data/lib/charming/presentation/components/table.rb +64 -32
- data/lib/charming/presentation/components/text_area.rb +7 -7
- data/lib/charming/presentation/components/text_input.rb +7 -7
- data/lib/charming/presentation/components/tree.rb +15 -6
- data/lib/charming/presentation/components/viewport.rb +3 -3
- data/lib/charming/presentation/layout/pane.rb +6 -2
- data/lib/charming/presentation/layout/screen_layout.rb +7 -0
- data/lib/charming/presentation/view.rb +35 -29
- data/lib/charming/projectile.rb +64 -0
- data/lib/charming/render_artifacts.rb +24 -0
- data/lib/charming/response.rb +19 -8
- data/lib/charming/router.rb +50 -68
- data/lib/charming/runtime.rb +54 -28
- data/lib/charming/{controller/command_palette.rb → shell/palette.rb} +43 -11
- data/lib/charming/{controller/sidebar_navigation.rb → shell/sidebar.rb} +11 -11
- data/lib/charming/spring.rb +126 -0
- data/lib/charming/tasks/context.rb +35 -0
- data/lib/charming/test_helper.rb +42 -22
- data/lib/charming/unhandled_component_event.rb +9 -0
- data/lib/charming/unknown_slot.rb +9 -0
- data/lib/charming/version.rb +1 -1
- data/lib/charming/welcome.rb +1 -1
- data/lib/charming.rb +20 -6
- metadata +25 -70
- data/lib/charming/controller/component_dispatching.rb +0 -125
data/lib/charming.rb
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require "active_support/inflector"
|
|
4
|
-
require "active_support/string_inquirer"
|
|
5
3
|
require "logger"
|
|
6
4
|
require "zeitwerk"
|
|
7
5
|
|
|
@@ -26,15 +24,15 @@ module Charming
|
|
|
26
24
|
# Base error class for all Charming-specific exceptions (used by templates, generators, runtime, etc.).
|
|
27
25
|
class Error < StandardError; end
|
|
28
26
|
|
|
29
|
-
# The current environment, read from CHARMING_ENV (default "development"). Returns
|
|
30
|
-
#
|
|
27
|
+
# The current environment, read from CHARMING_ENV (default "development"). Returns an
|
|
28
|
+
# EnvInquirer so callers can write `Charming.env.test?` / `Charming.env.production?`.
|
|
31
29
|
def self.env
|
|
32
|
-
@env ||=
|
|
30
|
+
@env ||= Internal::EnvInquirer.new(ENV["CHARMING_ENV"] || "development")
|
|
33
31
|
end
|
|
34
32
|
|
|
35
33
|
# Overrides the environment (used by tests and the CLI).
|
|
36
34
|
def self.env=(value)
|
|
37
|
-
@env = value.nil? ? nil :
|
|
35
|
+
@env = value.nil? ? nil : Internal::EnvInquirer.new(value.to_s)
|
|
38
36
|
end
|
|
39
37
|
|
|
40
38
|
# Entry point for running a Charming application. Instantiates a Runtime for *application* and starts
|
|
@@ -43,6 +41,12 @@ module Charming
|
|
|
43
41
|
Runtime.new(application, backend: backend).run
|
|
44
42
|
end
|
|
45
43
|
|
|
44
|
+
# Returns the seconds-per-frame time delta for a frame rate, for initializing
|
|
45
|
+
# physics primitives: `Charming::Spring.new(delta_time: Charming.fps(60))`.
|
|
46
|
+
def self.fps(frames_per_second)
|
|
47
|
+
1.0 / frames_per_second
|
|
48
|
+
end
|
|
49
|
+
|
|
46
50
|
# Returns the normalized key symbol for an event-like object — `event.key` when the object responds
|
|
47
51
|
# to it, otherwise `event.to_sym`. Lets components treat raw strings and KeyEvent objects uniformly.
|
|
48
52
|
def self.key_of(event)
|
|
@@ -78,6 +82,16 @@ module Charming
|
|
|
78
82
|
|
|
79
83
|
:"#{(ordered_modifiers + [key]).join("+")}"
|
|
80
84
|
end
|
|
85
|
+
|
|
86
|
+
# Emits a deprecation warning once per process per *category*, prefixed
|
|
87
|
+
# "[charming deprecation]". Warnings go to stderr.
|
|
88
|
+
def self.deprecate(message, category:)
|
|
89
|
+
@deprecation_emitted ||= {}
|
|
90
|
+
return if @deprecation_emitted[category]
|
|
91
|
+
|
|
92
|
+
@deprecation_emitted[category] = true
|
|
93
|
+
warn("[charming deprecation] #{message}")
|
|
94
|
+
end
|
|
81
95
|
end
|
|
82
96
|
|
|
83
97
|
Charming::Templates.register ".tui.erb", Charming::Templates::ErbHandler
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: charming
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.4.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- pando
|
|
@@ -29,26 +29,6 @@ dependencies:
|
|
|
29
29
|
- - ">="
|
|
30
30
|
- !ruby/object:Gem::Version
|
|
31
31
|
version: 8.1.2
|
|
32
|
-
- !ruby/object:Gem::Dependency
|
|
33
|
-
name: activesupport
|
|
34
|
-
requirement: !ruby/object:Gem::Requirement
|
|
35
|
-
requirements:
|
|
36
|
-
- - "~>"
|
|
37
|
-
- !ruby/object:Gem::Version
|
|
38
|
-
version: '8.1'
|
|
39
|
-
- - ">="
|
|
40
|
-
- !ruby/object:Gem::Version
|
|
41
|
-
version: 8.1.2
|
|
42
|
-
type: :runtime
|
|
43
|
-
prerelease: false
|
|
44
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
45
|
-
requirements:
|
|
46
|
-
- - "~>"
|
|
47
|
-
- !ruby/object:Gem::Version
|
|
48
|
-
version: '8.1'
|
|
49
|
-
- - ">="
|
|
50
|
-
- !ruby/object:Gem::Version
|
|
51
|
-
version: 8.1.2
|
|
52
32
|
- !ruby/object:Gem::Dependency
|
|
53
33
|
name: commonmarker
|
|
54
34
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -91,48 +71,6 @@ dependencies:
|
|
|
91
71
|
- - "~>"
|
|
92
72
|
- !ruby/object:Gem::Version
|
|
93
73
|
version: '5.0'
|
|
94
|
-
- !ruby/object:Gem::Dependency
|
|
95
|
-
name: tty-cursor
|
|
96
|
-
requirement: !ruby/object:Gem::Requirement
|
|
97
|
-
requirements:
|
|
98
|
-
- - "~>"
|
|
99
|
-
- !ruby/object:Gem::Version
|
|
100
|
-
version: '0.7'
|
|
101
|
-
type: :runtime
|
|
102
|
-
prerelease: false
|
|
103
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
104
|
-
requirements:
|
|
105
|
-
- - "~>"
|
|
106
|
-
- !ruby/object:Gem::Version
|
|
107
|
-
version: '0.7'
|
|
108
|
-
- !ruby/object:Gem::Dependency
|
|
109
|
-
name: zeitwerk
|
|
110
|
-
requirement: !ruby/object:Gem::Requirement
|
|
111
|
-
requirements:
|
|
112
|
-
- - "~>"
|
|
113
|
-
- !ruby/object:Gem::Version
|
|
114
|
-
version: '2.6'
|
|
115
|
-
type: :runtime
|
|
116
|
-
prerelease: false
|
|
117
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
118
|
-
requirements:
|
|
119
|
-
- - "~>"
|
|
120
|
-
- !ruby/object:Gem::Version
|
|
121
|
-
version: '2.6'
|
|
122
|
-
- !ruby/object:Gem::Dependency
|
|
123
|
-
name: tty-table
|
|
124
|
-
requirement: !ruby/object:Gem::Requirement
|
|
125
|
-
requirements:
|
|
126
|
-
- - "~>"
|
|
127
|
-
- !ruby/object:Gem::Version
|
|
128
|
-
version: '0.12'
|
|
129
|
-
type: :runtime
|
|
130
|
-
prerelease: false
|
|
131
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
132
|
-
requirements:
|
|
133
|
-
- - "~>"
|
|
134
|
-
- !ruby/object:Gem::Version
|
|
135
|
-
version: '0.12'
|
|
136
74
|
- !ruby/object:Gem::Dependency
|
|
137
75
|
name: tty-reader
|
|
138
76
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -148,21 +86,21 @@ dependencies:
|
|
|
148
86
|
- !ruby/object:Gem::Version
|
|
149
87
|
version: '0.9'
|
|
150
88
|
- !ruby/object:Gem::Dependency
|
|
151
|
-
name:
|
|
89
|
+
name: unicode-display_width
|
|
152
90
|
requirement: !ruby/object:Gem::Requirement
|
|
153
91
|
requirements:
|
|
154
92
|
- - "~>"
|
|
155
93
|
- !ruby/object:Gem::Version
|
|
156
|
-
version: '
|
|
94
|
+
version: '2.6'
|
|
157
95
|
type: :runtime
|
|
158
96
|
prerelease: false
|
|
159
97
|
version_requirements: !ruby/object:Gem::Requirement
|
|
160
98
|
requirements:
|
|
161
99
|
- - "~>"
|
|
162
100
|
- !ruby/object:Gem::Version
|
|
163
|
-
version: '
|
|
101
|
+
version: '2.6'
|
|
164
102
|
- !ruby/object:Gem::Dependency
|
|
165
|
-
name:
|
|
103
|
+
name: zeitwerk
|
|
166
104
|
requirement: !ruby/object:Gem::Requirement
|
|
167
105
|
requirements:
|
|
168
106
|
- - "~>"
|
|
@@ -196,17 +134,18 @@ files:
|
|
|
196
134
|
- lib/charming/controller.rb
|
|
197
135
|
- lib/charming/controller/action_hooks.rb
|
|
198
136
|
- lib/charming/controller/class_methods.rb
|
|
199
|
-
- lib/charming/controller/
|
|
200
|
-
- lib/charming/controller/component_dispatching.rb
|
|
137
|
+
- lib/charming/controller/component_dispatch.rb
|
|
201
138
|
- lib/charming/controller/dispatching.rb
|
|
202
139
|
- lib/charming/controller/focus.rb
|
|
203
140
|
- lib/charming/controller/focus_management.rb
|
|
204
141
|
- lib/charming/controller/key_dispatch.rb
|
|
205
142
|
- lib/charming/controller/rendering.rb
|
|
206
143
|
- lib/charming/controller/session_state.rb
|
|
207
|
-
- lib/charming/controller/sidebar_navigation.rb
|
|
208
144
|
- lib/charming/controller/terminal.rb
|
|
145
|
+
- lib/charming/controller/timers.rb
|
|
146
|
+
- lib/charming/cross_thread_access.rb
|
|
209
147
|
- lib/charming/database/commands.rb
|
|
148
|
+
- lib/charming/double_render_error.rb
|
|
210
149
|
- lib/charming/escape.rb
|
|
211
150
|
- lib/charming/events/focus_event.rb
|
|
212
151
|
- lib/charming/events/key_event.rb
|
|
@@ -267,15 +206,22 @@ files:
|
|
|
267
206
|
- lib/charming/image/source.rb
|
|
268
207
|
- lib/charming/image/terminal.rb
|
|
269
208
|
- lib/charming/image/transmit.rb
|
|
209
|
+
- lib/charming/internal/deep_freeze.rb
|
|
210
|
+
- lib/charming/internal/env_inquirer.rb
|
|
270
211
|
- lib/charming/internal/event_loop.rb
|
|
212
|
+
- lib/charming/internal/inflections.rb
|
|
271
213
|
- lib/charming/internal/renderer/differential.rb
|
|
272
214
|
- lib/charming/internal/renderer/full_repaint.rb
|
|
215
|
+
- lib/charming/internal/session_guard.rb
|
|
273
216
|
- lib/charming/internal/terminal/adapter.rb
|
|
217
|
+
- lib/charming/internal/terminal/cursor.rb
|
|
274
218
|
- lib/charming/internal/terminal/key_normalizer.rb
|
|
275
219
|
- lib/charming/internal/terminal/memory_backend.rb
|
|
276
220
|
- lib/charming/internal/terminal/modified_key_parser.rb
|
|
277
221
|
- lib/charming/internal/terminal/mouse_parser.rb
|
|
222
|
+
- lib/charming/internal/terminal/size.rb
|
|
278
223
|
- lib/charming/internal/terminal/tty_backend.rb
|
|
224
|
+
- lib/charming/internal/timer_control.rb
|
|
279
225
|
- lib/charming/presentation/component.rb
|
|
280
226
|
- lib/charming/presentation/components/activity_indicator.rb
|
|
281
227
|
- lib/charming/presentation/components/audio.rb
|
|
@@ -307,6 +253,7 @@ files:
|
|
|
307
253
|
- lib/charming/presentation/components/multi_select_list.rb
|
|
308
254
|
- lib/charming/presentation/components/paginator.rb
|
|
309
255
|
- lib/charming/presentation/components/progressbar.rb
|
|
256
|
+
- lib/charming/presentation/components/result.rb
|
|
310
257
|
- lib/charming/presentation/components/sparkline.rb
|
|
311
258
|
- lib/charming/presentation/components/spinner.rb
|
|
312
259
|
- lib/charming/presentation/components/status_bar.rb
|
|
@@ -366,16 +313,24 @@ files:
|
|
|
366
313
|
- lib/charming/presentation/ui/truncate.rb
|
|
367
314
|
- lib/charming/presentation/ui/width.rb
|
|
368
315
|
- lib/charming/presentation/view.rb
|
|
316
|
+
- lib/charming/projectile.rb
|
|
317
|
+
- lib/charming/render_artifacts.rb
|
|
369
318
|
- lib/charming/response.rb
|
|
370
319
|
- lib/charming/router.rb
|
|
371
320
|
- lib/charming/runtime.rb
|
|
372
321
|
- lib/charming/screen.rb
|
|
322
|
+
- lib/charming/shell/palette.rb
|
|
323
|
+
- lib/charming/shell/sidebar.rb
|
|
324
|
+
- lib/charming/spring.rb
|
|
373
325
|
- lib/charming/tasks/cancelled.rb
|
|
326
|
+
- lib/charming/tasks/context.rb
|
|
374
327
|
- lib/charming/tasks/inline_executor.rb
|
|
375
328
|
- lib/charming/tasks/progress.rb
|
|
376
329
|
- lib/charming/tasks/task.rb
|
|
377
330
|
- lib/charming/tasks/threaded_executor.rb
|
|
378
331
|
- lib/charming/test_helper.rb
|
|
332
|
+
- lib/charming/unhandled_component_event.rb
|
|
333
|
+
- lib/charming/unknown_slot.rb
|
|
379
334
|
- lib/charming/version.rb
|
|
380
335
|
- lib/charming/welcome.rb
|
|
381
336
|
- lib/charming/welcome/controller.rb
|
|
@@ -1,125 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Charming
|
|
4
|
-
class Controller
|
|
5
|
-
# Component-dispatch helpers mixed into Controller. Forwards key events to the currently
|
|
6
|
-
# focused component (the slot returned by `focus.current`) and translates component return
|
|
7
|
-
# values into controller hook calls (e.g., `slot_submitted`, `slot_selected`, `slot_cancelled`).
|
|
8
|
-
module ComponentDispatching
|
|
9
|
-
private
|
|
10
|
-
|
|
11
|
-
# Sends the current key event to the focused component (if it responds to `handle_key`).
|
|
12
|
-
# Returns `:handled` after dispatching, or nil when no component is focused.
|
|
13
|
-
def dispatch_to_focused_component
|
|
14
|
-
slot = focus.current
|
|
15
|
-
return nil unless slot && respond_to?(slot, true)
|
|
16
|
-
|
|
17
|
-
component = send(slot)
|
|
18
|
-
return nil unless component.respond_to?(:handle_key)
|
|
19
|
-
|
|
20
|
-
result = component.handle_key(event)
|
|
21
|
-
return nil if result.nil?
|
|
22
|
-
|
|
23
|
-
dispatch_component_result(slot, result)
|
|
24
|
-
:handled
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
# Translates a component `handle_key` *result* into a controller hook call. `:cancelled`
|
|
28
|
-
# triggers `<slot>_cancelled`, `[:submitted, value]` triggers `<slot>_submitted(value)`,
|
|
29
|
-
# `[:selected, value]` triggers `<slot>_selected(value)`. Falls back to a default render
|
|
30
|
-
# when no matching hook exists.
|
|
31
|
-
def dispatch_component_result(slot, result)
|
|
32
|
-
action, arguments = component_result_action(slot, result)
|
|
33
|
-
action ? send(action, *arguments) : render_default_action
|
|
34
|
-
render_default_action unless response
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
# Resolves which controller hook (if any) corresponds to the *result* from a component.
|
|
38
|
-
def component_result_action(slot, result)
|
|
39
|
-
case result
|
|
40
|
-
when :cancelled
|
|
41
|
-
component_action(slot, :cancelled)
|
|
42
|
-
when Array
|
|
43
|
-
component_array_action(slot, result)
|
|
44
|
-
end
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
# Handles array-shaped component results, currently `[:submitted, value]` and `[:selected, value]`.
|
|
48
|
-
def component_array_action(slot, result)
|
|
49
|
-
event_name, value = result
|
|
50
|
-
return component_action(slot, :submitted, value) if event_name == :submitted
|
|
51
|
-
return component_action(slot, :selected, value) if event_name == :selected
|
|
52
|
-
|
|
53
|
-
nil
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
# Returns `[action, arguments]` for the `<slot>_<suffix>` controller hook if defined, or nil.
|
|
57
|
-
def component_action(slot, suffix, *arguments)
|
|
58
|
-
action = :"#{slot}_#{suffix}"
|
|
59
|
-
return unless respond_to?(action, true)
|
|
60
|
-
|
|
61
|
-
[action, arguments]
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
# Handles Tab/Shift+Tab by cycling through the focus ring. Returns :handled after rendering.
|
|
65
|
-
def dispatch_tab_traversal
|
|
66
|
-
return nil unless key_name == :tab
|
|
67
|
-
return nil if focus.ring.empty?
|
|
68
|
-
|
|
69
|
-
focus.cycle(event.shift ? -1 : +1)
|
|
70
|
-
render_default_action
|
|
71
|
-
:handled
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
# Hit-tests the current mouse event against named layout panes from the latest render.
|
|
75
|
-
# Clicks move focus to matching slots; components in clicked panes receive local coordinates.
|
|
76
|
-
def dispatch_component_mouse
|
|
77
|
-
target = mouse_target_for_event
|
|
78
|
-
return nil unless target
|
|
79
|
-
|
|
80
|
-
slot = target.fetch(:name)
|
|
81
|
-
previous_focus = focus.current
|
|
82
|
-
focus.focus(slot) if focusable_click?(slot)
|
|
83
|
-
|
|
84
|
-
result = dispatch_mouse_to_target_component(slot, target)
|
|
85
|
-
return response if result.nil? && previous_focus == focus.current
|
|
86
|
-
|
|
87
|
-
result ? dispatch_component_result(slot, result) : render_default_action
|
|
88
|
-
response
|
|
89
|
-
end
|
|
90
|
-
|
|
91
|
-
def mouse_target_for_event
|
|
92
|
-
mouse_targets.rfind { |target| target.fetch(:rect).cover?(event.x, event.y) }
|
|
93
|
-
end
|
|
94
|
-
|
|
95
|
-
def focusable_click?(slot)
|
|
96
|
-
event.respond_to?(:click?) && event.click? && focus.ring.include?(slot)
|
|
97
|
-
end
|
|
98
|
-
|
|
99
|
-
def dispatch_mouse_to_target_component(slot, target)
|
|
100
|
-
return nil unless respond_to?(slot, true)
|
|
101
|
-
|
|
102
|
-
component = send(slot)
|
|
103
|
-
return nil unless component.respond_to?(:handle_mouse)
|
|
104
|
-
|
|
105
|
-
local_event = local_mouse_event(target.fetch(:inner_rect))
|
|
106
|
-
return nil unless local_event
|
|
107
|
-
|
|
108
|
-
component.handle_mouse(local_event)
|
|
109
|
-
end
|
|
110
|
-
|
|
111
|
-
def local_mouse_event(rect)
|
|
112
|
-
return nil unless rect.cover?(event.x, event.y)
|
|
113
|
-
|
|
114
|
-
Events::MouseEvent.new(
|
|
115
|
-
button: event.button,
|
|
116
|
-
x: event.x - rect.x,
|
|
117
|
-
y: event.y - rect.y,
|
|
118
|
-
ctrl: event.ctrl,
|
|
119
|
-
alt: event.alt,
|
|
120
|
-
shift: event.shift
|
|
121
|
-
)
|
|
122
|
-
end
|
|
123
|
-
end
|
|
124
|
-
end
|
|
125
|
-
end
|