Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1014)

Side by Side Diff: chrome/browser/ui/cocoa/chooser_content_view_cocoa.mm

Issue 2518933004: Add multiple selection support to chooser on desktops (Closed)
Patch Set: address comments Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 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 #import "chrome/browser/ui/cocoa/chooser_content_view_cocoa.h" 5 #import "chrome/browser/ui/cocoa/chooser_content_view_cocoa.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/macros.h" 9 #include "base/macros.h"
10 #include "base/strings/sys_string_conversions.h" 10 #include "base/strings/sys_string_conversions.h"
(...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after
308 [table_view_ setHidden:NO]; 308 [table_view_ setHidden:NO];
309 [spinner_ setHidden:YES]; 309 [spinner_ setHidden:YES];
310 } 310 }
311 311
312 void ChooserContentViewController::OnOptionRemoved(size_t index) { 312 void ChooserContentViewController::OnOptionRemoved(size_t index) {
313 // |table_view_| will automatically select the removed item's next item. 313 // |table_view_| will automatically select the removed item's next item.
314 // So here it tracks if the removed item is the item that was currently 314 // So here it tracks if the removed item is the item that was currently
315 // selected, if so, deselect it. Also if the removed item is before the 315 // selected, if so, deselect it. Also if the removed item is before the
316 // currently selected item, the currently selected item's index needs to 316 // currently selected item, the currently selected item's index needs to
317 // be adjusted by one. 317 // be adjusted by one.
318 NSInteger idx = static_cast<NSInteger>(index); 318 NSIndexSet* selected_rows = [table_view_ selectedRowIndexes];
319 NSInteger selected_row = [table_view_ selectedRow]; 319 NSMutableIndexSet* updated_selected_rows = [NSMutableIndexSet indexSet];
320 if (selected_row == idx) { 320 NSUInteger row = [selected_rows firstIndex];
321 [table_view_ deselectRow:idx]; 321 while (row != NSNotFound) {
322 } else if (selected_row > idx) { 322 if (row < index)
323 [table_view_ 323 [updated_selected_rows addIndex:row];
324 selectRowIndexes:[NSIndexSet indexSetWithIndex:selected_row - 1] 324 else if (row > index)
325 byExtendingSelection:NO]; 325 [updated_selected_rows addIndex:row - 1];
326 row = [selected_rows indexGreaterThanIndex:row];
326 } 327 }
327 328
329 [table_view_ selectRowIndexes:updated_selected_rows byExtendingSelection:NO];
330
328 UpdateTableView(); 331 UpdateTableView();
329 } 332 }
330 333
331 void ChooserContentViewController::OnOptionUpdated(size_t index) { 334 void ChooserContentViewController::OnOptionUpdated(size_t index) {
332 UpdateTableView(); 335 UpdateTableView();
333 } 336 }
334 337
335 void ChooserContentViewController::OnAdapterEnabledChanged(bool enabled) { 338 void ChooserContentViewController::OnAdapterEnabledChanged(bool enabled) {
336 // No row is selected since the adapter status has changed. 339 // No row is selected since the adapter status has changed.
337 // This will also disable the OK button if it was enabled because 340 // This will also disable the OK button if it was enabled because
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
372 // When complete, show |word_connector_| and |rescan_button_| and hide 375 // When complete, show |word_connector_| and |rescan_button_| and hide
373 // |scanning_message_|. 376 // |scanning_message_|.
374 [scanning_message_ setHidden:refreshing ? NO : YES]; 377 [scanning_message_ setHidden:refreshing ? NO : YES];
375 [word_connector_ setHidden:refreshing ? YES : NO]; 378 [word_connector_ setHidden:refreshing ? YES : NO];
376 [rescan_button_ setHidden:refreshing ? YES : NO]; 379 [rescan_button_ setHidden:refreshing ? YES : NO];
377 } 380 }
378 381
379 void ChooserContentViewController::UpdateTableView() { 382 void ChooserContentViewController::UpdateTableView() {
380 [table_view_ setEnabled:chooser_controller_->NumOptions() > 0]; 383 [table_view_ setEnabled:chooser_controller_->NumOptions() > 0];
381 // For NSView-based table views, calling reloadData will deselect the 384 // For NSView-based table views, calling reloadData will deselect the
382 // currently selected row, so |selected_row| stores the currently selected 385 // currently selected row, so |selected_rows| stores the currently selected
383 // row in order to select it again. 386 // rows in order to select them again.
384 NSInteger selected_row = [table_view_ selectedRow]; 387 NSIndexSet* selected_rows = [table_view_ selectedRowIndexes];
385 [table_view_ reloadData]; 388 [table_view_ reloadData];
386 if (selected_row != -1) { 389 [table_view_ selectRowIndexes:selected_rows byExtendingSelection:NO];
387 [table_view_ selectRowIndexes:[NSIndexSet indexSetWithIndex:selected_row]
388 byExtendingSelection:NO];
389 }
390 } 390 }
391 391
392 @implementation ChooserContentViewCocoa 392 @implementation ChooserContentViewCocoa
393 393
394 // TODO(juncai): restructure this function to be some smaller methods to 394 // TODO(juncai): restructure this function to be some smaller methods to
395 // create the pieces for the view. By doing so, the methods that calculate 395 // create the pieces for the view. By doing so, the methods that calculate
396 // the frame and origins can be moved into those methods, rather than as 396 // the frame and origins can be moved into those methods, rather than as
397 // helper functions. 397 // helper functions.
398 - (instancetype)initWithChooserTitle:(NSString*)chooserTitle 398 - (instancetype)initWithChooserTitle:(NSString*)chooserTitle
399 chooserController: 399 chooserController:
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
493 [scrollView_ setDrawsBackground:NO]; 493 [scrollView_ setDrawsBackground:NO];
494 494
495 // TableView. 495 // TableView.
496 tableView_.reset([[NSTableView alloc] initWithFrame:NSZeroRect]); 496 tableView_.reset([[NSTableView alloc] initWithFrame:NSZeroRect]);
497 tableColumn_.reset([[NSTableColumn alloc] initWithIdentifier:@""]); 497 tableColumn_.reset([[NSTableColumn alloc] initWithIdentifier:@""]);
498 [tableColumn_ setWidth:(scrollViewWidth - kMarginX)]; 498 [tableColumn_ setWidth:(scrollViewWidth - kMarginX)];
499 [tableView_ addTableColumn:tableColumn_]; 499 [tableView_ addTableColumn:tableColumn_];
500 // Make the column title invisible. 500 // Make the column title invisible.
501 [tableView_ setHeaderView:nil]; 501 [tableView_ setHeaderView:nil];
502 [tableView_ setFocusRingType:NSFocusRingTypeNone]; 502 [tableView_ setFocusRingType:NSFocusRingTypeNone];
503 [tableView_
504 setAllowsMultipleSelection:chooserController_->AllowMultipleSelection()
505 ? YES
506 : NO];
503 507
504 // Spinner. 508 // Spinner.
505 // Set the spinner in the center of the scroll view. 509 // Set the spinner in the center of the scroll view.
506 CGFloat spinnerOriginX = 510 CGFloat spinnerOriginX =
507 scrollViewOriginX + (scrollViewWidth - kSpinnerSize) / 2; 511 scrollViewOriginX + (scrollViewWidth - kSpinnerSize) / 2;
508 CGFloat spinnerOriginY = 512 CGFloat spinnerOriginY =
509 scrollViewOriginY + (scrollViewHeight - kSpinnerSize) / 2; 513 scrollViewOriginY + (scrollViewHeight - kSpinnerSize) / 2;
510 spinner_.reset([[SpinnerView alloc] 514 spinner_.reset([[SpinnerView alloc]
511 initWithFrame:NSMakeRect(spinnerOriginX, spinnerOriginY, kSpinnerSize, 515 initWithFrame:NSMakeRect(spinnerOriginX, spinnerOriginY, kSpinnerSize,
512 kSpinnerSize)]); 516 kSpinnerSize)]);
(...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after
787 791
788 return base::SysUTF16ToNSString( 792 return base::SysUTF16ToNSString(
789 chooserController_->GetOption(static_cast<size_t>(index))); 793 chooserController_->GetOption(static_cast<size_t>(index)));
790 } 794 }
791 795
792 - (void)updateTableView { 796 - (void)updateTableView {
793 chooserContentViewController_->UpdateTableView(); 797 chooserContentViewController_->UpdateTableView();
794 } 798 }
795 799
796 - (void)accept { 800 - (void)accept {
797 chooserController_->Select([tableView_ selectedRow]); 801 NSIndexSet* selectedRows = [tableView_ selectedRowIndexes];
802 NSUInteger index = [selectedRows firstIndex];
803 std::vector<size_t> indices;
804 while (index != NSNotFound) {
805 indices.push_back(index);
806 index = [selectedRows indexGreaterThanIndex:index];
807 }
808 chooserController_->Select(indices);
798 } 809 }
799 810
800 - (void)cancel { 811 - (void)cancel {
801 chooserController_->Cancel(); 812 chooserController_->Cancel();
802 } 813 }
803 814
804 - (void)close { 815 - (void)close {
805 chooserController_->Close(); 816 chooserController_->Close();
806 } 817 }
807 818
808 - (void)onAdapterOffHelp:(id)sender { 819 - (void)onAdapterOffHelp:(id)sender {
809 chooserController_->OpenAdapterOffHelpUrl(); 820 chooserController_->OpenAdapterOffHelpUrl();
810 } 821 }
811 822
812 - (void)onRescan:(id)sender { 823 - (void)onRescan:(id)sender {
813 chooserController_->RefreshOptions(); 824 chooserController_->RefreshOptions();
814 } 825 }
815 826
816 - (void)onHelpPressed:(id)sender { 827 - (void)onHelpPressed:(id)sender {
817 chooserController_->OpenHelpCenterUrl(); 828 chooserController_->OpenHelpCenterUrl();
818 } 829 }
819 830
820 - (void)updateContentRowColor { 831 - (void)updateContentRowColor {
821 NSInteger selectedRow = [tableView_ selectedRow]; 832 NSIndexSet* selectedRows = [tableView_ selectedRowIndexes];
822 NSInteger numOptions = 833 NSInteger numOptions =
823 base::checked_cast<NSInteger>(chooserController_->NumOptions()); 834 base::checked_cast<NSInteger>(chooserController_->NumOptions());
824 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); 835 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
825 for (NSInteger rowIndex = 0; rowIndex < numOptions; ++rowIndex) { 836 for (NSInteger rowIndex = 0; rowIndex < numOptions; ++rowIndex) {
837 BOOL isSelected = [selectedRows containsIndex:rowIndex];
826 // Update the color of the text. 838 // Update the color of the text.
827 [[self tableRowViewText:rowIndex] 839 [[self tableRowViewText:rowIndex]
828 setTextColor:(rowIndex == selectedRow ? [NSColor whiteColor] 840 setTextColor:(isSelected ? [NSColor whiteColor]
829 : [NSColor blackColor])]; 841 : [NSColor blackColor])];
830 842
831 // Update the color of the image. 843 // Update the color of the image.
832 if (chooserController_->ShouldShowIconBeforeText()) { 844 if (chooserController_->ShouldShowIconBeforeText()) {
833 if (chooserController_->IsConnected(rowIndex)) { 845 if (chooserController_->IsConnected(rowIndex)) {
834 [[self tableRowViewImage:rowIndex] 846 [[self tableRowViewImage:rowIndex]
835 setImage:gfx::NSImageFromImageSkia(gfx::CreateVectorIcon( 847 setImage:gfx::NSImageFromImageSkia(gfx::CreateVectorIcon(
836 gfx::VectorIconId::BLUETOOTH_CONNECTED, 848 gfx::VectorIconId::BLUETOOTH_CONNECTED,
837 rowIndex == selectedRow ? SK_ColorWHITE 849 isSelected ? SK_ColorWHITE : gfx::kChromeIconGrey))];
838 : gfx::kChromeIconGrey))];
839 } else { 850 } else {
840 int signalStrengthLevel = 851 int signalStrengthLevel =
841 chooserController_->GetSignalStrengthLevel(rowIndex); 852 chooserController_->GetSignalStrengthLevel(rowIndex);
842 if (signalStrengthLevel != -1) { 853 if (signalStrengthLevel != -1) {
843 int imageId = 854 int imageId =
844 rowIndex == selectedRow 855 isSelected
845 ? kSignalStrengthLevelImageSelectedIds[signalStrengthLevel] 856 ? kSignalStrengthLevelImageSelectedIds[signalStrengthLevel]
846 : kSignalStrengthLevelImageIds[signalStrengthLevel]; 857 : kSignalStrengthLevelImageIds[signalStrengthLevel];
847 [[self tableRowViewImage:rowIndex] 858 [[self tableRowViewImage:rowIndex]
848 setImage:rb.GetNativeImageNamed(imageId).ToNSImage()]; 859 setImage:rb.GetNativeImageNamed(imageId).ToNSImage()];
849 } 860 }
850 } 861 }
851 } 862 }
852 863
853 // Update the color of paired status. 864 // Update the color of paired status.
854 NSTextField* pairedStatusText = [self tableRowViewPairedStatus:rowIndex]; 865 NSTextField* pairedStatusText = [self tableRowViewPairedStatus:rowIndex];
855 if (pairedStatusText) { 866 if (pairedStatusText) {
856 [pairedStatusText 867 [pairedStatusText setTextColor:(skia::SkColorToCalibratedNSColor(
857 setTextColor:(skia::SkColorToCalibratedNSColor( 868 isSelected ? gfx::kGoogleGreen300
858 rowIndex == selectedRow ? gfx::kGoogleGreen300 869 : gfx::kGoogleGreen700))];
859 : gfx::kGoogleGreen700))];
860 } 870 }
861 } 871 }
862 } 872 }
863 873
864 - (NSImageView*)tableRowViewImage:(NSInteger)row { 874 - (NSImageView*)tableRowViewImage:(NSInteger)row {
865 ChooserContentTableRowView* tableRowView = 875 ChooserContentTableRowView* tableRowView =
866 [tableView_ viewAtColumn:0 row:row makeIfNecessary:YES]; 876 [tableView_ viewAtColumn:0 row:row makeIfNecessary:YES];
867 return [tableRowView image]; 877 return [tableRowView image];
868 } 878 }
869 879
(...skipping 11 matching lines...) Expand all
881 891
882 - (void)drawRect:(NSRect)rect { 892 - (void)drawRect:(NSRect)rect {
883 [[NSColor colorWithCalibratedWhite:245.0f / 255.0f alpha:1.0f] setFill]; 893 [[NSColor colorWithCalibratedWhite:245.0f / 255.0f alpha:1.0f] setFill];
884 NSRect footnoteFrame = 894 NSRect footnoteFrame =
885 NSMakeRect(0.0f, 0.0f, kChooserWidth, separatorOriginY_); 895 NSMakeRect(0.0f, 0.0f, kChooserWidth, separatorOriginY_);
886 NSRectFill(footnoteFrame); 896 NSRectFill(footnoteFrame);
887 [super drawRect:footnoteFrame]; 897 [super drawRect:footnoteFrame];
888 } 898 }
889 899
890 @end 900 @end
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698