OLD | NEW |
---|---|
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" |
11 #include "chrome/browser/chooser_controller/chooser_controller.h" | 11 #include "chrome/browser/chooser_controller/chooser_controller.h" |
12 #import "chrome/browser/ui/cocoa/constrained_window/constrained_window_button.h" | 12 #import "chrome/browser/ui/cocoa/constrained_window/constrained_window_button.h" |
13 #include "chrome/browser/ui/cocoa/spinner_view.h" | 13 #include "chrome/browser/ui/cocoa/spinner_view.h" |
14 #include "chrome/grit/generated_resources.h" | 14 #include "chrome/grit/generated_resources.h" |
15 #include "grit/ui_resources.h" | |
15 #import "third_party/google_toolbox_for_mac/src/AppKit/GTMUILocalizerAndLayoutTw eaker.h" | 16 #import "third_party/google_toolbox_for_mac/src/AppKit/GTMUILocalizerAndLayoutTw eaker.h" |
16 #import "ui/base/cocoa/controls/hyperlink_button_cell.h" | 17 #import "ui/base/cocoa/controls/hyperlink_button_cell.h" |
17 #include "ui/base/l10n/l10n_util_mac.h" | 18 #include "ui/base/l10n/l10n_util_mac.h" |
19 #include "ui/base/resource/resource_bundle.h" | |
18 | 20 |
19 namespace { | 21 namespace { |
20 | 22 |
21 // Chooser width. | 23 // Chooser width. |
22 const CGFloat kChooserWidth = 350.0f; | 24 const CGFloat kChooserWidth = 350.0f; |
23 | 25 |
24 // Chooser height. | 26 // Chooser height. |
25 const CGFloat kChooserHeight = 300.0f; | 27 const CGFloat kChooserHeight = 300.0f; |
26 | 28 |
29 // Signal strength level image size. | |
30 const CGFloat kSignalStrengthLevelImageSize = 20.0f; | |
31 | |
32 // Table row view height. | |
33 const CGFloat kTableRowViewHeight = 23.0f; | |
34 | |
27 // Spinner size. | 35 // Spinner size. |
28 const CGFloat kSpinnerSize = 24.0f; | 36 const CGFloat kSpinnerSize = 24.0f; |
29 | 37 |
30 // Distance between the chooser border and the view that is closest to the | 38 // Distance between the chooser border and the view that is closest to the |
31 // border. | 39 // border. |
32 const CGFloat kMarginX = 20.0f; | 40 const CGFloat kMarginX = 20.0f; |
33 const CGFloat kMarginY = 20.0f; | 41 const CGFloat kMarginY = 20.0f; |
34 | 42 |
35 // Distance between two views inside the chooser. | 43 // Distance between two views inside the chooser. |
36 const CGFloat kHorizontalPadding = 10.0f; | 44 const CGFloat kHorizontalPadding = 10.0f; |
37 const CGFloat kVerticalPadding = 10.0f; | 45 const CGFloat kVerticalPadding = 10.0f; |
38 | 46 |
39 // Separator alpha value. | 47 // Separator alpha value. |
40 const CGFloat kSeparatorAlphaValue = 0.6f; | 48 const CGFloat kSeparatorAlphaValue = 0.6f; |
41 | 49 |
42 // Separator height. | 50 // Separator height. |
43 const CGFloat kSeparatorHeight = 1.0f; | 51 const CGFloat kSeparatorHeight = 1.0f; |
44 | 52 |
53 // The lookup table for signal strength level image. | |
54 const int kSignalStrengthLevelImageIds[5] = {IDR_SIGNAL_0_BAR, IDR_SIGNAL_1_BAR, | |
55 IDR_SIGNAL_2_BAR, IDR_SIGNAL_3_BAR, | |
56 IDR_SIGNAL_4_BAR}; | |
57 | |
45 } // namespace | 58 } // namespace |
46 | 59 |
60 // A table row view that contains one line of text, and optionally contains an | |
61 // image in front of the text. | |
62 @interface TableRowView : NSView { | |
Robert Sesek
2016/08/24 18:47:37
Since ObjC is a flat, global namespace, I'd make t
juncai
2016/08/25 00:59:17
Done.
| |
63 @private | |
64 base::scoped_nsobject<NSImageView> image_; | |
65 base::scoped_nsobject<NSTextField> text_; | |
66 } | |
67 | |
68 // Designated initializer. | |
69 - (instancetype)initWithText:(NSString*)text | |
70 signalStrengthLevel:(NSInteger)level; | |
71 | |
72 // Gets the image in front of the text. | |
73 - (NSImageView*)image; | |
74 | |
75 // Gets the text. | |
76 - (NSTextField*)text; | |
77 | |
78 @end | |
79 | |
80 @implementation TableRowView | |
81 | |
82 - (instancetype)initWithText:(NSString*)text | |
83 signalStrengthLevel:(NSInteger)level { | |
84 if ((self = [super initWithFrame:NSZeroRect])) { | |
85 if (level != -1) { | |
86 DCHECK_GE(level, 0); | |
87 DCHECK_LT(level, base::checked_cast<NSInteger>( | |
88 arraysize(kSignalStrengthLevelImageIds))); | |
89 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); | |
90 NSImage* signalStrengthLevelImage = | |
91 rb.GetNativeImageNamed(kSignalStrengthLevelImageIds[level]) | |
92 .ToNSImage(); | |
93 | |
94 image_.reset([[NSImageView alloc] | |
95 initWithFrame:NSMakeRect(0, (kTableRowViewHeight - | |
96 kSignalStrengthLevelImageSize) / | |
97 2, | |
98 kSignalStrengthLevelImageSize, | |
99 kSignalStrengthLevelImageSize)]); | |
100 [image_ setImage:signalStrengthLevelImage]; | |
101 [self addSubview:image_]; | |
102 } | |
103 | |
104 text_.reset([[NSTextField alloc] initWithFrame:NSZeroRect]); | |
105 [text_ setDrawsBackground:NO]; | |
106 [text_ setBezeled:NO]; | |
107 [text_ setEditable:NO]; | |
108 [text_ setSelectable:NO]; | |
109 [text_ setStringValue:text]; | |
110 [text_ setFont:[NSFont systemFontOfSize:[NSFont systemFontSize]]]; | |
111 [text_ sizeToFit]; | |
112 CGFloat textHeight = NSHeight([text_ frame]); | |
113 [text_ setFrameOrigin:NSMakePoint( | |
114 level == -1 ? 0 : kSignalStrengthLevelImageSize + | |
115 kHorizontalPadding, | |
116 (kTableRowViewHeight - textHeight) / 2)]; | |
117 [self addSubview:text_]; | |
118 } | |
119 | |
120 return self; | |
121 } | |
122 | |
123 - (NSImageView*)image { | |
124 return image_.get(); | |
125 } | |
126 | |
127 - (NSTextField*)text { | |
128 return text_.get(); | |
129 } | |
130 | |
131 @end | |
132 | |
47 class ChooserContentViewController : public ChooserController::View { | 133 class ChooserContentViewController : public ChooserController::View { |
48 public: | 134 public: |
49 ChooserContentViewController(ChooserContentViewCocoa* chooser_content_view, | 135 ChooserContentViewController(ChooserContentViewCocoa* chooser_content_view, |
50 ChooserController* chooser_controller, | 136 ChooserController* chooser_controller, |
51 NSTableView* table_view, | 137 NSTableView* table_view, |
52 SpinnerView* spinner, | 138 SpinnerView* spinner, |
53 NSTextField* status, | 139 NSTextField* status, |
54 NSButton* rescan_button); | 140 NSButton* rescan_button); |
55 ~ChooserContentViewController() override; | 141 ~ChooserContentViewController() override; |
56 | 142 |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
168 // When refreshing, show |status_| and hide |rescan_button_|. | 254 // When refreshing, show |status_| and hide |rescan_button_|. |
169 // When complete, show |rescan_button_| and hide |status_|. | 255 // When complete, show |rescan_button_| and hide |status_|. |
170 [status_ setHidden:refreshing ? NO : YES]; | 256 [status_ setHidden:refreshing ? NO : YES]; |
171 [rescan_button_ setHidden:refreshing ? YES : NO]; | 257 [rescan_button_ setHidden:refreshing ? YES : NO]; |
172 | 258 |
173 [chooser_content_view_ updateView]; | 259 [chooser_content_view_ updateView]; |
174 } | 260 } |
175 | 261 |
176 void ChooserContentViewController::UpdateTableView() { | 262 void ChooserContentViewController::UpdateTableView() { |
177 [table_view_ setEnabled:chooser_controller_->NumOptions() > 0]; | 263 [table_view_ setEnabled:chooser_controller_->NumOptions() > 0]; |
264 // For NSView-based table views, calling reloadData will deselect the | |
265 // currently selected row, so |selected_row| stores the currently selected | |
266 // row in order to select it again. | |
267 NSInteger selected_row = [table_view_ selectedRow]; | |
178 [table_view_ reloadData]; | 268 [table_view_ reloadData]; |
269 if (selected_row != -1) { | |
270 [table_view_ selectRowIndexes:[NSIndexSet indexSetWithIndex:selected_row] | |
271 byExtendingSelection:NO]; | |
272 } | |
179 } | 273 } |
180 | 274 |
181 @implementation ChooserContentViewCocoa | 275 @implementation ChooserContentViewCocoa |
182 | 276 |
183 // TODO(juncai): restructure this function to be some smaller methods to | 277 // TODO(juncai): restructure this function to be some smaller methods to |
184 // create the pieces for the view. By doing so, the methods that calculate | 278 // create the pieces for the view. By doing so, the methods that calculate |
185 // the frame and origins can be moved into those methods, rather than as | 279 // the frame and origins can be moved into those methods, rather than as |
186 // helper functions. | 280 // helper functions. |
187 - (instancetype)initWithChooserTitle:(NSString*)chooserTitle | 281 - (instancetype)initWithChooserTitle:(NSString*)chooserTitle |
188 chooserController: | 282 chooserController: |
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
388 [titleView setEditable:NO]; | 482 [titleView setEditable:NO]; |
389 [titleView setSelectable:NO]; | 483 [titleView setSelectable:NO]; |
390 [titleView setStringValue:title]; | 484 [titleView setStringValue:title]; |
391 [titleView setFont:[NSFont systemFontOfSize:[NSFont systemFontSize]]]; | 485 [titleView setFont:[NSFont systemFontOfSize:[NSFont systemFontSize]]]; |
392 // The height is arbitrary as it will be adjusted later. | 486 // The height is arbitrary as it will be adjusted later. |
393 [titleView setFrameSize:NSMakeSize(kChooserWidth - 2 * kMarginX, 0.0f)]; | 487 [titleView setFrameSize:NSMakeSize(kChooserWidth - 2 * kMarginX, 0.0f)]; |
394 [GTMUILocalizerAndLayoutTweaker sizeToFitFixedWidthTextField:titleView]; | 488 [GTMUILocalizerAndLayoutTweaker sizeToFitFixedWidthTextField:titleView]; |
395 return titleView; | 489 return titleView; |
396 } | 490 } |
397 | 491 |
492 - (NSView*)createTableRowView:(NSInteger)rowIndex { | |
493 NSInteger level = -1; | |
494 size_t numOptions = chooserController_->NumOptions(); | |
495 if (chooserController_->ShouldShowIconBeforeText() && numOptions > 0) { | |
496 DCHECK_GE(rowIndex, 0); | |
497 DCHECK_LT(rowIndex, base::checked_cast<NSInteger>(numOptions)); | |
498 level = base::checked_cast<NSInteger>( | |
499 chooserController_->GetSignalStrengthLevel( | |
500 base::checked_cast<size_t>(rowIndex))); | |
501 } | |
502 | |
503 base::scoped_nsobject<TableRowView> tableRowView([[TableRowView alloc] | |
504 initWithText:[self optionAtIndex:rowIndex] | |
505 signalStrengthLevel:level]); | |
506 return tableRowView.autorelease(); | |
507 } | |
508 | |
509 - (CGFloat)tableRowViewHeight:(NSInteger)row { | |
510 return kTableRowViewHeight; | |
511 } | |
512 | |
398 - (base::scoped_nsobject<NSButton>)createButtonWithTitle:(NSString*)title { | 513 - (base::scoped_nsobject<NSButton>)createButtonWithTitle:(NSString*)title { |
399 base::scoped_nsobject<NSButton> button( | 514 base::scoped_nsobject<NSButton> button( |
400 [[ConstrainedWindowButton alloc] initWithFrame:NSZeroRect]); | 515 [[ConstrainedWindowButton alloc] initWithFrame:NSZeroRect]); |
401 [button setButtonType:NSMomentaryPushInButton]; | 516 [button setButtonType:NSMomentaryPushInButton]; |
402 [button setTitle:title]; | 517 [button setTitle:title]; |
403 [button sizeToFit]; | 518 [button sizeToFit]; |
404 return button; | 519 return button; |
405 } | 520 } |
406 | 521 |
407 - (base::scoped_nsobject<NSButton>)createConnectButton { | 522 - (base::scoped_nsobject<NSButton>)createConnectButton { |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
529 return helpButton_.get(); | 644 return helpButton_.get(); |
530 } | 645 } |
531 | 646 |
532 - (NSInteger)numberOfOptions { | 647 - (NSInteger)numberOfOptions { |
533 // When there are no devices, the table contains a message saying there are | 648 // When there are no devices, the table contains a message saying there are |
534 // no devices, so the number of rows is always at least 1. | 649 // no devices, so the number of rows is always at least 1. |
535 return std::max(static_cast<NSInteger>(chooserController_->NumOptions()), | 650 return std::max(static_cast<NSInteger>(chooserController_->NumOptions()), |
536 static_cast<NSInteger>(1)); | 651 static_cast<NSInteger>(1)); |
537 } | 652 } |
538 | 653 |
654 // When this function is called with numOptions == 0, it is to show the | |
655 // message saying there are no devices. | |
539 - (NSString*)optionAtIndex:(NSInteger)index { | 656 - (NSString*)optionAtIndex:(NSInteger)index { |
540 NSInteger numOptions = | 657 NSInteger numOptions = |
541 static_cast<NSInteger>(chooserController_->NumOptions()); | 658 static_cast<NSInteger>(chooserController_->NumOptions()); |
542 if (numOptions == 0) { | 659 if (numOptions == 0) { |
543 DCHECK_EQ(0, index); | 660 DCHECK_EQ(0, index); |
544 return base::SysUTF16ToNSString(chooserController_->GetNoOptionsText()); | 661 return base::SysUTF16ToNSString(chooserController_->GetNoOptionsText()); |
545 } | 662 } |
546 | 663 |
547 DCHECK_GE(index, 0); | 664 DCHECK_GE(index, 0); |
548 DCHECK_LT(index, numOptions); | 665 DCHECK_LT(index, numOptions); |
(...skipping 19 matching lines...) Expand all Loading... | |
568 } | 685 } |
569 | 686 |
570 - (void)onRescan:(id)sender { | 687 - (void)onRescan:(id)sender { |
571 chooserController_->RefreshOptions(); | 688 chooserController_->RefreshOptions(); |
572 } | 689 } |
573 | 690 |
574 - (void)onHelpPressed:(id)sender { | 691 - (void)onHelpPressed:(id)sender { |
575 chooserController_->OpenHelpCenterUrl(); | 692 chooserController_->OpenHelpCenterUrl(); |
576 } | 693 } |
577 | 694 |
695 - (NSImageView*)tableRowViewImage:(NSInteger)row { | |
696 TableRowView* tableRowView = | |
697 [tableView_ viewAtColumn:0 row:row makeIfNecessary:YES]; | |
698 return [tableRowView image]; | |
699 } | |
700 | |
701 - (NSTextField*)tableRowViewText:(NSInteger)row { | |
702 TableRowView* tableRowView = | |
703 [tableView_ viewAtColumn:0 row:row makeIfNecessary:YES]; | |
704 return [tableRowView text]; | |
705 } | |
706 | |
578 @end | 707 @end |
OLD | NEW |