diff options
author | mattm@chromium.org <mattm@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-06-18 18:49:37 +0000 |
---|---|---|
committer | mattm@chromium.org <mattm@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-06-18 18:49:37 +0000 |
commit | 989246dcb5a9b679a1260baf3a4364ec5cead962 (patch) | |
tree | 4030c5b3a8faa922213644242d0a61332803278b | |
parent | f9fc018f52b80dff2bb0193f76cfa640a688ded5 (diff) | |
download | chromium_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.cc | 233 | ||||
-rw-r--r-- | chrome/browser/gtk/edit_keyword_controller.h | 73 | ||||
-rw-r--r-- | chrome/browser/search_engines/edit_keyword_controller_base.h | 8 | ||||
-rw-r--r-- | chrome/browser/search_engines/template_url_fetcher.cc | 20 | ||||
-rw-r--r-- | chrome/browser/views/edit_keyword_controller.cc | 10 | ||||
-rw-r--r-- | chrome/chrome.gyp | 2 | ||||
-rw-r--r-- | chrome/common/temp_scaffolding_stubs.cc | 8 |
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) |