diff options
Diffstat (limited to 'chrome')
-rw-r--r-- | chrome/browser/cocoa/task_manager_mac.h | 5 | ||||
-rw-r--r-- | chrome/browser/cocoa/task_manager_mac.mm | 62 | ||||
-rw-r--r-- | chrome/browser/cocoa/task_manager_mac_unittest.mm | 34 | ||||
-rw-r--r-- | chrome/browser/task_manager.h | 2 |
4 files changed, 88 insertions, 15 deletions
diff --git a/chrome/browser/cocoa/task_manager_mac.h b/chrome/browser/cocoa/task_manager_mac.h index 6d57f82..5f87504 100644 --- a/chrome/browser/cocoa/task_manager_mac.h +++ b/chrome/browser/cocoa/task_manager_mac.h @@ -28,9 +28,10 @@ class TaskManagerMac; scoped_nsobject<WindowSizeAutosaver> size_saver_; - // Contains a permutation of [0..|model_->ResourceCount() - 1|]. Used to + // These contain a permutation of [0..|model_->ResourceCount() - 1|]. Used to // implement sorting. - std::vector<int> indexShuffle_; + std::vector<int> viewToModelMap_; + std::vector<int> modelToViewMap_; // Descriptor of the current sort column. scoped_nsobject<NSSortDescriptor> currentSortDescriptor_; diff --git a/chrome/browser/cocoa/task_manager_mac.mm b/chrome/browser/cocoa/task_manager_mac.mm index 7fd8c1e..526be01 100644 --- a/chrome/browser/cocoa/task_manager_mac.mm +++ b/chrome/browser/cocoa/task_manager_mac.mm @@ -89,6 +89,7 @@ class SortHelper { - (void)setUpTableHeaderContextMenu; - (void)toggleColumn:(id)sender; - (void)adjustSelectionAndEndProcessButton; +- (void)deselectRows; @end //////////////////////////////////////////////////////////////////////////////// @@ -118,16 +119,41 @@ class SortHelper { } - (void)sortShuffleArray { - indexShuffle_.resize(model_->ResourceCount()); - for (size_t i = 0; i < indexShuffle_.size(); ++i) - indexShuffle_[i] = i; + viewToModelMap_.resize(model_->ResourceCount()); + for (size_t i = 0; i < viewToModelMap_.size(); ++i) + viewToModelMap_[i] = i; - std::sort(indexShuffle_.begin(), indexShuffle_.end(), + std::sort(viewToModelMap_.begin(), viewToModelMap_.end(), SortHelper(model_, currentSortDescriptor_.get())); + + modelToViewMap_.resize(viewToModelMap_.size()); + for (size_t i = 0; i < viewToModelMap_.size(); ++i) + modelToViewMap_[viewToModelMap_[i]] = i; } - (void)reloadData { + // Store old view indices, and the model indices they map to. + NSIndexSet* viewSelection = [tableView_ selectedRowIndexes]; + std::vector<int> modelSelection; + for (NSUInteger i = [viewSelection lastIndex]; + i != NSNotFound; + i = [viewSelection indexLessThanIndex:i]) { + modelSelection.push_back(viewToModelMap_[i]); + } + + // Sort. [self sortShuffleArray]; + + // Use the model indices to get the new view indices of the selection, and + // set selection to that. This assumes that no rows were added or removed + // (in that case, the selection is cleared before -reloadData is called). + if (modelSelection.size() > 0) + DCHECK_EQ([tableView_ numberOfRows], model_->ResourceCount()); + NSMutableIndexSet* indexSet = [NSMutableIndexSet indexSet]; + for (size_t i = 0; i < modelSelection.size(); ++i) + [indexSet addIndex:modelToViewMap_[modelSelection[i]]]; + [tableView_ selectRowIndexes:indexSet byExtendingSelection:NO]; + [tableView_ reloadData]; [self adjustSelectionAndEndProcessButton]; } @@ -141,7 +167,7 @@ class SortHelper { for (NSUInteger i = [selection lastIndex]; i != NSNotFound; i = [selection indexLessThanIndex:i]) { - taskManager_->KillProcess(i); + taskManager_->KillProcess(viewToModelMap_[i]); } } @@ -298,19 +324,26 @@ class SortHelper { for (NSUInteger i = [selection lastIndex]; i != NSNotFound; i = [selection indexLessThanIndex:i]) { - if (taskManager_->IsBrowserProcess(i)) + int modelIndex = viewToModelMap_[i]; + if (taskManager_->IsBrowserProcess(modelIndex)) selectionContainsBrowserProcess = true; - std::pair<int, int> rangePair = model_->GetGroupRangeForResource(i); - NSRange range = NSMakeRange(rangePair.first, rangePair.second); - NSIndexSet* rangeIndexSet = [NSIndexSet indexSetWithIndexesInRange:range]; - [tableView_ selectRowIndexes:rangeIndexSet byExtendingSelection:YES]; + std::pair<int, int> rangePair = + model_->GetGroupRangeForResource(modelIndex); + NSMutableIndexSet* indexSet = [NSMutableIndexSet indexSet]; + for (int j = 0; j < rangePair.second; ++j) + [indexSet addIndex:modelToViewMap_[rangePair.first + j]]; + [tableView_ selectRowIndexes:indexSet byExtendingSelection:YES]; } bool enabled = [selection count] > 0 && !selectionContainsBrowserProcess; [endProcessButton_ setEnabled:enabled]; } +- (void)deselectRows { + [tableView_ deselectAll:self]; +} + // Table view delegate method. - (void)tableViewSelectionIsChanging:(NSNotification*)aNotification { [self adjustSelectionAndEndProcessButton]; @@ -334,8 +367,8 @@ class SortHelper { } - (NSString*)modelTextForRow:(int)row column:(int)columnId { - DCHECK_LT(static_cast<size_t>(row), indexShuffle_.size()); - row = indexShuffle_[row]; + DCHECK_LT(static_cast<size_t>(row), viewToModelMap_.size()); + row = viewToModelMap_[row]; switch (columnId) { case IDS_TASK_MANAGER_PAGE_COLUMN: // Process return base::SysWideToNSString(model_->GetResourceTitle(row)); @@ -421,7 +454,7 @@ class SortHelper { column:[[tableColumn identifier] intValue]]; [buttonCell setTitle:title]; [buttonCell setImage: - taskManagerObserver_->GetImageForRow(indexShuffle_[rowIndex])]; + taskManagerObserver_->GetImageForRow(viewToModelMap_[rowIndex])]; [buttonCell setRefusesFirstResponder:YES]; // Don't push in like a button. [buttonCell setHighlightsBy:NSNoCellMask]; } @@ -470,6 +503,7 @@ TaskManagerMac::~TaskManagerMac() { void TaskManagerMac::OnModelChanged() { icon_cache_.OnModelChanged(); + [window_controller_ deselectRows]; [window_controller_ reloadData]; } @@ -480,11 +514,13 @@ void TaskManagerMac::OnItemsChanged(int start, int length) { void TaskManagerMac::OnItemsAdded(int start, int length) { icon_cache_.OnItemsAdded(start, length); + [window_controller_ deselectRows]; [window_controller_ reloadData]; } void TaskManagerMac::OnItemsRemoved(int start, int length) { icon_cache_.OnItemsRemoved(start, length); + [window_controller_ deselectRows]; [window_controller_ reloadData]; } diff --git a/chrome/browser/cocoa/task_manager_mac_unittest.mm b/chrome/browser/cocoa/task_manager_mac_unittest.mm index 2275e14..570fe7e 100644 --- a/chrome/browser/cocoa/task_manager_mac_unittest.mm +++ b/chrome/browser/cocoa/task_manager_mac_unittest.mm @@ -77,3 +77,37 @@ TEST_F(TaskManagerWindowControllerTest, Sort) { task_manager.RemoveResource(&resource2); task_manager.RemoveResource(&resource3); } + +TEST_F(TaskManagerWindowControllerTest, SelectionAdaptsToSorting) { + TaskManager task_manager; + + TestResource resource1(UTF8ToUTF16("yyy"), 1); + TestResource resource2(UTF8ToUTF16("aaa"), 2); + + task_manager.AddResource(&resource1); + task_manager.AddResource(&resource2); + + TaskManagerMac* bridge(new TaskManagerMac(&task_manager)); + TaskManagerWindowController* controller = bridge->cocoa_controller(); + NSTableView* table = [controller tableView]; + ASSERT_EQ(2, [controller numberOfRowsInTableView:table]); + + // Select row 0 in the table (corresponds to row 1 in the model). + [table selectRowIndexes:[NSIndexSet indexSetWithIndex:0] + byExtendingSelection:NO]; + + // Change the name of resource2 so that it becomes row 1 in the table. + resource2.title_ = UTF8ToUTF16("zzz"); + bridge->OnItemsChanged(1, 1); + + // Check that the selection has moved to row 1. + NSIndexSet* selection = [table selectedRowIndexes]; + ASSERT_EQ(1u, [selection count]); + EXPECT_EQ(1u, [selection firstIndex]); + + // Releases the controller, which in turn deletes |bridge|. + [controller close]; + + task_manager.RemoveResource(&resource1); + task_manager.RemoveResource(&resource2); +} diff --git a/chrome/browser/task_manager.h b/chrome/browser/task_manager.h index 9c84f3c..4a92582 100644 --- a/chrome/browser/task_manager.h +++ b/chrome/browser/task_manager.h @@ -151,6 +151,8 @@ class TaskManager { FRIEND_TEST_ALL_PREFIXES(TaskManagerTest, RefreshCalled); FRIEND_TEST_ALL_PREFIXES(TaskManagerWindowControllerTest, Init); FRIEND_TEST_ALL_PREFIXES(TaskManagerWindowControllerTest, Sort); + FRIEND_TEST_ALL_PREFIXES(TaskManagerWindowControllerTest, + SelectionAdaptsToSorting); // Obtain an instance via GetInstance(). TaskManager(); |