Operating system requirements: iOS 5.0 or later.
Mobile device: iPad.
This example displays dashboard growth indicator and then a modal window with a message. They are hidden in three seconds. After that a mailing window is displayed.
The development environment console also displays the number of dashboard settings, dashboard data description, a modal window message and a dimension panel title.
Executing the example requires to place the following code instead of the executeExample method of the ViewController class (see the Displaying of Dashboard section):
// Get custom example placed in the body of this method -(void) executeExample { // Get dashboard controller MABaseReportViewController *controller = m_controller; // Enter the number of dashboard settings NSDictionary *settings = [[controller delegate] reportSettings]; if(settings != nil){ NSLog(@"Number of dashboard settings: %i", [settings count]); } // Display dashboard loading indicator [controller showActivityIndicator]; // Continue executing the example after a pause [self performSelector:@selector(continueExample:) withObject:controller afterDelay:3]; } // Continue executing the example -(void) continueExample:(MABaseReportViewController *)controller { // Get dashboard title NSString *title = @""; if ([[(MADashboardReportViewController*)controller delegate] title]) { title = [[(MADashboardReportViewController*)controller delegate] title]; } // Display modal window with message [controller showWaiterWithTitle:title andMessage:@" Loading"]; // Display modal window message NSString *message = [[controller waiterView] message]; NSLog(@"Modal window message: %@", message); // Start time for three seconds [NSTimer scheduledTimerWithTimeInterval:3.0f target:self selector:@selector(timerEvent)userInfo:nil repeats:NO]; } // Handle time event -(void) timerEvent { // Get dashboard controller MADashboardReportViewController *controller = (MADashboardReportViewController*)m_controller; // Display dashboard data description NSData *dashboardData = [[controller delegate] dashboardData]; if(dashboardData != nil) NSLog(@"Dashboard data description: %@", dashboardData); // Display dimension panel title NSString *dimPanelTitle = [[[controller delegate] dimensionsPanel] title]; if(dimPanelTitle != nil) NSLog(@"Dimension panel title: %@", dimPanelTitle); // Hide modal window with message [controller hideWaiter]; // Hide loading indicator [controller hideActivityIndicator]; // Display mailing window [controller composeMail]; }
It is also required to replace the code in the static example file MADashboardReportViewController.mm with the code given in the drop-down list:
Substitution code for the MADashboardReportViewController.mm file.
#import "MADashboardReportViewController.h" #import "MADashboardReportViewControllerDelegate.h" #import "UIView+Screenshot.h" #import "APXMLParser.h" #import "UIColor+hex.h" #import "TransparentToolbar.h" #import "MADataReportActionViewController.h" #import "APCompositeBlock.h" #import "MAReportAccessRights.h" #include "PPLAccessRightsManager.h" #import "NuGridController.h" #import "NuGridView.h" #import "MAGridDataViewControllerPrivate.h" #import "MATextDataViewController.h" #import "MAWebDataViewController.h" #import "MAImageDataViewController.h" #import "MADataReportViewController.h" #import "BackButtonHandlerProtocol.h" #import "MAProceduralReportDataViewController.h" extern NSString *DATASOURCE_CHANGED_NOTIFICATION; @implementation MADashboardReportViewController { PanelViewController *m_panelViewController; SplitViewController *m_splitViewController; BOOL m_viewSettingsPopoverDisplayed; UIAlertView *m_waiterView; int m_screenshotCounter; BOOL m_hasControls; NSMutableDictionary *m_localScreenshots; NSMutableSet *m_readyForScreenshotControllers; BOOL m_shouldBackAction; BOOL m_dashboardSetSelection; } @synthesize splitViewController = m_splitViewController, panelViewController = m_panelViewController; @synthesize delegate = m_delegate, report = m_report; @synthesize waiterView = m_waiterView; // Initialize delegate based controller - (id) initWithDelegate: (id<MADashboardReportViewControllerDelegate>)delegate { if ((self = [super initWithDelegate: delegate])) { m_dashboardSetSelection = NO; m_shouldBackAction = YES; NSAssert(self.delegate, @"ReportDelegate not nil"); // Get path to dashboard resources NSArray *resourcesPaths = [m_delegate dashboardResourcesPath]; // Get path to MIME types of dashboard resources NSArray *resourcesMimesTypes = [m_delegate dashboardResourcesMimeTypes]; NSString *xmlPath; for (int i = 0; i < [resourcesMimesTypes count]; i++) { if ([(NSString *)[resourcesMimesTypes objectAtIndex:i] isEqualToString:@"application/xml"]) { xmlPath = (NSString *)[resourcesPaths objectAtIndex:i]; } } NSData *xmlData = [NSData dataWithContentsOfFile:xmlPath]; APXMLParserObject *structure = [APXMLParser parseXML:xmlData]; m_report = [APKap alloc]; [m_report initWithParserObject:structure delegate:self]; BOOL handleAllControls = YES; for (APCompositeBlock *i in m_report.compositeBlocks.allValues) { if (i.hasParamsBlock) { handleAllControls = NO; break; } } for (APCompositeBlock *i in m_report.compositeBlocks.allValues) { i.handleAllControls = handleAllControls; } LOG(@"handleAllControls: %d", handleAllControls); NSArray *blocks = [structure findObjectsOfElementName:@"block"]; if (self.delegate.hasSelectionSynchronizationConfig) { for (APXMLParserObject *i in blocks) { NSString * controlKey = [i.attributes objectForKey:@"key"]; if ([[i.attributes objectForKey:@"type"] isEqualToString:@"Control"]) { m_hasControls = YES; APXMLParserObject *syncIndexKey = [i objectPropForKey:@"syncIndex"]; if (syncIndexKey) { NSNumber *value = [syncIndexKey.attributes objectForKey:@"val"]; // Creates an object describing dashboard control with specified key and dimension panel synchronization key [self.delegate addDimensionPanelControlWithKey:controlKey syncIndexKey: [value intValue]]; } } else { APXMLParserObject* title = [i objectPropForKey:@"title"]; if (title) { APXMLParserObject* show = [title objectPropForKey:@"show"]; NSNumber* val = [NSNumber numberWithInt:0]; if (show) { val = [show.attributes objectForKey:@"val"]; } if ([val intValue] == 1) { APXMLParserObject* text = [title objectPropForKey:@"text"]; NSString* textVal = [NSString string]; if (text) { textVal = [text.attributes objectForKey:@"val"]; } if (![textVal isEqualToString:@""]) { [m_report.dataViewsTitles setObject:textVal forKey:controlKey]; } } } } } } // Create a dashboard split view controller with sliding dimension panel m_splitViewController = [SplitViewController new]; // Create a dimension panel controller m_panelViewController = [PanelViewController new]; m_panelViewController.delegate = self; [m_panelViewController setPanelTitle:NSLocalizedString(@"Controls", @"DimPanel:Title")]; [self.delegate pullSelection]; if (m_hasControls) { m_splitViewController.panelViewController = m_panelViewController; } m_splitViewController.firstViewVisible = NO; self.report.isfullScreenEnabled = self.delegate.hasScreenshot; [self addObserverDataSourceChanged]; m_localScreenshots = [NSMutableDictionary new]; m_readyForScreenshotControllers = [NSMutableSet new]; } return self; } // Apply selected dimension element selection - (void) panelViewDidHide:(PanelViewController *)panelController { [self.delegate pushSelection]; } // Load selected dimension element selections - (void) panelViewDidShow:(PanelViewController *)panelController { [self.delegate pullSelection]; } // Sunscribe for data source change event - (void) addObserverDataSourceChanged { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updatePanelViewVisibility:) name:DATASOURCE_CHANGED_NOTIFICATION object:nil]; } // Unsubscribe from data source change event - (void) removeObserverDataSourceChanged { [[NSNotificationCenter defaultCenter] removeObserver:self name:DATASOURCE_CHANGED_NOTIFICATION object:nil]; } // Refresh panel visibility state - (void) updatePanelViewVisibility: (id) sender { if (m_splitViewController.panelViewController) { m_splitViewController.panelViewController.view.hidden = [self.delegate dimensionsPanel].dimensionsCount <= 0; } } // Create and set up table data view controller - (MAGridDataViewController *)createGridDataViewControllerWithMetabaseKey:(NSString *)key blockKey:(NSString *)blockKey { MAGridDataViewController *controller = [self.delegate createGridDataViewControllerWithMetabaseKey:key blockKey:blockKey]; controller.delegate = self; [(UIScrollView *)controller.gridController.view setBounces: NO]; return controller; } // Create and set up map data view controller - (MAMapDataViewController *)createMapDataViewControllerWithMetabaseKey:(NSString *)key blockKey:(NSString *)blockKey { MAMapDataViewController *controller = [self.delegate createMapDataViewControllerWithMetabaseKey:key blockKey:blockKey]; controller.delegate = self; return controller; } // Create and set up bubble tree data view controller - (MABubbleTreeDataViewController *)createBubbleTreeDataViewControllerWithMetabaseKey:(NSString *)key blockKey:(NSString *)blockKey { MABubbleTreeDataViewController *controller = [self.delegate createBubbleTreeDataViewControllerWithMetabaseKey:key blockKey:blockKey]; controller.delegate = self; return controller; } // Create and set up chart data view controller - (MAChartDataViewController *)createChartDataViewControllerWithMetabaseKey:(NSString *)key blockKey:(NSString *)blockKey { MAChartDataViewController *controller = [self.delegate createChartDataViewControllerWithMetabaseKey:key blockKey:blockKey]; controller.delegate = self; return controller; } // Create and set up bubble chart data view controller - (MABubbleDataViewController *)createBubbleDataViewControllerWithMetabaseKey:(NSString *)key blockKey:(NSString *)blockKey { MABubbleDataViewController *controller = [self.delegate createBubbleDataViewControllerWithMetabaseKey:key blockKey:blockKey]; controller.delegate = self; return controller; } // Create and set up tree map data view controller - (MATreeMapDataViewController *)createTreeMapDataViewControllerWithMetabaseKey:(NSString *)key blockKey:(NSString *)blockKey { MATreeMapDataViewController *controller = [self.delegate createTreeMapDataViewControllerWithMetabaseKey:key blockKey:blockKey]; controller.delegate = self; return controller; } // Create and set up regular report data view controller - (MAProceduralReportDataViewController *)createProceduralReportDataViewControllerWithMetabaseKey:(NSString *)key blockKey:(NSString *)blockKey { MAProceduralReportDataViewController *controller = [self.delegate createProceduralReportDataViewControllerWithMetabaseKey:key blockKey:blockKey]; controller.reportController = (MADataReportViewController *)self; return controller; } // Create and set up express report data view controller - (MADataViewController *)createExpressReportDataViewControllerWithMetabaseKey:(NSString *)key blockKey:(NSString *)blockKey { MADataViewController *controller = [self.delegate createExpressReportDataViewControllerWithMetabaseKey:key blockKey:blockKey]; controller.delegate = (MADataReportViewController *)self; return controller; } // Create and set up text data view controller - (MATextDataViewController *)createTextDataViewController { MATextDataViewController *controller = [[MATextDataViewController alloc] init]; controller.delegate = self; return controller; } // Create and set up browser data view controller - (MAWebDataViewController *)createWebDataViewController { MAWebDataViewController *controller = [[MAWebDataViewController alloc] init]; controller.delegate = self; return controller; } // Create and set up static image data view controller - (MAImageDataViewController *)createImageDataViewController { MAImageDataViewController *controller = [[MAImageDataViewController alloc] init]; controller.delegate = self; return controller; } // Return repository data source key by dashboard block key - (NSString *)metabaseKeyByBlockKey:(NSString *)key { return [self.delegate metabaseKeyByBlockKey:key]; } // Create a dashboard empty button - (UIBarButtonItem *)barSpace { UIBarButtonItem *space = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil]; return [space autorelease]; } // Create a dashboard button - (UIBarButtonItem *)createRightBarItem { double height = 44; UIToolbar *result = [[[TransparentToolbar alloc] initWithFrame:CGRectMake(0.0, 0.0, 0.0, height)] autorelease]; result.autoresizingMask = UIViewAutoresizingFlexibleHeight; result.backgroundColor = [UIColor clearColor]; NSMutableArray *buttons = [NSMutableArray new]; UIBarButtonItem *button = nil; if (m_report.fullScreenBlockKey) { id<MADataViewControllerProtocol>dataView = [m_report.dataViews objectForKey:m_report.fullScreenBlockKey]; NSArray *customButtons = [dataView barButtonItems]; if ([customButtons count]) { [buttons addObjectsFromArray:customButtons]; } if (dataView.hasSettingsController) { UIBarButtonItem *button = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"i.png"] style:UIBarButtonItemStylePlain target:self action:@selector(dataViewSettingsAction:)]; [buttons addObject:button]; [button release]; [buttons addObject:[self barSpace]]; } UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithImage:nil style:UIBarButtonItemStylePlain target:self action:nil]; [buttons addObject:backButton]; [backButton release]; } else { if ([m_report.compositeBlocks count]>1) { button = [[[UIBarButtonItem alloc] initWithTitle: m_report.slideMode?NSLocalizedString(@"Slide: ON", @"APViewController :: Slide: ON"):NSLocalizedString(@"Slide: OFF", @"APViewController :: Slide: OFF") style:UIBarButtonItemStylePlain target:self action:@selector(slideModeAction:)] autorelease]; [buttons addObject:button]; } button = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAction target:self action:@selector(reportAction:)]; [buttons addObject:button]; [button release]; } [result setItems:buttons]; [buttons release]; CGSize bestSize = [result sizeThatFits:result.frame.size]; CGRect frame = result.frame; frame.size = bestSize; result.frame = frame; return [[[UIBarButtonItem alloc] initWithCustomView:result] autorelease]; } // Set dashboard elements - (void) setBarButtonItems:(NSArray *)items forDataViewController:(id<MADataViewControllerProtocol>)controller { self.navigationItem.rightBarButtonItem = [self createRightBarItem]; } // - (void) slideModeAction: (id) sender { if (!self.delegate.hasScreenshot) { UIAlertView *alert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Error", @"Error") message:NSLocalizedString(@"Cannot switch to Slideshow mode", @"Cannot switch to Slideshow mode") delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil, nil]; [alert show]; [alert release]; return; } [self showWaiter]; for (MADataViewController *i in m_report.compositeBlocks.allValues) { i.view.hidden = YES; } [[NSRunLoop mainRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; m_report.slideMode = !m_report.slideMode; self.navigationItem.rightBarButtonItem = [self createRightBarItem]; [self hideWaiter]; } // Handle dashboard action event - (void) reportAction: (id) sender { MAReportAccessRights *rights = m_delegate.accessRights; BOOL isReadonly = !rights.canWrite; MADataReportActionViewController *controller = [[[MADataReportActionViewController alloc] initWithDelegate:self readOnly:isReadonly] autorelease]; // Display controller in popup window from specified element [self showInPopover:controller fromBarButtonItem:sender]; } // Handle data view settings action event - (void) dataViewSettingsAction:(id) sender { if (m_popoverController) { [self hidePopover]; m_viewSettingsPopoverDisplayed = NO; return; } UIViewController<PopoverContainedControllerProtocol> *controller = (UIViewController<PopoverContainedControllerProtocol> *)[(id<MADataViewControllerProtocol>)[m_report.dataViews objectForKey:m_report.fullScreenBlockKey] settingsController]; m_viewSettingsPopoverDisplayed = YES; [self showInPopover:controller fromBarButtonItem:sender]; } // Handle popup window hide event - (void) popoverControllerDidDismissPopover:(UIPopoverController *)popoverController { if (m_viewSettingsPopoverDisplayed) { UINavigationController *nav = (UINavigationController *)popoverController.contentViewController; UIViewController<PopoverContainedControllerProtocol> *ctl = (UIViewController<PopoverContainedControllerProtocol> *)[[nav viewControllers] objectAtIndex:0]; [(id<MADataViewControllerProtocol>)[m_report.dataViews objectForKey:m_report.fullScreenBlockKey] settingsControllerClosed:ctl]; } m_viewSettingsPopoverDisplayed = NO; [m_popoverController release]; m_popoverController = nil; } // Handle full-screen mode exit event - (void) fullscreenDismissAction:(id) sender { m_shouldBackAction = YES; if (m_popoverController) { if (m_viewSettingsPopoverDisplayed) { UINavigationController *nav = (UINavigationController *)m_popoverController.contentViewController; UIViewController<PopoverContainedControllerProtocol> *ctl = (UIViewController<PopoverContainedControllerProtocol> *)[[nav viewControllers] objectAtIndex:0]; [(id<MADataViewControllerProtocol>)[m_report.dataViews objectForKey:m_report.fullScreenBlockKey] settingsControllerClosed:ctl]; m_viewSettingsPopoverDisplayed = NO; } [m_popoverController dismissPopoverAnimated:YES]; [m_popoverController release]; m_popoverController = nil; } [m_splitViewController setHasControls:m_hasControls]; m_splitViewController.firstViewVisible = NO; // Inform that data view controller exits full-screen mode [self.delegate dataViewWillLeaveFullscreen:(id<MADataViewControllerProtocol>)[m_report.dataViews objectForKey:m_report.fullScreenBlockKey]]; [m_report dismissFullscreenCompositeBlock]; [self updatePanelViewVisibility:nil]; } // Display full-screen block controls - (void)showControlsForFullscreenBlock: (NSString *)blockKey { m_shouldBackAction = NO; self.navigationController.navigationBar.backItem.title = NSLocalizedString(@"Back", @"APViewController :: Report: Back"); self.navigationItem.rightBarButtonItem = [self createRightBarItem]; // Inform that block enters to full-screen mode [self.delegate didSelectedBlockWithKey:blockKey]; if (!m_hasControls) { m_splitViewController.panelViewController = m_panelViewController; [m_splitViewController setHasControls:YES]; } m_splitViewController.splitView.fixSecondViewSize = NO; m_splitViewController.splitView.titleView.titleLabel.text = self.reportTitle; m_splitViewController.splitView.hasTitle = YES; [m_panelViewController setPanelTitle:NSLocalizedString(@"Layout", @"DimPanel:Title")]; NSLog(@"setting title %@", self.title); m_splitViewController.firstViewVisible = NO; } // Hide full-screen block controls - (void)hideControlsForFullscreenBlock:(NSString *)blockKey { self.navigationItem.rightBarButtonItem = [self createRightBarItem]; m_shouldBackAction = NO; self.navigationController.navigationBar.backItem.title = NSLocalizedString(@"Back", @"APViewController :: Report: Back"); m_splitViewController.panelViewController = nil; m_splitViewController.splitView.fixSecondViewSize = NO; m_splitViewController.splitView.hasTitle = YES; m_splitViewController.splitView.titleView.titleLabel.text = self.reportTitle; [m_panelViewController setPanelTitle:NSLocalizedString(@"Layout", @"DimPanel:Title")]; NSLog(@"setting title %@", self.title); m_splitViewController.firstViewVisible = NO; [self.delegate didSelectedBlockWithKey:blockKey]; } // Exit blocks from full-screen mode - (void)dismissControlsForFullscreenBlock { self.navigationItem.rightBarButtonItem = [self createRightBarItem]; m_splitViewController.splitView.fixSecondViewSize = YES; m_splitViewController.splitView.hasTitle = NO; [m_panelViewController setPanelTitle:NSLocalizedString(@"Controls", @"DimPanel:Title")]; // Inform that block exits full-screen mode [self.delegate didDismissedBlock]; if (!m_hasControls) { m_splitViewController.panelViewController = nil; } } // Load dashboard data view - (void)loadView { [super loadView]; [self.view addSubview:m_splitViewController.view]; // Set up split view controller m_splitViewController.splitView.overlap = 44.0; m_splitViewController.splitView.titleHeight = 50.0; m_splitViewController.splitView.titleView.backgroundColor = [UIColor colorWithHex:@"#e3e7ec"]; m_splitViewController.splitView.titleView.bottomLineColor = [UIColor whiteColor]; m_splitViewController.splitView.hasTitle = NO; m_splitViewController.splitView.titleView.titleLabel.text = self.reportTitle; m_splitViewController.contentViewController = m_report; m_splitViewController.splitView.fixSecondViewSize = YES; m_splitViewController.firstViewVisible = NO; m_splitViewController.noResizeUntilAnimated = YES; [m_splitViewController setHasControls:m_hasControls]; self.navigationItem.rightBarButtonItem = [self createRightBarItem]; // Refresh pivot objects for building data tables [self.delegate refreshPivots]; for (NSString *i in m_report.compositeBlocks) { // Save composite block [m_delegate setCompositeBlock:[m_report.compositeBlocks objectForKey:i] forBlockKey:i]; } // If there is a list of settings if (!self.delegate.hasSelectionSynchronizationConfig) { for (APCompositeBlock *i in m_report.compositeBlocks.allValues) { if (i.handleSelectionBus) { for (APCompositeBlock *j in m_report.compositeBlocks.allValues) { if (i == j) continue; for (NSString *handleBlockKey in i.handleBlockKeys) { if ([handleBlockKey isEqualToString: j.key]) { // Link dashbgoard blocks [self.delegate addSlaveBlock:i.key toMasterBlock:j.key]; } } } } } // Set up linking of blocks by dashboard settings } else [self.delegate configureSelectionWithConfig]; } // Display loading indicator - (void) showActivityIndicator { NSLog(@"************* showWaiter"); [self.splitViewController showWaiter]; [[NSRunLoop mainRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.01]]; } // Hide loading indicator - (void) hideActivityIndicator { NSLog(@"************* hideWaiter"); [self.splitViewController hideWaiter]; [[NSRunLoop mainRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.01]]; if (![self.delegate hasScreenshot]) { dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 1.0 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{ UIImage *image = [self screenshot]; [self.delegate setScreenshot:UIImagePNGRepresentation(image)]; self.report.isfullScreenEnabled = YES; }); } } // Link dashobard blocks - (void) addSlaveBlock:(NSString *)slaveKey toMasterBlock:(NSString *)masterKey { [self.delegate addSlaveBlock:slaveKey toMasterBlock:masterKey]; } // Display settings bar - (void) dataViewController: (id<MADataViewControllerProtocol>) ctl showSettingsController: (UIViewController<PopoverContainedControllerProtocol> *) settings fromView: (UIView *) view { // Display panel in popup window of specified dashboard data view [self showInPopover:settings fromView:view]; } // Save screenshot to drawing context - (void) captureScreenshotToContext:(CGContextRef)context { [self.view.layer renderInContext:context]; } // Insert image inside another image + (UIImage *)insertImage:(UIImage *)image2 inImage:(UIImage *)image1 inRect:(CGRect)rect { UIGraphicsBeginImageContext(image1.size); [image1 drawInRect:CGRectMake(0, 0, image1.size.width, image1.size.height)]; CGContextRef ctx = UIGraphicsGetCurrentContext(); CGContextSetFillColorWithColor(ctx, UIColor.whiteColor.CGColor); CGContextFillRect(ctx, rect); [image2 drawInRect:rect]; UIImage *output = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return output; } // Create a screenshot - (UIImage *) screenshot { UIView *annoyingView = m_panelViewController.view; BOOL oldvisible = annoyingView.layer.hidden; annoyingView.layer.hidden = YES; UIGraphicsBeginImageContext(self.view.bounds.size); CGContextRef contextRef = UIGraphicsGetCurrentContext(); [self.view.layer renderInContext:contextRef]; UIImage *screenshot = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); annoyingView.layer.hidden = oldvisible; for (NSString *q in m_report.compositeBlocks) { APCompositeBlock *i = [m_report.compositeBlocks objectForKey:q]; MADataViewController *v = [m_report.dataViews objectForKey:q]; if ([i.type isEqualToString:@"Map"] || ([i.type isEqualToString:@"TreeMap"]) ||([i.type isEqualToString:@"BubbleTree"])) { CGRect insertionRect = [i.view convertRect:v.view.bounds toView:self.view]; insertionRect.origin.x += 2; insertionRect.origin.y += 53; UIImage *localScreenshot = v.screenshot; screenshot = [MADashboardReportViewController insertImage:localScreenshot inImage:screenshot inRect:insertionRect]; } } return screenshot; } #pragma mark BaseSettingsViewControllerDelegate // Execute action with dashboard - (void) performSettingsAction:(NSString *)key { [self hidePopover]; if ([key isEqualToString:kDataReportMailAction]) { // Sending email [self composeMail]; } else if ([key isEqualToString:kDataReportSaveAction]) { // Saving dashboard settings [self showWaiterWithTitle:NSLocalizedString(@"Saving...", @"saving message") andMessage:nil]; [self performSelector:@selector(saveReport) withObject:nil afterDelay:0.1]; } } // Save dashboard settings - (void) saveReport { UIImage *image = [self screenshot]; [self.delegate setScreenshot:UIImagePNGRepresentation(image)]; // Save dashboard settings [self.delegate saveReport]; [self hideWaiter]; } // Execute action with dashboard with additional parameters - (void) performSettingsAction:(NSString *)key withParameter:(NSObject *)params { [self hidePopover]; if ([key isEqualToString:kSaveFavoriteAction]) { if (!self.delegate.hasSelectionSynchronizationConfig) { UIAlertView *alert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Legacy report", @"legacy report") message:NSLocalizedString(@"Adding legacy reports to favorites is not supported", @"legacy report error message") delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil, nil]; [alert show]; [alert release]; } else { [self showWaiterWithTitle:NSLocalizedString(@"Please Wait...", nil) andMessage:nil]; [self performSelector:@selector(addToFavorites:) withObject:(NSString *)params afterDelay:0.5]; } } } // Add dashboard to favorites - (void)addToFavorites:(NSString *)name { [self.delegate saveFavoriteWithName:name]; [self hideWaiter]; } // Display dashboard data views - (void) viewDidLayoutSubviews { m_splitViewController.view.frame = self.view.bounds; } - (void) dealloc { for (MADataViewController *i in m_report.dataViews.allValues) { i.delegate = nil; } [m_report release]; [m_panelViewController release]; [m_splitViewController release]; [self removeObserverDataSourceChanged]; [m_localScreenshots release]; [m_readyForScreenshotControllers release]; [super dealloc]; } // Display waiting window - (void)showWaiter { if (!m_waiterView) { m_waiterView = [[[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Switching...", nil) message:nil delegate:self cancelButtonTitle:nil otherButtonTitles:nil] autorelease]; UIActivityIndicatorView *activityView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge]; activityView.frame = CGRectMake(139.0f - 18.0f, 50.0f, 37.0f, 37.0f); [activityView startAnimating]; [m_waiterView addSubview:activityView]; [m_waiterView show]; [activityView release]; } } // Hide waiting window - (void)hideWaiter { [m_waiterView dismissWithClickedButtonIndex:0 animated:YES]; m_waiterView = nil; } #pragma mark MADataViewControllerDelegate // Handle data view controller availability change event - (void) dataViewController: (id<MADataViewControllerProtocol>) ctl availabilityUpdated:(BOOL) availability { if (availability) { [self dataViewControllerDidFinishCalculations:ctl]; } else { [self dataViewControllerWillStartCalculations:ctl]; } } // Handle data view controller calculation start event - (void) dataViewControllerWillStartCalculations: (id<MADataViewControllerProtocol>) ctl { NSString *key = [[[m_report dataViews] allKeysForObject:ctl] lastObject]; if (self.report.fullScreenBlockKey && [self.report.fullScreenBlockKey isEqual:key]) { [self showActivityIndicator]; } else { APCompositeBlock *block = [[m_report compositeBlocks] objectForKey:key]; [block dataViewControllerWillStartCalculations]; } } // Handle data view controller calculation end event - (void) dataViewControllerDidFinishCalculations: (id<MADataViewControllerProtocol>) ctl { NSString *key = [[[m_report dataViews] allKeysForObject:ctl] lastObject]; if (self.report.fullScreenBlockKey && [self.report.fullScreenBlockKey isEqual:key]) { [self hideActivityIndicator]; } else { NSString *key = [[[m_report dataViews] allKeysForObject:ctl] lastObject]; APCompositeBlock *block = [m_report.compositeBlocks objectForKey:key]; [block dataViewControllerDidFinishCalculations]; } } // Inform that data view controller is ready to create a screenshot - (void) dataViewControllerReadyForScreenshot:(id<MADataViewControllerProtocol>)ctl { if ([self.delegate hasScreenshot]) return; BOOL dashboardHasGrid = NO; for(MADataViewController *controller in [m_report.dataViews allValues]) { if([controller isKindOfClass:[MAGridDataViewController class]]) { dashboardHasGrid = YES; break; } } BOOL uncheckingClass = dashboardHasGrid ? [ctl isKindOfClass:[MABubbleTreeDataViewController class]] || [ctl isKindOfClass:[MATreeMapDataViewController class]] || [ctl isKindOfClass:[MAMapData3DViewController class]] || [ctl isKindOfClass:[MAImageDataViewController class]] || [ctl isKindOfClass:[MAWebDataViewController class]] || [ctl isKindOfClass:[MATextDataViewController class]] : YES; if ([ctl isKindOfClass:[MAGridDataViewController class]]) { m_dashboardSetSelection = [(MAGridDataViewController*)ctl noStartupSelection] || [(MAGridDataViewController*)ctl gridSelection].count > 0; if (m_dashboardSetSelection) { for(MADataViewController *controller in [m_report.dataViews allValues]) { if(![controller isKindOfClass:[MAGridDataViewController class]]) { [controller updateDataWithGridSelection]; } } } } if (m_dashboardSetSelection || uncheckingClass) { NSValue *v = [NSValue valueWithNonretainedObject:ctl]; if ([m_readyForScreenshotControllers containsObject:v]) return; [m_readyForScreenshotControllers addObject:v]; if (m_screenshotCounter == 0) [m_localScreenshots removeAllObjects]; CGRect place = ctl.view.bounds; place = [self.view convertRect:place fromView:ctl.view]; UIImage *ctlScreenshot = ctl.screenshot; [m_localScreenshots setObject:ctlScreenshot forKey:[NSValue valueWithCGRect:place]]; m_screenshotCounter++; if (m_screenshotCounter == [m_report.dataViews count]) { UIView *annoyingView = m_panelViewController.view; BOOL oldvisible = annoyingView.layer.hidden; annoyingView.layer.hidden = YES; UIGraphicsBeginImageContext(self.view.bounds.size); CGContextRef contextRef = UIGraphicsGetCurrentContext(); [self.view.layer renderInContext:contextRef]; annoyingView.layer.hidden = oldvisible; [m_localScreenshots enumerateKeysAndObjectsUsingBlock:^(NSValue *key, UIImage *localScreenshot, BOOL *bStop){ CGRect rect = key.CGRectValue; CGContextRef ctx = UIGraphicsGetCurrentContext(); CGContextSetFillColorWithColor(ctx, UIColor.whiteColor.CGColor); CGContextFillRect(ctx, rect); [localScreenshot drawInRect:rect]; }]; UIImage *screenshot = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); NSData *data = UIImagePNGRepresentation(screenshot); [self.delegate setScreenshot:data]; self.report.isfullScreenEnabled = YES; [m_localScreenshots removeAllObjects]; [m_readyForScreenshotControllers removeAllObjects]; } } } // Get dashboard settings dictionary - (NSDictionary *) configurationForDataViewController: (id<MADataViewControllerProtocol>) controller { return [self.delegate configurationForDataViewController:controller]; } // Get saved dashboard data view controller settings - (NSData *) stateForDataViewController: (id<MADataViewControllerProtocol>) controller { return [self.delegate stateForDataViewController:controller]; } // Save dashboard data view controller settings - (void) setState: (NSData *) state forDataViewController: (id<MADataViewControllerProtocol>) controller { [self.delegate setState:state forDataViewController:controller]; } // Inform that data view controller changed data sample - (void) dataViewControllerChangedSelection:(id<MADataViewControllerProtocol>)controller { [self.delegate dataViewControllerChangedSelection:controller]; } // Refresh dashboard title - (void) dataViewControllerReloadTitle:(id<MADataViewControllerProtocol>)controller { m_splitViewController.splitView.titleView.titleLabel.text = self.reportTitle; } // Return dashboard title - (NSString *)reportTitle { if (!m_report.fullScreenBlockKey) { return self.delegate.title; } else { NSString *title = [m_report.dataViewsTitles objectForKey:m_report.fullScreenBlockKey]; if (title) { return title; } else { id<MADataViewControllerProtocol>dataView = [m_report.dataViews objectForKey:m_report.fullScreenBlockKey]; return dataView.dataViewTitle; } } } @end
Replace the body of the addDimensionPanelControlWithKey:syncIndexKey: method in the MADashboardReportViewControllerDelegateImpl class with the following code:
// Determine dimension key int64 dimensionKey = -1; // Determine array of observer dimensions NSMutableArray *listenerKeys = [NSMutableArray array]; // Get dimension key and array of observer dimension keys N_FOREACH(SPPLDashboardSynchronizationDimension, i, m_dashboardReport->synchronizationDimensions()->dimensions()) { SPPLDashboardDataSourceDimensionObject dimensionObject = i->dimensionObject(); if (i->syncIndexKey() == syncIndexKey && dimensionObject->isOriginal()) { dimensionKey = dimensionObject->key(); [listenerKeys addObject:dimensionObject->dataSourceObject()->dashboardRelatedId()->nsString()]; } } // Creates an object describing dashboard control [self addDimensionPanelControlWithKey:key dimensionKey:dimensionKey listenerKeys:listenerKeys];
Replace the code of the createReport:metabase: method in the MADashboardReportViewControllerFactory.m file with the following code:
// Create a controller delegate for working with dashboard MADashboardReportDelegateImpl *delegate = [[[MADashboardReportDelegateImpl alloc] initWithDashboardReport:dashboardReport metabase:metabase] autorelease]; // Create a dashboard based on delegate MADashboardReportViewController *report = [[[MADashboardReportViewController alloc] initWithDelegate:delegate] autorelease]; // Set dimension panel report.panelViewController.contentViewController = delegate.dimensionsPanel; return report;
After executing the example the dashboard loading indicator is displayed:
A modal window with a message is displayed against the shaded background in three seconds:
The development environment console also displays information about dashboard:
Modal window message: Loading
The dashboard loading indicator and the message window are hidden in three seconds, after that the mailing window is displayed:
See also: