Permalink
Browse files

Implement a first-attempt proposal for Teacup::Layout

  • Loading branch information...
1 parent 9c07e51 commit a38649d9fdc1f68c302ba262a18e2c7e28b70041 @ConradIrwin committed May 18, 2012
View
66 app/controllers/commune_view_controller.rb
@@ -1,20 +1,54 @@
class CommuneViewController < UIViewController
- include DomNomery
- DOM = {
- commune_view: self,
- how_much: UILabel,
- what_for: UILabel,
- who_paid: UILabel,
- who_participated: UILabel,
- amount: UITextField,
- event: UITextField,
- commune_it: UIButton,
- paid: PersonList::SelectOne,
- participated: PersonList::SelectMany
- }
+ layout :commune_view do
+ subview :how_much
+ subview :what_for
+ subview :who_paid
+ subview :who_participated
+ subview :amount
+ subview :event
+ subview :commune_it
+ subview :paid
+ subview :participated
+ subview :shiny_thing do
+ subview :shadow_view, {
+ top: 100,
+ width: 100,
+ height: 100,
+ left: 550,
+ backgroundColor: UIColor.blackColor
+ } do
+ subview :rounded_view, {
+ cornerRadius: 40,
+ top: 10,
+ left: 10,
+ width: 80,
+ height: 80,
+ backgroundColor: UIColor.blueColor
+ }
+ end
+ end
+ end
+
+ #TODO extend the style-sheet API to make this nicer. override `+`?
+ def style_sheet
+ super_sheet = self.class.style_sheet
+ Teacup::StyleSheet.new(:Temp) do
+ if UIDevice.currentDevice.orientation == UIDeviceOrientationLandscapeLeft ||
+ UIDevice.currentDevice.orientation == UIDeviceOrientationLandscapeRight
+ include Teacup::StyleSheet::IPad
+ else
+ include Teacup::StyleSheet::IPadVertical
+ end
+ include super_sheet
+ end
+ end
- def domDidNom
+ def willAnimateRotationToInterfaceOrientation(io, duration: duration)
+ layout.style_sheet = style_sheet
+ end
+
+ def layoutDidLoad
amount.delegate = self
event.delegate = self
commune_it.addTarget(self, action: :click, forControlEvents:UIControlEventTouchUpInside)
@@ -54,10 +88,6 @@ def shouldAutorotateToInterfaceOrientation(io)
true
end
- def willAnimateRotationToInterfaceOrientation(io, duration: duration)
- Teacup.update(view)
- end
-
def alert(msg)
alert = UIAlertView.new
alert.title = "Commune!"
View
2 core_extensions/ui_view.rb
@@ -8,5 +8,5 @@ def findAndResignFirstResponder
end
end
- attr_accessor :className
+ attr_accessor :style_name
end
View
45 core_extensions/ui_view_controller.rb
@@ -0,0 +1,45 @@
+class UIViewController
+
+ class << self
+ attr_accessor :style_sheet
+ attr_accessor :style_name
+ attr_accessor :layout_definition
+
+ def layout(name, properties={})
+ self.style_name = name
+ self.style_sheet = Teacup::StyleSheet.new(self.name) do
+ style(name, properties)
+ end
+ self.layout_definition = {name => {}}
+ @current_layout = layout_definition[name]
+ yield if block_given?
+ $stderr.puts self.layout_definition.inspect
+ ensure
+ @current_layout = nil
+ end
+
+ def subview(name, properties={})
+ @previous_layout = @current_layout
+ @current_layout = @previous_layout[name] = {}
+ self.style_sheet.style(name, properties)
+ yield if block_given?
+ ensure
+ @current_layout = @previous_layout
+ end
+ end
+
+ attr_accessor :layout
+
+ def method_missing(name, *args, &block)
+ layout && layout.elements[name.to_sym] || super
+ end
+
+ def viewDidLoad
+ self.layout = Teacup::Layout.new(view, style_sheet, self.class.layout_definition)
+
+ layoutDidLoad
+ true
+ end
+
+ def layoutDidLoad; end
+end
View
4 lib/teacup.rb
@@ -28,8 +28,8 @@ def apply_properties(properties, instance)
instance.setTitle(value, forState: UIControlStateNormal)
elsif instance.respond_to?(:"#{key}=")
instance.send(:"#{key}=", value)
- else
- $stderr.puts "Teacup WARN: Can't apply #{key} to #{instance.inspect}"
+ else
+ $stderr.puts "Teacup WARN: Can't apply #{key} to #{instance.inspect}"
end
end
end
View
97 lib/teacup/layout.rb
@@ -0,0 +1,97 @@
+module Teacup
+ class Layout
+ attr_reader :view, :style_sheet
+
+ def initialize(view, style_sheet, layout_definition={})
+ @view = view
+ @style_sheet = style_sheet
+
+ view.style_name = layout_definition.keys.first
+ elements[layout_definition.keys.first] = view
+ update(view)
+
+ recursively_create_subviews(view, layout_definition.values.first)
+ end
+
+ def style_sheet=(style_sheet)
+ @style_sheet = style_sheet
+ update(view)
+ end
+
+ def elements
+ @elements ||= {}
+ end
+
+ def recursively_create_subviews(view, dict)
+ dict.each do |name, subdict|
+ subview = elements[name] = self.new(name)
+ view.addSubview(subview)
+ recursively_create_subviews(subview, subdict)
+ end
+ end
+
+ def add(name, properties={})
+ subview = new(name, properties)
+ view.addSubview(subview)
+ subview
+ end
+
+ def new(name, properties={})
+ properties = style_sheet.query(name).merge(properties)
+
+ instance = if Proc === properties[:class]
+ properties[:class].call
+ else
+ (properties[:class] || UIView).new
+ end
+
+ instance.style_name = name
+ update(instance, properties)
+ instance
+ end
+
+ def update(view, properties=style_sheet.query(view.style_name))
+ apply_properties(properties, view)
+ view.subviews.each(&method(:update))
+ view
+ end
+
+ protected
+ def apply_properties(properties, instance)
+ clean_properties! properties
+
+ properties.each do |key, value|
+ if key == :title && UIButton === instance
+ instance.setTitle(value, forState: UIControlStateNormal)
+ elsif instance.respond_to?(:"#{key}=")
+ instance.send(:"#{key}=", value)
+ elsif instance.layer.respond_to?(:"#{key}=")
+ instance.layer.send(:"#{key}=", value)
+ else
+ $stderr.puts "Teacup WARN: Can't apply #{key} to #{instance.inspect}"
+ end
+ end
+
+ #OUCH! Figure out why this is needed
+ setCornerRadius(1.0) if rand > 1
+
+ end
+
+ def clean_properties!(properties)
+ return unless [:frame, :left, :top, :width, :height].any?(&properties.method(:key?))
+
+ frame = properties.delete(:frame) || [[0,0],[0,0]]
+
+ frame[0][0] = properties.delete(:left) || frame[0][0]
+ frame[0][1] = properties.delete(:top) || frame[0][1]
+ frame[1][0] = properties.delete(:width) || frame[1][0]
+ frame[1][1] = properties.delete(:height) || frame[1][1]
+
+ properties[:frame] = frame
+ end
+
+ def create(layout_definition)
+
+ end
+ end
+end

0 comments on commit a38649d

Please sign in to comment.