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
24class AutocompleteEditModel;
25class AutocompleteEditViewMac;
26@class AutocompleteMatrix;
27class AutocompletePopupModel;
28@class InstantOptInController;
29@class NSImage;
30class 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
38class 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;
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
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