summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/bookmarks/bookmark_context_menu_controller.cc18
-rw-r--r--chrome/browser/bookmarks/bookmark_input_window_dialog_controller.cc145
-rw-r--r--chrome/browser/bookmarks/bookmark_input_window_dialog_controller.h57
-rw-r--r--chrome/browser/ui/input_window_dialog.h62
-rw-r--r--chrome/browser/ui/input_window_dialog_gtk.cc109
-rw-r--r--chrome/browser/ui/input_window_dialog_gtk.h52
-rw-r--r--chrome/browser/ui/input_window_dialog_linux.cc23
-rw-r--r--chrome/browser/ui/input_window_dialog_views.cc274
-rw-r--r--chrome/browser/ui/views/bookmarks/bookmark_context_menu_controller_views.cc18
-rw-r--r--chrome/chrome_browser.gypi8
10 files changed, 756 insertions, 10 deletions
diff --git a/chrome/browser/bookmarks/bookmark_context_menu_controller.cc b/chrome/browser/bookmarks/bookmark_context_menu_controller.cc
index 04c00eb..0335e59 100644
--- a/chrome/browser/bookmarks/bookmark_context_menu_controller.cc
+++ b/chrome/browser/bookmarks/bookmark_context_menu_controller.cc
@@ -7,6 +7,7 @@
#include "base/compiler_specific.h"
#include "chrome/app/chrome_command_ids.h"
#include "chrome/browser/bookmarks/bookmark_editor.h"
+#include "chrome/browser/bookmarks/bookmark_input_window_dialog_controller.h"
#include "chrome/browser/bookmarks/bookmark_model.h"
#include "chrome/browser/bookmarks/bookmark_utils.h"
#include "chrome/browser/prefs/incognito_mode_prefs.h"
@@ -140,11 +141,18 @@ void BookmarkContextMenuController::ExecuteCommand(int id) {
break;
}
- BookmarkEditor::Show(
- parent_window_,
- profile_,
- BookmarkEditor::EditDetails::EditNode(selection_[0]),
- BookmarkEditor::SHOW_TREE);
+ if (selection_[0]->is_url()) {
+ BookmarkEditor::Show(
+ parent_window_,
+ profile_,
+ BookmarkEditor::EditDetails::EditNode(selection_[0]),
+ BookmarkEditor::SHOW_TREE);
+ } else {
+ BookmarkInputWindowDialogController::Show(
+ profile_,
+ parent_window_,
+ BookmarkEditor::EditDetails::EditNode(selection_[0]));
+ }
break;
case IDC_BOOKMARK_BAR_REMOVE: {
diff --git a/chrome/browser/bookmarks/bookmark_input_window_dialog_controller.cc b/chrome/browser/bookmarks/bookmark_input_window_dialog_controller.cc
new file mode 100644
index 0000000..19e265e
--- /dev/null
+++ b/chrome/browser/bookmarks/bookmark_input_window_dialog_controller.cc
@@ -0,0 +1,145 @@
+// Copyright (c) 2012 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/bookmarks/bookmark_input_window_dialog_controller.h"
+
+#include "base/string16.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/bookmarks/bookmark_model.h"
+#include "chrome/browser/bookmarks/bookmark_utils.h"
+#include "chrome/browser/profiles/profile.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+
+namespace {
+string16 GetWindowTitle(const BookmarkEditor::EditDetails& details) {
+ int title_id = 0;
+ switch (details.type) {
+ case BookmarkEditor::EditDetails::EXISTING_NODE:
+ if (details.existing_node->is_url()) {
+ title_id = IDS_BOOKMARK_EDITOR_TITLE;
+ } else {
+ title_id = IDS_BOOKMARK_FOLDER_EDITOR_WINDOW_TITLE;
+ }
+ break;
+ case BookmarkEditor::EditDetails::NEW_URL:
+ title_id = IDS_BOOKMARK_EDITOR_TITLE;
+ break;
+ case BookmarkEditor::EditDetails::NEW_FOLDER:
+ title_id = IDS_BOOKMARK_FOLDER_EDITOR_WINDOW_TITLE_NEW;
+ break;
+ default:
+ NOTREACHED();
+ break;
+ }
+ return l10n_util::GetStringUTF16(title_id);
+}
+} // namespace
+
+BookmarkInputWindowDialogController::~BookmarkInputWindowDialogController() {
+ if (model_)
+ model_->RemoveObserver(this);
+}
+
+// static
+void BookmarkInputWindowDialogController::Show(
+ Profile* profile,
+ gfx::NativeWindow wnd,
+ const BookmarkEditor::EditDetails& details) {
+ // BookmarkInputWindowDialogController deletes itself when done.
+ new BookmarkInputWindowDialogController(profile, wnd, details);
+}
+
+BookmarkInputWindowDialogController::BookmarkInputWindowDialogController(
+ Profile* profile,
+ gfx::NativeWindow wnd,
+ const BookmarkEditor::EditDetails& details)
+ : model_(profile->GetBookmarkModel()),
+ details_(details) {
+
+ model_->AddObserver(this);
+
+ InputWindowDialog::LabelContentsPairs label_contents_pairs;
+ string16 name_label =
+ l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_EDIT_FOLDER_LABEL);
+ if ((details.type == BookmarkEditor::EditDetails::EXISTING_NODE &&
+ details.existing_node->is_url()) ||
+ details.type == BookmarkEditor::EditDetails::NEW_URL) {
+ string16 url_label =
+ l10n_util::GetStringUTF16(IDS_BOOKMARK_EDITOR_URL_LABEL);
+ string16 name;
+ GURL url;
+ if (details.type == BookmarkEditor::EditDetails::NEW_URL) {
+ bookmark_utils::GetURLAndTitleToBookmarkFromCurrentTab(profile,
+ &url,
+ &name);
+ } else {
+ url = details.existing_node->url();
+ name = details.existing_node->GetTitle();
+ }
+ label_contents_pairs.push_back(std::make_pair(name_label, name));
+ label_contents_pairs.push_back(std::make_pair(url_label,
+ UTF8ToUTF16(url.spec())));
+ } else {
+ string16 name = (details.type == BookmarkEditor::EditDetails::NEW_FOLDER) ?
+ l10n_util::GetStringUTF16(IDS_BOOKMARK_EDITOR_NEW_FOLDER_NAME) :
+ details.existing_node->GetTitle();
+ label_contents_pairs.push_back(std::make_pair(name_label, name));
+ }
+
+ const InputWindowDialog::ButtonType button_type =
+ (details.type == BookmarkEditor::EditDetails::NEW_URL ||
+ details.type == BookmarkEditor::EditDetails::NEW_FOLDER) ?
+ InputWindowDialog::BUTTON_TYPE_ADD : InputWindowDialog::BUTTON_TYPE_SAVE;
+ dialog_ = InputWindowDialog::Create(wnd,
+ GetWindowTitle(details),
+ label_contents_pairs, this, button_type);
+ dialog_->Show();
+}
+
+bool BookmarkInputWindowDialogController::IsValid(
+ const InputWindowDialog::InputTexts& texts) {
+ if (texts.size() != 1 && texts.size() != 2) {
+ return false;
+ }
+ if (texts[0].empty() || (texts.size() == 2 && texts[1].empty())) {
+ return false;
+ }
+ return true;
+}
+
+void BookmarkInputWindowDialogController::InputAccepted(
+ const InputWindowDialog::InputTexts& texts) {
+ if (details_.type == BookmarkEditor::EditDetails::EXISTING_NODE) {
+ if (details_.existing_node->is_url()) {
+ DCHECK_EQ(2U, texts.size());
+ model_->SetTitle(details_.existing_node, texts[0]);
+ model_->SetURL(details_.existing_node, GURL(texts[1]));
+ } else {
+ DCHECK_EQ(1U, texts.size());
+ model_->SetTitle(details_.existing_node, texts[0]);
+ }
+ } else if (details_.type == BookmarkEditor::EditDetails::NEW_FOLDER) {
+ DCHECK_EQ(1U, texts.size());
+ // TODO(mazda): Add |details_.urls| to AddFolder.
+ model_->AddFolder(details_.parent_node, details_.index, texts[0]);
+ } else if (details_.type == BookmarkEditor::EditDetails::NEW_URL) {
+ DCHECK_EQ(2U, texts.size());
+ model_->AddURL(details_.parent_node, details_.index, texts[0],
+ GURL(texts[1]));
+ }
+}
+
+void BookmarkInputWindowDialogController::InputCanceled() {
+}
+
+void BookmarkInputWindowDialogController::BookmarkModelChanged() {
+}
+
+void BookmarkInputWindowDialogController::BookmarkModelBeingDeleted(
+ BookmarkModel* model) {
+ model_->RemoveObserver(this);
+ model_ = NULL;
+ BookmarkModelChanged();
+}
diff --git a/chrome/browser/bookmarks/bookmark_input_window_dialog_controller.h b/chrome/browser/bookmarks/bookmark_input_window_dialog_controller.h
new file mode 100644
index 0000000..ec30949
--- /dev/null
+++ b/chrome/browser/bookmarks/bookmark_input_window_dialog_controller.h
@@ -0,0 +1,57 @@
+// Copyright (c) 2012 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_BOOKMARKS_BOOKMARK_INPUT_WINDOW_DIALOG_CONTROLLER_H_
+#define CHROME_BROWSER_BOOKMARKS_BOOKMARK_INPUT_WINDOW_DIALOG_CONTROLLER_H_
+#pragma once
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "chrome/browser/bookmarks/base_bookmark_model_observer.h"
+#include "chrome/browser/bookmarks/bookmark_editor.h"
+#include "chrome/browser/ui/input_window_dialog.h"
+#include "ui/gfx/native_widget_types.h"
+
+class Profile;
+
+// BookmarkInputWindowDialogController manages the editing and/or creation of a
+// bookmark page or a bookmark folder. If the user presses ok, the name change
+// is committed to the model.
+//
+// BookmarkInputWindowDialogController deletes itself when the window is closed.
+class BookmarkInputWindowDialogController : public InputWindowDialog::Delegate,
+ public BaseBookmarkModelObserver {
+ public:
+ virtual ~BookmarkInputWindowDialogController();
+
+ static void Show(Profile* profile,
+ gfx::NativeWindow wnd,
+ const BookmarkEditor::EditDetails& details);
+
+ private:
+ BookmarkInputWindowDialogController(
+ Profile* profile,
+ gfx::NativeWindow wnd,
+ const BookmarkEditor::EditDetails& details);
+
+ // InputWindowDialog::Delegate:
+ virtual bool IsValid(const InputWindowDialog::InputTexts& texts) OVERRIDE;
+ virtual void InputAccepted(
+ const InputWindowDialog::InputTexts& texts) OVERRIDE;
+ virtual void InputCanceled() OVERRIDE;
+
+ // BaseBookmarkModelObserver:
+ virtual void BookmarkModelChanged() OVERRIDE;
+ virtual void BookmarkModelBeingDeleted(BookmarkModel* model) OVERRIDE;
+
+ BookmarkModel* model_;
+
+ BookmarkEditor::EditDetails details_;
+
+ InputWindowDialog* dialog_;
+
+ DISALLOW_COPY_AND_ASSIGN(BookmarkInputWindowDialogController);
+};
+
+#endif // CHROME_BROWSER_BOOKMARKS_BOOKMARK_INPUT_WINDOW_DIALOG_CONTROLLER_H_
diff --git a/chrome/browser/ui/input_window_dialog.h b/chrome/browser/ui/input_window_dialog.h
new file mode 100644
index 0000000..f692569
--- /dev/null
+++ b/chrome/browser/ui/input_window_dialog.h
@@ -0,0 +1,62 @@
+// Copyright (c) 2012 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_UI_INPUT_WINDOW_DIALOG_H_
+#define CHROME_BROWSER_UI_INPUT_WINDOW_DIALOG_H_
+#pragma once
+
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/string16.h"
+#include "ui/gfx/native_widget_types.h"
+
+// Cross platform access to a modal input window.
+class InputWindowDialog {
+ public:
+ enum ButtonType {
+ BUTTON_TYPE_ADD,
+ BUTTON_TYPE_SAVE,
+ };
+ typedef std::vector<std::pair<string16, string16> > LabelContentsPairs;
+ typedef std::vector<string16> InputTexts;
+
+ class Delegate {
+ public:
+ virtual ~Delegate() {}
+
+ // Checks whether |text| is a valid input string.
+ virtual bool IsValid(const InputTexts& texts) = 0;
+
+ // Callback for when the user clicks the OK button.
+ virtual void InputAccepted(const InputTexts& texts) = 0;
+
+ // Callback for when the user clicks the Cancel button.
+ virtual void InputCanceled() = 0;
+ };
+
+ // Creates a new input window dialog parented to |parent|. Ownership of
+ // |delegate| is taken by InputWindowDialog or InputWindowDialog's owner.
+ static InputWindowDialog* Create(
+ gfx::NativeWindow parent,
+ const string16& window_title,
+ const LabelContentsPairs& label_contents_pairs,
+ Delegate* delegate,
+ ButtonType type);
+
+ // Displays the window.
+ virtual void Show() = 0;
+
+ // Closes the window.
+ virtual void Close() = 0;
+
+ protected:
+ InputWindowDialog() {}
+ virtual ~InputWindowDialog() {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(InputWindowDialog);
+};
+
+#endif // CHROME_BROWSER_UI_INPUT_WINDOW_DIALOG_H_
diff --git a/chrome/browser/ui/input_window_dialog_gtk.cc b/chrome/browser/ui/input_window_dialog_gtk.cc
new file mode 100644
index 0000000..5abb3b2
--- /dev/null
+++ b/chrome/browser/ui/input_window_dialog_gtk.cc
@@ -0,0 +1,109 @@
+// Copyright (c) 2012 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/ui/input_window_dialog_gtk.h"
+
+#include <gtk/gtk.h>
+#include "base/message_loop.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "ui/base/gtk/gtk_signal.h"
+
+InputWindowDialogGtk::InputWindowDialogGtk(GtkWindow* parent,
+ const std::string& window_title,
+ const std::string& label,
+ const std::string& contents,
+ Delegate* delegate,
+ ButtonType type)
+ : dialog_(gtk_dialog_new_with_buttons(
+ window_title.c_str(),
+ parent,
+ GTK_DIALOG_MODAL,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
+ type == BUTTON_TYPE_ADD ? GTK_STOCK_ADD : GTK_STOCK_SAVE,
+ GTK_RESPONSE_ACCEPT,
+ NULL)),
+ delegate_(delegate) {
+ gtk_dialog_set_default_response(GTK_DIALOG(dialog_), GTK_RESPONSE_ACCEPT);
+#if !GTK_CHECK_VERSION(2, 22, 0)
+ gtk_dialog_set_has_separator(GTK_DIALOG(dialog_), FALSE);
+#endif
+ gtk_window_set_resizable(GTK_WINDOW(dialog_), FALSE);
+
+ GtkWidget* content_area = gtk_dialog_get_content_area(GTK_DIALOG(dialog_));
+ gtk_box_set_spacing(GTK_BOX(content_area), 18);
+
+ GtkWidget* hbox = gtk_hbox_new(FALSE, 6);
+ GtkWidget* label_widget = gtk_label_new(label.c_str());
+ gtk_box_pack_start(GTK_BOX(hbox), label_widget, FALSE, FALSE, 0);
+
+ input_ = gtk_entry_new();
+ gtk_entry_set_text(GTK_ENTRY(input_), contents.c_str());
+ g_signal_connect(input_, "changed",
+ G_CALLBACK(OnEntryChangedThunk), this);
+ g_object_set(G_OBJECT(input_), "activates-default", TRUE, NULL);
+ gtk_box_pack_start(GTK_BOX(hbox), input_, TRUE, TRUE, 0);
+
+ gtk_widget_show_all(hbox);
+
+ gtk_box_pack_start(GTK_BOX(content_area), hbox, FALSE, FALSE, 0);
+
+ g_signal_connect(dialog_, "response",
+ G_CALLBACK(OnResponseThunk), this);
+ g_signal_connect(dialog_, "delete-event",
+ G_CALLBACK(OnWindowDeleteEventThunk), this);
+ g_signal_connect(dialog_, "destroy",
+ G_CALLBACK(OnWindowDestroyThunk), this);
+}
+
+InputWindowDialogGtk::~InputWindowDialogGtk() {
+}
+
+void InputWindowDialogGtk::Show() {
+ gtk_util::ShowDialog(dialog_);
+}
+
+void InputWindowDialogGtk::Close() {
+ // Under the model that we've inherited from Windows, dialogs can receive
+ // more than one Close() call inside the current message loop event.
+ if (dialog_) {
+ gtk_widget_destroy(dialog_);
+ dialog_ = NULL;
+ }
+}
+
+void InputWindowDialogGtk::OnEntryChanged(GtkEditable* entry) {
+ string16 value(UTF8ToUTF16(gtk_entry_get_text(GTK_ENTRY(entry))));
+ InputWindowDialog::InputTexts texts;
+ texts.push_back(value);
+ gtk_dialog_set_response_sensitive(GTK_DIALOG(dialog_),
+ GTK_RESPONSE_ACCEPT,
+ delegate_->IsValid(texts));
+}
+
+void InputWindowDialogGtk::OnResponse(GtkWidget* dialog, int response_id) {
+ if (response_id == GTK_RESPONSE_ACCEPT) {
+ string16 value(UTF8ToUTF16(gtk_entry_get_text(GTK_ENTRY(input_))));
+ InputTexts texts;
+ texts.push_back(value);
+ delegate_->InputAccepted(texts);
+ } else {
+ delegate_->InputCanceled();
+ }
+ Close();
+}
+
+gboolean InputWindowDialogGtk::OnWindowDeleteEvent(GtkWidget* widget,
+ GdkEvent* event) {
+ Close();
+
+ // Return true to prevent the gtk dialog from being destroyed. Close will
+ // destroy it for us and the default gtk_dialog_delete_event_handler() will
+ // force the destruction without us being able to stop it.
+ return TRUE;
+}
+
+void InputWindowDialogGtk::OnWindowDestroy(GtkWidget* widget) {
+ MessageLoop::current()->DeleteSoon(FROM_HERE, this);
+}
diff --git a/chrome/browser/ui/input_window_dialog_gtk.h b/chrome/browser/ui/input_window_dialog_gtk.h
new file mode 100644
index 0000000..ef11187
--- /dev/null
+++ b/chrome/browser/ui/input_window_dialog_gtk.h
@@ -0,0 +1,52 @@
+// Copyright (c) 2012 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_UI_INPUT_WINDOW_DIALOG_GTK_H_
+#define CHROME_BROWSER_UI_INPUT_WINDOW_DIALOG_GTK_H_
+#pragma once
+
+#include <gtk/gtk.h>
+
+#include <string>
+
+#include "base/compiler_specific.h"
+#include "base/basictypes.h"
+#include "base/memory/scoped_ptr.h"
+#include "chrome/browser/ui/input_window_dialog.h"
+#include "ui/base/gtk/gtk_signal.h"
+
+class InputWindowDialogGtk : public InputWindowDialog {
+ public:
+ // Creates a dialog. Takes ownership of |delegate|.
+ InputWindowDialogGtk(GtkWindow* parent,
+ const std::string& window_title,
+ const std::string& label,
+ const std::string& contents,
+ Delegate* delegate,
+ ButtonType type);
+ virtual ~InputWindowDialogGtk();
+
+ virtual void Show() OVERRIDE;
+ virtual void Close() OVERRIDE;
+
+ private:
+ CHROMEG_CALLBACK_0(InputWindowDialogGtk, void, OnEntryChanged, GtkEditable*);
+ CHROMEGTK_CALLBACK_1(InputWindowDialogGtk, void, OnResponse, int);
+ CHROMEGTK_CALLBACK_1(InputWindowDialogGtk, gboolean,
+ OnWindowDeleteEvent, GdkEvent*);
+ CHROMEGTK_CALLBACK_0(InputWindowDialogGtk, void, OnWindowDestroy);
+
+ // The underlying gtk dialog window.
+ GtkWidget* dialog_;
+
+ // The GtkEntry in this form.
+ GtkWidget* input_;
+
+ // Our delegate. Consumes the window's output.
+ scoped_ptr<InputWindowDialog::Delegate> delegate_;
+
+ DISALLOW_COPY_AND_ASSIGN(InputWindowDialogGtk);
+};
+
+#endif // CHROME_BROWSER_UI_INPUT_WINDOW_DIALOG_GTK_H_
diff --git a/chrome/browser/ui/input_window_dialog_linux.cc b/chrome/browser/ui/input_window_dialog_linux.cc
new file mode 100644
index 0000000..4a91ce3
--- /dev/null
+++ b/chrome/browser/ui/input_window_dialog_linux.cc
@@ -0,0 +1,23 @@
+// Copyright (c) 2012 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/ui/input_window_dialog.h"
+
+#include "base/logging.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/ui/input_window_dialog_gtk.h"
+
+InputWindowDialog* InputWindowDialog::Create(
+ gfx::NativeWindow parent,
+ const string16& window_title,
+ const LabelContentsPairs& label_contents_pairs,
+ Delegate* delegate,
+ ButtonType type) {
+ return new InputWindowDialogGtk(parent,
+ UTF16ToUTF8(window_title),
+ UTF16ToUTF8(label_contents_pairs[0].first),
+ UTF16ToUTF8(label_contents_pairs[0].second),
+ delegate,
+ type);
+}
diff --git a/chrome/browser/ui/input_window_dialog_views.cc b/chrome/browser/ui/input_window_dialog_views.cc
new file mode 100644
index 0000000..a7bd9f74
--- /dev/null
+++ b/chrome/browser/ui/input_window_dialog_views.cc
@@ -0,0 +1,274 @@
+// Copyright (c) 2012 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/ui/input_window_dialog.h"
+
+#include "base/bind.h"
+#include "base/compiler_specific.h"
+#include "base/memory/weak_ptr.h"
+#include "base/message_loop.h"
+#include "base/utf_string_conversions.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/views/controls/label.h"
+#include "ui/views/controls/textfield/textfield.h"
+#include "ui/views/controls/textfield/textfield_controller.h"
+#include "ui/views/layout/grid_layout.h"
+#include "ui/views/layout/layout_constants.h"
+#include "ui/views/widget/widget.h"
+#include "ui/views/window/dialog_delegate.h"
+
+namespace {
+
+// Width of the text field, in pixels.
+const int kTextfieldWidth = 200;
+
+} // namespace
+
+// The Views implementation of the cross platform input dialog interface.
+class InputWindowDialogViews : public InputWindowDialog {
+ public:
+ InputWindowDialogViews(gfx::NativeWindow parent,
+ const string16& window_title,
+ const string16& label,
+ const string16& contents,
+ Delegate* delegate,
+ ButtonType type);
+ virtual ~InputWindowDialogViews();
+
+ // Overridden from InputWindowDialog:
+ virtual void Show() OVERRIDE;
+ virtual void Close() OVERRIDE;
+
+ const string16& window_title() const { return window_title_; }
+ const string16& label() const { return label_; }
+ const string16& contents() const { return contents_; }
+
+ Delegate* delegate() { return delegate_.get(); }
+ ButtonType type() const { return type_; }
+
+ private:
+ // Our chrome views window.
+ views::Widget* window_;
+
+ // Strings to feed to the on screen window.
+ string16 window_title_;
+ string16 label_;
+ string16 contents_;
+
+ // Our delegate. Consumes the window's output.
+ scoped_ptr<InputWindowDialog::Delegate> delegate_;
+ const ButtonType type_;
+
+ DISALLOW_COPY_AND_ASSIGN(InputWindowDialogViews);
+};
+
+// ContentView, as the name implies, is the content view for the InputWindow.
+// It registers accelerators that accept/cancel the input.
+class ContentView : public views::DialogDelegateView,
+ public views::TextfieldController {
+ public:
+ explicit ContentView(InputWindowDialogViews* delegate);
+
+ // views::DialogDelegateView:
+ virtual string16 GetDialogButtonLabel(ui::DialogButton button) const OVERRIDE;
+ virtual bool IsDialogButtonEnabled(ui::DialogButton button) const OVERRIDE;
+ virtual bool Accept() OVERRIDE;
+ virtual bool Cancel() OVERRIDE;
+ virtual void DeleteDelegate() OVERRIDE;
+ virtual string16 GetWindowTitle() const OVERRIDE;
+ virtual ui::ModalType GetModalType() const OVERRIDE;
+ virtual views::View* GetContentsView() OVERRIDE;
+
+ // views::TextfieldController:
+ virtual void ContentsChanged(views::Textfield* sender,
+ const string16& new_contents) OVERRIDE;
+ virtual bool HandleKeyEvent(views::Textfield*,
+ const views::KeyEvent&) OVERRIDE;
+
+ protected:
+ // views::View:
+ virtual void ViewHierarchyChanged(bool is_add,
+ views::View* parent,
+ views::View* child) OVERRIDE;
+
+ private:
+ // Set up dialog controls and layout.
+ void InitControlLayout();
+
+ // Sets focus to the first focusable element within the dialog.
+ void FocusFirstFocusableControl();
+
+ // The Textfield that the user can type into.
+ views::Textfield* text_field_;
+
+ // The delegate that the ContentView uses to communicate changes to the
+ // caller.
+ InputWindowDialogViews* delegate_;
+
+ // Helps us set focus to the first Textfield in the window.
+ base::WeakPtrFactory<ContentView> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(ContentView);
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// ContentView
+ContentView::ContentView(InputWindowDialogViews* delegate)
+ : delegate_(delegate),
+ ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) {
+ DCHECK(delegate_);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// ContentView, views::DialogDelegate implementation:
+
+string16 ContentView::GetDialogButtonLabel(ui::DialogButton button) const {
+ if (button == ui::DIALOG_BUTTON_OK) {
+ return l10n_util::GetStringUTF16(
+ delegate_->type() == InputWindowDialog::BUTTON_TYPE_ADD ? IDS_ADD
+ : IDS_SAVE);
+ }
+ return string16();
+}
+
+bool ContentView::IsDialogButtonEnabled(ui::DialogButton button) const {
+ if (button == ui::DIALOG_BUTTON_OK) {
+ InputWindowDialog::InputTexts texts;
+ texts.push_back(text_field_->text());
+ if (!delegate_->delegate()->IsValid(texts)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool ContentView::Accept() {
+ InputWindowDialog::InputTexts texts;
+ texts.push_back(text_field_->text());
+ delegate_->delegate()->InputAccepted(texts);
+ delegate_->Close();
+ return true;
+}
+
+bool ContentView::Cancel() {
+ delegate_->delegate()->InputCanceled();
+ return true;
+}
+
+void ContentView::DeleteDelegate() {
+ delete delegate_;
+}
+
+string16 ContentView::GetWindowTitle() const {
+ return delegate_->window_title();
+}
+
+ui::ModalType ContentView::GetModalType() const {
+ return ui::MODAL_TYPE_WINDOW;
+}
+
+views::View* ContentView::GetContentsView() {
+ return this;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// ContentView, views::TextfieldController implementation:
+
+void ContentView::ContentsChanged(views::Textfield* sender,
+ const string16& new_contents) {
+ GetDialogClientView()->UpdateDialogButtons();
+}
+
+bool ContentView::HandleKeyEvent(views::Textfield*,
+ const views::KeyEvent&) {
+ return false;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// ContentView, protected:
+
+void ContentView::ViewHierarchyChanged(bool is_add,
+ views::View* parent,
+ views::View* child) {
+ if (is_add && child == this)
+ InitControlLayout();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// ContentView, private:
+
+void ContentView::InitControlLayout() {
+ text_field_ = new views::Textfield;
+ text_field_->SetText(delegate_->contents());
+ text_field_->SetController(this);
+
+ // TODO(sky): Vertical alignment should be baseline.
+ views::GridLayout* layout = views::GridLayout::CreatePanel(this);
+ SetLayoutManager(layout);
+
+ views::ColumnSet* c1 = layout->AddColumnSet(0);
+ c1->AddColumn(views::GridLayout::CENTER, views::GridLayout::CENTER, 0,
+ views::GridLayout::USE_PREF, 0, 0);
+ c1->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
+ c1->AddColumn(views::GridLayout::FILL, views::GridLayout::CENTER, 1,
+ views::GridLayout::USE_PREF, kTextfieldWidth, kTextfieldWidth);
+
+ layout->StartRow(0, 0);
+ views::Label* label = new views::Label(delegate_->label());
+ layout->AddView(label);
+ layout->AddView(text_field_);
+
+ MessageLoop::current()->PostTask(
+ FROM_HERE, base::Bind(&ContentView::FocusFirstFocusableControl,
+ weak_factory_.GetWeakPtr()));
+}
+
+void ContentView::FocusFirstFocusableControl() {
+ text_field_->SelectAll();
+ text_field_->RequestFocus();
+}
+
+InputWindowDialogViews::InputWindowDialogViews(gfx::NativeWindow parent,
+ const string16& window_title,
+ const string16& label,
+ const string16& contents,
+ Delegate* delegate,
+ ButtonType type)
+ : window_title_(window_title),
+ label_(label),
+ contents_(contents),
+ delegate_(delegate),
+ type_(type) {
+ window_ = views::Widget::CreateWindowWithParent(new ContentView(this),
+ parent);
+ window_->client_view()->AsDialogClientView()->UpdateDialogButtons();
+}
+
+InputWindowDialogViews::~InputWindowDialogViews() {
+}
+
+void InputWindowDialogViews::Show() {
+ window_->Show();
+}
+
+void InputWindowDialogViews::Close() {
+ window_->Close();
+}
+
+// static
+InputWindowDialog* InputWindowDialog::Create(
+ gfx::NativeWindow parent,
+ const string16& window_title,
+ const LabelContentsPairs& label_contents_pairs,
+ Delegate* delegate,
+ ButtonType type) {
+ DCHECK_EQ(1U, label_contents_pairs.size());
+ return new InputWindowDialogViews(parent,
+ window_title,
+ label_contents_pairs[0].first,
+ label_contents_pairs[0].second,
+ delegate,
+ type);
+}
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_context_menu_controller_views.cc b/chrome/browser/ui/views/bookmarks/bookmark_context_menu_controller_views.cc
index 5659024..38587db 100644
--- a/chrome/browser/ui/views/bookmarks/bookmark_context_menu_controller_views.cc
+++ b/chrome/browser/ui/views/bookmarks/bookmark_context_menu_controller_views.cc
@@ -7,6 +7,7 @@
#include "base/compiler_specific.h"
#include "chrome/app/chrome_command_ids.h"
#include "chrome/browser/bookmarks/bookmark_editor.h"
+#include "chrome/browser/bookmarks/bookmark_input_window_dialog_controller.h"
#include "chrome/browser/bookmarks/bookmark_model.h"
#include "chrome/browser/bookmarks/bookmark_utils.h"
#include "chrome/browser/prefs/incognito_mode_prefs.h"
@@ -132,11 +133,18 @@ void BookmarkContextMenuControllerViews::ExecuteCommand(int id) {
return;
}
- BookmarkEditor::Show(
- parent_widget_->GetNativeWindow(),
- profile_,
- BookmarkEditor::EditDetails::EditNode(selection_[0]),
- BookmarkEditor::SHOW_TREE);
+ if (selection_[0]->is_url()) {
+ BookmarkEditor::Show(
+ parent_widget_->GetNativeWindow(),
+ profile_,
+ BookmarkEditor::EditDetails::EditNode(selection_[0]),
+ BookmarkEditor::SHOW_TREE);
+ } else {
+ BookmarkInputWindowDialogController::Show(
+ profile_,
+ parent_widget_->GetNativeWindow(),
+ BookmarkEditor::EditDetails::EditNode(selection_[0]));
+ }
break;
case IDC_BOOKMARK_BAR_REMOVE: {
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index 5fbe3d6..20acc53 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -293,6 +293,8 @@
'browser/bookmarks/bookmark_html_writer.h',
'browser/bookmarks/bookmark_index.cc',
'browser/bookmarks/bookmark_index.h',
+ 'browser/bookmarks/bookmark_input_window_dialog_controller.cc',
+ 'browser/bookmarks/bookmark_input_window_dialog_controller.h',
'browser/bookmarks/bookmark_model.cc',
'browser/bookmarks/bookmark_model.h',
'browser/bookmarks/bookmark_model_observer.h',
@@ -3343,6 +3345,11 @@
'browser/ui/gtk/view_id_util.h',
'browser/ui/gtk/web_intent_picker_gtk.cc',
'browser/ui/gtk/web_intent_picker_gtk.h',
+ 'browser/ui/input_window_dialog.h',
+ 'browser/ui/input_window_dialog_linux.cc',
+ 'browser/ui/input_window_dialog_gtk.cc',
+ 'browser/ui/input_window_dialog_gtk.h',
+ 'browser/ui/input_window_dialog_views.cc',
'browser/ui/intents/web_intent_inline_disposition_delegate.cc',
'browser/ui/intents/web_intent_inline_disposition_delegate.h',
'browser/ui/intents/web_intent_picker.cc',
@@ -4545,6 +4552,7 @@
['exclude', '^browser/renderer_host/render_widget_host_view_views*'],
['exclude', '^browser/tab_contents/web_drag_source_win.cc'],
['exclude', '^browser/tab_contents/web_drag_source_win.h'],
+ ['exclude', '^browser/ui/input_window_dialog_linux.cc'],
['exclude', '^browser/ui/panels/auto_hiding_desktop_bar_win.cc'],
['exclude', '^browser/ui/tabs/dock_info_win.cc'],
['exclude', '^browser/ui/views/about_ipc_dialog.cc'],