lib/sugarcube/uiactionsheet.rb in sugarcube-0.20.13 vs lib/sugarcube/uiactionsheet.rb in sugarcube-0.20.15

- old
+ new

@@ -1,20 +1,28 @@ class UIActionSheet - # UIActionSheet.alert("title", - # # The first button is considered the 'cancel' button, for the purposes of - # # whether the cancel or success handler gets called, the second button is - # # the 'destructive' button, and the rest are plain old buttons. - # buttons: %w"Cancel OK No-way", - # cancel: proc{ puts "nevermind" }, - # destructive: proc{ puts "OHHH YEAAH!" }, - # success: proc{ |pressed| puts "pressed: #{pressed}" }, - # ) + # For the purposes of whether the cancel or success handler gets called, the + # first button is considered the 'cancel' button, the second button is the + # 'destructive' button, and the rest are plain old buttons. + # + # If you use just one block, it will be used for *all* of the buttons. + # + # @example + # # use a different handler for each button type + # UIActionSheet.alert("title", + # buttons: %w"Cancel Delete No-way", + # cancel: proc{ puts "nevermind" }, + # destructive: proc{ puts "OHHH YEAAH!" }, + # success: proc{ |pressed| puts "pressed: #{pressed}" }, + # ) + # # use one handler for all buttons + # UIActionSheet.alert("title", buttons: [...]) { |button| } def self.alert(title, options={}, &block) # create the delegate delegate = SugarCube::ActionSheetDelegate.new - delegate.on_success = options[:success] || block + delegate.on_default = block + delegate.on_success = options[:success] delegate.on_destructive = options[:destructive] delegate.on_cancel = options[:cancel] delegate.send(:retain) args = [title] # initWithTitle: @@ -22,90 +30,122 @@ buttons = [] buttons.concat(options[:buttons]) if options[:buttons] if buttons.empty? - # cancelButtonTitle: is first, so check for cancel handler - if options[:cancel] - buttons << 'Cancel' - else - buttons << nil - end + # cancelButtonTitle: + buttons << nil - # destructiveButtonTitle, check for destructive handler - if options[:destructive] - buttons << 'Delete' - else - buttons << nil - end - elsif buttons.length == 1 and (options[:cancel] or options[:destructive]) - raise 'If you only have one button, use a :success handler, not :cancel or :destructive' - end - - # uses localized buttons in the actual alert - if buttons.length == 0 - buttons = [nil, nil] - elsif buttons.length == 1 + # destructiveButtonTitle buttons << nil - end - last_index = buttons.length - 1 - offset = 0 - - button_index_map = {} - if buttons[1] # destructive - button_index_map[0] = buttons[1] - offset += 1 - else - last_index -= 1 + # otherButtonTitles: + buttons << 'OK' + elsif buttons.length == 1 && (options[:cancel] || options[:destructive]) + raise 'If you only have one button, use a :success handler, not :cancel or :destructive' end - if buttons[0] # cancel - button_index_map[last_index] = buttons[0] - end - - buttons[2..-1].each_with_index { |button, index| - button_index_map[index + offset] = button - } - # the button titles, mapped to how UIActionSheet orders them. These are passed to the success handler. - delegate.button_index_map = button_index_map - + # cancelButtonTitle:destructiveButtonTitle:otherButtonTitles: args.concat(buttons.map{ |s| s ? s.localized : nil }) args << nil # otherButtonTitles:..., nil + # the button titles, mapped to how UIActionSheet orders them. These are + # passed to the success handler. + buttons_mapped = {} + if args[2] && args[3] # cancel && destructive buttons + buttons_mapped[0] = buttons[1] # destructiveIndex == 0, button == 1 + buttons_mapped[buttons.length - 1] = buttons[0] # cancelIndex == last, button == 0 + # from first+1 to last-1 + buttons[2..-1].each_with_index do |button,index| + buttons_mapped[index + 1] = button + end + elsif args[3] # destructive button + buttons_mapped[0] = buttons[1] # destructiveIndex == 0, button == 1 + # from first+1 to last-1 + buttons[2..-1].each_with_index do |button,index| + buttons_mapped[index + 1] = button + end + elsif args[2] # cancel button + buttons_mapped[buttons.length - 2] = buttons[0] # cancelIndex == last, button == 0 + buttons[2..-1].each_with_index do |button,index| + buttons_mapped[index] = button + end + else + buttons[2..-1].each_with_index do |button,index| + buttons_mapped[index] = button + end + end + delegate.buttons = buttons_mapped + alert = self.alloc alert.send('initWithTitle:delegate:cancelButtonTitle:destructiveButtonTitle:otherButtonTitles:', *args) - window = UIApplication.sharedApplication.keyWindow || UIApplication.sharedApplication.windows[0] - alert.showInView(window) + if options.key?(:style) + style = options[:style] + style = style.uiactionstyle unless style.is_a?(Fixnum) + alert.actionSheetStyle = style + end + if options.fetch(:show, true) + if options.key?(:from) + from = options[:from] + else + from = UIApplication.sharedApplication.windows[0] + end + + case from + when CGRect + view = UIApplication.sharedApplication.windows[0] + alert.showInRect(from, inView: view, animated: true) + when UIBarButtonItem + alert.showFromBarButtonItem(from) + when UIToolbar + alert.showFromToolbar(from) + when UITabBar + alert.showFromTabBar(from) + when UIView + alert.showInView(from) + else + raise "Unknown :from option #{from.inspect}" + end + end alert end + def <<(title) + addButtonWithTitle(title) + end + private def dummy self.initWithTitle(nil, delegate:nil, cancelButtonTitle:nil, destructiveButtonTitle:nil, otherButtonTitles:nil) end end module SugarCube class ActionSheetDelegate - attr_accessor :button_index_map + attr_accessor :buttons + attr_accessor :on_default attr_accessor :on_cancel attr_accessor :on_destructive attr_accessor :on_success def actionSheet(alert, didDismissWithButtonIndex:index) + handler = nil if index == alert.destructiveButtonIndex && on_destructive - on_destructive.call + handler = on_destructive || on_default elsif index == alert.cancelButtonIndex && on_cancel - on_cancel.call - elsif on_success - if on_success.arity == 0 - on_success.call + handler = on_cancel || on_default + else + handler = on_success || on_default + end + + if handler + if handler.arity == 0 + handler.call else - button = button_index_map[index] - on_success.call(button) + button = buttons[index] + handler.call(button) end end self.send(:autorelease) end