Logo Search packages:      
Sourcecode: adun.app version File versions  Download package

ULAnalyserPluginExtensions.m

#include "ULAnalyser.h"

@implementation ULAnalyser (ULAnalyserPluginExtensions)

- (void) updateAvailablePlugins
{
      NSArray* availablePlugins;

      availablePlugins = [analysisManager pluginsForCurrentInputs];
      [pluginList removeAllItems];
      [pluginList addItemsWithTitles: availablePlugins];
      //If the last selected plugin is still in the list select
      //it. Otherwise select the first available one.
      //If there are no available plugins we show "None".

      NSDebugLLog(@"ULAnalyser", @"Available plugins %@", availablePlugins);
      
      if([availablePlugins containsObject: selectedPlugin])
            [pluginList selectItemWithTitle: selectedPlugin];
      else if([availablePlugins count] == 0)
      {
            [selectedPlugin release];
            selectedPlugin = ;
            [pluginList addItemWithTitle: @"None"];
            [pluginList selectItemWithTitle: selectedPlugin];
      }
      else
      {
            [pluginList selectItemAtIndex: 0];
            [selectedPlugin release];
            selectedPlugin = [pluginList titleOfSelectedItem];
            [selectedPlugin retain];
      }     
}

/******************

Displaying Plugin Options

******************/

- (void) updatePluginOptions
{
      [self displayOptionsForPlugin];
}

- (void) pluginChanged: (id) sender
{
      NSDebugLLog(@"ULAnalyser", @"Plugin changed to %@", 
                   [pluginList titleOfSelectedItem]);

      if(![selectedPlugin isEqual: [pluginList titleOfSelectedItem]])
      {
            [selectedPlugin release];
            selectedPlugin = [[pluginList titleOfSelectedItem] retain];
            [self displayOptionsForPlugin];
      }
}

- (void) displayOptionsForPlugin
{
      if([analysisManager containsInputObjects] == YES && 
            ![[pluginList titleOfSelectedItem] isEqual: @"None"])
      {
            [currentOptions release];
            NS_DURING
            {
                  currentOptions = [analysisManager optionsForPlugin: 
                                    [pluginList titleOfSelectedItem]];
            }
            NS_HANDLER
            {
                  NSRunAlertPanel(@"Alert",
                        [localException reason],
                        @"Dismiss", 
                        nil,
                  nil);
            }
            NS_ENDHANDLER

            NSDebugLLog(@"ULAnalyser", @"New options %@", currentOptions);

            [currentOptions retain];
            [outlineDelegate release];
            outlineDelegate  = [[ULOutlineViewDelegate alloc]
                              initWithOptions: currentOptions];
            [optionsView setDataSource: outlineDelegate];
            [optionsView setDelegate: outlineDelegate];
            [optionsView reloadData];
      }
      else if([[pluginList titleOfSelectedItem] isEqual: @"None"])
      {
            [currentOptions release];
            currentOptions = nil;
            [outlineDelegate release];
            outlineDelegate  = [[ULOutlineViewDelegate alloc]
                              initWithOptions: currentOptions];
            [optionsView setDataSource: outlineDelegate];
            [optionsView setDelegate: outlineDelegate];
            [optionsView reloadData];
      }
}


/***************

Applying the current plugin

****************/

- (void) _forwardPluginNotification: (NSNotification*) aNotification
{
      NSNotification* newNotification;

      if([aNotification object] != self)
      {
            /*
             * Sequenece of events here deserves explanation. The thing to 
             * remember is the progress panel object and this object 
             * i.e. ULAnalyser are accessible from both threads.
             * 1) The thread applying the current plugin receives a notification 
             * and this method is called (in that thread) since we registered for it
             * in the method below - N.B Notifications are always delivered in 
             * the thread they are sentry.
             * 2) We want the progress panel to get this notification - or one like it 
             * - but from the main thread NOT from this thread. This is because 
             * the gui is not thread safe.
             * 3) We stop the progress panel getting this exact notification by setting
             * it to look for a different notifcation object i.e. The object of this 
             * notification is nil while the object the progress panel needs is this one.
             * 4) We create a new notification with the same name but with self as the object
             * 5) We post the notification on the main thread using 
             * performSelectorOnMainThread:withObject:waitUntilDone:
             * 6) The progress panel recieves the notification from the main thread. 
             * However there is one last twist. 
             * 7) Since below we registered this object for the same notification name 
             * with a nil object this method will get called again but this time on 
             * the main thread! We dont want to get caught in an infinite loop so the "if"
             * statement above identifies if this is the original notification or the new one.
             */

            newNotification = [NSNotification notificationWithName: [aNotification name]
                  object: self
                  userInfo: [aNotification userInfo]];

            [[NSNotificationCenter defaultCenter]
                  performSelectorOnMainThread: @selector(postNotification:)
                  withObject: newNotification
                  waitUntilDone: NO];
      }
}

- (void) _threadedApplyCurrentPlugin
{
      NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
      id holder;

      [[NSNotificationCenter defaultCenter] addObserver: self
            selector: @selector(_forwardPluginNotification:)
            name: @"ULAnalysisPluginDidCompleteStepNotification"
            object: nil];

      NS_DURING
      {
            holder = pluginResults;
            pluginResults = [analysisManager applyPlugin: [pluginList titleOfSelectedItem]
                              withOptions: currentOptions];
            [pluginResults retain];
            [holder release];

            NSDebugLLog(@"ULAnalyser", @"Plugin analysis completed");

            [progressPanel performSelectorOnMainThread: @selector(setProgressInfo:)
                  withObject: @"Complete"
                  waitUntilDone: NO];
            [progressPanel performSelectorOnMainThread: @selector(setProgressBarValue:)
                  withObject: [NSNumber numberWithDouble: 100.0]
                  waitUntilDone: YES];
            sleep(1);
            [progressPanel performSelectorOnMainThread: @selector(endPanel)
                  withObject: nil
                  waitUntilDone: NO];

            [[NSNotificationCenter defaultCenter] removeObserver: self
                  name: @"ULAnalysisPluginDidCompleteStepNotification"
                  object: nil];
      }
      NS_HANDLER
      {
            NSWarnLog(@"Caught plugin exception %@, %@, %@", 
                  [localException name], 
                  [localException reason],
                  [localException userInfo]);   
            [self performSelectorOnMainThread: @selector(handleThreadError:)
                  withObject: localException 
                  waitUntilDone: YES];
            [progressPanel performSelectorOnMainThread: @selector(endPanel)
                  withObject: nil
                  waitUntilDone: NO];
      }     
      NS_ENDHANDLER

      [pool release];
      [NSThread exit];
}

- (void) applyCurrentPlugin: (id) sender
{
      NSString* pluginString;
      id holder, anArray;

      //We dont thread energy converter since its very fast.
      if([[pluginList titleOfSelectedItem] isEqual: @"EnergyConverter"])
      {
            holder = pluginResults;
            pluginResults = [analysisManager applyPlugin: @"EnergyConverter"
                              withOptions: currentOptions];
            [pluginResults retain];
            [holder release];
      }
      else if([[pluginList titleOfSelectedItem] isEqual: @"None"])
      {
            NSRunAlertPanel(@"Alert",
                  @"No plugin has been selected",
                  @"Dismiss",
                  nil,
                  nil);
      }
      else
      {
            progressPanel = [ULProgressPanel progressPanelWithTitle: @"Progress Panel"
                              message: @"Processing"
                              progressInfo: @"Applying Plugin ..."];
            [progressPanel setPanelTitle: [NSString stringWithFormat:
                                     @"Progress - %@", [pluginList titleOfSelectedItem]]];
            [progressPanel setProgressBarValue: [NSNumber numberWithDouble: 0.0]];
            [progressPanel updateStatusOnNotification: @"ULAnalysisPluginDidCompleteStepNotification"
                  fromObject: self];

            //detach the thread and wait

            threadError = NO;
            [NSThread detachNewThreadSelector: @selector(_threadedApplyCurrentPlugin)
                  toTarget: self
                  withObject: nil];

            [progressPanel runProgressPanel: YES];

            //check if there were errors
            //If there was an error pluginResults will either be the same
            //as before or nil. If there was no error we check the returned
            //object is valid.
            if(!threadError)
            {
                  //plugin results is retained in the thread above
                  if(![pluginResults isKindOfClass: [NSDictionary class]])
                  {
                        NSRunAlertPanel(@"Alert",
                              @"Plugin returned invalid object",
                              @"Dismiss",
                              nil,
                              nil);
                        
                        [pluginResults release];
                        pluginResults = nil;
                  }
            }     

            [progressPanel removeStatusNotification: @"ULAnalysisPluginDidCompleteStepNotification"
                  fromObject: self];
      }

      pluginString = [pluginResults objectForKey: @"ULAnalysisPluginString"];
      if((anArray = [pluginResults objectForKey: @"ULAnalysisPluginDataSets"]) != nil)
      {
            //populate the data set list with names
            [pluginDataSets release];
            pluginDataSets = [anArray retain];
            [self setAvailableDataSets: pluginDataSets];
            //set the selectedDataSet to be the first one returned
            [selectedDataSet release];
            selectedDataSet = [pluginDataSets objectAtIndex: 0];
            [selectedDataSet retain];
      }     
      else
      {
            [selectedDataSet release];
            [pluginDataSets release];
            selectedDataSet = nil;
            pluginDataSets = nil;
            [self setAvailableDataSets: pluginDataSets];
      }     

      //display the selectedDataSet if there is one
      if(selectedDataSet != nil)
      {
            [dataView setDataSet: selectedDataSet];
            [dataView displayData];
      }
      else
            [dataView clearDataSet];

      if(pluginString != nil)
            [self logString: [NSString stringWithFormat: 
                  @"Analysis Plugin - %@.\n\n%@", 
                  [pluginList titleOfSelectedItem], 
                  pluginString]];
}


//FIXME: Deprecated - Use export on the selected object instead.
//Model object should have a method "outputRepresentations"
//and "representationForType" so they can advertise
//how they can be output
- (void) outputPluginResults: (id) sender
{
      NSFileManager* defaultManager;
      NSString* saveFile, *resultsFile;
      NSSavePanel * savePanel;
      int result;

      if(selectedDataSet != nil)
      {
            savePanel = [NSSavePanel savePanel];
            [savePanel setTitle: @"Export Results"];
            [savePanel setDirectory: [[ULIOManager appIOManager] applicationDir]];
            result = [savePanel runModal];

            if(result == NSOKButton)
            {
                  defaultManager = [NSFileManager defaultManager];
                  saveFile = [savePanel filename];
            
                  if([defaultManager fileExistsAtPath: saveFile])
                        [defaultManager removeFileAtPath: saveFile
                              handler: nil];

                  resultsFile = [[[ULIOManager appIOManager] applicationDir] 
                              stringByAppendingPathComponent:@"Results"];
                  if(![[NSFileManager defaultManager] copyPath: resultsFile
                        toPath: saveFile
                        handler: nil])
                  {
                        NSRunAlertPanel(@"Error", 
                              @"Couldn't output results\n Check you have write permission to the\
 chosen location",
                              @"Dismiss", 
                              nil, 
                              nil);
                  }
            }
      }
      else
            NSRunAlertPanel(@"Alert", 
                  @"There are no results to output",
                  @"Dismiss", 
                  nil, 
                  nil);
}

@end


Generated by  Doxygen 1.6.0   Back to index