summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormattm@chromium.org <mattm@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-06-18 18:49:37 +0000
committermattm@chromium.org <mattm@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-06-18 18:49:37 +0000
commit989246dcb5a9b679a1260baf3a4364ec5cead962 (patch)
tree4030c5b3a8faa922213644242d0a61332803278b
parentf9fc018f52b80dff2bb0193f76cfa640a688ded5 (diff)
downloadchromium_src-989246dcb5a9b679a1260baf3a4364ec5cead962.zip
chromium_src-989246dcb5a9b679a1260baf3a4364ec5cead962.tar.gz
chromium_src-989246dcb5a9b679a1260baf3a4364ec5cead962.tar.bz2
Add gtk EditKeywordController.
BUG=13326 Review URL: http://codereview.chromium.org/126305 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@18727 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/gtk/edit_keyword_controller.cc233
-rw-r--r--chrome/browser/gtk/edit_keyword_controller.h73
-rw-r--r--chrome/browser/search_engines/edit_keyword_controller_base.h8
-rw-r--r--chrome/browser/search_engines/template_url_fetcher.cc20
-rw-r--r--chrome/browser/views/edit_keyword_controller.cc10
-rw-r--r--chrome/chrome.gyp2
-rw-r--r--chrome/common/temp_scaffolding_stubs.cc8
7 files changed, 339 insertions, 15 deletions
diff --git a/chrome/browser/gtk/edit_keyword_controller.cc b/chrome/browser/gtk/edit_keyword_controller.cc
new file mode 100644
index 0000000..9cc6f0d
--- /dev/null
+++ b/chrome/browser/gtk/edit_keyword_controller.cc
@@ -0,0 +1,233 @@
+// 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/gtk/edit_keyword_controller.h"
+
+#include <gtk/gtk.h>
+
+#include "app/l10n_util.h"
+#include "app/resource_bundle.h"
+#include "base/string_util.h"
+#include "chrome/browser/net/url_fixer_upper.h"
+#include "chrome/browser/profile.h"
+#include "chrome/browser/search_engines/template_url.h"
+#include "chrome/browser/search_engines/template_url_model.h"
+#include "chrome/common/gtk_util.h"
+#include "googleurl/src/gurl.h"
+#include "grit/app_resources.h"
+#include "grit/generated_resources.h"
+#include "grit/theme_resources.h"
+
+namespace {
+
+std::string GetDisplayURL(const TemplateURL& turl) {
+ return turl.url() ? WideToUTF8(turl.url()->DisplayURL()) : std::string();
+}
+
+GtkWidget* CreateEntryImageHBox(GtkWidget* entry, GtkWidget* image) {
+ GtkWidget* hbox = gtk_hbox_new(FALSE, gtk_util::kControlSpacing);
+ gtk_box_pack_start(GTK_BOX(hbox), entry, TRUE, TRUE, 0);
+ gtk_box_pack_start(GTK_BOX(hbox), image, FALSE, FALSE, 0);
+ return hbox;
+}
+
+} // namespace
+
+// static
+void EditKeywordControllerBase::Create(gfx::NativeWindow parent_window,
+ const TemplateURL* template_url,
+ Delegate* delegate,
+ Profile* profile) {
+ new EditKeywordController(parent_window, template_url, delegate, profile);
+}
+
+EditKeywordController::EditKeywordController(
+ GtkWindow* parent_window,
+ const TemplateURL* template_url,
+ Delegate* delegate,
+ Profile* profile)
+ : EditKeywordControllerBase(template_url, delegate, profile) {
+ Init(parent_window);
+}
+
+void EditKeywordController::Init(GtkWindow* parent_window) {
+ dialog_ = gtk_dialog_new_with_buttons(
+ l10n_util::GetStringUTF8(
+ template_url() ?
+ IDS_SEARCH_ENGINES_EDITOR_EDIT_WINDOW_TITLE :
+ IDS_SEARCH_ENGINES_EDITOR_NEW_WINDOW_TITLE).c_str(),
+ // In views, this is window-modal. GTK only does app-modal which is
+ // overkill, so we'll just settle for being a non-modal transient.
+ parent_window,
+ GTK_DIALOG_NO_SEPARATOR,
+ GTK_STOCK_CANCEL,
+ GTK_RESPONSE_CANCEL,
+ NULL);
+
+ ok_button_ = gtk_dialog_add_button(GTK_DIALOG(dialog_),
+ GTK_STOCK_OK, GTK_RESPONSE_OK);
+ gtk_dialog_set_default_response(GTK_DIALOG(dialog_), GTK_RESPONSE_OK);
+
+ // The dialog layout hierarchy looks like this:
+ //
+ // \ GtkVBox |dialog_->vbox|
+ // +-\ GtkTable |controls|
+ // | +-\ row 0
+ // | | +- GtkLabel
+ // | | +-\ GtkHBox
+ // | | +- GtkEntry |title_entry_|
+ // | | +- GtkImage |title_image_|
+ // | +-\ row 1
+ // | | +- GtkLabel
+ // | | +-\ GtkHBox
+ // | | +- GtkEntry |keyword_entry_|
+ // | | +- GtkImage |keyword_image_|
+ // | +-\ row 2
+ // | +- GtkLabel
+ // | +-\ GtkHBox
+ // | +- GtkEntry |url_entry_|
+ // | +- GtkImage |url_image_|
+ // +- GtkLabel |description_label|
+
+ title_entry_ = gtk_entry_new();
+ gtk_entry_set_activates_default(GTK_ENTRY(title_entry_), TRUE);
+ g_signal_connect(G_OBJECT(title_entry_), "changed",
+ G_CALLBACK(OnEntryChanged), this);
+
+ keyword_entry_ = gtk_entry_new();
+ gtk_entry_set_activates_default(GTK_ENTRY(keyword_entry_), TRUE);
+ g_signal_connect(G_OBJECT(keyword_entry_), "changed",
+ G_CALLBACK(OnEntryChanged), this);
+ // TODO(mattm): will add in subsequent CL.
+ //g_signal_connect(G_OBJECT(keyword_entry_), "insert-text",
+ // G_CALLBACK(LowercaseInsertTextHandler), NULL);
+
+ url_entry_ = gtk_entry_new();
+ gtk_entry_set_activates_default(GTK_ENTRY(url_entry_), TRUE);
+ g_signal_connect(G_OBJECT(url_entry_), "changed",
+ G_CALLBACK(OnEntryChanged), this);
+
+ title_image_ = gtk_image_new_from_pixbuf(NULL);
+ keyword_image_ = gtk_image_new_from_pixbuf(NULL);
+ url_image_ = gtk_image_new_from_pixbuf(NULL);
+
+ if (template_url()) {
+ gtk_entry_set_text(GTK_ENTRY(title_entry_),
+ WideToUTF8(template_url()->short_name()).c_str());
+ gtk_entry_set_text(GTK_ENTRY(keyword_entry_),
+ WideToUTF8(template_url()->keyword()).c_str());
+ gtk_entry_set_text(GTK_ENTRY(url_entry_),
+ GetDisplayURL(*template_url()).c_str());
+ // We don't allow users to edit prepopulated URLs.
+ gtk_editable_set_editable(GTK_EDITABLE(url_entry_),
+ template_url()->prepopulate_id() == 0);
+ }
+
+ GtkWidget* controls = gtk_util::CreateLabeledControlsGroup(
+ l10n_util::GetStringUTF8(
+ IDS_SEARCH_ENGINES_EDITOR_DESCRIPTION_LABEL).c_str(),
+ CreateEntryImageHBox(title_entry_, title_image_),
+ l10n_util::GetStringUTF8(IDS_SEARCH_ENGINES_EDITOR_KEYWORD_LABEL).c_str(),
+ CreateEntryImageHBox(keyword_entry_, keyword_image_),
+ l10n_util::GetStringUTF8(IDS_SEARCH_ENGINES_EDITOR_URL_LABEL).c_str(),
+ CreateEntryImageHBox(url_entry_, url_image_),
+ NULL);
+ gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog_)->vbox), controls,
+ FALSE, FALSE, 0);
+
+ // 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.
+ std::string description =
+ l10n_util::GetStringUTF8(IDS_SEARCH_ENGINES_EDITOR_URL_DESCRIPTION_LABEL);
+ if (l10n_util::GetTextDirection() == l10n_util::RIGHT_TO_LEFT) {
+ const std::string reversed_percent("s%");
+ std::wstring::size_type percent_index =
+ description.find("%s", static_cast<std::string::size_type>(0));
+ if (percent_index != std::string::npos)
+ description.replace(percent_index,
+ reversed_percent.length(),
+ reversed_percent);
+ }
+
+ GtkWidget* description_label = gtk_label_new(description.c_str());
+ gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog_)->vbox), description_label,
+ FALSE, FALSE, 0);
+
+ gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(dialog_)->vbox),
+ gtk_util::kContentAreaSpacing);
+
+ gtk_widget_show_all(dialog_);
+
+ g_signal_connect(dialog_, "response", G_CALLBACK(OnResponse), this);
+ g_signal_connect(dialog_, "destroy", G_CALLBACK(OnWindowDestroy), this);
+}
+
+std::wstring EditKeywordController::GetURLInput() const {
+ return UTF8ToWide(gtk_entry_get_text(GTK_ENTRY(url_entry_)));
+}
+
+std::wstring EditKeywordController::GetKeywordInput() const {
+ return UTF8ToWide(gtk_entry_get_text(GTK_ENTRY(keyword_entry_)));
+}
+
+std::wstring EditKeywordController::GetTitleInput() const {
+ return UTF8ToWide(gtk_entry_get_text(GTK_ENTRY(title_entry_)));
+}
+
+void EditKeywordController::EnableControls() {
+ gtk_widget_set_sensitive(ok_button_,
+ IsKeywordValid() && IsTitleValid() && IsURLValid());
+ UpdateImage(keyword_image_, IsKeywordValid(),
+ IDS_SEARCH_ENGINES_INVALID_KEYWORD_TT);
+ UpdateImage(url_image_, IsURLValid(), IDS_SEARCH_ENGINES_INVALID_URL_TT);
+ UpdateImage(title_image_, IsTitleValid(),
+ IDS_SEARCH_ENGINES_INVALID_TITLE_TT);
+}
+
+void EditKeywordController::UpdateImage(GtkWidget* image,
+ bool is_valid,
+ int invalid_message_id) {
+ if (is_valid) {
+ gtk_widget_set_has_tooltip(image, FALSE);
+ gtk_image_set_from_pixbuf(GTK_IMAGE(image),
+ ResourceBundle::GetSharedInstance().GetPixbufNamed(
+ IDR_INPUT_GOOD));
+ } else {
+ gtk_widget_set_tooltip_text(
+ image, l10n_util::GetStringUTF8(invalid_message_id).c_str());
+ gtk_image_set_from_pixbuf(GTK_IMAGE(image),
+ ResourceBundle::GetSharedInstance().GetPixbufNamed(
+ IDR_INPUT_ALERT));
+ }
+}
+
+// static
+void EditKeywordController::OnEntryChanged(
+ GtkEditable* editable, EditKeywordController* window) {
+ window->EnableControls();
+}
+
+// static
+void EditKeywordController::OnResponse(GtkDialog* dialog, int response_id,
+ EditKeywordController* window) {
+ if (response_id == GTK_RESPONSE_OK) {
+ window->AcceptAddOrEdit();
+ } else {
+ window->CleanUpCancelledAdd();
+ }
+ gtk_widget_destroy(window->dialog_);
+}
+
+// static
+void EditKeywordController::OnWindowDestroy(
+ GtkWidget* widget, EditKeywordController* window) {
+ MessageLoop::current()->DeleteSoon(FROM_HERE, window);
+}
diff --git a/chrome/browser/gtk/edit_keyword_controller.h b/chrome/browser/gtk/edit_keyword_controller.h
new file mode 100644
index 0000000..86dc525
--- /dev/null
+++ b/chrome/browser/gtk/edit_keyword_controller.h
@@ -0,0 +1,73 @@
+// 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.
+
+#ifndef CHROME_BROWSER_GTK_EDIT_KEYWORD_CONTROLLER_H_
+#define CHROME_BROWSER_GTK_EDIT_KEYWORD_CONTROLLER_H_
+
+#include <gtk/gtk.h>
+
+#include "base/basictypes.h"
+#include "chrome/browser/search_engines/edit_keyword_controller_base.h"
+
+class Profile;
+class TemplateURL;
+
+class EditKeywordController : public EditKeywordControllerBase {
+ public:
+ EditKeywordController(GtkWindow* parent_window,
+ const TemplateURL* template_url,
+ Delegate* delegate,
+ Profile* profile);
+
+ protected:
+ // EditKeywordControllerBase overrides
+ virtual std::wstring GetURLInput() const;
+ virtual std::wstring GetKeywordInput() const;
+ virtual std::wstring GetTitleInput() const;
+
+ private:
+ // Create and show the window.
+ void Init(GtkWindow* parent_window);
+
+ // Set sensitivity of buttons based on entry state.
+ void EnableControls();
+
+ // Updates the tooltip and image of the image view based on is_valid. If
+ // is_valid is false the tooltip of the image view is set to the message with
+ // id invalid_message_id, otherwise the tooltip is set to the empty text.
+ void UpdateImage(GtkWidget* image, bool is_valid, int invalid_message_id);
+
+ // Callback for entry changes.
+ static void OnEntryChanged(GtkEditable* editable,
+ EditKeywordController* window);
+
+ // Callback for dialog buttons.
+ static void OnResponse(GtkDialog* dialog, int response_id,
+ EditKeywordController* window);
+
+ // Callback for window destruction.
+ static void OnWindowDestroy(GtkWidget* widget,
+ EditKeywordController* window);
+
+ // The dialog window.
+ GtkWidget* dialog_;
+
+ // Text entries for each field.
+ GtkWidget* title_entry_;
+ GtkWidget* keyword_entry_;
+ GtkWidget* url_entry_;
+
+ // Images showing whether each entry is okay or has errors.
+ GtkWidget* title_image_;
+ GtkWidget* keyword_image_;
+ GtkWidget* url_image_;
+
+ // The ok button (we need a reference to it so we can de-activate it when the
+ // entries are not all filled in.)
+ GtkWidget* ok_button_;
+
+ DISALLOW_COPY_AND_ASSIGN(EditKeywordController);
+};
+
+#endif // CHROME_BROWSER_GTK_EDIT_KEYWORD_CONTROLLER_GTK_H_
diff --git a/chrome/browser/search_engines/edit_keyword_controller_base.h b/chrome/browser/search_engines/edit_keyword_controller_base.h
index 11b3080..d01f6e9 100644
--- a/chrome/browser/search_engines/edit_keyword_controller_base.h
+++ b/chrome/browser/search_engines/edit_keyword_controller_base.h
@@ -7,6 +7,8 @@
#include <string>
+#include "base/gfx/native_widget_types.h"
+
class Profile;
class TemplateURL;
@@ -28,6 +30,12 @@ class EditKeywordControllerBase {
const std::wstring& url) = 0;
};
+ // Create and show the platform's implementation of the dialog.
+ static void Create(gfx::NativeWindow parent_window,
+ const TemplateURL* template_url,
+ Delegate* delegate,
+ Profile* profile);
+
// The |template_url| and/or |edit_keyword_delegate| may be NULL.
EditKeywordControllerBase(const TemplateURL* template_url,
Delegate* edit_keyword_delegate,
diff --git a/chrome/browser/search_engines/template_url_fetcher.cc b/chrome/browser/search_engines/template_url_fetcher.cc
index eca8fd0..164a70e 100644
--- a/chrome/browser/search_engines/template_url_fetcher.cc
+++ b/chrome/browser/search_engines/template_url_fetcher.cc
@@ -8,14 +8,11 @@
#include "chrome/browser/net/url_fetcher.h"
#include "chrome/browser/profile.h"
+#include "chrome/browser/search_engines/edit_keyword_controller_base.h"
#include "chrome/browser/search_engines/template_url.h"
#include "chrome/browser/search_engines/template_url_model.h"
#include "chrome/browser/search_engines/template_url_parser.h"
-#if defined(OS_WIN)
-#include "chrome/browser/views/edit_keyword_controller.h"
-#endif
-
// RequestDelegate ------------------------------------------------------------
class TemplateURLFetcher::RequestDelegate : public URLFetcher::Delegate {
public:
@@ -122,22 +119,15 @@ void TemplateURLFetcher::RequestDelegate::OnURLFetchComplete(
template_url->set_safe_for_autoreplace(true);
model->Add(template_url.release());
} else {
-#if defined(OS_WIN)
// Confirm addition and allow user to edit default choices. It's ironic
// that only *non*-autodetected additions get confirmed, but the user
// expects feedback that his action did something.
// The edit controller will take care of adding the URL to the model,
// which takes ownership, or of deleting it if the add is cancelled.
- EditKeywordController* controller =
- new EditKeywordController(parent_window_,
- template_url.release(),
- NULL, // no KeywordEditorView
- fetcher_->profile());
- controller->Show();
-#else
- // TODO(port): port EditKeywordController.
- NOTIMPLEMENTED() << "EditKeywordController.";
-#endif
+ EditKeywordControllerBase::Create(parent_window_,
+ template_url.release(),
+ NULL, // no KeywordEditorView
+ fetcher_->profile());
}
}
fetcher_->RequestCompleted(this);
diff --git a/chrome/browser/views/edit_keyword_controller.cc b/chrome/browser/views/edit_keyword_controller.cc
index f37dddf..7258b2d 100644
--- a/chrome/browser/views/edit_keyword_controller.cc
+++ b/chrome/browser/views/edit_keyword_controller.cc
@@ -32,6 +32,16 @@ std::wstring GetDisplayURL(const TemplateURL& turl) {
}
} // namespace
+// static
+void EditKeywordControllerBase::Create(gfx::NativeWindow parent_window,
+ const TemplateURL* template_url,
+ Delegate* delegate,
+ Profile* profile) {
+ EditKeywordController* controller =
+ new EditKeywordController(parent_window, template_url, delegate, profile);
+ controller->Show();
+}
+
EditKeywordController::EditKeywordController(
HWND parent,
const TemplateURL* template_url,
diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp
index b0e0cd4..ad0d097 100644
--- a/chrome/chrome.gyp
+++ b/chrome/chrome.gyp
@@ -961,6 +961,8 @@
'browser/gtk/download_shelf_gtk.cc',
'browser/gtk/download_shelf_gtk.h',
'browser/gtk/download_started_animation_gtk.cc',
+ 'browser/gtk/edit_keyword_controller.cc',
+ 'browser/gtk/edit_keyword_controller.h',
'browser/gtk/go_button_gtk.cc',
'browser/gtk/go_button_gtk.h',
'browser/gtk/gtk_chrome_button.cc',
diff --git a/chrome/common/temp_scaffolding_stubs.cc b/chrome/common/temp_scaffolding_stubs.cc
index 9447f74..74f5d4d 100644
--- a/chrome/common/temp_scaffolding_stubs.cc
+++ b/chrome/common/temp_scaffolding_stubs.cc
@@ -18,6 +18,7 @@
#include "chrome/browser/memory_details.h"
#include "chrome/browser/options_window.h"
#include "chrome/browser/rlz/rlz.h"
+#include "chrome/browser/search_engines/edit_keyword_controller_base.h"
#include "chrome/browser/shell_integration.h"
#include "chrome/browser/tab_contents/infobar_delegate.h"
#include "chrome/common/process_watcher.h"
@@ -299,6 +300,13 @@ void ShowOptionsWindow(OptionsPage page,
Profile* profile) {
NOTIMPLEMENTED();
}
+
+void EditKeywordControllerBase::Create(gfx::NativeWindow parent_window,
+ const TemplateURL* template_url,
+ Delegate* delegate,
+ Profile* profile) {
+ NOTIMPLEMENTED();
+}
#endif
#if defined(OS_MACOSX)