This source file includes following definitions.
- selected_line_state_
- ComputeMatchMaxWidths
- IsOpen
- SetHoveredLine
- SetSelectedLine
- ResetToDefaultMatch
- Move
- SetSelectedLineState
- TryDeletingCurrentItem
- GetIconIfExtensionMatch
- OnResultChanged
- AddObserver
- RemoveObserver
#include "chrome/browser/ui/omnibox/omnibox_popup_model.h"
#include <algorithm>
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/autocomplete/autocomplete_match.h"
#include "chrome/browser/extensions/api/omnibox/omnibox_api.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/search_engines/template_url.h"
#include "chrome/browser/search_engines/template_url_service.h"
#include "chrome/browser/search_engines/template_url_service_factory.h"
#include "chrome/browser/ui/omnibox/omnibox_popup_model_observer.h"
#include "chrome/browser/ui/omnibox/omnibox_popup_view.h"
#include "third_party/icu/source/common/unicode/ubidi.h"
#include "ui/gfx/image/image.h"
#include "ui/gfx/rect.h"
const size_t OmniboxPopupModel::kNoMatch = -1;
OmniboxPopupModel::OmniboxPopupModel(
OmniboxPopupView* popup_view,
OmniboxEditModel* edit_model)
: view_(popup_view),
edit_model_(edit_model),
hovered_line_(kNoMatch),
selected_line_(kNoMatch),
selected_line_state_(NORMAL) {
edit_model->set_popup_model(this);
}
OmniboxPopupModel::~OmniboxPopupModel() {
}
void OmniboxPopupModel::ComputeMatchMaxWidths(int contents_width,
int separator_width,
int description_width,
int available_width,
bool allow_shrinking_contents,
int* contents_max_width,
int* description_max_width) {
if (available_width <= 0) {
*contents_max_width = 0;
*description_max_width = 0;
return;
}
*contents_max_width = contents_width;
*description_max_width = description_width;
if (!description_width)
return;
available_width -= separator_width;
if (contents_width + description_width > available_width) {
if (allow_shrinking_contents) {
*contents_max_width = std::max(
(available_width + 1) / 2, available_width - description_width);
const int kMinimumContentsWidth = 300;
*contents_max_width = std::min(
std::max(*contents_max_width, kMinimumContentsWidth), contents_width);
}
*description_max_width = available_width - *contents_max_width;
const int kMinimumDescriptionWidth = 75;
if (*description_max_width <
std::min(description_width, kMinimumDescriptionWidth)) {
*description_max_width = 0;
*contents_max_width = contents_width;
}
}
}
bool OmniboxPopupModel::IsOpen() const {
return view_->IsOpen();
}
void OmniboxPopupModel::SetHoveredLine(size_t line) {
const bool is_disabling = (line == kNoMatch);
DCHECK(is_disabling || (line < result().size()));
if (line == hovered_line_)
return;
if ((hovered_line_ != kNoMatch) && (hovered_line_ != selected_line_))
view_->InvalidateLine(hovered_line_);
hovered_line_ = line;
if (!is_disabling && (hovered_line_ != selected_line_))
view_->InvalidateLine(hovered_line_);
}
void OmniboxPopupModel::SetSelectedLine(size_t line,
bool reset_to_default,
bool force) {
const AutocompleteResult& result = this->result();
if (result.empty())
return;
autocomplete_controller()->Stop(false);
line = std::min(line, result.size() - 1);
const AutocompleteMatch& match = result.match_at(line);
if (reset_to_default) {
manually_selected_match_.Clear();
} else {
manually_selected_match_.destination_url = match.destination_url;
manually_selected_match_.provider_affinity = match.provider;
manually_selected_match_.is_history_what_you_typed_match =
match.is_history_what_you_typed_match;
}
if (line == selected_line_ && !force)
return;
CHECK(selected_line_ != kNoMatch);
GURL current_destination(result.match_at(selected_line_).destination_url);
const size_t prev_selected_line = selected_line_;
selected_line_state_ = NORMAL;
selected_line_ = line;
view_->InvalidateLine(prev_selected_line);
view_->InvalidateLine(selected_line_);
base::string16 keyword;
bool is_keyword_hint;
match.GetKeywordUIState(edit_model_->profile(), &keyword, &is_keyword_hint);
if (reset_to_default) {
edit_model_->OnPopupDataChanged(match.inline_autocompletion, NULL,
keyword, is_keyword_hint);
} else {
edit_model_->OnPopupDataChanged(match.fill_into_edit, ¤t_destination,
keyword, is_keyword_hint);
}
view_->PaintUpdatesNow();
}
void OmniboxPopupModel::ResetToDefaultMatch() {
const AutocompleteResult& result = this->result();
CHECK(!result.empty());
SetSelectedLine(result.default_match() - result.begin(), true, false);
view_->OnDragCanceled();
}
void OmniboxPopupModel::Move(int count) {
const AutocompleteResult& result = this->result();
if (result.empty())
return;
SetHoveredLine(kNoMatch);
const size_t new_line = selected_line_ + count;
SetSelectedLine(((count < 0) && (new_line >= selected_line_)) ? 0 : new_line,
false, false);
}
void OmniboxPopupModel::SetSelectedLineState(LineState state) {
DCHECK(!result().empty());
DCHECK_NE(kNoMatch, selected_line_);
const AutocompleteMatch& match = result().match_at(selected_line_);
DCHECK(match.associated_keyword.get());
selected_line_state_ = state;
view_->InvalidateLine(selected_line_);
}
void OmniboxPopupModel::TryDeletingCurrentItem() {
if (selected_line_ == kNoMatch)
return;
autocomplete_controller()->Stop(false);
const AutocompleteMatch& match = result().match_at(selected_line_);
if (match.SupportsDeletion()) {
const size_t selected_line = selected_line_;
const bool was_temporary_text = !manually_selected_match_.empty();
autocomplete_controller()->DeleteMatch(match);
const AutocompleteResult& result = this->result();
if (!result.empty() &&
(was_temporary_text || selected_line != selected_line_)) {
SetSelectedLine(selected_line, false, true);
}
}
}
gfx::Image OmniboxPopupModel::GetIconIfExtensionMatch(
const AutocompleteMatch& match) const {
Profile* profile = edit_model_->profile();
const TemplateURL* template_url = match.GetTemplateURL(profile, false);
if (template_url &&
(template_url->GetType() == TemplateURL::OMNIBOX_API_EXTENSION)) {
return extensions::OmniboxAPI::Get(profile)->GetOmniboxPopupIcon(
template_url->GetExtensionId());
}
return gfx::Image();
}
void OmniboxPopupModel::OnResultChanged() {
const AutocompleteResult& result = this->result();
selected_line_ = result.default_match() == result.end() ?
kNoMatch : static_cast<size_t>(result.default_match() - result.begin());
CHECK((selected_line_ != kNoMatch) || result.empty());
manually_selected_match_.Clear();
selected_line_state_ = NORMAL;
if ((hovered_line_ != kNoMatch) && (result.size() <= hovered_line_))
SetHoveredLine(kNoMatch);
bool popup_was_open = view_->IsOpen();
view_->UpdatePopupAppearance();
if (view_->IsOpen() != popup_was_open) {
FOR_EACH_OBSERVER(OmniboxPopupModelObserver, observers_,
OnOmniboxPopupShownOrHidden());
}
}
void OmniboxPopupModel::AddObserver(OmniboxPopupModelObserver* observer) {
observers_.AddObserver(observer);
}
void OmniboxPopupModel::RemoveObserver(OmniboxPopupModelObserver* observer) {
observers_.RemoveObserver(observer);
}