blob: e2fcb0c4e7412f337d0fb708ee5829e27ba6b8b6 [file] [log] [blame]
[email protected]3cb0f8d92012-02-29 05:43:341// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]f387f1b2009-02-27 14:49:512// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
blundell7dbd3792015-08-05 15:14:195#ifndef COMPONENTS_OMNIBOX_BROWSER_OMNIBOX_POPUP_MODEL_H_
6#define COMPONENTS_OMNIBOX_BROWSER_OMNIBOX_POPUP_MODEL_H_
[email protected]f387f1b2009-02-27 14:49:517
avif57136c12015-12-25 23:27:458#include <stddef.h>
Dave Schuylerc7affc032018-04-26 20:43:379#include <map>
avif57136c12015-12-25 23:27:4510
avif57136c12015-12-25 23:27:4511#include "base/macros.h"
Tommy C. Li3b9185c742017-08-30 18:40:3212#include "base/memory/weak_ptr.h"
[email protected]55f39822013-07-10 02:32:1413#include "base/observer_list.h"
Tommy C. Li491455c2017-09-07 00:02:1414#include "build/build_config.h"
blundell2102f7c2015-07-09 10:00:5315#include "components/omnibox/browser/autocomplete_controller.h"
16#include "components/omnibox/browser/autocomplete_result.h"
blundell7dbd3792015-08-05 15:14:1917#include "components/omnibox/browser/omnibox_edit_model.h"
dschuylerf32bc3a2015-05-22 06:29:1618#include "third_party/skia/include/core/SkBitmap.h"
Tommy C. Li3b9185c742017-08-30 18:40:3219#include "ui/gfx/image/image.h"
[email protected]f387f1b2009-02-27 14:49:5120
[email protected]55f39822013-07-10 02:32:1421class OmniboxPopupModelObserver;
[email protected]b2544aa92012-06-21 04:20:0922class OmniboxPopupView;
Tommy C. Lia240bde2018-01-04 22:08:3523class GURL;
[email protected]e8476c992012-08-20 20:27:5924
25namespace gfx {
26class Image;
27}
[email protected]f387f1b2009-02-27 14:49:5128
[email protected]b2544aa92012-06-21 04:20:0929class OmniboxPopupModel {
[email protected]f387f1b2009-02-27 14:49:5130 public:
[email protected]3cb0f8d92012-02-29 05:43:3431 // See selected_line_state_ for details.
32 enum LineState {
33 NORMAL = 0,
Kevin Baileydbcdc352018-04-27 13:57:1434 KEYWORD,
35 TAB_SWITCH
[email protected]3cb0f8d92012-02-29 05:43:3436 };
37
[email protected]5af9bc82012-06-29 00:53:4838 OmniboxPopupModel(OmniboxPopupView* popup_view, OmniboxEditModel* edit_model);
Tommy C. Lic9c838d2018-06-01 00:02:5639 ~OmniboxPopupModel();
[email protected]f387f1b2009-02-27 14:49:5140
[email protected]5ef97902014-03-20 19:36:2441 // Computes the maximum width, in pixels, that can be allocated for the two
42 // parts of an autocomplete result, i.e. the contents and the description.
krb78c84b72016-03-15 14:50:3743 //
44 // When |description_on_separate_line| is true, the caller will be displaying
45 // two separate lines of text, so both contents and description can take up
46 // the full available width. Otherwise, the contents and description are
47 // assumed to be on the same line, with a separator between them.
48 //
49 // When |allow_shrinking_contents| is true, and the contents and description
50 // are together on a line without enough space for both, the code tries to
51 // divide the available space equally between the two, unless this would make
52 // one or both too narrow. Otherwise, the contents is given as much space as
53 // it wants and the description gets the remainder.
[email protected]5ef97902014-03-20 19:36:2454 static void ComputeMatchMaxWidths(int contents_width,
55 int separator_width,
56 int description_width,
57 int available_width,
krb78c84b72016-03-15 14:50:3758 bool description_on_separate_line,
[email protected]5ef97902014-03-20 19:36:2459 bool allow_shrinking_contents,
60 int* contents_max_width,
61 int* description_max_width);
62
Tommy C. Lic9c838d2018-06-01 00:02:5663 // Returns true if the popup is currently open.
64 bool IsOpen() const;
[email protected]f387f1b2009-02-27 14:49:5165
[email protected]b2544aa92012-06-21 04:20:0966 OmniboxPopupView* view() const { return view_; }
[email protected]6c4e66312010-08-09 15:18:1767
[email protected]f387f1b2009-02-27 14:49:5168 // Returns the AutocompleteController used by this popup.
69 AutocompleteController* autocomplete_controller() const {
[email protected]28b6e252011-02-16 16:31:2770 return edit_model_->autocomplete_controller();
[email protected]f387f1b2009-02-27 14:49:5171 }
72
73 const AutocompleteResult& result() const {
[email protected]28b6e252011-02-16 16:31:2774 return autocomplete_controller()->result();
[email protected]f387f1b2009-02-27 14:49:5175 }
76
[email protected]5af9bc82012-06-29 00:53:4877 size_t selected_line() const { return selected_line_; }
[email protected]f387f1b2009-02-27 14:49:5178
[email protected]5af9bc82012-06-29 00:53:4879 LineState selected_line_state() const { return selected_line_state_; }
[email protected]3cb0f8d92012-02-29 05:43:3480
[email protected]f387f1b2009-02-27 14:49:5181 // Call to change the selected line. This will update all state and repaint
82 // the necessary parts of the window, as well as updating the edit with the
[email protected]6181e4bd2010-08-09 23:22:4383 // new temporary text. |line| will be clamped to the range of valid lines.
[email protected]f387f1b2009-02-27 14:49:5184 // |reset_to_default| is true when the selection is being reset back to the
Kevin Baileya60106e2017-09-08 21:41:3685 // default match, and thus there is no temporary text (and not
86 // |has_selected_match_|). If |force| is true then the selected line will
[email protected]4fc461e2011-01-26 17:41:4887 // be updated forcibly even if the |line| is same as the current selected
88 // line.
[email protected]f387f1b2009-02-27 14:49:5189 // NOTE: This assumes the popup is open, and thus both old and new values for
90 // the selected line should not be kNoMatch.
[email protected]4fc461e2011-01-26 17:41:4891 void SetSelectedLine(size_t line, bool reset_to_default, bool force);
[email protected]f387f1b2009-02-27 14:49:5192
93 // Called when the user hits escape after arrowing around the popup. This
94 // will change the selected line back to the default match and redraw.
95 void ResetToDefaultMatch();
96
[email protected]f387f1b2009-02-27 14:49:5197 // Immediately updates and opens the popup if necessary, then moves the
98 // current selection down (|count| > 0) or up (|count| < 0), clamping to the
99 // first or last result if necessary. If |count| == 0, the selection will be
100 // unchanged, but the popup will still redraw and modify the text in the
[email protected]fbdc4232012-06-24 15:28:37101 // OmniboxEditModel.
[email protected]f387f1b2009-02-27 14:49:51102 void Move(int count);
103
[email protected]3cb0f8d92012-02-29 05:43:34104 // If the selected line has both a normal match and a keyword match, this can
pkasting19b75b72015-04-21 22:42:28105 // be used to choose which to select. This allows the user to toggle between
106 // normal and keyword mode with tab/shift-tab without rerunning autocomplete
107 // or disturbing other popup state, which in turn is an important part of
108 // supporting the use of tab to do both tab-to-search and
109 // tab-to-traverse-dropdown.
110 //
111 // It is an error to call this when the selected line does not have both
112 // matches (or there is no selection).
[email protected]3cb0f8d92012-02-29 05:43:34113 void SetSelectedLineState(LineState state);
114
[email protected]f387f1b2009-02-27 14:49:51115 // Called when the user hits shift-delete. This should determine if the item
116 // can be removed from history, and if so, remove it and update the popup.
117 void TryDeletingCurrentItem();
118
[email protected]7daef4642014-07-29 07:44:38119 // Returns true if the destination URL of the match is bookmarked.
120 bool IsStarredMatch(const AutocompleteMatch& match) const;
121
Kevin Baileya60106e2017-09-08 21:41:36122 // The user has manually selected a match.
123 bool has_selected_match() { return has_selected_match_; }
[email protected]e1fe3da2010-10-08 20:32:50124
[email protected]bb527642011-02-14 16:47:26125 // Invoked from the edit model any time the result set of the controller
126 // changes.
127 void OnResultChanged();
128
[email protected]55f39822013-07-10 02:32:14129 // Add and remove observers.
130 void AddObserver(OmniboxPopupModelObserver* observer);
131 void RemoveObserver(OmniboxPopupModelObserver* observer);
132
Dave Schuylerc7affc032018-04-26 20:43:37133 // Lookup the bitmap for |result_index|. Returns nullptr if not found.
134 const SkBitmap* RichSuggestionBitmapAt(int result_index) const;
dschuylerf32bc3a2015-05-22 06:29:16135 // Stores the image in a local data member and schedules a repaint.
Dave Schuylerc7affc032018-04-26 20:43:37136 void SetRichSuggestionBitmap(int result_index, const SkBitmap& bitmap);
dschuylerf32bc3a2015-05-22 06:29:16137
Tommy C. Li491455c2017-09-07 00:02:14138#if !defined(OS_ANDROID) && !defined(OS_IOS)
139 // Gets the icon for the match index.
140 gfx::Image GetMatchIcon(const AutocompleteMatch& match,
141 SkColor vector_icon_color);
142#endif
143
Kevin Baileydbcdc352018-04-27 13:57:14144 // Helper function to see if current selection has button and can accept
145 // the tab key.
146 bool SelectedLineHasTabMatch();
147
Justin Donnellyce9d1bf2017-08-10 16:24:55148 // The token value for selected_line_ and functions dealing with a "line
149 // number" that indicates "no line".
[email protected]3cb0f8d92012-02-29 05:43:34150 static const size_t kNoMatch;
[email protected]f387f1b2009-02-27 14:49:51151
152 private:
Tommy C. Li491455c2017-09-07 00:02:14153 void OnFaviconFetched(const GURL& page_url, const gfx::Image& icon);
Tommy C. Li3b9185c742017-08-30 18:40:32154
Dave Schuylerc7affc032018-04-26 20:43:37155 std::map<int, SkBitmap> rich_suggestion_bitmaps_;
dschuylerf32bc3a2015-05-22 06:29:16156
[email protected]b2544aa92012-06-21 04:20:09157 OmniboxPopupView* view_;
[email protected]f387f1b2009-02-27 14:49:51158
[email protected]fbdc4232012-06-24 15:28:37159 OmniboxEditModel* edit_model_;
[email protected]f387f1b2009-02-27 14:49:51160
[email protected]f387f1b2009-02-27 14:49:51161 // The currently selected line. This is kNoMatch when nothing is selected,
162 // which should only be true when the popup is closed.
163 size_t selected_line_;
164
[email protected]3cb0f8d92012-02-29 05:43:34165 // If the selected line has both a normal match and a keyword match, this
166 // determines whether the normal match (if NORMAL) or the keyword match
Kevin Baileydbcdc352018-04-27 13:57:14167 // (if KEYWORD) is selected. Likewise, if the selected line has a normal
168 // match and a tab switch match, this determines whether the tab switch match
169 // (if TAB_SWITCH) is selected.
[email protected]3cb0f8d92012-02-29 05:43:34170 LineState selected_line_state_;
171
Kevin Bailey367d5b82018-06-29 22:27:00172 // When a result changes, this informs of the URL in the previously selected
173 // suggestion whose tab switch button was focused, so that we may compare
174 // if equal.
175 GURL old_focused_url_;
176
Kevin Baileya60106e2017-09-08 21:41:36177 // The user has manually selected a match.
178 bool has_selected_match_;
[email protected]f387f1b2009-02-27 14:49:51179
[email protected]55f39822013-07-10 02:32:14180 // Observers.
brettwd195c952015-06-02 17:31:12181 base::ObserverList<OmniboxPopupModelObserver> observers_;
[email protected]55f39822013-07-10 02:32:14182
Tommy C. Li3b9185c742017-08-30 18:40:32183 base::WeakPtrFactory<OmniboxPopupModel> weak_factory_;
184
[email protected]b2544aa92012-06-21 04:20:09185 DISALLOW_COPY_AND_ASSIGN(OmniboxPopupModel);
[email protected]f387f1b2009-02-27 14:49:51186};
187
blundell7dbd3792015-08-05 15:14:19188#endif // COMPONENTS_OMNIBOX_BROWSER_OMNIBOX_POPUP_MODEL_H_