diff options
author | sail@chromium.org <sail@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-06-28 04:15:04 +0000 |
---|---|---|
committer | sail@chromium.org <sail@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-06-28 04:15:04 +0000 |
commit | 2bbfc5c543db1570edde26cdd2fd33cab070640a (patch) | |
tree | f11952919cafe927fc97e7eed0962b6e8ed0fc51 /chrome/browser | |
parent | 3c7945c703ee07137e63662640015e12551bd076 (diff) | |
download | chromium_src-2bbfc5c543db1570edde26cdd2fd33cab070640a.zip chromium_src-2bbfc5c543db1570edde26cdd2fd33cab070640a.tar.gz chromium_src-2bbfc5c543db1570edde26cdd2fd33cab070640a.tar.bz2 |
OmniboxPopupViewMac refactoring Part 2
This CL makes the following changes:
- more tests
- decouple OmniboxPopupMatrix from OmniboxPopupView for easier testing
- change camel case naming in c++ code to use underscore
BUG=9977
NOTRY=true
R=shess@chromium.org
Review URL: https://codereview.chromium.org/17787002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@209090 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
9 files changed, 512 insertions, 375 deletions
diff --git a/chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm b/chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm index 3c0f13a..db647f8 100644 --- a/chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm +++ b/chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm @@ -17,9 +17,6 @@ const CGFloat kTextXOffset = 28.0; // Rounding radius of selection and hover background on popup items. const CGFloat kCellRoundingRadius = 2.0; -NSColor* BackgroundColor() { - return [NSColor controlBackgroundColor]; -} NSColor* SelectedBackgroundColor() { return [NSColor selectedControlColor]; } @@ -48,8 +45,6 @@ NSColor* HoveredBackgroundColor() { // the title next to the image. This spaces things out to line up // with the star button and autocomplete field. - (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView *)controlView { - [BackgroundColor() set]; - NSRectFill(cellFrame); if ([self state] == NSOnState || [self isHighlighted]) { if ([self state] == NSOnState) [SelectedBackgroundColor() set]; diff --git a/chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell_unittest.mm b/chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell_unittest.mm new file mode 100644 index 0000000..9b08280 --- /dev/null +++ b/chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell_unittest.mm @@ -0,0 +1,47 @@ +// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h" + +#include "base/mac/scoped_nsobject.h" +#import "chrome/browser/ui/cocoa/cocoa_test_helper.h" + +namespace { + +class OmniboxPopupCellTest : public CocoaTest { + public: + OmniboxPopupCellTest() { + } + + virtual void SetUp() OVERRIDE { + CocoaTest::SetUp(); + cell_.reset([[OmniboxPopupCell alloc] initTextCell:@""]); + button_.reset([[NSButton alloc] initWithFrame:NSMakeRect(0, 0, 200, 20)]); + [button_ setCell:cell_]; + [[test_window() contentView] addSubview:button_]; + }; + + protected: + base::scoped_nsobject<OmniboxPopupCell> cell_; + base::scoped_nsobject<NSButton> button_; + + private: + DISALLOW_COPY_AND_ASSIGN(OmniboxPopupCellTest); +}; + +TEST_VIEW(OmniboxPopupCellTest, button_); + +TEST_F(OmniboxPopupCellTest, Image) { + [cell_ setImage:[NSImage imageNamed:NSImageNameInfo]]; + [button_ display]; +} + +TEST_F(OmniboxPopupCellTest, Title) { + base::scoped_nsobject<NSAttributedString> text([[NSAttributedString alloc] + initWithString:@"The quick brown fox jumps over the lazy dog."]); + [cell_ setAttributedTitle:text]; + [button_ display]; +} + +} // namespace diff --git a/chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.h b/chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.h index 21f999e..2ce6167 100644 --- a/chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.h +++ b/chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.h @@ -7,22 +7,38 @@ #import <Cocoa/Cocoa.h> -class OmniboxPopupViewMac; +#import "ui/base/cocoa/tracking_area.h" +#include "ui/base/window_open_disposition.h" +@class OmniboxPopupMatrix; + +class OmniboxPopupMatrixDelegate { + public: + // Called when the selection in the matrix changes. + virtual void OnMatrixRowSelected(OmniboxPopupMatrix* matrix, size_t row) = 0; + + // Called when the user clicks on a row. + virtual void OnMatrixRowClicked(OmniboxPopupMatrix* matrix, size_t row) = 0; + + // Called when the user middle clicks on a row. + virtual void OnMatrixRowMiddleClicked(OmniboxPopupMatrix* matrix, + size_t row) = 0; +}; + +// Sets up a tracking area to implement hover by highlighting the cell the mouse +// is over. @interface OmniboxPopupMatrix : NSMatrix { - @private - // Target for click and middle-click. - OmniboxPopupViewMac* popupView_; // weak, owns us. + OmniboxPopupMatrixDelegate* delegate_; // weak + ui::ScopedCrTrackingArea trackingArea_; } -// Create a zero-size matrix initializing |popupView_|. -- (id)initWithPopupView:(OmniboxPopupViewMac*)popupView; +// Create a zero-size matrix. +- (id)initWithDelegate:(OmniboxPopupMatrixDelegate*)delegate; -// Set |popupView_|. -- (void)setPopupView:(OmniboxPopupViewMac*)popupView; +// Sets the delegate. +- (void)setDelegate:(OmniboxPopupMatrixDelegate*)delegate; -// Return the currently highlighted row. Returns -1 if no row is -// highlighted. +// Return the currently highlighted row. Returns -1 if no row is highlighted. - (NSInteger)highlightedRow; @end diff --git a/chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm b/chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm index d0d3d1b..6bddf63 100644 --- a/chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm +++ b/chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm @@ -4,18 +4,14 @@ #import "chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.h" +#include "base/logging.h" #import "chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h" -#include "chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.h" namespace { // NSEvent -buttonNumber for middle mouse button. const NSInteger kMiddleButtonNumber = 2; -NSColor* BackgroundColor() { - return [NSColor controlBackgroundColor]; -} - } // namespace @interface OmniboxPopupMatrix() @@ -27,18 +23,16 @@ NSColor* BackgroundColor() { @implementation OmniboxPopupMatrix -- (id)initWithPopupView:(OmniboxPopupViewMac*)popupView { - self = [super initWithFrame:NSZeroRect]; - if (self) { - popupView_ = popupView; - +- (id)initWithDelegate:(OmniboxPopupMatrixDelegate*)delegate { + if ((self = [super initWithFrame:NSZeroRect])) { + delegate_ = delegate; [self setCellClass:[OmniboxPopupCell class]]; // Cells pack with no spacing. [self setIntercellSpacing:NSMakeSize(0.0, 0.0)]; [self setDrawsBackground:YES]; - [self setBackgroundColor:BackgroundColor()]; + [self setBackgroundColor:[NSColor controlBackgroundColor]]; [self renewRows:0 columns:1]; [self setAllowsEmptySelection:YES]; [self setMode:NSRadioModeMatrix]; @@ -49,8 +43,8 @@ NSColor* BackgroundColor() { return self; } -- (void)setPopupView:(OmniboxPopupViewMac*)popupView { - popupView_ = popupView; +- (void)setDelegate:(OmniboxPopupMatrixDelegate*)delegate { + delegate_ = delegate; } - (NSInteger)highlightedRow { @@ -69,13 +63,15 @@ NSColor* BackgroundColor() { [super updateTrackingAreas]; } -// Callbacks from NSTrackingArea. +// Callbacks from tracking area. - (void)mouseEntered:(NSEvent*)theEvent { [self highlightRowUnder:theEvent]; } + - (void)mouseMoved:(NSEvent*)theEvent { [self highlightRowUnder:theEvent]; } + - (void)mouseExited:(NSEvent*)theEvent { [self highlightRowAt:-1]; } @@ -88,6 +84,7 @@ NSColor* BackgroundColor() { } [super otherMouseDown:theEvent]; } + - (void)otherMouseDragged:(NSEvent*)theEvent { if ([theEvent buttonNumber] == kMiddleButtonNumber) { [self highlightRowUnder:theEvent]; @@ -102,21 +99,20 @@ NSColor* BackgroundColor() { return; } - // -otherMouseDragged: should always have been called at this - // location, but make sure the user is getting the right feedback. + // -otherMouseDragged: should always have been called at this location, but + // make sure the user is getting the right feedback. [self highlightRowUnder:theEvent]; const NSInteger highlightedRow = [self highlightedRow]; if (highlightedRow != -1) { - DCHECK(popupView_); - popupView_->OpenURLForRow(highlightedRow, true); + DCHECK(delegate_); + delegate_->OnMatrixRowMiddleClicked(self, highlightedRow); } } -// Track the mouse until released, keeping the cell under the mouse -// selected. If the mouse wanders off-view, revert to the -// originally-selected cell. If the mouse is released over a cell, -// call |popupView_| to open the row's URL. +// Track the mouse until released, keeping the cell under the mouse selected. +// If the mouse wanders off-view, revert to the originally-selected cell. If +// the mouse is released over a cell, call the delegate to open the row's URL. - (void)mouseDown:(NSEvent*)theEvent { NSCell* selectedCell = [self selectedCell]; @@ -132,44 +128,36 @@ NSColor* BackgroundColor() { theEvent = [[self window] nextEventMatchingMask:mask]; } while ([theEvent type] == NSLeftMouseDragged); - // Do not message |popupView_| if released outside view. + // Do not message the delegate if released outside view. if (![self selectCellForEvent:theEvent]) { [self selectCell:selectedCell]; } else { const NSInteger selectedRow = [self selectedRow]; DCHECK_GE(selectedRow, 0); - DCHECK(popupView_); - popupView_->OpenURLForRow(selectedRow, false); + DCHECK(delegate_); + delegate_->OnMatrixRowClicked(self, selectedRow); } } -// Remove all tracking areas and initialize the one we want. Removing -// all might be overkill, but it's unclear why there would be others -// for the popup window. - (void)resetTrackingArea { - for (NSTrackingArea* trackingArea in [self trackingAreas]) { - [self removeTrackingArea:trackingArea]; - } + if (trackingArea_.get()) + [self removeTrackingArea:trackingArea_.get()]; - // TODO(shess): Consider overriding -acceptsFirstMouse: and changing - // NSTrackingActiveInActiveApp to NSTrackingActiveAlways. - NSTrackingAreaOptions options = NSTrackingMouseEnteredAndExited; - options |= NSTrackingMouseMoved; - options |= NSTrackingActiveInActiveApp; - options |= NSTrackingInVisibleRect; - - base::scoped_nsobject<NSTrackingArea> trackingArea( - [[NSTrackingArea alloc] initWithRect:[self frame] - options:options - owner:self - userInfo:nil]); - [self addTrackingArea:trackingArea]; + trackingArea_.reset([[CrTrackingArea alloc] + initWithRect:[self frame] + options:NSTrackingMouseEnteredAndExited | + NSTrackingMouseMoved | + NSTrackingActiveInActiveApp | + NSTrackingInVisibleRect + owner:self + userInfo:nil]); + [self addTrackingArea:trackingArea_.get()]; } - (void)highlightRowAt:(NSInteger)rowIndex { - // highlightCell will be nil if rowIndex is out of range, so no cell - // will be highlighted. + // highlightCell will be nil if rowIndex is out of range, so no cell will be + // highlighted. NSCell* highlightCell = [self cellAtRow:rowIndex column:0]; for (NSCell* cell in [self cells]) { @@ -194,8 +182,8 @@ NSColor* BackgroundColor() { NSInteger row, column; if ([self getRow:&row column:&column forPoint:point]) { DCHECK_EQ(column, 0); - DCHECK(popupView_); - popupView_->SetSelectedLine(row); + DCHECK(delegate_); + delegate_->OnMatrixRowSelected(self, row); return YES; } return NO; diff --git a/chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix_unittest.mm b/chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix_unittest.mm new file mode 100644 index 0000000..54d1e47 --- /dev/null +++ b/chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix_unittest.mm @@ -0,0 +1,87 @@ +// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.h" + +#import "chrome/browser/ui/cocoa/cocoa_test_helper.h" +#import "ui/base/test/cocoa_test_event_utils.h" + +namespace { + +NSEvent* MouseEventInRow(NSMatrix* matrix, NSEventType type, NSInteger row) { + NSRect cell_rect = [matrix cellFrameAtRow:row column:0]; + NSPoint point_in_view = NSMakePoint(NSMidX(cell_rect), NSMidY(cell_rect)); + NSPoint point_in_window = [matrix convertPoint:point_in_view toView:nil]; + return cocoa_test_event_utils::MouseEventAtPoint( + point_in_window, type, 0); +} + +class OmniboxPopupMatrixTest : public CocoaTest, + public OmniboxPopupMatrixDelegate { + public: + OmniboxPopupMatrixTest() + : selected_row_(0), + clicked_row_(0), + middle_clicked_row_(0) { + } + + virtual void SetUp() OVERRIDE { + CocoaTest::SetUp(); + matrix_.reset([[OmniboxPopupMatrix alloc] initWithDelegate:this]); + [[test_window() contentView] addSubview:matrix_]; + }; + + virtual void OnMatrixRowSelected(OmniboxPopupMatrix* matrix, + size_t row) OVERRIDE { + selected_row_ = row; + [matrix_ selectCellAtRow:row column:0]; + } + + virtual void OnMatrixRowClicked(OmniboxPopupMatrix* matrix, + size_t row) OVERRIDE { + clicked_row_ = row; + } + + virtual void OnMatrixRowMiddleClicked(OmniboxPopupMatrix* matrix, + size_t row) OVERRIDE { + middle_clicked_row_ = row; + } + + protected: + base::scoped_nsobject<OmniboxPopupMatrix> matrix_; + size_t selected_row_; + size_t clicked_row_; + size_t middle_clicked_row_; + + private: + DISALLOW_COPY_AND_ASSIGN(OmniboxPopupMatrixTest); +}; + +TEST_VIEW(OmniboxPopupMatrixTest, matrix_); + +TEST_F(OmniboxPopupMatrixTest, HighlightedRow) { + [matrix_ renewRows:3 columns:1]; + EXPECT_EQ(-1, [matrix_ highlightedRow]); + + [matrix_ mouseEntered:MouseEventInRow(matrix_, NSMouseMoved, 0)]; + EXPECT_EQ(0, [matrix_ highlightedRow]); + [matrix_ mouseEntered:MouseEventInRow(matrix_, NSMouseMoved, 2)]; + EXPECT_EQ(2, [matrix_ highlightedRow]); + + [matrix_ mouseExited:MouseEventInRow(matrix_, NSMouseMoved, 2)]; + EXPECT_EQ(-1, [matrix_ highlightedRow]); +} + +TEST_F(OmniboxPopupMatrixTest, SelectedRow) { + [matrix_ renewRows:3 columns:1]; + + [NSApp postEvent:MouseEventInRow(matrix_, NSLeftMouseUp, 2) atStart:YES]; + [matrix_ mouseDown:MouseEventInRow(matrix_, NSLeftMouseDown, 2)]; + + EXPECT_EQ(2u, selected_row_); + EXPECT_EQ(2u, clicked_row_); + EXPECT_EQ(0u, middle_clicked_row_); +} + +} // namespace diff --git a/chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.h b/chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.h index 1d577ef..410beab 100644 --- a/chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.h +++ b/chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.h @@ -11,26 +11,20 @@ #include "base/mac/scoped_nsobject.h" #include "base/memory/scoped_ptr.h" #include "chrome/browser/autocomplete/autocomplete_match.h" +#import "chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.h" #include "chrome/browser/ui/omnibox/omnibox_popup_view.h" #include "ui/gfx/font.h" +class AutocompleteResult; class OmniboxEditModel; -@class OmniboxPopupMatrix; class OmniboxPopupModel; class OmniboxView; // Implements OmniboxPopupView using a raw NSWindow containing an // NSTableView. -// -// TODO(rohitrao): This class is set up in a way that makes testing hard. -// Refactor and write unittests. http://crbug.com/9977 - -class OmniboxPopupViewMac : public OmniboxPopupView { +class OmniboxPopupViewMac : public OmniboxPopupView, + public OmniboxPopupMatrixDelegate { public: - static OmniboxPopupView* Create(OmniboxView* omnibox_view, - OmniboxEditModel* edit_model, - NSTextField* field); - OmniboxPopupViewMac(OmniboxView* omnibox_view, OmniboxEditModel* edit_model, NSTextField* field); @@ -38,71 +32,56 @@ class OmniboxPopupViewMac : public OmniboxPopupView { // Overridden from OmniboxPopupView: virtual bool IsOpen() const OVERRIDE; - virtual void InvalidateLine(size_t line) OVERRIDE { - // TODO(shess): Verify that there is no need to implement this. - // This is currently used in two places in the model: - // - // When setting the selected line, the selected line is - // invalidated, then the selected line is changed, then the new - // selected line is invalidated, then PaintUpdatesNow() is called. - // For us PaintUpdatesNow() should be sufficient. - // - // Same thing happens when changing the hovered line, except with - // no call to PaintUpdatesNow(). Since this code does not - // currently support special display of the hovered line, there's - // nothing to do here. - // - // deanm indicates that this is an anti-flicker optimization, - // which we probably cannot utilize (and may not need) so long as - // we're using NSTableView to implement the popup contents. We - // may need to move away from NSTableView to implement hover, - // though. - } + virtual void InvalidateLine(size_t line) OVERRIDE {} virtual void UpdatePopupAppearance() OVERRIDE; - virtual gfx::Rect GetTargetBounds() OVERRIDE; - // This is only called by model in SetSelectedLine() after updating // everything. Popup should already be visible. virtual void PaintUpdatesNow() OVERRIDE; - virtual void OnDragCanceled() OVERRIDE {} - // Set |line| to be selected. - void SetSelectedLine(size_t line); + // Overridden from OmniboxPopupMatrixDelegate: + virtual void OnMatrixRowSelected(OmniboxPopupMatrix* matrix, + size_t row) OVERRIDE; + virtual void OnMatrixRowClicked(OmniboxPopupMatrix* matrix, + size_t row) OVERRIDE; + virtual void OnMatrixRowMiddleClicked(OmniboxPopupMatrix* matrix, + size_t row) OVERRIDE; - // Opens the URL corresponding to the given |row|. If |force_background| is - // true, forces the URL to open in a background tab. Otherwise, determines - // the proper window open disposition from the modifier flags on |[NSApp - // currentEvent]|. - void OpenURLForRow(int row, bool force_background); + OmniboxPopupMatrix* matrix() { return matrix_; } // Return the text to show for the match, based on the match's // contents and description. Result will be in |font|, with the // boldfaced version used for matches. static NSAttributedString* MatchText(const AutocompleteMatch& match, gfx::Font& font, - float cellWidth); + float cell_width); - // Helper for MatchText() to allow sharing code between the contents - // and description cases. Returns NSMutableAttributedString as a - // convenience for MatchText(). + // Applies the given font and colors to the match string based on + // classifications. static NSMutableAttributedString* DecorateMatchedString( - const string16 &matchString, - const AutocompleteMatch::ACMatchClassifications &classifications, - NSColor* textColor, NSColor* dimTextColor, gfx::Font& font); + const string16& match_string, + const AutocompleteMatch::ACMatchClassifications& classifications, + NSColor* text_color, + NSColor* dim_text_color, + gfx::Font& font); // Helper for MatchText() to elide a marked-up string using - // gfx::ElideText() as a model. Modifies |aString| in place. + // gfx::ElideText() as a model. Modifies |a_string| in place. // TODO(shess): Consider breaking AutocompleteButtonCell out of this // code, and modifying it to have something like -setMatch:, so that // these convolutions to expose internals for testing can be // cleaner. static NSMutableAttributedString* ElideString( - NSMutableAttributedString* aString, - const string16 originalString, + NSMutableAttributedString* a_string, + const string16& original_string, const gfx::Font& font, - const float cellWidth); + const float cell_width); + + protected: + // Gets the autocomplete results. This is virtual so that it can be overriden + // by tests. + virtual const AutocompleteResult& GetResult() const; private: // Create the popup_ instance if needed. @@ -119,17 +98,18 @@ class OmniboxPopupViewMac : public OmniboxPopupView { // Returns the NSImage that should be used as an icon for the given match. NSImage* ImageForMatch(const AutocompleteMatch& match); - // TODO(shess): |omnibox_view_| should already be accessible via - // |field_|, or perhaps via |model_|. Consider refactoring. + // Opens the URL at the given row. + void OpenURLForRow(size_t row, WindowOpenDisposition disposition); + OmniboxView* omnibox_view_; scoped_ptr<OmniboxPopupModel> model_; NSTextField* field_; // owned by tab controller // Child window containing a matrix which implements the popup. base::scoped_nsobject<NSWindow> popup_; - NSRect targetPopupFrame_; + NSRect target_popup_frame_; - base::scoped_nsobject<OmniboxPopupMatrix> autocomplete_matrix_; + base::scoped_nsobject<OmniboxPopupMatrix> matrix_; DISALLOW_COPY_AND_ASSIGN(OmniboxPopupViewMac); }; diff --git a/chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm b/chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm index e1d2291..76b67fb 100644 --- a/chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm +++ b/chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm @@ -12,7 +12,6 @@ #include "chrome/browser/search/search.h" #include "chrome/browser/ui/cocoa/browser_window_controller.h" #import "chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h" -#import "chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.h" #include "chrome/browser/ui/cocoa/omnibox/omnibox_view_mac.h" #include "chrome/browser/ui/omnibox/omnibox_edit_model.h" #include "chrome/browser/ui/omnibox/omnibox_popup_model.h" @@ -64,18 +63,6 @@ NSColor* URLTextColor() { } // namespace -// static -OmniboxPopupView* OmniboxPopupViewMac::Create(OmniboxView* omnibox_view, - OmniboxEditModel* edit_model, - NSTextField* field) { -#if defined(HTML_INSTANT_EXTENDED_POPUP) - if (chrome::IsInstantExtendedAPIEnabled()) - return new OmniboxPopupNonView(edit_model); -#endif - return new OmniboxPopupViewMac(omnibox_view, edit_model, field); -} - - OmniboxPopupViewMac::OmniboxPopupViewMac(OmniboxView* omnibox_view, OmniboxEditModel* edit_model, NSTextField* field) @@ -83,7 +70,7 @@ OmniboxPopupViewMac::OmniboxPopupViewMac(OmniboxView* omnibox_view, model_(new OmniboxPopupModel(this, edit_model)), field_(field), popup_(nil), - targetPopupFrame_(NSZeroRect) { + target_popup_frame_(NSZeroRect) { DCHECK(omnibox_view); DCHECK(edit_model); } @@ -95,7 +82,7 @@ OmniboxPopupViewMac::~OmniboxPopupViewMac() { // Break references to |this| because the popup may not be // deallocated immediately. - [autocomplete_matrix_ setPopupView:NULL]; + [matrix_ setDelegate:NULL]; } bool OmniboxPopupViewMac::IsOpen() const { @@ -104,55 +91,50 @@ bool OmniboxPopupViewMac::IsOpen() const { void OmniboxPopupViewMac::UpdatePopupAppearance() { DCHECK([NSThread isMainThread]); - const AutocompleteResult& result = model_->result(); + const AutocompleteResult& result = GetResult(); if (result.empty()) { [[popup_ parentWindow] removeChildWindow:popup_]; [popup_ orderOut:nil]; // Break references to |this| because the popup may not be // deallocated immediately. - [autocomplete_matrix_ setPopupView:NULL]; - autocomplete_matrix_.reset(); + [matrix_ setDelegate:nil]; + matrix_.reset(); popup_.reset(nil); - targetPopupFrame_ = NSZeroRect; + target_popup_frame_ = NSZeroRect; return; } CreatePopupIfNeeded(); - // The popup's font is a slightly smaller version of the field's. - NSFont* fieldFont = OmniboxViewMac::GetFieldFont(); - const CGFloat resultFontSize = [fieldFont pointSize]; - gfx::Font resultFont(base::SysNSStringToUTF8([fieldFont fontName]), - static_cast<int>(resultFontSize)); + gfx::Font result_font(OmniboxViewMac::GetFieldFont()); - // Calculate the width of the matrix based on backing out the - // popup's border from the width of the field. - const CGFloat matrixWidth = NSWidth([field_ bounds]); - DCHECK_GT(matrixWidth, 0.0); + // Calculate the width of the matrix based on backing out the popup's border + // from the width of the field. + const CGFloat matrix_width = NSWidth([field_ bounds]); + DCHECK_GT(matrix_width, 0.0); // Load the results into the popup's matrix. - const size_t rows = model_->result().size(); + const size_t rows = GetResult().size(); DCHECK_GT(rows, 0U); - [autocomplete_matrix_ renewRows:rows columns:1]; + [matrix_ renewRows:rows columns:1]; for (size_t ii = 0; ii < rows; ++ii) { - OmniboxPopupCell* cell = [autocomplete_matrix_ cellAtRow:ii column:0]; - const AutocompleteMatch& match = model_->result().match_at(ii); + OmniboxPopupCell* cell = [matrix_ cellAtRow:ii column:0]; + const AutocompleteMatch& match = GetResult().match_at(ii); [cell setImage:ImageForMatch(match)]; - [cell setAttributedTitle:MatchText(match, resultFont, matrixWidth)]; + [cell setAttributedTitle:MatchText(match, result_font, matrix_width)]; } // Set the cell size to fit a line of text in the cell's font. All // cells should use the same font and each should layout in one // line, so they should all be about the same height. - const NSSize cellSize = - [[autocomplete_matrix_ cellAtRow:0 column:0] cellSize]; - DCHECK_GT(cellSize.height, 0.0); - const CGFloat cellHeight = cellSize.height + kCellHeightAdjust; - [autocomplete_matrix_ setCellSize:NSMakeSize(matrixWidth, cellHeight)]; + const NSSize cell_size = [[matrix_ cellAtRow:0 column:0] cellSize]; + DCHECK_GT(cell_size.height, 0.0); + const CGFloat cell_height = cell_size.height + kCellHeightAdjust; + [matrix_ setCellSize:NSMakeSize(matrix_width, cell_height)]; // Update the selection before placing (and displaying) the window. PaintUpdatesNow(); @@ -160,50 +142,48 @@ void OmniboxPopupViewMac::UpdatePopupAppearance() { // Calculate the matrix size manually rather than using -sizeToCells // because actually resizing the matrix messed up the popup size // animation. - DCHECK_EQ([autocomplete_matrix_ intercellSpacing].height, 0.0); - PositionPopup(rows * cellHeight); + DCHECK_EQ([matrix_ intercellSpacing].height, 0.0); + PositionPopup(rows * cell_height); } gfx::Rect OmniboxPopupViewMac::GetTargetBounds() { // Flip the coordinate system before returning. NSScreen* screen = [[NSScreen screens] objectAtIndex:0]; - NSRect monitorFrame = [screen frame]; - gfx::Rect bounds(NSRectToCGRect(targetPopupFrame_)); - bounds.set_y(monitorFrame.size.height - bounds.y() - bounds.height()); + NSRect monitor_frame = [screen frame]; + gfx::Rect bounds(NSRectToCGRect(target_popup_frame_)); + bounds.set_y(monitor_frame.size.height - bounds.y() - bounds.height()); return bounds; } // This is only called by model in SetSelectedLine() after updating // everything. Popup should already be visible. void OmniboxPopupViewMac::PaintUpdatesNow() { - [autocomplete_matrix_ selectCellAtRow:model_->selected_line() column:0]; + [matrix_ selectCellAtRow:model_->selected_line() column:0]; } -void OmniboxPopupViewMac::SetSelectedLine(size_t line) { - model_->SetSelectedLine(line, false, false); +void OmniboxPopupViewMac::OnMatrixRowSelected(OmniboxPopupMatrix* matrix, + size_t row) { + model_->SetSelectedLine(row, false, false); } -void OmniboxPopupViewMac::OpenURLForRow(int row, bool force_background) { - DCHECK_GE(row, 0); - - WindowOpenDisposition disposition = NEW_BACKGROUND_TAB; - if (!force_background) { - disposition = ui::WindowOpenDispositionFromNSEvent([NSApp currentEvent]); - } +void OmniboxPopupViewMac::OnMatrixRowClicked(OmniboxPopupMatrix* matrix, + size_t row) { + OpenURLForRow(row, + ui::WindowOpenDispositionFromNSEvent([NSApp currentEvent])); +} - // OpenMatch() may close the popup, which will clear the result set - // and, by extension, |match| and its contents. So copy the - // relevant match out to make sure it stays alive until the call - // completes. - AutocompleteMatch match = model_->result().match_at(row); - omnibox_view_->OpenMatch(match, disposition, GURL(), row); +void OmniboxPopupViewMac::OnMatrixRowMiddleClicked(OmniboxPopupMatrix* matrix, + size_t row) { + OpenURLForRow(row, NEW_BACKGROUND_TAB); } // Return the text to show for the match, based on the match's // contents and description. Result will be in |font|, with the // boldfaced version used for matches. NSAttributedString* OmniboxPopupViewMac::MatchText( - const AutocompleteMatch& match, gfx::Font& font, float cellWidth) { + const AutocompleteMatch& match, + gfx::Font& font, + float cell_width) { NSMutableAttributedString *as = DecorateMatchedString(match.contents, match.contents_class, @@ -219,18 +199,17 @@ NSAttributedString* OmniboxPopupViewMac::MatchText( // partially visible. // TODO(shess): Consider revising our NSCell subclass to have two // bits and just draw them right, rather than truncating here. - const float textWidth = cellWidth - kTextXOffset; + const float text_width = cell_width - kTextXOffset; as = ElideString(as, match.contents, font, - textWidth * kMaxContentsFraction); - - NSDictionary* attributes = - [NSDictionary dictionaryWithObjectsAndKeys: - font.GetNativeFont(), NSFontAttributeName, - ContentTextColor(), NSForegroundColorAttributeName, - nil]; - NSString* rawEnDash = @" \u2013 "; - NSAttributedString* enDash = - [[[NSAttributedString alloc] initWithString:rawEnDash + text_width * kMaxContentsFraction); + + NSDictionary* attributes = @{ + NSFontAttributeName : font.GetNativeFont(), + NSForegroundColorAttributeName : ContentTextColor() + }; + NSString* raw_en_dash = @" \u2013 "; + NSAttributedString* en_dash = + [[[NSAttributedString alloc] initWithString:raw_en_dash attributes:attributes] autorelease]; // In Windows, a boolean force_dim is passed as true for the @@ -242,7 +221,7 @@ NSAttributedString* OmniboxPopupViewMac::MatchText( DimContentTextColor(), font); - [as appendAttributedString:enDash]; + [as appendAttributedString:en_dash]; [as appendAttributedString:description]; } @@ -256,22 +235,22 @@ NSAttributedString* OmniboxPopupViewMac::MatchText( return as; } -// Helper for MatchText() to allow sharing code between the contents -// and description cases. Returns NSMutableAttributedString as a -// convenience for MatchText(). +// static NSMutableAttributedString* OmniboxPopupViewMac::DecorateMatchedString( - const string16 &matchString, - const AutocompleteMatch::ACMatchClassifications &classifications, - NSColor* textColor, NSColor* dimTextColor, gfx::Font& font) { + const string16& match_string, + const AutocompleteMatch::ACMatchClassifications& classifications, + NSColor* text_color, + NSColor* dim_text_color, + gfx::Font& font) { // Cache for on-demand computation of the bold version of |font|. - NSFont* boldFont = nil; + NSFont* bold_font = nil; // Start out with a string using the default style info. - NSString* s = base::SysUTF16ToNSString(matchString); - NSDictionary* attributes = [NSDictionary dictionaryWithObjectsAndKeys: - font.GetNativeFont(), NSFontAttributeName, - textColor, NSForegroundColorAttributeName, - nil]; + NSString* s = base::SysUTF16ToNSString(match_string); + NSDictionary* attributes = @{ + NSFontAttributeName : font.GetNativeFont(), + NSForegroundColorAttributeName : text_color + }; NSMutableAttributedString* as = [[[NSMutableAttributedString alloc] initWithString:s attributes:attributes] @@ -279,17 +258,17 @@ NSMutableAttributedString* OmniboxPopupViewMac::DecorateMatchedString( // As a protective measure, bail if the length of the match string is not // the same as the length of the converted NSString. http://crbug.com/121703 - if ([s length] != matchString.size()) + if ([s length] != match_string.size()) return as; // Mark up the runs which differ from the default. for (ACMatchClassifications::const_iterator i = classifications.begin(); i != classifications.end(); ++i) { - const BOOL isLast = (i+1) == classifications.end(); - const NSInteger nextOffset = - (isLast ? [s length] : static_cast<NSInteger>((i + 1)->offset)); + const BOOL is_last = (i+1) == classifications.end(); + const NSInteger next_offset = + (is_last ? [s length] : static_cast<NSInteger>((i + 1)->offset)); const NSInteger location = static_cast<NSInteger>(i->offset); - const NSInteger length = nextOffset - static_cast<NSInteger>(i->offset); + const NSInteger length = next_offset - static_cast<NSInteger>(i->offset); // Guard against bad, off-the-end classification ranges. if (i->offset >= [s length] || length <= 0) break; @@ -298,21 +277,22 @@ NSMutableAttributedString* OmniboxPopupViewMac::DecorateMatchedString( if (0 != (i->style & ACMatchClassification::URL)) { [as addAttribute:NSForegroundColorAttributeName - value:URLTextColor() range:range]; + value:URLTextColor() + range:range]; } if (0 != (i->style & ACMatchClassification::MATCH)) { - if (!boldFont) { - NSFontManager* fontManager = [NSFontManager sharedFontManager]; - boldFont = [fontManager convertFont:font.GetNativeFont() - toHaveTrait:NSBoldFontMask]; + if (!bold_font) { + NSFontManager* font_manager = [NSFontManager sharedFontManager]; + bold_font = [font_manager convertFont:font.GetNativeFont() + toHaveTrait:NSBoldFontMask]; } - [as addAttribute:NSFontAttributeName value:boldFont range:range]; + [as addAttribute:NSFontAttributeName value:bold_font range:range]; } if (0 != (i->style & ACMatchClassification::DIM)) { [as addAttribute:NSForegroundColorAttributeName - value:dimTextColor + value:dim_text_color range:range]; } } @@ -321,39 +301,43 @@ NSMutableAttributedString* OmniboxPopupViewMac::DecorateMatchedString( } NSMutableAttributedString* OmniboxPopupViewMac::ElideString( - NSMutableAttributedString* aString, - const string16 originalString, + NSMutableAttributedString* a_string, + const string16& original_string, const gfx::Font& font, const float width) { // If it already fits, nothing to be done. - if ([aString size].width <= width) { - return aString; + if ([a_string size].width <= width) { + return a_string; } // If ElideText() decides to do nothing, nothing to be done. const string16 elided = - ui::ElideText(originalString, font, width, ui::ELIDE_AT_END); - if (0 == elided.compare(originalString)) { - return aString; + ui::ElideText(original_string, font, width, ui::ELIDE_AT_END); + if (0 == elided.compare(original_string)) { + return a_string; } // If everything was elided away, clear the string. if (elided.empty()) { - [aString deleteCharactersInRange:NSMakeRange(0, [aString length])]; - return aString; + [a_string deleteCharactersInRange:NSMakeRange(0, [a_string length])]; + return a_string; } // The ellipses should be the last character, and everything before // that should match the original string. const size_t i(elided.length() - 1); - DCHECK_NE(0, elided.compare(0, i, originalString)); + DCHECK_NE(0, elided.compare(0, i, original_string)); // Replace the end of |aString| with the ellipses from |elided|. NSString* s = base::SysUTF16ToNSString(elided.substr(i)); - [aString replaceCharactersInRange:NSMakeRange(i, [aString length] - i) - withString:s]; + [a_string replaceCharactersInRange:NSMakeRange(i, [a_string length] - i) + withString:s]; + + return a_string; +} - return aString; +const AutocompleteResult& OmniboxPopupViewMac::GetResult() const { + return model_->result(); } void OmniboxPopupViewMac::CreatePopupIfNeeded() { @@ -376,9 +360,8 @@ void OmniboxPopupViewMac::CreatePopupIfNeeded() { [[FlippedView alloc] initWithFrame:NSZeroRect]); [popup_ setContentView:contentView]; - autocomplete_matrix_.reset( - [[OmniboxPopupMatrix alloc] initWithPopupView:this]); - [contentView addSubview:autocomplete_matrix_]; + matrix_.reset([[OmniboxPopupMatrix alloc] initWithDelegate:this]); + [contentView addSubview:matrix_]; // TODO(dtseng): Ignore until we provide NSAccessibility support. [popup_ accessibilitySetOverrideValue:NSAccessibilityUnknownRole @@ -389,37 +372,37 @@ void OmniboxPopupViewMac::CreatePopupIfNeeded() { void OmniboxPopupViewMac::PositionPopup(const CGFloat matrixHeight) { BrowserWindowController* controller = [BrowserWindowController browserWindowControllerForView:field_]; - NSRect anchorRectBase = [controller omniboxPopupAnchorRect]; + NSRect anchor_rect_base = [controller omniboxPopupAnchorRect]; // Calculate the popup's position on the screen. - NSRect popupFrame = anchorRectBase; + NSRect popup_frame = anchor_rect_base; // Size to fit the matrix and shift down by the size. - popupFrame.size.height = matrixHeight + kPopupPaddingVertical * 2.0; - popupFrame.origin.y -= NSHeight(popupFrame); + popup_frame.size.height = matrixHeight + kPopupPaddingVertical * 2.0; + popup_frame.origin.y -= NSHeight(popup_frame); // Shift to screen coordinates. - popupFrame.origin = - [[controller window] convertBaseToScreen:popupFrame.origin]; + popup_frame.origin = + [[controller window] convertBaseToScreen:popup_frame.origin]; // Do nothing if the popup is already animating to the given |frame|. - if (NSEqualRects(popupFrame, targetPopupFrame_)) + if (NSEqualRects(popup_frame, target_popup_frame_)) return; - NSPoint fieldOriginBase = + NSPoint field_origin_base = [field_ convertPoint:[field_ bounds].origin toView:nil]; - NSRect matrixFrame = NSZeroRect; - matrixFrame.origin.x = fieldOriginBase.x - NSMinX(anchorRectBase); - matrixFrame.origin.y = kPopupPaddingVertical; - matrixFrame.size.width = [autocomplete_matrix_ cellSize].width; - matrixFrame.size.height = matrixHeight; - [autocomplete_matrix_ setFrame:matrixFrame]; + NSRect matrix_frame = NSZeroRect; + matrix_frame.origin.x = field_origin_base.x - NSMinX(anchor_rect_base); + matrix_frame.origin.y = kPopupPaddingVertical; + matrix_frame.size.width = [matrix_ cellSize].width; + matrix_frame.size.height = matrixHeight; + [matrix_ setFrame:matrix_frame]; - NSRect currentPopupFrame = [popup_ frame]; - targetPopupFrame_ = popupFrame; + NSRect current_poup_frame = [popup_ frame]; + target_popup_frame_ = popup_frame; // Animate the frame change if the only change is that the height got smaller. // Otherwise, resize immediately. - bool animate = (NSHeight(popupFrame) < NSHeight(currentPopupFrame) && - NSWidth(popupFrame) == NSWidth(currentPopupFrame)); + bool animate = (NSHeight(popup_frame) < NSHeight(current_poup_frame) && + NSWidth(popup_frame) == NSWidth(current_poup_frame)); base::scoped_nsobject<NSDictionary> savedAnimations; if (!animate) { @@ -431,16 +414,14 @@ void OmniboxPopupViewMac::PositionPopup(const CGFloat matrixHeight) { // convinces AppKit to do the right thing. Save off the current animations // dictionary so it can be restored later. savedAnimations.reset([[popup_ animations] copy]); - [popup_ setAnimations: - [NSDictionary dictionaryWithObjectsAndKeys:[NSNull null], - @"frame", nil]]; + [popup_ setAnimations:@{@"frame" : [NSNull null]}]; } [NSAnimationContext beginGrouping]; // Don't use the GTM additon for the "Steve" slowdown because this can happen // async from user actions and the effects could be a surprise. [[NSAnimationContext currentContext] setDuration:kShrinkAnimationDuration]; - [[popup_ animator] setFrame:popupFrame display:YES]; + [[popup_ animator] setFrame:popup_frame display:YES]; [NSAnimationContext endGrouping]; if (!animate) { @@ -462,3 +443,14 @@ NSImage* OmniboxPopupViewMac::ImageForMatch(const AutocompleteMatch& match) { IDR_OMNIBOX_STAR : AutocompleteMatch::TypeToIcon(match.type); return OmniboxViewMac::ImageForResource(resource_id); } + +void OmniboxPopupViewMac::OpenURLForRow(size_t row, + WindowOpenDisposition disposition) { + DCHECK_GE(row, 0u); + + // OpenMatch() may close the popup, which will clear the result set and, by + // extension, |match| and its contents. So copy the relevant match out to + // make sure it stays alive until the call completes. + AutocompleteMatch match = GetResult().match_at(row); + omnibox_view_->OpenMatch(match, disposition, GURL(), row); +} diff --git a/chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac_unittest.mm b/chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac_unittest.mm index c2545e9..75f973a 100644 --- a/chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac_unittest.mm +++ b/chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac_unittest.mm @@ -7,7 +7,8 @@ #include "base/memory/scoped_ptr.h" #include "base/strings/sys_string_conversions.h" #include "base/strings/utf_string_conversions.h" -#include "testing/platform_test.h" +#include "chrome/browser/ui/cocoa/cocoa_profile_test.h" +#import "chrome/browser/ui/cocoa/omnibox/omnibox_view_mac.h" #include "ui/base/text/text_elider.h" namespace { @@ -19,15 +20,14 @@ const float kLargeWidth = 10000; NSUInteger RunLengthForAttribute(NSAttributedString* string, NSUInteger location, NSString* attributeName) { - const NSRange fullRange = NSMakeRange(0, [string length]); + const NSRange full_range = NSMakeRange(0, [string length]); NSRange range; [string attribute:attributeName - atIndex:location longestEffectiveRange:&range inRange:fullRange]; + atIndex:location longestEffectiveRange:&range inRange:full_range]; - // In order to signal when the run doesn't start exactly at - // location, return a weirdo length. This causes the incorrect - // expectation to manifest at the calling location, which is more - // useful than an EXPECT_EQ() would be here. + // In order to signal when the run doesn't start exactly at location, return + // a weirdo length. This causes the incorrect expectation to manifest at the + // calling location, which is more useful than an EXPECT_EQ() would be here. if (range.location != location) { return -1; } @@ -35,36 +35,38 @@ NSUInteger RunLengthForAttribute(NSAttributedString* string, return range.length; } -// Return true if the run starting at |location| has |color| for -// attribute NSForegroundColorAttributeName. +// Return true if the run starting at |location| has |color| for attribute +// NSForegroundColorAttributeName. bool RunHasColor(NSAttributedString* string, NSUInteger location, NSColor* color) { - const NSRange fullRange = NSMakeRange(0, [string length]); + const NSRange full_range = NSMakeRange(0, [string length]); NSRange range; - NSColor* runColor = [string attribute:NSForegroundColorAttributeName - atIndex:location - longestEffectiveRange:&range inRange:fullRange]; - - // According to one "Ali Ozer", you can compare objects within the - // same color space using -isEqual:. Converting color spaces - // seems too heavyweight for these tests. + NSColor* run_color = [string attribute:NSForegroundColorAttributeName + atIndex:location + longestEffectiveRange:&range + inRange:full_range]; + + // According to one "Ali Ozer", you can compare objects within the same color + // space using -isEqual:. Converting color spaces seems too heavyweight for + // these tests. // http://lists.apple.com/archives/cocoa-dev/2005/May/msg00186.html - return [runColor isEqual:color] ? true : false; + return [run_color isEqual:color] ? true : false; } -// Return true if the run starting at |location| has the font -// trait(s) in |mask| font in NSFontAttributeName. +// Return true if the run starting at |location| has the font trait(s) in |mask| +// font in NSFontAttributeName. bool RunHasFontTrait(NSAttributedString* string, NSUInteger location, NSFontTraitMask mask) { - const NSRange fullRange = NSMakeRange(0, [string length]); + const NSRange full_range = NSMakeRange(0, [string length]); NSRange range; - NSFont* runFont = [string attribute:NSFontAttributeName - atIndex:location - longestEffectiveRange:&range inRange:fullRange]; + NSFont* run_font = [string attribute:NSFontAttributeName + atIndex:location + longestEffectiveRange:&range + inRange:full_range]; NSFontManager* fontManager = [NSFontManager sharedFontManager]; - if (runFont && (mask == ([fontManager traitsOfFont:runFont]&mask))) { + if (run_font && (mask == ([fontManager traitsOfFont:run_font] & mask))) { return true; } return false; @@ -80,29 +82,51 @@ AutocompleteMatch MakeMatch(const string16& contents, return m; } -class OmniboxPopupViewMacTest : public PlatformTest { +class MockOmniboxPopupViewMac : public OmniboxPopupViewMac { public: - OmniboxPopupViewMacTest() {} + MockOmniboxPopupViewMac(OmniboxView* omnibox_view, + OmniboxEditModel* edit_model, + NSTextField* field) + : OmniboxPopupViewMac(omnibox_view, edit_model, field) { + } - virtual void SetUp() { - PlatformTest::SetUp(); + void SetResultCount(size_t count) { + ACMatches matches; + for (size_t i = 0; i < count; ++i) + matches.push_back(AutocompleteMatch()); + result_.Reset(); + result_.AppendMatches(matches); + } + + protected: + virtual const AutocompleteResult& GetResult() const OVERRIDE { + return result_; + } - // These are here because there is no autorelease pool for the - // constructor. + private: + AutocompleteResult result_; +}; + +class OmniboxPopupViewMacTest : public CocoaProfileTest { + public: + OmniboxPopupViewMacTest() { color_ = [NSColor blackColor]; - dimColor_ = [NSColor darkGrayColor]; + dim_color_ = [NSColor darkGrayColor]; font_ = gfx::Font( base::SysNSStringToUTF8([[NSFont userFontOfSize:12] fontName]), 12); } + protected: NSColor* color_; // weak - NSColor* dimColor_; // weak + NSColor* dim_color_; // weak gfx::Font font_; + + private: + DISALLOW_COPY_AND_ASSIGN(OmniboxPopupViewMacTest); }; -// Simple inputs with no matches should result in styled output who's -// text matches the input string, with the passed-in color, and -// nothing bolded. +// Simple inputs with no matches should result in styled output who's text +// matches the input string, with the passed-in color, and nothing bolded. TEST_F(OmniboxPopupViewMacTest, DecorateMatchedStringNoMatch) { NSString* const string = @"This is a test"; AutocompleteMatch::ACMatchClassifications classifications; @@ -110,7 +134,7 @@ TEST_F(OmniboxPopupViewMacTest, DecorateMatchedStringNoMatch) { NSAttributedString* decorated = OmniboxPopupViewMac::DecorateMatchedString( base::SysNSStringToUTF16(string), classifications, - color_, dimColor_, font_); + color_, dim_color_, font_); // Result has same characters as the input. EXPECT_EQ([decorated length], [string length]); @@ -123,13 +147,13 @@ TEST_F(OmniboxPopupViewMacTest, DecorateMatchedStringNoMatch) { EXPECT_TRUE(RunHasColor(decorated, 0U, color_)); // An unbolded font for the entire string. - EXPECT_EQ(RunLengthForAttribute(decorated, 0U, - NSFontAttributeName), [string length]); + EXPECT_EQ(RunLengthForAttribute(decorated, 0U, NSFontAttributeName), + [string length]); EXPECT_FALSE(RunHasFontTrait(decorated, 0U, NSBoldFontMask)); } -// Identical to DecorateMatchedStringNoMatch, except test that URL -// style gets a different color than we passed in. +// Identical to DecorateMatchedStringNoMatch, except test that URL style gets a +// different color than we passed in. TEST_F(OmniboxPopupViewMacTest, DecorateMatchedStringURLNoMatch) { NSString* const string = @"This is a test"; AutocompleteMatch::ACMatchClassifications classifications; @@ -140,7 +164,7 @@ TEST_F(OmniboxPopupViewMacTest, DecorateMatchedStringURLNoMatch) { NSAttributedString* decorated = OmniboxPopupViewMac::DecorateMatchedString( base::SysNSStringToUTF16(string), classifications, - color_, dimColor_, font_); + color_, dim_color_, font_); // Result has same characters as the input. EXPECT_EQ([decorated length], [string length]); @@ -162,24 +186,24 @@ TEST_F(OmniboxPopupViewMacTest, DecorateMatchedStringURLNoMatch) { TEST_F(OmniboxPopupViewMacTest, DecorateMatchedStringDimNoMatch) { NSString* const string = @"This is a test"; // Dim "is". - const NSUInteger runLength1 = 5, runLength2 = 2, runLength3 = 7; + const NSUInteger run_length_1 = 5, run_length_2 = 2, run_length_3 = 7; // Make sure nobody messed up the inputs. - EXPECT_EQ(runLength1 + runLength2 + runLength3, [string length]); + EXPECT_EQ(run_length_1 + run_length_2 + run_length_3, [string length]); // Push each run onto classifications. AutocompleteMatch::ACMatchClassifications classifications; classifications.push_back( ACMatchClassification(0, ACMatchClassification::NONE)); classifications.push_back( - ACMatchClassification(runLength1, ACMatchClassification::DIM)); + ACMatchClassification(run_length_1, ACMatchClassification::DIM)); classifications.push_back( - ACMatchClassification(runLength1 + runLength2, + ACMatchClassification(run_length_1 + run_length_2, ACMatchClassification::NONE)); NSAttributedString* decorated = OmniboxPopupViewMac::DecorateMatchedString( base::SysNSStringToUTF16(string), classifications, - color_, dimColor_, font_); + color_, dim_color_, font_); // Result has same characters as the input. EXPECT_EQ([decorated length], [string length]); @@ -188,18 +212,18 @@ TEST_F(OmniboxPopupViewMacTest, DecorateMatchedStringDimNoMatch) { // Should have three font runs, normal, dim, normal. EXPECT_EQ(RunLengthForAttribute(decorated, 0U, NSForegroundColorAttributeName), - runLength1); + run_length_1); EXPECT_TRUE(RunHasColor(decorated, 0U, color_)); - EXPECT_EQ(RunLengthForAttribute(decorated, runLength1, + EXPECT_EQ(RunLengthForAttribute(decorated, run_length_1, NSForegroundColorAttributeName), - runLength2); - EXPECT_TRUE(RunHasColor(decorated, runLength1, dimColor_)); + run_length_2); + EXPECT_TRUE(RunHasColor(decorated, run_length_1, dim_color_)); - EXPECT_EQ(RunLengthForAttribute(decorated, runLength1 + runLength2, + EXPECT_EQ(RunLengthForAttribute(decorated, run_length_1 + run_length_2, NSForegroundColorAttributeName), - runLength3); - EXPECT_TRUE(RunHasColor(decorated, runLength1 + runLength2, color_)); + run_length_3); + EXPECT_TRUE(RunHasColor(decorated, run_length_1 + run_length_2, color_)); // An unbolded font for the entire string. EXPECT_EQ(RunLengthForAttribute(decorated, 0U, @@ -207,29 +231,28 @@ TEST_F(OmniboxPopupViewMacTest, DecorateMatchedStringDimNoMatch) { EXPECT_FALSE(RunHasFontTrait(decorated, 0U, NSBoldFontMask)); } -// Test that the matched run gets bold-faced, but keeps the same -// color. +// Test that the matched run gets bold-faced, but keeps the same color. TEST_F(OmniboxPopupViewMacTest, DecorateMatchedStringMatch) { NSString* const string = @"This is a test"; // Match "is". - const NSUInteger runLength1 = 5, runLength2 = 2, runLength3 = 7; + const NSUInteger run_length_1 = 5, run_length_2 = 2, run_length_3 = 7; // Make sure nobody messed up the inputs. - EXPECT_EQ(runLength1 + runLength2 + runLength3, [string length]); + EXPECT_EQ(run_length_1 + run_length_2 + run_length_3, [string length]); // Push each run onto classifications. AutocompleteMatch::ACMatchClassifications classifications; classifications.push_back( ACMatchClassification(0, ACMatchClassification::NONE)); classifications.push_back( - ACMatchClassification(runLength1, ACMatchClassification::MATCH)); + ACMatchClassification(run_length_1, ACMatchClassification::MATCH)); classifications.push_back( - ACMatchClassification(runLength1 + runLength2, + ACMatchClassification(run_length_1 + run_length_2, ACMatchClassification::NONE)); NSAttributedString* decorated = OmniboxPopupViewMac::DecorateMatchedString( base::SysNSStringToUTF16(string), classifications, - color_, dimColor_, font_); + color_, dim_color_, font_); // Result has same characters as the input. EXPECT_EQ([decorated length], [string length]); @@ -243,16 +266,16 @@ TEST_F(OmniboxPopupViewMacTest, DecorateMatchedStringMatch) { // Should have three font runs, not bold, bold, then not bold again. EXPECT_EQ(RunLengthForAttribute(decorated, 0U, - NSFontAttributeName), runLength1); + NSFontAttributeName), run_length_1); EXPECT_FALSE(RunHasFontTrait(decorated, 0U, NSBoldFontMask)); - EXPECT_EQ(RunLengthForAttribute(decorated, runLength1, - NSFontAttributeName), runLength2); - EXPECT_TRUE(RunHasFontTrait(decorated, runLength1, NSBoldFontMask)); + EXPECT_EQ(RunLengthForAttribute(decorated, run_length_1, + NSFontAttributeName), run_length_2); + EXPECT_TRUE(RunHasFontTrait(decorated, run_length_1, NSBoldFontMask)); - EXPECT_EQ(RunLengthForAttribute(decorated, runLength1 + runLength2, - NSFontAttributeName), runLength3); - EXPECT_FALSE(RunHasFontTrait(decorated, runLength1 + runLength2, + EXPECT_EQ(RunLengthForAttribute(decorated, run_length_1 + run_length_2, + NSFontAttributeName), run_length_3); + EXPECT_FALSE(RunHasFontTrait(decorated, run_length_1 + run_length_2, NSBoldFontMask)); } @@ -260,24 +283,24 @@ TEST_F(OmniboxPopupViewMacTest, DecorateMatchedStringMatch) { TEST_F(OmniboxPopupViewMacTest, DecorateMatchedStringURLMatch) { NSString* const string = @"http://hello.world/"; // Match "hello". - const NSUInteger runLength1 = 7, runLength2 = 5, runLength3 = 7; + const NSUInteger run_length_1 = 7, run_length_2 = 5, run_length_3 = 7; // Make sure nobody messed up the inputs. - EXPECT_EQ(runLength1 + runLength2 + runLength3, [string length]); + EXPECT_EQ(run_length_1 + run_length_2 + run_length_3, [string length]); // Push each run onto classifications. AutocompleteMatch::ACMatchClassifications classifications; classifications.push_back( ACMatchClassification(0, ACMatchClassification::URL)); const int kURLMatch = ACMatchClassification::URL|ACMatchClassification::MATCH; - classifications.push_back(ACMatchClassification(runLength1, kURLMatch)); + classifications.push_back(ACMatchClassification(run_length_1, kURLMatch)); classifications.push_back( - ACMatchClassification(runLength1 + runLength2, + ACMatchClassification(run_length_1 + run_length_2, ACMatchClassification::URL)); NSAttributedString* decorated = OmniboxPopupViewMac::DecorateMatchedString( base::SysNSStringToUTF16(string), classifications, - color_, dimColor_, font_); + color_, dim_color_, font_); // Result has same characters as the input. EXPECT_EQ([decorated length], [string length]); @@ -291,16 +314,16 @@ TEST_F(OmniboxPopupViewMacTest, DecorateMatchedStringURLMatch) { // Should have three font runs, not bold, bold, then not bold again. EXPECT_EQ(RunLengthForAttribute(decorated, 0U, - NSFontAttributeName), runLength1); + NSFontAttributeName), run_length_1); EXPECT_FALSE(RunHasFontTrait(decorated, 0U, NSBoldFontMask)); - EXPECT_EQ(RunLengthForAttribute(decorated, runLength1, - NSFontAttributeName), runLength2); - EXPECT_TRUE(RunHasFontTrait(decorated, runLength1, NSBoldFontMask)); + EXPECT_EQ(RunLengthForAttribute(decorated, run_length_1, + NSFontAttributeName), run_length_2); + EXPECT_TRUE(RunHasFontTrait(decorated, run_length_1, NSBoldFontMask)); - EXPECT_EQ(RunLengthForAttribute(decorated, runLength1 + runLength2, - NSFontAttributeName), runLength3); - EXPECT_FALSE(RunHasFontTrait(decorated, runLength1 + runLength2, + EXPECT_EQ(RunLengthForAttribute(decorated, run_length_1 + run_length_2, + NSFontAttributeName), run_length_3); + EXPECT_FALSE(RunHasFontTrait(decorated, run_length_1 + run_length_2, NSBoldFontMask)); } @@ -343,9 +366,9 @@ TEST_F(OmniboxPopupViewMacTest, MatchText) { TEST_F(OmniboxPopupViewMacTest, MatchTextContentsMatch) { NSString* const contents = @"This is a test"; // Match "is". - const NSUInteger runLength1 = 5, runLength2 = 2, runLength3 = 7; + const NSUInteger run_length_1 = 5, run_length_2 = 2, run_length_3 = 7; // Make sure nobody messed up the inputs. - EXPECT_EQ(runLength1 + runLength2 + runLength3, [contents length]); + EXPECT_EQ(run_length_1 + run_length_2 + run_length_3, [contents length]); AutocompleteMatch m = MakeMatch(base::SysNSStringToUTF16(contents), string16()); @@ -354,9 +377,9 @@ TEST_F(OmniboxPopupViewMacTest, MatchTextContentsMatch) { m.contents_class.push_back( ACMatchClassification(0, ACMatchClassification::NONE)); m.contents_class.push_back( - ACMatchClassification(runLength1, ACMatchClassification::MATCH)); + ACMatchClassification(run_length_1, ACMatchClassification::MATCH)); m.contents_class.push_back( - ACMatchClassification(runLength1 + runLength2, + ACMatchClassification(run_length_1 + run_length_2, ACMatchClassification::NONE)); NSAttributedString* decorated = @@ -373,16 +396,16 @@ TEST_F(OmniboxPopupViewMacTest, MatchTextContentsMatch) { // Should have three font runs, not bold, bold, then not bold again. EXPECT_EQ(RunLengthForAttribute(decorated, 0U, - NSFontAttributeName), runLength1); + NSFontAttributeName), run_length_1); EXPECT_FALSE(RunHasFontTrait(decorated, 0U, NSBoldFontMask)); - EXPECT_EQ(RunLengthForAttribute(decorated, runLength1, - NSFontAttributeName), runLength2); - EXPECT_TRUE(RunHasFontTrait(decorated, runLength1, NSBoldFontMask)); + EXPECT_EQ(RunLengthForAttribute(decorated, run_length_1, + NSFontAttributeName), run_length_2); + EXPECT_TRUE(RunHasFontTrait(decorated, run_length_1, NSBoldFontMask)); - EXPECT_EQ(RunLengthForAttribute(decorated, runLength1 + runLength2, - NSFontAttributeName), runLength3); - EXPECT_FALSE(RunHasFontTrait(decorated, runLength1 + runLength2, + EXPECT_EQ(RunLengthForAttribute(decorated, run_length_1 + run_length_2, + NSFontAttributeName), run_length_3); + EXPECT_FALSE(RunHasFontTrait(decorated, run_length_1 + run_length_2, NSBoldFontMask)); } @@ -391,9 +414,9 @@ TEST_F(OmniboxPopupViewMacTest, MatchTextDescriptionMatch) { NSString* const contents = @"This is a test"; NSString* const description = @"That was a test"; // Match "That was". - const NSUInteger runLength1 = 8, runLength2 = 7; + const NSUInteger run_length_1 = 8, run_length_2 = 7; // Make sure nobody messed up the inputs. - EXPECT_EQ(runLength1 + runLength2, [description length]); + EXPECT_EQ(run_length_1 + run_length_2, [description length]); AutocompleteMatch m = MakeMatch(base::SysNSStringToUTF16(contents), base::SysNSStringToUTF16(description)); @@ -402,7 +425,7 @@ TEST_F(OmniboxPopupViewMacTest, MatchTextDescriptionMatch) { m.description_class.push_back( ACMatchClassification(0, ACMatchClassification::MATCH)); m.description_class.push_back( - ACMatchClassification(runLength1, ACMatchClassification::NONE)); + ACMatchClassification(run_length_1, ACMatchClassification::NONE)); NSAttributedString* decorated = OmniboxPopupViewMac::MatchText(m, font_, kLargeWidth); @@ -431,12 +454,12 @@ TEST_F(OmniboxPopupViewMacTest, MatchTextDescriptionMatch) { EXPECT_FALSE(RunHasFontTrait(decorated, 0U, NSBoldFontMask)); EXPECT_EQ(RunLengthForAttribute(decorated, descriptionLocation, - NSFontAttributeName), runLength1); + NSFontAttributeName), run_length_1); EXPECT_TRUE(RunHasFontTrait(decorated, descriptionLocation, NSBoldFontMask)); - EXPECT_EQ(RunLengthForAttribute(decorated, descriptionLocation + runLength1, - NSFontAttributeName), runLength2); - EXPECT_FALSE(RunHasFontTrait(decorated, descriptionLocation + runLength1, + EXPECT_EQ(RunLengthForAttribute(decorated, descriptionLocation + run_length_1, + NSFontAttributeName), run_length_2); + EXPECT_FALSE(RunHasFontTrait(decorated, descriptionLocation + run_length_1, NSBoldFontMask)); } @@ -479,9 +502,9 @@ TEST_F(OmniboxPopupViewMacTest, MatchTextElide) { NSString* const contents = @"This is a test with long contents"; NSString* const description = @"That was a test"; // Match "long". - const NSUInteger runLength1 = 20, runLength2 = 4, runLength3 = 9; + const NSUInteger run_length_1 = 20, run_length_2 = 4, run_length_3 = 9; // Make sure nobody messed up the inputs. - EXPECT_EQ(runLength1 + runLength2 + runLength3, [contents length]); + EXPECT_EQ(run_length_1 + run_length_2 + run_length_3, [contents length]); AutocompleteMatch m = MakeMatch(base::SysNSStringToUTF16(contents), base::SysNSStringToUTF16(description)); @@ -490,9 +513,9 @@ TEST_F(OmniboxPopupViewMacTest, MatchTextElide) { m.contents_class.push_back( ACMatchClassification(0, ACMatchClassification::NONE)); m.contents_class.push_back( - ACMatchClassification(runLength1, ACMatchClassification::MATCH)); + ACMatchClassification(run_length_1, ACMatchClassification::MATCH)); m.contents_class.push_back( - ACMatchClassification(runLength1 + runLength2, + ACMatchClassification(run_length_1 + run_length_2, ACMatchClassification::URL)); // Figure out the width of the contents. @@ -520,7 +543,7 @@ TEST_F(OmniboxPopupViewMacTest, MatchTextElide) { // values being passed to NSAttributedString. Push the ellipsis // through part of each run to verify that we don't continue to see // such things. - while([commonPrefix length] > runLength1 - 3) { + while([commonPrefix length] > run_length_1 - 3) { EXPECT_GT(cellWidth, 0.0); cellWidth -= 1.0; decorated = OmniboxPopupViewMac::MatchText(m, font_, cellWidth); @@ -530,24 +553,33 @@ TEST_F(OmniboxPopupViewMacTest, MatchTextElide) { } } -// TODO(shess): Test that -// OmniboxPopupViewMac::UpdatePopupAppearance() creates/destroys -// the popup according to result contents. Test that the matrix gets -// the right number of results. Test the contents of the cells for -// the right strings. Icons? Maybe, that seems harder to test. -// Styling seems almost impossible. - -// TODO(shess): Test that OmniboxPopupViewMac::PaintUpdatesNow() -// updates the matrix selection. - -// TODO(shess): Test that OmniboxPopupViewMac::AcceptInput() -// updates the model's selection from the matrix before returning. -// Could possibly test that via -select:. - -// TODO(shess): Test that AutocompleteButtonCell returns the right -// background colors for on, highlighted, and neither. - -// TODO(shess): Test that AutocompleteMatrixTarget can be initialized -// and then sends -select: to the view. +TEST_F(OmniboxPopupViewMacTest, UpdatePopupAppearance) { + base::scoped_nsobject<NSTextField> field( + [[NSTextField alloc] initWithFrame:NSMakeRect(0, 0, 100, 20)]); + [[test_window() contentView] addSubview:field]; + + OmniboxViewMac view(NULL, NULL, profile(), NULL, NULL); + MockOmniboxPopupViewMac popup_view(&view, view.model(), field); + + popup_view.UpdatePopupAppearance(); + EXPECT_FALSE(popup_view.IsOpen()); + EXPECT_EQ(0, [popup_view.matrix() numberOfRows]); + + popup_view.SetResultCount(3); + popup_view.UpdatePopupAppearance(); + EXPECT_TRUE(popup_view.IsOpen()); + EXPECT_EQ(3, [popup_view.matrix() numberOfRows]); + + int old_height = popup_view.GetTargetBounds().height(); + popup_view.SetResultCount(5); + popup_view.UpdatePopupAppearance(); + EXPECT_GT(popup_view.GetTargetBounds().height(), old_height); + EXPECT_EQ(5, [popup_view.matrix() numberOfRows]); + + popup_view.SetResultCount(0); + popup_view.UpdatePopupAppearance(); + EXPECT_FALSE(popup_view.IsOpen()); + EXPECT_EQ(0, [popup_view.matrix() numberOfRows]); +} } // namespace diff --git a/chrome/browser/ui/cocoa/omnibox/omnibox_view_mac.mm b/chrome/browser/ui/cocoa/omnibox/omnibox_view_mac.mm index 27711fd..940bb51 100644 --- a/chrome/browser/ui/cocoa/omnibox/omnibox_view_mac.mm +++ b/chrome/browser/ui/cocoa/omnibox/omnibox_view_mac.mm @@ -139,7 +139,7 @@ OmniboxViewMac::OmniboxViewMac(OmniboxEditController* controller, CommandUpdater* command_updater, AutocompleteTextField* field) : OmniboxView(profile, controller, toolbar_model, command_updater), - popup_view_(OmniboxPopupViewMac::Create(this, model(), field)), + popup_view_(new OmniboxPopupViewMac(this, model(), field)), field_(field), delete_was_pressed_(false), delete_at_end_pressed_(false) { |