| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/ui/views/bookmarks/bookmark_bubble_view.h" | 5 #include "chrome/browser/ui/views/bookmarks/bookmark_bubble_view.h" |
| 6 | 6 |
| 7 #include <utility> | |
| 8 | |
| 9 #include "base/macros.h" | |
| 10 #include "base/metrics/user_metrics.h" | 7 #include "base/metrics/user_metrics.h" |
| 11 #include "base/strings/string16.h" | |
| 12 #include "base/strings/string_util.h" | 8 #include "base/strings/string_util.h" |
| 13 #include "base/strings/utf_string_conversions.h" | 9 #include "base/strings/utf_string_conversions.h" |
| 14 #include "chrome/app/chrome_command_ids.h" | |
| 15 #include "chrome/browser/bookmarks/bookmark_model_factory.h" | 10 #include "chrome/browser/bookmarks/bookmark_model_factory.h" |
| 16 #include "chrome/browser/platform_util.h" | 11 #include "chrome/browser/platform_util.h" |
| 17 #include "chrome/browser/profiles/profile.h" | 12 #include "chrome/browser/profiles/profile.h" |
| 18 #include "chrome/browser/ui/bookmarks/bookmark_bubble_observer.h" | 13 #include "chrome/browser/ui/bookmarks/bookmark_bubble_observer.h" |
| 19 #include "chrome/browser/ui/bookmarks/bookmark_editor.h" | 14 #include "chrome/browser/ui/bookmarks/bookmark_editor.h" |
| 20 #include "chrome/browser/ui/browser_dialogs.h" | 15 #include "chrome/browser/ui/browser_dialogs.h" |
| 21 #include "chrome/browser/ui/sync/sync_promo_ui.h" | 16 #include "chrome/browser/ui/sync/sync_promo_ui.h" |
| 22 #include "chrome/browser/ui/views/harmony/chrome_layout_provider.h" | 17 #include "chrome/browser/ui/views/harmony/chrome_layout_provider.h" |
| 23 #include "chrome/browser/ui/views/sync/bubble_sync_promo_view.h" | 18 #include "chrome/browser/ui/views/sync/bubble_sync_promo_view.h" |
| 24 #include "chrome/grit/chromium_strings.h" | 19 #include "chrome/grit/chromium_strings.h" |
| 25 #include "chrome/grit/generated_resources.h" | 20 #include "chrome/grit/generated_resources.h" |
| 26 #include "components/bookmarks/browser/bookmark_model.h" | 21 #include "components/bookmarks/browser/bookmark_model.h" |
| 27 #include "components/bookmarks/browser/bookmark_utils.h" | 22 #include "components/bookmarks/browser/bookmark_utils.h" |
| 28 #include "components/strings/grit/components_strings.h" | 23 #include "components/strings/grit/components_strings.h" |
| 29 #include "ui/accessibility/ax_node_data.h" | 24 #include "ui/accessibility/ax_node_data.h" |
| 30 #include "ui/base/l10n/l10n_util.h" | 25 #include "ui/base/l10n/l10n_util.h" |
| 31 #include "ui/events/keycodes/keyboard_codes.h" | 26 #include "ui/events/keycodes/keyboard_codes.h" |
| 32 #include "ui/views/bubble/bubble_frame_view.h" | |
| 33 #include "ui/views/controls/button/md_text_button.h" | 27 #include "ui/views/controls/button/md_text_button.h" |
| 34 #include "ui/views/controls/combobox/combobox.h" | 28 #include "ui/views/controls/combobox/combobox.h" |
| 35 #include "ui/views/controls/label.h" | 29 #include "ui/views/controls/label.h" |
| 36 #include "ui/views/controls/link.h" | |
| 37 #include "ui/views/controls/textfield/textfield.h" | 30 #include "ui/views/controls/textfield/textfield.h" |
| 38 #include "ui/views/layout/fill_layout.h" | 31 #include "ui/views/layout/fill_layout.h" |
| 39 #include "ui/views/layout/grid_layout.h" | 32 #include "ui/views/layout/grid_layout.h" |
| 40 #include "ui/views/widget/widget.h" | 33 #include "ui/views/widget/widget.h" |
| 41 | 34 |
| 42 #if defined(OS_WIN) | 35 #if defined(OS_WIN) |
| 43 #include "chrome/browser/sync/profile_sync_service_factory.h" | 36 #include "chrome/browser/sync/profile_sync_service_factory.h" |
| 44 #include "chrome/browser/ui/views/desktop_ios_promotion/desktop_ios_promotion_bu
bble_view.h" | 37 #include "chrome/browser/ui/views/desktop_ios_promotion/desktop_ios_promotion_bu
bble_view.h" |
| 45 #include "chrome/browser/ui/views/desktop_ios_promotion/desktop_ios_promotion_fo
otnote_view.h" | 38 #include "chrome/browser/ui/views/desktop_ios_promotion/desktop_ios_promotion_fo
otnote_view.h" |
| 46 #include "components/browser_sync/profile_sync_service.h" | 39 #include "components/browser_sync/profile_sync_service.h" |
| 47 #endif | 40 #endif |
| 48 | 41 |
| 49 using base::UserMetricsAction; | 42 using base::UserMetricsAction; |
| 50 using bookmarks::BookmarkModel; | 43 using bookmarks::BookmarkModel; |
| 51 using bookmarks::BookmarkNode; | 44 using bookmarks::BookmarkNode; |
| 52 using views::ColumnSet; | 45 using views::ColumnSet; |
| 53 using views::GridLayout; | 46 using views::GridLayout; |
| 54 | 47 |
| 55 namespace { | 48 namespace { |
| 56 | 49 |
| 57 // This combobox prevents any lengthy content from stretching the bubble view. | 50 // This combobox prevents any lengthy content from stretching the bubble view. |
| 58 class UnsizedCombobox : public views::Combobox { | 51 class UnsizedCombobox : public views::Combobox { |
| 59 public: | 52 public: |
| 60 explicit UnsizedCombobox(ui::ComboboxModel* model) : views::Combobox(model) {} | 53 explicit UnsizedCombobox(ui::ComboboxModel* model) : views::Combobox(model) {} |
| 61 ~UnsizedCombobox() override {} | 54 ~UnsizedCombobox() override {} |
| 62 | 55 |
| 56 // views::Combobox: |
| 63 gfx::Size GetPreferredSize() const override { | 57 gfx::Size GetPreferredSize() const override { |
| 64 return gfx::Size(0, views::Combobox::GetPreferredSize().height()); | 58 return gfx::Size(0, views::Combobox::GetPreferredSize().height()); |
| 65 } | 59 } |
| 66 | 60 |
| 67 private: | 61 private: |
| 68 DISALLOW_COPY_AND_ASSIGN(UnsizedCombobox); | 62 DISALLOW_COPY_AND_ASSIGN(UnsizedCombobox); |
| 69 }; | 63 }; |
| 70 | 64 |
| 71 } // namespace | 65 } // namespace |
| 72 | 66 |
| 73 BookmarkBubbleView* BookmarkBubbleView::bookmark_bubble_ = NULL; | 67 BookmarkBubbleView* BookmarkBubbleView::bookmark_bubble_ = nullptr; |
| 74 | 68 |
| 75 // static | 69 // static |
| 76 views::Widget* BookmarkBubbleView::ShowBubble( | 70 views::Widget* BookmarkBubbleView::ShowBubble( |
| 77 views::View* anchor_view, | 71 views::View* anchor_view, |
| 78 const gfx::Rect& anchor_rect, | 72 const gfx::Rect& anchor_rect, |
| 79 gfx::NativeView parent_window, | 73 gfx::NativeView parent_window, |
| 80 bookmarks::BookmarkBubbleObserver* observer, | 74 bookmarks::BookmarkBubbleObserver* observer, |
| 81 std::unique_ptr<BubbleSyncPromoDelegate> delegate, | 75 std::unique_ptr<BubbleSyncPromoDelegate> delegate, |
| 82 Profile* profile, | 76 Profile* profile, |
| 83 const GURL& url, | 77 const GURL& url, |
| 84 bool already_bookmarked) { | 78 bool already_bookmarked) { |
| 85 if (bookmark_bubble_) | 79 if (bookmark_bubble_) |
| 86 return nullptr; | 80 return nullptr; |
| 87 | 81 |
| 88 bookmark_bubble_ = | 82 bookmark_bubble_ = |
| 89 new BookmarkBubbleView(anchor_view, observer, std::move(delegate), | 83 new BookmarkBubbleView(anchor_view, observer, std::move(delegate), |
| 90 profile, url, !already_bookmarked); | 84 profile, url, !already_bookmarked); |
| 91 // Bookmark bubble should always anchor TOP_RIGHT, but the | 85 // Bookmark bubble should always anchor TOP_RIGHT, but the |
| 92 // LocationBarBubbleDelegateView does not know that and may use different | 86 // LocationBarBubbleDelegateView does not know that and may use different |
| 93 // arrow anchoring. | 87 // arrow anchoring. |
| 94 bookmark_bubble_->set_arrow(views::BubbleBorder::TOP_RIGHT); | 88 bookmark_bubble_->set_arrow(views::BubbleBorder::TOP_RIGHT); |
| 95 if (!anchor_view) { | 89 if (!anchor_view) { |
| 96 bookmark_bubble_->SetAnchorRect(anchor_rect); | 90 bookmark_bubble_->SetAnchorRect(anchor_rect); |
| 97 bookmark_bubble_->set_parent_window(parent_window); | 91 bookmark_bubble_->set_parent_window(parent_window); |
| 98 } | 92 } |
| 99 views::Widget* bubble_widget = | 93 views::Widget* bubble_widget = |
| 100 views::BubbleDialogDelegateView::CreateBubble(bookmark_bubble_); | 94 views::BubbleDialogDelegateView::CreateBubble(bookmark_bubble_); |
| 101 bubble_widget->Show(); | 95 bubble_widget->Show(); |
| 102 // Select the entire title textfield contents when the bubble is first shown. | 96 // Select the entire title textfield contents when the bubble is first shown. |
| 103 bookmark_bubble_->title_tf_->SelectAll(true); | 97 bookmark_bubble_->name_field_->SelectAll(true); |
| 104 bookmark_bubble_->SetArrowPaintType(views::BubbleBorder::PAINT_TRANSPARENT); | 98 bookmark_bubble_->SetArrowPaintType(views::BubbleBorder::PAINT_TRANSPARENT); |
| 105 | 99 |
| 106 if (bookmark_bubble_->observer_) { | 100 if (bookmark_bubble_->observer_) { |
| 107 BookmarkModel* model = BookmarkModelFactory::GetForBrowserContext(profile); | 101 BookmarkModel* model = BookmarkModelFactory::GetForBrowserContext(profile); |
| 108 const BookmarkNode* node = model->GetMostRecentlyAddedUserNodeForURL(url); | 102 const BookmarkNode* node = model->GetMostRecentlyAddedUserNodeForURL(url); |
| 109 bookmark_bubble_->observer_->OnBookmarkBubbleShown(node); | 103 bookmark_bubble_->observer_->OnBookmarkBubbleShown(node); |
| 110 } | 104 } |
| 111 return bubble_widget; | 105 return bubble_widget; |
| 112 } | 106 } |
| 113 | 107 |
| 108 // static |
| 114 void BookmarkBubbleView::Hide() { | 109 void BookmarkBubbleView::Hide() { |
| 115 if (bookmark_bubble_) | 110 if (bookmark_bubble_) |
| 116 bookmark_bubble_->GetWidget()->Close(); | 111 bookmark_bubble_->GetWidget()->Close(); |
| 117 } | 112 } |
| 118 | 113 |
| 119 BookmarkBubbleView::~BookmarkBubbleView() { | 114 BookmarkBubbleView::~BookmarkBubbleView() { |
| 120 if (apply_edits_) { | 115 if (apply_edits_) { |
| 121 ApplyEdits(); | 116 ApplyEdits(); |
| 122 } else if (remove_bookmark_) { | 117 } else if (remove_bookmark_) { |
| 123 BookmarkModel* model = BookmarkModelFactory::GetForBrowserContext(profile_); | 118 BookmarkModel* model = BookmarkModelFactory::GetForBrowserContext(profile_); |
| 124 const BookmarkNode* node = model->GetMostRecentlyAddedUserNodeForURL(url_); | 119 const BookmarkNode* node = model->GetMostRecentlyAddedUserNodeForURL(url_); |
| 125 if (node) | 120 if (node) |
| 126 model->Remove(node); | 121 model->Remove(node); |
| 127 } | 122 } |
| 128 // |parent_combobox_| needs to be destroyed before |parent_model_| as it | 123 // |parent_combobox_| needs to be destroyed before |parent_model_| as it |
| 129 // uses |parent_model_| in its destructor. | 124 // uses |parent_model_| in its destructor. |
| 130 delete parent_combobox_; | 125 delete parent_combobox_; |
| 131 } | 126 } |
| 132 | 127 |
| 133 void BookmarkBubbleView::WindowClosing() { | 128 // Private methods ------------------------------------------------------------- |
| 134 // We have to reset |bubble_| here, not in our destructor, because we'll be | |
| 135 // destroyed asynchronously and the shown state will be checked before then. | |
| 136 DCHECK_EQ(bookmark_bubble_, this); | |
| 137 bookmark_bubble_ = NULL; | |
| 138 is_showing_ios_promotion_ = false; | |
| 139 | |
| 140 if (observer_) | |
| 141 observer_->OnBookmarkBubbleHidden(); | |
| 142 } | |
| 143 | |
| 144 bool BookmarkBubbleView::AcceleratorPressed( | |
| 145 const ui::Accelerator& accelerator) { | |
| 146 ui::KeyboardCode key_code = accelerator.key_code(); | |
| 147 if (key_code == ui::VKEY_RETURN) { | |
| 148 HandleButtonPressed(close_button_); | |
| 149 return true; | |
| 150 } | |
| 151 if (key_code == ui::VKEY_E && accelerator.IsAltDown()) { | |
| 152 HandleButtonPressed(edit_button_); | |
| 153 return true; | |
| 154 } | |
| 155 if (key_code == ui::VKEY_R && accelerator.IsAltDown()) { | |
| 156 HandleButtonPressed(remove_button_); | |
| 157 return true; | |
| 158 } | |
| 159 | |
| 160 return LocationBarBubbleDelegateView::AcceleratorPressed(accelerator); | |
| 161 } | |
| 162 | |
| 163 void BookmarkBubbleView::Init() { | |
| 164 remove_button_ = views::MdTextButton::CreateSecondaryUiButton( | |
| 165 this, l10n_util::GetStringUTF16(IDS_BOOKMARK_BUBBLE_REMOVE_BOOKMARK)); | |
| 166 | |
| 167 edit_button_ = views::MdTextButton::CreateSecondaryUiButton( | |
| 168 this, l10n_util::GetStringUTF16(IDS_BOOKMARK_BUBBLE_OPTIONS)); | |
| 169 | |
| 170 close_button_ = views::MdTextButton::CreateSecondaryUiButton( | |
| 171 this, l10n_util::GetStringUTF16(IDS_DONE)); | |
| 172 close_button_->SetIsDefault(true); | |
| 173 | |
| 174 views::Label* combobox_label = new views::Label( | |
| 175 l10n_util::GetStringUTF16(IDS_BOOKMARK_BUBBLE_FOLDER_TEXT)); | |
| 176 | |
| 177 parent_combobox_ = new UnsizedCombobox(&parent_model_); | |
| 178 parent_combobox_->set_listener(this); | |
| 179 parent_combobox_->SetAccessibleName( | |
| 180 l10n_util::GetStringUTF16(IDS_BOOKMARK_AX_BUBBLE_FOLDER_TEXT)); | |
| 181 | |
| 182 SetLayoutManager(new views::FillLayout); | |
| 183 bookmark_details_view_ = base::MakeUnique<View>(); | |
| 184 GridLayout* layout = new GridLayout(bookmark_details_view_.get()); | |
| 185 bookmark_details_view_->SetLayoutManager(layout); | |
| 186 | |
| 187 // This column set is used for the labels and textfields as well as the | |
| 188 // buttons at the bottom. | |
| 189 const int cs_id = 0; | |
| 190 ColumnSet* cs = layout->AddColumnSet(cs_id); | |
| 191 ChromeLayoutProvider* provider = ChromeLayoutProvider::Get(); | |
| 192 | |
| 193 cs->AddColumn(provider->GetControlLabelGridAlignment(), GridLayout::CENTER, 0, | |
| 194 GridLayout::USE_PREF, 0, 0); | |
| 195 cs->AddPaddingColumn( | |
| 196 0, provider->GetDistanceMetric(DISTANCE_UNRELATED_CONTROL_HORIZONTAL)); | |
| 197 | |
| 198 cs->AddColumn(GridLayout::FILL, GridLayout::CENTER, 0, | |
| 199 GridLayout::USE_PREF, 0, 0); | |
| 200 cs->AddPaddingColumn(1, provider->GetDistanceMetric( | |
| 201 DISTANCE_UNRELATED_CONTROL_HORIZONTAL_LARGE)); | |
| 202 | |
| 203 cs->AddColumn(GridLayout::LEADING, GridLayout::TRAILING, 0, | |
| 204 GridLayout::USE_PREF, 0, 0); | |
| 205 cs->AddPaddingColumn(0, provider->GetDistanceMetric( | |
| 206 views::DISTANCE_RELATED_BUTTON_HORIZONTAL)); | |
| 207 cs->AddColumn(GridLayout::LEADING, GridLayout::TRAILING, 0, | |
| 208 GridLayout::USE_PREF, 0, 0); | |
| 209 | |
| 210 layout->StartRow(0, cs_id); | |
| 211 views::Label* label = new views::Label( | |
| 212 l10n_util::GetStringUTF16(IDS_BOOKMARK_BUBBLE_TITLE_TEXT)); | |
| 213 layout->AddView(label); | |
| 214 title_tf_ = new views::Textfield(); | |
| 215 title_tf_->SetText(GetTitle()); | |
| 216 title_tf_->SetAccessibleName( | |
| 217 l10n_util::GetStringUTF16(IDS_BOOKMARK_AX_BUBBLE_TITLE_TEXT)); | |
| 218 | |
| 219 layout->AddView(title_tf_, 5, 1); | |
| 220 | |
| 221 layout->AddPaddingRow( | |
| 222 0, provider->GetInsetsMetric(views::INSETS_DIALOG_CONTENTS).top()); | |
| 223 | |
| 224 layout->StartRow(0, cs_id); | |
| 225 layout->AddView(combobox_label); | |
| 226 layout->AddView(parent_combobox_, 5, 1); | |
| 227 | |
| 228 layout->AddPaddingRow( | |
| 229 0, provider->GetDistanceMetric(views::DISTANCE_RELATED_CONTROL_VERTICAL)); | |
| 230 | |
| 231 layout->StartRow(0, cs_id); | |
| 232 layout->SkipColumns(2); | |
| 233 layout->AddView(remove_button_); | |
| 234 layout->AddView(edit_button_); | |
| 235 layout->AddView(close_button_); | |
| 236 | |
| 237 AddAccelerator(ui::Accelerator(ui::VKEY_RETURN, ui::EF_NONE)); | |
| 238 AddAccelerator(ui::Accelerator(ui::VKEY_E, ui::EF_ALT_DOWN)); | |
| 239 AddAccelerator(ui::Accelerator(ui::VKEY_R, ui::EF_ALT_DOWN)); | |
| 240 | |
| 241 AddChildView(bookmark_details_view_.get()); | |
| 242 } | |
| 243 | |
| 244 gfx::ImageSkia BookmarkBubbleView::GetWindowIcon() { | |
| 245 #if defined(OS_WIN) | |
| 246 if (is_showing_ios_promotion_) { | |
| 247 return desktop_ios_promotion::GetPromoImage( | |
| 248 GetNativeTheme()->GetSystemColor( | |
| 249 ui::NativeTheme::kColorId_TextfieldDefaultColor)); | |
| 250 } | |
| 251 #endif | |
| 252 return gfx::ImageSkia(); | |
| 253 } | |
| 254 | |
| 255 bool BookmarkBubbleView::ShouldShowWindowIcon() const { | |
| 256 return is_showing_ios_promotion_; | |
| 257 } | |
| 258 | |
| 259 base::string16 BookmarkBubbleView::GetWindowTitle() const { | |
| 260 #if defined(OS_WIN) | |
| 261 if (is_showing_ios_promotion_) { | |
| 262 return desktop_ios_promotion::GetPromoTitle( | |
| 263 desktop_ios_promotion::PromotionEntryPoint::BOOKMARKS_BUBBLE); | |
| 264 } | |
| 265 #endif | |
| 266 return l10n_util::GetStringUTF16(newly_bookmarked_ | |
| 267 ? IDS_BOOKMARK_BUBBLE_PAGE_BOOKMARKED | |
| 268 : IDS_BOOKMARK_BUBBLE_PAGE_BOOKMARK); | |
| 269 } | |
| 270 | |
| 271 const char* BookmarkBubbleView::GetClassName() const { | |
| 272 return "BookmarkBubbleView"; | |
| 273 } | |
| 274 | |
| 275 views::View* BookmarkBubbleView::GetInitiallyFocusedView() { | |
| 276 return title_tf_; | |
| 277 } | |
| 278 | |
| 279 views::View* BookmarkBubbleView::CreateFootnoteView() { | |
| 280 #if defined(OS_WIN) | |
| 281 if (!is_showing_ios_promotion_ && | |
| 282 IsIOSPromotionEligible( | |
| 283 desktop_ios_promotion::PromotionEntryPoint::BOOKMARKS_FOOTNOTE)) { | |
| 284 footnote_view_ = new DesktopIOSPromotionFootnoteView(profile_, this); | |
| 285 return footnote_view_; | |
| 286 } | |
| 287 #endif | |
| 288 if (!SyncPromoUI::ShouldShowSyncPromo(profile_)) | |
| 289 return nullptr; | |
| 290 | |
| 291 base::RecordAction( | |
| 292 base::UserMetricsAction("Signin_Impression_FromBookmarkBubble")); | |
| 293 | |
| 294 footnote_view_ = | |
| 295 new BubbleSyncPromoView(delegate_.get(), IDS_BOOKMARK_SYNC_PROMO_LINK, | |
| 296 IDS_BOOKMARK_SYNC_PROMO_MESSAGE); | |
| 297 return footnote_view_; | |
| 298 } | |
| 299 | 129 |
| 300 BookmarkBubbleView::BookmarkBubbleView( | 130 BookmarkBubbleView::BookmarkBubbleView( |
| 301 views::View* anchor_view, | 131 views::View* anchor_view, |
| 302 bookmarks::BookmarkBubbleObserver* observer, | 132 bookmarks::BookmarkBubbleObserver* observer, |
| 303 std::unique_ptr<BubbleSyncPromoDelegate> delegate, | 133 std::unique_ptr<BubbleSyncPromoDelegate> delegate, |
| 304 Profile* profile, | 134 Profile* profile, |
| 305 const GURL& url, | 135 const GURL& url, |
| 306 bool newly_bookmarked) | 136 bool newly_bookmarked) |
| 307 : LocationBarBubbleDelegateView(anchor_view, nullptr), | 137 : LocationBarBubbleDelegateView(anchor_view, nullptr), |
| 308 observer_(observer), | 138 observer_(observer), |
| 309 delegate_(std::move(delegate)), | 139 delegate_(std::move(delegate)), |
| 310 profile_(profile), | 140 profile_(profile), |
| 311 url_(url), | 141 url_(url), |
| 312 newly_bookmarked_(newly_bookmarked), | 142 newly_bookmarked_(newly_bookmarked), |
| 313 parent_model_(BookmarkModelFactory::GetForBrowserContext(profile_), | 143 parent_model_(BookmarkModelFactory::GetForBrowserContext(profile_), |
| 314 BookmarkModelFactory::GetForBrowserContext(profile_) | 144 BookmarkModelFactory::GetForBrowserContext(profile_) |
| 315 ->GetMostRecentlyAddedUserNodeForURL(url)), | 145 ->GetMostRecentlyAddedUserNodeForURL(url)), |
| 316 remove_button_(nullptr), | 146 remove_button_(nullptr), |
| 317 edit_button_(nullptr), | 147 edit_button_(nullptr), |
| 318 close_button_(nullptr), | 148 save_button_(nullptr), |
| 319 title_tf_(nullptr), | 149 name_field_(nullptr), |
| 320 parent_combobox_(nullptr), | 150 parent_combobox_(nullptr), |
| 321 ios_promo_view_(nullptr), | 151 ios_promo_view_(nullptr), |
| 322 footnote_view_(nullptr), | 152 footnote_view_(nullptr), |
| 323 remove_bookmark_(false), | 153 remove_bookmark_(false), |
| 324 apply_edits_(true), | 154 apply_edits_(true), |
| 325 is_showing_ios_promotion_(false) { | 155 is_showing_ios_promotion_(false) { |
| 326 chrome::RecordDialogCreation(chrome::DialogIdentifier::BOOKMARK); | 156 chrome::RecordDialogCreation(chrome::DialogIdentifier::BOOKMARK); |
| 327 } | 157 } |
| 328 | 158 |
| 329 base::string16 BookmarkBubbleView::GetTitle() { | 159 base::string16 BookmarkBubbleView::GetBookmarkName() { |
| 330 BookmarkModel* bookmark_model = | 160 BookmarkModel* bookmark_model = |
| 331 BookmarkModelFactory::GetForBrowserContext(profile_); | 161 BookmarkModelFactory::GetForBrowserContext(profile_); |
| 332 const BookmarkNode* node = | 162 const BookmarkNode* node = |
| 333 bookmark_model->GetMostRecentlyAddedUserNodeForURL(url_); | 163 bookmark_model->GetMostRecentlyAddedUserNodeForURL(url_); |
| 334 if (node) | 164 if (node) |
| 335 return node->GetTitle(); | 165 return node->GetTitle(); |
| 336 else | 166 else |
| 337 NOTREACHED(); | 167 NOTREACHED(); |
| 338 return base::string16(); | 168 return base::string16(); |
| 339 } | 169 } |
| 340 | 170 |
| 341 void BookmarkBubbleView::GetAccessibleNodeData(ui::AXNodeData* node_data) { | |
| 342 LocationBarBubbleDelegateView::GetAccessibleNodeData(node_data); | |
| 343 node_data->SetName(l10n_util::GetStringUTF8( | |
| 344 newly_bookmarked_ ? IDS_BOOKMARK_BUBBLE_PAGE_BOOKMARKED | |
| 345 : IDS_BOOKMARK_AX_BUBBLE_PAGE_BOOKMARK)); | |
| 346 } | |
| 347 | |
| 348 void BookmarkBubbleView::ButtonPressed(views::Button* sender, | |
| 349 const ui::Event& event) { | |
| 350 HandleButtonPressed(sender); | |
| 351 } | |
| 352 | |
| 353 void BookmarkBubbleView::OnPerformAction(views::Combobox* combobox) { | |
| 354 if (combobox->selected_index() + 1 == parent_model_.GetItemCount()) { | |
| 355 base::RecordAction(UserMetricsAction("BookmarkBubble_EditFromCombobox")); | |
| 356 ShowEditor(); | |
| 357 } | |
| 358 } | |
| 359 | |
| 360 void BookmarkBubbleView::HandleButtonPressed(views::Button* sender) { | 171 void BookmarkBubbleView::HandleButtonPressed(views::Button* sender) { |
| 361 if (sender == remove_button_) { | 172 if (sender == remove_button_) { |
| 362 base::RecordAction(UserMetricsAction("BookmarkBubble_Unstar")); | 173 base::RecordAction(UserMetricsAction("BookmarkBubble_Unstar")); |
| 363 // Set this so we remove the bookmark after the window closes. | 174 // Set this so we remove the bookmark after the window closes. |
| 364 remove_bookmark_ = true; | 175 remove_bookmark_ = true; |
| 365 apply_edits_ = false; | 176 apply_edits_ = false; |
| 366 GetWidget()->Close(); | 177 GetWidget()->Close(); |
| 367 } else if (sender == edit_button_) { | 178 } else if (sender == edit_button_) { |
| 368 base::RecordAction(UserMetricsAction("BookmarkBubble_Edit")); | 179 base::RecordAction(UserMetricsAction("BookmarkBubble_Edit")); |
| 369 ShowEditor(); | 180 ShowEditor(); |
| 370 } else { | 181 } else { |
| 371 DCHECK_EQ(close_button_, sender); | 182 DCHECK_EQ(save_button_, sender); |
| 372 #if defined(OS_WIN) | 183 #if defined(OS_WIN) |
| 373 if (IsIOSPromotionEligible( | 184 if (IsIOSPromotionEligible( |
| 374 desktop_ios_promotion::PromotionEntryPoint::BOOKMARKS_BUBBLE)) { | 185 desktop_ios_promotion::PromotionEntryPoint::BOOKMARKS_BUBBLE)) { |
| 375 ShowIOSPromotion( | 186 ShowIOSPromotion( |
| 376 desktop_ios_promotion::PromotionEntryPoint::BOOKMARKS_BUBBLE); | 187 desktop_ios_promotion::PromotionEntryPoint::BOOKMARKS_BUBBLE); |
| 377 } else { | 188 } else { |
| 378 GetWidget()->Close(); | 189 GetWidget()->Close(); |
| 379 } | 190 } |
| 380 #else | 191 #else |
| 381 GetWidget()->Close(); | 192 GetWidget()->Close(); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 402 BookmarkEditor::SHOW_TREE); | 213 BookmarkEditor::SHOW_TREE); |
| 403 } | 214 } |
| 404 | 215 |
| 405 void BookmarkBubbleView::ApplyEdits() { | 216 void BookmarkBubbleView::ApplyEdits() { |
| 406 // Set this to make sure we don't attempt to apply edits again. | 217 // Set this to make sure we don't attempt to apply edits again. |
| 407 apply_edits_ = false; | 218 apply_edits_ = false; |
| 408 | 219 |
| 409 BookmarkModel* model = BookmarkModelFactory::GetForBrowserContext(profile_); | 220 BookmarkModel* model = BookmarkModelFactory::GetForBrowserContext(profile_); |
| 410 const BookmarkNode* node = model->GetMostRecentlyAddedUserNodeForURL(url_); | 221 const BookmarkNode* node = model->GetMostRecentlyAddedUserNodeForURL(url_); |
| 411 if (node) { | 222 if (node) { |
| 412 const base::string16 new_title = title_tf_->text(); | 223 const base::string16 new_title = name_field_->text(); |
| 413 if (new_title != node->GetTitle()) { | 224 if (new_title != node->GetTitle()) { |
| 414 model->SetTitle(node, new_title); | 225 model->SetTitle(node, new_title); |
| 415 base::RecordAction( | 226 base::RecordAction( |
| 416 UserMetricsAction("BookmarkBubble_ChangeTitleInBubble")); | 227 UserMetricsAction("BookmarkBubble_ChangeTitleInBubble")); |
| 417 } | 228 } |
| 418 parent_model_.MaybeChangeParent(node, parent_combobox_->selected_index()); | 229 parent_model_.MaybeChangeParent(node, parent_combobox_->selected_index()); |
| 419 } | 230 } |
| 420 } | 231 } |
| 421 | 232 |
| 422 void BookmarkBubbleView::OnIOSPromotionFootnoteLinkClicked() { | |
| 423 #if defined(OS_WIN) | |
| 424 ShowIOSPromotion( | |
| 425 desktop_ios_promotion::PromotionEntryPoint::FOOTNOTE_FOLLOWUP_BUBBLE); | |
| 426 #endif | |
| 427 } | |
| 428 | |
| 429 #if defined(OS_WIN) | 233 #if defined(OS_WIN) |
| 430 | 234 |
| 431 bool BookmarkBubbleView::IsIOSPromotionEligible( | 235 bool BookmarkBubbleView::IsIOSPromotionEligible( |
| 432 desktop_ios_promotion::PromotionEntryPoint entry_point) { | 236 desktop_ios_promotion::PromotionEntryPoint entry_point) { |
| 433 PrefService* prefs = profile_->GetPrefs(); | 237 PrefService* prefs = profile_->GetPrefs(); |
| 434 const browser_sync::ProfileSyncService* sync_service = | 238 const browser_sync::ProfileSyncService* sync_service = |
| 435 ProfileSyncServiceFactory::GetForProfile(profile_); | 239 ProfileSyncServiceFactory::GetForProfile(profile_); |
| 436 return desktop_ios_promotion::IsEligibleForIOSPromotion(prefs, sync_service, | 240 return desktop_ios_promotion::IsEligibleForIOSPromotion(prefs, sync_service, |
| 437 entry_point); | 241 entry_point); |
| 438 } | 242 } |
| 439 | 243 |
| 440 void BookmarkBubbleView::ShowIOSPromotion( | 244 void BookmarkBubbleView::ShowIOSPromotion( |
| 441 desktop_ios_promotion::PromotionEntryPoint entry_point) { | 245 desktop_ios_promotion::PromotionEntryPoint entry_point) { |
| 442 DCHECK(!is_showing_ios_promotion_); | 246 DCHECK(!is_showing_ios_promotion_); |
| 443 RemoveChildView(bookmark_details_view_.get()); | 247 // Hide the contents, but don't delete. It's needed in the destructor. |
| 248 bookmark_contents_view_->SetVisible(false); |
| 444 delete footnote_view_; | 249 delete footnote_view_; |
| 445 footnote_view_ = nullptr; | 250 footnote_view_ = nullptr; |
| 446 is_showing_ios_promotion_ = true; | 251 is_showing_ios_promotion_ = true; |
| 447 ios_promo_view_ = new DesktopIOSPromotionBubbleView(profile_, entry_point); | 252 ios_promo_view_ = new DesktopIOSPromotionBubbleView(profile_, entry_point); |
| 448 AddChildView(ios_promo_view_); | 253 AddChildView(ios_promo_view_); |
| 449 GetWidget()->UpdateWindowIcon(); | 254 GetWidget()->UpdateWindowIcon(); |
| 450 GetWidget()->UpdateWindowTitle(); | 255 GetWidget()->UpdateWindowTitle(); |
| 451 // Resize the bubble so it has the same width as the parent bubble. | 256 // Resize the bubble so it has the same width as the parent bubble. |
| 452 ios_promo_view_->UpdateBubbleHeight(); | 257 ios_promo_view_->UpdateBubbleHeight(); |
| 453 } | 258 } |
| 454 #endif | 259 #endif |
| 260 |
| 261 // ui::DialogModel ------------------------------------------------------------- |
| 262 |
| 263 int BookmarkBubbleView::GetDialogButtons() const { |
| 264 // TODO(tapted): DialogClientView should manage the buttons. |
| 265 return ui::DIALOG_BUTTON_NONE; |
| 266 } |
| 267 |
| 268 // views::WidgetDelegate ------------------------------------------------------- |
| 269 |
| 270 views::View* BookmarkBubbleView::GetInitiallyFocusedView() { |
| 271 return name_field_; |
| 272 } |
| 273 |
| 274 base::string16 BookmarkBubbleView::GetWindowTitle() const { |
| 275 #if defined(OS_WIN) |
| 276 if (is_showing_ios_promotion_) { |
| 277 return desktop_ios_promotion::GetPromoTitle( |
| 278 desktop_ios_promotion::PromotionEntryPoint::BOOKMARKS_BUBBLE); |
| 279 } |
| 280 #endif |
| 281 return l10n_util::GetStringUTF16(newly_bookmarked_ |
| 282 ? IDS_BOOKMARK_BUBBLE_PAGE_BOOKMARKED |
| 283 : IDS_BOOKMARK_BUBBLE_PAGE_BOOKMARK); |
| 284 } |
| 285 |
| 286 gfx::ImageSkia BookmarkBubbleView::GetWindowIcon() { |
| 287 #if defined(OS_WIN) |
| 288 if (is_showing_ios_promotion_) { |
| 289 return desktop_ios_promotion::GetPromoImage( |
| 290 GetNativeTheme()->GetSystemColor( |
| 291 ui::NativeTheme::kColorId_TextfieldDefaultColor)); |
| 292 } |
| 293 #endif |
| 294 return gfx::ImageSkia(); |
| 295 } |
| 296 |
| 297 bool BookmarkBubbleView::ShouldShowWindowIcon() const { |
| 298 return is_showing_ios_promotion_; |
| 299 } |
| 300 |
| 301 void BookmarkBubbleView::WindowClosing() { |
| 302 // We have to reset |bubble_| here, not in our destructor, because we'll be |
| 303 // destroyed asynchronously and the shown state will be checked before then. |
| 304 DCHECK_EQ(bookmark_bubble_, this); |
| 305 bookmark_bubble_ = NULL; |
| 306 is_showing_ios_promotion_ = false; |
| 307 |
| 308 if (observer_) |
| 309 observer_->OnBookmarkBubbleHidden(); |
| 310 } |
| 311 |
| 312 // views::DialogDelegate ------------------------------------------------------- |
| 313 |
| 314 views::View* BookmarkBubbleView::CreateFootnoteView() { |
| 315 #if defined(OS_WIN) |
| 316 if (!is_showing_ios_promotion_ && |
| 317 IsIOSPromotionEligible( |
| 318 desktop_ios_promotion::PromotionEntryPoint::BOOKMARKS_FOOTNOTE)) { |
| 319 footnote_view_ = new DesktopIOSPromotionFootnoteView(profile_, this); |
| 320 return footnote_view_; |
| 321 } |
| 322 #endif |
| 323 if (!SyncPromoUI::ShouldShowSyncPromo(profile_)) |
| 324 return nullptr; |
| 325 |
| 326 base::RecordAction(UserMetricsAction("Signin_Impression_FromBookmarkBubble")); |
| 327 |
| 328 footnote_view_ = |
| 329 new BubbleSyncPromoView(delegate_.get(), IDS_BOOKMARK_SYNC_PROMO_LINK, |
| 330 IDS_BOOKMARK_SYNC_PROMO_MESSAGE); |
| 331 return footnote_view_; |
| 332 } |
| 333 |
| 334 // views::View ----------------------------------------------------------------- |
| 335 |
| 336 const char* BookmarkBubbleView::GetClassName() const { |
| 337 return "BookmarkBubbleView"; |
| 338 } |
| 339 |
| 340 bool BookmarkBubbleView::AcceleratorPressed( |
| 341 const ui::Accelerator& accelerator) { |
| 342 ui::KeyboardCode key_code = accelerator.key_code(); |
| 343 if (key_code == ui::VKEY_RETURN) { |
| 344 HandleButtonPressed(save_button_); |
| 345 return true; |
| 346 } |
| 347 if (key_code == ui::VKEY_E && accelerator.IsAltDown()) { |
| 348 HandleButtonPressed(edit_button_); |
| 349 return true; |
| 350 } |
| 351 if (key_code == ui::VKEY_R && accelerator.IsAltDown()) { |
| 352 HandleButtonPressed(remove_button_); |
| 353 return true; |
| 354 } |
| 355 |
| 356 return LocationBarBubbleDelegateView::AcceleratorPressed(accelerator); |
| 357 } |
| 358 |
| 359 void BookmarkBubbleView::GetAccessibleNodeData(ui::AXNodeData* node_data) { |
| 360 LocationBarBubbleDelegateView::GetAccessibleNodeData(node_data); |
| 361 node_data->SetName(l10n_util::GetStringUTF8( |
| 362 newly_bookmarked_ ? IDS_BOOKMARK_BUBBLE_PAGE_BOOKMARKED |
| 363 : IDS_BOOKMARK_AX_BUBBLE_PAGE_BOOKMARK)); |
| 364 } |
| 365 |
| 366 // views::BubbleDialogDelegateView --------------------------------------------- |
| 367 |
| 368 void BookmarkBubbleView::Init() { |
| 369 remove_button_ = views::MdTextButton::CreateSecondaryUiButton( |
| 370 this, l10n_util::GetStringUTF16(IDS_BOOKMARK_BUBBLE_REMOVE_BOOKMARK)); |
| 371 |
| 372 edit_button_ = views::MdTextButton::CreateSecondaryUiButton( |
| 373 this, l10n_util::GetStringUTF16(IDS_BOOKMARK_BUBBLE_OPTIONS)); |
| 374 |
| 375 save_button_ = views::MdTextButton::CreateSecondaryUiButton( |
| 376 this, l10n_util::GetStringUTF16(IDS_DONE)); |
| 377 save_button_->SetIsDefault(true); |
| 378 |
| 379 views::Label* combobox_label = new views::Label( |
| 380 l10n_util::GetStringUTF16(IDS_BOOKMARK_BUBBLE_FOLDER_TEXT)); |
| 381 |
| 382 parent_combobox_ = new UnsizedCombobox(&parent_model_); |
| 383 parent_combobox_->set_listener(this); |
| 384 parent_combobox_->SetAccessibleName( |
| 385 l10n_util::GetStringUTF16(IDS_BOOKMARK_AX_BUBBLE_FOLDER_TEXT)); |
| 386 |
| 387 SetLayoutManager(new views::FillLayout); |
| 388 bookmark_contents_view_ = new views::View(); |
| 389 GridLayout* layout = new GridLayout(bookmark_contents_view_); |
| 390 bookmark_contents_view_->SetLayoutManager(layout); |
| 391 |
| 392 // This column set is used for the labels and textfields as well as the |
| 393 // buttons at the bottom. |
| 394 const int cs_id = 0; |
| 395 ColumnSet* cs = layout->AddColumnSet(cs_id); |
| 396 ChromeLayoutProvider* provider = ChromeLayoutProvider::Get(); |
| 397 |
| 398 cs->AddColumn(provider->GetControlLabelGridAlignment(), GridLayout::CENTER, 0, |
| 399 GridLayout::USE_PREF, 0, 0); |
| 400 cs->AddPaddingColumn( |
| 401 0, provider->GetDistanceMetric(DISTANCE_UNRELATED_CONTROL_HORIZONTAL)); |
| 402 |
| 403 cs->AddColumn(GridLayout::FILL, GridLayout::CENTER, 0, GridLayout::USE_PREF, |
| 404 0, 0); |
| 405 cs->AddPaddingColumn(1, provider->GetDistanceMetric( |
| 406 DISTANCE_UNRELATED_CONTROL_HORIZONTAL_LARGE)); |
| 407 |
| 408 cs->AddColumn(GridLayout::LEADING, GridLayout::TRAILING, 0, |
| 409 GridLayout::USE_PREF, 0, 0); |
| 410 cs->AddPaddingColumn(0, provider->GetDistanceMetric( |
| 411 views::DISTANCE_RELATED_BUTTON_HORIZONTAL)); |
| 412 cs->AddColumn(GridLayout::LEADING, GridLayout::TRAILING, 0, |
| 413 GridLayout::USE_PREF, 0, 0); |
| 414 |
| 415 layout->StartRow(0, cs_id); |
| 416 views::Label* label = new views::Label( |
| 417 l10n_util::GetStringUTF16(IDS_BOOKMARK_BUBBLE_TITLE_TEXT)); |
| 418 layout->AddView(label); |
| 419 name_field_ = new views::Textfield(); |
| 420 name_field_->SetText(GetBookmarkName()); |
| 421 name_field_->SetAccessibleName( |
| 422 l10n_util::GetStringUTF16(IDS_BOOKMARK_AX_BUBBLE_TITLE_TEXT)); |
| 423 |
| 424 layout->AddView(name_field_, 5, 1); |
| 425 |
| 426 layout->AddPaddingRow( |
| 427 0, provider->GetInsetsMetric(views::INSETS_DIALOG_CONTENTS).top()); |
| 428 |
| 429 layout->StartRow(0, cs_id); |
| 430 layout->AddView(combobox_label); |
| 431 layout->AddView(parent_combobox_, 5, 1); |
| 432 |
| 433 layout->AddPaddingRow( |
| 434 0, provider->GetDistanceMetric(views::DISTANCE_RELATED_CONTROL_VERTICAL)); |
| 435 |
| 436 layout->StartRow(0, cs_id); |
| 437 layout->SkipColumns(2); |
| 438 layout->AddView(remove_button_); |
| 439 layout->AddView(edit_button_); |
| 440 layout->AddView(save_button_); |
| 441 |
| 442 AddAccelerator(ui::Accelerator(ui::VKEY_RETURN, ui::EF_NONE)); |
| 443 AddAccelerator(ui::Accelerator(ui::VKEY_E, ui::EF_ALT_DOWN)); |
| 444 AddAccelerator(ui::Accelerator(ui::VKEY_R, ui::EF_ALT_DOWN)); |
| 445 |
| 446 AddChildView(bookmark_contents_view_); |
| 447 } |
| 448 |
| 449 // views::ButtonListener ------------------------------------------------------- |
| 450 |
| 451 void BookmarkBubbleView::ButtonPressed(views::Button* sender, |
| 452 const ui::Event& event) { |
| 453 HandleButtonPressed(sender); |
| 454 } |
| 455 |
| 456 // views::ComboboxListener ----------------------------------------------------- |
| 457 |
| 458 void BookmarkBubbleView::OnPerformAction(views::Combobox* combobox) { |
| 459 if (combobox->selected_index() + 1 == parent_model_.GetItemCount()) { |
| 460 base::RecordAction(UserMetricsAction("BookmarkBubble_EditFromCombobox")); |
| 461 ShowEditor(); |
| 462 } |
| 463 } |
| 464 |
| 465 // DesktopIOSPromotionFootnoteDelegate ----------------------------------------- |
| 466 |
| 467 void BookmarkBubbleView::OnIOSPromotionFootnoteLinkClicked() { |
| 468 #if defined(OS_WIN) |
| 469 ShowIOSPromotion( |
| 470 desktop_ios_promotion::PromotionEntryPoint::FOOTNOTE_FOLLOWUP_BUBBLE); |
| 471 #endif |
| 472 } |
| OLD | NEW |