summaryrefslogtreecommitdiffstats
path: root/chrome/browser/views/edit_search_engine_dialog.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser/views/edit_search_engine_dialog.cc')
-rw-r--r--chrome/browser/views/edit_search_engine_dialog.cc261
1 files changed, 261 insertions, 0 deletions
diff --git a/chrome/browser/views/edit_search_engine_dialog.cc b/chrome/browser/views/edit_search_engine_dialog.cc
new file mode 100644
index 0000000..18d3c6f
--- /dev/null
+++ b/chrome/browser/views/edit_search_engine_dialog.cc
@@ -0,0 +1,261 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/views/edit_search_engine_dialog.h"
+
+#include "app/l10n_util.h"
+#include "app/resource_bundle.h"
+#include "base/string_util.h"
+#include "chrome/browser/search_engines/edit_search_engine_controller.h"
+#include "chrome/browser/search_engines/template_url.h"
+#include "googleurl/src/gurl.h"
+#include "grit/app_resources.h"
+#include "grit/generated_resources.h"
+#include "grit/theme_resources.h"
+#include "views/controls/label.h"
+#include "views/controls/image_view.h"
+#include "views/controls/table/table_view.h"
+#include "views/grid_layout.h"
+#include "views/standard_layout.h"
+#include "views/window/window.h"
+
+using views::GridLayout;
+using views::ImageView;
+using views::Textfield;
+
+
+namespace {
+// Converts a URL as understood by TemplateURL to one appropriate for display
+// to the user.
+std::wstring GetDisplayURL(const TemplateURL& turl) {
+ return turl.url() ? turl.url()->DisplayURL() : std::wstring();
+}
+} // namespace
+
+namespace browser {
+
+void EditSearchEngine(gfx::NativeWindow parent,
+ const TemplateURL* template_url,
+ EditSearchEngineControllerDelegate* delegate,
+ Profile* profile) {
+ EditSearchEngineDialog::Show(parent, template_url, delegate, profile);
+}
+
+} // namespace browser
+
+EditSearchEngineDialog::EditSearchEngineDialog(
+ const TemplateURL* template_url,
+ EditSearchEngineControllerDelegate* delegate,
+ Profile* profile)
+ : controller_(new EditSearchEngineController(template_url,
+ delegate,
+ profile)) {
+ Init();
+}
+
+// static
+void EditSearchEngineDialog::Show(gfx::NativeWindow parent,
+ const TemplateURL* template_url,
+ EditSearchEngineControllerDelegate* delegate,
+ Profile* profile) {
+ EditSearchEngineDialog* contents =
+ new EditSearchEngineDialog(template_url, delegate, profile);
+ // Window interprets an empty rectangle as needing to query the content for
+ // the size as well as centering relative to the parent.
+ views::Window::CreateChromeWindow(parent, gfx::Rect(), contents);
+ contents->window()->Show();
+ contents->GetDialogClientView()->UpdateDialogButtons();
+ contents->title_tf_->SelectAll();
+ contents->title_tf_->RequestFocus();
+}
+
+bool EditSearchEngineDialog::IsModal() const {
+ return true;
+}
+
+std::wstring EditSearchEngineDialog::GetWindowTitle() const {
+ return l10n_util::GetString(controller_->template_url() ?
+ IDS_SEARCH_ENGINES_EDITOR_EDIT_WINDOW_TITLE :
+ IDS_SEARCH_ENGINES_EDITOR_NEW_WINDOW_TITLE);
+}
+
+bool EditSearchEngineDialog::IsDialogButtonEnabled(
+ MessageBoxFlags::DialogButton button) const {
+ if (button == MessageBoxFlags::DIALOGBUTTON_OK) {
+ return (controller_->IsKeywordValid(keyword_tf_->text()) &&
+ controller_->IsTitleValid(title_tf_->text()) &&
+ controller_->IsURLValid(url_tf_->text()));
+ }
+ return true;
+}
+
+bool EditSearchEngineDialog::Cancel() {
+ controller_->CleanUpCancelledAdd();
+ return true;
+}
+
+bool EditSearchEngineDialog::Accept() {
+ controller_->AcceptAddOrEdit(keyword_tf_->text(), title_tf_->text(),
+ url_tf_->text());
+ return true;
+}
+
+views::View* EditSearchEngineDialog::GetContentsView() {
+ return this;
+}
+
+void EditSearchEngineDialog::ContentsChanged(Textfield* sender,
+ const std::wstring& new_contents) {
+ GetDialogClientView()->UpdateDialogButtons();
+ UpdateImageViews();
+}
+
+bool EditSearchEngineDialog::HandleKeystroke(
+ Textfield* sender,
+ const views::Textfield::Keystroke& key) {
+ return false;
+}
+
+void EditSearchEngineDialog::Init() {
+ // Create the views we'll need.
+ if (controller_->template_url()) {
+ title_tf_ =
+ CreateTextfield(controller_->template_url()->short_name(), false);
+ keyword_tf_ = CreateTextfield(controller_->template_url()->keyword(), true);
+ url_tf_ =
+ CreateTextfield(GetDisplayURL(*controller_->template_url()), false);
+ // We don't allow users to edit prepopulate URLs. This is done as
+ // occasionally we need to update the URL of prepopulated TemplateURLs.
+ url_tf_->SetReadOnly(controller_->template_url()->prepopulate_id() != 0);
+ } else {
+ title_tf_ = CreateTextfield(std::wstring(), false);
+ keyword_tf_ = CreateTextfield(std::wstring(), true);
+ url_tf_ = CreateTextfield(std::wstring(), false);
+ }
+ title_iv_ = new ImageView();
+ keyword_iv_ = new ImageView();
+ url_iv_ = new ImageView();
+
+ UpdateImageViews();
+
+ const int related_x = kRelatedControlHorizontalSpacing;
+ const int related_y = kRelatedControlVerticalSpacing;
+ const int unrelated_y = kUnrelatedControlVerticalSpacing;
+
+ // View and GridLayout take care of deleting GridLayout for us.
+ GridLayout* layout = CreatePanelGridLayout(this);
+ SetLayoutManager(layout);
+
+ // Define the structure of the layout.
+
+ // For the buttons.
+ views::ColumnSet* column_set = layout->AddColumnSet(0);
+ column_set->AddPaddingColumn(1, 0);
+ column_set->AddColumn(GridLayout::FILL, GridLayout::CENTER, 0,
+ GridLayout::USE_PREF, 0, 0);
+ column_set->AddPaddingColumn(0, related_x);
+ column_set->AddColumn(GridLayout::FILL, GridLayout::CENTER, 0,
+ GridLayout::USE_PREF, 0, 0);
+ column_set->LinkColumnSizes(1, 3, -1);
+
+ // For the Textfields.
+ column_set = layout->AddColumnSet(1);
+ column_set->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 0,
+ GridLayout::USE_PREF, 0, 0);
+ column_set->AddPaddingColumn(0, related_x);
+ column_set->AddColumn(GridLayout::FILL, GridLayout::CENTER, 1,
+ GridLayout::USE_PREF, 0, 0);
+ column_set->AddPaddingColumn(0, related_x);
+ column_set->AddColumn(GridLayout::CENTER, GridLayout::CENTER, 0,
+ GridLayout::USE_PREF, 0, 0);
+
+ // For the description.
+ column_set = layout->AddColumnSet(2);
+ column_set->AddColumn(GridLayout::FILL, GridLayout::CENTER, 0,
+ GridLayout::USE_PREF, 0, 0);
+
+ // Add the contents.
+ layout->StartRow(0, 1);
+ layout->AddView(CreateLabel(IDS_SEARCH_ENGINES_EDITOR_DESCRIPTION_LABEL));
+ layout->AddView(title_tf_);
+ layout->AddView(title_iv_);
+
+ layout->StartRowWithPadding(0, 1, 0, related_y);
+ layout->AddView(CreateLabel(IDS_SEARCH_ENGINES_EDITOR_KEYWORD_LABEL));
+ layout->AddView(keyword_tf_);
+ layout->AddView(keyword_iv_);
+
+ layout->StartRowWithPadding(0, 1, 0, related_y);
+ layout->AddView(CreateLabel(IDS_SEARCH_ENGINES_EDITOR_URL_LABEL));
+ layout->AddView(url_tf_);
+ layout->AddView(url_iv_);
+
+ // On RTL UIs (such as Arabic and Hebrew) the description text is not
+ // displayed correctly since it contains the substring "%s". This substring
+ // is not interpreted by the Unicode BiDi algorithm as an LTR string and
+ // therefore the end result is that the following right to left text is
+ // displayed: ".three two s% one" (where 'one', 'two', etc. are words in
+ // Hebrew).
+ //
+ // In order to fix this problem we transform the substring "%s" so that it
+ // is displayed correctly when rendered in an RTL context.
+ layout->StartRowWithPadding(0, 2, 0, unrelated_y);
+ std::wstring description =
+ l10n_util::GetString(IDS_SEARCH_ENGINES_EDITOR_URL_DESCRIPTION_LABEL);
+ if (l10n_util::GetTextDirection() == l10n_util::RIGHT_TO_LEFT) {
+ const std::wstring reversed_percent(L"s%");
+ std::wstring::size_type percent_index =
+ description.find(L"%s", static_cast<std::wstring::size_type>(0));
+ if (percent_index != std::wstring::npos)
+ description.replace(percent_index,
+ reversed_percent.length(),
+ reversed_percent);
+ }
+
+ views::Label* description_label = new views::Label(description);
+ description_label->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
+ layout->AddView(description_label);
+
+ layout->AddPaddingRow(0, related_y);
+}
+
+views::Label* EditSearchEngineDialog::CreateLabel(int message_id) {
+ views::Label* label = new views::Label(l10n_util::GetString(message_id));
+ label->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
+ return label;
+}
+
+Textfield* EditSearchEngineDialog::CreateTextfield(const std::wstring& text,
+ bool lowercase) {
+ Textfield* text_field = new Textfield(
+ lowercase ? Textfield::STYLE_LOWERCASE : Textfield::STYLE_DEFAULT);
+ text_field->SetText(text);
+ text_field->SetController(this);
+ return text_field;
+}
+
+void EditSearchEngineDialog::UpdateImageViews() {
+ UpdateImageView(keyword_iv_, controller_->IsKeywordValid(keyword_tf_->text()),
+ IDS_SEARCH_ENGINES_INVALID_KEYWORD_TT);
+ UpdateImageView(url_iv_, controller_->IsURLValid(url_tf_->text()),
+ IDS_SEARCH_ENGINES_INVALID_URL_TT);
+ UpdateImageView(title_iv_, controller_->IsTitleValid(title_tf_->text()),
+ IDS_SEARCH_ENGINES_INVALID_TITLE_TT);
+}
+
+void EditSearchEngineDialog::UpdateImageView(ImageView* image_view,
+ bool is_valid,
+ int invalid_message_id) {
+ if (is_valid) {
+ image_view->SetTooltipText(std::wstring());
+ image_view->SetImage(
+ ResourceBundle::GetSharedInstance().GetBitmapNamed(
+ IDR_INPUT_GOOD));
+ } else {
+ image_view->SetTooltipText(l10n_util::GetString(invalid_message_id));
+ image_view->SetImage(
+ ResourceBundle::GetSharedInstance().GetBitmapNamed(
+ IDR_INPUT_ALERT));
+ }
+}