1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef CHROME_BROWSER_AUTOCOMPLETE_AUTOCOMPLETE_POPUP_VIEW_MAC_H_ 6 #define CHROME_BROWSER_AUTOCOMPLETE_AUTOCOMPLETE_POPUP_VIEW_MAC_H_ 7 #pragma once 8 9 #import <Cocoa/Cocoa.h> 10 11 #include <string> 12 13 #include "base/basictypes.h" 14 #include "base/memory/scoped_nsobject.h" 15 #include "base/memory/scoped_ptr.h" 16 #include "chrome/browser/autocomplete/autocomplete.h" 17 #include "chrome/browser/autocomplete/autocomplete_match.h" 18 #include "chrome/browser/autocomplete/autocomplete_popup_view.h" 19 #import "chrome/browser/ui/cocoa/location_bar/instant_opt_in_controller.h" 20 #include "ui/gfx/font.h" 21 #include "webkit/glue/window_open_disposition.h" 22 23 24 class AutocompleteEditModel; 25 class AutocompleteEditViewMac; 26 @class AutocompleteMatrix; 27 class AutocompletePopupModel; 28 @class InstantOptInController; 29 @class NSImage; 30 class Profile; 31 32 // Implements AutocompletePopupView using a raw NSWindow containing an 33 // NSTableView. 34 // 35 // TODO(rohitrao): This class is set up in a way that makes testing hard. 36 // Refactor and write unittests. http://crbug.com/9977 37 38 class AutocompletePopupViewMac : public AutocompletePopupView, 39 public InstantOptInControllerDelegate { 40 public: 41 AutocompletePopupViewMac(AutocompleteEditViewMac* edit_view, 42 AutocompleteEditModel* edit_model, 43 Profile* profile, 44 NSTextField* field); 45 virtual ~AutocompletePopupViewMac(); 46 47 // Implement the InstantOptInControllerDelegate interface. 48 virtual void UserPressedOptIn(bool opt_in); 49 50 // Implement the AutocompletePopupView interface. 51 virtual bool IsOpen() const; InvalidateLine(size_t line)52 virtual void InvalidateLine(size_t line) { 53 // TODO(shess): Verify that there is no need to implement this. 54 // This is currently used in two places in the model: 55 // 56 // When setting the selected line, the selected line is 57 // invalidated, then the selected line is changed, then the new 58 // selected line is invalidated, then PaintUpdatesNow() is called. 59 // For us PaintUpdatesNow() should be sufficient. 60 // 61 // Same thing happens when changing the hovered line, except with 62 // no call to PaintUpdatesNow(). Since this code does not 63 // currently support special display of the hovered line, there's 64 // nothing to do here. 65 // 66 // deanm indicates that this is an anti-flicker optimization, 67 // which we probably cannot utilize (and may not need) so long as 68 // we're using NSTableView to implement the popup contents. We 69 // may need to move away from NSTableView to implement hover, 70 // though. 71 } 72 virtual void UpdatePopupAppearance(); 73 74 virtual gfx::Rect GetTargetBounds(); 75 76 // Set |line| to be selected. 77 void SetSelectedLine(size_t line); 78 79 // This is only called by model in SetSelectedLine() after updating 80 // everything. Popup should already be visible. 81 virtual void PaintUpdatesNow(); 82 OnDragCanceled()83 virtual void OnDragCanceled() {} 84 85 // Opens the URL corresponding to the given |row|. If |force_background| is 86 // true, forces the URL to open in a background tab. Otherwise, determines 87 // the proper window open disposition from the modifier flags on |[NSApp 88 // currentEvent]|. 89 void OpenURLForRow(int row, bool force_background); 90 91 // Return the text to show for the match, based on the match's 92 // contents and description. Result will be in |font|, with the 93 // boldfaced version used for matches. 94 static NSAttributedString* MatchText(const AutocompleteMatch& match, 95 gfx::Font& font, 96 float cellWidth); 97 98 // Helper for MatchText() to allow sharing code between the contents 99 // and description cases. Returns NSMutableAttributedString as a 100 // convenience for MatchText(). 101 static NSMutableAttributedString* DecorateMatchedString( 102 const string16 &matchString, 103 const AutocompleteMatch::ACMatchClassifications &classifications, 104 NSColor* textColor, NSColor* dimTextColor, gfx::Font& font); 105 106 // Helper for MatchText() to elide a marked-up string using 107 // gfx::ElideText() as a model. Modifies |aString| in place. 108 // TODO(shess): Consider breaking AutocompleteButtonCell out of this 109 // code, and modifying it to have something like -setMatch:, so that 110 // these convolutions to expose internals for testing can be 111 // cleaner. 112 static NSMutableAttributedString* ElideString( 113 NSMutableAttributedString* aString, 114 const string16 originalString, 115 const gfx::Font& font, 116 const float cellWidth); 117 118 private: 119 // Returns the AutocompleteMatrix for this popup view. 120 AutocompleteMatrix* GetAutocompleteMatrix(); 121 122 // Create the popup_ instance if needed. 123 void CreatePopupIfNeeded(); 124 125 // Calculate the appropriate position for the popup based on the 126 // field's screen position and the given target for the matrix 127 // height, and makes the popup visible. Animates to the new frame 128 // if the popup shrinks, snaps to the new frame if the popup grows, 129 // allows existing animations to continue if the size doesn't 130 // change. 131 void PositionPopup(const CGFloat matrixHeight); 132 133 // Returns the NSImage that should be used as an icon for the given match. 134 NSImage* ImageForMatch(const AutocompleteMatch& match); 135 136 // Returns whether or not to show the instant opt-in prompt. 137 bool ShouldShowInstantOptIn(); 138 139 scoped_ptr<AutocompletePopupModel> model_; 140 AutocompleteEditViewMac* edit_view_; 141 NSTextField* field_; // owned by tab controller 142 143 // Child window containing a matrix which implements the popup. 144 scoped_nsobject<NSWindow> popup_; 145 scoped_nsobject<InstantOptInController> opt_in_controller_; 146 NSRect targetPopupFrame_; 147 148 DISALLOW_COPY_AND_ASSIGN(AutocompletePopupViewMac); 149 }; 150 151 #endif // CHROME_BROWSER_AUTOCOMPLETE_AUTOCOMPLETE_POPUP_VIEW_MAC_H_ 152