| Index: chrome/browser/cocoa/autocomplete_text_field_cell.mm
|
| diff --git a/chrome/browser/cocoa/autocomplete_text_field_cell.mm b/chrome/browser/cocoa/autocomplete_text_field_cell.mm
|
| index 5fb7b16388266b2ed17ac740faee880d54e769bb..c8f2122afbcbed9a6028b9dc207bc17eae77e306 100644
|
| --- a/chrome/browser/cocoa/autocomplete_text_field_cell.mm
|
| +++ b/chrome/browser/cocoa/autocomplete_text_field_cell.mm
|
| @@ -39,12 +39,14 @@ const NSInteger kKeywordHintImageBaseline = -6;
|
| const NSInteger kIconHorizontalPad = 3;
|
|
|
| // How far to shift bounding box of hint icon label down from top of field.
|
| -const NSInteger kIconLabelYOffset = 5;
|
| +const NSInteger kIconLabelYOffset = 7;
|
|
|
| // How far the editor insets itself, for purposes of determining if
|
| // decorations need to be trimmed.
|
| const CGFloat kEditorHorizontalInset = 3.0;
|
|
|
| +const CGFloat kLocationIconXOffset = 3.0;
|
| +
|
| // Conveniences to centralize width+offset calculations.
|
| CGFloat WidthForHint(NSAttributedString* hintString) {
|
| return kHintXOffset + ceil([hintString size].width);
|
| @@ -54,6 +56,16 @@ 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) {
|
| + DCHECK(NSEqualSizes([image size], rect.size));
|
| + [image setFlipped:[view isFlipped]];
|
| + [image drawInRect:rect
|
| + fromRect:NSZeroRect // Entire image
|
| + operation:NSCompositeSourceOver
|
| + fraction:1.0];
|
| +}
|
| +
|
| } // namespace
|
|
|
| @implementation AutocompleteTextFieldIcon
|
| @@ -61,13 +73,52 @@ CGFloat WidthForKeyword(NSAttributedString* keywordString) {
|
| @synthesize rect = rect_;
|
| @synthesize view = view_;
|
|
|
| -+ (AutocompleteTextFieldIcon*)
|
| - iconWithRect:(NSRect)rect
|
| - view:(LocationBarViewMac::LocationBarImageView*)view {
|
| - AutocompleteTextFieldIcon* result = [[AutocompleteTextFieldIcon alloc] init];
|
| - [result setRect:rect];
|
| - [result setView:view];
|
| - return [result autorelease];
|
| +// 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_);
|
| + }
|
| }
|
|
|
| @end
|
| @@ -214,7 +265,11 @@ CGFloat WidthForKeyword(NSAttributedString* keywordString) {
|
| }
|
|
|
| - (void)setLocationIconView:(LocationBarViewMac::LocationIconView*)view {
|
| - location_icon_view_ = view;
|
| + locationIconView_ = view;
|
| +}
|
| +
|
| +- (void)setSecurityLabelView:(LocationBarViewMac::LocationBarImageView*)view {
|
| + securityLabelView_ = view;
|
| }
|
|
|
| - (void)setContentSettingViewsList:
|
| @@ -226,69 +281,57 @@ CGFloat WidthForKeyword(NSAttributedString* keywordString) {
|
| - (NSRect)textFrameForFrame:(NSRect)cellFrame {
|
| NSRect textFrame([super textFrameForFrame:cellFrame]);
|
|
|
| + // TODO(shess): Check the set of exclusions in |LocationBarViewMac|.
|
| + // If |keywordString_| takes precedence over other cases, then this
|
| + // code could be made simpler.
|
| + if (!keywordString_ && locationIconView_ && locationIconView_->IsVisible()) {
|
| + const NSSize imageSize = locationIconView_->GetImageSize();
|
| + textFrame.origin.x += imageSize.width;
|
| + textFrame.size.width -= imageSize.width;
|
| + }
|
| +
|
| 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(cellFrame)) {
|
| + if (hintWidth < NSWidth(textFrame)) {
|
| textFrame.size.width -= hintWidth;
|
| }
|
| } else if (keywordString_) {
|
| DCHECK(!hintString_);
|
| const CGFloat keywordWidth(WidthForKeyword(keywordString_));
|
|
|
| - // 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)) {
|
| + if (keywordWidth < NSWidth(textFrame)) {
|
| textFrame.origin.x += keywordWidth;
|
| - textFrame.size.width = NSMaxX(cellFrame) - NSMinX(textFrame);
|
| + textFrame.size.width -= keywordWidth;
|
| }
|
| } else {
|
| - // Leave room for images on the right (lock icon etc).
|
| + // 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* 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;
|
| + if ([iconFrames count]) {
|
| + const CGFloat minX = NSMinX([[iconFrames objectAtIndex:0] rect]);
|
| + if (minX >= NSMinX(textFrame)) {
|
| + textFrame.size.width = minX - NSMinX(textFrame);
|
| + }
|
| + }
|
| }
|
|
|
| return textFrame;
|
| }
|
|
|
| -// 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)locationIconFrameForFrame:(NSRect)cellFrame {
|
| - if (!location_icon_view_ || !location_icon_view_->IsVisible()) {
|
| + if (!locationIconView_ || !locationIconView_->IsVisible())
|
| return NSZeroRect;
|
| - }
|
| -
|
| - // Calculate the total width occupied by the image, label, and padding.
|
| - NSSize imageSize = [location_icon_view_->GetImage() size];
|
| - CGFloat widthUsed = imageSize.width + kIconHorizontalPad;
|
| - NSAttributedString* label = location_icon_view_->GetLabel();
|
| - if (label) {
|
| - widthUsed += ceil([label size].width) + kHintXOffset;
|
| - }
|
|
|
| - return [self rightJustifyImage:imageSize
|
| - inRect:cellFrame
|
| - withMargin:widthUsed];
|
| + 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);
|
| }
|
|
|
| - (size_t)pageActionCount {
|
| @@ -359,42 +402,19 @@ CGFloat WidthForKeyword(NSAttributedString* keywordString) {
|
| [keywordString_.get() drawInRect:infoFrame];
|
| }
|
|
|
| -- (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];
|
| +- (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView*)controlView {
|
| + if (!keywordString_ && locationIconView_ && locationIconView_->IsVisible()) {
|
| + DrawImageInRect(locationIconView_->GetImage(), controlView,
|
| + [self locationIconFrameForFrame:cellFrame]);
|
| }
|
|
|
| - // 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];
|
| -}
|
| -
|
| -- (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];
|
| + [icon drawInView:controlView];
|
| }
|
| }
|
|
|
| @@ -402,71 +422,108 @@ CGFloat WidthForKeyword(NSAttributedString* keywordString) {
|
| }
|
|
|
| - (NSArray*)layedOutIcons:(NSRect)cellFrame {
|
| - NSMutableArray* result = [NSMutableArray arrayWithCapacity:0];
|
| - NSRect iconFrame = cellFrame;
|
| - if (location_icon_view_ && location_icon_view_->IsVisible()) {
|
| - NSRect locationIconFrame = [self locationIconFrameForFrame:iconFrame];
|
| - [result addObject:
|
| - [AutocompleteTextFieldIcon iconWithRect:locationIconFrame
|
| - view:location_icon_view_]];
|
| - iconFrame.size.width -= NSMaxX(iconFrame) - NSMinX(locationIconFrame);
|
| + // The set of views to display right-justified in the cell, from
|
| + // left to right.
|
| + NSMutableArray* result = [NSMutableArray array];
|
| +
|
| + // Security label floats to left of page actions.
|
| + if (securityLabelView_ && securityLabelView_->IsVisible() &&
|
| + securityLabelView_->GetLabel()) {
|
| + scoped_nsobject<AutocompleteTextFieldIcon> icon(
|
| + [[AutocompleteTextFieldIcon alloc]
|
| + initLabelWithView:securityLabelView_]);
|
| + [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);
|
| - }
|
| - }
|
| + // 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_) {
|
| - // 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);
|
| - }
|
| + 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));
|
| + }
|
| +
|
| + // 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];
|
| }
|
| }
|
| +
|
| + // 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;
|
| + }
|
| return result;
|
| }
|
|
|
| -- (NSMenu*)actionMenuForEvent:(NSEvent*)event
|
| - inRect:(NSRect)cellFrame
|
| - ofView:(NSView*)aView {
|
| - NSPoint location = [aView convertPoint:[event locationInWindow] fromView:nil];
|
| +- (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;
|
| + }
|
|
|
| - const BOOL flipped = [aView isFlipped];
|
| for (AutocompleteTextFieldIcon* icon in [self layedOutIcons:cellFrame]) {
|
| - if (NSMouseInRect(location, [icon rect], flipped)) {
|
| - return [icon view]->GetMenu();
|
| - }
|
| + if (NSMouseInRect(location, [icon rect], flipped))
|
| + return icon;
|
| }
|
| +
|
| + return nil;
|
| +}
|
| +
|
| +- (NSMenu*)actionMenuForEvent:(NSEvent*)theEvent
|
| + inRect:(NSRect)cellFrame
|
| + ofView:(AutocompleteTextField*)controlView {
|
| + AutocompleteTextFieldIcon*
|
| + icon = [self iconForEvent:theEvent inRect:cellFrame ofView:controlView];
|
| + if (icon)
|
| + return [icon view]->GetMenu();
|
| return nil;
|
| }
|
|
|
| +- (BOOL)mouseDown:(NSEvent*)theEvent
|
| + inRect:(NSRect)cellFrame
|
| + ofView:(AutocompleteTextField*)controlView {
|
| + AutocompleteTextFieldIcon*
|
| + icon = [self iconForEvent:theEvent inRect:cellFrame ofView:controlView];
|
| + if (icon) {
|
| + [icon view]->OnMousePressed([icon rect]);
|
| + return YES;
|
| + }
|
| +
|
| + return NO;
|
| +}
|
| +
|
| @end
|
|
|