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_MODEL_H_
6#define CHROME_BROWSER_AUTOCOMPLETE_AUTOCOMPLETE_POPUP_MODEL_H_
7#pragma once
8
9#include "base/memory/scoped_ptr.h"
10#include "chrome/browser/autocomplete/autocomplete.h"
11#include "chrome/browser/autocomplete/autocomplete_edit.h"
12
13class AutocompleteEditView;
14class AutocompletePopupView;
15class Profile;
16class SkBitmap;
17
18class AutocompletePopupModel {
19 public:
20  AutocompletePopupModel(AutocompletePopupView* popup_view,
21                         AutocompleteEditModel* edit_model,
22                         Profile* profile);
23  ~AutocompletePopupModel();
24
25  // Invoked when the profile has changed.
26  void set_profile(Profile* profile) { profile_ = profile; }
27
28  // TODO(sky): see about removing this.
29  Profile* profile() const { return profile_; }
30
31  // Returns true if the popup is currently open.
32  bool IsOpen() const;
33
34  AutocompletePopupView* view() const { return view_; }
35
36  // Returns the AutocompleteController used by this popup.
37  AutocompleteController* autocomplete_controller() const {
38    return edit_model_->autocomplete_controller();
39  }
40
41  const AutocompleteResult& result() const {
42    return autocomplete_controller()->result();
43  }
44
45  size_t hovered_line() const {
46    return hovered_line_;
47  }
48
49  // Call to change the hovered line.  |line| should be within the range of
50  // valid lines (to enable hover) or kNoMatch (to disable hover).
51  void SetHoveredLine(size_t line);
52
53  size_t selected_line() const {
54    return selected_line_;
55  }
56
57  // Call to change the selected line.  This will update all state and repaint
58  // the necessary parts of the window, as well as updating the edit with the
59  // new temporary text.  |line| will be clamped to the range of valid lines.
60  // |reset_to_default| is true when the selection is being reset back to the
61  // default match, and thus there is no temporary text (and no
62  // |manually_selected_match_|). If |force| is true then the selected line will
63  // be updated forcibly even if the |line| is same as the current selected
64  // line.
65  // NOTE: This assumes the popup is open, and thus both old and new values for
66  // the selected line should not be kNoMatch.
67  void SetSelectedLine(size_t line, bool reset_to_default, bool force);
68
69  // Called when the user hits escape after arrowing around the popup.  This
70  // will change the selected line back to the default match and redraw.
71  void ResetToDefaultMatch();
72
73  // Gets the selected keyword or keyword hint for the given match. If the match
74  // is already keyword, then the keyword will be returned directly. Otherwise,
75  // it returns GetKeywordForText(match.fill_into_edit, keyword).
76  bool GetKeywordForMatch(const AutocompleteMatch& match,
77                          string16* keyword) const;
78
79  // Gets the selected keyword or keyword hint for the given text. Returns
80  // true if |keyword| represents a keyword hint, or false if |keyword|
81  // represents a selected keyword. (|keyword| will always be set [though
82  // possibly to the empty string], and you cannot have both a selected keyword
83  // and a keyword hint simultaneously.)
84  bool GetKeywordForText(const string16& text, string16* keyword) const;
85
86  // Immediately updates and opens the popup if necessary, then moves the
87  // current selection down (|count| > 0) or up (|count| < 0), clamping to the
88  // first or last result if necessary.  If |count| == 0, the selection will be
89  // unchanged, but the popup will still redraw and modify the text in the
90  // AutocompleteEditModel.
91  void Move(int count);
92
93  // Called when the user hits shift-delete.  This should determine if the item
94  // can be removed from history, and if so, remove it and update the popup.
95  void TryDeletingCurrentItem();
96
97  // If |match| is from an extension, returns the extension icon; otherwise
98  // returns NULL.
99  const SkBitmap* GetIconIfExtensionMatch(const AutocompleteMatch& match) const;
100
101  // The match the user has manually chosen, if any.
102  const AutocompleteResult::Selection& manually_selected_match() const {
103    return manually_selected_match_;
104  }
105
106  // Invoked from the edit model any time the result set of the controller
107  // changes.
108  void OnResultChanged();
109
110  // The token value for selected_line_, hover_line_ and functions dealing with
111  // a "line number" that indicates "no line".
112  static const size_t kNoMatch = -1;
113
114 private:
115  AutocompletePopupView* view_;
116
117  AutocompleteEditModel* edit_model_;
118
119  // Profile for current tab.
120  Profile* profile_;
121
122  // The line that's currently hovered.  If we're not drawing a hover rect,
123  // this will be kNoMatch, even if the cursor is over the popup contents.
124  size_t hovered_line_;
125
126  // The currently selected line.  This is kNoMatch when nothing is selected,
127  // which should only be true when the popup is closed.
128  size_t selected_line_;
129
130  // The match the user has manually chosen, if any.
131  AutocompleteResult::Selection manually_selected_match_;
132
133  DISALLOW_COPY_AND_ASSIGN(AutocompletePopupModel);
134};
135
136#endif  // CHROME_BROWSER_AUTOCOMPLETE_AUTOCOMPLETE_POPUP_MODEL_H_
137