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
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user