Index: chrome/browser/ui/cocoa/extensions/media_gallery_list_entry_view.mm |
diff --git a/chrome/browser/ui/cocoa/extensions/media_gallery_list_entry_view.mm b/chrome/browser/ui/cocoa/extensions/media_gallery_list_entry_view.mm |
new file mode 100644 |
index 0000000000000000000000000000000000000000..bd98f4b442a5c2e02c57a6714f393d6628a581c3 |
--- /dev/null |
+++ b/chrome/browser/ui/cocoa/extensions/media_gallery_list_entry_view.mm |
@@ -0,0 +1,222 @@ |
+// Copyright 2014 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#import "chrome/browser/ui/cocoa/extensions/media_gallery_list_entry_view.h" |
+ |
+#include "base/strings/sys_string_conversions.h" |
+#import "chrome/browser/ui/cocoa/constrained_window/constrained_window_control_utils.h" |
+#include "chrome/browser/ui/chrome_style.h" |
+#include "grit/theme_resources.h" |
+#import "ui/base/cocoa/menu_controller.h" |
+#include "ui/base/resource/resource_bundle.h" |
+ |
+const CGFloat kCheckboxMargin = 10; |
+ |
+ui::MenuModel* MediaGalleryListEntryController::GetContextMenu( |
+ MediaGalleryPrefId pref_id) { |
+ return NULL; |
+} |
+ |
+@interface MediaGalleryListEntry () |
+- (void)onCheckboxToggled:(id)sender; |
+- (void)onFolderViewerClicked:(id)sender; |
+- (ui::MenuModel*)getContextMenu; |
+- (void)layoutSubViews; |
+@end |
+ |
+ |
+@interface MediaGalleryButton : NSButton { |
+ @private |
+ MediaGalleryListEntry* controller_; // |controller_| owns |self|. |
+ base::scoped_nsobject<MenuController> menuController_; |
+} |
+ |
+- (id)initWithFrame:(NSRect)frameRect |
+ controller:(MediaGalleryListEntry*)controller; |
+- (NSMenu*)menuForEvent:(NSEvent*)theEvent; |
+ |
+@end |
+ |
+@implementation MediaGalleryButton |
+ |
+- (id)initWithFrame:(NSRect)frameRect |
+ controller:(MediaGalleryListEntry*)controller { |
+ if ((self = [super initWithFrame:frameRect])) { |
+ controller_ = controller; |
+ } |
+ return self; |
+} |
+ |
+- (NSMenu*)menuForEvent:(NSEvent*)theEvent { |
+ menuController_.reset( |
+ [[MenuController alloc] initWithModel:[controller_ getContextMenu] |
+ useWithPopUpButtonCell:NO]); |
+ return [menuController_ menu]; |
+} |
+ |
+@end |
+ |
+ |
+@implementation MediaGalleryListEntry |
+ |
+- (id)initWithFrame:(NSRect)frameRect |
+ controller:(MediaGalleryListEntryController*)controller |
+ prefId:(MediaGalleryPrefId)prefId |
+ galleryName:(base::string16)galleryName |
+ subscript:(base::string16)subscript |
+ tooltip:(base::string16)tooltip |
+ showFolderViewer:(bool)showFolderViewer { |
+ if ((self = [super initWithFrame:frameRect])) { |
+ controller_ = controller; |
+ prefId_ = prefId; |
+ |
+ NSString* nsTooltip = base::SysUTF16ToNSString(tooltip); |
+ |
+ // Set a auto resize mask so that -resizeWithOldSuperviewSize: is called. |
+ // It is overridden so the particular mask doesn't matter. |
+ [self setAutoresizingMask:NSViewWidthSizable]; |
+ checkbox_.reset( |
+ [[MediaGalleryButton alloc] initWithFrame:NSZeroRect |
+ controller:self]); |
+ [[checkbox_ cell] setLineBreakMode:NSLineBreakByTruncatingMiddle]; |
+ [checkbox_ setButtonType:NSSwitchButton]; |
+ [checkbox_ setTarget:self]; |
+ [checkbox_ setAction:@selector(onCheckboxToggled:)]; |
+ |
+ [checkbox_ setTitle:base::SysUTF16ToNSString(galleryName)]; |
+ [checkbox_ setToolTip:nsTooltip]; |
+ [self addSubview:checkbox_]; |
+ |
+ // Folder viewer button. |
+ if (showFolderViewer) { |
+ folderViewer_.reset( |
+ [[MediaGalleryButton alloc] initWithFrame:NSZeroRect |
+ controller:self]); |
+ [folderViewer_ setButtonType:NSMomentaryChangeButton]; |
+ [folderViewer_ setTarget:self]; |
+ [folderViewer_ setAction:@selector(onFolderViewerClicked:)]; |
+ |
+ ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); |
+ [folderViewer_ setImage:rb.GetNativeImageNamed( |
+ IDR_FILE_FOLDER).ToNSImage()]; |
+ [folderViewer_ setTitle:nil]; |
+ [folderViewer_ setBordered:false]; |
+ [folderViewer_ setToolTip:nsTooltip]; |
+ [self addSubview:folderViewer_]; |
+ } |
+ |
+ // Additional details text. |
+ if (!subscript.empty()) { |
+ details_.reset([[NSTextField alloc] initWithFrame:NSZeroRect]); |
+ [[details_ cell] setLineBreakMode:NSLineBreakByTruncatingHead]; |
+ [details_ setEditable:NO]; |
+ [details_ setSelectable:NO]; |
+ [details_ setBezeled:NO]; |
+ [details_ setAttributedStringValue: |
+ constrained_window::GetAttributedLabelString( |
+ base::SysUTF16ToNSString(subscript), |
+ chrome_style::kTextFontStyle, |
+ NSNaturalTextAlignment, |
+ NSLineBreakByClipping |
+ )]; |
+ [details_ setTextColor:[NSColor disabledControlTextColor]]; |
+ [self addSubview:details_]; |
+ } |
+ |
+ [self layoutSubViews]; |
+ } |
+ return self; |
+} |
+ |
+- (void)setFrameSize:(NSSize)frameSize { |
+ [super setFrameSize:frameSize]; |
+ [self layoutSubViews]; |
+} |
+ |
+- (void)resizeWithOldSuperviewSize:(NSSize)oldBoundsSize { |
+ NSRect frame = [self frame]; |
+ frame.size.width = NSWidth([[self superview] frame]); |
+ [self setFrameSize:frame.size]; |
+} |
+ |
+- (void)setState:(bool)selected { |
+ [checkbox_ setState:selected ? NSOnState : NSOffState]; |
+} |
+ |
+- (void)onCheckboxToggled:(id)sender { |
+ controller_->OnCheckboxToggled(prefId_, [sender state] == NSOnState); |
+} |
+ |
+- (void)onFolderViewerClicked:(id)sender { |
+ controller_->OnFolderViewerClicked(prefId_); |
+} |
+ |
+- (ui::MenuModel*)getContextMenu { |
+ return controller_->GetContextMenu(prefId_); |
+} |
+ |
+- (void)layoutSubViews { |
+ NSRect bounds = [self bounds]; |
+ // If we have an empty frame, we should auto size, so start with really big |
+ // bounds and then set it to the real size of the contents later. |
+ if (NSIsEmptyRect([self frame])) |
+ bounds.size = NSMakeSize(10000, 10000); |
+ |
+ [checkbox_ sizeToFit]; |
+ [folderViewer_ sizeToFit]; |
+ [details_ sizeToFit]; |
+ |
+ // Auto size everything and lay it out horizontally. |
+ CGFloat xPos = kCheckboxMargin; |
+ for (NSView* view in [self subviews]) { |
+ NSRect viewFrame = [view frame]; |
+ viewFrame.origin.x = xPos; |
+ viewFrame.size.height = std::min(NSHeight(bounds), NSHeight(viewFrame)); |
+ [view setFrame:viewFrame]; |
+ xPos = NSMaxX([view frame]) + kCheckboxMargin; |
+ } |
+ |
+ // Size the views. If all the elements don't naturally fit, the checkbox |
+ // should get squished and will elide in the middle. However, it shouldn't |
+ // squish too much so it gets at least half of the max width and the details |
+ // text should elide as well in that case. |
+ if (xPos > NSWidth(bounds)) { |
+ CGFloat maxRHSContent = NSWidth(bounds) / 2 - kCheckboxMargin; |
+ NSRect detailsFrame = [details_ frame]; |
+ NSRect checkboxFrame = [checkbox_ frame]; |
+ |
+ if (NSMaxX(detailsFrame) - NSMaxX(checkboxFrame) > maxRHSContent) { |
+ detailsFrame.size.width = std::max( |
+ maxRHSContent - (NSMinX(detailsFrame) - NSMaxX(checkboxFrame)), |
+ NSWidth(bounds) - kCheckboxMargin - NSMinX(detailsFrame)); |
+ [details_ setFrameSize:detailsFrame.size]; |
+ xPos = NSMaxX(detailsFrame) + kCheckboxMargin; |
+ } |
+ CGFloat overflow = xPos - NSWidth(bounds); |
+ if (overflow > 0) { |
+ checkboxFrame.size.width -= overflow; |
+ [checkbox_ setFrameSize:checkboxFrame.size]; |
+ if (folderViewer_.get()) { |
+ NSRect folderViewerFrame = [folderViewer_ frame]; |
+ folderViewerFrame.origin.x -= overflow; |
+ [folderViewer_ setFrameOrigin:folderViewerFrame.origin]; |
+ } |
+ if (details_.get()) { |
+ detailsFrame.origin.x -= overflow; |
+ [details_ setFrameOrigin:detailsFrame.origin]; |
+ } |
+ } |
+ } |
+ |
+ if (NSIsEmptyRect([self frame])) { |
+ NSRect frame = NSMakeRect(0, 0, 1, 1); |
+ for (NSView* view in [self subviews]) { |
+ frame = NSUnionRect(frame, [view frame]); |
+ } |
+ frame.size.width += kCheckboxMargin; |
+ [super setFrameSize:frame.size]; |
+ } |
+} |
+ |
+@end |