diff options
Diffstat (limited to 'chrome/browser/cocoa')
19 files changed, 578 insertions, 939 deletions
diff --git a/chrome/browser/cocoa/autocomplete_text_field.h b/chrome/browser/cocoa/autocomplete_text_field.h index 8e16705..1b1856d 100644 --- a/chrome/browser/cocoa/autocomplete_text_field.h +++ b/chrome/browser/cocoa/autocomplete_text_field.h @@ -119,13 +119,6 @@ class AutocompleteTextFieldObserver { // is not over an action. - (NSMenu*)actionMenuForEvent:(NSEvent*)event; -// Return the rectangle the star is being shown in, for purposes of -// positioning the bookmark bubble. -- (NSRect)starIconFrame; - -// If the location icon is draggable, return its drag pasteboard. -- (NSPasteboard*)locationDragPasteboard; - @end #endif // CHROME_BROWSER_COCOA_AUTOCOMPLETE_TEXT_FIELD_H_ diff --git a/chrome/browser/cocoa/autocomplete_text_field.mm b/chrome/browser/cocoa/autocomplete_text_field.mm index a07cac1..60d3507 100644 --- a/chrome/browser/cocoa/autocomplete_text_field.mm +++ b/chrome/browser/cocoa/autocomplete_text_field.mm @@ -124,10 +124,14 @@ return; } - // Give the cell a chance to intercept clicks in page-actions and - // other decorative items. - if ([cell mouseDown:theEvent inRect:bounds ofView:self]) { - return; + // If the user clicked on one of the icons (security icon, Page + // Actions, etc), let the icon handle the click. + for (AutocompleteTextFieldIcon* icon in [cell layedOutIcons:bounds]) { + const NSRect iconRect = [icon rect]; + if (NSMouseInRect(location, iconRect, flipped)) { + [icon view]->OnMousePressed(iconRect); + return; + } } NSText* editor = [self currentEditor]; @@ -195,7 +199,6 @@ // Show the I-beam cursor unless the mouse is over an image within the field // (Page Actions or the security icon) in which case show the arrow cursor. -// TODO(rohitrao): Should default to the arrow cursor. http://crbug.com/41612 - (void)resetCursorRects { NSRect fieldBounds = [self bounds]; [self addCursorRect:fieldBounds cursor:[NSCursor IBeamCursor]]; @@ -203,17 +206,8 @@ AutocompleteTextFieldCell* cell = [self autocompleteTextFieldCell]; for (AutocompleteTextFieldIcon* icon in [cell layedOutIcons:fieldBounds]) [self addCursorRect:[icon rect] cursor:[NSCursor arrowCursor]]; - - // Special-case the location image, since it is not in |-layedOutIcons|. - const NSRect locationIconFrame = [cell locationIconFrameForFrame:fieldBounds]; - [self addCursorRect:locationIconFrame cursor:[NSCursor arrowCursor]]; } -// TODO(shess): -resetFieldEditorFrameIfNeeded is the place where -// changes to the cell layout should be flushed. LocationBarViewMac -// and ToolbarController are calling this routine directly, and I -// think they are probably wrong. -// http://crbug.com/40053 - (void)updateCursorAndToolTipRects { // This will force |resetCursorRects| to be called, as it is not to be called // directly. @@ -377,13 +371,4 @@ actionMenuForEvent:event inRect:[self bounds] ofView:self]; } -- (NSRect)starIconFrame { - AutocompleteTextFieldCell* cell = [self autocompleteTextFieldCell]; - return [cell starIconFrameForFrame:[self bounds]]; -} - -- (NSPasteboard*)locationDragPasteboard { - return [[self autocompleteTextFieldCell] locationDragPasteboard]; -} - @end diff --git a/chrome/browser/cocoa/autocomplete_text_field_cell.h b/chrome/browser/cocoa/autocomplete_text_field_cell.h index bc791cf..1e0a3c5 100644 --- a/chrome/browser/cocoa/autocomplete_text_field_cell.h +++ b/chrome/browser/cocoa/autocomplete_text_field_cell.h @@ -13,15 +13,7 @@ class ExtensionAction; // Holds a |LocationBarImageView| and its current rect. Do not keep references // to this object, only use it directly after calling |-layedOutIcons:|. -// TODO(shess): This class is basically a helper for laying out the -// icons. Try to refactor it away. If that is not reasonable, at -// least split the image and label cases into subclasses once the -// Omnibox stuff is settled. @interface AutocompleteTextFieldIcon : NSObject { - // YES to draw the label part of |view_|, otherwise draw the image - // part. - BOOL isLabel_; - // The frame rect of |view_|. NSRect rect_; @@ -29,20 +21,12 @@ class ExtensionAction; LocationBarViewMac::LocationBarImageView* view_; } +// Returns a new AutocompleteTextFieldIcon object. ++ (AutocompleteTextFieldIcon*) + iconWithRect:(NSRect)rect + view:(LocationBarViewMac::LocationBarImageView*)view; @property(assign, nonatomic) NSRect rect; @property(assign, nonatomic) LocationBarViewMac::LocationBarImageView* view; - -- (id)initImageWithView:(LocationBarViewMac::LocationBarImageView*)view; -- (id)initLabelWithView:(LocationBarViewMac::LocationBarImageView*)view; - -// Position |view_| right-justified in |frame|. -- (void)positionInFrame:(NSRect)frame; - -// Draw image or label of |view_| in |rect_| within |controlView|. -// Only call after |-positionInFrame:| has set |rect_| (or after an -// explicit |-setRect:|). -- (void)drawInView:(NSView*)controlView; - @end // AutocompleteTextFieldCell extends StyledTextFieldCell to provide support for @@ -60,17 +44,10 @@ class ExtensionAction; // side of the field. Exclusive WRT |keywordString_|; scoped_nsobject<NSAttributedString> hintString_; - // The location icon sits at the left-hand side of the field. - // |keywordString_| overrides. - LocationBarViewMac::LocationIconView* locationIconView_; - - // The star icon sits at the right-hand side of the field when an - // URL is being shown. - LocationBarViewMac::LocationBarImageView* starIconView_; - - // The security label floats to the left of page actions at the - // right-hand side. - LocationBarViewMac::LocationBarImageView* securityLabelView_; + // View showing the state of the SSL connection. Owned by the location bar. + // Display is exclusive WRT the |hintString_| and |keywordString_|. + // This may be NULL during testing. + LocationBarViewMac::SecurityImageView* security_image_view_; // List of views showing visible Page Actions. Owned by the location bar. // Display is exclusive WRT the |hintString_| and |keywordString_|. @@ -100,58 +77,34 @@ class ExtensionAction; availableWidth:(CGFloat)width; - (void)clearKeywordAndHint; -- (void)setLocationIconView:(LocationBarViewMac::LocationIconView*)view; -- (void)setStarIconView:(LocationBarViewMac::LocationBarImageView*)view; -- (void)setSecurityLabelView:(LocationBarViewMac::LocationBarImageView*)view; +- (void)setSecurityImageView:(LocationBarViewMac::SecurityImageView*)view; - (void)setPageActionViewList:(LocationBarViewMac::PageActionViewList*)list; - (void)setContentSettingViewsList: (LocationBarViewMac::ContentSettingViews*)views; -// Returns the portion of the cell to use for displaying the location -// icon. -- (NSRect)locationIconFrameForFrame:(NSRect)cellFrame; - // Returns an array of the visible AutocompleteTextFieldIcon objects. Returns // only visible icons. - (NSArray*)layedOutIcons:(NSRect)cellFrame; -// Return the rectangle the star is being shown in, for purposes of -// positioning the bookmark bubble. -- (NSRect)starIconFrameForFrame:(NSRect)cellFrame; - -// Returns the portion of the cell to use for displaying the Page -// Action icon at the given index. May be NSZeroRect if the index's -// action is not visible. This does a linear walk over all page -// actions, so do not call this in a loop to get the position of all -// page actions. Use |-layedOutIcons:| instead in that case. -- (NSRect)pageActionFrameForIndex:(size_t)index inFrame:(NSRect)cellFrame; // Similar to |pageActionFrameForIndex:inFrame| but accepts an // ExtensionAction for when the index is not known. - (NSRect)pageActionFrameForExtensionAction:(ExtensionAction*)action inFrame:(NSRect)cellFrame; -// Find the icon under the event. |nil| if |theEvent| is not over -// anything. -- (AutocompleteTextFieldIcon*)iconForEvent:(NSEvent*)theEvent - inRect:(NSRect)cellFrame - ofView:(AutocompleteTextField*)controlView; +// Returns the portion of the cell to use for displaying the Page Action icon +// at the given index. May be NSZeroRect if the index's action is not visible. +// This does a linear walk over all page actions, so do not call this in a loop +// to get the position of all page actions. Use |-layedOutIcons:| instead in that +// case. +- (NSRect)pageActionFrameForIndex:(size_t)index inFrame:(NSRect)cellFrame; // Return the appropriate menu for any page actions under event. // Returns nil if no menu is present for the action, or if the event // is not over an action. -- (NSMenu*)actionMenuForEvent:(NSEvent*)theEvent +- (NSMenu*)actionMenuForEvent:(NSEvent*)event inRect:(NSRect)cellFrame - ofView:(AutocompleteTextField*)controlView; - -// Called by |AutocompleteTextField| to let page actions intercept -// clicks. Returns |YES| if the click has been intercepted. -- (BOOL)mouseDown:(NSEvent*)theEvent - inRect:(NSRect)cellFrame - ofView:(AutocompleteTextField*)controlView; - -// If the location icon is draggable, return its drag pasteboard. -- (NSPasteboard*)locationDragPasteboard; + ofView:(NSView*)aView; @end @@ -165,4 +118,8 @@ class ExtensionAction; // Returns the total number of installed Page Actions, visible or not. - (size_t)pageActionCount; +// Returns the portion of the cell to use for displaying the security (SSL lock) +// icon, leaving space for its label if any. +- (NSRect)securityImageFrameForFrame:(NSRect)cellFrame; + @end diff --git a/chrome/browser/cocoa/autocomplete_text_field_cell.mm b/chrome/browser/cocoa/autocomplete_text_field_cell.mm index 9801892..7b7f35c 100644 --- a/chrome/browser/cocoa/autocomplete_text_field_cell.mm +++ b/chrome/browser/cocoa/autocomplete_text_field_cell.mm @@ -7,20 +7,6 @@ #include "app/resource_bundle.h" #include "base/logging.h" #include "gfx/font.h" -#include "grit/theme_resources.h" - -@interface AutocompleteTextAttachmentCell : NSTextAttachmentCell { -} - -// TODO(shess): -// Override -cellBaselineOffset to allow the image to be shifted up or -// down relative to the containing text's baseline. - -// Draw the image using |DrawImageInRect()| helper function for -// |-setFlipped:| consistency with other image drawing. -- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)aView; - -@end namespace { @@ -49,28 +35,16 @@ const NSInteger kKeywordYInset = 4; // technique would be nice to have, though. const NSInteger kKeywordHintImageBaseline = -6; -// Drops the magnifying glass icon so that it looks centered in the -// keyword-search bubble. -const NSInteger kKeywordSearchImageBaseline = -5; - // The amount of padding on either side reserved for drawing an icon. const NSInteger kIconHorizontalPad = 3; // How far to shift bounding box of hint icon label down from top of field. -const NSInteger kIconLabelYOffset = 7; +const NSInteger kIconLabelYOffset = 5; // How far the editor insets itself, for purposes of determining if // decorations need to be trimmed. const CGFloat kEditorHorizontalInset = 3.0; -// Cause the location icon to line up above the icons in the popup. -const CGFloat kLocationIconXOffset = 6.0; -const CGFloat kLocationIconXPad = 1.0; - -// How long to wait for mouse-up on the location icon before assuming -// that the user wants to drag. -const NSTimeInterval kLocationIconDragTimeout = 0.25; - // Conveniences to centralize width+offset calculations. CGFloat WidthForHint(NSAttributedString* hintString) { return kHintXOffset + ceil([hintString size].width); @@ -80,103 +54,20 @@ CGFloat WidthForKeyword(NSAttributedString* keywordString) { 2 * kKeywordTokenInset; } -// Convenience to draw |image| in the |rect| portion of |view|. -void DrawImageInRect(NSImage* image, NSView* view, const NSRect& rect) { - // If there is an image, make sure we calculated the target size - // correctly. - DCHECK(!image || NSEqualSizes([image size], rect.size)); - [image setFlipped:[view isFlipped]]; - [image drawInRect:rect - fromRect:NSZeroRect // Entire image - operation:NSCompositeSourceOver - fraction:1.0]; -} - -// Helper function to generate an attributed string containing -// |anImage|. If |baselineAdjustment| is 0, the image sits on the -// text baseline, positive values shift it up, negative values shift -// it down. -NSAttributedString* AttributedStringForImage(NSImage* anImage, - CGFloat baselineAdjustment) { - scoped_nsobject<AutocompleteTextAttachmentCell> attachmentCell( - [[AutocompleteTextAttachmentCell alloc] initImageCell:anImage]); - scoped_nsobject<NSTextAttachment> attachment( - [[NSTextAttachment alloc] init]); - [attachment setAttachmentCell:attachmentCell]; - - scoped_nsobject<NSMutableAttributedString> as( - [[NSAttributedString attributedStringWithAttachment:attachment] - mutableCopy]); - [as addAttribute:NSBaselineOffsetAttributeName - value:[NSNumber numberWithFloat:baselineAdjustment] - range:NSMakeRange(0, [as length])]; - - return [[as copy] autorelease]; -} - } // namespace -@implementation AutocompleteTextAttachmentCell - -- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)aView { - // Draw image with |DrawImageInRect()| to get consistent - // |-setFlipped:| treatment. - DrawImageInRect([self image], aView, cellFrame); -} - -@end - @implementation AutocompleteTextFieldIcon @synthesize rect = rect_; @synthesize view = view_; -// Private helper. -- (id)initWithView:(LocationBarViewMac::LocationBarImageView*)view - isLabel:(BOOL)isLabel { - self = [super init]; - if (self) { - isLabel_ = isLabel; - view_ = view; - rect_ = NSZeroRect; - } - return self; -} - -- (id)initImageWithView:(LocationBarViewMac::LocationBarImageView*)view { - return [self initWithView:view isLabel:NO]; -} - -- (id)initLabelWithView:(LocationBarViewMac::LocationBarImageView*)view { - return [self initWithView:view isLabel:YES]; -} - -- (void)positionInFrame:(NSRect)frame { - if (isLabel_) { - NSAttributedString* label = view_->GetLabel(); - DCHECK(label); - const CGFloat labelWidth = ceil([label size].width); - rect_ = NSMakeRect(NSMaxX(frame) - labelWidth, - NSMinY(frame) + kIconLabelYOffset, - labelWidth, NSHeight(frame) - kIconLabelYOffset); - } else { - const NSSize imageSize = view_->GetImageSize(); - const CGFloat yOffset = floor((NSHeight(frame) - imageSize.height) / 2); - rect_ = NSMakeRect(NSMaxX(frame) - imageSize.width, - NSMinY(frame) + yOffset, - imageSize.width, imageSize.height); - } -} - -- (void)drawInView:(NSView*)controlView { - // Make sure someone called |-positionInFrame:|. - DCHECK(!NSIsEmptyRect(rect_)); - if (isLabel_) { - NSAttributedString* label = view_->GetLabel(); - [label drawInRect:rect_]; - } else { - DrawImageInRect(view_->GetImage(), controlView, rect_); - } ++ (AutocompleteTextFieldIcon*) + iconWithRect:(NSRect)rect + view:(LocationBarViewMac::LocationBarImageView*)view { + AutocompleteTextFieldIcon* result = [[AutocompleteTextFieldIcon alloc] init]; + [result setRect:rect]; + [result setView:view]; + return [result autorelease]; } @end @@ -205,40 +96,18 @@ NSAttributedString* AttributedStringForImage(NSImage* anImage, // Adjust for space between editor and decorations. width -= 2 * kEditorHorizontalInset; - // Get the magnifying glass to put at the front of the string. - NSImage* image = - AutocompleteEditViewMac::ImageForResource(IDR_OMNIBOX_SEARCH); - const NSSize imageSize = [image size]; - - // Based on what fits, choose |fullString| with the image, - // |fullString| without the image, or |partialString|. + // If |fullString| won't fit, choose |partialString|. NSDictionary* attributes = [NSDictionary dictionaryWithObject:[self font] forKey:NSFontAttributeName]; NSString* s = fullString; - const CGFloat sWidth = [s sizeWithAttributes:attributes].width; - if (sWidth + imageSize.width > width) { - image = nil; - } - if (sWidth > width) { + if ([s sizeWithAttributes:attributes].width > width) { if (partialString) { s = partialString; } } - - scoped_nsobject<NSMutableAttributedString> as( - [[NSMutableAttributedString alloc] initWithString:s - attributes:attributes]); - - // Insert the image at the front of the string if it didn't make - // things too wide. - if (image) { - NSAttributedString* is = - AttributedStringForImage(image, kKeywordSearchImageBaseline); - [as insertAttributedString:is atIndex:0]; - } - - keywordString_.reset([as copy]); + keywordString_.reset( + [[NSAttributedString alloc] initWithString:s attributes:attributes]); } // Convenience for the attributes used in the right-justified info @@ -286,8 +155,21 @@ NSAttributedString* AttributedStringForImage(NSImage* anImage, initWithString:s attributes:[self hintAttributes]]); // Build an attachment containing the hint image. - NSAttributedString* is = - AttributedStringForImage(anImage, kKeywordHintImageBaseline); + scoped_nsobject<NSTextAttachmentCell> attachmentCell( + [[NSTextAttachmentCell alloc] initImageCell:anImage]); + scoped_nsobject<NSTextAttachment> attachment( + [[NSTextAttachment alloc] init]); + [attachment setAttachmentCell:attachmentCell]; + + // The attachment's baseline needs to be adjusted so the image + // doesn't sit on the same baseline as the text and make + // everything too tall. + scoped_nsobject<NSMutableAttributedString> is( + [[NSAttributedString attributedStringWithAttachment:attachment] + mutableCopy]); + [is addAttribute:NSBaselineOffsetAttributeName + value:[NSNumber numberWithFloat:kKeywordHintImageBaseline] + range:NSMakeRange(0, [is length])]; // Stuff the image attachment between the prefix and suffix. [as insertAttributedString:is atIndex:[prefixString length]]; @@ -331,16 +213,8 @@ NSAttributedString* AttributedStringForImage(NSImage* anImage, page_action_views_ = list; } -- (void)setLocationIconView:(LocationBarViewMac::LocationIconView*)view { - locationIconView_ = view; -} - -- (void)setStarIconView:(LocationBarViewMac::LocationBarImageView*)view { - starIconView_ = view; -} - -- (void)setSecurityLabelView:(LocationBarViewMac::LocationBarImageView*)view { - securityLabelView_ = view; +- (void)setSecurityImageView:(LocationBarViewMac::SecurityImageView*)view { + security_image_view_ = view; } - (void)setContentSettingViewsList: @@ -352,81 +226,69 @@ NSAttributedString* AttributedStringForImage(NSImage* anImage, - (NSRect)textFrameForFrame:(NSRect)cellFrame { NSRect textFrame([super textFrameForFrame:cellFrame]); - // NOTE: This function must closely match the logic in - // |-drawInteriorWithFrame:inView:|. - - // Location icon is not shown in keyword search mode. - if (!keywordString_ && locationIconView_ && locationIconView_->IsVisible()) { - const NSRect iconFrame = [self locationIconFrameForFrame:cellFrame]; - const CGFloat newOrigin = NSMaxX(iconFrame) + kLocationIconXPad; - textFrame.size.width = NSMaxX(textFrame) - newOrigin; - textFrame.origin.x = newOrigin; - } - - // Leave room for items on the right (SSL label, page actions, etc). - // Icons are laid out in |cellFrame| rather than |textFrame| for - // consistency with drawing code. - NSArray* icons = [self layedOutIcons:cellFrame]; - if ([icons count]) { - // Max x for resulting text frame. - const CGFloat maxX = NSMinX([[icons objectAtIndex:0] rect]); - textFrame.size.width = maxX - NSMinX(textFrame); - } - - // Keyword string or hint string if they fit. - if (keywordString_) { - DCHECK(!hintString_); - const CGFloat keywordWidth(WidthForKeyword(keywordString_)); - - if (keywordWidth < NSWidth(textFrame)) { - textFrame.origin.x += keywordWidth; - textFrame.size.width -= keywordWidth; - } - } else if (hintString_) { + if (hintString_) { DCHECK(!keywordString_); const CGFloat hintWidth(WidthForHint(hintString_)); // TODO(shess): This could be better. Show the hint until the // non-hint text bumps against it? - if (hintWidth < NSWidth(textFrame)) { + if (hintWidth < NSWidth(cellFrame)) { textFrame.size.width -= hintWidth; } - } + } else if (keywordString_) { + DCHECK(!hintString_); + const CGFloat keywordWidth(WidthForKeyword(keywordString_)); - // SSL label if it fits. - if (securityLabelView_ && securityLabelView_->IsVisible() && - securityLabelView_->GetLabel()) { - NSAttributedString* label = securityLabelView_->GetLabel(); - const CGFloat labelWidth = ceil([label size].width) + kIconHorizontalPad; - if (NSWidth(textFrame) > labelWidth) { - textFrame.size.width -= labelWidth; + // TODO(shess): This could be better. There's support for a + // "short" version of the keyword string, work that in in a + // follow-on pass. + if (keywordWidth < NSWidth(cellFrame)) { + textFrame.origin.x += keywordWidth; + textFrame.size.width = NSMaxX(cellFrame) - NSMinX(textFrame); } + } else { + // Leave room for images on the right (lock icon etc). + NSArray* iconFrames = [self layedOutIcons:cellFrame]; + CGFloat width = 0; + if ([iconFrames count] > 0) + width = NSMaxX(cellFrame) - NSMinX([[iconFrames lastObject] rect]); + if (width > 0) + width += kIconHorizontalPad; + if (width < NSWidth(cellFrame)) + textFrame.size.width -= width; } return textFrame; } -- (NSRect)locationIconFrameForFrame:(NSRect)cellFrame { - if (!locationIconView_ || !locationIconView_->IsVisible()) - return NSZeroRect; - - const NSSize imageSize = locationIconView_->GetImageSize(); - const CGFloat yOffset = floor((NSHeight(cellFrame) - imageSize.height) / 2); - return NSMakeRect(NSMinX(cellFrame) + kLocationIconXOffset, - NSMinY(cellFrame) + yOffset, - imageSize.width, imageSize.height); +// Returns a rect of size |imageSize| centered vertically and right-justified in +// the |box|, with its top left corner |margin| pixels from the right end of the +// box. (The image thus occupies part of the |margin|.) +- (NSRect)rightJustifyImage:(NSSize)imageSize + inRect:(NSRect)box + withMargin:(CGFloat)margin { + box.origin.x += box.size.width - margin; + box.origin.y += floor((box.size.height - imageSize.height) / 2); + box.size = imageSize; + return box; } -- (NSRect)starIconFrameForFrame:(NSRect)cellFrame { - if (!starIconView_ || !starIconView_->IsVisible()) +- (NSRect)securityImageFrameForFrame:(NSRect)cellFrame { + if (!security_image_view_ || !security_image_view_->IsVisible()) { return NSZeroRect; + } + + // Calculate the total width occupied by the image, label, and padding. + NSSize imageSize = [security_image_view_->GetImage() size]; + CGFloat widthUsed = imageSize.width + kIconHorizontalPad; + NSAttributedString* label = security_image_view_->GetLabel(); + if (label) { + widthUsed += ceil([label size].width) + kHintXOffset; + } - // The star icon is always at the RHS. - scoped_nsobject<AutocompleteTextFieldIcon> icon( - [[AutocompleteTextFieldIcon alloc] initImageWithView:starIconView_]); - cellFrame.size.width -= kHintXOffset; - [icon positionInFrame:cellFrame]; - return [icon rect]; + return [self rightJustifyImage:imageSize + inRect:cellFrame + withMargin:widthUsed]; } - (size_t)pageActionCount { @@ -503,223 +365,118 @@ NSAttributedString* AttributedStringForImage(NSImage* anImage, [path stroke]; // Draw text w/in the rectangle. - infoFrame.origin.x += 3.0; + infoFrame.origin.x += 4.0; + infoFrame.origin.y += 1.0; [keywordString_.get() drawInRect:infoFrame]; } -- (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView*)controlView { - NSRect workingFrame = cellFrame; - - // NOTE: This function must closely match the logic in - // |-textFrameForFrame:|. - - // Location icon is not shown in keyword search mode. - if (!keywordString_ && locationIconView_ && locationIconView_->IsVisible()) { - const NSRect iconFrame = [self locationIconFrameForFrame:cellFrame]; - DrawImageInRect(locationIconView_->GetImage(), controlView, iconFrame); - const CGFloat newOrigin = NSMaxX(iconFrame) + kLocationIconXPad; - workingFrame.size.width = NSMaxX(workingFrame) - newOrigin; - workingFrame.origin.x = newOrigin; - } - - NSArray* icons = [self layedOutIcons:cellFrame]; - for (AutocompleteTextFieldIcon* icon in icons) { - [icon drawInView:controlView]; - } - if ([icons count]) { - // Max x for resulting text frame. - const CGFloat maxX = NSMinX([[icons objectAtIndex:0] rect]); - workingFrame.size.width = maxX - NSMinX(workingFrame); +- (void)drawImageView:(LocationBarViewMac::LocationBarImageView*)imageView + inFrame:(NSRect)imageFrame + inView:(NSView*)controlView { + // If there's a label, draw it to the right of the icon. The caller must have + // left sufficient space. + NSAttributedString* label = imageView->GetLabel(); + if (label) { + CGFloat labelWidth = ceil([label size].width) + kHintXOffset; + NSRect textFrame(NSMakeRect(NSMaxX(imageFrame) + kIconHorizontalPad, + imageFrame.origin.y + kIconLabelYOffset, + labelWidth, + imageFrame.size.height - kIconLabelYOffset)); + [label drawInRect:textFrame]; } - // Keyword string or hint string if they fit. - if (keywordString_) { - DCHECK(!hintString_); - const CGFloat keywordWidth(WidthForKeyword(keywordString_)); - - if (keywordWidth < NSWidth(workingFrame)) { - [self drawKeywordWithFrame:cellFrame inView:controlView]; - workingFrame.origin.x += keywordWidth; - workingFrame.size.width -= keywordWidth; - } - } else if (hintString_) { - DCHECK(!keywordString_); - const CGFloat hintWidth(WidthForHint(hintString_)); - - // TODO(shess): This could be better. Show the hint until the - // non-hint text bumps against it? - if (hintWidth < NSWidth(workingFrame)) { - [self drawHintWithFrame:cellFrame inView:controlView]; - workingFrame.size.width -= hintWidth; - } - } + // Draw the entire image. + NSRect imageRect = NSZeroRect; + NSImage* image = imageView->GetImage(); + image.size = [image size]; + [image setFlipped:[controlView isFlipped]]; + [image drawInRect:imageFrame + fromRect:imageRect + operation:NSCompositeSourceOver + fraction:1.0]; +} - // SSL label if it fits. - if (securityLabelView_ && securityLabelView_->IsVisible() && - securityLabelView_->GetLabel()) { - NSAttributedString* label = securityLabelView_->GetLabel(); - const CGFloat labelWidth = ceil([label size].width) + kIconHorizontalPad; - if (NSWidth(workingFrame) > labelWidth) { - workingFrame.size.width -= kIconHorizontalPad; - - scoped_nsobject<AutocompleteTextFieldIcon> icon( - [[AutocompleteTextFieldIcon alloc] - initLabelWithView:securityLabelView_]); - [icon positionInFrame:workingFrame]; - [icon drawInView:controlView]; - DCHECK_EQ(labelWidth, NSWidth([icon rect]) + kIconHorizontalPad); - workingFrame.size.width -= NSWidth([icon rect]); +- (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView*)controlView { + if (hintString_) { + [self drawHintWithFrame:cellFrame inView:controlView]; + } else if (keywordString_) { + [self drawKeywordWithFrame:cellFrame inView:controlView]; + } else { + for (AutocompleteTextFieldIcon* icon in [self layedOutIcons:cellFrame]) { + [self drawImageView:[icon view] + inFrame:[icon rect] + inView:controlView]; } } - // Superclass draws text portion WRT original |cellFrame|. [super drawInteriorWithFrame:cellFrame inView:controlView]; } - (NSArray*)layedOutIcons:(NSRect)cellFrame { - // The set of views to display right-justified in the cell, from - // left to right. - NSMutableArray* result = [NSMutableArray array]; - - // Collect the image views for bulk processing. - // TODO(shess): Refactor with LocationBarViewMac to make the - // different types of items more consistent. - std::vector<LocationBarViewMac::LocationBarImageView*> views; - - if (content_setting_views_) { - views.insert(views.end(), - content_setting_views_->begin(), - content_setting_views_->end()); - } - - // TODO(shess): Previous implementation of this method made a - // right-to-left array, so add the page-action items in that order. - // As part of the refactor mentioned above, lay everything out - // nicely left-to-right. - for (size_t i = [self pageActionCount]; i-- > 0;) { - views.push_back(page_action_views_->ViewAt(i)); + NSMutableArray* result = [NSMutableArray arrayWithCapacity:0]; + NSRect iconFrame = cellFrame; + if (security_image_view_ && security_image_view_->IsVisible()) { + NSRect securityImageFrame = [self securityImageFrameForFrame:iconFrame]; + [result addObject: + [AutocompleteTextFieldIcon iconWithRect:securityImageFrame + view:security_image_view_]]; + iconFrame.size.width -= NSMaxX(iconFrame) - NSMinX(securityImageFrame); } - // The star icon should always come last. - if (starIconView_) - views.push_back(starIconView_); - - // Load the visible views into |result|. - for (std::vector<LocationBarViewMac::LocationBarImageView*>::const_iterator - iter = views.begin(); iter != views.end(); ++iter) { - if ((*iter)->IsVisible()) { - scoped_nsobject<AutocompleteTextFieldIcon> icon( - [[AutocompleteTextFieldIcon alloc] initImageWithView:*iter]); - [result addObject:icon]; + const size_t pageActionCount = [self pageActionCount]; + for (size_t i = 0; i < pageActionCount; ++i) { + LocationBarViewMac::PageActionImageView* view = + page_action_views_->ViewAt(i); + if (view->IsVisible()) { + // If this function is called right after a page action icon has been + // created, the images for all views will still be loading; in this case, + // each visible view will give us its default size. + NSSize iconSize = view->GetPreferredImageSize(); + NSRect pageActionFrame = + [self rightJustifyImage:iconSize + inRect:iconFrame + withMargin:kIconHorizontalPad + iconSize.width]; + [result addObject: + [AutocompleteTextFieldIcon iconWithRect:pageActionFrame view:view]]; + iconFrame.size.width -= NSMaxX(iconFrame) - NSMinX(pageActionFrame); } } - // Leave a boundary at RHS of field. - cellFrame.size.width -= kHintXOffset; - - // Position each view within the frame from right to left. - for (AutocompleteTextFieldIcon* icon in [result reverseObjectEnumerator]) { - [icon positionInFrame:cellFrame]; - - // Trim the icon's space from the frame. - cellFrame.size.width = NSMinX([icon rect]) - kIconHorizontalPad; + if (content_setting_views_) { + // We use a reverse_iterator here because we're laying out the views from + // right to left but in the vector they're ordered left to right. + for (LocationBarViewMac::ContentSettingViews::const_reverse_iterator + it(content_setting_views_->rbegin()); + it != const_cast<const LocationBarViewMac::ContentSettingViews*>( + content_setting_views_)->rend(); + ++it) { + if ((*it)->IsVisible()) { + NSImage* image = (*it)->GetImage(); + NSRect blockedContentFrame = + [self rightJustifyImage:[image size] + inRect:iconFrame + withMargin:[image size].width + kIconHorizontalPad]; + [result addObject: + [AutocompleteTextFieldIcon iconWithRect:blockedContentFrame + view:*it]]; + iconFrame.size.width -= NSMaxX(iconFrame) - NSMinX(blockedContentFrame); + } + } } return result; } -- (AutocompleteTextFieldIcon*)iconForEvent:(NSEvent*)theEvent - inRect:(NSRect)cellFrame - ofView:(AutocompleteTextField*)controlView { - const BOOL flipped = [controlView isFlipped]; - const NSPoint location = - [controlView convertPoint:[theEvent locationInWindow] fromView:nil]; - - // Special check for location image, it is not in |-layedOutIcons:|. - const NSRect locationIconFrame = [self locationIconFrameForFrame:cellFrame]; - if (NSMouseInRect(location, locationIconFrame, flipped)) { - // Make up an icon to return. - AutocompleteTextFieldIcon* icon = - [[[AutocompleteTextFieldIcon alloc] - initImageWithView:locationIconView_] autorelease]; - [icon setRect:locationIconFrame]; - return icon; - } - - for (AutocompleteTextFieldIcon* icon in [self layedOutIcons:cellFrame]) { - if (NSMouseInRect(location, [icon rect], flipped)) - return icon; - } - - return nil; -} - -- (NSMenu*)actionMenuForEvent:(NSEvent*)theEvent +- (NSMenu*)actionMenuForEvent:(NSEvent*)event inRect:(NSRect)cellFrame - ofView:(AutocompleteTextField*)controlView { - AutocompleteTextFieldIcon* - icon = [self iconForEvent:theEvent inRect:cellFrame ofView:controlView]; - if (icon) - return [icon view]->GetMenu(); - return nil; -} + ofView:(NSView*)aView { + NSPoint location = [aView convertPoint:[event locationInWindow] fromView:nil]; -- (BOOL)mouseDown:(NSEvent*)theEvent - inRect:(NSRect)cellFrame - ofView:(AutocompleteTextField*)controlView { - AutocompleteTextFieldIcon* icon = - [self iconForEvent:theEvent inRect:cellFrame ofView:controlView]; - if (!icon) - return NO; - - // If the icon is draggable, then initiate a drag if the user drags - // or holds the mouse down for awhile. - if ([icon view]->IsDraggable()) { - NSDate* timeout = - [NSDate dateWithTimeIntervalSinceNow:kLocationIconDragTimeout]; - NSEvent* event = [NSApp nextEventMatchingMask:(NSLeftMouseDraggedMask | - NSLeftMouseUpMask) - untilDate:timeout - inMode:NSEventTrackingRunLoopMode - dequeue:YES]; - if (!event || [event type] == NSLeftMouseDragged) { - NSPasteboard* pboard = [icon view]->GetDragPasteboard(); - DCHECK(pboard); - - // TODO(shess): My understanding is that the -isFlipped - // adjustment should not be necessary. But without it, the - // image is nowhere near the cursor. Perhaps the icon's rect is - // incorrectly calculated? - // http://crbug.com/40711 - NSPoint dragPoint = [icon rect].origin; - if ([controlView isFlipped]) - dragPoint.y += NSHeight([icon rect]); - - [controlView dragImage:[icon view]->GetImage() - at:dragPoint - offset:NSZeroSize - event:event ? event : theEvent - pasteboard:pboard - source:self - slideBack:YES]; - return YES; + const BOOL flipped = [aView isFlipped]; + for (AutocompleteTextFieldIcon* icon in [self layedOutIcons:cellFrame]) { + if (NSMouseInRect(location, [icon rect], flipped)) { + return [icon view]->GetMenu(); } - - // On mouse-up fall through to mouse-pressed case. - DCHECK_EQ([event type], NSLeftMouseUp); } - - [icon view]->OnMousePressed([icon rect]); - return YES; -} - -- (NSDragOperation)draggingSourceOperationMaskForLocal:(BOOL)isLocal { - return NSDragOperationCopy; -} - -- (NSPasteboard*)locationDragPasteboard { - if (locationIconView_ && locationIconView_->IsDraggable()) - return locationIconView_->GetDragPasteboard(); - return nil; } diff --git a/chrome/browser/cocoa/autocomplete_text_field_cell_unittest.mm b/chrome/browser/cocoa/autocomplete_text_field_cell_unittest.mm index 5bd02cc..0a16c48 100644 --- a/chrome/browser/cocoa/autocomplete_text_field_cell_unittest.mm +++ b/chrome/browser/cocoa/autocomplete_text_field_cell_unittest.mm @@ -4,11 +4,9 @@ #import <Cocoa/Cocoa.h> -#include "app/resource_bundle.h" #include "base/scoped_nsobject.h" #import "chrome/browser/cocoa/autocomplete_text_field_cell.h" #import "chrome/browser/cocoa/cocoa_test_helper.h" -#include "grit/theme_resources.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/platform_test.h" @@ -45,7 +43,7 @@ class TestPageActionViewList : public LocationBarViewMac::PageActionViewList { class AutocompleteTextFieldCellTest : public CocoaTest { public: - AutocompleteTextFieldCellTest() : location_icon_view_(NULL), + AutocompleteTextFieldCellTest() : security_image_view_(NULL, NULL, NULL), page_action_views_() { // Make sure this is wide enough to play games with the cell // decorations. @@ -59,8 +57,7 @@ class AutocompleteTextFieldCellTest : public CocoaTest { [[AutocompleteTextFieldCell alloc] initTextCell:@"Testing"]); [cell setEditable:YES]; [cell setBordered:YES]; - [cell setLocationIconView:&location_icon_view_]; - [cell setSecurityLabelView:&security_label_view_]; + [cell setSecurityImageView:&security_image_view_]; [cell setPageActionViewList:&page_action_views_]; [view_ setCell:cell.get()]; @@ -68,8 +65,7 @@ class AutocompleteTextFieldCellTest : public CocoaTest { } NSTextField* view_; - LocationBarViewMac::LocationIconView location_icon_view_; - LocationBarViewMac::LocationBarImageView security_label_view_; + LocationBarViewMac::SecurityImageView security_image_view_; TestPageActionViewList page_action_views_; }; @@ -203,16 +199,15 @@ TEST_F(AutocompleteTextFieldCellTest, TextFrame) { EXPECT_EQ(NSMaxX(bounds), NSMaxX(textFrame)); EXPECT_TRUE(NSContainsRect(cursorFrame, textFrame)); - // Location icon takes up space on the left - location_icon_view_.SetImage( - ResourceBundle::GetSharedInstance().GetNSImageNamed( - IDR_OMNIBOX_HTTPS_VALID)); - location_icon_view_.SetVisible(true); + // Security icon takes up space on the right + security_image_view_.SetImageShown( + LocationBarViewMac::SecurityImageView::LOCK); + security_image_view_.SetVisible(true); textFrame = [cell textFrameForFrame:bounds]; EXPECT_FALSE(NSIsEmptyRect(textFrame)); EXPECT_TRUE(NSContainsRect(bounds, textFrame)); - EXPECT_GT(NSMinX(textFrame), NSMinX(bounds)); + EXPECT_LT(NSMaxX(textFrame), NSMaxX(bounds)); EXPECT_TRUE(NSContainsRect(cursorFrame, textFrame)); // Search hint text takes precedence over the hint icon; the text frame @@ -270,10 +265,9 @@ TEST_F(AutocompleteTextFieldCellTest, DrawingRectForBounds) { EXPECT_TRUE(NSContainsRect(NSInsetRect(textFrame, 1, 1), drawingRect)); EXPECT_TRUE(NSEqualRects(drawingRect, originalDrawingRect)); - location_icon_view_.SetImage( - ResourceBundle::GetSharedInstance().GetNSImageNamed( - IDR_OMNIBOX_HTTPS_VALID)); - location_icon_view_.SetVisible(true); + security_image_view_.SetImageShown( + LocationBarViewMac::SecurityImageView::LOCK); + security_image_view_.SetVisible(true); textFrame = [cell textFrameForFrame:bounds]; drawingRect = [cell drawingRectForBounds:bounds]; @@ -281,60 +275,55 @@ TEST_F(AutocompleteTextFieldCellTest, DrawingRectForBounds) { EXPECT_TRUE(NSContainsRect(NSInsetRect(textFrame, 1, 1), drawingRect)); } -// Test that the location icon is at the right side of the cell. -TEST_F(AutocompleteTextFieldCellTest, LocationIconFrame) { +// Test that the security icon is at the right side of the cell. +TEST_F(AutocompleteTextFieldCellTest, SecurityImageFrame) { AutocompleteTextFieldCell* cell = static_cast<AutocompleteTextFieldCell*>([view_ cell]); const NSRect bounds([view_ bounds]); - location_icon_view_.SetImage( - ResourceBundle::GetSharedInstance().GetNSImageNamed( - IDR_OMNIBOX_HTTPS_VALID)); + security_image_view_.SetImageShown( + LocationBarViewMac::SecurityImageView::LOCK); - location_icon_view_.SetVisible(true); - const NSRect iconRect = [cell locationIconFrameForFrame:bounds]; - EXPECT_FALSE(NSIsEmptyRect(iconRect)); - EXPECT_TRUE(NSContainsRect(bounds, iconRect)); + security_image_view_.SetVisible(false); + EXPECT_EQ(0u, [[cell layedOutIcons:bounds] count]); - // Location icon should be left of |drawingRect|. - const NSRect drawingRect = [cell drawingRectForBounds:bounds]; - EXPECT_GT(NSMinX(drawingRect), NSMinX(iconRect)); + security_image_view_.SetVisible(true); + NSArray* icons = [cell layedOutIcons:bounds]; + ASSERT_EQ(1u, [icons count]); + NSRect iconRect = [[icons objectAtIndex:0] rect]; - // Location icon should be left of |textFrame|. - const NSRect textFrame = [cell textFrameForFrame:bounds]; - EXPECT_GT(NSMinX(textFrame), NSMinX(iconRect)); -} + EXPECT_FALSE(NSIsEmptyRect(iconRect)); + EXPECT_TRUE(NSContainsRect(bounds, iconRect)); -// Test that security label takes space to the right. -TEST_F(AutocompleteTextFieldCellTest, SecurityLabelFrame) { - AutocompleteTextFieldCell* cell = - static_cast<AutocompleteTextFieldCell*>([view_ cell]); - const NSRect bounds([view_ bounds]); + // Make sure we are right of the |drawingRect|. + NSRect drawingRect = [cell drawingRectForBounds:bounds]; + EXPECT_LE(NSMaxX(drawingRect), NSMinX(iconRect)); - // No label shows nothing, regardless of visibility setting. - security_label_view_.SetVisible(false); - const NSRect baseTextFrame = [cell textFrameForFrame:bounds]; - security_label_view_.SetVisible(true); - EXPECT_TRUE(NSEqualRects(baseTextFrame, [cell textFrameForFrame:bounds])); + // Make sure we're right of the |textFrame|. + NSRect textFrame = [cell textFrameForFrame:bounds]; + EXPECT_LE(NSMaxX(textFrame), NSMinX(iconRect)); - // Still not visible even with a label. + // Now add a label. NSFont* font = [NSFont controlContentFontOfSize:12.0]; NSColor* color = [NSColor blackColor]; - security_label_view_.SetLabel(@"Label", font, color); - security_label_view_.SetVisible(false); - EXPECT_TRUE(NSEqualRects(baseTextFrame, [cell textFrameForFrame:bounds])); + security_image_view_.SetLabel(@"Label", font, color); + icons = [cell layedOutIcons:bounds]; + ASSERT_EQ(1u, [icons count]); + iconRect = [[icons objectAtIndex:0] rect]; - // Visible with a label is strictly narrower than without. - security_label_view_.SetVisible(true); - NSRect textFrame = [cell textFrameForFrame:bounds]; - const CGFloat labelWidth = [security_label_view_.GetLabel() size].width; - EXPECT_TRUE(NSContainsRect(baseTextFrame, textFrame)); - EXPECT_LT(NSWidth(textFrame), NSWidth(baseTextFrame) - labelWidth); + EXPECT_FALSE(NSIsEmptyRect(iconRect)); + EXPECT_TRUE(NSContainsRect(bounds, iconRect)); - NSString* longLabel = - @"Really super-long labels will not show up if there's not enough room."; - security_label_view_.SetLabel(longLabel, font, color); + // Make sure we are right of the |drawingRect|. + drawingRect = [cell drawingRectForBounds:bounds]; + EXPECT_LE(NSMaxX(drawingRect), NSMinX(iconRect)); + + // Make sure we're right of the |textFrame|. textFrame = [cell textFrameForFrame:bounds]; - EXPECT_TRUE(NSEqualRects(baseTextFrame, [cell textFrameForFrame:bounds])); + EXPECT_LE(NSMaxX(textFrame), NSMinX(iconRect)); + + // Make sure we clear correctly. + security_image_view_.SetVisible(false); + EXPECT_EQ(0u, [[cell layedOutIcons:bounds] count]); } // Test Page Action counts. @@ -360,6 +349,8 @@ TEST_F(AutocompleteTextFieldCellTest, PageActionImageFrame) { AutocompleteTextFieldCell* cell = static_cast<AutocompleteTextFieldCell*>([view_ cell]); const NSRect bounds([view_ bounds]); + security_image_view_.SetImageShown( + LocationBarViewMac::SecurityImageView::LOCK); TestPageActionImageView page_action_view; // We'll assume that the extensions code enforces icons smaller than the @@ -377,12 +368,13 @@ TEST_F(AutocompleteTextFieldCellTest, PageActionImageFrame) { list.Add(&page_action_view2); [cell setPageActionViewList:&list]; + security_image_view_.SetVisible(false); page_action_view.SetVisible(false); page_action_view2.SetVisible(false); EXPECT_TRUE(NSIsEmptyRect([cell pageActionFrameForIndex:0 inFrame:bounds])); EXPECT_TRUE(NSIsEmptyRect([cell pageActionFrameForIndex:1 inFrame:bounds])); - // One page action, no lock icon. + // One page action, no security icon. page_action_view.SetVisible(true); NSRect iconRect0 = [cell pageActionFrameForIndex:0 inFrame:bounds]; @@ -397,19 +389,17 @@ TEST_F(AutocompleteTextFieldCellTest, PageActionImageFrame) { NSRect textFrame = [cell textFrameForFrame:bounds]; EXPECT_LE(NSMaxX(textFrame), NSMinX(iconRect0)); - // Two page actions plus a security label. + // Two page actions plus a security icon. page_action_view2.SetVisible(true); + security_image_view_.SetVisible(true); NSArray* icons = [cell layedOutIcons:bounds]; - ASSERT_EQ(2u, [icons count]); - - // TODO(shess): page-action list is inverted from -layedOutIcons: - // Yes, this is confusing, fix it. + EXPECT_EQ(3u, [icons count]); iconRect0 = [cell pageActionFrameForIndex:0 inFrame:bounds]; NSRect iconRect1 = [cell pageActionFrameForIndex:1 inFrame:bounds]; - NSRect labelRect = [[icons objectAtIndex:0] rect]; + NSRect lockRect = [[icons objectAtIndex:0] rect]; EXPECT_TRUE(NSEqualRects(iconRect0, [[icons objectAtIndex:1] rect])); - EXPECT_TRUE(NSEqualRects(iconRect1, [[icons objectAtIndex:0] rect])); + EXPECT_TRUE(NSEqualRects(iconRect1, [[icons objectAtIndex:2] rect])); // Make sure they're all in the expected order, and right of the |drawingRect| // and |textFrame|. @@ -420,13 +410,13 @@ TEST_F(AutocompleteTextFieldCellTest, PageActionImageFrame) { EXPECT_TRUE(NSContainsRect(bounds, iconRect0)); EXPECT_FALSE(NSIsEmptyRect(iconRect1)); EXPECT_TRUE(NSContainsRect(bounds, iconRect1)); - EXPECT_FALSE(NSIsEmptyRect(labelRect)); - EXPECT_TRUE(NSContainsRect(bounds, labelRect)); + EXPECT_FALSE(NSIsEmptyRect(lockRect)); + EXPECT_TRUE(NSContainsRect(bounds, lockRect)); EXPECT_LE(NSMaxX(drawingRect), NSMinX(iconRect1)); EXPECT_LE(NSMaxX(textFrame), NSMinX(iconRect1)); EXPECT_LE(NSMaxX(iconRect1), NSMinX(iconRect0)); - EXPECT_LE(NSMaxX(labelRect), NSMinX(iconRect0)); + EXPECT_LE(NSMaxX(iconRect0), NSMinX(lockRect)); } // Test that the cell correctly chooses the partial keyword if there's @@ -438,22 +428,11 @@ TEST_F(AutocompleteTextFieldCellTest, UsesPartialKeywordIfNarrow) { const NSString* kFullString = @"Search Engine:"; const NSString* kPartialString = @"Search Eng:"; - // Wide width chooses the full string, including an image on the - // left. + // Wide width chooses the full string. [cell setKeywordString:kFullString partialString:kPartialString availableWidth:kWidth]; EXPECT_TRUE([cell keywordString]); - EXPECT_TRUE([[[cell keywordString] string] hasSuffix:kFullString]); - EXPECT_TRUE([[cell keywordString] containsAttachments]); - - // If not enough space to include the image, uses exactly the full - // string. - CGFloat allWidth = [[cell keywordString] size].width; - [cell setKeywordString:kFullString - partialString:kPartialString - availableWidth:allWidth - 5.0]; - EXPECT_TRUE([cell keywordString]); EXPECT_TRUE([[[cell keywordString] string] isEqualToString:kFullString]); // Narrow width chooses the partial string. diff --git a/chrome/browser/cocoa/autocomplete_text_field_editor.mm b/chrome/browser/cocoa/autocomplete_text_field_editor.mm index 974b346..70aa5cd 100644 --- a/chrome/browser/cocoa/autocomplete_text_field_editor.mm +++ b/chrome/browser/cocoa/autocomplete_text_field_editor.mm @@ -33,35 +33,6 @@ class Extension; return self; } -// If the entire field is selected, drag the same data as would be -// dragged from the field's location icon. In some cases the textual -// contents will not contain relevant data (for instance, "http://" is -// stripped from URLs). -- (BOOL)dragSelectionWithEvent:(NSEvent *)event - offset:(NSSize)mouseOffset - slideBack:(BOOL)slideBack { - const NSRange allRange = NSMakeRange(0, [[self textStorage] length]); - if (NSEqualRanges(allRange, [self selectedRange])) { - NSPasteboard* pboard = [[self delegate] locationDragPasteboard]; - if (pboard) { - NSPoint p; - NSImage* image = [self dragImageForSelectionWithEvent:event origin:&p]; - - [self dragImage:image - at:p - offset:mouseOffset - event:event - pasteboard:pboard - source:self - slideBack:slideBack]; - return YES; - } - } - return [super dragSelectionWithEvent:event - offset:mouseOffset - slideBack:slideBack]; -} - - (void)copy:(id)sender { AutocompleteTextFieldObserver* observer = [self observer]; DCHECK(observer); diff --git a/chrome/browser/cocoa/autocomplete_text_field_unittest.mm b/chrome/browser/cocoa/autocomplete_text_field_unittest.mm index 1d0ae49..d695f86 100644 --- a/chrome/browser/cocoa/autocomplete_text_field_unittest.mm +++ b/chrome/browser/cocoa/autocomplete_text_field_unittest.mm @@ -4,7 +4,6 @@ #import <Cocoa/Cocoa.h> -#include "app/resource_bundle.h" #import "base/cocoa_protocols_mac.h" #include "base/scoped_nsobject.h" #import "chrome/browser/cocoa/autocomplete_text_field.h" @@ -12,7 +11,6 @@ #import "chrome/browser/cocoa/autocomplete_text_field_editor.h" #import "chrome/browser/cocoa/autocomplete_text_field_unittest_helper.h" #import "chrome/browser/cocoa/cocoa_test_helper.h" -#include "grit/theme_resources.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/platform_test.h" @@ -22,34 +20,18 @@ using ::testing::Return; using ::testing::StrictMock; namespace { -class MockLocationIconView : public LocationBarViewMac::LocationIconView { +class MockSecurityImageView : public LocationBarViewMac::SecurityImageView { public: - MockLocationIconView() - : LocationBarViewMac::LocationIconView(NULL), - is_draggable_(false), - mouse_was_pressed_(false) {} - - // |LocationBarViewMac::LocationIconView| dragging support needs - // more setup than this test provides. - bool IsDraggable() { - return is_draggable_; - } - virtual NSPasteboard* GetDragPasteboard() { - return [NSPasteboard pasteboardWithUniqueName]; - } - void SetDraggable(bool is_draggable) { - is_draggable_ = is_draggable; - } + MockSecurityImageView(LocationBarViewMac* owner, + Profile* profile, + ToolbarModel* model) + : LocationBarViewMac::SecurityImageView(owner, profile, model) {} // We can't use gmock's MOCK_METHOD macro, because it doesn't like the // NSRect argument to OnMousePressed. virtual void OnMousePressed(NSRect bounds) { mouse_was_pressed_ = true; } - bool MouseWasPressed() { return mouse_was_pressed_; } - - private: - bool is_draggable_; bool mouse_was_pressed_; }; @@ -600,35 +582,32 @@ TEST_F(AutocompleteTextFieldTest, TripleClickSelectsAll) { } // Clicking the security icon should call its OnMousePressed. -TEST_F(AutocompleteTextFieldTest, LocationIconMouseDown) { +TEST_F(AutocompleteTextFieldObserverTest, SecurityIconMouseDown) { AutocompleteTextFieldCell* cell = [field_ autocompleteTextFieldCell]; - MockLocationIconView location_icon_view; - [cell setLocationIconView:&location_icon_view]; - location_icon_view.SetImage( - ResourceBundle::GetSharedInstance().GetNSImageNamed( - IDR_OMNIBOX_HTTPS_VALID)); - location_icon_view.SetVisible(true); + MockSecurityImageView security_image_view(NULL, NULL, NULL); + [cell setSecurityImageView:&security_image_view]; + security_image_view.SetImageShown( + LocationBarViewMac::SecurityImageView::LOCK); + security_image_view.SetVisible(true); - NSRect iconFrame([cell locationIconFrameForFrame:[field_ bounds]]); + NSRect iconFrame([cell securityImageFrameForFrame:[field_ bounds]]); NSPoint location(NSMakePoint(NSMidX(iconFrame), NSMidY(iconFrame))); - NSEvent* downEvent(Event(field_, location, NSLeftMouseDown, 1)); - NSEvent* upEvent(Event(field_, location, NSLeftMouseUp, 1)); - - // Since location icon can be dragged, the mouse-press is sent on - // mouse-up. - [NSApp postEvent:upEvent atStart:YES]; - [field_ mouseDown:downEvent]; - EXPECT_TRUE(location_icon_view.MouseWasPressed()); + NSEvent* event(Event(field_, location, NSLeftMouseDown, 1)); - // TODO(shess): Test that mouse drags are initiated if the next - // event is a drag, or if the mouse-up takes too long to arrive. + [field_ mouseDown:event]; + EXPECT_TRUE(security_image_view.mouse_was_pressed_); } // Clicking a Page Action icon should call its OnMousePressed. -TEST_F(AutocompleteTextFieldTest, PageActionMouseDown) { +TEST_F(AutocompleteTextFieldObserverTest, PageActionMouseDown) { AutocompleteTextFieldCell* cell = [field_ autocompleteTextFieldCell]; + MockSecurityImageView security_image_view(NULL, NULL, NULL); + security_image_view.SetImageShown( + LocationBarViewMac::SecurityImageView::LOCK); + [cell setSecurityImageView:&security_image_view]; + MockPageActionImageView page_action_view; NSImage* image = [NSImage imageNamed:@"NSApplicationIcon"]; page_action_view.SetImage(image); @@ -641,7 +620,8 @@ TEST_F(AutocompleteTextFieldTest, PageActionMouseDown) { list.Add(&page_action_view2); [cell setPageActionViewList:&list]; - // One page action. + // One page action, no security lock. + security_image_view.SetVisible(false); page_action_view.SetVisible(true); page_action_view2.SetVisible(false); NSRect iconFrame([cell pageActionFrameForIndex:0 inFrame:[field_ bounds]]); @@ -651,7 +631,7 @@ TEST_F(AutocompleteTextFieldTest, PageActionMouseDown) { [field_ mouseDown:event]; EXPECT_TRUE(page_action_view.MouseWasPressed()); - // Two page actions, no lock. + // Two page actions, no security lock. page_action_view2.SetVisible(true); iconFrame = [cell pageActionFrameForIndex:0 inFrame:[field_ bounds]]; location = NSMakePoint(NSMidX(iconFrame), NSMidY(iconFrame)); @@ -667,7 +647,8 @@ TEST_F(AutocompleteTextFieldTest, PageActionMouseDown) { [field_ mouseDown:event]; EXPECT_TRUE(page_action_view.MouseWasPressed()); - // Two page actions. + // Two page actions plus security lock. + security_image_view.SetVisible(true); iconFrame = [cell pageActionFrameForIndex:0 inFrame:[field_ bounds]]; location = NSMakePoint(NSMidX(iconFrame), NSMidY(iconFrame)); event = Event(field_, location, NSLeftMouseDown, 1); @@ -681,6 +662,13 @@ TEST_F(AutocompleteTextFieldTest, PageActionMouseDown) { [field_ mouseDown:event]; EXPECT_TRUE(page_action_view.MouseWasPressed()); + + iconFrame = [cell securityImageFrameForFrame:[field_ bounds]]; + location = NSMakePoint(NSMidX(iconFrame), NSMidY(iconFrame)); + event = Event(field_, location, NSLeftMouseDown, 1); + + [field_ mouseDown:event]; + EXPECT_TRUE(security_image_view.mouse_was_pressed_); } // Test that page action menus are properly returned. @@ -872,22 +860,4 @@ TEST_F(AutocompleteTextFieldObserverTest, SendsOnResignKey) { [test_window() resignKeyWindow]; } -TEST_F(AutocompleteTextFieldTest, LocationDragPasteboard) { - AutocompleteTextFieldCell* cell = [field_ autocompleteTextFieldCell]; - - MockLocationIconView location_icon_view; - location_icon_view.SetImage( - ResourceBundle::GetSharedInstance().GetNSImageNamed( - IDR_OMNIBOX_HTTPS_VALID)); - location_icon_view.SetVisible(true); - [cell setLocationIconView:&location_icon_view]; - - // Not draggable, so no pasteboard. - EXPECT_FALSE([field_ locationDragPasteboard]); - - // Gets a pasteboard when draggable. - location_icon_view.SetDraggable(true); - EXPECT_TRUE([field_ locationDragPasteboard]); -} - } // namespace diff --git a/chrome/browser/cocoa/bookmark_bubble_controller.mm b/chrome/browser/cocoa/bookmark_bubble_controller.mm index 465691e..fc2ff7b 100644 --- a/chrome/browser/cocoa/bookmark_bubble_controller.mm +++ b/chrome/browser/cocoa/bookmark_bubble_controller.mm @@ -98,7 +98,7 @@ [BrowserWindowController browserWindowControllerForWindow:parentWindow_]; [bwc lockBarVisibilityForOwner:self withAnimation:NO delay:NO]; NSWindow* window = [self window]; // completes nib load - [bubble_ setArrowLocation:kTopRight]; + [bubble_ setArrowLocation:kTopLeft]; // Insure decent positioning even in the absence of a browser controller, // which will occur for some unit tests. NSPoint arrowtip = bwc ? [bwc pointForBubbleArrowTip] : diff --git a/chrome/browser/cocoa/browser_test_helper.h b/chrome/browser/cocoa/browser_test_helper.h index b7e3e64..0420c7a 100644 --- a/chrome/browser/cocoa/browser_test_helper.h +++ b/chrome/browser/cocoa/browser_test_helper.h @@ -25,15 +25,6 @@ class BrowserTestHelper { profile_.reset(new TestingProfile()); profile_->CreateBookmarkModel(true); profile_->BlockUntilBookmarkModelLoaded(); - - // TODO(shess): These are needed in case someone creates a browser - // window off of browser_. pkasting indicates that other - // platforms use a stub |BrowserWindow| and thus don't need to do - // this. - // http://crbug.com/39725 - profile_->CreateAutocompleteClassifier(); - profile_->CreateTemplateURLModel(); - browser_.reset(new Browser(Browser::TYPE_NORMAL, profile_.get())); } diff --git a/chrome/browser/cocoa/browser_window_controller.mm b/chrome/browser/cocoa/browser_window_controller.mm index ceee615..101807d 100644 --- a/chrome/browser/cocoa/browser_window_controller.mm +++ b/chrome/browser/cocoa/browser_window_controller.mm @@ -1375,7 +1375,7 @@ } - (NSPoint)pointForBubbleArrowTip { - NSRect rect = [toolbarController_ starIconInWindowCoordinates]; + NSRect rect = [toolbarController_ starButtonInWindowCoordinates]; // Determine the point of the arrow of the bubble window. NSPoint p = rect.origin; p.x += (NSWidth(rect) / 2.0) + 1.0; // Star is not exactly in center. diff --git a/chrome/browser/cocoa/browser_window_controller_unittest.mm b/chrome/browser/cocoa/browser_window_controller_unittest.mm index d6a3dca..5b054fa 100644 --- a/chrome/browser/cocoa/browser_window_controller_unittest.mm +++ b/chrome/browser/cocoa/browser_window_controller_unittest.mm @@ -437,10 +437,10 @@ TEST_F(BrowserWindowControllerTest, TestTopRightForBubble) { NSPoint p = [controller_ pointForBubbleArrowTip]; NSRect all = [[controller_ window] frame]; - // As a sanity check make sure the point is vaguely in the top right + // As a sanity check make sure the point is vaguely in the top left // of the window. EXPECT_GT(p.y, all.origin.y + (all.size.height/2)); - EXPECT_GT(p.x, all.origin.x + (all.size.width/2)); + EXPECT_LT(p.x, all.origin.x + (all.size.width/2)); } // By the "zoom frame", we mean what Apple calls the "standard frame". diff --git a/chrome/browser/cocoa/location_bar_view_mac.h b/chrome/browser/cocoa/location_bar_view_mac.h index 66584f0..2107ec3 100644 --- a/chrome/browser/cocoa/location_bar_view_mac.h +++ b/chrome/browser/cocoa/location_bar_view_mac.h @@ -24,6 +24,7 @@ #include "third_party/skia/include/core/SkBitmap.h" @class AutocompleteTextField; +class BubblePositioner; class CommandUpdater; class ContentSettingImageModel; @class ExtensionPopupController; @@ -40,6 +41,7 @@ class LocationBarViewMac : public AutocompleteEditController, public NotificationObserver { public: LocationBarViewMac(AutocompleteTextField* field, + const BubblePositioner* bubble_positioner, CommandUpdater* command_updater, ToolbarModel* toolbar_model, Profile* profile, @@ -62,9 +64,6 @@ class LocationBarViewMac : public AutocompleteEditController, virtual void InvalidatePageActions(); virtual void SaveStateToContents(TabContents* contents); virtual void Revert(); - virtual const AutocompleteEditView* location_entry() const { - return edit_view_.get(); - } virtual AutocompleteEditView* location_entry() { return edit_view_.get(); } @@ -77,13 +76,6 @@ class LocationBarViewMac : public AutocompleteEditController, virtual ExtensionAction* GetVisiblePageAction(size_t index); virtual void TestPageActionPressed(size_t index); - // Set/Get the editable state of the field. - void SetEditable(bool editable); - bool IsEditable(); - - // Set the starred state of the bookmark star. - void SetStarred(bool starred); - // Updates the location bar. Resets the bar's permanent text and // security style, and if |should_restore_state| is true, restores // saved state from the tab (for tab switching). @@ -132,6 +124,7 @@ class LocationBarViewMac : public AutocompleteEditController, const std::wstring& keyword, const std::wstring& short_name, const bool is_keyword_hint, + const bool show_search_hint, NSImage* image); // Overridden from NotificationObserver. @@ -149,9 +142,7 @@ class LocationBarViewMac : public AutocompleteEditController, // Sets the image. void SetImage(NSImage* image); - - // Get the |resource_id| image resource and set the image. - void SetIcon(int resource_id); + void SetImage(SkBitmap* image); // Sets the label text, font, and color. |text| may be nil; |color| and // |font| are ignored if |text| is nil. @@ -165,21 +156,9 @@ class LocationBarViewMac : public AutocompleteEditController, const NSAttributedString* GetLabel() const { return label_; } bool IsVisible() const { return visible_; } - // Default size when no image is present. - virtual NSSize GetDefaultImageSize() const; - - // Returns the size of the image, else the default size. - NSSize GetImageSize() const; - // Returns the tooltip for this image view or |nil| if there is none. virtual const NSString* GetToolTip() { return nil; } - // Used to determinate if the item can act as a drag source. - virtual bool IsDraggable() { return false; } - - // The drag pasteboard to use if a drag is initiated. - virtual NSPasteboard* GetDragPasteboard() { return nil; } - // Called on mouse down. virtual void OnMousePressed(NSRect bounds) {} @@ -197,50 +176,42 @@ class LocationBarViewMac : public AutocompleteEditController, DISALLOW_COPY_AND_ASSIGN(LocationBarImageView); }; - // LocationIconView is used to display an icon to the left of the address. - class LocationIconView : public LocationBarImageView { + // SecurityImageView is used to display the lock or warning icon when the + // current URL's scheme is https. + class SecurityImageView : public LocationBarImageView { public: - explicit LocationIconView(LocationBarViewMac* owner); - virtual ~LocationIconView(); + enum Image { + LOCK = 0, + WARNING + }; - // Is draggable if the autocomplete edit view has not be changed. - virtual bool IsDraggable(); + SecurityImageView(LocationBarViewMac* owner, + Profile* profile, + ToolbarModel* model); + virtual ~SecurityImageView(); - // Drag the URL and title from the current tab. - virtual NSPasteboard* GetDragPasteboard(); + // Sets the image to the appropriate icon. + void SetImageShown(Image image); // Shows the page info dialog. virtual void OnMousePressed(NSRect bounds); private: - // The location bar view that owns us. - LocationBarViewMac* owner_; + // The lock icon shown when using HTTPS. Loaded lazily, the first time it's + // needed. + scoped_nsobject<NSImage> lock_icon_; - DISALLOW_COPY_AND_ASSIGN(LocationIconView); - }; - - // Used to display the bookmark star in the RHS. - class StarIconView : public LocationBarImageView { - public: - explicit StarIconView(CommandUpdater* command_updater); - virtual ~StarIconView() {} + // The warning icon shown when HTTPS is broken. Loaded lazily, the first + // time it's needed. + scoped_nsobject<NSImage> warning_icon_; - // Shows the bookmark bubble. - virtual void OnMousePressed(NSRect bounds); - - // Set the image and tooltip based on |starred|. - void SetStarred(bool starred); - - virtual const NSString* GetToolTip(); - - private: - // For bringing up bookmark bar. - CommandUpdater* command_updater_; // Weak, owned by Browser. + // The location bar view that owns us. + LocationBarViewMac* owner_; - // The string to show for a tooltip. - scoped_nsobject<NSString> tooltip_; + Profile* profile_; + ToolbarModel* model_; - DISALLOW_COPY_AND_ASSIGN(StarIconView); + DISALLOW_COPY_AND_ASSIGN(SecurityImageView); }; // PageActionImageView is used to display the icon for a given Page Action @@ -260,13 +231,14 @@ class LocationBarViewMac : public AutocompleteEditController, void set_preview_enabled(bool enabled) { preview_enabled_ = enabled; } - bool preview_enabled() const { return preview_enabled_; } + bool preview_enabled() { return preview_enabled_; } + // Returns the size of the image, or a default size if no image available. // When a new page action is created, all the icons are destroyed and // recreated; at this point we need to calculate sizes to lay out the // icons even though no images are available yet. For this case, we return // the default image size for a page icon. - virtual NSSize GetDefaultImageSize() const; + virtual NSSize GetPreferredImageSize(); // Either notify listeners or show a popup depending on the Page Action. virtual void OnMousePressed(NSRect bounds); @@ -412,11 +384,11 @@ class LocationBarViewMac : public AutocompleteEditController, }; private: - // Sets the location icon we should be showing. - void SetIcon(int resource_id); + // Sets the SSL icon we should be showing. + void SetSecurityIcon(ToolbarModel::Icon icon); - // Sets the label for the SSL state. - void SetSecurityLabel(); + // Sets the label for the SSL icon. + void SetSecurityIconLabel(); // Posts |notification| to the default notification center. void PostNotification(const NSString* notification); @@ -439,14 +411,8 @@ class LocationBarViewMac : public AutocompleteEditController, // The user's desired disposition for how their input should be opened. WindowOpenDisposition disposition_; - // A view that shows an icon to the left of the address. - LocationIconView location_icon_view_; - - // Security info as text which floats left of the page actions. - LocationBarImageView security_label_view_; - - // Bookmark star right of page actions. - StarIconView star_icon_view_; + // The view that shows the lock/warning when in HTTPS mode. + SecurityImageView security_image_view_; // Any installed Page Actions. PageActionViewList page_action_views_; diff --git a/chrome/browser/cocoa/location_bar_view_mac.mm b/chrome/browser/cocoa/location_bar_view_mac.mm index 6e33130..62b12d4 100644 --- a/chrome/browser/cocoa/location_bar_view_mac.mm +++ b/chrome/browser/cocoa/location_bar_view_mac.mm @@ -41,7 +41,6 @@ #include "grit/generated_resources.h" #include "grit/theme_resources.h" #include "skia/ext/skia_utils_mac.h" -#import "third_party/mozilla/NSPasteboard+Utils.h" // TODO(shess): This code is mostly copied from the gtk @@ -63,13 +62,11 @@ std::wstring GetKeywordName(Profile* profile, const std::wstring& keyword) { return std::wstring(); } -// Values for the label colors for different security states. -static const CGFloat kEVSecureTextColorRedComponent = 0.03; -static const CGFloat kEVSecureTextColorGreenComponent = 0.58; -static const CGFloat kEVSecureTextColorBlueComponent = 0.0; -static const CGFloat kSecurityErrorTextColorRedComponent = 0.63; -static const CGFloat kSecurityErrorTextColorGreenComponent = 0.0; -static const CGFloat kSecurityErrorTextColorBlueComponent = 0.0; +// Values for the green text color displayed for EV certificates, based +// on the values for kEvTextColor in location_bar_view_gtk.cc. +static const CGFloat kEvTextColorRedComponent = 0.0; +static const CGFloat kEvTextColorGreenComponent = 0.59; +static const CGFloat kEvTextColorBlueComponent = 0.08; // Build a short string to use in keyword-search when the field isn't // very big. @@ -94,18 +91,17 @@ std::wstring CalculateMinString(const std::wstring& description) { LocationBarViewMac::LocationBarViewMac( AutocompleteTextField* field, + const BubblePositioner* bubble_positioner, CommandUpdater* command_updater, ToolbarModel* toolbar_model, Profile* profile, Browser* browser) - : edit_view_(new AutocompleteEditViewMac(this, toolbar_model, profile, - command_updater, field)), + : edit_view_(new AutocompleteEditViewMac(this, bubble_positioner, + toolbar_model, profile, command_updater, field)), command_updater_(command_updater), field_(field), disposition_(CURRENT_TAB), - location_icon_view_(this), - security_label_view_(), - star_icon_view_(command_updater), + security_image_view_(this, profile, toolbar_model), page_action_views_(this, profile, toolbar_model), profile_(profile), browser_(browser), @@ -120,9 +116,7 @@ LocationBarViewMac::LocationBarViewMac( } AutocompleteTextFieldCell* cell = [field_ autocompleteTextFieldCell]; - [cell setLocationIconView:&location_icon_view_]; - [cell setSecurityLabelView:&security_label_view_]; - [cell setStarIconView:&star_icon_view_]; + [cell setSecurityImageView:&security_image_view_]; [cell setPageActionViewList:&page_action_views_]; [cell setContentSettingViewsList:&content_setting_views_]; @@ -135,9 +129,7 @@ LocationBarViewMac::~LocationBarViewMac() { // Disconnect from cell in case it outlives us. AutocompleteTextFieldCell* cell = [field_ autocompleteTextFieldCell]; [cell setPageActionViewList:NULL]; - [cell setLocationIconView:NULL]; - [cell setSecurityLabelView:NULL]; - [cell setStarIconView:NULL]; + [cell setSecurityImageView:NULL]; } std::wstring LocationBarViewMac::GetInputString() const { @@ -214,7 +206,7 @@ void LocationBarViewMac::SaveStateToContents(TabContents* contents) { void LocationBarViewMac::Update(const TabContents* contents, bool should_restore_state) { - SetIcon(edit_view_->GetIcon()); + SetSecurityIcon(toolbar_model_->GetIcon()); page_action_views_.RefreshViews(); RefreshContentSettingsViews(); // AutocompleteEditView restores state if the tab is non-NULL. @@ -260,6 +252,7 @@ void LocationBarViewMac::OnChangedImpl(AutocompleteTextField* field, const std::wstring& keyword, const std::wstring& short_name, const bool is_keyword_hint, + const bool show_search_hint, NSImage* image) { AutocompleteTextFieldCell* cell = [field autocompleteTextFieldCell]; const CGFloat availableWidth([field availableDecorationWidth]); @@ -305,6 +298,12 @@ void LocationBarViewMac::OnChangedImpl(AutocompleteTextField* field, [cell setKeywordHintPrefix:prefix image:image suffix:suffix availableWidth:availableWidth]; + } else if (show_search_hint) { + // Show a search hint right-justified in the field if there is no + // keyword. + const std::wstring hint(l10n_util::GetString(IDS_OMNIBOX_EMPTY_TEXT)); + [cell setSearchHintString:base::SysWideToNSString(hint) + availableWidth:availableWidth]; } else { // Nothing interesting to show, plain old text field. [cell clearKeywordAndHint]; @@ -331,6 +330,7 @@ void LocationBarViewMac::OnChanged() { keyword, short_name, edit_view_->model()->is_keyword_hint(), + edit_view_->model()->show_search_hint(), GetTabButtonImage()); } @@ -444,22 +444,6 @@ void LocationBarViewMac::TestPageActionPressed(size_t index) { page_action_views_.OnMousePressed(NSZeroRect, index); } -void LocationBarViewMac::SetEditable(bool editable) { - [field_ setEditable:editable ? YES : NO]; - star_icon_view_.SetVisible(editable); - UpdatePageActions(); -} - -bool LocationBarViewMac::IsEditable() { - return [field_ isEditable] ? true : false; -} - -void LocationBarViewMac::SetStarred(bool starred) { - star_icon_view_.SetStarred(starred); - [field_ updateCursorAndToolTipRects]; - [field_ resetFieldEditorFrameIfNeeded]; -} - NSImage* LocationBarViewMac::GetTabButtonImage() { if (!tab_button_image_) { SkBitmap* skiaBitmap = ResourceBundle::GetSharedInstance(). @@ -471,37 +455,44 @@ NSImage* LocationBarViewMac::GetTabButtonImage() { return tab_button_image_; } -void LocationBarViewMac::SetIcon(int resource_id) { - DCHECK(resource_id != 0); - - // The icon is always visible except when there is a keyword hint. - if (!edit_view_->model()->keyword().empty() && - !edit_view_->model()->is_keyword_hint()) { - location_icon_view_.SetVisible(false); +void LocationBarViewMac::SetSecurityIconLabel() { + std::wstring info_text; + std::wstring info_tooltip; + ToolbarModel::InfoTextType info_text_type = + toolbar_model_->GetInfoText(&info_text, &info_tooltip); + if (info_text_type == ToolbarModel::INFO_EV_TEXT) { + NSString* icon_label = base::SysWideToNSString(info_text); + NSColor* color = [NSColor colorWithCalibratedRed:kEvTextColorRedComponent + green:kEvTextColorGreenComponent + blue:kEvTextColorBlueComponent + alpha:1.0]; + security_image_view_.SetLabel(icon_label, [field_ font], color); } else { - NSImage* image = AutocompleteEditViewMac::ImageForResource(resource_id); - location_icon_view_.SetImage(image); - location_icon_view_.SetVisible(true); - SetSecurityLabel(); + security_image_view_.SetLabel(nil, nil, nil); } - [field_ resetFieldEditorFrameIfNeeded]; } -void LocationBarViewMac::SetSecurityLabel() { - if (toolbar_model_->GetSecurityLevel() == ToolbarModel::EV_SECURE) { - std::wstring security_info_text(toolbar_model_->GetEVCertName()); - NSString* icon_label = base::SysWideToNSString(security_info_text); - NSColor* color = - [NSColor colorWithCalibratedRed:kEVSecureTextColorRedComponent - green:kEVSecureTextColorGreenComponent - blue:kEVSecureTextColorBlueComponent - alpha:1.0]; - security_label_view_.SetLabel(icon_label, [field_ font], color); - security_label_view_.SetVisible(true); - } else { - security_label_view_.SetLabel(nil, nil, nil); - security_label_view_.SetVisible(false); +void LocationBarViewMac::SetSecurityIcon(ToolbarModel::Icon icon) { + switch (icon) { + case ToolbarModel::LOCK_ICON: + security_image_view_.SetImageShown(SecurityImageView::LOCK); + security_image_view_.SetVisible(true); + SetSecurityIconLabel(); + break; + case ToolbarModel::WARNING_ICON: + security_image_view_.SetImageShown(SecurityImageView::WARNING); + security_image_view_.SetVisible(true); + SetSecurityIconLabel(); + break; + case ToolbarModel::NO_ICON: + security_image_view_.SetVisible(false); + break; + default: + NOTREACHED(); + security_image_view_.SetVisible(false); + break; } + [field_ resetFieldEditorFrameIfNeeded]; } void LocationBarViewMac::Observe(NotificationType type, @@ -544,9 +535,8 @@ void LocationBarViewMac::LocationBarImageView::SetImage(NSImage* image) { image_.reset([image retain]); } -void LocationBarViewMac::LocationBarImageView::SetIcon(int resource_id) { - ResourceBundle& rb = ResourceBundle::GetSharedInstance(); - SetImage(rb.GetNSImageNamed(resource_id)); +void LocationBarViewMac::LocationBarImageView::SetImage(SkBitmap* image) { + SetImage(gfx::SkBitmapToNSImage(*image)); } void LocationBarViewMac::LocationBarImageView::SetLabel(NSString* text, @@ -574,32 +564,43 @@ void LocationBarViewMac::LocationBarImageView::SetVisible(bool visible) { visible_ = visible; } -NSSize LocationBarViewMac::LocationBarImageView::GetDefaultImageSize() const { - return NSZeroSize; -} +// SecurityImageView------------------------------------------------------------ -NSSize LocationBarViewMac::LocationBarImageView::GetImageSize() const { - NSImage* image = GetImage(); - if (image) - return [image size]; - return GetDefaultImageSize(); -} +LocationBarViewMac::SecurityImageView::SecurityImageView( + LocationBarViewMac* owner, + Profile* profile, + ToolbarModel* model) + : lock_icon_(nil), + warning_icon_(nil), + owner_(owner), + profile_(profile), + model_(model) {} -// LocationIconView ------------------------------------------------------------ +LocationBarViewMac::SecurityImageView::~SecurityImageView() {} -LocationBarViewMac::LocationIconView::LocationIconView( - LocationBarViewMac* owner) - : owner_(owner) { +void LocationBarViewMac::SecurityImageView::SetImageShown(Image image) { + switch (image) { + case LOCK: + if (!lock_icon_.get()) { + ResourceBundle& rb = ResourceBundle::GetSharedInstance(); + lock_icon_.reset([rb.GetNSImageNamed(IDR_LOCK) retain]); + } + SetImage(lock_icon_); + break; + case WARNING: + if (!warning_icon_.get()) { + ResourceBundle& rb = ResourceBundle::GetSharedInstance(); + warning_icon_.reset([rb.GetNSImageNamed(IDR_WARNING) retain]); + } + SetImage(warning_icon_); + break; + default: + NOTREACHED(); + break; + } } -LocationBarViewMac::LocationIconView::~LocationIconView() {} - -void LocationBarViewMac::LocationIconView::OnMousePressed(NSRect bounds) { - // Do not show page info if the user has been editing the location - // bar, or the location bar is at the NTP. - if (owner_->location_entry()->IsEditingOrEmpty()) - return; - +void LocationBarViewMac::SecurityImageView::OnMousePressed(NSRect bounds) { TabContents* tab = owner_->GetTabContents(); NavigationEntry* nav_entry = tab->controller().GetActiveEntry(); if (!nav_entry) { @@ -609,57 +610,6 @@ void LocationBarViewMac::LocationIconView::OnMousePressed(NSRect bounds) { tab->ShowPageInfo(nav_entry->url(), nav_entry->ssl(), true); } -bool LocationBarViewMac::LocationIconView::IsDraggable() { - // Do not drag if the user has been editing the location bar, or the - // location bar is at the NTP. - if (owner_->location_entry()->IsEditingOrEmpty()) - return false; - - return true; -} - -NSPasteboard* LocationBarViewMac::LocationIconView::GetDragPasteboard() { - TabContents* tab = owner_->GetTabContents(); - DCHECK(tab); - - NSString* url = base::SysUTF8ToNSString(tab->GetURL().spec()); - NSString* title = base::SysUTF16ToNSString(tab->GetTitle()); - - NSPasteboard* pboard = [NSPasteboard pasteboardWithName:NSDragPboard]; - [pboard declareURLPasteboardWithAdditionalTypes:[NSArray array] - owner:nil]; - [pboard setDataForURL:url title:title]; - return pboard; -} - -// StarIconView----------------------------------------------------------------- - -LocationBarViewMac::StarIconView::StarIconView(CommandUpdater* command_updater) - : command_updater_(command_updater) { - SetVisible(true); - SetStarred(false); -} - -void LocationBarViewMac::StarIconView::SetStarred(bool starred) { - if (starred) { - SetImage(AutocompleteEditViewMac::ImageForResource(IDR_OMNIBOX_STAR_LIT)); - tooltip_.reset( - [l10n_util::GetNSStringWithFixup(IDS_TOOLTIP_STARRED) retain]); - } else { - SetImage(AutocompleteEditViewMac::ImageForResource(IDR_OMNIBOX_STAR)); - tooltip_.reset( - [l10n_util::GetNSStringWithFixup(IDS_TOOLTIP_STAR) retain]); - } -} - -void LocationBarViewMac::StarIconView::OnMousePressed(NSRect bounds) { - command_updater_->ExecuteCommand(IDC_BOOKMARK_PAGE); -} - -const NSString* LocationBarViewMac::StarIconView::GetToolTip() { - return tooltip_.get(); -} - // PageActionImageView---------------------------------------------------------- LocationBarViewMac::PageActionImageView::PageActionImageView( @@ -697,9 +647,14 @@ LocationBarViewMac::PageActionImageView::PageActionImageView( LocationBarViewMac::PageActionImageView::~PageActionImageView() { } -NSSize LocationBarViewMac::PageActionImageView::GetDefaultImageSize() const { - return NSMakeSize(Extension::kPageActionIconMaxSize, - Extension::kPageActionIconMaxSize); +NSSize LocationBarViewMac::PageActionImageView::GetPreferredImageSize() { + NSImage* image = GetImage(); + if (image) { + return [image size]; + } else { + return NSMakeSize(Extension::kPageActionIconMaxSize, + Extension::kPageActionIconMaxSize); + } } // Overridden from LocationBarImageView. Either notify listeners or show a @@ -913,9 +868,10 @@ void LocationBarViewMac::ContentSettingImageView::UpdateFromTabContents( const TabContents* tab_contents) { content_setting_image_model_->UpdateFromTabContents(tab_contents); if (content_setting_image_model_->is_visible()) { + ResourceBundle& rb = ResourceBundle::GetSharedInstance(); // TODO(thakis): We should use pdfs for these icons on OSX. // http://crbug.com/35847 - SetIcon(content_setting_image_model_->get_icon()); + SetImage(rb.GetNSImageNamed(content_setting_image_model_->get_icon())); SetToolTip(base::SysUTF8ToNSString( content_setting_image_model_->get_tooltip())); SetVisible(true); @@ -939,11 +895,6 @@ void LocationBarViewMac::PageActionViewList::DeleteAll() { } void LocationBarViewMac::PageActionViewList::RefreshViews() { - if (!owner_->IsEditable()) { - DeleteAll(); - return; - } - std::vector<ExtensionAction*> page_actions; ExtensionsService* service = profile_->GetExtensionsService(); if (!service) diff --git a/chrome/browser/cocoa/location_bar_view_mac_unittest.mm b/chrome/browser/cocoa/location_bar_view_mac_unittest.mm index ecb2a7b..aec948d 100644 --- a/chrome/browser/cocoa/location_bar_view_mac_unittest.mm +++ b/chrome/browser/cocoa/location_bar_view_mac_unittest.mm @@ -81,6 +81,7 @@ TEST_F(LocationBarViewMacTest, OnChangedImpl) { NSImage* image = [NSImage imageNamed:@"NSApplicationIcon"]; const std::wstring kKeyword(L"Google"); + const NSString* kSearchHint = @"Type to search"; const NSString* kKeywordPrefix = @"Press "; const NSString* kKeywordSuffix = @" to search Google"; const NSString* kKeywordString = @"Search Google:"; @@ -89,20 +90,39 @@ TEST_F(LocationBarViewMacTest, OnChangedImpl) { [NSString stringWithFormat:@"Search Go%C:", 0x2026]; // With no special hints requested, none set. - LocationBarViewMac::OnChangedImpl(field_, std::wstring(), std::wstring(), false, image); + LocationBarViewMac::OnChangedImpl( + field_, std::wstring(), std::wstring(), false, false, image); EXPECT_FALSE([cell keywordString]); EXPECT_FALSE([cell hintString]); - // Request a keyword hint. - LocationBarViewMac::OnChangedImpl(field_, kKeyword, kKeyword, true, image); + // Request only a search hint. + LocationBarViewMac::OnChangedImpl( + field_, std::wstring(), std::wstring(), false, true, image); + EXPECT_FALSE([cell keywordString]); + EXPECT_TRUE([[[cell hintString] string] isEqualToString:kSearchHint]); + + // Request a keyword hint, same results whether |search_hint| + // parameter is true or false. + LocationBarViewMac::OnChangedImpl( + field_, kKeyword, kKeyword, true, true, image); + EXPECT_FALSE([cell keywordString]); + EXPECT_TRUE([[[cell hintString] string] hasPrefix:kKeywordPrefix]); + EXPECT_TRUE([[[cell hintString] string] hasSuffix:kKeywordSuffix]); + LocationBarViewMac::OnChangedImpl( + field_, kKeyword, kKeyword, true, false, image); EXPECT_FALSE([cell keywordString]); EXPECT_TRUE([[[cell hintString] string] hasPrefix:kKeywordPrefix]); EXPECT_TRUE([[[cell hintString] string] hasSuffix:kKeywordSuffix]); - // Request keyword-search mode. + // Request keyword-search mode, same results whether |search_hint| + // parameter is true or false. LocationBarViewMac::OnChangedImpl( - field_, kKeyword, kKeyword, false, image); - EXPECT_TRUE([[[cell keywordString] string] hasSuffix:kKeywordString]); + field_, kKeyword, kKeyword, false, true, image); + EXPECT_TRUE([[[cell keywordString] string] isEqualToString:kKeywordString]); + EXPECT_FALSE([cell hintString]); + LocationBarViewMac::OnChangedImpl( + field_, kKeyword, kKeyword, false, false, image); + EXPECT_TRUE([[[cell keywordString] string] isEqualToString:kKeywordString]); EXPECT_FALSE([cell hintString]); // Check that a partial keyword-search string is passed down in case @@ -112,13 +132,14 @@ TEST_F(LocationBarViewMacTest, OnChangedImpl) { NSRect frame([field_ frame]); frame.size.width = 10.0; [field_ setFrame:frame]; - LocationBarViewMac::OnChangedImpl(field_, kKeyword, kKeyword, false, image); + LocationBarViewMac::OnChangedImpl( + field_, kKeyword, kKeyword, false, true, image); EXPECT_TRUE([[[cell keywordString] string] isEqualToString:kPartialString]); EXPECT_FALSE([cell hintString]); // Transition back to baseline. LocationBarViewMac::OnChangedImpl( - field_, std::wstring(), std::wstring(), false, image); + field_, std::wstring(), std::wstring(), false, false, image); EXPECT_FALSE([cell keywordString]); EXPECT_FALSE([cell hintString]); } diff --git a/chrome/browser/cocoa/status_bubble_mac_unittest.mm b/chrome/browser/cocoa/status_bubble_mac_unittest.mm index 6f4dab4..3dd628e 100644 --- a/chrome/browser/cocoa/status_bubble_mac_unittest.mm +++ b/chrome/browser/cocoa/status_bubble_mac_unittest.mm @@ -141,7 +141,7 @@ TEST_F(StatusBubbleMacTest, SetURL) { EXPECT_TRUE([GetURLText() isEqualToString:@"foopy://"]); bubble_->SetURL(GURL("http://www.cnn.com"), L""); EXPECT_TRUE(IsVisible()); - EXPECT_TRUE([GetURLText() isEqualToString:@"www.cnn.com/"]); + EXPECT_TRUE([GetURLText() isEqualToString:@"http://www.cnn.com/"]); } // Test hiding bubble that's already hidden. @@ -162,7 +162,7 @@ TEST_F(StatusBubbleMacTest, SetStatusAndURL) { EXPECT_TRUE([GetBubbleViewText() isEqualToString:@"Status"]); bubble_->SetURL(GURL("http://www.nytimes.com/"), L""); EXPECT_TRUE(IsVisible()); - EXPECT_TRUE([GetBubbleViewText() isEqualToString:@"www.nytimes.com/"]); + EXPECT_TRUE([GetBubbleViewText() isEqualToString:@"http://www.nytimes.com/"]); bubble_->SetURL(GURL(), L""); EXPECT_TRUE(IsVisible()); EXPECT_TRUE([GetBubbleViewText() isEqualToString:@"Status"]); @@ -170,13 +170,13 @@ TEST_F(StatusBubbleMacTest, SetStatusAndURL) { EXPECT_FALSE(IsVisible()); bubble_->SetURL(GURL("http://www.nytimes.com/"), L""); EXPECT_TRUE(IsVisible()); - EXPECT_TRUE([GetBubbleViewText() isEqualToString:@"www.nytimes.com/"]); + EXPECT_TRUE([GetBubbleViewText() isEqualToString:@"http://www.nytimes.com/"]); bubble_->SetStatus(L"Status"); EXPECT_TRUE(IsVisible()); EXPECT_TRUE([GetBubbleViewText() isEqualToString:@"Status"]); bubble_->SetStatus(L""); EXPECT_TRUE(IsVisible()); - EXPECT_TRUE([GetBubbleViewText() isEqualToString:@"www.nytimes.com/"]); + EXPECT_TRUE([GetBubbleViewText() isEqualToString:@"http://www.nytimes.com/"]); bubble_->SetURL(GURL(), L""); EXPECT_FALSE(IsVisible()); } diff --git a/chrome/browser/cocoa/tab_strip_controller_unittest.mm b/chrome/browser/cocoa/tab_strip_controller_unittest.mm index 82cea8e..0967ae4 100644 --- a/chrome/browser/cocoa/tab_strip_controller_unittest.mm +++ b/chrome/browser/cocoa/tab_strip_controller_unittest.mm @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2009 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. diff --git a/chrome/browser/cocoa/toolbar_controller.h b/chrome/browser/cocoa/toolbar_controller.h index c038077..3c5086b 100644 --- a/chrome/browser/cocoa/toolbar_controller.h +++ b/chrome/browser/cocoa/toolbar_controller.h @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2009 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. @@ -22,6 +22,7 @@ class AppMenuModel; @class BackForwardMenuController; class Browser; @class BrowserActionsController; +class BubblePositioner; class CommandUpdater; @class DelayedMenuButton; class LocationBar; @@ -69,6 +70,8 @@ class ToolbarModel; // Used for monitoring the optional toolbar button prefs. scoped_ptr<ToolbarControllerInternal::PrefObserverBridge> prefObserver_; + // Used to position the omnibox bubble. + scoped_ptr<BubblePositioner> bubblePositioner_; BooleanPrefMember showHomeButton_; BooleanPrefMember showPageOptionButtons_; BOOL hasToolbar_; // If NO, we may have only the location bar. @@ -96,6 +99,7 @@ class ToolbarModel; IBOutlet DelayedMenuButton* forwardButton_; IBOutlet NSButton* reloadButton_; IBOutlet NSButton* homeButton_; + IBOutlet NSButton* starButton_; IBOutlet NSButton* goButton_; IBOutlet MenuButton* pageButton_; IBOutlet MenuButton* wrenchButton_; @@ -143,10 +147,9 @@ class ToolbarModel; // ignored. This changes the behavior of other methods, like |-view|. - (void)setHasToolbar:(BOOL)toolbar hasLocationBar:(BOOL)locBar; -// The bookmark bubble (when you click the star or hit Command-d) -// needs to know where to go. Somewhere near the star icon seems like -// a good start. -- (NSRect)starIconInWindowCoordinates; +// The bookmark bubble (when you click the star) needs to know where to go. +// Somewhere near the star button seems like a good start. +- (NSRect)starButtonInWindowCoordinates; // Returns the desired toolbar height for the given compression factor. - (CGFloat)desiredHeightForCompression:(CGFloat)compressByHeight; @@ -168,6 +171,7 @@ class ToolbarModel; - (NSArray*)toolbarViews; - (void)showOptionalHomeButton; - (void)showOptionalPageWrenchButtons; +- (gfx::Rect)locationStackBounds; // Return a hover button for the current event. - (NSButton*)hoverButtonForEvent:(NSEvent*)theEvent; @end diff --git a/chrome/browser/cocoa/toolbar_controller.mm b/chrome/browser/cocoa/toolbar_controller.mm index 085c493..0d12ee5 100644 --- a/chrome/browser/cocoa/toolbar_controller.mm +++ b/chrome/browser/cocoa/toolbar_controller.mm @@ -15,6 +15,7 @@ #include "chrome/browser/autocomplete/autocomplete_edit_view.h" #include "chrome/browser/browser.h" #include "chrome/browser/browser_window.h" +#include "chrome/browser/bubble_positioner.h" #import "chrome/browser/cocoa/autocomplete_text_field.h" #import "chrome/browser/cocoa/autocomplete_text_field_editor.h" #import "chrome/browser/cocoa/back_forward_menu_controller.h" @@ -50,6 +51,8 @@ NSString* const kBackButtonImageName = @"back_Template.pdf"; NSString* const kForwardButtonImageName = @"forward_Template.pdf"; NSString* const kReloadButtonImageName = @"reload_Template.pdf"; NSString* const kHomeButtonImageName = @"home_Template.pdf"; +NSString* const kStarButtonImageName = @"star_Template.pdf"; +NSString* const kStarButtonFillingImageName = @"starred.pdf"; NSString* const kGoButtonGoImageName = @"go_Template.pdf"; NSString* const kGoButtonStopImageName = @"stop_Template.pdf"; NSString* const kPageButtonImageName = @"menu_page_Template.pdf"; @@ -84,6 +87,26 @@ const CGFloat kAnimationDuration = 0.2; - (void)adjustLocationAndGoPositionsBy:(CGFloat)dX animate:(BOOL)animate; @end +namespace { + +// A C++ class used to correctly position the omnibox. +class BubblePositionerMac : public BubblePositioner { + public: + BubblePositionerMac(ToolbarController* controller) + : controller_(controller) { } + virtual ~BubblePositionerMac() { } + + // BubblePositioner: + virtual gfx::Rect GetLocationStackBounds() const { + return [controller_ locationStackBounds]; + } + + private: + ToolbarController* controller_; // weak, owns us +}; + +} // namespace + namespace ToolbarControllerInternal { // A C++ delegate that handles enabling/disabling menu items and handling when @@ -202,6 +225,7 @@ class PrefObserverBridge : public NotificationObserver { [forwardButton_ setImage:nsimage_cache::ImageNamed(kForwardButtonImageName)]; [reloadButton_ setImage:nsimage_cache::ImageNamed(kReloadButtonImageName)]; [homeButton_ setImage:nsimage_cache::ImageNamed(kHomeButtonImageName)]; + [starButton_ setImage:nsimage_cache::ImageNamed(kStarButtonImageName)]; [goButton_ setImage:nsimage_cache::ImageNamed(kGoButtonGoImageName)]; [pageButton_ setImage:nsimage_cache::ImageNamed(kPageButtonImageName)]; [wrenchButton_ setImage:nsimage_cache::ImageNamed(kWrenchButtonImageName)]; @@ -210,7 +234,9 @@ class PrefObserverBridge : public NotificationObserver { [wrenchButton_ setShowsBorderOnlyWhileMouseInside:YES]; [self initCommandStatus:commands_]; + bubblePositioner_.reset(new BubblePositionerMac(self)); locationBarView_.reset(new LocationBarViewMac(locationBar_, + bubblePositioner_.get(), commands_, toolbarModel_, profile_, browser_)); [locationBar_ setFont:[NSFont systemFontOfSize:[NSFont systemFontSize]]]; @@ -286,6 +312,10 @@ class PrefObserverBridge : public NotificationObserver { [[homeButton_ cell] accessibilitySetOverrideValue:description forAttribute:NSAccessibilityDescriptionAttribute]; + description = l10n_util::GetNSStringWithFixup(IDS_ACCNAME_STAR); + [[starButton_ cell] + accessibilitySetOverrideValue:description + forAttribute:NSAccessibilityDescriptionAttribute]; description = l10n_util::GetNSStringWithFixup(IDS_ACCNAME_LOCATION); [[locationBar_ cell] accessibilitySetOverrideValue:description @@ -364,6 +394,9 @@ class PrefObserverBridge : public NotificationObserver { case IDC_HOME: button = homeButton_; break; + case IDC_BOOKMARK_PAGE: + button = starButton_; + break; } [button setEnabled:enabled]; } @@ -376,6 +409,8 @@ class PrefObserverBridge : public NotificationObserver { setEnabled:commands->IsCommandEnabled(IDC_FORWARD) ? YES : NO]; [reloadButton_ setEnabled:commands->IsCommandEnabled(IDC_RELOAD) ? YES : NO]; [homeButton_ setEnabled:commands->IsCommandEnabled(IDC_HOME) ? YES : NO]; + [starButton_ + setEnabled:commands->IsCommandEnabled(IDC_BOOKMARK_PAGE) ? YES : NO]; } - (void)updateToolbarWithContents:(TabContents*)tab @@ -390,7 +425,23 @@ class PrefObserverBridge : public NotificationObserver { } - (void)setStarredState:(BOOL)isStarred { - locationBarView_->SetStarred(isStarred ? true : false); + NSImage* starImage = nil; + NSString* toolTip; + if (isStarred) { + starImage = nsimage_cache::ImageNamed(kStarButtonFillingImageName); + // Cache the string since we'll need it a lot + static NSString* starredToolTip = + [l10n_util::GetNSStringWithFixup(IDS_TOOLTIP_STARRED) retain]; + toolTip = starredToolTip; + } else { + // Cache the string since we'll need it a lot + static NSString* starToolTip = + [l10n_util::GetNSStringWithFixup(IDS_TOOLTIP_STAR) retain]; + toolTip = starToolTip; + } + + [(GradientButtonCell*)[starButton_ cell] setUnderlayImage:starImage]; + [starButton_ setToolTip:toolTip]; } - (void)setIsLoading:(BOOL)isLoading { @@ -419,7 +470,7 @@ class PrefObserverBridge : public NotificationObserver { // Make location bar not editable when in a pop-up. // TODO(viettrungluu): is this right (all the time)? - locationBarView_->SetEditable(toolbar ? true : false); + [locationBar_ setEditable:toolbar]; } - (NSView*)view { @@ -457,7 +508,7 @@ class PrefObserverBridge : public NotificationObserver { // Returns an array of views in the order of the outlets above. - (NSArray*)toolbarViews { return [NSArray arrayWithObjects:backButton_, forwardButton_, reloadButton_, - homeButton_, goButton_, pageButton_, wrenchButton_, + homeButton_, starButton_, goButton_, pageButton_, wrenchButton_, locationBar_, browserActionsContainerView_, nil]; } @@ -470,16 +521,14 @@ class PrefObserverBridge : public NotificationObserver { return frame; } -// Computes the padding between the buttons that should have a -// separation from the positions in the nib. |homeButton_| is right -// of |forwardButton_| unless it has been hidden, in which case -// |reloadButton_| is in that spot. +// Computes the padding between the buttons that should have a separation from +// the positions in the nib. Since the forward and reload buttons are always +// visible, we use those buttons as the canonical spacing. - (CGFloat)interButtonSpacing { - const NSRect forwardFrame = [forwardButton_ frame]; - NSButton* nextButton = [homeButton_ isHidden] ? reloadButton_ : homeButton_; - const NSRect nextButtonFrame = [nextButton frame]; - DCHECK_GT(NSMinX(nextButtonFrame), NSMaxX(forwardFrame)); - return NSMinX(nextButtonFrame) - NSMaxX(forwardFrame); + NSRect forwardFrame = [forwardButton_ frame]; + NSRect reloadFrame = [reloadButton_ frame]; + DCHECK(NSMinX(reloadFrame) > NSMaxX(forwardFrame)); + return NSMinX(reloadFrame) - NSMaxX(forwardFrame); } // Show or hide the home button based on the pref. @@ -498,7 +547,7 @@ class PrefObserverBridge : public NotificationObserver { if (hide) moveX *= -1; // Reverse the direction of the move. - [reloadButton_ setFrame:NSOffsetRect([reloadButton_ frame], moveX, 0)]; + [starButton_ setFrame:NSOffsetRect([starButton_ frame], moveX, 0)]; [locationBar_ setFrame:[self adjustRect:[locationBar_ frame] byAmount:moveX]]; [homeButton_ setHidden:hide]; @@ -721,8 +770,8 @@ class PrefObserverBridge : public NotificationObserver { [NSAnimationContext endGrouping]; } -- (NSRect)starIconInWindowCoordinates { - return [locationBar_ convertRect:[locationBar_ starIconFrame] toView:nil]; +- (NSRect)starButtonInWindowCoordinates { + return [starButton_ convertRect:[starButton_ bounds] toView:nil]; } - (CGFloat)desiredHeightForCompression:(CGFloat)compressByHeight { @@ -797,6 +846,31 @@ class PrefObserverBridge : public NotificationObserver { } +- (gfx::Rect)locationStackBounds { + // The number of pixels from the left or right edges of the location stack to + // "just inside the visible borders". When the omnibox bubble contents are + // aligned with this, the visible borders tacked on to the outsides will line + // up with the visible borders on the location stack. + const int kLocationStackEdgeWidth = 2; + + const NSRect locationFrame = [locationBar_ frame]; + + // Expand to include star and go buttons. Including the widths + // rather that calculating from their current placement because this + // method can be called while the resize is still rearranging the + // views involved. + const CGFloat minX = NSMinX(locationFrame) - NSWidth([starButton_ frame]); + const CGFloat maxX = NSMaxX(locationFrame) + NSWidth([goButton_ frame]); + + NSRect r = NSMakeRect(minX, NSMinY(locationFrame), maxX - minX, + NSHeight(locationFrame)); + gfx::Rect stack_bounds( + NSRectToCGRect([[self view] convertRect:r toView:nil])); + // Inset the bounds to just inside the visible edges (see comment above). + stack_bounds.Inset(kLocationStackEdgeWidth, 0); + return stack_bounds; +} + // (URLDropTargetController protocol) - (void)dropURLs:(NSArray*)urls inView:(NSView*)view at:(NSPoint)point { // TODO(viettrungluu): This code is more or less copied from the code in diff --git a/chrome/browser/cocoa/toolbar_controller_unittest.mm b/chrome/browser/cocoa/toolbar_controller_unittest.mm index 08e3176..dab5cba 100644 --- a/chrome/browser/cocoa/toolbar_controller_unittest.mm +++ b/chrome/browser/cocoa/toolbar_controller_unittest.mm @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2009 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. @@ -43,7 +43,7 @@ class ToolbarControllerTest : public CocoaTest { // Indexes that match the ordering returned by the private ToolbarController // |-toolbarViews| method. enum { - kBackIndex, kForwardIndex, kReloadIndex, kHomeIndex, kGoIndex, + kBackIndex, kForwardIndex, kReloadIndex, kHomeIndex, kStarIndex, kGoIndex, kPageIndex, kWrenchIndex, kLocationIndex, kBrowserActionContainerViewIndex }; @@ -78,6 +78,8 @@ class ToolbarControllerTest : public CocoaTest { [[views objectAtIndex:kReloadIndex] isEnabled] ? true : false); EXPECT_EQ(updater->IsCommandEnabled(IDC_HOME), [[views objectAtIndex:kHomeIndex] isEnabled] ? true : false); + EXPECT_EQ(updater->IsCommandEnabled(IDC_BOOKMARK_PAGE), + [[views objectAtIndex:kStarIndex] isEnabled] ? true : false); } BrowserTestHelper helper_; @@ -158,16 +160,16 @@ TEST_F(ToolbarControllerTest, ToggleHome) { NSView* homeButton = [[bar_ toolbarViews] objectAtIndex:kHomeIndex]; EXPECT_EQ(showHome, ![homeButton isHidden]); - NSView* reloadButton = [[bar_ toolbarViews] objectAtIndex:kReloadIndex]; + NSView* starButton = [[bar_ toolbarViews] objectAtIndex:kStarIndex]; NSView* locationBar = [[bar_ toolbarViews] objectAtIndex:kLocationIndex]; - NSRect originalReloadFrame = [reloadButton frame]; + NSRect originalStarFrame = [starButton frame]; NSRect originalLocationBarFrame = [locationBar frame]; // Toggle the pref and make sure the button changed state and the other // views moved. prefs->SetBoolean(prefs::kShowHomeButton, !showHome); EXPECT_EQ(showHome, [homeButton isHidden]); - EXPECT_NE(NSMinX(originalReloadFrame), NSMinX([reloadButton frame])); + EXPECT_NE(NSMinX(originalStarFrame), NSMinX([starButton frame])); EXPECT_NE(NSMinX(originalLocationBarFrame), NSMinX([locationBar frame])); EXPECT_NE(NSWidth(originalLocationBarFrame), NSWidth([locationBar frame])); } @@ -218,14 +220,32 @@ TEST_F(ToolbarControllerTest, DontToggleWhenNoToolbar) { EXPECT_TRUE(NSEqualRects(locationBarFrame, newLocationBarFrame)); } -TEST_F(ToolbarControllerTest, StarIconInWindowCoordinates) { - NSRect star = [bar_ starIconInWindowCoordinates]; +TEST_F(ToolbarControllerTest, StarButtonInWindowCoordinates) { + NSRect star = [bar_ starButtonInWindowCoordinates]; NSRect all = [[[bar_ view] window] frame]; // Make sure the star is completely inside the window rect EXPECT_TRUE(NSContainsRect(all, star)); } +TEST_F(ToolbarControllerTest, BubblePosition) { + NSView* locationBar = [[bar_ toolbarViews] objectAtIndex:kLocationIndex]; + + // The window frame (in window base coordinates). + NSRect all = [[[bar_ view] window] frame]; + // The frame of the location bar in window base coordinates. + NSRect locationFrame = + [locationBar convertRect:[locationBar bounds] toView:nil]; + // The frame of the location stack in window base coordinates. The horizontal + // coordinates here are used for the omnibox dropdown. + gfx::Rect locationStackFrame = [bar_ locationStackBounds]; + + // Make sure the location stack starts to the left of and ends to the right of + // the location bar. + EXPECT_LT(locationStackFrame.x(), NSMinX(locationFrame)); + EXPECT_GT(locationStackFrame.right(), NSMaxX(locationFrame)); +} + TEST_F(ToolbarControllerTest, HoverButtonForEvent) { scoped_nsobject<HitView> view([[HitView alloc] initWithFrame:NSMakeRect(0,0,100,100)]); |