From cda626214920eb0d6271c318a7595dd9b90dfc8a Mon Sep 17 00:00:00 2001 From: "stuart.morgan%alumni.case.edu" Date: Thu, 10 Jan 2008 23:53:22 +0000 Subject: [PATCH] Camino only - Bug 407544: Clean up event handling in the download manager. r/sr=mento git-svn-id: svn://10.0.0.236/trunk@242872 18797224-902f-48f8-a5cc-f745e15eee43 --- .../src/download/ProgressDlgController.h | 6 +- .../src/download/ProgressDlgController.mm | 138 ++++++------------ mozilla/camino/src/download/ProgressView.h | 9 -- mozilla/camino/src/download/ProgressView.mm | 89 +++-------- .../src/download/ProgressViewController.h | 12 ++ .../src/download/ProgressViewController.mm | 17 +++ 6 files changed, 97 insertions(+), 174 deletions(-) diff --git a/mozilla/camino/src/download/ProgressDlgController.h b/mozilla/camino/src/download/ProgressDlgController.h index ce8841fcd29..d6f4b4444aa 100644 --- a/mozilla/camino/src/download/ProgressDlgController.h +++ b/mozilla/camino/src/download/ProgressDlgController.h @@ -69,8 +69,7 @@ #import "CHDownloadProgressDisplay.h" #import "FileChangeWatcher.h" - -@class ProgressViewController; +#import "ProgressViewController.h"; // For DownloadSelectionBehavior enum // // interface ProgressDlgController @@ -107,6 +106,9 @@ -(IBAction)pause:(id)sender; -(IBAction)resume:(id)sender; +-(void)updateSelectionOfDownload:(ProgressViewController*)selectedDownload + withBehavior:(DownloadSelectionBehavior)behavior; + -(int)numDownloadsInProgress; -(void)clearAllDownloads; -(void)didStartDownload:(ProgressViewController*)progressDisplay; diff --git a/mozilla/camino/src/download/ProgressDlgController.mm b/mozilla/camino/src/download/ProgressDlgController.mm index cfec168aeff..1a517c9f4c7 100644 --- a/mozilla/camino/src/download/ProgressDlgController.mm +++ b/mozilla/camino/src/download/ProgressDlgController.mm @@ -59,7 +59,7 @@ static NSString* const kProgressWindowFrameSaveName = @"ProgressWindow"; -(void)rebuildViews; -(NSArray*)selectedProgressViewControllers; -(ProgressViewController*)progressViewControllerAtIndex:(unsigned)inIndex; --(void)deselectDLInstancesInArray:(NSArray*)instances; +-(void)deselectDownloads:(NSArray*)downloads; -(void)scrollIntoView:(ProgressViewController*)controller; -(void)killDownloadTimer; -(void)setupDownloadTimer; @@ -122,16 +122,6 @@ static id gSharedProgressController = nil; [mStackView setDataSource:self]; mSelectionPivotIndex = -1; - - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(DLInstanceSelected:) - name:kDownloadInstanceSelectedNotificationName - object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(DLInstanceOpened:) - name:kDownloadInstanceOpenedNotificationName - object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(cancel:) - name:kDownloadInstanceCancelledNotificationName - object:nil]; } return self; } @@ -152,7 +142,6 @@ static id gSharedProgressController = nil; -(void)dealloc { - [[NSNotificationCenter defaultCenter] removeObserver:self]; if (self == gSharedProgressController) { gSharedProgressController = nil; } @@ -177,7 +166,10 @@ static id gSharedProgressController = nil; // open all selected instances -(IBAction)open:(id)sender { - [[self selectedProgressViewControllers] makeObjectsPerformSelector:@selector(open:) withObject:sender]; + if ([self shouldAllowOpenAction]) + [[self selectedProgressViewControllers] makeObjectsPerformSelector:@selector(open:) withObject:sender]; + else + NSBeep(); } // @@ -299,83 +291,49 @@ static id gSharedProgressController = nil; [self saveProgressViewControllers]; } -// -// -DLInstanceOpened: -// -// Called when one of the ProgressView's should be opened (dbl clicked, for example). Open all of the -// selected instances with the Finder. -// --(void)DLInstanceOpened:(NSNotification*)notification +-(void)updateSelectionOfDownload:(ProgressViewController*)selectedDownload + withBehavior:(DownloadSelectionBehavior)behavior { - if ([self fileExistsForSelectedItems]) - [self open:self]; -} + int indexOfSelectedDownload = (int)[mProgressViewControllers indexOfObject:selectedDownload]; -// calculate what buttons should be enabled/disabled because the user changed the selection state --(void)DLInstanceSelected:(NSNotification*)notification -{ - // make sure the notification object is the kind we want - ProgressView* selectedView = ((ProgressView*)[notification object]); - if (![selectedView isKindOfClass:[ProgressView class]]) - return; + NSArray* currentlySelectedDownloads = [self selectedProgressViewControllers]; - ProgressViewController* selectedViewController = [selectedView controller]; - - NSArray* selectedArray = [self selectedProgressViewControllers]; - - int indexOfSelectedController = (int)[mProgressViewControllers indexOfObject:selectedViewController]; - - // check for key modifiers and select more instances if appropriate - // if its shift key, extend the selection one way or another - // if its command key, just let the selection happen wherever it is (don't mess with it here) - // if its not either clear all selections except the one that just happened - switch ([selectedView lastModifier]) - { - case kNoKey: - // deselect everything - [self deselectDLInstancesInArray:selectedArray]; - [selectedViewController setSelected:YES]; - mSelectionPivotIndex = indexOfSelectedController; + switch (behavior) { + case DownloadSelectExclusively: + [self deselectDownloads:currentlySelectedDownloads]; + [selectedDownload setSelected:YES]; + mSelectionPivotIndex = indexOfSelectedDownload; break; - case kCommandKey: - if (![selectedViewController isSelected]) - { - // if this was at the pivot index set the pivot index to -1 - if (indexOfSelectedController == mSelectionPivotIndex) - mSelectionPivotIndex = -1; + case DownloadSelectByExtending: + if (mSelectionPivotIndex == -1 || [currentlySelectedDownloads count] == 0) { + mSelectionPivotIndex = indexOfSelectedDownload; } - else - { - if ([selectedArray count] == 1) - mSelectionPivotIndex = indexOfSelectedController; - } - break; - - case kShiftKey: - if (mSelectionPivotIndex == -1) - mSelectionPivotIndex = indexOfSelectedController; - else - { - if ([selectedArray count] == 1) - mSelectionPivotIndex = indexOfSelectedController; - else - { - // deselect everything - [self deselectDLInstancesInArray:selectedArray]; - if (indexOfSelectedController <= mSelectionPivotIndex) - { - for (int i = indexOfSelectedController; i <= mSelectionPivotIndex; i++) - [(ProgressViewController*)[mProgressViewControllers objectAtIndex:i] setSelected:YES]; - } - else if (indexOfSelectedController > mSelectionPivotIndex) - { - for (int i = mSelectionPivotIndex; i <= indexOfSelectedController; i++) - [(ProgressViewController*)[mProgressViewControllers objectAtIndex:i] setSelected:YES]; - } + else { + [self deselectDownloads:currentlySelectedDownloads]; + if (indexOfSelectedDownload <= mSelectionPivotIndex) { + for (int i = indexOfSelectedDownload; i <= mSelectionPivotIndex; i++) + [(ProgressViewController*)[mProgressViewControllers objectAtIndex:i] setSelected:YES]; + } + else if (indexOfSelectedDownload > mSelectionPivotIndex) { + for (int i = mSelectionPivotIndex; i <= indexOfSelectedDownload; i++) + [(ProgressViewController*)[mProgressViewControllers objectAtIndex:i] setSelected:YES]; } } break; + + case DownloadSelectByInverting: + if ([selectedDownload isSelected]) { + // if this was at the pivot index set the pivot index to -1 + if (indexOfSelectedDownload == mSelectionPivotIndex) + mSelectionPivotIndex = -1; + } + else { + if ([currentlySelectedDownloads count] == 0) + mSelectionPivotIndex = indexOfSelectedDownload; + } + [selectedDownload setSelected:(![selectedDownload isSelected])]; + break; } } @@ -407,7 +365,7 @@ static id gSharedProgressController = nil; } // deselect everything if the shift key isn't a modifier if (!shiftKeyDown) - [self deselectDLInstancesInArray:[self selectedProgressViewControllers]]; + [self deselectDownloads:[self selectedProgressViewControllers]]; if (i == (int)[mProgressViewControllers count]) // if nothing was selected select the first item instanceToSelect = 0; @@ -439,7 +397,7 @@ static id gSharedProgressController = nil; // deselect everything if the shift key isn't a modifier if (!shiftKeyDown) - [self deselectDLInstancesInArray:[self selectedProgressViewControllers]]; + [self deselectDownloads:[self selectedProgressViewControllers]]; if (i < 0) // if nothing was selected select the first item instanceToSelect = ([mProgressViewControllers count] - 1); @@ -489,24 +447,22 @@ static id gSharedProgressController = nil; } } --(void)deselectDLInstancesInArray:(NSArray*)instances +-(void)deselectDownloads:(NSArray*)downloads { - unsigned count = [instances count]; + unsigned count = [downloads count]; for (unsigned i = 0; i < count; i++) { - [(ProgressViewController*)[instances objectAtIndex:i] setSelected:NO]; + [(ProgressViewController*)[downloads objectAtIndex:i] setSelected:NO]; } } -// return a mutable array with instance in order top-down +// Returns the currently-selected download view controllers. -(NSArray*)selectedProgressViewControllers { NSMutableArray *selectedArray = [[NSMutableArray alloc] init]; unsigned selectedCount = [mProgressViewControllers count]; for (unsigned i = 0; i < selectedCount; i++) { - if ([[mProgressViewControllers objectAtIndex:i] isSelected]) { - // insert at zero so they're in order to-down + if ([[mProgressViewControllers objectAtIndex:i] isSelected]) [selectedArray addObject:[mProgressViewControllers objectAtIndex:i]]; - } } [selectedArray autorelease]; return selectedArray; @@ -557,7 +513,7 @@ static id gSharedProgressController = nil; [self setupDownloadTimer]; // downloads should be individually selected when initiated - [self deselectDLInstancesInArray:[self selectedProgressViewControllers]]; + [self deselectDownloads:[self selectedProgressViewControllers]]; [(ProgressViewController*)progressDisplay setSelected:YES]; // make sure new download is visible diff --git a/mozilla/camino/src/download/ProgressView.h b/mozilla/camino/src/download/ProgressView.h index 3c181849ff6..fae84e994c7 100644 --- a/mozilla/camino/src/download/ProgressView.h +++ b/mozilla/camino/src/download/ProgressView.h @@ -41,10 +41,6 @@ @class ProgressViewController; -extern NSString* const kDownloadInstanceSelectedNotificationName; -extern NSString* const kDownloadInstanceOpenedNotificationName; -extern NSString* const kDownloadInstanceCancelledNotificationName; - // // interface ProgressView // @@ -59,13 +55,8 @@ extern NSString* const kDownloadInstanceCancelledNotificationName; IBOutlet NSImageView* mFileIconView; ProgressViewController* mProgressController; // WEAK reference NSEvent* mFileIconMouseDownEvent; // STRONG reference - int mLastModifier; } -// returns the most recent modifier key used during the last -// click on this view --(int)lastModifier; - // get/set our owning controller, to which we maintain a weak link -(void)setController:(ProgressViewController*)controller; -(ProgressViewController*)controller; diff --git a/mozilla/camino/src/download/ProgressView.mm b/mozilla/camino/src/download/ProgressView.mm index 8a5d7a8f155..d303cddc995 100644 --- a/mozilla/camino/src/download/ProgressView.mm +++ b/mozilla/camino/src/download/ProgressView.mm @@ -41,29 +41,8 @@ #import "ProgressViewController.h" -NSString* const kDownloadInstanceSelectedNotificationName = @"DownloadInstanceSelected"; -NSString* const kDownloadInstanceOpenedNotificationName = @"DownloadInstanceOpened"; -NSString* const kDownloadInstanceCancelledNotificationName = @"DownloadInstanceCancelled"; - -@interface ProgressView(Private) - --(BOOL)isSelected; --(void)setSelected:(BOOL)inSelected; - -@end - @implementation ProgressView -- (id)initWithFrame:(NSRect)frame -{ - self = [super initWithFrame:frame]; - if (self) { - mLastModifier = kNoKey; - mProgressController = nil; - } - return self; -} - - (void)dealloc { [mFileIconMouseDownEvent release]; @@ -72,7 +51,7 @@ NSString* const kDownloadInstanceCancelledNotificationName = @"DownloadInstanceC -(void)drawRect:(NSRect)rect { - if ([self isSelected]) { + if ([mProgressController isSelected]) { [[NSColor selectedTextBackgroundColor] set]; } else { @@ -84,33 +63,25 @@ NSString* const kDownloadInstanceCancelledNotificationName = @"DownloadInstanceC -(void)mouseDown:(NSEvent*)theEvent { unsigned int mods = [theEvent modifierFlags]; - mLastModifier = kNoKey; - BOOL shouldSelect = YES; - // set mLastModifier to any relevant modifier key - if (!((mods & NSShiftKeyMask) && (mods & NSCommandKeyMask))) { - if (mods & NSShiftKeyMask) { - mLastModifier = kShiftKey; - } - else if (mods & NSCommandKeyMask) { - if ([self isSelected]) - shouldSelect = NO; - mLastModifier = kCommandKey; - } - } - [self setSelected:shouldSelect]; - [[NSNotificationCenter defaultCenter] postNotificationName:kDownloadInstanceSelectedNotificationName - object:self]; + DownloadSelectionBehavior selectionBehavior; + // Favor command behavior over shift, like most table views do + if (mods & NSCommandKeyMask) + selectionBehavior = DownloadSelectByInverting; + else if (mods & NSShiftKeyMask) + selectionBehavior = DownloadSelectByExtending; + else + selectionBehavior = DownloadSelectExclusively; + [mProgressController updateSelectionWithBehavior:selectionBehavior]; [mFileIconMouseDownEvent release]; mFileIconMouseDownEvent = nil; if ([theEvent type] == NSLeftMouseDown) { // See if it's a double-click; if so, send a notification off to the // controller which will handle it accordingly. Doing it after processing - // the modifiers allows someone to shift-dblClick and open all selected - // items in the list in one action. + // the selection change allows someone to shift-double-click and open all + // selected items in the list in one action. if ([theEvent clickCount] == 2) { - [[NSNotificationCenter defaultCenter] postNotificationName:kDownloadInstanceOpenedNotificationName - object:self]; + [mProgressController openSelectedDownloads]; } // If not, and the download isn't active, see if it's a click on the icon. else if (![mProgressController isActive]) { @@ -183,32 +154,8 @@ NSString* const kDownloadInstanceCancelledNotificationName = @"DownloadInstanceC [mProgressController remove:self]; } --(int)lastModifier -{ - return mLastModifier; -} - -- (BOOL)isSelected -{ - // make sure the controller is not nil before checking if it is selected - if (!mProgressController) - return NO; - - return [mProgressController isSelected]; -} - --(void)setSelected:(BOOL)inSelected -{ - // make sure the controller is not nil before setting its selected state - if (!mProgressController) - return; - - [mProgressController setSelected:inSelected]; -} - -(void)setController:(ProgressViewController*)controller { - // Don't retain since this view will only exist if its controller does mProgressController = controller; } @@ -220,11 +167,9 @@ NSString* const kDownloadInstanceCancelledNotificationName = @"DownloadInstanceC -(NSMenu*)menuForEvent:(NSEvent*)theEvent { // if the item is unselected, select it and deselect everything else before displaying the contextual menu - if (![self isSelected]) { - mLastModifier = kNoKey; // control is only special because it means its contextual menu time - [self setSelected:YES]; - [self display]; // change selection immediately - [[NSNotificationCenter defaultCenter] postNotificationName:kDownloadInstanceSelectedNotificationName object:self]; + if (![mProgressController isSelected]) { + [mProgressController updateSelectionWithBehavior:DownloadSelectExclusively]; + [self display]; // change visual selection immediately } return [[self controller] contextualMenu]; } @@ -236,7 +181,7 @@ NSString* const kDownloadInstanceCancelledNotificationName = @"DownloadInstanceC ([theEvent modifierFlags] & NSCommandKeyMask) != 0) && [[theEvent characters] isEqualToString:@"."]) { - [[NSNotificationCenter defaultCenter] postNotificationName:kDownloadInstanceCancelledNotificationName object:self]; + [mProgressController cancelSelectedDownloads]; return YES; } diff --git a/mozilla/camino/src/download/ProgressViewController.h b/mozilla/camino/src/download/ProgressViewController.h index 356dce8127a..56d29d428f9 100644 --- a/mozilla/camino/src/download/ProgressViewController.h +++ b/mozilla/camino/src/download/ProgressViewController.h @@ -56,6 +56,11 @@ enum { kShiftKey = 1, kCommandKey = 2 }; +typedef enum { + DownloadSelectExclusively, + DownloadSelectByInverting, + DownloadSelectByExtending +} DownloadSelectionBehavior; // Define these auto remove download pref values here // becase both ProgressViewController and ProgressDlgController @@ -129,10 +134,17 @@ const int kRemoveUponSuccessfulDownloadPrefValue = 2; -(BOOL)hasSucceeded; +// Directly sets the selection of this item (should not be called by the view). -(void)setSelected:(BOOL)inSelected; -(NSDictionary*)downloadInfoDictionary; -(NSMenu*)contextualMenu; +// Handlers for actions that are triggered by user action on a view but aren't +// specific to the view. +-(void)updateSelectionWithBehavior:(DownloadSelectionBehavior)behavior; +-(void)openSelectedDownloads; +-(void)cancelSelectedDownloads; + @end diff --git a/mozilla/camino/src/download/ProgressViewController.mm b/mozilla/camino/src/download/ProgressViewController.mm index b1d86706730..1d1cc6602d6 100644 --- a/mozilla/camino/src/download/ProgressViewController.mm +++ b/mozilla/camino/src/download/ProgressViewController.mm @@ -694,6 +694,23 @@ enum { #pragma mark - +-(void)updateSelectionWithBehavior:(DownloadSelectionBehavior)behavior +{ + [mProgressWindowController updateSelectionOfDownload:self withBehavior:behavior]; +} + +-(void)openSelectedDownloads +{ + [mProgressWindowController open:self]; +} + +-(void)cancelSelectedDownloads +{ + [mProgressWindowController cancel:self]; +} + +#pragma mark - + -(void)onStartDownload:(BOOL)isFileSave { mIsFileSave = isFileSave;