Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactoring #7

Merged
merged 11 commits into from Jul 3, 2012
3 changes: 2 additions & 1 deletion .gitignore
Expand Up @@ -7,4 +7,5 @@ resources/*.storyboardc
*.gem
.bundle
Gemfile.lock
pkg/*
pkg/*
.rvmrc
4 changes: 4 additions & 0 deletions Gemfile
@@ -0,0 +1,4 @@
source 'https://rubygems.org'

# Specify your gem's dependencies in motion-settings.gemspec
gemspec
6 changes: 6 additions & 0 deletions app/app_delegate.rb
Expand Up @@ -29,6 +29,12 @@ def application(application, didFinishLaunchingWithOptions:launchOptions)
title: "Switch",
key: :switch,
type: :switch,
}, {
title: "Bio",
key: :bio,
type: :text,
placeholder: "Enter your Bio here...",
rowHeight: 100
}]
}, {
title: "Account Type",
Expand Down
17 changes: 17 additions & 0 deletions examples/KitchenSink/app/app_delegate.rb
Expand Up @@ -43,6 +43,23 @@ def application(application, didFinishLaunchingWithOptions:launchOptions)
placeholder: "required",
type: :string,
secure: true
}, {
title: "Row Height",
key: :row_height,
placeholder: "60px",
type: :string,
rowHeight: 60
}, {
title: "Text",
key: :text,
type: :text,
placeholder: "Enter your text here",
rowHeight: 100
}, {
title: "Check",
key: :check,
type: :check,
value: true
}, {
title: "Remember?",
key: :remember,
Expand Down
2 changes: 1 addition & 1 deletion lib/formotion.rb
Expand Up @@ -2,7 +2,7 @@
require 'bubble-wrap/core'

BW.require File.expand_path('../formotion/**/*.rb', __FILE__) do
['form.rb', 'row.rb', 'section.rb'].each {|file|
['form/form.rb', 'row/row.rb', 'section/section.rb'].each {|file|
file("lib/formotion/#{file}").depends_on 'lib/formotion/base.rb'
}
file("lib/formotion/form_controller.rb").depends_on 'lib/formotion/patch/ui_text_field.rb'
Expand Down
File renamed without changes.
Expand Up @@ -63,25 +63,16 @@ def tableView(tableView, cellForRowAtIndexPath:indexPath)
cell
end

def tableView(tableView, heightForRowAtIndexPath: indexPath)
row = row_for_index_path(indexPath)
row.rowHeight || tableView.rowHeight
end

# UITableViewDelegate Methods
def tableView(tableView, didSelectRowAtIndexPath:indexPath)
tableView.deselectRowAtIndexPath(indexPath, animated:true)
row = row_for_index_path(indexPath)
if row.submit_button?
self.submit
elsif row.checkable?
if row.section.select_one and !row.value
row.section.rows.each {|other_row|
other_row.value = (other_row == row)
Formotion::RowCellBuilder.make_check_cell(other_row, tableView.cellForRowAtIndexPath(other_row.index_path))
}
elsif !row.section.select_one
row.value = !row.value
Formotion::RowCellBuilder.make_check_cell(row, tableView.cellForRowAtIndexPath(row.index_path))
end
elsif row.editable?
row.text_field.becomeFirstResponder
end
row.object.on_select(tableView, self)
end
end
end
9 changes: 9 additions & 0 deletions lib/formotion/patch/object.rb
@@ -0,0 +1,9 @@
class Object
# Creates an alias for :method with the form
# old_#{method}
# Instance evals the block.
def swizzle(method, &block)
self.class.send(:alias_method, "old_#{method.to_s}".to_sym, method)
self.instance_eval &block
end
end
122 changes: 122 additions & 0 deletions lib/formotion/patch/ui_text_view.rb
@@ -0,0 +1,122 @@
# Methods which use blocks for UITextViewDelegate methods.
# EX
# field.should_end? do |text_field|
# if text_field.text != "secret"
# return false
# end
# true
# end
#
# Also includes an on_change method, which calls after the text
# has changed (there is no UITextViewDelegate equivalent.)
# EX
# field.on_change do |text_field|
# p text_field.text
# end

class UITextView
attr_accessor :menu_options_enabled

def canPerformAction(action, withSender:sender)
self.menu_options_enabled
end

# block takes argument textView; should return true/false
def should_begin?(&block)
add_delegate_method do
@delegate.textViewShouldBeginEditing_callback = block
end
end

# block takes argument textView
def on_begin(&block)
add_delegate_method do
@delegate.textViewDidBeginEditing_callback = block
end
end

# block takes argument textView; should return true/false
def should_end?(&block)
add_delegate_method do
@delegate.textViewShouldEndEditing_callback = block
end
end

# block takes argument textView
def on_end(&block)
add_delegate_method do
@delegate.textViewDidBeginEditing_callback = block
end
end

# block takes argument textView
def on_change(&block)
add_delegate_method do
@delegate.textViewDidChange_callback = block
end
end

# block takes argument textView, range [NSRange], and string; should return true/false
def should_change?(&block)
add_delegate_method do
@delegate.shouldChangeCharactersInRange_callback = block
end
end

private
def add_delegate_method
# create strong reference to the delegate
# (.delegate= only creates a weak reference)
@delegate ||= UITextView_Delegate.new
yield
self.delegate = @delegate
end
end

class UITextView_Delegate
[:textViewShouldBeginEditing, :textViewDidBeginEditing,
:textViewShouldEndEditing, :textViewDidEndEditing,
:textViewDidChange, :shouldChangeCharactersInRange].each {|method|
attr_accessor (method.to_s + "_callback").to_sym
}

def textViewShouldBeginEditing(theTextView)
if self.textViewShouldBeginEditing_callback
return self.textViewShouldBeginEditing_callback.call(theTextView)
end
true
end

def textViewDidBeginEditing(theTextView)
if self.textViewDidBeginEditing_callback
return self.textViewDidBeginEditing_callback.call(theTextView)
end
end

def textViewShouldEndEditing(theTextView)
if self.textViewShouldEndEditing_callback
return self.textViewShouldEndEditing_callback.call(theTextView)
end
true
end

def textView(textView, shouldChangeTextInRange:range, replacementText:text)
if self.shouldChangeCharactersInRange_callback
return self.shouldChangeCharactersInRange_callback.call(textView, range, text)
end
true
end

def textViewDidEndEditing(theTextView)
if self.textViewDidEndEditing_callback
return self.textViewDidEndEditing_callback.call(theTextView)
end
end

def textViewDidChange(theTextView)
if self.textViewDidChange_callback
self.textViewDidChange_callback.call(theTextView)
end
end

end
65 changes: 65 additions & 0 deletions lib/formotion/patch/ui_text_view_placeholder.rb
@@ -0,0 +1,65 @@
class UITextView
attr_reader :placeholder
attr_accessor :placeholder_color

alias_method :old_initWithCoder, :initWithCoder
def initWithCoder(decoder)
old_initWithCoder(decoder)
setup
self
end

alias_method :old_initWithFrame, :initWithFrame
def initWithFrame(frame)
old_initWithFrame(frame)
setup
self
end

def setup
@foreground_observer = NSNotificationCenter.defaultCenter.observe UITextViewTextDidChangeNotification do |notification|
updateShouldDrawPlaceholder
end
end

alias_method :old_drawRect, :drawRect
def drawRect(rect)
old_drawRect(rect)

if (@shouldDrawPlaceholder)
self.placeholder_color.set
self.placeholder.drawInRect(placeholder_rect, withFont:self.font)
end
end


alias_method :old_setText, :setText
def setText(text)
old_setText(text)

updateShouldDrawPlaceholder
end

def placeholder=(placeholder)
return if @placeholder == placeholder

@placeholder = placeholder

updateShouldDrawPlaceholder
end

def placeholder_rect
CGRectMake(self.contentInset.left + 10.0, self.contentInset.top, self.frame.size.width - self.contentInset.left - self.contentInset.right - 16.0, self.frame.size.height - self.contentInset.top - self.contentInset.bottom - 16.0)
end

def placeholder_color
@placeholder_color ||= UIColor.lightGrayColor
end

def updateShouldDrawPlaceholder
prev = @shouldDrawPlaceholder;
@shouldDrawPlaceholder = self.placeholder && self.text.length == 0

self.setNeedsDisplay if (prev != @shouldDrawPlaceholder)
end
end