ruby_motion_query 0.5.8 → 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.
- checksums.yaml +4 -4
- data/README.md +24 -1478
- data/motion/ext.rb +1 -1
- data/motion/ruby_motion_query/actions.rb +68 -4
- data/motion/ruby_motion_query/animations.rb +3 -0
- data/motion/ruby_motion_query/debug.rb +1 -0
- data/motion/ruby_motion_query/device.rb +8 -0
- data/motion/ruby_motion_query/grid.rb +370 -0
- data/motion/ruby_motion_query/image.rb +2 -0
- data/motion/ruby_motion_query/inspector.rb +354 -0
- data/motion/ruby_motion_query/inspector_stylesheet.rb +106 -0
- data/motion/ruby_motion_query/position.rb +39 -20
- data/motion/ruby_motion_query/rect.rb +557 -0
- data/motion/ruby_motion_query/stylers/ui_button_styler.rb +16 -3
- data/motion/ruby_motion_query/stylers/ui_view_styler.rb +71 -43
- data/motion/ruby_motion_query/stylesheet.rb +11 -0
- data/motion/ruby_motion_query/subviews.rb +2 -0
- data/motion/ruby_motion_query/tags.rb +14 -0
- data/motion/ruby_motion_query/utils.rb +8 -5
- data/motion/ruby_motion_query/version.rb +1 -1
- data/templates/view/app/views/name.rb +2 -1
- metadata +8 -4
data/motion/ext.rb
CHANGED
@@ -26,7 +26,7 @@ class UIView
|
|
26
26
|
def rmq_appended
|
27
27
|
end
|
28
28
|
|
29
|
-
# Technically my_view.rmq is the same as rmq(my_view), so it may seem enticing to use
|
29
|
+
# Technically my_view.rmq is the same as rmq(my_view), so it may seem enticing to use,
|
30
30
|
# but the really nice thing about rmq is its consistent API, and doing this
|
31
31
|
# for one view: my_view.rmq and this for two views: rmq(my_view, my_other_view) sucks
|
32
32
|
def rmq(*working_selectors)
|
@@ -11,13 +11,77 @@ module RubyMotionQuery
|
|
11
11
|
self
|
12
12
|
end
|
13
13
|
|
14
|
+
# Get or set the most common data for a particuliar view(s) in a
|
15
|
+
# performant way (more performant than attr)
|
16
|
+
# For example, text for UILabel, image for UIImageView
|
17
|
+
#
|
18
|
+
# @return [RMQ]
|
19
|
+
def data(new_data = nil)
|
20
|
+
if new_data
|
21
|
+
selected.each do |view|
|
22
|
+
case view
|
23
|
+
when UILabel then view.setText new_data # set is faster than =
|
24
|
+
when UIButton then view.setTitle(new_data, forState: UIControlStateNormal)
|
25
|
+
when UIImageView then view.image = new_data
|
26
|
+
#when UITableView then
|
27
|
+
#when UISwitch then
|
28
|
+
#when UIDatePicker then
|
29
|
+
#when UISegmentedControl then
|
30
|
+
#when UIRefreshControl then
|
31
|
+
#when UIPageControl then
|
32
|
+
#when UISlider then
|
33
|
+
#when UIStepper then
|
34
|
+
#when UITabBar then
|
35
|
+
#when UITableViewCell then
|
36
|
+
when UITextView then view.setText new_data
|
37
|
+
when UITextField then view.setText new_data
|
38
|
+
#when UINavigationBar then
|
39
|
+
#when UIScrollView then
|
40
|
+
|
41
|
+
# TODO, finish
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
self
|
46
|
+
else
|
47
|
+
out = selected.map do |view|
|
48
|
+
case view
|
49
|
+
when UILabel then view.text
|
50
|
+
when UIButton then view.titleForState(UIControlStateNormal)
|
51
|
+
when UIImageView then view.image
|
52
|
+
#when UITableView then
|
53
|
+
#when UISwitch then
|
54
|
+
#when UIDatePicker then
|
55
|
+
#when UISegmentedControl then
|
56
|
+
#when UIRefreshControl then
|
57
|
+
#when UIPageControl then
|
58
|
+
#when UISlider then
|
59
|
+
#when UIStepper then
|
60
|
+
#when UITabBar then
|
61
|
+
#when UITableViewCell then
|
62
|
+
when UITextView then view.text
|
63
|
+
when UITextField then view.text
|
64
|
+
#when UINavigationBar then
|
65
|
+
#when UIScrollView then
|
66
|
+
|
67
|
+
# TODO, finish
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
out = out.first if out.length == 1
|
72
|
+
out
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
14
76
|
# @return [RMQ]
|
15
77
|
def send(method, args = nil)
|
16
78
|
selected.each do |view|
|
17
|
-
if
|
18
|
-
|
19
|
-
|
20
|
-
|
79
|
+
if view.respond_to?(method)
|
80
|
+
if args
|
81
|
+
view.__send__ method, args
|
82
|
+
else
|
83
|
+
view.__send__ method
|
84
|
+
end
|
21
85
|
end
|
22
86
|
end
|
23
87
|
self
|
@@ -18,11 +18,14 @@ module RubyMotionQuery
|
|
18
18
|
view_rmq = self_rmq.wrap(view)
|
19
19
|
|
20
20
|
animations_lambda = -> do
|
21
|
+
# TODO, check arity and allow no params
|
21
22
|
animations_callback.call(view_rmq)
|
22
23
|
end
|
23
24
|
|
24
25
|
after_lambda = if after_callback
|
25
26
|
->(did_finish) {
|
27
|
+
# TODO, check arity and allow just view_rmq or no params. Also
|
28
|
+
# this is backwards, should be view_rmq, did_finish
|
26
29
|
after_callback.call(did_finish, view_rmq)
|
27
30
|
}
|
28
31
|
else
|
@@ -28,6 +28,14 @@ module RubyMotionQuery
|
|
28
28
|
@_height ||= Device.screen.bounds.size.height
|
29
29
|
end
|
30
30
|
|
31
|
+
def screen_width
|
32
|
+
portrait? ? screen.bounds.size.width : screen.bounds.size.height
|
33
|
+
end
|
34
|
+
|
35
|
+
def screen_height
|
36
|
+
portrait? ? screen.bounds.size.height : screen.bounds.size.width
|
37
|
+
end
|
38
|
+
|
31
39
|
def ipad?
|
32
40
|
@_ipad = (UIDevice.currentDevice.userInterfaceIdiom == UIUserInterfaceIdiomPad) if @_ipad.nil?
|
33
41
|
@_ipad
|
@@ -0,0 +1,370 @@
|
|
1
|
+
module RubyMotionQuery
|
2
|
+
class App
|
3
|
+
class << self
|
4
|
+
def grid
|
5
|
+
@_app_grid ||= Grid.new(Grid::DEFAULT)
|
6
|
+
end
|
7
|
+
def grid=(value)
|
8
|
+
@_app_grid = value
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class RMQ
|
14
|
+
# Current grid, wether the current controller's or the App's gri
|
15
|
+
def grid
|
16
|
+
if stylesheet && (g = stylesheet.grid)
|
17
|
+
g
|
18
|
+
else
|
19
|
+
App.grid
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# A grid for layout.
|
25
|
+
# There is an app grid at: rmq.app.grid
|
26
|
+
# You can also have a grid per stylesheet. If none exists, the app
|
27
|
+
# grid will be used. rmq.stylesheet.grid (this will return app's if nil).
|
28
|
+
# If you want to create a grid for your stylesheet, you can just dup the app one
|
29
|
+
# like so (inside the stylesheet): self.grid = rmq.app.grid.dup
|
30
|
+
# Then you can mod it: self.grid.num_columns = 6
|
31
|
+
#
|
32
|
+
# @example If you want your view to be from b2 to d3, you can do any of the following:
|
33
|
+
#
|
34
|
+
# # a b c d e
|
35
|
+
# # ....................
|
36
|
+
# # 1 . a1 b1 c1 d1 e1
|
37
|
+
# # .....------------...
|
38
|
+
# # 2 . a2 |b2 c2 d2| e2
|
39
|
+
# # .....| |...
|
40
|
+
# # 3 . a3 |b3 c3 d3| e3
|
41
|
+
# # .....------------...
|
42
|
+
# # 4 . a4 b4 c4 d4 e4
|
43
|
+
# # ....................
|
44
|
+
# # 5 . a5 b5 c5 d5 e5
|
45
|
+
# # ....................
|
46
|
+
#
|
47
|
+
# st.frame = "b2:d3"
|
48
|
+
# st.origin = "b2:d3"
|
49
|
+
# st.frame = {grid: "b2", w: 100, h: 200}
|
50
|
+
# my_view.frame = some_grid['b2:d3']
|
51
|
+
# my_view.origin = some_grid['b2:d3']
|
52
|
+
# rmq.append(UIView).layout('b2:d3')
|
53
|
+
#
|
54
|
+
# @example Create a new grid inside a stylesheet by duping the app's grid
|
55
|
+
# self.grid = rmq.app.grid.dup
|
56
|
+
# # Then change the number of num_columns
|
57
|
+
# self.grid.num_columns = 6
|
58
|
+
#
|
59
|
+
# @example Creating a new grid
|
60
|
+
# Grid.new({
|
61
|
+
# num_columns: 10,
|
62
|
+
# num_rows: 13,
|
63
|
+
# column_gutter: 10,
|
64
|
+
# row_gutter: 10,
|
65
|
+
# content_left_margin: 5,
|
66
|
+
# content_right_margin: 5,
|
67
|
+
# content_top_margin: 70,
|
68
|
+
# content_bottom_margin: 5
|
69
|
+
# })
|
70
|
+
#
|
71
|
+
# @example Align all your buttons left on the c column
|
72
|
+
# rmq(UIButon).layout('c')
|
73
|
+
#
|
74
|
+
# @example Log your grid
|
75
|
+
# rmq.app.grid.log
|
76
|
+
#
|
77
|
+
# # {:num_columns=>10, :num_rows=>13, :column_gutter=>10, :content_left_margin=>5,
|
78
|
+
# # :content_right_margin=>5, :content_top_margin=>5, :content_bottom_margin=>5,
|
79
|
+
# # :row_gutter=>10, :status_bar_bottom=>20, :nav_bar_bottom=>64}
|
80
|
+
#
|
81
|
+
# # a b c d e f g h i j
|
82
|
+
# # 0 . . . . . . . . . .
|
83
|
+
# # 1 . . . . . . . . . .
|
84
|
+
# # 2 . . . . . . . . . .
|
85
|
+
# # 3 . . . . . . . . . .
|
86
|
+
# # 4 . . . . . . . . . .
|
87
|
+
# # 5 . . . . . . . . . .
|
88
|
+
# # 6 . . . . . . . . . .
|
89
|
+
# # 7 . . . . . . . . . .
|
90
|
+
# # 8 . . . . . . . . . .
|
91
|
+
# # 9 . . . . . . . . . .
|
92
|
+
# # 10 . . . . . . . . . .
|
93
|
+
# # 11 . . . . . . . . . .
|
94
|
+
# # 12 . . . . . . . . . .
|
95
|
+
#
|
96
|
+
class Grid
|
97
|
+
attr_reader :num_columns, :column_gutter, :content_left_margin, :content_right_margin,
|
98
|
+
:content_bottom_margin, :content_top_margin, :num_rows, :row_gutter,
|
99
|
+
:status_bar_bottom, :nav_bar_bottom
|
100
|
+
|
101
|
+
MAX_COLUMNS = 26
|
102
|
+
MAX_ROWS = 30
|
103
|
+
STATUS_BAR_BOTTOM = 20
|
104
|
+
NAV_BAR_BOTTOM = 64
|
105
|
+
|
106
|
+
DEFAULT = {
|
107
|
+
num_columns: 10,
|
108
|
+
column_gutter: 10,
|
109
|
+
num_rows: 16,
|
110
|
+
row_gutter: 10,
|
111
|
+
content_left_margin: 10,
|
112
|
+
content_right_margin: 10,
|
113
|
+
content_top_margin: 70,
|
114
|
+
content_bottom_margin: 10
|
115
|
+
}
|
116
|
+
|
117
|
+
def initialize(params)
|
118
|
+
@grid_hash = {}
|
119
|
+
|
120
|
+
self.num_columns = params[:num_columns]
|
121
|
+
self.num_rows = params[:num_rows]
|
122
|
+
|
123
|
+
@column_gutter = params[:column_gutter]
|
124
|
+
@content_left_margin = params[:content_left_margin]
|
125
|
+
@content_right_margin = params[:content_right_margin]
|
126
|
+
@content_top_margin = params[:content_top_margin]
|
127
|
+
@content_bottom_margin = params[:content_bottom_margin]
|
128
|
+
@row_gutter = params[:row_gutter]
|
129
|
+
@status_bar_bottom = params[:status_bar_bottom] || STATUS_BAR_BOTTOM
|
130
|
+
@nav_bar_bottom = params[:nav_bar_bottom] || NAV_BAR_BOTTOM
|
131
|
+
end
|
132
|
+
|
133
|
+
def num_columns=(value)
|
134
|
+
value = MAX_COLUMNS if value > MAX_COLUMNS
|
135
|
+
@num_columns = value
|
136
|
+
clear_cache
|
137
|
+
end
|
138
|
+
def num_rows=(value)
|
139
|
+
value = MAX_ROWS if value > MAX_ROWS
|
140
|
+
@num_rows = value
|
141
|
+
clear_cache
|
142
|
+
end
|
143
|
+
def column_gutter=(value)
|
144
|
+
@column_gutter = value
|
145
|
+
clear_cache
|
146
|
+
end
|
147
|
+
def content_left_margin=(value)
|
148
|
+
@content_left_margin = value
|
149
|
+
clear_cache
|
150
|
+
end
|
151
|
+
def content_right_margin=(value)
|
152
|
+
@content_right_margin = value
|
153
|
+
clear_cache
|
154
|
+
end
|
155
|
+
def content_top_margin=(value)
|
156
|
+
@content_top_margin = value
|
157
|
+
clear_cache
|
158
|
+
end
|
159
|
+
def content_bottom_margin=(value)
|
160
|
+
@content_bottom_margin = value
|
161
|
+
clear_cache
|
162
|
+
end
|
163
|
+
def row_gutter=(value)
|
164
|
+
@row_gutter = value
|
165
|
+
clear_cache
|
166
|
+
end
|
167
|
+
def status_bar_bottom=(value)
|
168
|
+
@status_bar_bottom = value
|
169
|
+
clear_cache
|
170
|
+
end
|
171
|
+
def nav_bar_bottom=(value)
|
172
|
+
@nav_bar_bottom = value
|
173
|
+
clear_cache
|
174
|
+
end
|
175
|
+
|
176
|
+
# @example
|
177
|
+
# my_grid['a1']
|
178
|
+
# my_grid['a']
|
179
|
+
# my_grid['1']
|
180
|
+
# my_grid['a1:f12']
|
181
|
+
# my_grid['a0:a0'] # Entire a0 block
|
182
|
+
# my_grid['a:d'] # Just width
|
183
|
+
# my_grid['1:4'] # Just height
|
184
|
+
# my_grid['a:4'] # Just width, and just height on the other end (interesting eh)
|
185
|
+
#
|
186
|
+
# @return hash with any combination of l:, t:, w:, or :h. Or nil if invalid
|
187
|
+
def [](coord)
|
188
|
+
@grid_hash[coord] ||= begin
|
189
|
+
if coord.is_a?(Array)
|
190
|
+
|
191
|
+
l = column_lefts[coord[0]]
|
192
|
+
t = row_tops[coord[1]]
|
193
|
+
case coord.length
|
194
|
+
when 2
|
195
|
+
RubyMotionQuery::Rect.new([l, t, column_width, row_height])
|
196
|
+
when 4
|
197
|
+
RubyMotionQuery::Rect.new([l, t, coord[2], coord[3]])
|
198
|
+
else
|
199
|
+
nil
|
200
|
+
end
|
201
|
+
|
202
|
+
else
|
203
|
+
return nil unless coord
|
204
|
+
|
205
|
+
# TODO this needs refactoring once the full tests are done
|
206
|
+
coord.gsub!(/\s/, '')
|
207
|
+
is_end_coord = coord.start_with?(':')
|
208
|
+
parts = coord.split(':')
|
209
|
+
parts.reject!{|o| o == ''}
|
210
|
+
|
211
|
+
case parts.length
|
212
|
+
when 0
|
213
|
+
nil
|
214
|
+
when 1
|
215
|
+
lefts = column_lefts
|
216
|
+
tops = row_tops
|
217
|
+
|
218
|
+
p1 = parts.first
|
219
|
+
digits = p1.gsub(/\D/, '')
|
220
|
+
if digits == ''
|
221
|
+
digits = nil
|
222
|
+
else
|
223
|
+
top_i = digits.to_i
|
224
|
+
top_i = (tops.length - 1) if top_i >= tops.length
|
225
|
+
end
|
226
|
+
|
227
|
+
letter = p1.gsub(/\d/, '')
|
228
|
+
if letter == ''
|
229
|
+
letter = nil
|
230
|
+
else
|
231
|
+
letter.downcase!
|
232
|
+
left_i = (letter.ord - 97)
|
233
|
+
left_i = (lefts.length - 1) if left_i >= lefts.length
|
234
|
+
end
|
235
|
+
|
236
|
+
if digits && letter
|
237
|
+
if lefts.length > left_i && tops.length > top_i
|
238
|
+
if is_end_coord
|
239
|
+
{r: lefts[left_i] + column_width, b: tops[top_i] + row_height}
|
240
|
+
else
|
241
|
+
{l: lefts[left_i], t: tops[top_i]}
|
242
|
+
end
|
243
|
+
else
|
244
|
+
nil
|
245
|
+
end
|
246
|
+
elsif digits
|
247
|
+
if is_end_coord
|
248
|
+
{b: tops[top_i] + row_height}
|
249
|
+
else
|
250
|
+
{t: tops[top_i]}
|
251
|
+
end
|
252
|
+
elsif letter
|
253
|
+
if is_end_coord
|
254
|
+
{r: lefts[left_i] + column_width}
|
255
|
+
else
|
256
|
+
{l: lefts[left_i]}
|
257
|
+
end
|
258
|
+
else
|
259
|
+
nil
|
260
|
+
end
|
261
|
+
when 2
|
262
|
+
self[parts.first].merge(self[":#{parts.last}"])
|
263
|
+
end
|
264
|
+
end.freeze
|
265
|
+
end
|
266
|
+
end
|
267
|
+
|
268
|
+
# TODO, do this when orientation changes
|
269
|
+
def clear_cache
|
270
|
+
@grid_hash = {}
|
271
|
+
@_usable_width = nil
|
272
|
+
@_column_width = nil
|
273
|
+
@_usable_height = nil
|
274
|
+
@_row_height = nil
|
275
|
+
end
|
276
|
+
|
277
|
+
def to_h
|
278
|
+
{
|
279
|
+
num_columns: @num_columns,
|
280
|
+
num_rows: @num_rows,
|
281
|
+
column_gutter: @column_gutter,
|
282
|
+
content_left_margin: @content_left_margin,
|
283
|
+
content_right_margin: @content_right_margin,
|
284
|
+
content_top_margin: @content_top_margin,
|
285
|
+
content_bottom_margin: @content_bottom_margin,
|
286
|
+
row_gutter: @row_gutter,
|
287
|
+
status_bar_bottom: @status_bar_bottom,
|
288
|
+
nav_bar_bottom: @nav_bar_bottom
|
289
|
+
}
|
290
|
+
end
|
291
|
+
|
292
|
+
|
293
|
+
def to_s
|
294
|
+
left_m = ""
|
295
|
+
out = left_m.dup
|
296
|
+
out << ' '
|
297
|
+
|
298
|
+
0.upto(@num_columns - 1).each do |c|
|
299
|
+
out << "#{(c+97).chr} "
|
300
|
+
end
|
301
|
+
|
302
|
+
0.upto(@num_rows - 1).each do |r|
|
303
|
+
out << "\n"
|
304
|
+
out << left_m
|
305
|
+
out << r.to_s.rjust(4)
|
306
|
+
|
307
|
+
0.upto(@num_columns - 1).each do |c|
|
308
|
+
out << " ."
|
309
|
+
end
|
310
|
+
end
|
311
|
+
|
312
|
+
out
|
313
|
+
end
|
314
|
+
def log
|
315
|
+
puts self.inspect
|
316
|
+
puts self.to_s
|
317
|
+
end
|
318
|
+
def inspect
|
319
|
+
to_h.inspect
|
320
|
+
end
|
321
|
+
|
322
|
+
def dup
|
323
|
+
Grid.new(self.to_h)
|
324
|
+
end
|
325
|
+
|
326
|
+
def usable_width
|
327
|
+
@_usable_width ||= (RMQ.device.screen_width - (@column_gutter * (@num_columns - 1)) - @content_left_margin - @content_right_margin)
|
328
|
+
end
|
329
|
+
|
330
|
+
def column_width
|
331
|
+
@_column_width ||= usable_width / @num_columns
|
332
|
+
end
|
333
|
+
|
334
|
+
def column_lefts
|
335
|
+
out = []
|
336
|
+
if @num_columns
|
337
|
+
0.upto(@num_columns - 1) do |i|
|
338
|
+
out << (@content_left_margin + (i * @column_gutter) + (i * column_width))
|
339
|
+
end
|
340
|
+
end
|
341
|
+
out
|
342
|
+
end
|
343
|
+
|
344
|
+
def column_rights
|
345
|
+
column_lefts.map{|x| x + column_width}
|
346
|
+
end
|
347
|
+
|
348
|
+
def usable_height
|
349
|
+
@_usable_height ||= (RMQ.device.screen_height - (@row_gutter * (@num_rows - 1)) - @content_top_margin - @content_bottom_margin)
|
350
|
+
end
|
351
|
+
|
352
|
+
def row_height
|
353
|
+
@_row_height ||= usable_height / @num_rows
|
354
|
+
end
|
355
|
+
|
356
|
+
def row_tops
|
357
|
+
out = []
|
358
|
+
if @num_rows
|
359
|
+
0.upto(@num_rows - 1) do |i|
|
360
|
+
out << (@content_top_margin + (i * @row_gutter) + (i * row_height))
|
361
|
+
end
|
362
|
+
end
|
363
|
+
out
|
364
|
+
end
|
365
|
+
def row_bottoms
|
366
|
+
row_tops.map{|y| y + row_height}
|
367
|
+
end
|
368
|
+
|
369
|
+
end
|
370
|
+
end
|
@@ -67,6 +67,8 @@ module RubyMotionQuery
|
|
67
67
|
#
|
68
68
|
# @return [UIImage]
|
69
69
|
def from_view(view, use_content_size = false)
|
70
|
+
#return nil if (view.origin.x == 0 || view.origin.y == 0)
|
71
|
+
|
70
72
|
scale = UIScreen.mainScreen.scale
|
71
73
|
if use_content_size
|
72
74
|
UIGraphicsBeginImageContextWithOptions(view.contentSize, false, scale)
|