OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/cocoa/task_manager_mac.h" | 5 #include "chrome/browser/cocoa/task_manager_mac.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "app/l10n_util_mac.h" | 10 #include "app/l10n_util_mac.h" |
11 #include "base/mac_util.h" | 11 #include "base/mac_util.h" |
12 #include "base/sys_string_conversions.h" | 12 #include "base/sys_string_conversions.h" |
13 #include "chrome/browser/browser_process.h" | 13 #include "chrome/browser/browser_process.h" |
14 #import "chrome/browser/cocoa/window_size_autosaver.h" | 14 #import "chrome/browser/cocoa/window_size_autosaver.h" |
15 #include "chrome/common/pref_names.h" | 15 #include "chrome/common/pref_names.h" |
16 #include "grit/generated_resources.h" | 16 #include "grit/generated_resources.h" |
17 | 17 |
18 // TODO(thakis): Column sort comparator | 18 namespace { |
19 // TODO(thakis): Clicking column header doesn't sort | |
20 // TODO(thakis): Default sort column | |
21 | 19 |
22 // Width of "a" and most other letters/digits in "small" table views. | 20 // Width of "a" and most other letters/digits in "small" table views. |
23 static const int kCharWidth = 6; | 21 const int kCharWidth = 6; |
24 | 22 |
25 // Some of the strings below have spaces at the end or are missing letters, to | 23 // Some of the strings below have spaces at the end or are missing letters, to |
26 // make the columns look nicer, and to take potentially longer localized strings | 24 // make the columns look nicer, and to take potentially longer localized strings |
27 // into account. | 25 // into account. |
28 static const struct ColumnWidth { | 26 const struct ColumnWidth { |
29 int columnId; | 27 int columnId; |
30 int minWidth; | 28 int minWidth; |
31 int maxWidth; // If this is -1, 1.5*minColumWidth is used as max width. | 29 int maxWidth; // If this is -1, 1.5*minColumWidth is used as max width. |
32 } columnWidths[] = { | 30 } columnWidths[] = { |
33 // Note that arraysize includes the trailing \0. That's intended. | 31 // Note that arraysize includes the trailing \0. That's intended. |
34 { IDS_TASK_MANAGER_PAGE_COLUMN, 120, 600 }, | 32 { IDS_TASK_MANAGER_PAGE_COLUMN, 120, 600 }, |
35 { IDS_TASK_MANAGER_PHYSICAL_MEM_COLUMN, | 33 { IDS_TASK_MANAGER_PHYSICAL_MEM_COLUMN, |
36 arraysize("800 MiB") * kCharWidth, -1 }, | 34 arraysize("800 MiB") * kCharWidth, -1 }, |
37 { IDS_TASK_MANAGER_SHARED_MEM_COLUMN, | 35 { IDS_TASK_MANAGER_SHARED_MEM_COLUMN, |
38 arraysize("800 MiB") * kCharWidth, -1 }, | 36 arraysize("800 MiB") * kCharWidth, -1 }, |
39 { IDS_TASK_MANAGER_PRIVATE_MEM_COLUMN, | 37 { IDS_TASK_MANAGER_PRIVATE_MEM_COLUMN, |
40 arraysize("800 MiB") * kCharWidth, -1 }, | 38 arraysize("800 MiB") * kCharWidth, -1 }, |
41 { IDS_TASK_MANAGER_CPU_COLUMN, | 39 { IDS_TASK_MANAGER_CPU_COLUMN, |
42 arraysize("99.9") * kCharWidth, -1 }, | 40 arraysize("99.9") * kCharWidth, -1 }, |
43 { IDS_TASK_MANAGER_NET_COLUMN, | 41 { IDS_TASK_MANAGER_NET_COLUMN, |
44 arraysize("150 kiB/s") * kCharWidth, -1 }, | 42 arraysize("150 kiB/s") * kCharWidth, -1 }, |
45 { IDS_TASK_MANAGER_PROCESS_ID_COLUMN, | 43 { IDS_TASK_MANAGER_PROCESS_ID_COLUMN, |
46 arraysize("73099 ") * kCharWidth, -1 }, | 44 arraysize("73099 ") * kCharWidth, -1 }, |
47 { IDS_TASK_MANAGER_WEBCORE_IMAGE_CACHE_COLUMN, | 45 { IDS_TASK_MANAGER_WEBCORE_IMAGE_CACHE_COLUMN, |
48 arraysize("2000.0K (2000.0 live)") * kCharWidth, -1 }, | 46 arraysize("2000.0K (2000.0 live)") * kCharWidth, -1 }, |
49 { IDS_TASK_MANAGER_WEBCORE_SCRIPTS_CACHE_COLUMN, | 47 { IDS_TASK_MANAGER_WEBCORE_SCRIPTS_CACHE_COLUMN, |
50 arraysize("2000.0K (2000.0 live)") * kCharWidth, -1 }, | 48 arraysize("2000.0K (2000.0 live)") * kCharWidth, -1 }, |
51 { IDS_TASK_MANAGER_WEBCORE_CSS_CACHE_COLUMN, | 49 { IDS_TASK_MANAGER_WEBCORE_CSS_CACHE_COLUMN, |
52 arraysize("2000.0K (2000.0 live)") * kCharWidth, -1 }, | 50 arraysize("2000.0K (2000.0 live)") * kCharWidth, -1 }, |
53 { IDS_TASK_MANAGER_GOATS_TELEPORTED_COLUMN, | 51 { IDS_TASK_MANAGER_GOATS_TELEPORTED_COLUMN, |
54 arraysize("15 ") * kCharWidth, -1 }, | 52 arraysize("15 ") * kCharWidth, -1 }, |
55 }; | 53 }; |
56 | 54 |
| 55 class SortHelper { |
| 56 public: |
| 57 SortHelper(TaskManagerModel* model, NSSortDescriptor* column) |
| 58 : sort_column_([[column key] intValue]), |
| 59 ascending_([column ascending]), |
| 60 model_(model) {} |
| 61 |
| 62 bool operator()(int a, int b) { |
| 63 int cmp_result = model_->CompareValues(a, b, sort_column_ ); |
| 64 if (!ascending_) |
| 65 cmp_result = -cmp_result; |
| 66 // TODO(thakis): Do grouping like on GTK. |
| 67 return cmp_result < 0; |
| 68 } |
| 69 private: |
| 70 int sort_column_; |
| 71 bool ascending_; |
| 72 TaskManagerModel* model_; // weak; |
| 73 }; |
| 74 |
| 75 } // namespace |
| 76 |
57 @interface TaskManagerWindowController (Private) | 77 @interface TaskManagerWindowController (Private) |
58 - (NSTableColumn*)addColumnWithId:(int)columnId visible:(BOOL)isVisible; | 78 - (NSTableColumn*)addColumnWithId:(int)columnId visible:(BOOL)isVisible; |
59 - (void)setUpTableColumns; | 79 - (void)setUpTableColumns; |
60 - (void)setUpTableHeaderContextMenu; | 80 - (void)setUpTableHeaderContextMenu; |
61 - (void)toggleColumn:(id)sender; | 81 - (void)toggleColumn:(id)sender; |
62 - (void)adjustSelectionAndEndProcessButton; | 82 - (void)adjustSelectionAndEndProcessButton; |
63 @end | 83 @end |
64 | 84 |
65 //////////////////////////////////////////////////////////////////////////////// | 85 //////////////////////////////////////////////////////////////////////////////// |
66 // TaskManagerWindowController implementation: | 86 // TaskManagerWindowController implementation: |
67 | 87 |
68 @implementation TaskManagerWindowController | 88 @implementation TaskManagerWindowController |
69 | 89 |
70 - (id)initWithTaskManagerObserver:(TaskManagerMac*)taskManagerObserver { | 90 - (id)initWithTaskManagerObserver:(TaskManagerMac*)taskManagerObserver { |
71 NSString* nibpath = [mac_util::MainAppBundle() | 91 NSString* nibpath = [mac_util::MainAppBundle() |
72 pathForResource:@"TaskManager" | 92 pathForResource:@"TaskManager" |
73 ofType:@"nib"]; | 93 ofType:@"nib"]; |
74 if ((self = [super initWithWindowNibPath:nibpath owner:self])) { | 94 if ((self = [super initWithWindowNibPath:nibpath owner:self])) { |
75 taskManagerObserver_ = taskManagerObserver; | 95 taskManagerObserver_ = taskManagerObserver; |
76 taskManager_ = taskManagerObserver_->task_manager(); | 96 taskManager_ = taskManagerObserver_->task_manager(); |
77 model_ = taskManager_->model(); | 97 model_ = taskManager_->model(); |
78 | 98 |
79 if (g_browser_process && g_browser_process->local_state()) { | 99 if (g_browser_process && g_browser_process->local_state()) { |
80 size_saver_.reset([[WindowSizeAutosaver alloc] | 100 size_saver_.reset([[WindowSizeAutosaver alloc] |
81 initWithWindow:[self window] | 101 initWithWindow:[self window] |
82 prefService:g_browser_process->local_state() | 102 prefService:g_browser_process->local_state() |
83 path:prefs::kTaskManagerWindowPlacement | 103 path:prefs::kTaskManagerWindowPlacement |
84 state:kSaveWindowRect]); | 104 state:kSaveWindowRect]); |
85 } | 105 } |
86 [[self window] makeKeyAndOrderFront:self]; | 106 [self showWindow:self]; |
87 } | 107 } |
88 return self; | 108 return self; |
89 } | 109 } |
90 | 110 |
| 111 - (void)sortShuffleArray { |
| 112 indexShuffle_.resize(model_->ResourceCount()); |
| 113 for (size_t i = 0; i < indexShuffle_.size(); ++i) |
| 114 indexShuffle_[i] = i; |
| 115 |
| 116 std::sort(indexShuffle_.begin(), indexShuffle_.end(), |
| 117 SortHelper(model_, currentSortDescriptor_.get())); |
| 118 } |
| 119 |
91 - (void)reloadData { | 120 - (void)reloadData { |
| 121 [self sortShuffleArray]; |
92 [tableView_ reloadData]; | 122 [tableView_ reloadData]; |
93 [self adjustSelectionAndEndProcessButton]; | 123 [self adjustSelectionAndEndProcessButton]; |
94 } | 124 } |
95 | 125 |
96 - (IBAction)statsLinkClicked:(id)sender { | 126 - (IBAction)statsLinkClicked:(id)sender { |
97 TaskManager::GetInstance()->OpenAboutMemory(); | 127 TaskManager::GetInstance()->OpenAboutMemory(); |
98 } | 128 } |
99 | 129 |
100 - (IBAction)killSelectedProcesses:(id)sender { | 130 - (IBAction)killSelectedProcesses:(id)sender { |
101 NSIndexSet* selection = [tableView_ selectedRowIndexes]; | 131 NSIndexSet* selection = [tableView_ selectedRowIndexes]; |
102 for (NSUInteger i = [selection lastIndex]; | 132 for (NSUInteger i = [selection lastIndex]; |
103 i != NSNotFound; | 133 i != NSNotFound; |
104 i = [selection indexLessThanIndex:i]) { | 134 i = [selection indexLessThanIndex:i]) { |
105 taskManager_->KillProcess(i); | 135 taskManager_->KillProcess(i); |
106 } | 136 } |
107 } | 137 } |
108 | 138 |
109 - (void)selectDoubleClickedTab:(id)sender { | 139 - (void)selectDoubleClickedTab:(id)sender { |
110 NSInteger row = [tableView_ clickedRow]; | 140 NSInteger row = [tableView_ clickedRow]; |
111 if (row < 0) | 141 if (row < 0) |
112 return; // Happens e.g. if the table header is double-clicked. | 142 return; // Happens e.g. if the table header is double-clicked. |
113 taskManager_->ActivateProcess(row); | 143 taskManager_->ActivateProcess(row); |
114 } | 144 } |
115 | 145 |
| 146 - (NSTableView*)tableView { |
| 147 return tableView_; |
| 148 } |
| 149 |
116 - (void)awakeFromNib { | 150 - (void)awakeFromNib { |
117 [self setUpTableColumns]; | 151 [self setUpTableColumns]; |
118 [self setUpTableHeaderContextMenu]; | 152 [self setUpTableHeaderContextMenu]; |
119 [self adjustSelectionAndEndProcessButton]; | 153 [self adjustSelectionAndEndProcessButton]; |
120 | 154 |
121 [tableView_ setDoubleAction:@selector(selectDoubleClickedTab:)]; | 155 [tableView_ setDoubleAction:@selector(selectDoubleClickedTab:)]; |
122 } | 156 } |
123 | 157 |
124 // Adds a column which has the given string id as title. |isVisible| specifies | 158 // Adds a column which has the given string id as title. |isVisible| specifies |
125 // if the column is initially visible. | 159 // if the column is initially visible. |
126 - (NSTableColumn*)addColumnWithId:(int)columnId visible:(BOOL)isVisible { | 160 - (NSTableColumn*)addColumnWithId:(int)columnId visible:(BOOL)isVisible { |
127 scoped_nsobject<NSTableColumn> column([[NSTableColumn alloc] | 161 scoped_nsobject<NSTableColumn> column([[NSTableColumn alloc] |
128 initWithIdentifier:[NSNumber numberWithInt:columnId]]); | 162 initWithIdentifier:[NSNumber numberWithInt:columnId]]); |
129 | 163 |
130 NSTextAlignment textAlignment = columnId == IDS_TASK_MANAGER_PAGE_COLUMN ? | 164 NSTextAlignment textAlignment = columnId == IDS_TASK_MANAGER_PAGE_COLUMN ? |
131 NSLeftTextAlignment : NSRightTextAlignment; | 165 NSLeftTextAlignment : NSRightTextAlignment; |
132 | 166 |
133 [[column.get() headerCell] | 167 [[column.get() headerCell] |
134 setStringValue:l10n_util::GetNSStringWithFixup(columnId)]; | 168 setStringValue:l10n_util::GetNSStringWithFixup(columnId)]; |
135 [[column.get() headerCell] setAlignment:textAlignment]; | 169 [[column.get() headerCell] setAlignment:textAlignment]; |
136 [[column.get() dataCell] setAlignment:textAlignment]; | 170 [[column.get() dataCell] setAlignment:textAlignment]; |
137 | 171 |
138 NSFont* font = [NSFont systemFontOfSize:[NSFont smallSystemFontSize]]; | 172 NSFont* font = [NSFont systemFontOfSize:[NSFont smallSystemFontSize]]; |
139 [[column.get() dataCell] setFont:font]; | 173 [[column.get() dataCell] setFont:font]; |
140 | 174 |
141 [column.get() setHidden:!isVisible]; | 175 [column.get() setHidden:!isVisible]; |
142 [column.get() setEditable:NO]; | 176 [column.get() setEditable:NO]; |
143 | 177 |
| 178 // The page column should by default be sorted ascending. |
| 179 BOOL ascending = columnId == IDS_TASK_MANAGER_PAGE_COLUMN; |
| 180 |
| 181 scoped_nsobject<NSSortDescriptor> sortDescriptor([[NSSortDescriptor alloc] |
| 182 initWithKey:[NSString stringWithFormat:@"%d", columnId] |
| 183 ascending:ascending]); |
| 184 [column.get() setSortDescriptorPrototype:sortDescriptor.get()]; |
| 185 |
144 // Default values, only used in release builds if nobody notices the DCHECK | 186 // Default values, only used in release builds if nobody notices the DCHECK |
145 // during development when adding new columns. | 187 // during development when adding new columns. |
146 int minWidth = 200, maxWidth = 400; | 188 int minWidth = 200, maxWidth = 400; |
147 | 189 |
148 size_t i; | 190 size_t i; |
149 for (i = 0; i < arraysize(columnWidths); ++i) { | 191 for (i = 0; i < arraysize(columnWidths); ++i) { |
150 if (columnWidths[i].columnId == columnId) { | 192 if (columnWidths[i].columnId == columnId) { |
151 minWidth = columnWidths[i].minWidth; | 193 minWidth = columnWidths[i].minWidth; |
152 maxWidth = columnWidths[i].maxWidth; | 194 maxWidth = columnWidths[i].maxWidth; |
153 if (maxWidth < 0) | 195 if (maxWidth < 0) |
(...skipping 20 matching lines...) Expand all Loading... |
174 // |nameColumn| displays an icon for every row -- this is done by an | 216 // |nameColumn| displays an icon for every row -- this is done by an |
175 // NSButtonCell. | 217 // NSButtonCell. |
176 scoped_nsobject<NSButtonCell> nameCell( | 218 scoped_nsobject<NSButtonCell> nameCell( |
177 [[NSButtonCell alloc] initTextCell:@""]); | 219 [[NSButtonCell alloc] initTextCell:@""]); |
178 [nameCell.get() setImagePosition:NSImageLeft]; | 220 [nameCell.get() setImagePosition:NSImageLeft]; |
179 [nameCell.get() setButtonType:NSSwitchButton]; | 221 [nameCell.get() setButtonType:NSSwitchButton]; |
180 [nameCell.get() setAlignment:[[nameColumn dataCell] alignment]]; | 222 [nameCell.get() setAlignment:[[nameColumn dataCell] alignment]]; |
181 [nameCell.get() setFont:[[nameColumn dataCell] font]]; | 223 [nameCell.get() setFont:[[nameColumn dataCell] font]]; |
182 [nameColumn setDataCell:nameCell.get()]; | 224 [nameColumn setDataCell:nameCell.get()]; |
183 | 225 |
| 226 // Initially, sort on the tab name. |
| 227 [tableView_ setSortDescriptors: |
| 228 [NSArray arrayWithObject:[nameColumn sortDescriptorPrototype]]]; |
| 229 |
184 [self addColumnWithId:IDS_TASK_MANAGER_PHYSICAL_MEM_COLUMN visible:YES]; | 230 [self addColumnWithId:IDS_TASK_MANAGER_PHYSICAL_MEM_COLUMN visible:YES]; |
185 [self addColumnWithId:IDS_TASK_MANAGER_SHARED_MEM_COLUMN visible:NO]; | 231 [self addColumnWithId:IDS_TASK_MANAGER_SHARED_MEM_COLUMN visible:NO]; |
186 [self addColumnWithId:IDS_TASK_MANAGER_PRIVATE_MEM_COLUMN visible:NO]; | 232 [self addColumnWithId:IDS_TASK_MANAGER_PRIVATE_MEM_COLUMN visible:NO]; |
187 [self addColumnWithId:IDS_TASK_MANAGER_CPU_COLUMN visible:YES]; | 233 [self addColumnWithId:IDS_TASK_MANAGER_CPU_COLUMN visible:YES]; |
188 [self addColumnWithId:IDS_TASK_MANAGER_NET_COLUMN visible:YES]; | 234 [self addColumnWithId:IDS_TASK_MANAGER_NET_COLUMN visible:YES]; |
189 [self addColumnWithId:IDS_TASK_MANAGER_PROCESS_ID_COLUMN visible:NO]; | 235 [self addColumnWithId:IDS_TASK_MANAGER_PROCESS_ID_COLUMN visible:NO]; |
190 [self addColumnWithId:IDS_TASK_MANAGER_WEBCORE_IMAGE_CACHE_COLUMN | 236 [self addColumnWithId:IDS_TASK_MANAGER_WEBCORE_IMAGE_CACHE_COLUMN |
191 visible:NO]; | 237 visible:NO]; |
192 [self addColumnWithId:IDS_TASK_MANAGER_WEBCORE_SCRIPTS_CACHE_COLUMN | 238 [self addColumnWithId:IDS_TASK_MANAGER_WEBCORE_SCRIPTS_CACHE_COLUMN |
193 visible:NO]; | 239 visible:NO]; |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
253 | 299 |
254 bool enabled = [selection count] > 0 && !selectionContainsBrowserProcess; | 300 bool enabled = [selection count] > 0 && !selectionContainsBrowserProcess; |
255 [endProcessButton_ setEnabled:enabled]; | 301 [endProcessButton_ setEnabled:enabled]; |
256 } | 302 } |
257 | 303 |
258 // Table view delegate method. | 304 // Table view delegate method. |
259 - (void)tableViewSelectionIsChanging:(NSNotification*)aNotification { | 305 - (void)tableViewSelectionIsChanging:(NSNotification*)aNotification { |
260 [self adjustSelectionAndEndProcessButton]; | 306 [self adjustSelectionAndEndProcessButton]; |
261 } | 307 } |
262 | 308 |
| 309 - (void)windowWillClose:(NSNotification*)notification { |
| 310 if (taskManagerObserver_) { |
| 311 taskManagerObserver_->WindowWasClosed(); |
| 312 taskManagerObserver_ = nil; |
| 313 } |
| 314 [self autorelease]; |
| 315 } |
| 316 |
263 @end | 317 @end |
264 | 318 |
265 @implementation TaskManagerWindowController (NSTableDataSource) | 319 @implementation TaskManagerWindowController (NSTableDataSource) |
266 | 320 |
267 - (NSInteger)numberOfRowsInTableView:(NSTableView*)tableView { | 321 - (NSInteger)numberOfRowsInTableView:(NSTableView*)tableView { |
268 DCHECK(tableView == tableView_ || tableView_ == nil); | 322 DCHECK(tableView == tableView_ || tableView_ == nil); |
269 return model_->ResourceCount(); | 323 return model_->ResourceCount(); |
270 } | 324 } |
271 | 325 |
272 - (NSString*)modelTextForRow:(int)row column:(int)columnId { | 326 - (NSString*)modelTextForRow:(int)row column:(int)columnId { |
| 327 DCHECK_LT(static_cast<size_t>(row), indexShuffle_.size()); |
| 328 row = indexShuffle_[row]; |
273 switch (columnId) { | 329 switch (columnId) { |
274 case IDS_TASK_MANAGER_PAGE_COLUMN: // Process | 330 case IDS_TASK_MANAGER_PAGE_COLUMN: // Process |
275 return base::SysWideToNSString(model_->GetResourceTitle(row)); | 331 return base::SysWideToNSString(model_->GetResourceTitle(row)); |
276 | 332 |
277 case IDS_TASK_MANAGER_PRIVATE_MEM_COLUMN: // Memory | 333 case IDS_TASK_MANAGER_PRIVATE_MEM_COLUMN: // Memory |
278 if (!model_->IsResourceFirstInGroup(row)) | 334 if (!model_->IsResourceFirstInGroup(row)) |
279 return @""; | 335 return @""; |
280 return base::SysWideToNSString(model_->GetResourcePrivateMemory(row)); | 336 return base::SysWideToNSString(model_->GetResourcePrivateMemory(row)); |
281 | 337 |
282 case IDS_TASK_MANAGER_SHARED_MEM_COLUMN: // Memory | 338 case IDS_TASK_MANAGER_SHARED_MEM_COLUMN: // Memory |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
355 column:[[tableColumn identifier] intValue]]; | 411 column:[[tableColumn identifier] intValue]]; |
356 [buttonCell setTitle:title]; | 412 [buttonCell setTitle:title]; |
357 [buttonCell setImage:taskManagerObserver_->GetImageForRow(rowIndex)]; | 413 [buttonCell setImage:taskManagerObserver_->GetImageForRow(rowIndex)]; |
358 [buttonCell setRefusesFirstResponder:YES]; // Don't push in like a button. | 414 [buttonCell setRefusesFirstResponder:YES]; // Don't push in like a button. |
359 [buttonCell setHighlightsBy:NSNoCellMask]; | 415 [buttonCell setHighlightsBy:NSNoCellMask]; |
360 } | 416 } |
361 | 417 |
362 return cell; | 418 return cell; |
363 } | 419 } |
364 | 420 |
| 421 - (void) tableView:(NSTableView*)tableView |
| 422 sortDescriptorsDidChange:(NSArray*)oldDescriptors { |
| 423 NSArray* newDescriptors = [tableView sortDescriptors]; |
| 424 if ([newDescriptors count] < 1) |
| 425 return; |
| 426 |
| 427 currentSortDescriptor_.reset([[newDescriptors objectAtIndex:0] retain]); |
| 428 [self reloadData]; // Sorts. |
| 429 } |
| 430 |
365 @end | 431 @end |
366 | 432 |
367 //////////////////////////////////////////////////////////////////////////////// | 433 //////////////////////////////////////////////////////////////////////////////// |
368 // TaskManagerMac implementation: | 434 // TaskManagerMac implementation: |
369 | 435 |
370 TaskManagerMac::TaskManagerMac() | 436 TaskManagerMac::TaskManagerMac(TaskManager* task_manager) |
371 : task_manager_(TaskManager::GetInstance()), | 437 : task_manager_(task_manager), |
372 model_(TaskManager::GetInstance()->model()), | 438 model_(task_manager->model()), |
373 icon_cache_(this) { | 439 icon_cache_(this) { |
374 window_controller_ = | 440 window_controller_ = |
375 [[TaskManagerWindowController alloc] initWithTaskManagerObserver:this]; | 441 [[TaskManagerWindowController alloc] initWithTaskManagerObserver:this]; |
376 model_->AddObserver(this); | 442 model_->AddObserver(this); |
377 } | 443 } |
378 | 444 |
379 // static | 445 // static |
380 TaskManagerMac* TaskManagerMac::instance_ = NULL; | 446 TaskManagerMac* TaskManagerMac::instance_ = NULL; |
381 | 447 |
382 TaskManagerMac::~TaskManagerMac() { | 448 TaskManagerMac::~TaskManagerMac() { |
383 task_manager_->OnWindowClosed(); | 449 if (this == instance_) { |
| 450 // Do not do this when running in unit tests: |StartUpdating()| never got |
| 451 // called in that case. |
| 452 task_manager_->OnWindowClosed(); |
| 453 } |
384 model_->RemoveObserver(this); | 454 model_->RemoveObserver(this); |
385 } | 455 } |
386 | 456 |
387 //////////////////////////////////////////////////////////////////////////////// | 457 //////////////////////////////////////////////////////////////////////////////// |
388 // TaskManagerMac, TaskManagerModelObserver implementation: | 458 // TaskManagerMac, TaskManagerModelObserver implementation: |
389 | 459 |
390 void TaskManagerMac::OnModelChanged() { | 460 void TaskManagerMac::OnModelChanged() { |
391 icon_cache_.OnModelChanged(); | 461 icon_cache_.OnModelChanged(); |
392 [window_controller_ reloadData]; | 462 [window_controller_ reloadData]; |
393 } | 463 } |
(...skipping 25 matching lines...) Expand all Loading... |
419 instance_ = NULL; | 489 instance_ = NULL; |
420 } | 490 } |
421 | 491 |
422 // static | 492 // static |
423 void TaskManagerMac::Show() { | 493 void TaskManagerMac::Show() { |
424 if (instance_) { | 494 if (instance_) { |
425 // If there's a Task manager window open already, just activate it. | 495 // If there's a Task manager window open already, just activate it. |
426 [[instance_->window_controller_ window] | 496 [[instance_->window_controller_ window] |
427 makeKeyAndOrderFront:instance_->window_controller_]; | 497 makeKeyAndOrderFront:instance_->window_controller_]; |
428 } else { | 498 } else { |
429 instance_ = new TaskManagerMac; | 499 instance_ = new TaskManagerMac(TaskManager::GetInstance()); |
430 instance_->model_->StartUpdating(); | 500 instance_->model_->StartUpdating(); |
431 } | 501 } |
432 } | 502 } |
OLD | NEW |