diff options
-rw-r--r-- | chrome/browser/views/options/general_page_view.cc | 5 | ||||
-rw-r--r-- | chrome/browser/views/options/general_page_view.h | 8 | ||||
-rw-r--r-- | chrome/browser/views/shelf_item_dialog.cc | 313 | ||||
-rw-r--r-- | chrome/browser/views/shelf_item_dialog.h | 131 | ||||
-rw-r--r-- | chrome/browser/views/url_picker.cc | 317 | ||||
-rw-r--r-- | chrome/browser/views/url_picker.h | 131 | ||||
-rw-r--r-- | chrome/chrome.gyp | 4 |
7 files changed, 456 insertions, 453 deletions
diff --git a/chrome/browser/views/options/general_page_view.cc b/chrome/browser/views/options/general_page_view.cc index e99444d..f639efe 100644 --- a/chrome/browser/views/options/general_page_view.cc +++ b/chrome/browser/views/options/general_page_view.cc @@ -21,7 +21,6 @@ #include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/browser/views/keyword_editor_view.h" #include "chrome/browser/views/options/options_group_view.h" -#include "chrome/browser/dom_ui/new_tab_ui.h" #include "chrome/common/chrome_constants.h" #include "chrome/common/pref_names.h" #include "chrome/common/pref_service.h" @@ -889,7 +888,7 @@ void GeneralPageView::SaveStartupPref() { } void GeneralPageView::AddURLToStartupURLs() { - ShelfItemDialog* dialog = new ShelfItemDialog(this, profile(), false); + UrlPicker* dialog = new UrlPicker(this, profile(), false); dialog->Show(GetWindow()->GetNativeWindow()); } @@ -936,7 +935,7 @@ void GeneralPageView::EnableCustomHomepagesControls(bool enable) { startup_custom_pages_table_->SetEnabled(enable); } -void GeneralPageView::AddBookmark(ShelfItemDialog* dialog, +void GeneralPageView::AddBookmark(UrlPicker* dialog, const std::wstring& title, const GURL& url) { int index = startup_custom_pages_table_->FirstSelectedRow(); diff --git a/chrome/browser/views/options/general_page_view.h b/chrome/browser/views/options/general_page_view.h index 27827be..1cf5f30 100644 --- a/chrome/browser/views/options/general_page_view.h +++ b/chrome/browser/views/options/general_page_view.h @@ -7,7 +7,7 @@ #include "chrome/browser/shell_integration.h" #include "chrome/browser/views/options/options_page_view.h" -#include "chrome/browser/views/shelf_item_dialog.h" +#include "chrome/browser/views/url_picker.h" #include "chrome/common/pref_member.h" #include "views/controls/combobox/combobox.h" #include "views/controls/button/button.h" @@ -35,7 +35,7 @@ class GeneralPageView : public OptionsPageView, public views::Combobox::Listener, public views::ButtonListener, public views::Textfield::Controller, - public ShelfItemDialogDelegate, + public UrlPickerDelegate, public views::TableViewObserver, public ShellIntegration::DefaultBrowserObserver { public: @@ -94,8 +94,8 @@ class GeneralPageView : public OptionsPageView, // option if that preference is not selected. void EnableCustomHomepagesControls(bool enable); - // ShelfItemDialogDelegate. Adds the URL to the list of startup urls. - virtual void AddBookmark(ShelfItemDialog* dialog, + // UrlPickerDelegate. Adds the URL to the list of startup urls. + virtual void AddBookmark(UrlPicker* dialog, const std::wstring& title, const GURL& url); diff --git a/chrome/browser/views/shelf_item_dialog.cc b/chrome/browser/views/shelf_item_dialog.cc index ce3c7b0..e69de29 100644 --- a/chrome/browser/views/shelf_item_dialog.cc +++ b/chrome/browser/views/shelf_item_dialog.cc @@ -1,313 +0,0 @@ -// Copyright (c) 2006-2008 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/shelf_item_dialog.h" - -#include "app/l10n_util.h" -#include "app/resource_bundle.h" -#include "app/table_model.h" -#include "app/table_model_observer.h" -#include "base/stl_util-inl.h" -#include "base/string_util.h" -#include "chrome/browser/net/url_fixer_upper.h" -#include "chrome/browser/possible_url_model.h" -#include "chrome/browser/profile.h" -#include "chrome/browser/tab_contents/tab_contents.h" -#include "chrome/common/pref_names.h" -#include "chrome/common/pref_service.h" -#include "grit/app_resources.h" -#include "grit/generated_resources.h" -#include "grit/locale_settings.h" -#include "net/base/net_util.h" -#include "views/background.h" -#include "views/controls/label.h" -#include "views/controls/table/table_view.h" -#include "views/controls/textfield/textfield.h" -#include "views/focus/focus_manager.h" -#include "views/grid_layout.h" -#include "views/standard_layout.h" -#include "views/widget/widget.h" - -using views::ColumnSet; -using views::GridLayout; - -// Preferred height of the table. -static const int kTableWidth = 300; - -//////////////////////////////////////////////////////////////////////////////// -// -// ShelfItemDialog implementation -// -//////////////////////////////////////////////////////////////////////////////// -ShelfItemDialog::ShelfItemDialog(ShelfItemDialogDelegate* delegate, - Profile* profile, - bool show_title) - : profile_(profile), - expected_title_handle_(0), - delegate_(delegate) { - DCHECK(profile_); - - ResourceBundle& rb = ResourceBundle::GetSharedInstance(); - - url_table_model_.reset(new PossibleURLModel()); - - TableColumn col1(IDS_ASI_PAGE_COLUMN, TableColumn::LEFT, -1, - 50); - col1.sortable = true; - TableColumn col2(IDS_ASI_URL_COLUMN, TableColumn::LEFT, -1, - 50); - col2.sortable = true; - std::vector<TableColumn> cols; - cols.push_back(col1); - cols.push_back(col2); - - url_table_ = new views::TableView(url_table_model_.get(), cols, - views::ICON_AND_TEXT, true, true, - true); - url_table_->SetObserver(this); - - // Yummy layout code. - const int labels_column_set_id = 0; - const int single_column_view_set_id = 1; - GridLayout* layout = CreatePanelGridLayout(this); - SetLayoutManager(layout); - ColumnSet* column_set = layout->AddColumnSet(labels_column_set_id); - column_set->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 0, - GridLayout::USE_PREF, 0, 0); - column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing); - column_set->AddColumn(GridLayout::FILL, GridLayout::CENTER, 1, - GridLayout::USE_PREF, 0, 0); - - column_set = layout->AddColumnSet(single_column_view_set_id); - column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1, - GridLayout::FIXED, kTableWidth, 0); - - if (show_title) { - layout->StartRow(0, labels_column_set_id); - views::Label* title_label = new views::Label(); - title_label->SetHorizontalAlignment(views::Label::ALIGN_LEFT); - title_label->SetText(l10n_util::GetString(IDS_ASI_TITLE_LABEL)); - layout->AddView(title_label); - - title_field_ = new views::Textfield(); - title_field_->SetController(this); - layout->AddView(title_field_); - - layout->AddPaddingRow(0, kRelatedControlVerticalSpacing); - } else { - title_field_ = NULL; - } - - layout->StartRow(0, labels_column_set_id); - views::Label* url_label = new views::Label(); - url_label->SetHorizontalAlignment(views::Label::ALIGN_LEFT); - url_label->SetText(l10n_util::GetString(IDS_ASI_URL)); - layout->AddView(url_label); - - url_field_ = new views::Textfield(); - url_field_->SetController(this); - layout->AddView(url_field_); - - layout->AddPaddingRow(0, kUnrelatedControlVerticalSpacing); - - layout->StartRow(0, single_column_view_set_id); - views::Label* description_label = new views::Label(); - description_label->SetHorizontalAlignment(views::Label::ALIGN_LEFT); - description_label->SetText(l10n_util::GetString(IDS_ASI_DESCRIPTION)); - description_label->SetFont( - description_label->GetFont().DeriveFont(0, gfx::Font::BOLD)); - layout->AddView(description_label); - - layout->AddPaddingRow(0, kRelatedControlVerticalSpacing); - - layout->StartRow(1, single_column_view_set_id); - layout->AddView(url_table_); - - layout->AddPaddingRow(0, kRelatedControlVerticalSpacing); - - AddAccelerator(views::Accelerator(VK_RETURN, false, false, false)); -} - -ShelfItemDialog::~ShelfItemDialog() { - url_table_->SetModel(NULL); -} - -void ShelfItemDialog::Show(HWND parent) { - DCHECK(!window()); - views::Window::CreateChromeWindow(parent, gfx::Rect(), this)->Show(); - if (title_field_) { - title_field_->SetText(l10n_util::GetString(IDS_ASI_DEFAULT_TITLE)); - title_field_->SelectAll(); - title_field_->RequestFocus(); - } else { - url_field_->SelectAll(); - url_field_->RequestFocus(); - } - url_table_model_->Reload(profile_); -} - -void ShelfItemDialog::Close() { - DCHECK(window()); - window()->Close(); -} - -std::wstring ShelfItemDialog::GetWindowTitle() const { - return l10n_util::GetString(IDS_ASI_ADD_TITLE); -} - -bool ShelfItemDialog::IsModal() const { - return true; -} - -std::wstring ShelfItemDialog::GetDialogButtonLabel( - MessageBoxFlags::DialogButton button) const { - if (button == MessageBoxFlags::DIALOGBUTTON_OK) - return l10n_util::GetString(IDS_ASI_ADD); - return std::wstring(); -} - -void ShelfItemDialog::OnURLInfoAvailable( - HistoryService::Handle handle, - bool success, - const history::URLRow* info, - history::VisitVector* unused) { - if (handle != expected_title_handle_) - return; - - std::wstring s; - if (success) - s = info->title(); - if (s.empty()) - s = l10n_util::GetString(IDS_ASI_DEFAULT_TITLE); - - if (title_field_) { - // expected_title_handle_ is reset if the title Textfield is edited so we - // can safely set the value. - title_field_->SetText(s); - title_field_->SelectAll(); - } - expected_title_handle_ = 0; -} - -void ShelfItemDialog::InitiateTitleAutoFill(const GURL& url) { - HistoryService* hs = profile_->GetHistoryService(Profile::EXPLICIT_ACCESS); - if (!hs) - return; - - if (expected_title_handle_) - hs->CancelRequest(expected_title_handle_); - - expected_title_handle_ = hs->QueryURL(url, false, &history_consumer_, - NewCallback(this, &ShelfItemDialog::OnURLInfoAvailable)); -} - -void ShelfItemDialog::ContentsChanged(views::Textfield* sender, - const std::wstring& new_contents) { - // If the user has edited the title field we no longer want to autofill it - // so we reset the expected handle to an impossible value. - if (sender == title_field_) - expected_title_handle_ = 0; - GetDialogClientView()->UpdateDialogButtons(); -} - -bool ShelfItemDialog::Accept() { - if (!IsDialogButtonEnabled(MessageBoxFlags::DIALOGBUTTON_OK)) { - if (!GetInputURL().is_valid()) - url_field_->RequestFocus(); - else if (title_field_) - title_field_->RequestFocus(); - return false; - } - PerformModelChange(); - return true; -} - -int ShelfItemDialog::GetDefaultDialogButton() const { - // Don't set a default button, this view already has an accelerator for the - // enter key. - return MessageBoxFlags::DIALOGBUTTON_NONE; -} - -bool ShelfItemDialog::IsDialogButtonEnabled( - MessageBoxFlags::DialogButton button) const { - if (button == MessageBoxFlags::DIALOGBUTTON_OK) - return GetInputURL().is_valid(); - return true; -} - -views::View* ShelfItemDialog::GetContentsView() { - return this; -} - -void ShelfItemDialog::PerformModelChange() { - DCHECK(delegate_); - GURL url(GetInputURL()); - const std::wstring title = - title_field_ ? title_field_->text() : std::wstring(); - delegate_->AddBookmark(this, title, url); -} - -gfx::Size ShelfItemDialog::GetPreferredSize() { - return gfx::Size(views::Window::GetLocalizedContentsSize( - IDS_SHELFITEM_DIALOG_WIDTH_CHARS, - IDS_SHELFITEM_DIALOG_HEIGHT_LINES)); -} - -bool ShelfItemDialog::AcceleratorPressed( - const views::Accelerator& accelerator) { - if (accelerator.GetKeyCode() == VK_ESCAPE) { - window()->Close(); - } else if (accelerator.GetKeyCode() == VK_RETURN) { - views::FocusManager* fm = GetFocusManager(); - if (fm->GetFocusedView() == url_table_) { - // Return on table behaves like a double click. - OnDoubleClick(); - } else if (fm->GetFocusedView()== url_field_) { - // Return on the url field accepts the input if url is valid. If the URL - // is invalid, focus is left on the url field. - if (GetInputURL().is_valid()) { - PerformModelChange(); - if (window()) - window()->Close(); - } else { - url_field_->SelectAll(); - } - } else if (title_field_ && fm->GetFocusedView() == title_field_) { - url_field_->SelectAll(); - url_field_->RequestFocus(); - } - } - return true; -} - -void ShelfItemDialog::OnSelectionChanged() { - int selection = url_table_->FirstSelectedRow(); - if (selection >= 0 && selection < url_table_model_->RowCount()) { - std::wstring languages = - profile_->GetPrefs()->GetString(prefs::kAcceptLanguages); - // Because the url_field_ is user-editable, we set the URL with - // username:password and escaped path and query. - std::wstring formatted = net::FormatUrl( - url_table_model_->GetURL(selection), languages, - false, UnescapeRule::NONE, NULL, NULL); - url_field_->SetText(formatted); - if (title_field_) - title_field_->SetText(url_table_model_->GetTitle(selection)); - GetDialogClientView()->UpdateDialogButtons(); - } -} - -void ShelfItemDialog::OnDoubleClick() { - int selection = url_table_->FirstSelectedRow(); - if (selection >= 0 && selection < url_table_model_->RowCount()) { - OnSelectionChanged(); - PerformModelChange(); - if (window()) - window()->Close(); - } -} - -GURL ShelfItemDialog::GetInputURL() const { - return GURL(URLFixerUpper::FixupURL(url_field_->text(), L"")); -} diff --git a/chrome/browser/views/shelf_item_dialog.h b/chrome/browser/views/shelf_item_dialog.h index 8f5953a..e69de29 100644 --- a/chrome/browser/views/shelf_item_dialog.h +++ b/chrome/browser/views/shelf_item_dialog.h @@ -1,131 +0,0 @@ -// 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_VIEWS_SHELF_ITEM_DIALOG_H_ -#define CHROME_BROWSER_VIEWS_SHELF_ITEM_DIALOG_H_ - -#include "chrome/browser/cancelable_request.h" -#include "chrome/browser/history/history.h" -#include "views/controls/button/native_button.h" -#include "views/controls/table/table_view_observer.h" -#include "views/controls/textfield/textfield.h" -#include "views/view.h" -#include "views/window/dialog_delegate.h" -#include "views/window/window.h" - -namespace views { -class Button; -class Label; -class TableView; -} - -class PossibleURLModel; -class Profile; -class ShelfItemDialog; - -// TODO(sky): rename this, perhaps to URLPicker. - -// ShelfItemDialog delegate. Notified when the user accepts the entry. -class ShelfItemDialogDelegate { - public: - virtual void AddBookmark(ShelfItemDialog* dialog, - const std::wstring& title, - const GURL& url) = 0; -}; - -//////////////////////////////////////////////////////////////////////////////// -// -// This class implements the dialog that let the user add a bookmark or page -// to the list of urls to open on startup. -// ShelfItemDialog deletes itself when the dialog is closed. -// -//////////////////////////////////////////////////////////////////////////////// -class ShelfItemDialog : public views::View, - public views::DialogDelegate, - public views::Textfield::Controller, - public views::TableViewObserver { - public: - ShelfItemDialog(ShelfItemDialogDelegate* delegate, - Profile* profile, - bool show_title); - virtual ~ShelfItemDialog(); - - // Show the dialog on the provided contents. - virtual void Show(HWND parent); - - // Closes the dialog. - void Close(); - - // DialogDelegate. - virtual std::wstring GetWindowTitle() const; - virtual bool IsModal() const; - virtual std::wstring GetDialogButtonLabel( - MessageBoxFlags::DialogButton button) const; - virtual bool Accept(); - virtual int GetDefaultDialogButton() const; - virtual bool IsDialogButtonEnabled( - MessageBoxFlags::DialogButton button) const; - virtual views::View* GetContentsView(); - - // TextField::Controller. - virtual void ContentsChanged(views::Textfield* sender, - const std::wstring& new_contents); - virtual bool HandleKeystroke(views::Textfield* sender, - const views::Textfield::Keystroke& key) { - return false; - } - - // Overridden from View. - virtual gfx::Size GetPreferredSize(); - virtual bool AcceleratorPressed(const views::Accelerator& accelerator); - - // TableViewObserver. - virtual void OnSelectionChanged(); - virtual void OnDoubleClick(); - - private: - // Modify the model from the user interface. - void PerformModelChange(); - - // Fetch the title for the entered URL. If we get the title in time before - // the user starts to modify the title field, the title field is changed. - void InitiateTitleAutoFill(const GURL& url); - - // Invoked by the history system when a title becomes available. - void OnURLInfoAvailable(HistoryService::Handle handle, - bool success, - const history::URLRow* info, - history::VisitVector* unused); - - // Returns the URL the user has typed. - GURL GetInputURL() const; - - // Profile. - Profile* profile_; - - // URL Field. - views::Textfield* url_field_; - - // Title field. This is NULL if we're not showing the title. - views::Textfield* title_field_; - - // The table model. - scoped_ptr<PossibleURLModel> url_table_model_; - - // The table of visited urls. - views::TableView* url_table_; - - // Handle of the title request we are expecting. - CancelableRequestProvider::Handle expected_title_handle_; - - // The consumer object for the history database. - CancelableRequestConsumer history_consumer_; - - // The delegate. - ShelfItemDialogDelegate* delegate_; - - DISALLOW_COPY_AND_ASSIGN(ShelfItemDialog); -}; - -#endif // CHROME_BROWSER_VIEWS_SHELF_ITEM_DIALOG_H_ diff --git a/chrome/browser/views/url_picker.cc b/chrome/browser/views/url_picker.cc new file mode 100644 index 0000000..604e97f --- /dev/null +++ b/chrome/browser/views/url_picker.cc @@ -0,0 +1,317 @@ +// Copyright (c) 2006-2008 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/url_picker.h" + +#include "app/l10n_util.h" +#include "app/resource_bundle.h" +#include "app/table_model.h" +#include "app/table_model_observer.h" +#include "base/stl_util-inl.h" +#include "base/string_util.h" +#include "chrome/browser/net/url_fixer_upper.h" +#include "chrome/browser/possible_url_model.h" +#include "chrome/browser/profile.h" +#include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/common/pref_names.h" +#include "chrome/common/pref_service.h" +#include "grit/app_resources.h" +#include "grit/generated_resources.h" +#include "grit/locale_settings.h" +#include "net/base/net_util.h" +#include "views/background.h" +#include "views/controls/label.h" +#include "views/controls/table/table_view.h" +#include "views/controls/textfield/textfield.h" +#include "views/focus/focus_manager.h" +#include "views/grid_layout.h" +#include "views/standard_layout.h" +#include "views/widget/widget.h" + +using views::ColumnSet; +using views::GridLayout; + +// Preferred height of the table. +static const int kTableWidth = 300; + +UrlPickerDelegate::~UrlPickerDelegate() {} + +//////////////////////////////////////////////////////////////////////////////// +// +// UrlPicker implementation +// +//////////////////////////////////////////////////////////////////////////////// +UrlPicker::UrlPicker(UrlPickerDelegate* delegate, + Profile* profile, + bool show_title) + : profile_(profile), + expected_title_handle_(0), + delegate_(delegate) { + DCHECK(profile_); + + ResourceBundle& rb = ResourceBundle::GetSharedInstance(); + + url_table_model_.reset(new PossibleURLModel()); + + TableColumn col1(IDS_ASI_PAGE_COLUMN, TableColumn::LEFT, -1, + 50); + col1.sortable = true; + TableColumn col2(IDS_ASI_URL_COLUMN, TableColumn::LEFT, -1, + 50); + col2.sortable = true; + std::vector<TableColumn> cols; + cols.push_back(col1); + cols.push_back(col2); + + url_table_ = new views::TableView(url_table_model_.get(), cols, + views::ICON_AND_TEXT, true, true, + true); + url_table_->SetObserver(this); + + // Yummy layout code. + GridLayout* layout = CreatePanelGridLayout(this); + SetLayoutManager(layout); + + const int labels_column_set_id = 0; + const int single_column_view_set_id = 1; + + ColumnSet* column_set = layout->AddColumnSet(labels_column_set_id); + column_set->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 0, + GridLayout::USE_PREF, 0, 0); + column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing); + column_set->AddColumn(GridLayout::FILL, GridLayout::CENTER, 1, + GridLayout::USE_PREF, 0, 0); + + column_set = layout->AddColumnSet(single_column_view_set_id); + column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1, + GridLayout::FIXED, kTableWidth, 0); + + if (show_title) { + layout->StartRow(0, labels_column_set_id); + views::Label* title_label = new views::Label(); + title_label->SetHorizontalAlignment(views::Label::ALIGN_LEFT); + title_label->SetText(l10n_util::GetString(IDS_ASI_TITLE_LABEL)); + layout->AddView(title_label); + + title_field_ = new views::Textfield(); + title_field_->SetController(this); + layout->AddView(title_field_); + + layout->AddPaddingRow(0, kRelatedControlVerticalSpacing); + } else { + title_field_ = NULL; + } + + layout->StartRow(0, labels_column_set_id); + views::Label* url_label = new views::Label(); + url_label->SetHorizontalAlignment(views::Label::ALIGN_LEFT); + url_label->SetText(l10n_util::GetString(IDS_ASI_URL)); + layout->AddView(url_label); + + url_field_ = new views::Textfield(); + url_field_->SetController(this); + layout->AddView(url_field_); + + layout->AddPaddingRow(0, kUnrelatedControlVerticalSpacing); + + layout->StartRow(0, single_column_view_set_id); + views::Label* description_label = new views::Label(); + description_label->SetHorizontalAlignment(views::Label::ALIGN_LEFT); + description_label->SetText(l10n_util::GetString(IDS_ASI_DESCRIPTION)); + description_label->SetFont( + description_label->GetFont().DeriveFont(0, gfx::Font::BOLD)); + layout->AddView(description_label); + + layout->AddPaddingRow(0, kRelatedControlVerticalSpacing); + + layout->StartRow(1, single_column_view_set_id); + layout->AddView(url_table_); + + layout->AddPaddingRow(0, kRelatedControlVerticalSpacing); + + AddAccelerator(views::Accelerator(VK_RETURN, false, false, false)); +} + +UrlPicker::~UrlPicker() { + url_table_->SetModel(NULL); +} + +void UrlPicker::Show(HWND parent) { + DCHECK(!window()); + views::Window::CreateChromeWindow(parent, gfx::Rect(), this)->Show(); + if (title_field_) { + title_field_->SetText(l10n_util::GetString(IDS_ASI_DEFAULT_TITLE)); + title_field_->SelectAll(); + title_field_->RequestFocus(); + } else { + url_field_->SelectAll(); + url_field_->RequestFocus(); + } + url_table_model_->Reload(profile_); +} + +void UrlPicker::Close() { + DCHECK(window()); + window()->Close(); +} + +std::wstring UrlPicker::GetWindowTitle() const { + return l10n_util::GetString(IDS_ASI_ADD_TITLE); +} + +bool UrlPicker::IsModal() const { + return true; +} + +std::wstring UrlPicker::GetDialogButtonLabel( + MessageBoxFlags::DialogButton button) const { + if (button == MessageBoxFlags::DIALOGBUTTON_OK) + return l10n_util::GetString(IDS_ASI_ADD); + return std::wstring(); +} + +void UrlPicker::OnURLInfoAvailable( + HistoryService::Handle handle, + bool success, + const history::URLRow* info, + history::VisitVector* unused) { + if (handle != expected_title_handle_) + return; + + std::wstring s; + if (success) + s = info->title(); + if (s.empty()) + s = l10n_util::GetString(IDS_ASI_DEFAULT_TITLE); + + if (title_field_) { + // expected_title_handle_ is reset if the title Textfield is edited so we + // can safely set the value. + title_field_->SetText(s); + title_field_->SelectAll(); + } + expected_title_handle_ = 0; +} + +void UrlPicker::InitiateTitleAutoFill(const GURL& url) { + HistoryService* hs = profile_->GetHistoryService(Profile::EXPLICIT_ACCESS); + if (!hs) + return; + + if (expected_title_handle_) + hs->CancelRequest(expected_title_handle_); + + expected_title_handle_ = hs->QueryURL(url, false, &history_consumer_, + NewCallback(this, &UrlPicker::OnURLInfoAvailable)); +} + +void UrlPicker::ContentsChanged(views::Textfield* sender, + const std::wstring& new_contents) { + // If the user has edited the title field we no longer want to autofill it + // so we reset the expected handle to an impossible value. + if (sender == title_field_) + expected_title_handle_ = 0; + GetDialogClientView()->UpdateDialogButtons(); +} + +bool UrlPicker::Accept() { + if (!IsDialogButtonEnabled(MessageBoxFlags::DIALOGBUTTON_OK)) { + if (!GetInputURL().is_valid()) + url_field_->RequestFocus(); + else if (title_field_) + title_field_->RequestFocus(); + return false; + } + PerformModelChange(); + return true; +} + +int UrlPicker::GetDefaultDialogButton() const { + // Don't set a default button, this view already has an accelerator for the + // enter key. + return MessageBoxFlags::DIALOGBUTTON_NONE; +} + +bool UrlPicker::IsDialogButtonEnabled( + MessageBoxFlags::DialogButton button) const { + if (button == MessageBoxFlags::DIALOGBUTTON_OK) + return GetInputURL().is_valid(); + return true; +} + +views::View* UrlPicker::GetContentsView() { + return this; +} + +void UrlPicker::PerformModelChange() { + DCHECK(delegate_); + GURL url(GetInputURL()); + const std::wstring title = + title_field_ ? title_field_->text() : std::wstring(); + delegate_->AddBookmark(this, title, url); +} + +gfx::Size UrlPicker::GetPreferredSize() { + return gfx::Size(views::Window::GetLocalizedContentsSize( + IDS_SHELFITEM_DIALOG_WIDTH_CHARS, + IDS_SHELFITEM_DIALOG_HEIGHT_LINES)); +} + +bool UrlPicker::AcceleratorPressed( + const views::Accelerator& accelerator) { + if (accelerator.GetKeyCode() == VK_ESCAPE) { + window()->Close(); + } else if (accelerator.GetKeyCode() == VK_RETURN) { + views::FocusManager* fm = GetFocusManager(); + if (fm->GetFocusedView() == url_table_) { + // Return on table behaves like a double click. + OnDoubleClick(); + } else if (fm->GetFocusedView()== url_field_) { + // Return on the url field accepts the input if url is valid. If the URL + // is invalid, focus is left on the url field. + if (GetInputURL().is_valid()) { + PerformModelChange(); + if (window()) + window()->Close(); + } else { + url_field_->SelectAll(); + } + } else if (title_field_ && fm->GetFocusedView() == title_field_) { + url_field_->SelectAll(); + url_field_->RequestFocus(); + } + } + return true; +} + +void UrlPicker::OnSelectionChanged() { + int selection = url_table_->FirstSelectedRow(); + if (selection >= 0 && selection < url_table_model_->RowCount()) { + std::wstring languages = + profile_->GetPrefs()->GetString(prefs::kAcceptLanguages); + // Because the url_field_ is user-editable, we set the URL with + // username:password and escaped path and query. + std::wstring formatted = net::FormatUrl( + url_table_model_->GetURL(selection), languages, + false, UnescapeRule::NONE, NULL, NULL); + url_field_->SetText(formatted); + if (title_field_) + title_field_->SetText(url_table_model_->GetTitle(selection)); + GetDialogClientView()->UpdateDialogButtons(); + } +} + +void UrlPicker::OnDoubleClick() { + int selection = url_table_->FirstSelectedRow(); + if (selection >= 0 && selection < url_table_model_->RowCount()) { + OnSelectionChanged(); + PerformModelChange(); + if (window()) + window()->Close(); + } +} + +GURL UrlPicker::GetInputURL() const { + return GURL(URLFixerUpper::FixupURL(url_field_->text(), L"")); +} diff --git a/chrome/browser/views/url_picker.h b/chrome/browser/views/url_picker.h new file mode 100644 index 0000000..13376ba --- /dev/null +++ b/chrome/browser/views/url_picker.h @@ -0,0 +1,131 @@ +// 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_VIEWS_URL_PICKER_H_ +#define CHROME_BROWSER_VIEWS_URL_PICKER_H_ + +#include "chrome/browser/cancelable_request.h" +#include "chrome/browser/history/history.h" +#include "views/controls/button/native_button.h" +#include "views/controls/table/table_view_observer.h" +#include "views/controls/textfield/textfield.h" +#include "views/view.h" +#include "views/window/dialog_delegate.h" +#include "views/window/window.h" + +namespace views { +class Button; +class Label; +class TableView; +} + +class PossibleURLModel; +class Profile; +class UrlPicker; + +// UrlPicker delegate. Notified when the user accepts the entry. +class UrlPickerDelegate { + public: + virtual ~UrlPickerDelegate(); + + virtual void AddBookmark(UrlPicker* dialog, + const std::wstring& title, + const GURL& url) = 0; +}; + +//////////////////////////////////////////////////////////////////////////////// +// +// This class implements the dialog that let the user add a bookmark or page +// to the list of urls to open on startup. +// UrlPicker deletes itself when the dialog is closed. +// +//////////////////////////////////////////////////////////////////////////////// +class UrlPicker : public views::View, + public views::DialogDelegate, + public views::Textfield::Controller, + public views::TableViewObserver { + public: + UrlPicker(UrlPickerDelegate* delegate, + Profile* profile, + bool show_title); + virtual ~UrlPicker(); + + // Show the dialog on the provided contents. + virtual void Show(HWND parent); + + // Closes the dialog. + void Close(); + + // DialogDelegate. + virtual std::wstring GetWindowTitle() const; + virtual bool IsModal() const; + virtual std::wstring GetDialogButtonLabel( + MessageBoxFlags::DialogButton button) const; + virtual bool Accept(); + virtual int GetDefaultDialogButton() const; + virtual bool IsDialogButtonEnabled( + MessageBoxFlags::DialogButton button) const; + virtual views::View* GetContentsView(); + + // TextField::Controller. + virtual void ContentsChanged(views::Textfield* sender, + const std::wstring& new_contents); + virtual bool HandleKeystroke(views::Textfield* sender, + const views::Textfield::Keystroke& key) { + return false; + } + + // Overridden from View. + virtual gfx::Size GetPreferredSize(); + virtual bool AcceleratorPressed(const views::Accelerator& accelerator); + + // TableViewObserver. + virtual void OnSelectionChanged(); + virtual void OnDoubleClick(); + + private: + // Modify the model from the user interface. + void PerformModelChange(); + + // Fetch the title for the entered URL. If we get the title in time before + // the user starts to modify the title field, the title field is changed. + void InitiateTitleAutoFill(const GURL& url); + + // Invoked by the history system when a title becomes available. + void OnURLInfoAvailable(HistoryService::Handle handle, + bool success, + const history::URLRow* info, + history::VisitVector* unused); + + // Returns the URL the user has typed. + GURL GetInputURL() const; + + // Profile. + Profile* profile_; + + // URL Field. + views::Textfield* url_field_; + + // Title field. This is NULL if we're not showing the title. + views::Textfield* title_field_; + + // The table model. + scoped_ptr<PossibleURLModel> url_table_model_; + + // The table of visited urls. + views::TableView* url_table_; + + // Handle of the title request we are expecting. + CancelableRequestProvider::Handle expected_title_handle_; + + // The consumer object for the history database. + CancelableRequestConsumer history_consumer_; + + // The delegate. + UrlPickerDelegate* delegate_; + + DISALLOW_COPY_AND_ASSIGN(UrlPicker); +}; + +#endif // CHROME_BROWSER_VIEWS_URL_PICKER_H_ diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp index 6b59d03..f1d5200 100644 --- a/chrome/chrome.gyp +++ b/chrome/chrome.gyp @@ -1858,8 +1858,6 @@ 'browser/views/sad_tab_view.h', 'browser/views/select_profile_dialog.cc', 'browser/views/select_profile_dialog.h', - 'browser/views/shelf_item_dialog.cc', - 'browser/views/shelf_item_dialog.h', 'browser/views/shell_dialogs_win.cc', 'browser/views/star_toggle.cc', 'browser/views/star_toggle.h', @@ -1932,6 +1930,8 @@ 'browser/views/toolbar_view.h', 'browser/views/uninstall_dialog.cc', 'browser/views/uninstall_dialog.h', + 'browser/views/url_picker.cc', + 'browser/views/url_picker.h', 'browser/views/user_data_dir_dialog.cc', 'browser/views/user_data_dir_dialog.h', 'browser/visitedlink_master.cc', |