motion-xray 1.0.4

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 (56) hide show
  1. data/.gitignore +21 -0
  2. data/Gemfile +3 -0
  3. data/Gemfile.lock +28 -0
  4. data/README.md +426 -0
  5. data/Rakefile +11 -0
  6. data/app/app_delegate.rb +44 -0
  7. data/lib/motion-xray.rb +37 -0
  8. data/lib/motion-xray/plugins/accessibility_plugin.rb +129 -0
  9. data/lib/motion-xray/plugins/log_plugin.rb +301 -0
  10. data/lib/motion-xray/plugins/save_ui_plugin.rb +142 -0
  11. data/lib/motion-xray/plugins/ui_plugin.rb +41 -0
  12. data/lib/motion-xray/version.rb +5 -0
  13. data/lib/motion-xray/views/xray_color_swatch.rb +234 -0
  14. data/lib/motion-xray/views/xray_dpad.rb +142 -0
  15. data/lib/motion-xray/views/xray_gradient_view.rb +23 -0
  16. data/lib/motion-xray/views/xray_headers.rb +101 -0
  17. data/lib/motion-xray/views/xray_lock_button.rb +50 -0
  18. data/lib/motion-xray/views/xray_scroll_view.rb +12 -0
  19. data/lib/motion-xray/views/xray_toolbar.rb +173 -0
  20. data/lib/motion-xray/views/xray_window.rb +13 -0
  21. data/lib/motion-xray/xray.rb +56 -0
  22. data/lib/motion-xray/xray_constants.rb +5 -0
  23. data/lib/motion-xray/xray_dummy.rb +8 -0
  24. data/lib/motion-xray/xray_editors.rb +62 -0
  25. data/lib/motion-xray/xray_ext.rb +125 -0
  26. data/lib/motion-xray/xray_plugin.rb +40 -0
  27. data/lib/motion-xray/xray_typewriter.rb +217 -0
  28. data/lib/motion-xray/xray_ui.rb +723 -0
  29. data/lib/motion-xray/z_editors/xray_boolean_editor.rb +24 -0
  30. data/lib/motion-xray/z_editors/xray_color_editor.rb +119 -0
  31. data/lib/motion-xray/z_editors/xray_frame_editor.rb +108 -0
  32. data/lib/motion-xray/z_editors/xray_image_editor.rb +78 -0
  33. data/lib/motion-xray/z_editors/xray_text_editor.rb +94 -0
  34. data/lib/resources/xray_button_bg@2x.png +0 -0
  35. data/lib/resources/xray_choose_button@2x.png +0 -0
  36. data/lib/resources/xray_clear_button@2x.png +0 -0
  37. data/lib/resources/xray_detail_button@2x.png +0 -0
  38. data/lib/resources/xray_dpad@2x.png +0 -0
  39. data/lib/resources/xray_dpad_center@2x.png +0 -0
  40. data/lib/resources/xray_dpad_down@2x.png +0 -0
  41. data/lib/resources/xray_dpad_left@2x.png +0 -0
  42. data/lib/resources/xray_dpad_right@2x.png +0 -0
  43. data/lib/resources/xray_dpad_up@2x.png +0 -0
  44. data/lib/resources/xray_drawer_left@2x.png +0 -0
  45. data/lib/resources/xray_drawer_right@2x.png +0 -0
  46. data/lib/resources/xray_edit_button@2x.png +0 -0
  47. data/lib/resources/xray_email_button@2x.png +0 -0
  48. data/lib/resources/xray_lock_button_horizontal@2x.png +0 -0
  49. data/lib/resources/xray_lock_button_locked@2x.png +0 -0
  50. data/lib/resources/xray_lock_button_unlocked@2x.png +0 -0
  51. data/lib/resources/xray_lock_button_vertical@2x.png +0 -0
  52. data/motion-xray.gemspec +40 -0
  53. data/resources/Default-568h@2x.png +0 -0
  54. data/spec/xray_view_spec.rb +43 -0
  55. data/vendor/Podfile.lock +11 -0
  56. metadata +177 -0
@@ -0,0 +1,23 @@
1
+ module Motion ; module Xray
2
+
3
+ class XrayGradientView < UIView
4
+ attr_accessor :start_color
5
+ attr_accessor :final_color
6
+
7
+ def drawRect(rect)
8
+ context = UIGraphicsGetCurrentContext()
9
+ color_space = CGColorSpaceCreateDeviceRGB()
10
+ cgcolors = [
11
+ (start_color || :white).uicolor.CGColor,
12
+ (final_color || :lightgray).uicolor.CGColor,
13
+ ]
14
+
15
+ points = [0, 1]
16
+
17
+ gradient = CGGradientCreateWithColors(color_space, cgcolors, points.to_pointer(:float))
18
+ CGContextDrawLinearGradient(context, gradient, self.bounds.top_left, self.bounds.bottom_left, 0)
19
+ end
20
+
21
+ end
22
+
23
+ end end
@@ -0,0 +1,101 @@
1
+ module Motion ; module Xray
2
+
3
+ class XrayHeaderBackground < UIView
4
+ attr_accessor :label
5
+
6
+ def initWithFrame(frame)
7
+ super.tap do
8
+ self.layer.borderWidth = 1
9
+ self.layer.borderColor = :xray_dashboard_label_border.uicolor.CGColor
10
+ self.layer.backgroundColor = :xray_dashboard_label_bg.uicolor.CGColor
11
+ end
12
+ end
13
+
14
+ def label=(lbl)
15
+ if @label
16
+ @label.removeFromSuperview
17
+ end
18
+ @label = lbl
19
+ self << @label
20
+ end
21
+
22
+ def text=(str)
23
+ label.text = str
24
+ end
25
+
26
+ end
27
+
28
+ class XrayHeaderLabel < UILabel
29
+
30
+ def initWithFrame(frame)
31
+ super.tap do
32
+ self.font = 'Futura'.uifont(12)
33
+ self.textAlignment = :left.uitextalignment
34
+ self.textColor = :xray_dashboard_label_text.uicolor
35
+ self.backgroundColor = :clear.uicolor
36
+ end
37
+ end
38
+
39
+ end
40
+
41
+ class XraySectionHeader < UIControl
42
+ attr_accessor :text
43
+ attr :tracking_view
44
+
45
+ def initWithFrame(frame)
46
+ super.tap do
47
+ @exposed = true
48
+ @pressed = false
49
+ @tracking_view = XrayTypewriterView.alloc.initWithFrame([[0, 0], [self.frame.size.width, 0]])
50
+ end
51
+ end
52
+
53
+ def exposed?
54
+ @exposed
55
+ end
56
+
57
+ def exposed=(value)
58
+ @exposed = !! value
59
+ end
60
+
61
+ def drawRect(rect)
62
+ context = UIGraphicsGetCurrentContext()
63
+ color_space = CGColorSpaceCreateDeviceRGB()
64
+ if @pressed
65
+ else
66
+ cgcolors = [
67
+ :white.uicolor.CGColor,
68
+ :lightgray.uicolor.CGColor,
69
+ ]
70
+ end
71
+
72
+ points = [0, 1]
73
+
74
+ gradient = CGGradientCreateWithColors(color_space, cgcolors, points.to_pointer(:float))
75
+ CGContextDrawLinearGradient(context, gradient, self.bounds.top_left, self.bounds.bottom_left, 0)
76
+
77
+ text.drawAtPoint([17, 3], withFont: :bold.uifont(11))
78
+
79
+ CGContextSaveGState(context)
80
+ triangle_bounds = CGRect.new([0, 0], [20, 20]).shrink(6)
81
+ :clear.uicolor.setStroke
82
+ :lightgray.uicolor.setFill
83
+
84
+ if false
85
+ if @exposed
86
+ CGContextMoveToPoint(context, triangle_bounds.top_right(true).x, triangle_bounds.top_right(true).y)
87
+ CGContextAddLineToPoint(context, triangle_bounds.bottom_center(true).x, triangle_bounds.bottom_center(true).y)
88
+ CGContextAddLineToPoint(context, triangle_bounds.top_left(true).x, triangle_bounds.top_left(true).y)
89
+ else
90
+ CGContextMoveToPoint(context, triangle_bounds.top_left(true).x, triangle_bounds.top_left(true).y)
91
+ CGContextAddLineToPoint(context, triangle_bounds.center_right(true).x, triangle_bounds.center_right(true).y)
92
+ CGContextAddLineToPoint(context, triangle_bounds.bottom_left(true).x, triangle_bounds.bottom_left(true).y)
93
+ end
94
+ end
95
+ CGContextDrawPath(context, KCGPathFillStroke)
96
+ CGContextRestoreGState(context)
97
+ end
98
+
99
+ end
100
+
101
+ end end
@@ -0,0 +1,50 @@
1
+ module Motion ; module Xray
2
+
3
+ class XrayLockButton < UIButton
4
+ States = 4
5
+ LockedState = 0
6
+ UnlockedState = 1
7
+ LockedVerticalState = 2
8
+ LockedHorizontalState = 3
9
+ InitialState = LockedState
10
+
11
+ UnlockedImage = 'xray_lock_button_unlocked'.uiimage
12
+ LockedHorizontalImage = 'xray_lock_button_horizontal'.uiimage
13
+ LockedVerticalImage = 'xray_lock_button_vertical'.uiimage
14
+ LockedImage = 'xray_lock_button_locked'.uiimage
15
+
16
+ attr :lock_state
17
+
18
+ def init
19
+ frame = [[0, 0], UnlockedImage.size]
20
+ initWithFrame(frame)
21
+ end
22
+
23
+ def initWithFrame(frame)
24
+ super.tap do
25
+ @lock_state = InitialState
26
+ update_state
27
+ self.on :touch do
28
+ @lock_state += 1
29
+ @lock_state = @lock_state % States
30
+ update_state
31
+ end
32
+ end
33
+ end
34
+
35
+ def update_state
36
+ case @lock_state
37
+ when UnlockedState
38
+ self.setImage(UnlockedImage, forState: :normal.uicontrolstate)
39
+ when LockedVerticalState
40
+ self.setImage(LockedVerticalImage, forState: :normal.uicontrolstate)
41
+ when LockedHorizontalState
42
+ self.setImage(LockedHorizontalImage, forState: :normal.uicontrolstate)
43
+ when LockedState
44
+ self.setImage(LockedImage, forState: :normal.uicontrolstate)
45
+ end
46
+ end
47
+
48
+ end
49
+
50
+ end end
@@ -0,0 +1,12 @@
1
+ module Motion ; module Xray
2
+
3
+ class XrayScrollView < UIScrollView
4
+
5
+ def touchesShouldCancelInContentView(view)
6
+ return false if view.is_a?(XrayDpad)
7
+ return super
8
+ end
9
+
10
+ end
11
+
12
+ end end
@@ -0,0 +1,173 @@
1
+ module Motion ; module Xray
2
+
3
+ # Toolbar is a terrible name. It's more of a "tab bar", but that name was
4
+ # taken. Plus, I dunno, maybe I'll add other tools to it!
5
+ class XrayToolbar < UIView
6
+ attr_accessor :canvas
7
+ attr_accessor :selected
8
+ attr_accessor :delegate
9
+
10
+ def initWithFrame(frame)
11
+ super.tap do
12
+ self.backgroundColor = :white.uicolor
13
+ self.layer.borderColor = :black.uicolor.cgcolor
14
+ self.layer.borderWidth = 1
15
+ grad_layer = CAGradientLayer.layer
16
+ grad_layer.frame = self.layer.bounds
17
+ grad_layer.colors = [0x526691.uicolor.cgcolor, 0x27386e.uicolor.cgcolor]
18
+ self.layer << grad_layer
19
+
20
+ @scroll_view = UIScrollView.alloc.initWithFrame(bounds)
21
+ self << @scroll_view
22
+ @selected_view = XraySelectedToolbarItem.new
23
+ @scroll_view << @selected_view
24
+
25
+ @index = nil
26
+ @toolbar_items = []
27
+ @views = []
28
+ @item_x = margin
29
+
30
+ recognizer = UITapGestureRecognizer.alloc.initWithTarget(self, action:'tapped:')
31
+ recognizer.numberOfTapsRequired = 1
32
+ recognizer.numberOfTouchesRequired = 1
33
+ self.addGestureRecognizer(recognizer)
34
+ end
35
+ end
36
+
37
+ def tapped(event)
38
+ touched_x = event.locationInView(self).x + @scroll_view.contentOffset.x
39
+ touched_index = nil
40
+ @toolbar_items.each_with_index do |item, index|
41
+ if touched_x < item.frame.max_x
42
+ touched_index = index
43
+ break
44
+ end
45
+ end
46
+ select(touched_index) if touched_index
47
+ end
48
+
49
+ def margin
50
+ 10
51
+ end
52
+
53
+ def add(name, plugin_view)
54
+ toolbar_item = XrayToolbarItem.alloc.initWithText(name)
55
+ toolbar_item.frame = toolbar_item.frame.right(@item_x).down(5)
56
+ @item_x += toolbar_item.frame.width
57
+ @item_x += margin
58
+ @scroll_view << toolbar_item
59
+ @scroll_view.contentSize = [@item_x, self.bounds.height]
60
+ @toolbar_items << toolbar_item
61
+ @views << plugin_view
62
+
63
+ unless @index
64
+ select(0)
65
+ end
66
+ end
67
+
68
+ def select(index)
69
+ toolbar_item = @toolbar_items[index]
70
+ will_hide
71
+ @index = index
72
+ self.canvas.subviews.each &:removeFromSuperview
73
+ UIView.animate {
74
+ @selected_view.item = toolbar_item
75
+ }
76
+ will_show
77
+
78
+ plugin_view = @views[@index]
79
+ self.canvas << plugin_view
80
+
81
+ if self.canvas.is_a?(UIScrollView)
82
+ self.canvas.contentSize = plugin_view.frame.size
83
+ self.canvas.setContentOffset([0, 0], animated: false)
84
+ end
85
+ end
86
+
87
+ def show
88
+ will_show
89
+ end
90
+
91
+ def will_hide
92
+ end
93
+
94
+ def will_show
95
+ end
96
+
97
+ end
98
+
99
+ class PluginToolbar < XrayToolbar
100
+
101
+ def initWithFrame(frame)
102
+ super.tap do
103
+ @plugin_items = []
104
+ @selected = nil
105
+ end
106
+ end
107
+
108
+ def add(plugin)
109
+ name = plugin.xray_name
110
+ plugin_view = plugin.get_plugin_view(@canvas)
111
+ @plugin_items << plugin
112
+ super(name, plugin_view)
113
+ end
114
+
115
+ def will_hide
116
+ @selected.hide if @selected
117
+ end
118
+
119
+ def will_show
120
+ @selected = @plugin_items[@index]
121
+ @selected.show if @selected
122
+ end
123
+
124
+ end
125
+
126
+ class XraySelectedToolbarItem < UIView
127
+ attr :item
128
+
129
+ def initWithFrame(frame)
130
+ super.tap do
131
+ self.backgroundColor = :clear.uicolor
132
+ @item = nil
133
+ end
134
+ end
135
+
136
+ def item=(item)
137
+ @item = item
138
+ f = item.frame
139
+ f.origin.x -= corner_radius
140
+ f.origin.y -= corner_radius / 2
141
+ f.size = item.size
142
+ f.size.width += corner_radius * 2
143
+ f.size.height += corner_radius
144
+ self.frame = f
145
+ setNeedsDisplay
146
+ end
147
+
148
+ def corner_radius
149
+ 5
150
+ end
151
+
152
+ def drawRect(rect)
153
+ :white.uicolor.setFill
154
+ UIBezierPath.bezierPathWithRoundedRect(bounds, cornerRadius:corner_radius).fill
155
+ end
156
+
157
+ end
158
+
159
+ class XrayToolbarItem < UILabel
160
+ attr :name
161
+
162
+ def initWithText(text)
163
+ initWithFrame(CGRect.empty).tap do
164
+ self.backgroundColor = :clear.uicolor
165
+ self.font = :label.uifont(12)
166
+ self.text = text
167
+ sizeToFit
168
+ end
169
+ end
170
+
171
+ end
172
+
173
+ end end
@@ -0,0 +1,13 @@
1
+ module Motion ; module Xray
2
+
3
+ class XrayWindow < UIWindow
4
+
5
+ def motionEnded(motion, withEvent:event)
6
+ if event.type == UIEventSubtypeMotionShake
7
+ Xray.toggle
8
+ end
9
+ end
10
+
11
+ end
12
+
13
+ end end
@@ -0,0 +1,56 @@
1
+ module Motion ; module Xray
2
+
3
+ module_function
4
+ def ui
5
+ unless @xray_ui
6
+ @xray_ui ||= UI.new
7
+
8
+ # register default plugins if this is the first time xray_ui has been
9
+ # accessed. AKA "startup". Default plugins get pushed to the front,
10
+ # so they will appear in reverse order than they are here.
11
+ [LogPlugin, AccessibilityPlugin, UIPlugin].each do |plugin_class|
12
+ unless Xray.plugins.any? { |plugin| plugin_class === plugin }
13
+ Xray.plugins.unshift(plugin_class.new)
14
+ end
15
+ end
16
+ end
17
+ return @xray_ui
18
+ end
19
+
20
+ def controller
21
+ @xray_controller ||= XrayViewController.new
22
+ end
23
+
24
+ def toggle
25
+ Xray.ui.toggle
26
+ end
27
+
28
+ def fire_up
29
+ Xray.ui.fire_up
30
+ end
31
+
32
+ def cool_down
33
+ Xray.ui.cool_down
34
+ end
35
+
36
+ def window
37
+ UIApplication.sharedApplication.keyWindow || UIApplication.sharedApplication.windows[0]
38
+ end
39
+
40
+ def app_shared
41
+ UIApplication.sharedApplication
42
+ end
43
+
44
+ def app_bounds
45
+ UIScreen.mainScreen.bounds
46
+ end
47
+
48
+ def plugins
49
+ @plugins ||= []
50
+ end
51
+
52
+ def register(plugin)
53
+ Xray.plugins << plugin
54
+ end
55
+
56
+ end end
@@ -0,0 +1,5 @@
1
+ Symbol.css_colors[:xray_dashboard_label_text] = :darkblue.uicolor
2
+ Symbol.css_colors[:xray_dashboard_label_border] = :lightblue.uicolor
3
+ Symbol.css_colors[:xray_dashboard_label_bg] = :ghostwhite.uicolor
4
+
5
+ XrayTargetDidChangeNotification = 'Motion::Xray::TargetDidChangeNotification'
@@ -0,0 +1,8 @@
1
+ module Motion ; module Xray
2
+ module_function
3
+ def dummy
4
+ view.userInteractionEnabled = true
5
+ view.userInteractionEnabled?
6
+ view.isUserInteractionEnabled
7
+ end
8
+ end end