diff options
author | rohitrao@chromium.org <rohitrao@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-11-06 00:57:40 +0000 |
---|---|---|
committer | rohitrao@chromium.org <rohitrao@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-11-06 00:57:40 +0000 |
commit | de1509c9e4b7322ef13b754acd4f500916b2e0f7 (patch) | |
tree | f35e47690f4ce382a18fa2e47493dfce8a6c0870 /chrome | |
parent | 189cf275c82afe58c656066cc4137ce9e95ece48 (diff) | |
download | chromium_src-de1509c9e4b7322ef13b754acd4f500916b2e0f7.zip chromium_src-de1509c9e4b7322ef13b754acd4f500916b2e0f7.tar.gz chromium_src-de1509c9e4b7322ef13b754acd4f500916b2e0f7.tar.bz2 |
[Mac] Draw the results label correctly in the findbar.
Adds common base classes (StyledTextField and StyledTextFieldCell) for both the find bar and omnibox text fields.
BUG=http://crbug.com/19550
TEST=Findbar results label should not be overdrawn by find text.
TEST=Autocomplete drawing (keyword, hint, lock icon) should not be affected.
Review URL: http://codereview.chromium.org/319005
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@31186 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
24 files changed, 1086 insertions, 337 deletions
diff --git a/chrome/app/nibs/FindBar.xib b/chrome/app/nibs/FindBar.xib index 7561a88..9965871 100644 --- a/chrome/app/nibs/FindBar.xib +++ b/chrome/app/nibs/FindBar.xib @@ -1,18 +1,14 @@ <?xml version="1.0" encoding="UTF-8"?> -<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.10"> +<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.03"> <data> <int key="IBDocument.SystemTarget">1050</int> - <string key="IBDocument.SystemVersion">10B504</string> - <string key="IBDocument.InterfaceBuilderVersion">732</string> - <string key="IBDocument.AppKitVersion">1038.2</string> - <string key="IBDocument.HIToolboxVersion">437.00</string> - <object class="NSMutableDictionary" key="IBDocument.PluginVersions"> - <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin</string> - <string key="NS.object.0">732</string> - </object> + <string key="IBDocument.SystemVersion">9L31a</string> + <string key="IBDocument.InterfaceBuilderVersion">677</string> + <string key="IBDocument.AppKitVersion">949.54</string> + <string key="IBDocument.HIToolboxVersion">353.00</string> <object class="NSMutableArray" key="IBDocument.EditedObjectIDs"> <bool key="EncodedWithXMLCoder">YES</bool> - <integer value="29"/> + <integer value="2"/> </object> <object class="NSArray" key="IBDocument.PluginDependencies"> <bool key="EncodedWithXMLCoder">YES</bool> @@ -20,7 +16,7 @@ </object> <object class="NSMutableDictionary" key="IBDocument.Metadata"> <bool key="EncodedWithXMLCoder">YES</bool> - <object class="NSArray" key="dict.sortedKeys" id="0"> + <object class="NSArray" key="dict.sortedKeys"> <bool key="EncodedWithXMLCoder">YES</bool> </object> <object class="NSMutableArray" key="dict.values"> @@ -48,23 +44,24 @@ <int key="NSvFlags">256</int> <object class="NSMutableArray" key="NSSubviews"> <bool key="EncodedWithXMLCoder">YES</bool> - <object class="NSTextField" id="445667"> + <object class="NSTextField" id="510660793"> <reference key="NSNextResponder" ref="612665518"/> <int key="NSvFlags">290</int> - <string key="NSFrame">{{200, 3}, {31, 22}}</string> + <string key="NSFrame">{{13, 5}, {216, 24}}</string> <reference key="NSSuperview" ref="612665518"/> <bool key="NSEnabled">YES</bool> - <object class="NSTextFieldCell" key="NSCell" id="236923920"> - <int key="NSCellFlags">-1542324672</int> - <int key="NSCellFlags2">71304192</int> + <object class="NSTextFieldCell" key="NSCell" id="926027568"> + <int key="NSCellFlags">-1804468671</int> + <int key="NSCellFlags2">272630784</int> <string key="NSContents"/> <object class="NSFont" key="NSSupport" id="197084721"> <string key="NSName">LucidaGrande</string> - <double key="NSSize">13</double> + <double key="NSSize">1.300000e+01</double> <int key="NSfFlags">1044</int> </object> - <reference key="NSControlView" ref="445667"/> - <object class="NSColor" key="NSBackgroundColor" id="649287797"> + <reference key="NSControlView" ref="510660793"/> + <bool key="NSDrawsBackground">YES</bool> + <object class="NSColor" key="NSBackgroundColor"> <int key="NSColorSpace">6</int> <string key="NSCatalogName">System</string> <string key="NSColorName">textBackgroundColor</string> @@ -74,26 +71,6 @@ </object> </object> <object class="NSColor" key="NSTextColor"> - <int key="NSColorSpace">1</int> - <bytes key="NSRGB">MC42MTk1NjUyNSAwLjYxOTU2NTI1IDAuNjE5NTY1MjUAA</bytes> - </object> - </object> - </object> - <object class="NSTextField" id="510660793"> - <reference key="NSNextResponder" ref="612665518"/> - <int key="NSvFlags">290</int> - <string key="NSFrame">{{13, 6}, {216, 22}}</string> - <reference key="NSSuperview" ref="612665518"/> - <bool key="NSEnabled">YES</bool> - <object class="NSTextFieldCell" key="NSCell" id="926027568"> - <int key="NSCellFlags">-1804468671</int> - <int key="NSCellFlags2">272630784</int> - <string key="NSContents"/> - <reference key="NSSupport" ref="197084721"/> - <reference key="NSControlView" ref="510660793"/> - <bool key="NSDrawsBackground">YES</bool> - <reference key="NSBackgroundColor" ref="649287797"/> - <object class="NSColor" key="NSTextColor"> <int key="NSColorSpace">6</int> <string key="NSCatalogName">System</string> <string key="NSColorName">textColor</string> @@ -115,8 +92,8 @@ <int key="NSCellFlags2">134217728</int> <string key="NSContents"/> <reference key="NSSupport" ref="197084721"/> - <reference key="NSControlView" ref="455192438"/> <int key="NSTag">2</int> + <reference key="NSControlView" ref="455192438"/> <int key="NSButtonFlags">-2033958657</int> <int key="NSButtonFlags2">134</int> <object class="NSCustomResource" key="NSNormalImage"> @@ -140,8 +117,8 @@ <int key="NSCellFlags2">134217728</int> <string key="NSContents"/> <reference key="NSSupport" ref="197084721"/> - <reference key="NSControlView" ref="968135285"/> <int key="NSTag">1</int> + <reference key="NSControlView" ref="968135285"/> <int key="NSButtonFlags">-2033434369</int> <int key="NSButtonFlags2">134</int> <object class="NSCustomResource" key="NSNormalImage"> @@ -234,14 +211,6 @@ </object> <object class="IBConnectionRecord"> <object class="IBOutletConnection" key="connection"> - <string key="label">resultsLabel_</string> - <reference key="source" ref="1001"/> - <reference key="destination" ref="445667"/> - </object> - <int key="connectionID">19</int> - </object> - <object class="IBConnectionRecord"> - <object class="IBOutletConnection" key="connection"> <string key="label">nextButton_</string> <reference key="source" ref="1001"/> <reference key="destination" ref="968135285"/> @@ -278,26 +247,28 @@ <bool key="EncodedWithXMLCoder">YES</bool> <object class="IBObjectRecord"> <int key="objectID">0</int> - <reference key="object" ref="0"/> + <object class="NSArray" key="object" id="482098745"> + <bool key="EncodedWithXMLCoder">YES</bool> + </object> <reference key="children" ref="1000"/> <nil key="parent"/> </object> <object class="IBObjectRecord"> <int key="objectID">-2</int> <reference key="object" ref="1001"/> - <reference key="parent" ref="0"/> - <string key="objectName">File's Owner</string> + <reference key="parent" ref="482098745"/> + <string type="base64-UTF8" key="objectName">RmlsZSdzIE93bmVyA</string> </object> <object class="IBObjectRecord"> <int key="objectID">-1</int> <reference key="object" ref="1003"/> - <reference key="parent" ref="0"/> + <reference key="parent" ref="482098745"/> <string key="objectName">First Responder</string> </object> <object class="IBObjectRecord"> <int key="objectID">-3</int> <reference key="object" ref="1004"/> - <reference key="parent" ref="0"/> + <reference key="parent" ref="482098745"/> <string key="objectName">Application</string> </object> <object class="IBObjectRecord"> @@ -307,14 +278,13 @@ <bool key="EncodedWithXMLCoder">YES</bool> <reference ref="612665518"/> </object> - <reference key="parent" ref="0"/> + <reference key="parent" ref="482098745"/> </object> <object class="IBObjectRecord"> <int key="objectID">2</int> <reference key="object" ref="612665518"/> <object class="NSMutableArray" key="children"> <bool key="EncodedWithXMLCoder">YES</bool> - <reference ref="445667"/> <reference ref="742622660"/> <reference ref="510660793"/> <reference ref="455192438"/> @@ -323,15 +293,6 @@ <reference key="parent" ref="139541997"/> </object> <object class="IBObjectRecord"> - <int key="objectID">6</int> - <reference key="object" ref="445667"/> - <object class="NSMutableArray" key="children"> - <bool key="EncodedWithXMLCoder">YES</bool> - <reference ref="236923920"/> - </object> - <reference key="parent" ref="612665518"/> - </object> - <object class="IBObjectRecord"> <int key="objectID">7</int> <reference key="object" ref="742622660"/> <object class="NSMutableArray" key="children"> @@ -387,20 +348,16 @@ <reference key="object" ref="768031501"/> <reference key="parent" ref="742622660"/> </object> - <object class="IBObjectRecord"> - <int key="objectID">9</int> - <reference key="object" ref="236923920"/> - <reference key="parent" ref="445667"/> - </object> </object> </object> <object class="NSMutableDictionary" key="flattenedProperties"> <bool key="EncodedWithXMLCoder">YES</bool> - <object class="NSArray" key="dict.sortedKeys"> + <object class="NSMutableArray" key="dict.sortedKeys"> <bool key="EncodedWithXMLCoder">YES</bool> <string>-1.IBPluginDependency</string> <string>-2.IBPluginDependency</string> <string>-3.IBPluginDependency</string> + <string>10.CustomClassName</string> <string>10.IBPluginDependency</string> <string>11.CustomClassName</string> <string>11.IBPluginDependency</string> @@ -416,21 +373,17 @@ <string>29.IBPluginDependency</string> <string>3.IBPluginDependency</string> <string>4.IBPluginDependency</string> + <string>5.CustomClassName</string> <string>5.IBPluginDependency</string> - <string>6.IBPluginDependency</string> - <string>6.IBViewIntegration.shadowBlurRadius</string> - <string>6.IBViewIntegration.shadowColor</string> - <string>6.IBViewIntegration.shadowOffsetHeight</string> - <string>6.IBViewIntegration.shadowOffsetWidth</string> <string>7.IBPluginDependency</string> <string>8.IBPluginDependency</string> - <string>9.IBPluginDependency</string> </object> <object class="NSMutableArray" key="dict.values"> <bool key="EncodedWithXMLCoder">YES</bool> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>FindBarTextFieldCell</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>ToolbarButtonCell</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> @@ -438,20 +391,15 @@ <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>{{753, 971}, {310, 33}}</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> - <real value="0.0"/> + <real value="0.000000e+00"/> <reference ref="817558590"/> - <real value="0.0"/> - <real value="0.0"/> + <real value="0.000000e+00"/> + <real value="0.000000e+00"/> <string>{{805, 959}, {310, 33}}</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> - <string>com.apple.InterfaceBuilder.CocoaPlugin</string> - <string>com.apple.InterfaceBuilder.CocoaPlugin</string> - <real value="0.0"/> - <reference ref="817558590"/> - <real value="0.0"/> - <real value="0.0"/> + <string>FindBarTextField</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> @@ -459,7 +407,9 @@ </object> <object class="NSMutableDictionary" key="unlocalizedProperties"> <bool key="EncodedWithXMLCoder">YES</bool> - <reference key="dict.sortedKeys" ref="0"/> + <object class="NSArray" key="dict.sortedKeys"> + <bool key="EncodedWithXMLCoder">YES</bool> + </object> <object class="NSMutableArray" key="dict.values"> <bool key="EncodedWithXMLCoder">YES</bool> </object> @@ -467,7 +417,9 @@ <nil key="activeLocalization"/> <object class="NSMutableDictionary" key="localizations"> <bool key="EncodedWithXMLCoder">YES</bool> - <reference key="dict.sortedKeys" ref="0"/> + <object class="NSArray" key="dict.sortedKeys"> + <bool key="EncodedWithXMLCoder">YES</bool> + </object> <object class="NSMutableArray" key="dict.values"> <bool key="EncodedWithXMLCoder">YES</bool> </object> @@ -503,7 +455,7 @@ <string key="superclassName">NSViewController</string> <object class="NSMutableDictionary" key="actions"> <bool key="EncodedWithXMLCoder">YES</bool> - <object class="NSArray" key="dict.sortedKeys"> + <object class="NSMutableArray" key="dict.sortedKeys"> <bool key="EncodedWithXMLCoder">YES</bool> <string>close:</string> <string>nextResult:</string> @@ -518,8 +470,9 @@ </object> <object class="NSMutableDictionary" key="outlets"> <bool key="EncodedWithXMLCoder">YES</bool> - <object class="NSArray" key="dict.sortedKeys"> + <object class="NSMutableArray" key="dict.sortedKeys"> <bool key="EncodedWithXMLCoder">YES</bool> + <string>findBarView_</string> <string>findText_</string> <string>nextButton_</string> <string>previousButton_</string> @@ -527,7 +480,8 @@ </object> <object class="NSMutableArray" key="dict.values"> <bool key="EncodedWithXMLCoder">YES</bool> - <string>NSTextField</string> + <string>NSView</string> + <string>FindBarTextField</string> <string>NSButton</string> <string>NSButton</string> <string>NSTextField</string> @@ -539,6 +493,22 @@ </object> </object> <object class="IBPartialClassDescription"> + <string key="className">FindBarTextField</string> + <string key="superclassName">StyledTextField</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBProjectSource</string> + <string key="minorKey">browser/cocoa/find_bar_text_field.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">FindBarTextFieldCell</string> + <string key="superclassName">StyledTextFieldCell</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBProjectSource</string> + <string key="minorKey">browser/cocoa/find_bar_text_field_cell.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> <string key="className">FindBarView</string> <string key="superclassName">BackgroundGradientView</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> @@ -569,70 +539,32 @@ </object> </object> <object class="IBPartialClassDescription"> - <string key="className">ToolbarButtonCell</string> - <string key="superclassName">ClickHoldButtonCell</string> + <string key="className">StyledTextField</string> + <string key="superclassName">NSTextField</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBProjectSource</string> - <string key="minorKey">browser/cocoa/toolbar_button_cell.h</string> + <string key="minorKey">browser/cocoa/styled_text_field.h</string> </object> </object> - </object> - <object class="NSMutableArray" key="referencedPartialClassDescriptionsV3.1+"> - <bool key="EncodedWithXMLCoder">YES</bool> <object class="IBPartialClassDescription"> - <string key="className">FindBarCocoaController</string> - <string key="superclassName">NSViewController</string> - <object class="NSMutableDictionary" key="actions"> - <bool key="EncodedWithXMLCoder">YES</bool> - <object class="NSArray" key="dict.sortedKeys"> - <bool key="EncodedWithXMLCoder">YES</bool> - <string>close:</string> - <string>nextResult:</string> - <string>previousResult:</string> - </object> - <object class="NSMutableArray" key="dict.values"> - <bool key="EncodedWithXMLCoder">YES</bool> - <string>id</string> - <string>id</string> - <string>id</string> - </object> - </object> - <object class="NSMutableDictionary" key="outlets"> - <bool key="EncodedWithXMLCoder">YES</bool> - <object class="NSArray" key="dict.sortedKeys"> - <bool key="EncodedWithXMLCoder">YES</bool> - <string>findBarView_</string> - <string>findText_</string> - <string>nextButton_</string> - <string>previousButton_</string> - <string>resultsLabel_</string> - </object> - <object class="NSMutableArray" key="dict.values"> - <bool key="EncodedWithXMLCoder">YES</bool> - <string>NSView</string> - <string>NSTextField</string> - <string>NSButton</string> - <string>NSButton</string> - <string>NSTextField</string> - </object> + <string key="className">StyledTextFieldCell</string> + <string key="superclassName">NSTextFieldCell</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBProjectSource</string> + <string key="minorKey">browser/cocoa/styled_text_field_cell.h</string> </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">ToolbarButtonCell</string> + <string key="superclassName">ClickHoldButtonCell</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBDocumentRelativeSource</string> - <string key="minorKey">../../browser/cocoa/find_bar_cocoa_controller.h</string> + <string key="majorKey">IBProjectSource</string> + <string key="minorKey">browser/cocoa/toolbar_button_cell.h</string> </object> </object> </object> </object> <int key="IBDocument.localizationMode">0</int> - <object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDependencies"> - <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin.macosx</string> - <integer value="1050" key="NS.object.0"/> - </object> - <object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDevelopmentDependencies"> - <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin.InterfaceBuilder3</string> - <integer value="3000" key="NS.object.0"/> - </object> - <bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool> <string key="IBDocument.LastKnownRelativeProjectPath">../../chrome.xcodeproj</string> <int key="IBDocument.defaultPropertyAccessControl">3</int> </data> diff --git a/chrome/browser/cocoa/autocomplete_text_field.h b/chrome/browser/cocoa/autocomplete_text_field.h index 7ffbb7e..112212c 100644 --- a/chrome/browser/cocoa/autocomplete_text_field.h +++ b/chrome/browser/cocoa/autocomplete_text_field.h @@ -6,6 +6,7 @@ #define CHROME_BROWSER_COCOA_AUTOCOMPLETE_TEXT_FIELD_H_ #import <Cocoa/Cocoa.h> +#import "chrome/browser/cocoa/styled_text_field.h" @class AutocompleteTextFieldCell; @@ -25,10 +26,8 @@ // Provides a hook so that we can call directly down to // AutocompleteEditViewMac rather than traversing the delegate chain. - class AutocompleteTextFieldObserver { public: - // Called when the control-key state changes while the field is // first responder. virtual void OnControlKeyChanged(bool pressed) = 0; @@ -54,7 +53,7 @@ class AutocompleteTextFieldObserver { virtual void OnFrameChanged() = 0; }; -@interface AutocompleteTextField : NSTextField { +@interface AutocompleteTextField : StyledTextField { @private AutocompleteTextFieldObserver* observer_; // weak, owned by location bar. } @@ -64,15 +63,6 @@ class AutocompleteTextFieldObserver { // Convenience method to return the cell, casted appropriately. - (AutocompleteTextFieldCell*)autocompleteTextFieldCell; -// If the keyword, keyword hint, or search hint changed, then the -// field editor may need to be repositioned. -- (void)resetFieldEditorFrameIfNeeded; - -// Returns the amount of the field's width which is not being taken up -// by the text contents. May be negative if the contents are large -// enough to scroll. -- (CGFloat)availableDecorationWidth; - // Superclass aborts editing before changing the string, which causes // problems for undo. This version modifies the field editor's // contents if the control is already being edited. diff --git a/chrome/browser/cocoa/autocomplete_text_field.mm b/chrome/browser/cocoa/autocomplete_text_field.mm index 9d995c11..c89fd17 100644 --- a/chrome/browser/cocoa/autocomplete_text_field.mm +++ b/chrome/browser/cocoa/autocomplete_text_field.mm @@ -2,10 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/cocoa/autocomplete_text_field.h" +#import "chrome/browser/cocoa/autocomplete_text_field.h" #include "base/logging.h" -#include "chrome/browser/cocoa/autocomplete_text_field_cell.h" +#import "chrome/browser/cocoa/autocomplete_text_field_cell.h" @implementation AutocompleteTextField @@ -29,48 +29,6 @@ return static_cast<AutocompleteTextFieldCell*>([self cell]); } -// Cocoa text fields are edited by placing an NSTextView as subview, -// positioned by the cell's -editWithFrame:inView:... method. Using -// the standard -makeFirstResponder: machinery to reposition the field -// editor results in resetting the field editor's editing state, which -// AutocompleteEditViewMac monitors. This causes problems because -// editing can require the field editor to be repositioned, which -// could disrupt editing. This code repositions the subview directly, -// which causes no editing-state changes. -- (void)resetFieldEditorFrameIfNeeded { - // No action if not editing. - NSText* editor = [self currentEditor]; - if (!editor) { - return; - } - - // When editing, we should have exactly one subview, which is a - // clipview containing the editor (for purposes of scrolling). - NSArray* subviews = [self subviews]; - DCHECK_EQ([subviews count], 1U); - DCHECK([editor isDescendantOf:self]); - if ([subviews count] == 0) { - return; - } - - // If the frame is already right, don't make any visible changes. - AutocompleteTextFieldCell* cell = [self autocompleteTextFieldCell]; - const NSRect frame([cell drawingRectForBounds:[self bounds]]); - NSView* subview = [subviews objectAtIndex:0]; - if (NSEqualRects(frame, [subview frame])) { - return; - } - - [subview setFrame:frame]; - - // Make sure the selection remains visible. - // TODO(shess) This could be janky if it jerks the visible region - // around too much. I believe that text fields only scroll in - // response to selection movement (continuing the selection past the - // edge, or arrowing the cursor around). - [editor scrollRangeToVisible:[editor selectedRange]]; -} - // Reroute events for the decoration area to the field editor. This // will cause the cursor to be moved as close to the edge where the // event was seen as possible. @@ -104,7 +62,7 @@ const NSPoint locationInWindow = [theEvent locationInWindow]; const NSPoint location = [self convertPoint:locationInWindow fromView:nil]; - AutocompleteTextFieldCell* cell = [self cell]; + AutocompleteTextFieldCell* cell = [self autocompleteTextFieldCell]; const NSRect textFrame([cell textFrameForFrame:[self bounds]]); // A version of the textFrame which extends across the field's @@ -174,13 +132,7 @@ [editor mouseDown:theEvent]; } -- (CGFloat)availableDecorationWidth { - NSAttributedString* as = [self attributedStringValue]; - const NSSize size([as size]); - const NSRect bounds([self bounds]); - return NSWidth(bounds) - size.width; -} - +// Overriden to pass OnFrameChanged() notifications to |observer_|. - (void)setFrame:(NSRect)frameRect { [super setFrame:frameRect]; if (observer_) { diff --git a/chrome/browser/cocoa/autocomplete_text_field_cell.h b/chrome/browser/cocoa/autocomplete_text_field_cell.h index 2aa04a8..65749a6 100644 --- a/chrome/browser/cocoa/autocomplete_text_field_cell.h +++ b/chrome/browser/cocoa/autocomplete_text_field_cell.h @@ -4,20 +4,17 @@ #import <Cocoa/Cocoa.h> +#import "chrome/browser/cocoa/styled_text_field_cell.h" + #include "base/scoped_nsobject.h" #include "chrome/browser/cocoa/location_bar_view_mac.h" -// AutocompleteTextFieldCell customizes the look of the Omnibox text -// field. The border and focus ring are modified, as is the font -// baseline. - -// The cell also provides support for certain decorations to be -// applied to the field. These are the search hint ("Type to search" -// on the right-hand side), the keyword hint ("Press [Tab] to search -// Engine" on the right-hand side), and keyword mode ("Search Engine:" -// in a button-like token on the left-hand side). - -@interface AutocompleteTextFieldCell : NSTextFieldCell { +// AutocompleteTextFieldCell extends StyledTextFieldCell to provide support for +// certain decorations to be applied to the field. These are the search hint +// ("Type to search" on the right-hand side), the keyword hint ("Press [Tab] to +// search Engine" on the right-hand side), and keyword mode ("Search Engine:" in +// a button-like token on the left-hand side). +@interface AutocompleteTextFieldCell : StyledTextFieldCell { @private // Set if there is a string to display in a rounded rect on the // left-hand side of the field. Exclusive WRT |hintString_|. @@ -58,13 +55,6 @@ // security_image_view_ to handle the click (i.e., show the page info dialog). - (void)onSecurityIconMousePressed; -// Return the portion of the cell to show the text cursor over. -- (NSRect)textCursorFrameForFrame:(NSRect)cellFrame; - -// Return the portion of the cell to use for text display. This -// corresponds to the frame with our added decorations sliced off. -- (NSRect)textFrameForFrame:(NSRect)cellFrame; - // Return 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; diff --git a/chrome/browser/cocoa/autocomplete_text_field_cell.mm b/chrome/browser/cocoa/autocomplete_text_field_cell.mm index 56581ce..2104a31 100644 --- a/chrome/browser/cocoa/autocomplete_text_field_cell.mm +++ b/chrome/browser/cocoa/autocomplete_text_field_cell.mm @@ -6,12 +6,12 @@ #include "app/gfx/font.h" #include "app/resource_bundle.h" -#import "base/logging.h" +#include "base/logging.h" #import "third_party/GTM/AppKit/GTMTheme.h" namespace { -const NSInteger kBaselineAdjust = 2; +const CGFloat kBaselineAdjust = 2.0; // How far to offset the keyword token into the field. const NSInteger kKeywordXOffset = 3; @@ -36,11 +36,6 @@ const NSInteger kKeywordYInset = 4; // technique would be nice to have, though. const NSInteger kKeywordHintImageBaseline = -6; -// Offset from the bottom of the field for drawing decoration text. -// TODO(shess): Somehow determine the baseline for the text field and -// use that. -const NSInteger kBaselineOffset = 4; - // The amount of padding on either side reserved for drawing an icon. const NSInteger kIconHorizontalPad = 3; @@ -72,6 +67,10 @@ CGFloat WidthForKeyword(NSAttributedString* keywordString) { return hintString_.get(); } +- (CGFloat)baselineAdjust { + return kBaselineAdjust; +} + - (void)setKeywordString:(NSString*)fullString partialString:(NSString*)partialString availableWidth:(CGFloat)width { @@ -94,7 +93,6 @@ CGFloat WidthForKeyword(NSAttributedString* keywordString) { } keywordString_.reset( [[NSAttributedString alloc] initWithString:s attributes:attributes]); - } // Convenience for the attributes used in the right-justified info @@ -204,52 +202,9 @@ CGFloat WidthForKeyword(NSAttributedString* keywordString) { security_image_view_->OnMousePressed(); } -// TODO(shess): This code is manually drawing the cell's border area, -// but otherwise the cell assumes -setBordered:YES for purposes of -// calculating things like the editing area. This is probably -// incorrect. I know that this affects -drawingRectForBounds:. - -- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView*)controlView { - DCHECK([controlView isFlipped]); - [[NSColor colorWithCalibratedWhite:1.0 alpha:0.25] set]; - NSFrameRectWithWidthUsingOperation(cellFrame, 1, NSCompositeSourceOver); - - // TODO(shess): This inset is also reflected in ToolbarController - // -autocompletePopupPosition. - NSRect frame = NSInsetRect(cellFrame, 0, 1); - [[self backgroundColor] setFill]; - NSRect innerFrame = NSInsetRect(frame, 1, 1); - NSRectFill(innerFrame); - - NSRect shadowFrame, restFrame; - NSDivideRect(innerFrame, &shadowFrame, &restFrame, 1, NSMinYEdge); - - BOOL isMainWindow = [[controlView window] isMainWindow]; - GTMTheme *theme = [controlView gtm_theme]; - NSColor* stroke = [theme strokeColorForStyle:GTMThemeStyleToolBarButton - state:isMainWindow]; - [stroke set]; - NSFrameRectWithWidthUsingOperation(frame, 1.0, NSCompositeSourceOver); - - // Draw the shadow. - [[NSColor colorWithCalibratedWhite:0.0 alpha:0.05] setFill]; - NSRectFillUsingOperation(shadowFrame, NSCompositeSourceOver); - - if ([self showsFirstResponder]) { - [[[NSColor keyboardFocusIndicatorColor] colorWithAlphaComponent:0.5] set]; - NSFrameRectWithWidthUsingOperation(NSInsetRect(frame, 0, 0), 2, - NSCompositeSourceOver); - } - - [self drawInteriorWithFrame:cellFrame inView:controlView]; -} - -- (NSRect)textCursorFrameForFrame:(NSRect)cellFrame { - return NSInsetRect(cellFrame, 0, kBaselineAdjust); -} - +// Overriden to account for the hint strings and hint icons. - (NSRect)textFrameForFrame:(NSRect)cellFrame { - NSRect textFrame([self textCursorFrameForFrame:cellFrame]); + NSRect textFrame([super textFrameForFrame:cellFrame]); if (hintString_) { DCHECK(!keywordString_); @@ -323,13 +278,6 @@ CGFloat WidthForKeyword(NSAttributedString* keywordString) { return [self imageFrameForFrame:cellFrame withImageView:security_image_view_]; } -// For NSTextFieldCell this is the area within the borders. For our -// purposes, we count the info decorations as being part of the -// border. -- (NSRect)drawingRectForBounds:(NSRect)theRect { - return [super drawingRectForBounds:[self textFrameForFrame:theRect]]; -} - - (void)drawHintWithFrame:(NSRect)cellFrame inView:(NSView*)controlView { DCHECK(hintString_); @@ -413,9 +361,4 @@ CGFloat WidthForKeyword(NSAttributedString* keywordString) { [super drawInteriorWithFrame:cellFrame inView:controlView]; } -- (void)resetCursorRect:(NSRect)cellFrame inView:(NSView *)controlView { - [super resetCursorRect:[self textCursorFrameForFrame:cellFrame] - inView:controlView]; -} - @end diff --git a/chrome/browser/cocoa/autocomplete_text_field_cell_unittest.mm b/chrome/browser/cocoa/autocomplete_text_field_cell_unittest.mm index 3cc5703..79f0ecb 100644 --- a/chrome/browser/cocoa/autocomplete_text_field_cell_unittest.mm +++ b/chrome/browser/cocoa/autocomplete_text_field_cell_unittest.mm @@ -19,43 +19,42 @@ const CGFloat kWidth(300.0); // A narrow width for tests which test things that don't fit. const CGFloat kNarrowWidth(5.0); -class AutocompleteTextFieldCellTest : public PlatformTest { +class AutocompleteTextFieldCellTest : public CocoaTest { public: AutocompleteTextFieldCellTest() : security_image_view_(NULL, NULL) { // Make sure this is wide enough to play games with the cell // decorations. const NSRect frame = NSMakeRect(0, 0, kWidth, 30); - view_.reset([[NSTextField alloc] initWithFrame:frame]); + + scoped_nsobject<NSTextField> view( + [[NSTextField alloc] initWithFrame:frame]); + view_ = view.get(); + scoped_nsobject<AutocompleteTextFieldCell> cell( [[AutocompleteTextFieldCell alloc] initTextCell:@"Testing"]); [cell setEditable:YES]; [cell setBordered:YES]; - [view_ setCell:cell.get()]; [cell setSecurityImageView:&security_image_view_]; - [cocoa_helper_.contentView() addSubview:view_.get()]; + [view_ setCell:cell.get()]; + + [[test_window() contentView] addSubview:view_]; } - CocoaTestHelper cocoa_helper_; // Inits Cocoa, creates window, etc... - scoped_nsobject<NSTextField> view_; + NSTextField* view_; LocationBarViewMac::SecurityImageView security_image_view_; }; -// Test adding/removing from the view hierarchy, mostly to ensure nothing -// leaks or crashes. -TEST_F(AutocompleteTextFieldCellTest, AddRemove) { - EXPECT_EQ(cocoa_helper_.contentView(), [view_ superview]); - [view_.get() removeFromSuperview]; - EXPECT_FALSE([view_ superview]); -} +// Basic view tests (AddRemove, Display). +TEST_VIEW(AutocompleteTextFieldCellTest, view_); // Test drawing, mostly to ensure nothing leaks or crashes. -TEST_F(AutocompleteTextFieldCellTest, Display) { +TEST_F(AutocompleteTextFieldCellTest, FocusedDisplay) { [view_ display]; - // Test focussed drawing. - cocoa_helper_.makeFirstResponder(view_); + // Test focused drawing. + [test_window() makePretendKeyWindowAndSetFirstResponder:view_]; [view_ display]; - cocoa_helper_.clearFirstResponder(); + [test_window() clearPretendKeyWindowAndFirstResponder]; // Test display of various cell configurations. AutocompleteTextFieldCell* cell = diff --git a/chrome/browser/cocoa/find_bar_cocoa_controller.h b/chrome/browser/cocoa/find_bar_cocoa_controller.h index b974fcf..21ce106 100644 --- a/chrome/browser/cocoa/find_bar_cocoa_controller.h +++ b/chrome/browser/cocoa/find_bar_cocoa_controller.h @@ -11,6 +11,7 @@ class BrowserWindowCocoa; class FindBarBridge; +@class FindBarTextField; class FindNotificationDetails; @class FocusTracker; @@ -23,8 +24,7 @@ class FindNotificationDetails; @interface FindBarCocoaController : NSViewController { @private IBOutlet NSView* findBarView_; - IBOutlet NSTextField* findText_; - IBOutlet NSTextField* resultsLabel_; + IBOutlet FindBarTextField* findText_; IBOutlet NSButton* nextButton_; IBOutlet NSButton* previousButton_; diff --git a/chrome/browser/cocoa/find_bar_cocoa_controller.mm b/chrome/browser/cocoa/find_bar_cocoa_controller.mm index dc39596..009370b 100644 --- a/chrome/browser/cocoa/find_bar_cocoa_controller.mm +++ b/chrome/browser/cocoa/find_bar_cocoa_controller.mm @@ -4,14 +4,14 @@ #import <Cocoa/Cocoa.h> -#include "app/l10n_util.h" #include "base/mac_util.h" #include "base/sys_string_conversions.h" -#include "grit/generated_resources.h" #include "chrome/browser/find_bar_controller.h" #include "chrome/browser/cocoa/browser_window_cocoa.h" #import "chrome/browser/cocoa/find_bar_cocoa_controller.h" #import "chrome/browser/cocoa/find_bar_bridge.h" +#import "chrome/browser/cocoa/find_bar_text_field.h" +#import "chrome/browser/cocoa/find_bar_text_field_cell.h" #import "chrome/browser/cocoa/find_pasteboard.h" #import "chrome/browser/cocoa/focus_tracker.h" #import "chrome/browser/cocoa/tab_strip_controller.h" @@ -276,33 +276,20 @@ static float kFindBarCloseDuration = 0.15; result.number_of_matches() != -1; NSString* searchString = [findText_ stringValue]; if ([searchString length] > 0 && validRange) { - [resultsLabel_ setStringValue:base::SysWideToNSString( - l10n_util::GetStringF(IDS_FIND_IN_PAGE_COUNT, - IntToWString(result.active_match_ordinal()), - IntToWString(result.number_of_matches())))]; + [[findText_ findBarTextFieldCell] + setActiveMatch:result.active_match_ordinal() + of:result.number_of_matches()]; } else { - // If there was no text entered, we don't show anything in the result count - // area. - [resultsLabel_ setStringValue:@""]; + // If there was no text entered, we don't show anything in the results area. + [[findText_ findBarTextFieldCell] clearResults]; } + [findText_ resetFieldEditorFrameIfNeeded]; + // If we found any results, reset the focus tracker, so we always // restore focus to the tab contents. if (result.number_of_matches() > 0) focusTracker_.reset(nil); - - // Resize |resultsLabel_| to completely contain its string and right-justify - // it within |findText_|. sizeToFit may shrink the frame vertically, which we - // don't want, so we save the original vertical positioning. - NSRect labelFrame = [resultsLabel_ frame]; - [resultsLabel_ sizeToFit]; - labelFrame.size.width = [resultsLabel_ frame].size.width; - labelFrame.origin.x = NSMaxX([findText_ frame]) - labelFrame.size.width; - [resultsLabel_ setFrame:labelFrame]; - - // TODO(rohitrao): If the search string is too long, then it will overlap with - // the results label. Fix. Perhaps use the code that fades out the tab titles - // if they are too long. } - (BOOL)isFindBarVisible { diff --git a/chrome/browser/cocoa/find_bar_cocoa_controller_unittest.mm b/chrome/browser/cocoa/find_bar_cocoa_controller_unittest.mm index 5b48350..71614d8 100644 --- a/chrome/browser/cocoa/find_bar_cocoa_controller_unittest.mm +++ b/chrome/browser/cocoa/find_bar_cocoa_controller_unittest.mm @@ -13,6 +13,7 @@ #import "chrome/browser/cocoa/cocoa_test_helper.h" #import "chrome/browser/cocoa/find_bar_cocoa_controller.h" #import "chrome/browser/cocoa/find_pasteboard.h" +#import "chrome/browser/cocoa/find_bar_text_field.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/platform_test.h" @@ -20,8 +21,7 @@ @interface FindBarCocoaController(Testing) - (NSView*)findBarView; - (NSString*)findText; -- (NSTextField*)findTextField; -- (NSTextField*)resultsLabel; +- (FindBarTextField*)findTextField; @end @implementation FindBarCocoaController(Testing) @@ -36,10 +36,6 @@ - (NSTextField*)findTextField { return findText_; } - -- (NSTextField*)resultsLabel { - return resultsLabel_; -} @end namespace { diff --git a/chrome/browser/cocoa/find_bar_text_field.h b/chrome/browser/cocoa/find_bar_text_field.h new file mode 100644 index 0000000..714fbdb --- /dev/null +++ b/chrome/browser/cocoa/find_bar_text_field.h @@ -0,0 +1,21 @@ +// 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. + +#import <Cocoa/Cocoa.h> +#import "chrome/browser/cocoa/styled_text_field.h" + +@class FindBarTextFieldCell; + +// TODO(rohitrao): This class may not need to exist, since it does not really +// add any functionality over StyledTextField. See if we can change the nib +// file to put a FindBarTextFieldCell into a StyledTextField. + +// Extends StyledTextField to use a custom cell class (FindBarTextFieldCell). +@interface FindBarTextField : StyledTextField { +} + +// Convenience method to return the cell, casted appropriately. +- (FindBarTextFieldCell*)findBarTextFieldCell; + +@end diff --git a/chrome/browser/cocoa/find_bar_text_field.mm b/chrome/browser/cocoa/find_bar_text_field.mm new file mode 100644 index 0000000..7873c02 --- /dev/null +++ b/chrome/browser/cocoa/find_bar_text_field.mm @@ -0,0 +1,25 @@ +// 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. + +#import "chrome/browser/cocoa/find_bar_text_field.h" + +#include "base/logging.h" +#import "chrome/browser/cocoa/find_bar_text_field_cell.h" + +@implementation FindBarTextField + ++ (Class)cellClass { + return [FindBarTextFieldCell class]; +} + +- (void)awakeFromNib { + DCHECK([[self cell] isKindOfClass:[FindBarTextFieldCell class]]); +} + +- (FindBarTextFieldCell*)findBarTextFieldCell { + DCHECK([[self cell] isKindOfClass:[FindBarTextFieldCell class]]); + return static_cast<FindBarTextFieldCell*>([self cell]); +} + +@end diff --git a/chrome/browser/cocoa/find_bar_text_field_cell.h b/chrome/browser/cocoa/find_bar_text_field_cell.h new file mode 100644 index 0000000..2ca447ac --- /dev/null +++ b/chrome/browser/cocoa/find_bar_text_field_cell.h @@ -0,0 +1,24 @@ +// 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. + +#import <Cocoa/Cocoa.h> + +#import "chrome/browser/cocoa/styled_text_field_cell.h" + +#include "base/scoped_nsobject.h" + +// FindBarTextFieldCell extends StyledTextFieldCell to provide support for a +// results label rooted at the right edge of the cell. +@interface FindBarTextFieldCell : StyledTextFieldCell { + @private + // Set if there is a results label to display on the right side of the cell. + scoped_nsobject<NSAttributedString> resultsString_; +} + +// Sets the results label to the localized equivalent of "X of Y". +- (void)setActiveMatch:(NSInteger)current of:(NSInteger)total; + +- (void)clearResults; + +@end diff --git a/chrome/browser/cocoa/find_bar_text_field_cell.mm b/chrome/browser/cocoa/find_bar_text_field_cell.mm new file mode 100644 index 0000000..9b52c5f --- /dev/null +++ b/chrome/browser/cocoa/find_bar_text_field_cell.mm @@ -0,0 +1,109 @@ +// 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. + +#import "chrome/browser/cocoa/find_bar_text_field_cell.h" + +#include "app/l10n_util.h" +#include "base/logging.h" +#include "base/string_util.h" +#include "base/sys_string_conversions.h" +#include "grit/generated_resources.h" + +namespace { + +const CGFloat kBaselineAdjust = 1.0; + +// How far to offset the keyword token into the field. +const NSInteger kResultsXOffset = 3; + +// How much width (beyond text) to add to the keyword token on each +// side. +const NSInteger kResultsTokenInset = 3; + +// How far to shift bounding box of hint down from top of field. +// Assumes -setFlipped:YES. +const NSInteger kResultsYOffset = 4; + +// How far the editor insets itself, for purposes of determining if +// decorations need to be trimmed. +const CGFloat kEditorHorizontalInset = 3.0; + +// Conveniences to centralize width+offset calculations. +CGFloat WidthForResults(NSAttributedString* resultsString) { + return kResultsXOffset + ceil([resultsString size].width) + + 2 * kResultsTokenInset; +} + +} // namespace + +@implementation FindBarTextFieldCell + +- (CGFloat)baselineAdjust { + return kBaselineAdjust; +} + +// @synthesize doesn't seem to compile for this transition. +- (NSAttributedString*)resultsString { + return resultsString_.get(); +} + +// Convenience for the attributes used in the right-justified info +// cells. Sets the background color to red if |foundMatches| is YES. +- (NSDictionary*)resultsAttributes:(BOOL)foundMatches { + scoped_nsobject<NSMutableParagraphStyle> style( + [[NSMutableParagraphStyle alloc] init]); + [style setAlignment:NSRightTextAlignment]; + + return [NSDictionary dictionaryWithObjectsAndKeys: + [self font], NSFontAttributeName, + [NSColor lightGrayColor], NSForegroundColorAttributeName, + [NSColor whiteColor], NSBackgroundColorAttributeName, + style.get(), NSParagraphStyleAttributeName, + nil]; +} + +- (void)setActiveMatch:(NSInteger)current of:(NSInteger)total { + NSString* results = + base::SysWideToNSString(l10n_util::GetStringF(IDS_FIND_IN_PAGE_COUNT, + IntToWString(current), + IntToWString(total))); + resultsString_.reset([[NSAttributedString alloc] + initWithString:results + attributes:[self resultsAttributes:(total > 0)]]); +} + +- (void)clearResults { + resultsString_.reset(nil); +} + +- (NSRect)textFrameForFrame:(NSRect)cellFrame { + NSRect textFrame([super textFrameForFrame:cellFrame]); + if (resultsString_) + textFrame.size.width -= WidthForResults(resultsString_); + return textFrame; +} + +// Do not show the I-beam cursor over the results label. +- (NSRect)textCursorFrameForFrame:(NSRect)cellFrame { + return [self textFrameForFrame:cellFrame]; +} + +- (void)drawResultsWithFrame:(NSRect)cellFrame inView:(NSView*)controlView { + DCHECK(resultsString_); + + NSRect textFrame = [self textFrameForFrame:cellFrame]; + NSRect infoFrame(NSMakeRect(NSMaxX(textFrame), + cellFrame.origin.y + kResultsYOffset, + ceil([resultsString_ size].width), + cellFrame.size.height - kResultsYOffset)); + [resultsString_.get() drawInRect:infoFrame]; +} + +- (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView*)controlView { + if (resultsString_) + [self drawResultsWithFrame:cellFrame inView:controlView]; + [super drawInteriorWithFrame:cellFrame inView:controlView]; +} + +@end diff --git a/chrome/browser/cocoa/find_bar_text_field_cell_unittest.mm b/chrome/browser/cocoa/find_bar_text_field_cell_unittest.mm new file mode 100644 index 0000000..50011a4 --- /dev/null +++ b/chrome/browser/cocoa/find_bar_text_field_cell_unittest.mm @@ -0,0 +1,138 @@ +// 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. + +#import <Cocoa/Cocoa.h> + +#include "base/scoped_nsobject.h" +#import "chrome/browser/cocoa/find_bar_text_field_cell.h" +#import "chrome/browser/cocoa/cocoa_test_helper.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/platform_test.h" + +@interface FindBarTextFieldCell (ExposedForTesting) +- (NSAttributedString*)resultsString; +@end + +@implementation FindBarTextFieldCell (ExposedForTesting) +- (NSAttributedString*)resultsString { + return resultsString_.get(); +} +@end + +namespace { + +// Width of the field so that we don't have to ask |field_| for it all +// the time. +const CGFloat kWidth(300.0); + +// A narrow width for tests which test things that don't fit. +const CGFloat kNarrowWidth(5.0); + +class FindBarTextFieldCellTest : public CocoaTest { + public: + FindBarTextFieldCellTest() { + // Make sure this is wide enough to play games with the cell + // decorations. + const NSRect frame = NSMakeRect(0, 0, kWidth, 30); + + scoped_nsobject<FindBarTextFieldCell> cell( + [[FindBarTextFieldCell alloc] initTextCell:@"Testing"]); + cell_ = cell; + [cell_ setEditable:YES]; + [cell_ setBordered:YES]; + + scoped_nsobject<NSTextField> view( + [[NSTextField alloc] initWithFrame:frame]); + view_ = view; + [view_ setCell:cell_]; + + [[test_window() contentView] addSubview:view_]; + } + + NSTextField* view_; + FindBarTextFieldCell* cell_; +}; + +// Basic view tests (AddRemove, Display). +TEST_VIEW(FindBarTextFieldCellTest, view_); + +// Test drawing, mostly to ensure nothing leaks or crashes. +TEST_F(FindBarTextFieldCellTest, FocusedDisplay) { + [view_ display]; + + // Test focused drawing. + [test_window() makePretendKeyWindowAndSetFirstResponder:view_]; + [view_ display]; + [test_window() clearPretendKeyWindowAndFirstResponder]; + + // Test display of various cell configurations. + [cell_ setActiveMatch:4 of:30]; + [view_ display]; + + [cell_ setActiveMatch:0 of:0]; + [view_ display]; + + [cell_ clearResults]; + [view_ display]; +} + +// Verify that setting and clearing the find results changes the results string +// appropriately. +TEST_F(FindBarTextFieldCellTest, SetAndClearFindResults) { + [cell_ setActiveMatch:10 of:30]; + scoped_nsobject<NSAttributedString> tenString([[cell_ resultsString] copy]); + EXPECT_GT([tenString length], 0U); + + [cell_ setActiveMatch:0 of:0]; + scoped_nsobject<NSAttributedString> zeroString([[cell_ resultsString] copy]); + EXPECT_GT([zeroString length], 0U); + EXPECT_FALSE([tenString isEqualToAttributedString:zeroString]); + + [cell_ clearResults]; + EXPECT_EQ(0U, [[cell_ resultsString] length]); +} + +TEST_F(FindBarTextFieldCellTest, TextFrame) { + const NSRect bounds = [view_ bounds]; + NSRect textFrame = [cell_ textFrameForFrame:bounds]; + NSRect cursorFrame = [cell_ textCursorFrameForFrame:bounds]; + + // At default settings, everything goes to the text area. + EXPECT_FALSE(NSIsEmptyRect(textFrame)); + EXPECT_TRUE(NSContainsRect(bounds, textFrame)); + EXPECT_EQ(NSMinX(bounds), NSMinX(textFrame)); + EXPECT_EQ(NSMaxX(bounds), NSMaxX(textFrame)); + EXPECT_TRUE(NSEqualRects(cursorFrame, textFrame)); + + // Setting an active match leaves text frame to left. + [cell_ setActiveMatch:4 of:5]; + textFrame = [cell_ textFrameForFrame:bounds]; + cursorFrame = [cell_ textCursorFrameForFrame:bounds]; + EXPECT_FALSE(NSIsEmptyRect(textFrame)); + EXPECT_TRUE(NSContainsRect(bounds, textFrame)); + EXPECT_LT(NSMaxX(textFrame), NSMaxX(bounds)); + EXPECT_TRUE(NSEqualRects(cursorFrame, textFrame)); + +} + +// The editor frame should be slightly inset from the text frame. +TEST_F(FindBarTextFieldCellTest, DrawingRectForBounds) { + const NSRect bounds = [view_ bounds]; + NSRect textFrame = [cell_ textFrameForFrame:bounds]; + NSRect drawingRect = [cell_ drawingRectForBounds:bounds]; + + // Save the starting frame for after clear. + const NSRect originalDrawingRect(drawingRect); + + EXPECT_FALSE(NSIsEmptyRect(drawingRect)); + EXPECT_TRUE(NSContainsRect(textFrame, NSInsetRect(drawingRect, 1, 1))); + + [cell_ setActiveMatch:4 of:5]; + textFrame = [cell_ textFrameForFrame:bounds]; + drawingRect = [cell_ drawingRectForBounds:bounds]; + EXPECT_FALSE(NSIsEmptyRect(drawingRect)); + EXPECT_TRUE(NSContainsRect(textFrame, NSInsetRect(drawingRect, 1, 1))); +} + +} // namespace diff --git a/chrome/browser/cocoa/find_bar_text_field_unittest.mm b/chrome/browser/cocoa/find_bar_text_field_unittest.mm new file mode 100644 index 0000000..fdb1b38 --- /dev/null +++ b/chrome/browser/cocoa/find_bar_text_field_unittest.mm @@ -0,0 +1,92 @@ +// 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. + +#import <Cocoa/Cocoa.h> + +#import "base/cocoa_protocols_mac.h" +#include "base/scoped_nsobject.h" +#import "chrome/browser/cocoa/find_bar_text_field.h" +#import "chrome/browser/cocoa/find_bar_text_field_cell.h" +#import "chrome/browser/cocoa/cocoa_test_helper.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/platform_test.h" +#import "third_party/ocmock/OCMock/OCMock.h" + +// OCMock wants to mock a concrete class or protocol. This should +// provide a correct protocol for newer versions of the SDK, while +// providing something mockable for older versions. + +@protocol MockTextEditingDelegate<NSControlTextEditingDelegate> +- (void)controlTextDidBeginEditing:(NSNotification*)aNotification; +- (BOOL)control:(NSControl*)control textShouldEndEditing:(NSText*)fieldEditor; +@end + +namespace { + +// Width of the field so that we don't have to ask |field_| for it all +// the time. +static const CGFloat kWidth(300.0); + +class FindBarTextFieldTest : public CocoaTest { + public: + FindBarTextFieldTest() { + // Make sure this is wide enough to play games with the cell + // decorations. + NSRect frame = NSMakeRect(0, 0, kWidth, 30); + scoped_nsobject<FindBarTextField> field( + [[FindBarTextField alloc] initWithFrame:frame]); + field_ = field.get(); + + [field_ setStringValue:@"Test test"]; + [[test_window() contentView] addSubview:field_]; + } + + FindBarTextField* field_; +}; + +// Basic view tests (AddRemove, Display). +TEST_VIEW(FindBarTextFieldTest, field_); + +// Test that we have the right cell class. +TEST_F(FindBarTextFieldTest, CellClass) { + EXPECT_TRUE([[field_ cell] isKindOfClass:[FindBarTextFieldCell class]]); +} + +// Test that we get the same cell from -cell and +// -findBarTextFieldCell. +TEST_F(FindBarTextFieldTest, Cell) { + FindBarTextFieldCell* cell = [field_ findBarTextFieldCell]; + EXPECT_EQ(cell, [field_ cell]); + EXPECT_TRUE(cell != nil); +} + +// Test that becoming first responder sets things up correctly. +TEST_F(FindBarTextFieldTest, FirstResponder) { + EXPECT_EQ(nil, [field_ currentEditor]); + EXPECT_EQ([[field_ subviews] count], 0U); + [test_window() makePretendKeyWindowAndSetFirstResponder:field_]; + EXPECT_FALSE(nil == [field_ currentEditor]); + EXPECT_EQ([[field_ subviews] count], 1U); + EXPECT_TRUE([[field_ currentEditor] isDescendantOf:field_]); +} + +// Test drawing, mostly to ensure nothing leaks or crashes. +TEST_F(FindBarTextFieldTest, Display) { + [field_ display]; + + // Test focussed drawing. + [test_window() makePretendKeyWindowAndSetFirstResponder:field_]; + [field_ display]; + [test_window() clearPretendKeyWindowAndFirstResponder]; + + // Test display of various cell configurations. + FindBarTextFieldCell* cell = [field_ findBarTextFieldCell]; + [cell setActiveMatch:4 of:5]; + [field_ display]; + + [cell clearResults]; + [field_ display]; +} + +} // namespace diff --git a/chrome/browser/cocoa/styled_text_field.h b/chrome/browser/cocoa/styled_text_field.h new file mode 100644 index 0000000..68a65b7 --- /dev/null +++ b/chrome/browser/cocoa/styled_text_field.h @@ -0,0 +1,29 @@ +// 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. + +#import <Cocoa/Cocoa.h> + +@class StyledTextFieldCell; + +// An implementation of NSTextField that is designed to work with +// StyledTextFieldCell. Provides methods to redraw the field when cell +// decorations have changed and overrides |mouseDown:| to properly handle clicks +// in sections of the cell with decorations. +@interface StyledTextField : NSTextField { +} + +// Repositions and redraws the field editor. Call this method when the cell's +// text frame has changed (whenever changing cell decorations). +- (void)resetFieldEditorFrameIfNeeded; + +// Returns the amount of the field's width which is not being taken up +// by the text contents. May be negative if the contents are large +// enough to scroll. +- (CGFloat)availableDecorationWidth; + +@end + +@interface StyledTextField (ExposedForTesting) +- (StyledTextFieldCell*)styledTextFieldCell; +@end diff --git a/chrome/browser/cocoa/styled_text_field.mm b/chrome/browser/cocoa/styled_text_field.mm new file mode 100644 index 0000000..bf2641c --- /dev/null +++ b/chrome/browser/cocoa/styled_text_field.mm @@ -0,0 +1,65 @@ +// 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. + +#import "chrome/browser/cocoa/styled_text_field.h" + +#include "base/logging.h" +#import "chrome/browser/cocoa/styled_text_field_cell.h" + +@implementation StyledTextField + +- (StyledTextFieldCell*)styledTextFieldCell { + DCHECK([[self cell] isKindOfClass:[StyledTextFieldCell class]]); + return static_cast<StyledTextFieldCell*>([self cell]); +} + +// Cocoa text fields are edited by placing an NSTextView as subview, +// positioned by the cell's -editWithFrame:inView:... method. Using +// the standard -makeFirstResponder: machinery to reposition the field +// editor results in resetting the field editor's editing state, which +// AutocompleteEditViewMac monitors. This causes problems because +// editing can require the field editor to be repositioned, which +// could disrupt editing. This code repositions the subview directly, +// which causes no editing-state changes. +- (void)resetFieldEditorFrameIfNeeded { + // No action if not editing. + NSText* editor = [self currentEditor]; + if (!editor) { + return; + } + + // When editing, we should have exactly one subview, which is a + // clipview containing the editor (for purposes of scrolling). + NSArray* subviews = [self subviews]; + DCHECK_EQ([subviews count], 1U); + DCHECK([editor isDescendantOf:self]); + if ([subviews count] == 0) { + return; + } + + // If the frame is already right, don't make any visible changes. + StyledTextFieldCell* cell = [self styledTextFieldCell]; + const NSRect frame([cell drawingRectForBounds:[self bounds]]); + NSView* subview = [subviews objectAtIndex:0]; + if (NSEqualRects(frame, [subview frame])) { + return; + } + + [subview setFrame:frame]; + + // Make sure the selection remains visible. + // TODO(shess) This could be janky if it jerks the visible region + // around too much. I believe that text fields only scroll in + // response to selection movement (continuing the selection past the + // edge, or arrowing the cursor around). + [editor scrollRangeToVisible:[editor selectedRange]]; +} + +- (CGFloat)availableDecorationWidth { + NSAttributedString* as = [self attributedStringValue]; + const NSSize size([as size]); + const NSRect bounds([self bounds]); + return NSWidth(bounds) - size.width; +} +@end diff --git a/chrome/browser/cocoa/styled_text_field_cell.h b/chrome/browser/cocoa/styled_text_field_cell.h new file mode 100644 index 0000000..476f765 --- /dev/null +++ b/chrome/browser/cocoa/styled_text_field_cell.h @@ -0,0 +1,31 @@ +// 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. + +#import <Cocoa/Cocoa.h> + +// StyledTextFieldCell customizes the look of the standard Cocoa text field. +// The border and focus ring are modified, as is the font baseline. Subclasses +// can override |drawInteriorWithFrame:inView:| to provide custom drawing for +// decorations, but they must make sure to call the superclass' implementation +// with a modified frame after performing any custom drawing. + +@interface StyledTextFieldCell : NSTextFieldCell { +} + +// Baseline adjust for the text in this cell. Defaults to 0. Subclasses should +// override as needed. +- (CGFloat)baselineAdjust; + +// Return the portion of the cell to show the text cursor over. The default +// implementation returns the full |cellFrame|. Subclasses should override this +// method if they add any decorations. +- (NSRect)textCursorFrameForFrame:(NSRect)cellFrame; + +// Return the portion of the cell to use for text display. This corresponds to +// the frame with our added decorations sliced off. The default implementation +// returns the full |cellFrame|, as by default there are no decorations. +// Subclasses should override this method if they add any decorations. +- (NSRect)textFrameForFrame:(NSRect)cellFrame; + +@end diff --git a/chrome/browser/cocoa/styled_text_field_cell.mm b/chrome/browser/cocoa/styled_text_field_cell.mm new file mode 100644 index 0000000..79b1adf --- /dev/null +++ b/chrome/browser/cocoa/styled_text_field_cell.mm @@ -0,0 +1,83 @@ +// 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. + +#import "chrome/browser/cocoa/styled_text_field_cell.h" + +#include "app/gfx/font.h" +#include "app/resource_bundle.h" +#include "base/logging.h" +#import "third_party/GTM/AppKit/GTMTheme.h" + +@implementation StyledTextFieldCell + +- (CGFloat)baselineAdjust { + return 0.0; +} + +// Returns the same value as textCursorFrameForFrame, but does not call it +// directly to avoid potential infinite loops. +- (NSRect)textFrameForFrame:(NSRect)cellFrame { + return NSInsetRect(cellFrame, 0, [self baselineAdjust]); +} + +// Returns the same value as textFrameForFrame, but does not call it directly to +// avoid potential infinite loops. +- (NSRect)textCursorFrameForFrame:(NSRect)cellFrame { + return NSInsetRect(cellFrame, 0, [self baselineAdjust]); +} + +// Override to show the I-beam cursor only in the area given by +// |textCursorFrameForFrame:|. +- (void)resetCursorRect:(NSRect)cellFrame inView:(NSView *)controlView { + [super resetCursorRect:[self textCursorFrameForFrame:cellFrame] + inView:controlView]; +} + +// For NSTextFieldCell this is the area within the borders. For our +// purposes, we count the info decorations as being part of the +// border. +- (NSRect)drawingRectForBounds:(NSRect)theRect { + return [super drawingRectForBounds:[self textFrameForFrame:theRect]]; +} + +// TODO(shess): This code is manually drawing the cell's border area, +// but otherwise the cell assumes -setBordered:YES for purposes of +// calculating things like the editing area. This is probably +// incorrect. I know that this affects -drawingRectForBounds:. +- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView*)controlView { + DCHECK([controlView isFlipped]); + [[NSColor colorWithCalibratedWhite:1.0 alpha:0.25] set]; + NSFrameRectWithWidthUsingOperation(cellFrame, 1, NSCompositeSourceOver); + + // TODO(shess): This inset is also reflected in ToolbarController + // -autocompletePopupPosition. + NSRect frame = NSInsetRect(cellFrame, 0, 1); + [[self backgroundColor] setFill]; + NSRect innerFrame = NSInsetRect(frame, 1, 1); + NSRectFill(innerFrame); + + NSRect shadowFrame, restFrame; + NSDivideRect(innerFrame, &shadowFrame, &restFrame, 1, NSMinYEdge); + + BOOL isMainWindow = [[controlView window] isMainWindow]; + GTMTheme *theme = [controlView gtm_theme]; + NSColor* stroke = [theme strokeColorForStyle:GTMThemeStyleToolBarButton + state:isMainWindow]; + [stroke set]; + NSFrameRectWithWidthUsingOperation(frame, 1.0, NSCompositeSourceOver); + + // Draw the shadow. + [[NSColor colorWithCalibratedWhite:0.0 alpha:0.05] setFill]; + NSRectFillUsingOperation(shadowFrame, NSCompositeSourceOver); + + if ([self showsFirstResponder]) { + [[[NSColor keyboardFocusIndicatorColor] colorWithAlphaComponent:0.5] set]; + NSFrameRectWithWidthUsingOperation(NSInsetRect(frame, 0, 0), 2, + NSCompositeSourceOver); + } + + [self drawInteriorWithFrame:cellFrame inView:controlView]; +} + +@end diff --git a/chrome/browser/cocoa/styled_text_field_cell_unittest.mm b/chrome/browser/cocoa/styled_text_field_cell_unittest.mm new file mode 100644 index 0000000..5928d43 --- /dev/null +++ b/chrome/browser/cocoa/styled_text_field_cell_unittest.mm @@ -0,0 +1,97 @@ +// 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. + +#import <Cocoa/Cocoa.h> + +#include "base/scoped_nsobject.h" +#import "chrome/browser/cocoa/styled_text_field_cell.h" +#import "chrome/browser/cocoa/styled_text_field_test_helper.h" +#import "chrome/browser/cocoa/cocoa_test_helper.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/platform_test.h" + +namespace { + +// Width of the field so that we don't have to ask |field_| for it all +// the time. +const CGFloat kWidth(300.0); + +class StyledTextFieldCellTest : public CocoaTest { + public: + StyledTextFieldCellTest() { + // Make sure this is wide enough to play games with the cell + // decorations. + const NSRect frame = NSMakeRect(0, 0, kWidth, 30); + + scoped_nsobject<StyledTextFieldTestCell> cell( + [[StyledTextFieldTestCell alloc] initTextCell:@"Testing"]); + cell_ = cell.get(); + [cell_ setEditable:YES]; + [cell_ setBordered:YES]; + + scoped_nsobject<NSTextField> view( + [[NSTextField alloc] initWithFrame:frame]); + view_ = view.get(); + [view_ setCell:cell_]; + + [[test_window() contentView] addSubview:view_]; + } + + //CocoaTestHelper cocoa_helper_; // Inits Cocoa, creates window, etc... + NSTextField* view_; + StyledTextFieldTestCell* cell_; +}; + +// Basic view tests (AddRemove, Display). +TEST_VIEW(StyledTextFieldCellTest, view_); + +// Test drawing, mostly to ensure nothing leaks or crashes. +TEST_F(StyledTextFieldCellTest, FocusedDisplay) { + [view_ display]; + + // Test focused drawing. + [test_window() makePretendKeyWindowAndSetFirstResponder:view_]; + [view_ display]; + [test_window() clearPretendKeyWindowAndFirstResponder]; + + // Test display of various cell configurations. + [cell_ setLeftMargin:5]; + [view_ display]; + + [cell_ setRightMargin:15]; + [view_ display]; +} + +// The editor frame should be slightly inset from the text frame. +TEST_F(StyledTextFieldCellTest, DrawingRectForBounds) { + const NSRect bounds = [view_ bounds]; + NSRect textFrame = [cell_ textFrameForFrame:bounds]; + NSRect drawingRect = [cell_ drawingRectForBounds:bounds]; + + EXPECT_FALSE(NSIsEmptyRect(drawingRect)); + EXPECT_TRUE(NSContainsRect(textFrame, NSInsetRect(drawingRect, 1, 1))); + + // Save the starting frame for after clear. + const NSRect originalDrawingRect = drawingRect; + + [cell_ setLeftMargin:10]; + textFrame = [cell_ textFrameForFrame:bounds]; + drawingRect = [cell_ drawingRectForBounds:bounds]; + EXPECT_FALSE(NSIsEmptyRect(drawingRect)); + EXPECT_TRUE(NSContainsRect(textFrame, NSInsetRect(drawingRect, 1, 1))); + + [cell_ setRightMargin:20]; + textFrame = [cell_ textFrameForFrame:bounds]; + drawingRect = [cell_ drawingRectForBounds:bounds]; + EXPECT_FALSE(NSIsEmptyRect(drawingRect)); + EXPECT_TRUE(NSContainsRect(NSInsetRect(textFrame, 1, 1), drawingRect)); + + [cell_ setLeftMargin:0]; + textFrame = [cell_ textFrameForFrame:bounds]; + drawingRect = [cell_ drawingRectForBounds:bounds]; + EXPECT_FALSE(NSIsEmptyRect(drawingRect)); + EXPECT_TRUE(NSContainsRect(NSInsetRect(textFrame, 1, 1), drawingRect)); +} + +} // namespace diff --git a/chrome/browser/cocoa/styled_text_field_test_helper.h b/chrome/browser/cocoa/styled_text_field_test_helper.h new file mode 100644 index 0000000..20788d4 --- /dev/null +++ b/chrome/browser/cocoa/styled_text_field_test_helper.h @@ -0,0 +1,16 @@ +// 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. + +#import <Cocoa/Cocoa.h> +#import "chrome/browser/cocoa/styled_text_field_cell.h" + +// Subclass of StyledTextFieldCell that allows you to slice off sections on the +// left and right of the cell. +@interface StyledTextFieldTestCell : StyledTextFieldCell { + CGFloat leftMargin_; + CGFloat rightMargin_; +} +@property(assign) CGFloat leftMargin; +@property(assign) CGFloat rightMargin; +@end diff --git a/chrome/browser/cocoa/styled_text_field_test_helper.mm b/chrome/browser/cocoa/styled_text_field_test_helper.mm new file mode 100644 index 0000000..fcae06a --- /dev/null +++ b/chrome/browser/cocoa/styled_text_field_test_helper.mm @@ -0,0 +1,18 @@ +// 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. + +#import <Cocoa/Cocoa.h> +#import "chrome/browser/cocoa/styled_text_field_test_helper.h" + +@implementation StyledTextFieldTestCell +@synthesize leftMargin = leftMargin_; +@synthesize rightMargin = rightMargin_; + +- (NSRect)textFrameForFrame:(NSRect)frame { + NSRect textFrame = [super textFrameForFrame:frame]; + textFrame.origin.x += leftMargin_; + textFrame.size.width -= (leftMargin_ + rightMargin_); + return textFrame; +} +@end diff --git a/chrome/browser/cocoa/styled_text_field_unittest.mm b/chrome/browser/cocoa/styled_text_field_unittest.mm new file mode 100644 index 0000000..000e77a --- /dev/null +++ b/chrome/browser/cocoa/styled_text_field_unittest.mm @@ -0,0 +1,198 @@ +// 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. + +#import <Cocoa/Cocoa.h> + +#import "base/cocoa_protocols_mac.h" +#include "base/scoped_nsobject.h" +#import "chrome/browser/cocoa/styled_text_field.h" +#import "chrome/browser/cocoa/styled_text_field_cell.h" +#import "chrome/browser/cocoa/styled_text_field_test_helper.h" +#import "chrome/browser/cocoa/cocoa_test_helper.h" +#include "testing/gtest/include/gtest/gtest.h" +#import "third_party/ocmock/OCMock/OCMock.h" + +namespace { + +// Width of the field so that we don't have to ask |field_| for it all +// the time. +static const CGFloat kWidth(300.0); + +class StyledTextFieldTest : public CocoaTest { + public: + StyledTextFieldTest() { + // Make sure this is wide enough to play games with the cell + // decorations. + NSRect frame = NSMakeRect(0, 0, kWidth, 30); + + scoped_nsobject<StyledTextFieldTestCell> cell( + [[StyledTextFieldTestCell alloc] initTextCell:@"Testing"]); + cell_ = cell.get(); + [cell_ setEditable:YES]; + [cell_ setBordered:YES]; + + scoped_nsobject<StyledTextField> field( + [[StyledTextField alloc] initWithFrame:frame]); + field_ = field.get(); + [field_ setCell:cell_]; + + [[test_window() contentView] addSubview:field_]; + } + + // Helper to return the field-editor frame being used w/in |field_|. + NSRect EditorFrame() { + EXPECT_TRUE([field_ currentEditor]); + EXPECT_EQ([[field_ subviews] count], 1U); + if ([[field_ subviews] count] > 0) { + return [[[field_ subviews] objectAtIndex:0] frame]; + } else { + // Return something which won't work so the caller can soldier + // on. + return NSZeroRect; + } + } + + StyledTextField* field_; + StyledTextFieldTestCell* cell_; +}; + +// Basic view tests (AddRemove, Display). +TEST_VIEW(StyledTextFieldTest, field_); + +// Test that we get the same cell from -cell and +// -styledTextFieldCell. +TEST_F(StyledTextFieldTest, Cell) { + StyledTextFieldCell* cell = [field_ styledTextFieldCell]; + EXPECT_EQ(cell, [field_ cell]); + EXPECT_TRUE(cell != nil); +} + +// Test that becoming first responder sets things up correctly. +TEST_F(StyledTextFieldTest, FirstResponder) { + EXPECT_EQ(nil, [field_ currentEditor]); + EXPECT_EQ([[field_ subviews] count], 0U); + [test_window() makePretendKeyWindowAndSetFirstResponder:field_]; + EXPECT_FALSE(nil == [field_ currentEditor]); + EXPECT_EQ([[field_ subviews] count], 1U); + EXPECT_TRUE([[field_ currentEditor] isDescendantOf:field_]); +} + +TEST_F(StyledTextFieldTest, AvailableDecorationWidth) { + // A fudge factor to account for how much space the border takes up. + // The test shouldn't be too dependent on the field's internals, but + // it also shouldn't let deranged cases fall through the cracks + // (like nothing available with no text, or everything available + // with some text). + const CGFloat kBorderWidth = 20.0; + + // With no contents, almost the entire width is available for + // decorations. + [field_ setStringValue:@""]; + CGFloat availableWidth = [field_ availableDecorationWidth]; + EXPECT_LE(availableWidth, kWidth); + EXPECT_GT(availableWidth, kWidth - kBorderWidth); + + // With minor contents, most of the remaining width is available for + // decorations. + NSDictionary* attributes = + [NSDictionary dictionaryWithObject:[field_ font] + forKey:NSFontAttributeName]; + NSString* string = @"Hello world"; + const NSSize size([string sizeWithAttributes:attributes]); + [field_ setStringValue:string]; + availableWidth = [field_ availableDecorationWidth]; + EXPECT_LE(availableWidth, kWidth - size.width); + EXPECT_GT(availableWidth, kWidth - size.width - kBorderWidth); + + // With huge contents, nothing at all is left for decorations. + string = @"A long string which is surely wider than field_ can hold."; + [field_ setStringValue:string]; + availableWidth = [field_ availableDecorationWidth]; + EXPECT_LT(availableWidth, 0.0); +} + +// Test drawing, mostly to ensure nothing leaks or crashes. +TEST_F(StyledTextFieldTest, Display) { + [field_ display]; + + // Test focused drawing. + [test_window() makePretendKeyWindowAndSetFirstResponder:field_]; + [field_ display]; +} + +// Test that the field editor gets the same bounds when focus is delivered by +// the standard focusing machinery, or by -resetFieldEditorFrameIfNeeded. +TEST_F(StyledTextFieldTest, ResetFieldEditorBase) { + // Capture the editor frame resulting from the standard focus machinery. + [test_window() makePretendKeyWindowAndSetFirstResponder:field_]; + const NSRect baseEditorFrame(EditorFrame()); + + // Setting a hint should result in a strictly smaller editor frame. + EXPECT_EQ(0, [cell_ leftMargin]); + EXPECT_EQ(0, [cell_ rightMargin]); + [cell_ setLeftMargin:10]; + [field_ resetFieldEditorFrameIfNeeded]; + EXPECT_FALSE(NSEqualRects(baseEditorFrame, EditorFrame())); + EXPECT_TRUE(NSContainsRect(baseEditorFrame, EditorFrame())); + + // Resetting the margin and using -resetFieldEditorFrameIfNeeded should result + // in the same frame as the standard focus machinery. + [cell_ setLeftMargin:0]; + [field_ resetFieldEditorFrameIfNeeded]; + EXPECT_TRUE(NSEqualRects(baseEditorFrame, EditorFrame())); +} + +// Test that the field editor gets the same bounds when focus is delivered by +// the standard focusing machinery, or by -resetFieldEditorFrameIfNeeded. +TEST_F(StyledTextFieldTest, ResetFieldEditorLeftMargin) { + const CGFloat kLeftMargin = 20; + + // Start the cell off with a non-zero left margin. + [cell_ setLeftMargin:kLeftMargin]; + [cell_ setRightMargin:0]; + + // Capture the editor frame resulting from the standard focus machinery. + [test_window() makePretendKeyWindowAndSetFirstResponder:field_]; + const NSRect baseEditorFrame(EditorFrame()); + + // Clearing the margin should result in a strictly larger editor frame. + [cell_ setLeftMargin:0]; + [field_ resetFieldEditorFrameIfNeeded]; + EXPECT_FALSE(NSEqualRects(baseEditorFrame, EditorFrame())); + EXPECT_TRUE(NSContainsRect(EditorFrame(), baseEditorFrame)); + + // Setting the same margin and using -resetFieldEditorFrameIfNeeded should + // result in the same frame as the standard focus machinery. + [cell_ setLeftMargin:kLeftMargin]; + [field_ resetFieldEditorFrameIfNeeded]; + EXPECT_TRUE(NSEqualRects(baseEditorFrame, EditorFrame())); +} + +// Test that the field editor gets the same bounds when focus is delivered by +// the standard focusing machinery, or by -resetFieldEditorFrameIfNeeded. +TEST_F(StyledTextFieldTest, ResetFieldEditorRightMargin) { + const CGFloat kRightMargin = 20; + + // Start the cell off with a non-zero right margin. + [cell_ setLeftMargin:0]; + [cell_ setRightMargin:kRightMargin]; + + // Capture the editor frame resulting from the standard focus machinery. + [test_window() makePretendKeyWindowAndSetFirstResponder:field_]; + const NSRect baseEditorFrame(EditorFrame()); + + // Clearing the margin should result in a strictly larger editor frame. + [cell_ setRightMargin:0]; + [field_ resetFieldEditorFrameIfNeeded]; + EXPECT_FALSE(NSEqualRects(baseEditorFrame, EditorFrame())); + EXPECT_TRUE(NSContainsRect(EditorFrame(), baseEditorFrame)); + + // Setting the same margin and using -resetFieldEditorFrameIfNeeded should + // result in the same frame as the standard focus machinery. + [cell_ setRightMargin:kRightMargin]; + [field_ resetFieldEditorFrameIfNeeded]; + EXPECT_TRUE(NSEqualRects(baseEditorFrame, EditorFrame())); +} + +} // namespace diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp index 9ac647f..43711d0 100755 --- a/chrome/chrome.gyp +++ b/chrome/chrome.gyp @@ -1143,6 +1143,10 @@ 'browser/cocoa/find_bar_bridge.mm', 'browser/cocoa/find_bar_cocoa_controller.h', 'browser/cocoa/find_bar_cocoa_controller.mm', + 'browser/cocoa/find_bar_text_field.h', + 'browser/cocoa/find_bar_text_field.mm', + 'browser/cocoa/find_bar_text_field_cell.h', + 'browser/cocoa/find_bar_text_field_cell.mm', 'browser/cocoa/find_bar_view.h', 'browser/cocoa/find_bar_view.mm', 'browser/cocoa/find_pasteboard.h', @@ -1212,6 +1216,10 @@ 'browser/cocoa/shell_dialogs_mac.mm', 'browser/cocoa/status_bubble_mac.h', 'browser/cocoa/status_bubble_mac.mm', + 'browser/cocoa/styled_text_field.h', + 'browser/cocoa/styled_text_field.mm', + 'browser/cocoa/styled_text_field_cell.h', + 'browser/cocoa/styled_text_field_cell.mm', 'browser/cocoa/tab_contents_controller.h', 'browser/cocoa/tab_contents_controller.mm', 'browser/cocoa/tab_controller.h', @@ -4532,6 +4540,8 @@ 'browser/cocoa/event_utils_unittest.mm', 'browser/cocoa/find_bar_bridge_unittest.mm', 'browser/cocoa/find_bar_cocoa_controller_unittest.mm', + 'browser/cocoa/find_bar_text_field_unittest.mm', + 'browser/cocoa/find_bar_text_field_cell_unittest.mm', 'browser/cocoa/find_bar_view_unittest.mm', 'browser/cocoa/find_pasteboard_unittest.mm', 'browser/cocoa/focus_tracker_unittest.mm', @@ -4559,6 +4569,10 @@ 'browser/cocoa/sad_tab_view_unittest.mm', 'browser/cocoa/search_engine_list_model_unittest.mm', 'browser/cocoa/status_bubble_mac_unittest.mm', + 'browser/cocoa/styled_text_field_test_helper.h', + 'browser/cocoa/styled_text_field_test_helper.mm', + 'browser/cocoa/styled_text_field_unittest.mm', + 'browser/cocoa/styled_text_field_cell_unittest.mm', 'browser/cocoa/tab_controller_unittest.mm', 'browser/cocoa/tab_strip_controller_unittest.mm', 'browser/cocoa/tab_strip_view_unittest.mm', |