Module: Teacup::Layout
- Included in:
- NSView, NSViewController, NSWindow, NSWindowController, UIView, UIViewController
- Defined in:
- lib/teacup/layout.rb
Overview
Teacup::Layout defines a layout and subview function that can be used to declare and configure the layout of views and the view hierarchy in your application.
This module is included into UIView and UIViewController directly so these functions are available in the places you need them.
In order to use layout() in a UIViewController most effectively you will want to define a stylesheet method that returns a stylesheet.
Class Method Summary collapse
Instance Method Summary collapse
-
#auto(layout_view = top_level_view, layout_subviews = {}, &layout_block) ⇒ Object
Calling this method uses Nick Quaranto’s motion-layout gem to provide ASCII art style access to autolayout.
-
#layout(view_or_class, *teacup_settings, &block) ⇒ Object
Alter the layout of a view.
-
#stylesheet ⇒ Object
Returns the stylesheet.
-
#stylesheet=(val) ⇒ Object
Assign a Stylesheet or Stylesheet name (Symbol).
-
#subview(class_or_instance, *args, &block) ⇒ Object
Add a new subview to the view heirarchy.
- #top_level_view ⇒ Object
Class Method Details
.included(base) ⇒ Object
40 41 42 |
# File 'lib/teacup/layout.rb', line 40 def self.included(base) base.extend LayoutClass end |
Instance Method Details
#auto(layout_view = top_level_view, layout_subviews = {}, &layout_block) ⇒ Object
Calling this method uses Nick Quaranto’s motion-layout gem to provide ASCII art style access to autolayout. It assigns all the subviews by stylename, and assigns ‘self.view` as the target view. Beyond that, it’s up to you to implement the layout methods:
auto do
metrics 'margin' => 20
vertical "|-[top]-margin-[bottom]-|"
horizontal "|-margin-[top]-margin-|"
horizontal "|-margin-[bottom]-margin-|"
end
241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 |
# File 'lib/teacup/layout.rb', line 241 def auto(layout_view=top_level_view, layout_subviews={}, &layout_block) raise "gem install 'motion-layout'" unless defined? Motion::Layout styled_subviews = layout_view.teacup_subviews.select { |v| v.stylename } styled_subviews.each do |view| if ! layout_subviews[view.stylename.to_s] layout_subviews[view.stylename.to_s] = view end end Motion::Layout.new do |layout| layout.view layout_view layout.subviews layout_subviews layout.instance_eval(&layout_block) end end |
#layout(view_or_class, *teacup_settings, &block) ⇒ Object
Alter the layout of a view
For example, to alter the width and height of a carousel:
Or to layout the carousel in the default style:
You can also use this method with #subview, for example to add a new image to a carousel:
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 |
# File 'lib/teacup/layout.rb', line 113 def layout(view_or_class, *teacup_settings, &block) view = Teacup.to_instance(view_or_class) # prevents the calling of restyle! until we return to this method should_restyle = Teacup.should_restyle_and_block teacup_style = Style.new teacup_settings.each do |setting| case setting when Symbol, String view.stylename = setting when Hash # override settings, but apply them to teacup_style so that it remains # a Teacup::Style object Teacup::merge_defaults(setting, teacup_style, teacup_style) when Enumerable view.style_classes = setting when nil # skip. this is so that helper methods that accept arguments like # stylename can pass those on to this method without having to # introspect the values (just set the default value to `nil`) # # long story short: tests will fail `nil` is not ignore here else raise "The argument #{setting.inspect} is not supported in Teacup::Layout::layout()" end end if view.is_a? Teacup::View view.style(teacup_style.build(view)) else Teacup.apply_hash view, teacup_style.build(view) end # assign the 'teacup_next_responder', which is queried for a stylesheet if # one is not explicitly assigned to the view. If the view already has a # teacup_next_responder assigned, it's because another object is already # responsible for managing the view's stylesheet. if view.teacup_next_responder.nil? && view.is_a?(Layout) view.teacup_next_responder = self end if block_given? superview_chain << view begin # yield will not work if this is defined in the context of the # UIViewController `layout` class method. yield view rescue NoMethodError => e NSLog("Exception executing layout(#{view.inspect}) in #{self.inspect} (stylesheet=#{stylesheet})") raise e end superview_chain.pop end if should_restyle Teacup.should_restyle! view.restyle! end view end |
#stylesheet ⇒ Object
Returns the stylesheet. If the stylesheet was assigned by name, the stylesheet object with this name is returned.
65 66 67 68 69 70 71 |
# File 'lib/teacup/layout.rb', line 65 def stylesheet if @stylesheet.is_a? Symbol @stylesheet = Teacup::Stylesheet[@stylesheet] end return @stylesheet || self.class.stylesheet end |
#stylesheet=(val) ⇒ Object
Assign a Stylesheet or Stylesheet name (Symbol)
57 58 59 |
# File 'lib/teacup/layout.rb', line 57 def stylesheet= val @stylesheet = val end |
#subview(class_or_instance, *args, &block) ⇒ Object
Add a new subview to the view heirarchy.
By default the subview will be added at the top level of the view heirarchy, though if this function is executed within a block passed to #layout or #subview, then this view will be added as a subview of the instance being layed out by the block.
This is particularly useful when coupled with the UIViewController.heirarchy function that allows you to declare your view heirarchy.
For example, to specify that a controller should contain some labels:
If you need to add a new image at runtime, you can also do that:
216 217 218 219 220 221 222 223 224 |
# File 'lib/teacup/layout.rb', line 216 def subview(class_or_instance, *args, &block) instance = Teacup.to_instance(class_or_instance) (superview_chain.last || top_level_view).addSubview(instance) layout(instance, *args, &block) instance end |
#top_level_view ⇒ Object
258 259 260 |
# File 'lib/teacup/layout.rb', line 258 def top_level_view raise "No default view has been defined for #{self.class}. Implement `top_level_view`." end |