Add a "Add New..." Button Below the Grid


#1

Greetings Programs!

How would I add a “Add New…” button below the grid like it is in the “organize” example in the ShinobiPlay app.

That button repositions itself/flows with the grid depending on if a row is added or removed.

Thanks!

Wg


DataGrid: is there a way to have a frozen footer
#2

Hi,

I think I’ve just answered your post here:
http://www.shinobicontrols.com/forum/shinobicontrols/2013/5/using-a-pickerdate-picker-or-tableview-to-select-values-when-editing/

Chris


#3

I don’t know if this is the best way but this is what I have finally figured out. I hope it helps someone in the same boat.

To add the button first add this after adding the datagrid to the subview:

#define BUTTON_PADDING 10
#define BUTTON_HEIGHT 30
#define BUTTON_WIDTH 110

// add to the view
    [self.view addSubview:shinobiDataGrid];

	// Add a button to use at the bottom of the grid.
	addNewLine = [UIButton buttonWithType:UIButtonTypeCustom];
	addNewLine.frame = CGRectMake(0, 0, BUTTON_WIDTH, BUTTON_HEIGHT);
        [addNewLine setTitle:@"Add New Line" forState:UIControlStateNormal];
        [addNewLine setAutoresizingMask:UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin];
        [addNewLine addTarget:self action:@selector(addNewServiceOrderLine:) forControlEvents:UIControlEventTouchUpInside];
	[addNewLine setAlpha:0.0f];
	[addNewLine setHidden:YES];

	UIScrollView *scrollView = (UIScrollView *)[self.view.subviews objectAtIndex:0];
	[scrollView addSubview:addNewLine];

Once you’ve loaded in the grid, call the following method:

// Resize the subviews.
		[self resizeSubViews];

  Note the fact that I had to put it in a dispatch_after block to let the datagrid finish loading before calculating the contentSize:

-(void)resizeSubViews
{
	double delayInSeconds = 0.1;
	dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
	dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
		UIScrollView *scrollView = (UIScrollView *)[self.view.subviews objectAtIndex:0];
		// Set the contentSize for the two scrollviews.
		[scrollView setContentSize:CGSizeMake(scrollView.contentSize.width, scrollView.contentSize.height + ((BUTTON_HEIGHT + BUTTON_PADDING) * 2))];
		[[scrollView.subviews objectAtIndex:0] setContentSize:CGSizeMake(scrollView.contentSize.width, scrollView.contentSize.height + ((BUTTON_HEIGHT + BUTTON_PADDING) * 2))];

		// Place the button in the center of the grid at the bottom.
		[addNewLine setCenter:CGPointMake(shinobiDataGrid.center.x, (-shinobiDataGrid.contentOffset.y) + shinobiDataGrid.contentSize.height - (BUTTON_HEIGHT + BUTTON_PADDING))];
		
		[addNewLine setHidden:NO];
		[addNewLine setAlpha:1.0f];
	});
}

Then for the scrollViewDidScroll:

// Recalculate where the button should be positioned.
-(void)recalculateButtonPosition {
    // Place the button in the center of the grid at the bottom.
    [addNewLine setCenter:CGPointMake(shinobiDataGrid.center.x, (-shinobiDataGrid.contentOffset.y) + shinobiDataGrid.contentSize.height - (BUTTON_HEIGHT + BUTTON_PADDING))];
}

-(void)scrollViewDidScroll:(UIScrollView*)scrollView
{
	[self recalculateButtonPosition];
}

Finally call the recalculateButtonPosition method whereever you make changes to the datasource including adding/deleting a line.

[self recalculateButtonPosition];

This is how I have my addNewServiceOrderLine method:

- (void)addNewServiceOrderLine:(id)sender
{
    NSLog(@"\n----------------------------------\nAdd New button was clicked.\n----------------------------------\n");
	
	[self addServiceOrderLine];
}

- (void)addServiceOrderLine
{
	if (self.serviceOrderLines != nil) {
		NSLog(@"Adding new service order line for service order id: %@", self.serviceOrder.serviceOrderId);
		
		// Add a new service order line.
		ServiceOrderLine *serviceOrderLine = [ServiceOrderLine addNewServiceOrderLine:self.serviceOrder.serviceOrderId];
		
		if (serviceOrderLine != nil) {
			[self.serviceOrderLines addObject:serviceOrderLine];
			
			NSLog(@"Added Service Order Line for order: %@", serviceOrderLine.serviceOrderId);
			
			// Reload the grid.
			[shinobiDataGrid reload];
			
			// Resize the subviews.
			[self resizeSubViews];

			NSError *error;
			if (![parentManagedObjectContext save:&error]) {
				NSLog(@"Could not save changes to core data: %@", [error localizedDescription]);
			}
			else {
				NSLog(@"Changes saved.");
			}
		}
	}
	else
	{
		NSLog(@"\n----------------------------------\nNo service order selected.\n----------------------------------\n");
		
		ShowAlert(3, @"Cannot Add Line", @"No Service Order Selected");
	}
}

And deleting:

if (buttonIndex == alertView.firstOtherButtonIndex)
		{
			// Delete the service order line.
			NSLog(@"Delete service order line.");
			
			// Locate the line that is being deleted.
			ServiceOrderLine *orderLine = [self.serviceOrderLines objectAtIndex:self.modifyCell.coordinate.row.rowIndex];
			
			if ([ServiceOrderLine deleteServiceOrderLine:orderLine.serviceOrderId lineNumber:orderLine.lineNumber])
			{
				[self.serviceOrderLines removeObjectAtIndex:self.modifyCell.coordinate.row.rowIndex];
				
				// Reload the datagrid.
				[shinobiDataGrid reload];
				
				// Resize the subviews.
				[self resizeSubViews];
				
				NSLog(@"Deleted service order line: %@", orderLine.lineNumber);
			}
			else
			{
				NSLog(@"Could not delete service order line: %@", orderLine.lineNumber);
			}
		}

Wg