Index: chrome/browser/ui/cocoa/chooser_content_view_cocoa.mm |
diff --git a/chrome/browser/ui/cocoa/chooser_content_view_cocoa.mm b/chrome/browser/ui/cocoa/chooser_content_view_cocoa.mm |
index ba6990f50c09c09857a3e7404e918c992c21d06d..567c9fe27604ca7c9511ea5707e09a5a35b595d4 100644 |
--- a/chrome/browser/ui/cocoa/chooser_content_view_cocoa.mm |
+++ b/chrome/browser/ui/cocoa/chooser_content_view_cocoa.mm |
@@ -12,10 +12,15 @@ |
#import "chrome/browser/ui/cocoa/constrained_window/constrained_window_button.h" |
#include "chrome/browser/ui/cocoa/spinner_view.h" |
#include "chrome/grit/generated_resources.h" |
+#include "skia/ext/skia_utils_mac.h" |
#import "third_party/google_toolbox_for_mac/src/AppKit/GTMUILocalizerAndLayoutTweaker.h" |
#import "ui/base/cocoa/controls/hyperlink_button_cell.h" |
#include "ui/base/l10n/l10n_util_mac.h" |
#include "ui/base/resource/resource_bundle.h" |
+#include "ui/gfx/color_palette.h" |
+#include "ui/gfx/image/image_skia_util_mac.h" |
+#include "ui/gfx/paint_vector_icon.h" |
+#include "ui/gfx/vector_icons_public.h" |
#include "ui/resources/grit/ui_resources.h" |
namespace { |
@@ -26,11 +31,12 @@ const CGFloat kChooserWidth = 350.0f; |
// Chooser height. |
const CGFloat kChooserHeight = 300.0f; |
-// Signal strength level image size. |
-const CGFloat kSignalStrengthLevelImageSize = 20.0f; |
+// Row view image size. |
+const CGFloat kRowViewImageSize = 20.0f; |
// Table row view height. |
-const CGFloat kTableRowViewHeight = 23.0f; |
+const CGFloat kTableRowViewOneLineHeight = 23.0f; |
+const CGFloat kTableRowViewTwoLinesHeight = 39.0f; |
// Spinner size. |
const CGFloat kSpinnerSize = 24.0f; |
@@ -50,11 +56,29 @@ const CGFloat kSeparatorAlphaValue = 0.6f; |
// Separator height. |
const CGFloat kSeparatorHeight = 1.0f; |
+// Distance between two views inside the table row view. |
+const CGFloat kTableRowViewHorizontalPadding = 5.0f; |
+const CGFloat kTableRowViewVerticalPadding = 1.0f; |
+ |
// The lookup table for signal strength level image. |
const int kSignalStrengthLevelImageIds[5] = {IDR_SIGNAL_0_BAR, IDR_SIGNAL_1_BAR, |
IDR_SIGNAL_2_BAR, IDR_SIGNAL_3_BAR, |
IDR_SIGNAL_4_BAR}; |
+// Creates a label with |text|. |
+base::scoped_nsobject<NSTextField> CreateLabel(NSString* text) { |
+ base::scoped_nsobject<NSTextField> label( |
+ [[NSTextField alloc] initWithFrame:NSZeroRect]); |
+ [label setDrawsBackground:NO]; |
+ [label setBezeled:NO]; |
+ [label setEditable:NO]; |
+ [label setSelectable:NO]; |
+ [label setStringValue:text]; |
+ [label setFont:[NSFont systemFontOfSize:[NSFont systemFontSize]]]; |
+ [label sizeToFit]; |
+ return label; |
+} |
+ |
} // namespace |
// A table row view that contains one line of text, and optionally contains an |
@@ -63,11 +87,21 @@ const int kSignalStrengthLevelImageIds[5] = {IDR_SIGNAL_0_BAR, IDR_SIGNAL_1_BAR, |
@private |
base::scoped_nsobject<NSImageView> image_; |
base::scoped_nsobject<NSTextField> text_; |
+ base::scoped_nsobject<NSTextField> pairedStatus_; |
} |
// Designated initializer. |
+// This initializer is used when the chooser needs to show the no-devices-found |
+// message. |
+- (instancetype)initWithText:(NSString*)text; |
+ |
+// Designated initializer. |
- (instancetype)initWithText:(NSString*)text |
- signalStrengthLevel:(NSInteger)level; |
+ signalStrengthLevel:(NSInteger)level |
+ isConnected:(bool)isConnected |
+ isPaired:(bool)isPaired |
+ rowHeight:(CGFloat)rowHeight |
+ textNeedIndentation:(bool)textNeedIndentation; |
// Gets the image in front of the text. |
- (NSImageView*)image; |
@@ -75,46 +109,102 @@ const int kSignalStrengthLevelImageIds[5] = {IDR_SIGNAL_0_BAR, IDR_SIGNAL_1_BAR, |
// Gets the text. |
- (NSTextField*)text; |
+// Gets the paired status. |
+- (NSTextField*)pairedStatus; |
+ |
@end |
@implementation ChooserContentTableRowView |
+- (instancetype)initWithText:(NSString*)text { |
+ if ((self = [super initWithFrame:NSZeroRect])) { |
+ text_ = CreateLabel(text); |
+ CGFloat textHeight = NSHeight([text_ frame]); |
+ CGFloat textOriginX = kTableRowViewHorizontalPadding; |
+ CGFloat textOriginY = (kTableRowViewOneLineHeight - textHeight) / 2; |
+ [text_ setFrameOrigin:NSMakePoint(textOriginX, textOriginY)]; |
+ [self addSubview:text_]; |
+ } |
+ |
+ return self; |
+} |
+ |
- (instancetype)initWithText:(NSString*)text |
- signalStrengthLevel:(NSInteger)level { |
+ signalStrengthLevel:(NSInteger)level |
+ isConnected:(bool)isConnected |
+ isPaired:(bool)isPaired |
+ rowHeight:(CGFloat)rowHeight |
+ textNeedIndentation:(bool)textNeedIndentation { |
if ((self = [super initWithFrame:NSZeroRect])) { |
- if (level != -1) { |
+ // Create the views. |
+ // Image. |
+ ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); |
+ NSImage* image = nullptr; |
+ if (isConnected) { |
+ image = gfx::NSImageFromImageSkia(gfx::CreateVectorIcon( |
+ gfx::VectorIconId::BLUETOOTH_CONNECTED, gfx::kChromeIconGrey)); |
+ } else if (level != -1) { |
DCHECK_GE(level, 0); |
DCHECK_LT(level, base::checked_cast<NSInteger>( |
arraysize(kSignalStrengthLevelImageIds))); |
- ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); |
- NSImage* signalStrengthLevelImage = |
- rb.GetNativeImageNamed(kSignalStrengthLevelImageIds[level]) |
- .ToNSImage(); |
+ image = rb.GetNativeImageNamed(kSignalStrengthLevelImageIds[level]) |
+ .ToNSImage(); |
+ } |
+ CGFloat imageOriginX = kTableRowViewHorizontalPadding; |
+ CGFloat imageOriginY = (rowHeight - kRowViewImageSize) / 2; |
+ if (image) { |
image_.reset([[NSImageView alloc] |
- initWithFrame:NSMakeRect(0, (kTableRowViewHeight - |
- kSignalStrengthLevelImageSize) / |
- 2, |
- kSignalStrengthLevelImageSize, |
- kSignalStrengthLevelImageSize)]); |
- [image_ setImage:signalStrengthLevelImage]; |
+ initWithFrame:NSMakeRect(imageOriginX, imageOriginY, |
+ kRowViewImageSize, kRowViewImageSize)]); |
+ [image_ setImage:image]; |
[self addSubview:image_]; |
} |
- text_.reset([[NSTextField alloc] initWithFrame:NSZeroRect]); |
- [text_ setDrawsBackground:NO]; |
- [text_ setBezeled:NO]; |
- [text_ setEditable:NO]; |
- [text_ setSelectable:NO]; |
- [text_ setStringValue:text]; |
- [text_ setFont:[NSFont systemFontOfSize:[NSFont systemFontSize]]]; |
- [text_ sizeToFit]; |
+ // Text. |
+ text_ = CreateLabel(text); |
CGFloat textHeight = NSHeight([text_ frame]); |
- [text_ setFrameOrigin:NSMakePoint( |
- level == -1 ? 0 : kSignalStrengthLevelImageSize + |
- kHorizontalPadding, |
- (kTableRowViewHeight - textHeight) / 2)]; |
+ |
+ // Paired status. |
+ CGFloat pairedStatusHeight = 0.0f; |
+ if (isPaired) { |
+ pairedStatus_ = CreateLabel( |
+ l10n_util::GetNSString(IDS_DEVICE_CHOOSER_PAIRED_STATUS_TEXT)); |
+ [pairedStatus_ |
+ setTextColor:skia::SkColorToCalibratedNSColor(gfx::kGoogleGreen700)]; |
+ pairedStatusHeight = NSHeight([pairedStatus_ frame]); |
+ } |
+ |
+ // Lay out the views. |
+ // Text. |
+ CGFloat textOriginX = kTableRowViewHorizontalPadding; |
+ if (textNeedIndentation) |
+ textOriginX += imageOriginX + kRowViewImageSize; |
+ CGFloat textOriginY; |
+ if (isPaired) { |
+ textOriginY = pairedStatusHeight + |
+ (rowHeight - textHeight - pairedStatusHeight - |
+ kTableRowViewVerticalPadding) / |
+ 2 + |
+ kTableRowViewVerticalPadding; |
+ } else { |
+ textOriginY = (rowHeight - textHeight) / 2; |
+ } |
+ |
+ [text_ setFrameOrigin:NSMakePoint(textOriginX, textOriginY)]; |
[self addSubview:text_]; |
+ |
+ // Paired status. |
+ if (isPaired) { |
+ CGFloat pairedStatusOriginX = textOriginX; |
+ CGFloat pairedStatusOriginY = |
+ (rowHeight - textHeight - pairedStatusHeight - |
+ kTableRowViewVerticalPadding) / |
+ 2; |
+ [pairedStatus_ |
+ setFrameOrigin:NSMakePoint(pairedStatusOriginX, pairedStatusOriginY)]; |
+ [self addSubview:pairedStatus_]; |
+ } |
} |
return self; |
@@ -128,6 +218,10 @@ const int kSignalStrengthLevelImageIds[5] = {IDR_SIGNAL_0_BAR, IDR_SIGNAL_1_BAR, |
return text_.get(); |
} |
+- (NSTextField*)pairedStatus { |
+ return pairedStatus_.get(); |
+} |
+ |
@end |
class ChooserContentViewController : public ChooserController::View { |
@@ -310,8 +404,8 @@ void ChooserContentViewController::UpdateTableView() { |
titleHeight_ = NSHeight([titleView_ frame]); |
// Status. |
- status_ = [self createTextField:l10n_util::GetNSString( |
- IDS_BLUETOOTH_DEVICE_CHOOSER_SCANNING)]; |
+ status_ = CreateLabel( |
+ l10n_util::GetNSString(IDS_BLUETOOTH_DEVICE_CHOOSER_SCANNING)); |
CGFloat statusWidth = kChooserWidth / 2 - kMarginX; |
// The height is arbitrary as it will be adjusted later. |
[status_ setFrameSize:NSMakeSize(statusWidth, 0.0f)]; |
@@ -341,9 +435,8 @@ void ChooserContentViewController::UpdateTableView() { |
separator_ = [self createSeparator]; |
// Message. |
- message_ = [self createTextField:l10n_util::GetNSStringF( |
- IDS_DEVICE_CHOOSER_FOOTNOTE_TEXT, |
- base::string16())]; |
+ message_ = CreateLabel(l10n_util::GetNSStringF( |
+ IDS_DEVICE_CHOOSER_FOOTNOTE_TEXT, base::string16())); |
CGFloat messageWidth = NSWidth([message_ frame]); |
messageHeight_ = NSHeight([message_ frame]); |
@@ -489,25 +582,58 @@ void ChooserContentViewController::UpdateTableView() { |
return titleView; |
} |
-- (base::scoped_nsobject<NSView>)createTableRowView:(NSInteger)rowIndex { |
+- (base::scoped_nsobject<NSView>)createTableRowView:(NSInteger)row { |
NSInteger level = -1; |
+ bool isConnected = false; |
+ bool isPaired = false; |
size_t numOptions = chooserController_->NumOptions(); |
- if (chooserController_->ShouldShowIconBeforeText() && numOptions > 0) { |
- DCHECK_GE(rowIndex, 0); |
- DCHECK_LT(rowIndex, base::checked_cast<NSInteger>(numOptions)); |
- level = base::checked_cast<NSInteger>( |
- chooserController_->GetSignalStrengthLevel( |
- base::checked_cast<size_t>(rowIndex))); |
+ base::scoped_nsobject<NSView> tableRowView; |
+ if (numOptions == 0) { |
+ DCHECK_EQ(0, row); |
+ tableRowView.reset([[ChooserContentTableRowView alloc] |
+ initWithText:[self optionAtIndex:row]]); |
+ } else { |
+ DCHECK_GE(row, 0); |
+ DCHECK_LT(row, base::checked_cast<NSInteger>(numOptions)); |
+ size_t rowIndex = base::checked_cast<size_t>(row); |
+ if (chooserController_->ShouldShowIconBeforeText()) { |
+ level = base::checked_cast<NSInteger>( |
+ chooserController_->GetSignalStrengthLevel(rowIndex)); |
+ } |
+ isConnected = chooserController_->IsConnected(rowIndex); |
+ isPaired = chooserController_->IsPaired(rowIndex); |
+ bool textNeedIndentation = false; |
+ for (size_t i = 0; i < numOptions; ++i) { |
+ if (chooserController_->GetSignalStrengthLevel(i) != -1 || |
+ chooserController_->IsConnected(i)) { |
+ textNeedIndentation = true; |
+ break; |
+ } |
+ } |
+ tableRowView.reset([[ChooserContentTableRowView alloc] |
+ initWithText:[self optionAtIndex:row] |
+ signalStrengthLevel:level |
+ isConnected:isConnected |
+ isPaired:isPaired |
+ rowHeight:[self tableRowViewHeight:row] |
+ textNeedIndentation:textNeedIndentation]); |
} |
- base::scoped_nsobject<NSView> tableRowView([[ChooserContentTableRowView alloc] |
- initWithText:[self optionAtIndex:rowIndex] |
- signalStrengthLevel:level]); |
return tableRowView; |
} |
- (CGFloat)tableRowViewHeight:(NSInteger)row { |
- return kTableRowViewHeight; |
+ size_t numOptions = chooserController_->NumOptions(); |
+ if (numOptions == 0) { |
+ DCHECK_EQ(0, row); |
+ return kTableRowViewOneLineHeight; |
+ } |
+ |
+ DCHECK_GE(row, 0); |
+ DCHECK_LT(row, base::checked_cast<NSInteger>(numOptions)); |
+ size_t rowIndex = base::checked_cast<size_t>(row); |
+ return chooserController_->IsPaired(rowIndex) ? kTableRowViewTwoLinesHeight |
+ : kTableRowViewOneLineHeight; |
} |
- (base::scoped_nsobject<NSButton>)createButtonWithTitle:(NSString*)title { |
@@ -540,19 +666,6 @@ void ChooserContentViewController::UpdateTableView() { |
return spacer; |
} |
-- (base::scoped_nsobject<NSTextField>)createTextField:(NSString*)text { |
- base::scoped_nsobject<NSTextField> textField( |
- [[NSTextField alloc] initWithFrame:NSZeroRect]); |
- [textField setDrawsBackground:NO]; |
- [textField setBezeled:NO]; |
- [textField setEditable:NO]; |
- [textField setSelectable:NO]; |
- [textField setStringValue:text]; |
- [textField setFont:[NSFont systemFontOfSize:[NSFont systemFontSize]]]; |
- [textField sizeToFit]; |
- return textField; |
-} |
- |
- (base::scoped_nsobject<NSButton>)createHyperlinkButtonWithText: |
(NSString*)text { |
base::scoped_nsobject<NSButton> button( |
@@ -704,4 +817,10 @@ void ChooserContentViewController::UpdateTableView() { |
return [tableRowView text]; |
} |
+- (NSTextField*)tableRowViewPairedStatus:(NSInteger)row { |
+ ChooserContentTableRowView* tableRowView = |
+ [tableView_ viewAtColumn:0 row:row makeIfNecessary:YES]; |
+ return [tableRowView pairedStatus]; |
+} |
+ |
@end |