Files
rmq/motion/ruby_motion_query/stylesheet.rb
2015-03-02 19:05:37 -06:00

281 lines
7.5 KiB
Ruby

module RubyMotionQuery
class RMQ
# @return [RMQ]
def stylesheet=(value)
controller = self.weak_view_controller
unless value.is_a?(RubyMotionQuery::Stylesheet)
value = value.new(controller)
end
@_stylesheet = value
controller.rmq_data.stylesheet = value
self
end
# @return [RubyMotionQuery::Stylesheet]
def stylesheet
@_stylesheet ||= begin
if self.weak_view_controller && (ss = self.weak_view_controller.rmq_data.stylesheet)
ss
elsif (prmq = self.parent_rmq) && prmq.stylesheet
prmq.stylesheet
end
end
end
# @example
# rmq(view).apply_style(:style_name_here)
# rmq(view).apply_style(:style_name_here, :another_style, :yet_another_style)
# rmq(view).apply_styles(:style_name_here, :another_style, :yet_another_style) # Alias
#
# @return [RMQ]
def apply_style(*style_names)
if style_names
selected.each do |selected_view|
style_names.each do |style_name|
apply_style_to_view selected_view, style_name
end
end
end
self
end
alias :apply_styles :apply_style
# Pass a block to apply styles, an inline way of applynig a style
# @example
# rmq(view).style{|st| st.background_color = rmq.color.blue}
# @return [RMQ]
def style
selected.each do |view|
yield(styler_for(view))
end
self
end
# @example
# rmq(view).styles
#
# @return style_names as an array
def styles
out = selected.map do |view|
view.rmq_data.styles
end
out.flatten!.uniq!
out
end
# @example
# foo = rmq(view).has_style?(:style_name_here)
#
# @return true if all selected views has the style
def has_style?(style_name)
selected.each do |view|
return false unless view.rmq_data.has_style?(style_name)
end
true
end
# Reapplies all styles in order. User rmq(view).styles to see the styles applied to a view(s)
# @example
# rmq.all.reapply_styles
# rmq(viewa, viewb, viewc).reapply_styles
#
# @return [RMQ]
def reapply_styles
selected.each do |selected_view|
selected_view.rmq_data.styles.each do |style_name|
apply_style_to_view selected_view, style_name
end
end
self
end
def styler_for(view)
# TODO should have a pool of stylers to reuse, or just assume single threaded and
# memoize this, however if you do that, make sure the dev doesn't retain them in a var
custom_stylers(view) || begin
case view
when UILabel then Stylers::UILabelStyler.new(view)
when UIButton then Stylers::UIButtonStyler.new(view)
when UIActivityIndicatorView then Stylers::UIActivityIndicatorViewStyler.new(view)
when UIImageView then Stylers::UIImageViewStyler.new(view)
when UITableView then Stylers::UITableViewStyler.new(view)
when UISwitch then Stylers::UISwitchStyler.new(view)
when UIDatePicker then Stylers::UIDatePickerStyler.new(view)
when UISegmentedControl then Stylers::UISegmentedControlStyler.new(view)
when UIRefreshControl then Stylers::UIRefreshControlStyler.new(view)
when UIPageControl then Stylers::UIPageControlStyler.new(view)
when UIProgressView then Stylers::UIProgressViewStyler.new(view)
when UISlider then Stylers::UISliderStyler.new(view)
when UIStepper then Stylers::UIStepperStyler.new(view)
when UITabBar then Stylers::UITabBarStyler.new(view)
when UITableViewCell then Stylers::UITableViewCellStyler.new(view)
when UITextView then Stylers::UITextViewStyler.new(view)
when UITextField then Stylers::UITextFieldStyler.new(view)
when UINavigationBar then Stylers::UINavigationBarStyler.new(view)
when UIScrollView then Stylers::UIScrollViewStyler.new(view)
# TODO, all the controls are done, but missing some views, add
else
if view.respond_to?(:rmq_styler)
# If you're creating an RMQ plug-in that is a view you can set your styler by adding this method
view.rmq_styler
else
if view.is_a?(UIControl)
Stylers::UIControlStyler.new(view)
else
Stylers::UIViewStyler.new(view)
end
end
end
end
end
protected
# Override to set your own stylers, or just open up the styler classes
def custom_stylers(view)
end
def apply_style_to_view(view, style_name)
begin
stylesheet.public_send(style_name, styler_for(view))
view.rmq_data.styles << style_name unless view.rmq_data.has_style?(style_name)
view.rmq_style_applied
rescue NoMethodError => e
if e.message =~ /.*#{style_name.to_s}.*/
puts "\n[RMQ ERROR] style_name :#{style_name} doesn't exist for a #{view.class.name}. Add 'def #{style_name}(st)' to #{stylesheet.class.name} class\n\n"
else
raise e
end
end
end
end
class Stylesheet
attr_reader :controller
def initialize(controller)
@controller = RubyMotionQuery::RMQ.weak_ref(controller)
unless Stylesheet.application_was_setup
Stylesheet.application_was_setup = true
application_setup
end
setup
end
def application_setup
# Override to do your overall setup for your applications. This
# is where you want to add your custom fonts and colors
# This only gets called once
end
def setup
# Override if you need to do setup in your specific stylesheet
end
class << self
attr_accessor :application_was_setup
end
def grid
@grid || RMQ.app.grid
end
def grid=(value)
@grid = value
end
# Convenience methods -------------------
def rmq(*working_selectors)
if @controller.nil?
if (app = RubyMotionQuery::RMQ.app) && (window = app.window) && (cvc = app.current_view_controller)
cvc.rmq(working_selectors)
else
RubyMotionQuery::RMQ.create_with_array_and_selectors([], working_selectors, self)
end
else
RubyMotionQuery::RMQ.create_with_selectors(working_selectors, @controller)
end
end
def device
RMQ.device
end
def landscape?
device.landscape?
end
def portrait?
device.portrait?
end
def iphone?
device.iphone?
end
def ipad?
device.ipad?
end
def four_inch?
device.four_inch?
end
def retina?
device.retina?
end
def window
RMQ.app.window
end
def device_width
device.width
end
def device_height
device.height
end
def screen_width
device.screen_width
end
def screen_height
device.screen_height
end
def content_width
content_size.width
end
def content_height
content_size.height
end
# Content size of the controller's rootview, if it is a
# UIScrollView, UICollectionView, UITableView, etc
def content_size
if @controller.view.respond_to?(:contentSize)
@controller.view.contentSize
else
CGSizeZero
end
end
def image
RMQ.image
end
def color(*params)
RMQ.color(*params)
end
def font
RMQ.font
end
end
end