omz:forum

    • Register
    • Login
    • Search
    • Recent
    • Popular

    Welcome!

    This is the community forum for my apps Pythonista and Editorial.

    For individual support questions, you can also send an email. If you have a very short question or just want to say hello — I'm @olemoritz on Twitter.


    Implementing a radio style (single selected option) check mark in a forms dialog

    Pythonista
    3
    16
    5514
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • madivad
      madivad last edited by

      I would like to use the check type entry in a form dialog but in a radio button fashion. ie only one check mark in that section at a time.

      I’m trying to work it out and I think I know how to program it, I just don’t know where to implement it in the _FormDialogController

      1 Reply Last reply Reply Quote 0
      • ccc
        ccc last edited by

        http://omz-software.com/pythonista/docs/ios/ui.html#switch

        1 Reply Last reply Reply Quote 0
        • madivad
          madivad last edited by madivad

          I hadn’t thought of switch, I think that looks better than check anyway :)

          @ccc or @cvp , What is the method that is called within the form controller that would need to be overwritten/created?

          cvp 1 Reply Last reply Reply Quote 0
          • madivad
            madivad last edited by

            Wow, and I've just found the segmented control too that @cvp was talking about. Am working to implement that. A single line of options is much better than a list. That's very nice, I'll let you know how I get on

            cvp 1 Reply Last reply Reply Quote 0
            • cvp
              cvp @madivad last edited by cvp

              @madivad try this and see field under age and value of returned diag when you select a segment

              import dialogs
              import datetime
              import ui
              
              #================ copy dialogs.form_dialog: begin
              import collections
              import sys
              PY3 = sys.version_info[0] >= 3
              if PY3:
              	basestring = str
              
              def my_form_dialog(title='', fields=None, sections=None, done_button_title='Done'):
              	if not sections and not fields:
              		raise ValueError('sections or fields are required')
              	if not sections:
              		sections = [('', fields)]
              	if not isinstance(title, basestring):
              		raise TypeError('title must be a string')
              	for section in sections:
              		if not isinstance(section, collections.Sequence):
              			raise TypeError('Sections must be sequences (title, fields)')
              		if len(section) < 2:
              			raise TypeError('Sections must have 2 or 3 items (title, fields[, footer]')
              		if not isinstance(section[0], basestring):
              			raise TypeError('Section titles must be strings')
              		if not isinstance(section[1], collections.Sequence):
              			raise TypeError('Expected a sequence of field dicts')
              		for field in section[1]:
              			if not isinstance(field, dict):
              				raise TypeError('fields must be dicts')
              
              	#========== modify 1: begin
              	c = dialogs._FormDialogController(title, sections, done_button_title=done_button_title)
              	for s in range(0,len(c.sections)):
              		for i in range(0,len(c.cells[s])):			# loop on rows of section s
              			cell = c.cells[s][i]									
              			if len(cell.content_view.subviews) > 0:
              				tf = cell.content_view.subviews[0] 		# ui.TextField of value in row
              				item = c.sections[s][1][i]						# section s, 1=items, row i
              				if 'segments' in item:
              					segmented = ui.SegmentedControl()
              					segmented.name = cell.text_label.text
              					segmented.frame = tf.frame
              					segmented.x = c.view.width - segmented.width - 8
              					segmented.segments = item['segments']
              					cell.content_view.remove_subview(tf)
              					del c.values[tf.name]
              					del tf
              					cell.content_view.add_subview(segmented)
              	#========== modify 1: end
              				
              	c.container_view.present('sheet')
              	c.container_view.wait_modal()
              	# Get rid of the view to avoid a retain cycle:
              	c.container_view = None
              	if c.was_canceled:
              		return None
              		
              	#========== modify 2: begin
              	for s in range(0,len(c.sections)):
              		for i in range(0,len(c.cells[s])):			# loop on rows of section s
              			cell = c.cells[s][i]									
              			if len(cell.content_view.subviews) > 0:
              				tf = cell.content_view.subviews[0] 		# ui.TextField of value in row
              				if isinstance(tf, ui.SegmentedControl):
              					if tf.selected_index >= 0:
              						item = c.sections[s][1][i]						# section s, 1=items, row i
              						c.values[tf.name] = item['segments'][tf.selected_index]
              	#========== modify 2: end		
              	
              	return c.values
              #================ copy dialogs.form_dialog: end
              
              form_list_of_sections = []
              
              sectionA_dicts = []
              sectionA_dicts.append(dict(type = 'text', title = 'First Name',
              key = 'first', placeholder = 'John'))
              
              sectionA_dicts.append(dict(type = 'text', title = 'Last Name',
              key = 'last', placeholder = 'Doe')) 
              
              sectionA_dicts.append(dict(type = 'number', title = 'age',
              key = 'age', placeholder='30')) 
              
              sectionA_dicts.append(dict(type = 'text', title = 'My segmented control',
              key = 'segm', segments = ['yes','no']))
              
              form_list_of_sections.append(('Section A', sectionA_dicts, 'Section A ends'))
              
              sectionB_dicts = []
              sectionB_dicts.append(dict(type = 'date', title = 'Date Of Birth',
              key = 'DOB', value = datetime.date.today()))
              
              sectionB_dicts.append(dict(type = 'url', title = 'Home Page',
                  key = 'homepage', placeholder = 'http://example.com')) 
                  
              form_list_of_sections.append(('Section B', sectionB_dicts, 'Section B ends'))
              
              sectionC_dicts = []
              sectionC_dicts.append(dict(type = 'email', title = 'email',
              key = 'email', placeholder = 'name@mailserver.com')) 
              
              sectionC_dicts.append(dict(type = 'switch', title = 'is_married',
              key = 'is_married', value = True))  
              
              sectionC_dicts.append(dict(type = 'check', title = 'is_registered',
              key = 'is_registered', value = False))  
              
              form_list_of_sections.append(('Section C', sectionC_dicts, 'Section C ends'))
              
              diag = my_form_dialog(title = 'Form Dialog', sections=form_list_of_sections)
              print(diag) 
              
              1 Reply Last reply Reply Quote 0
              • cvp
                cvp @madivad last edited by

                @madivad said:

                What is the method that is called within the form controller that would need to be overwritten/created?

                I don't understand the question if it is relative to the switch because your sample already contains a switch.

                1 Reply Last reply Reply Quote 0
                • cvp
                  cvp last edited by cvp

                  And without your own form_dialog....but it has been hard to find 😅

                  def segmented_action(sender):
                  	global c
                  	if sender.selected_index >= 0:		
                  		c.values[sender.name] = sender.segments[sender.selected_index]
                  
                  def my_tableview_cell_for_row(self,tv, section, row):
                  	global c
                  	c = self
                  	cell = self.cells[section][row]
                  	if len(cell.content_view.subviews) > 0:
                  		tf = cell.content_view.subviews[0]      # ui.TextField of value in row
                  		item = self.sections[section][1][row]	
                  		if 'segments' in item:
                  			# check if SegmentedControl already added
                  			for sv in cell.content_view.subviews:
                  				if type(sv) is ui.SegmentedControl:
                  					return cell
                  			segmented = ui.SegmentedControl()
                  			segmented.name = cell.text_label.text
                  			segmented.action = segmented_action
                  			segmented.frame = tf.frame
                  			segmented.x = c.view.width - segmented.width - 8
                  			segmented.segments = item['segments']
                  			cell.content_view.add_subview(segmented)
                  		elif isinstance(tf, ui.TextField):
                  			tf.alignment=ui.ALIGN_RIGHT
                  	return cell
                      
                  dialogs._FormDialogController.tableview_cell_for_row = my_tableview_cell_for_row
                  
                  diag = dialogs.form_dialog(title = 'Form Dialog', sections=form_list_of_sections)  
                  
                  1 Reply Last reply Reply Quote 0
                  • cvp
                    cvp last edited by

                    The last code is not correct if you scroll the dialog so the Segments are hidden and reshown back because the code adds a new subview each time. Let me some time to correct it.
                    That's the problem when you do this process in tableview_cell_for_row

                    1 Reply Last reply Reply Quote 0
                    • cvp
                      cvp last edited by cvp

                      Code corrected (and edited in the post), sorry for that

                      1 Reply Last reply Reply Quote 0
                      • cvp
                        cvp last edited by

                        And if you want a dialog field as a button (radio, checkbox, ...), this code could help you.
                        You have to design the field with two images for your button, like:

                        sectionA_dicts.append(dict(type = 'text', title = 'My button',
                        key = 'button', button = ['iob:ios7_checkmark_32','iob:ios7_checkmark_outline_32'])) 
                        

                        and the associated process:

                        def button_action(sender):
                        	global c
                        	sender.idx = 1 - sender.idx
                        	sender.image = ui.Image.named(sender.images[sender.idx])
                        	c.values[sender.name] = sender.idx
                        
                        def my_tableview_cell_for_row(self,tv, section, row):
                        	global c
                        	c = self
                        	cell = self.cells[section][row]
                        	if len(cell.content_view.subviews) > 0:
                        		tf = cell.content_view.subviews[0]      # ui.TextField of value in row
                        		item = self.sections[section][1][row]	
                        		if 'segments' in item:
                        			# check if SegmentedControl already added
                        			for sv in cell.content_view.subviews:
                        				if type(sv) is ui.SegmentedControl:
                        					return cell
                        			segmented = ui.SegmentedControl()
                        			segmented.name = cell.text_label.text
                        			segmented.action = segmented_action
                        			segmented.frame = tf.frame
                        			segmented.x = c.view.width - segmented.width - 8
                        			segmented.segments = item['segments']
                        			cell.content_view.add_subview(segmented)
                        		elif 'button' in item:
                        			# check if Button already added
                        			for sv in cell.content_view.subviews:
                        				if type(sv) is ui.Button:
                        					return cell
                        			button = ui.Button()
                        			button.name = cell.text_label.text
                        			button.action = button_action
                        			button.frame = tf.frame
                        			button.width = button.height
                        			button.x = c.view.width - button.width - 8
                        			button.images = item['button']
                        			button.title = ''
                        			button.idx = 0
                        			button.image = ui.Image.named(button.images[button.idx])
                        			cell.content_view.add_subview(button)
                        		elif type(tf) is ui.TextField:
                        			tf.alignment=ui.ALIGN_RIGHT
                        	return cell 
                        

                        1 Reply Last reply Reply Quote 0
                        • cvp
                          cvp last edited by cvp

                          and supporting color images in button:

                          .
                          .
                          .
                          
                          sectionA_dicts.append(dict(type = 'text', title = 'My face',
                          key = 'face', button = ['emj:Smiling_1','emj:Disappointed']))
                          .
                          .
                          .
                          def button_action(sender):
                          	global c
                          	sender.idx = 1 - sender.idx
                          	sender.image = ui.Image.named(sender.images[sender.idx]).with_rendering_mode(ui.RENDERING_MODE_ORIGINAL)
                          	c.values[sender.name] = sender.idx
                          .
                          .
                          .
                          
                          			button.image = ui.Image.named(button.images[button.idx]).with_rendering_mode(ui.RENDERING_MODE_ORIGINAL)
                          .
                          .
                          .
                          

                          1 Reply Last reply Reply Quote 0
                          • madivad
                            madivad last edited by

                            @cvp you are incredible...

                            I saw your first posts on the way to work and thought, “yeah, I have to get to that!” And now I log back and on and find this!!!! MUCH to digest!

                            I will be back (busy the next few days, but the kids are on holidays after tomorrow and I’ll slow down on the workload, so I should be able to get into this more)

                            Seriously, thanks for your contributions, you are awesome!

                            1 Reply Last reply Reply Quote 0
                            • madivad
                              madivad last edited by

                              @cvp I finally got back to this, I got it all working as expected, the only issue I have is with the custom rows (My segmented control*, My button, and My face), they allow the cursor into the row label on the left hand side if the user touches near them.

                              I’ve spent a couple of hours going over the cradle and only minimally beginning to understand it :)

                              * the segmented control is ok in the custom/my_form_dialog and doesn’t allow the cursor in. It only allows the cursor when using the inbuilt dialog.

                              cvp 2 Replies Last reply Reply Quote 0
                              • cvp
                                cvp @madivad last edited by

                                @madivad It is normal. When we create the new fields types in tableview_cell_for_row, the original TextField still exists. In the other case, the code deletes the TextField.

                                1 Reply Last reply Reply Quote 0
                                • cvp
                                  cvp @madivad last edited by

                                  @madivad you can add these lines when you create a new field type
                                  after

                                  			cell.content_view.add_subview(segmented) 
                                  

                                  Add

                                  			cell.content_view.remove_subview(tf)
                                  			del self.values[tf.name]
                                  			del tf 
                                  
                                  1 Reply Last reply Reply Quote 0
                                  • madivad
                                    madivad last edited by

                                    @cvp said:

                                            cell.content_view.remove_subview(tf)
                                            del self.values[tf.name]
                                            del tf 
                                    

                                    I knew it was something like that, I was giving it a go but hadn’t got it right.

                                    Thanks.

                                    1 Reply Last reply Reply Quote 0
                                    • First post
                                      Last post
                                    Powered by NodeBB Forums | Contributors