reflexion 0.3.15 → 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/.doc/ext/reflex/key_event.cpp +3 -3
- data/.github/workflows/release-gem.yml +2 -16
- data/ChangeLog.md +13 -0
- data/README.md +205 -6
- data/VERSION +1 -1
- data/ext/reflex/key_event.cpp +3 -3
- data/include/reflex/defs.h +24 -24
- data/reflex.gemspec +3 -3
- data/samples/bats.rb +2 -2
- data/samples/ios/hello/hello/main.cpp +3 -3
- data/samples/ios/hello/hello.xcodeproj/project.pbxproj +868 -588
- data/samples/osx/hello/hello/main.cpp +4 -4
- data/samples/osx/hello/hello.xcodeproj/project.pbxproj +902 -594
- data/src/ios/event.h +25 -1
- data/src/ios/event.mm +95 -12
- data/src/ios/view_controller.mm +133 -1
- data/src/osx/event.mm +1 -1
- metadata +8 -8
data/src/ios/event.h
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
#define __REFLEX_SRC_IOS_EVENT_H__
|
|
5
5
|
|
|
6
6
|
|
|
7
|
-
#import <UIKit/
|
|
7
|
+
#import <UIKit/UIKit.h>
|
|
8
8
|
#include "../event.h"
|
|
9
9
|
|
|
10
10
|
|
|
@@ -12,6 +12,17 @@ namespace Reflex
|
|
|
12
12
|
{
|
|
13
13
|
|
|
14
14
|
|
|
15
|
+
class NativeKeyEvent : public KeyEvent
|
|
16
|
+
{
|
|
17
|
+
|
|
18
|
+
public:
|
|
19
|
+
|
|
20
|
+
NativeKeyEvent (UIPress* press, Action action)
|
|
21
|
+
API_AVAILABLE(ios(13.4));
|
|
22
|
+
|
|
23
|
+
};// NativeKeyEvent
|
|
24
|
+
|
|
25
|
+
|
|
15
26
|
class NativePointerEvent : public PointerEvent
|
|
16
27
|
{
|
|
17
28
|
|
|
@@ -19,9 +30,22 @@ namespace Reflex
|
|
|
19
30
|
|
|
20
31
|
NativePointerEvent (NSSet* touches, UIEvent* event, UIView* view);
|
|
21
32
|
|
|
33
|
+
NativePointerEvent (UIHoverGestureRecognizer* recognizer, UIView* view);
|
|
34
|
+
|
|
22
35
|
};// NativePointerEvent
|
|
23
36
|
|
|
24
37
|
|
|
38
|
+
class NativeWheelEvent : public WheelEvent
|
|
39
|
+
{
|
|
40
|
+
|
|
41
|
+
public:
|
|
42
|
+
|
|
43
|
+
NativeWheelEvent (
|
|
44
|
+
UIPanGestureRecognizer* recognizer, UIView* view, CGPoint position);
|
|
45
|
+
|
|
46
|
+
};// NativeWheelEvent
|
|
47
|
+
|
|
48
|
+
|
|
25
49
|
}// Reflex
|
|
26
50
|
|
|
27
51
|
|
data/src/ios/event.mm
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
#include <assert.h>
|
|
6
|
+
#include <xot/util.h>
|
|
6
7
|
#include "window.h"
|
|
7
8
|
|
|
8
9
|
|
|
@@ -11,7 +12,23 @@ namespace Reflex
|
|
|
11
12
|
|
|
12
13
|
|
|
13
14
|
static uint
|
|
14
|
-
|
|
15
|
+
get_mouse_button_types (UIEvent* event)
|
|
16
|
+
{
|
|
17
|
+
if (!event) return 0;
|
|
18
|
+
|
|
19
|
+
uint ret = 0;
|
|
20
|
+
if (@available(iOS 13.4, *))
|
|
21
|
+
{
|
|
22
|
+
UIEventButtonMask mask = event.buttonMask;
|
|
23
|
+
if (mask & UIEventButtonMaskPrimary) ret |= Pointer::MOUSE_LEFT;
|
|
24
|
+
if (mask & UIEventButtonMaskSecondary) ret |= Pointer::MOUSE_RIGHT;
|
|
25
|
+
if (mask & UIEventButtonMaskForButtonNumber(3)) ret |= Pointer::MOUSE_MIDDLE;
|
|
26
|
+
}
|
|
27
|
+
return ret;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
static uint
|
|
31
|
+
get_type (UITouch* touch, UIEvent* event)
|
|
15
32
|
{
|
|
16
33
|
assert(touch);
|
|
17
34
|
|
|
@@ -22,8 +39,15 @@ namespace Reflex
|
|
|
22
39
|
{
|
|
23
40
|
case UITouchTypeDirect: return Pointer::TOUCH;
|
|
24
41
|
case UITouchTypePencil: return Pointer::PEN;
|
|
25
|
-
default: return Pointer::TYPE_NONE;
|
|
26
42
|
}
|
|
43
|
+
|
|
44
|
+
if (@available(iOS 13.4, *))
|
|
45
|
+
{
|
|
46
|
+
if (type == UITouchTypeIndirectPointer)
|
|
47
|
+
return Pointer::MOUSE | get_mouse_button_types(event);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return Pointer::TYPE_NONE;
|
|
27
51
|
}
|
|
28
52
|
|
|
29
53
|
static Pointer::Action
|
|
@@ -52,14 +76,8 @@ namespace Reflex
|
|
|
52
76
|
}
|
|
53
77
|
|
|
54
78
|
static uint
|
|
55
|
-
|
|
79
|
+
to_modifiers (NSInteger flags)
|
|
56
80
|
{
|
|
57
|
-
if (!event) return 0;
|
|
58
|
-
|
|
59
|
-
NSInteger flags = 0;
|
|
60
|
-
if (@available(iOS 13.4, *))
|
|
61
|
-
flags = event.modifierFlags;
|
|
62
|
-
|
|
63
81
|
return
|
|
64
82
|
(flags & UIKeyModifierAlphaShift) ? MOD_CAPS : 0 |
|
|
65
83
|
(flags & UIKeyModifierShift) ? MOD_SHIFT : 0 |
|
|
@@ -69,6 +87,18 @@ namespace Reflex
|
|
|
69
87
|
(flags & UIKeyModifierNumericPad) ? MOD_NUMPAD : 0;
|
|
70
88
|
}
|
|
71
89
|
|
|
90
|
+
static uint
|
|
91
|
+
get_modifiers (const UIEvent* event)
|
|
92
|
+
{
|
|
93
|
+
if (!event) return 0;
|
|
94
|
+
|
|
95
|
+
NSInteger flags = 0;
|
|
96
|
+
if (@available(iOS 13.4, *))
|
|
97
|
+
flags = event.modifierFlags;
|
|
98
|
+
|
|
99
|
+
return to_modifiers(flags);
|
|
100
|
+
}
|
|
101
|
+
|
|
72
102
|
uint
|
|
73
103
|
KeyEvent_get_modifiers ()
|
|
74
104
|
{
|
|
@@ -76,25 +106,45 @@ namespace Reflex
|
|
|
76
106
|
}
|
|
77
107
|
|
|
78
108
|
|
|
109
|
+
static const char*
|
|
110
|
+
get_chars (UIKey* key) API_AVAILABLE(ios(13.4))
|
|
111
|
+
{
|
|
112
|
+
NSString* s = key.characters;
|
|
113
|
+
if (!s || [s hasPrefix: @"UIKeyInput"])
|
|
114
|
+
return NULL;
|
|
115
|
+
return s.UTF8String;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
NativeKeyEvent::NativeKeyEvent (UIPress* press, Action action)
|
|
119
|
+
: KeyEvent(
|
|
120
|
+
action, get_chars(press.key), (int) press.key.keyCode,
|
|
121
|
+
to_modifiers(press.key.modifierFlags), 0)
|
|
122
|
+
{
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
|
|
79
126
|
NativePointerEvent::NativePointerEvent (
|
|
80
127
|
NSSet* touches, UIEvent* event, UIView* view)
|
|
81
128
|
{
|
|
82
129
|
for (UITouch* touch in touches)
|
|
83
130
|
{
|
|
84
131
|
Pointer::Action action = get_action(touch);
|
|
132
|
+
uint type = get_type(touch, event);
|
|
85
133
|
|
|
86
134
|
Pointer pointer(
|
|
87
135
|
0,
|
|
88
|
-
|
|
136
|
+
type,
|
|
89
137
|
action,
|
|
90
138
|
to_point([touch locationInView: view]),
|
|
91
139
|
get_modifiers(event),
|
|
92
140
|
(uint) touch.tapCount,
|
|
93
141
|
action == Pointer::MOVE,
|
|
94
142
|
touch.timestamp);
|
|
95
|
-
Pointer_set_system_id(&pointer, (Pointer::ID) touch);
|
|
96
143
|
|
|
97
|
-
if (
|
|
144
|
+
if (!(type & Pointer::MOUSE))
|
|
145
|
+
Pointer_set_system_id(&pointer, (Pointer::ID) touch);
|
|
146
|
+
|
|
147
|
+
if (action != Pointer::DOWN)
|
|
98
148
|
{
|
|
99
149
|
Pointer_set_prev_position(
|
|
100
150
|
&pointer, to_point([touch previousLocationInView: view]));
|
|
@@ -105,5 +155,38 @@ namespace Reflex
|
|
|
105
155
|
}
|
|
106
156
|
}
|
|
107
157
|
|
|
158
|
+
NativePointerEvent::NativePointerEvent (
|
|
159
|
+
UIHoverGestureRecognizer* recognizer, UIView* view)
|
|
160
|
+
{
|
|
161
|
+
assert(recognizer && view);
|
|
162
|
+
|
|
163
|
+
Pointer pointer(
|
|
164
|
+
0,
|
|
165
|
+
Pointer::MOUSE,
|
|
166
|
+
Pointer::MOVE,
|
|
167
|
+
to_point([recognizer locationInView: view]),
|
|
168
|
+
get_modifiers(nil),
|
|
169
|
+
0,
|
|
170
|
+
false,
|
|
171
|
+
Xot::time());
|
|
172
|
+
|
|
173
|
+
if (pointer)
|
|
174
|
+
PointerEvent_add_pointer(this, pointer);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
NativeWheelEvent::NativeWheelEvent (
|
|
179
|
+
UIPanGestureRecognizer* recognizer, UIView* view, CGPoint position)
|
|
180
|
+
: WheelEvent(0, 0, 0, 0, 0, 0, get_modifiers(nil))
|
|
181
|
+
{
|
|
182
|
+
assert(recognizer && view);
|
|
183
|
+
|
|
184
|
+
WheelEvent_set_position(this, to_point(position));
|
|
185
|
+
|
|
186
|
+
CGPoint delta = [recognizer translationInView: view];
|
|
187
|
+
this->dposition().x = delta.x;
|
|
188
|
+
this->dposition().y = delta.y;
|
|
189
|
+
}
|
|
190
|
+
|
|
108
191
|
|
|
109
192
|
}// Reflex
|
data/src/ios/view_controller.mm
CHANGED
|
@@ -121,12 +121,14 @@ ReflexViewController_get_show_fun ()
|
|
|
121
121
|
@end
|
|
122
122
|
|
|
123
123
|
|
|
124
|
-
@interface ReflexViewController () <GLKViewDelegate>
|
|
124
|
+
@interface ReflexViewController () <GLKViewDelegate, UIGestureRecognizerDelegate>
|
|
125
125
|
|
|
126
126
|
@property(nonatomic, strong) ReflexView* reflexView;
|
|
127
127
|
|
|
128
128
|
@property(nonatomic, strong) CADisplayLink* displayLink;
|
|
129
129
|
|
|
130
|
+
@property(nonatomic, strong) UIHoverGestureRecognizer* hoverRecognizer;
|
|
131
|
+
|
|
130
132
|
@end
|
|
131
133
|
|
|
132
134
|
|
|
@@ -264,10 +266,36 @@ ReflexViewController_get_show_fun ()
|
|
|
264
266
|
//view.drawableMultisample = GLKViewDrawableMultisample4X;
|
|
265
267
|
|
|
266
268
|
[self.view addSubview: view];
|
|
269
|
+
[self setupMouseRecognizers: view];
|
|
267
270
|
|
|
268
271
|
self.reflexView = view;
|
|
269
272
|
}
|
|
270
273
|
|
|
274
|
+
- (void) setupMouseRecognizers: (UIView*) view
|
|
275
|
+
{
|
|
276
|
+
if (@available(iOS 13.4, *))
|
|
277
|
+
{
|
|
278
|
+
UIHoverGestureRecognizer* hover = [[[UIHoverGestureRecognizer alloc]
|
|
279
|
+
initWithTarget: self action: @selector(hoverChanged:)]
|
|
280
|
+
autorelease];
|
|
281
|
+
hover.delegate = self;
|
|
282
|
+
[view addGestureRecognizer: hover];
|
|
283
|
+
self.hoverRecognizer = hover;
|
|
284
|
+
|
|
285
|
+
UIPanGestureRecognizer* pan = [[[UIPanGestureRecognizer alloc]
|
|
286
|
+
initWithTarget: self action: @selector(scrollChanged:)]
|
|
287
|
+
autorelease];
|
|
288
|
+
pan.allowedScrollTypesMask = UIScrollTypeMaskAll;
|
|
289
|
+
// 0/0 touches means the recognizer only fires from indirect scroll
|
|
290
|
+
// (mouse wheel / trackpad scroll) — touch-based panning is left to
|
|
291
|
+
// the touchesBegan/etc. path so this won't intercept finger pans.
|
|
292
|
+
pan.minimumNumberOfTouches = 0;
|
|
293
|
+
pan.maximumNumberOfTouches = 0;
|
|
294
|
+
pan.delegate = self;
|
|
295
|
+
[view addGestureRecognizer: pan];
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
|
|
271
299
|
- (void) cleanupReflexView
|
|
272
300
|
{
|
|
273
301
|
ReflexView* view = self.reflexView;
|
|
@@ -299,10 +327,14 @@ ReflexViewController_get_show_fun ()
|
|
|
299
327
|
selector: @selector(willResignActive)
|
|
300
328
|
name: UIApplicationWillResignActiveNotification
|
|
301
329
|
object: nil];
|
|
330
|
+
|
|
331
|
+
[self becomeFirstResponder];
|
|
302
332
|
}
|
|
303
333
|
|
|
304
334
|
- (void) viewDidDisappear: (BOOL) animated
|
|
305
335
|
{
|
|
336
|
+
[self resignFirstResponder];
|
|
337
|
+
|
|
306
338
|
[NSNotificationCenter.defaultCenter
|
|
307
339
|
removeObserver: self
|
|
308
340
|
name: UIApplicationDidBecomeActiveNotification
|
|
@@ -334,6 +366,11 @@ ReflexViewController_get_show_fun ()
|
|
|
334
366
|
self.reflexView.frame = self.view.bounds;
|
|
335
367
|
}
|
|
336
368
|
|
|
369
|
+
- (BOOL) canBecomeFirstResponder
|
|
370
|
+
{
|
|
371
|
+
return YES;
|
|
372
|
+
}
|
|
373
|
+
|
|
337
374
|
- (void) startTimer
|
|
338
375
|
{
|
|
339
376
|
[self startTimer: 60];
|
|
@@ -509,4 +546,99 @@ ReflexViewController_get_show_fun ()
|
|
|
509
546
|
Window_call_pointer_event(win, &e);
|
|
510
547
|
}
|
|
511
548
|
|
|
549
|
+
- (void) hoverChanged: (UIHoverGestureRecognizer*) recognizer
|
|
550
|
+
API_AVAILABLE(ios(13.4))
|
|
551
|
+
{
|
|
552
|
+
Reflex::Window* win = self.window;
|
|
553
|
+
if (!win) return;
|
|
554
|
+
|
|
555
|
+
if (touching_count > 0) return;
|
|
556
|
+
|
|
557
|
+
if (
|
|
558
|
+
recognizer.state != UIGestureRecognizerStateBegan &&
|
|
559
|
+
recognizer.state != UIGestureRecognizerStateChanged)
|
|
560
|
+
{
|
|
561
|
+
return;
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
Reflex::NativePointerEvent e(recognizer, self.reflexView);
|
|
565
|
+
if (e.size() > 0)
|
|
566
|
+
Window_call_pointer_event(win, &e);
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
- (void) scrollChanged: (UIPanGestureRecognizer*) recognizer
|
|
570
|
+
API_AVAILABLE(ios(13.4))
|
|
571
|
+
{
|
|
572
|
+
Reflex::Window* win = self.window;
|
|
573
|
+
if (!win) return;
|
|
574
|
+
|
|
575
|
+
if (
|
|
576
|
+
recognizer.state != UIGestureRecognizerStateBegan &&
|
|
577
|
+
recognizer.state != UIGestureRecognizerStateChanged)
|
|
578
|
+
{
|
|
579
|
+
return;
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
// The pan recognizer's locationInView drifts with the synthetic scroll
|
|
583
|
+
// touch, so use the hover recognizer's location — it tracks the actual
|
|
584
|
+
// cursor and exposes the last known position regardless of its state.
|
|
585
|
+
CGPoint pos = [self.hoverRecognizer locationInView: self.reflexView];
|
|
586
|
+
|
|
587
|
+
Reflex::NativeWheelEvent e(recognizer, self.reflexView, pos);
|
|
588
|
+
Window_call_wheel_event(win, &e);
|
|
589
|
+
|
|
590
|
+
// reset translation so subsequent deltas are incremental
|
|
591
|
+
[recognizer setTranslation: CGPointZero inView: self.reflexView];
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
- (BOOL) gestureRecognizer: (UIGestureRecognizer*) recognizer
|
|
595
|
+
shouldRecognizeSimultaneouslyWithGestureRecognizer: (UIGestureRecognizer*) other
|
|
596
|
+
{
|
|
597
|
+
// UIKit only calls this delegate method when at least one of the two
|
|
598
|
+
// recognizers has us set as its delegate, and we only set ourselves as
|
|
599
|
+
// the delegate for our mouse recognizers (hover / indirect scroll). So
|
|
600
|
+
// every call here already involves one of ours, and we want it to run
|
|
601
|
+
// alongside whatever else is on the view (touches, app-added gestures).
|
|
602
|
+
return YES;
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
- (void) pressesBegan: (NSSet<UIPress*>*) presses
|
|
606
|
+
withEvent: (UIPressesEvent*) event
|
|
607
|
+
{
|
|
608
|
+
if (@available(iOS 13.4, *))
|
|
609
|
+
[self handlePresses: presses action: Reflex::KeyEvent::DOWN];
|
|
610
|
+
[super pressesBegan: presses withEvent: event];
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
- (void) pressesEnded: (NSSet<UIPress*>*) presses
|
|
614
|
+
withEvent: (UIPressesEvent*) event
|
|
615
|
+
{
|
|
616
|
+
if (@available(iOS 13.4, *))
|
|
617
|
+
[self handlePresses: presses action: Reflex::KeyEvent::UP];
|
|
618
|
+
[super pressesEnded: presses withEvent: event];
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
- (void) pressesCancelled: (NSSet<UIPress*>*) presses
|
|
622
|
+
withEvent: (UIPressesEvent*) event
|
|
623
|
+
{
|
|
624
|
+
if (@available(iOS 13.4, *))
|
|
625
|
+
[self handlePresses: presses action: Reflex::KeyEvent::UP];
|
|
626
|
+
[super pressesCancelled: presses withEvent: event];
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
- (void) handlePresses: (NSSet<UIPress*>*) presses
|
|
630
|
+
action: (Reflex::KeyEvent::Action) action
|
|
631
|
+
API_AVAILABLE(ios(13.4))
|
|
632
|
+
{
|
|
633
|
+
Reflex::Window* win = self.window;
|
|
634
|
+
if (!win) return;
|
|
635
|
+
|
|
636
|
+
for (UIPress* press in presses)
|
|
637
|
+
{
|
|
638
|
+
if (!press.key) continue;
|
|
639
|
+
Reflex::NativeKeyEvent e(press, action);
|
|
640
|
+
Window_call_key_event(win, &e);
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
|
|
512
644
|
@end// ReflexViewController
|
data/src/osx/event.mm
CHANGED
|
@@ -163,7 +163,7 @@ namespace Reflex
|
|
|
163
163
|
|
|
164
164
|
|
|
165
165
|
NativeWheelEvent::NativeWheelEvent (NSEvent* e, NSView* view)
|
|
166
|
-
: WheelEvent(0, 0, 0, [e deltaX], [e deltaY], [e deltaZ], get_modifiers(e))
|
|
166
|
+
: WheelEvent(0, 0, 0, [e deltaX], -[e deltaY], [e deltaZ], get_modifiers(e))
|
|
167
167
|
{
|
|
168
168
|
WheelEvent_set_position(this, get_pointer_position(e, view));
|
|
169
169
|
}
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: reflexion
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.4.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- xordog
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-05-
|
|
11
|
+
date: 2026-05-16 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: xot
|
|
@@ -16,42 +16,42 @@ dependencies:
|
|
|
16
16
|
requirements:
|
|
17
17
|
- - "~>"
|
|
18
18
|
- !ruby/object:Gem::Version
|
|
19
|
-
version: 0.3.
|
|
19
|
+
version: 0.3.13
|
|
20
20
|
type: :runtime
|
|
21
21
|
prerelease: false
|
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
23
|
requirements:
|
|
24
24
|
- - "~>"
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
|
-
version: 0.3.
|
|
26
|
+
version: 0.3.13
|
|
27
27
|
- !ruby/object:Gem::Dependency
|
|
28
28
|
name: rucy
|
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
|
30
30
|
requirements:
|
|
31
31
|
- - "~>"
|
|
32
32
|
- !ruby/object:Gem::Version
|
|
33
|
-
version: 0.3.
|
|
33
|
+
version: 0.3.13
|
|
34
34
|
type: :runtime
|
|
35
35
|
prerelease: false
|
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
|
37
37
|
requirements:
|
|
38
38
|
- - "~>"
|
|
39
39
|
- !ruby/object:Gem::Version
|
|
40
|
-
version: 0.3.
|
|
40
|
+
version: 0.3.13
|
|
41
41
|
- !ruby/object:Gem::Dependency
|
|
42
42
|
name: rays
|
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
|
44
44
|
requirements:
|
|
45
45
|
- - "~>"
|
|
46
46
|
- !ruby/object:Gem::Version
|
|
47
|
-
version: 0.3.
|
|
47
|
+
version: 0.3.13
|
|
48
48
|
type: :runtime
|
|
49
49
|
prerelease: false
|
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
|
51
51
|
requirements:
|
|
52
52
|
- - "~>"
|
|
53
53
|
- !ruby/object:Gem::Version
|
|
54
|
-
version: 0.3.
|
|
54
|
+
version: 0.3.13
|
|
55
55
|
description: This library helps you to develop interactive graphical user interface.
|
|
56
56
|
email: xordog@gmail.com
|
|
57
57
|
executables: []
|