summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
Diffstat (limited to 'chrome')
-rw-r--r--chrome/browser/cocoa/task_manager_mac.h5
-rw-r--r--chrome/browser/cocoa/task_manager_mac.mm62
-rw-r--r--chrome/browser/cocoa/task_manager_mac_unittest.mm34
-rw-r--r--chrome/browser/task_manager.h2
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();