Index: chrome/browser/ui/views/intent_picker_bubble_view.cc |
diff --git a/chrome/browser/ui/views/intent_picker_bubble_view.cc b/chrome/browser/ui/views/intent_picker_bubble_view.cc |
index 0d46d817d4822b33e4f3f64474e5f87bd3a8bc7d..325672cc5b77d85d97f023765ce952df584fe2cc 100644 |
--- a/chrome/browser/ui/views/intent_picker_bubble_view.cc |
+++ b/chrome/browser/ui/views/intent_picker_bubble_view.cc |
@@ -15,9 +15,12 @@ |
#include "content/public/browser/navigation_handle.h" |
#include "third_party/skia/include/core/SkColor.h" |
#include "ui/base/l10n/l10n_util.h" |
+#include "ui/base/material_design/material_design_controller.h" |
#include "ui/gfx/canvas.h" |
+#include "ui/views/animation/ink_drop_highlight.h" |
bruthig
2016/08/30 19:16:37
Is this needed?
djacobo_
2016/09/06 23:21:24
I guess I tried to use .../ink_drop_host_view.h re
|
#include "ui/views/border.h" |
#include "ui/views/controls/button/image_button.h" |
+#include "ui/views/controls/button/md_text_button.h" |
#include "ui/views/controls/scroll_view.h" |
#include "ui/views/controls/scrollbar/overlay_scroll_bar.h" |
#include "ui/views/layout/box_layout.h" |
@@ -31,21 +34,11 @@ constexpr size_t kMaxAppResults = arc::ArcNavigationThrottle::kMaxAppResults; |
// Main components sizes |
constexpr int kRowHeight = 40; |
constexpr int kMaxWidth = 320; |
-constexpr int kHeaderHeight = 60; |
-constexpr int kFooterHeight = 68; |
-// Inter components padding |
-constexpr int kButtonSeparation = 8; |
-constexpr int kLabelImageSeparation = 12; |
// UI position wrt the Top Container |
constexpr int kTopContainerMerge = 3; |
constexpr size_t kAppTagNoneSelected = static_cast<size_t>(-1); |
-// Arbitrary negative values to use as tags on the |always_button_| and |
-// |just_once_button_|. These are negative to differentiate from the app's tags |
-// which are always >= 0. |
-enum class Option : int { ALWAYS = -2, JUST_ONCE }; |
- |
} // namespace |
// static |
@@ -55,18 +48,12 @@ void IntentPickerBubbleView::ShowBubble( |
const ThrottleCallback& throttle_cb) { |
Browser* browser = |
chrome::FindBrowserWithWebContents(handle->GetWebContents()); |
- if (!browser) { |
+ if (!browser || !BrowserView::GetBrowserViewForBrowser(browser)) { |
throttle_cb.Run(kAppTagNoneSelected, |
arc::ArcNavigationThrottle::CloseReason::ERROR); |
return; |
} |
BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser); |
- if (!browser_view) { |
- throttle_cb.Run(kAppTagNoneSelected, |
- arc::ArcNavigationThrottle::CloseReason::ERROR); |
- return; |
- } |
- |
IntentPickerBubbleView* delegate = new IntentPickerBubbleView( |
app_info, throttle_cb, handle->GetWebContents()); |
delegate->set_margins(gfx::Insets()); |
@@ -101,65 +88,52 @@ IntentPickerBubbleView::CreateBubbleView( |
return bubble; |
} |
-void IntentPickerBubbleView::Init() { |
- SkColor button_text_color = SkColorSetRGB(0x42, 0x85, 0xf4); |
- |
- views::BoxLayout* general_layout = |
- new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 0); |
- SetLayoutManager(general_layout); |
+bool IntentPickerBubbleView::Accept() { |
+ if (!throttle_cb_.is_null()) { |
+ auto callback = throttle_cb_; |
+ throttle_cb_.Reset(); |
+ callback.Run(selected_app_tag_, |
+ arc::ArcNavigationThrottle::CloseReason::JUST_ONCE_PRESSED); |
+ } |
+ return true; |
+} |
- // Create a view for the upper part of the UI, managed by a GridLayout to |
- // allow precise padding. |
- View* header = new View(); |
- views::GridLayout* header_layout = new views::GridLayout(header); |
- header->SetLayoutManager(header_layout); |
- views::Label* open_with = new views::Label( |
- l10n_util::GetStringUTF16(IDS_INTENT_PICKER_BUBBLE_VIEW_OPEN_WITH)); |
- open_with->SetHorizontalAlignment(gfx::ALIGN_LEFT); |
- open_with->SetFontList(gfx::FontList("Roboto-medium, 15px")); |
+bool IntentPickerBubbleView::Cancel() { |
+ if (!throttle_cb_.is_null()) { |
+ auto callback = throttle_cb_; |
+ throttle_cb_.Reset(); |
+ callback.Run(selected_app_tag_, |
+ arc::ArcNavigationThrottle::CloseReason::ALWAYS_PRESSED); |
+ } |
+ return true; |
+} |
- views::ColumnSet* column_set = header_layout->AddColumnSet(0); |
- column_set->AddPaddingColumn(0, 16); |
- column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 1, |
- views::GridLayout::FIXED, kMaxWidth, kMaxWidth); |
- column_set->AddPaddingColumn(0, 16); |
- // Tell the GridLayout where to start, then proceed to place the views. |
- header_layout->AddPaddingRow(0.0, 21); |
- header_layout->StartRow(0, 0); |
- header_layout->AddView(open_with); |
- header_layout->AddPaddingRow(0.0, 24); |
+bool IntentPickerBubbleView::Close() { |
+ // Whenever closing the bubble without pressing |JUST ONCE| or |ALWAYS| we |
+ // need to report back that the user didn't select anything. |
+ if (!throttle_cb_.is_null()) { |
+ auto callback = throttle_cb_; |
+ throttle_cb_.Reset(); |
+ callback.Run(kAppTagNoneSelected, |
+ arc::ArcNavigationThrottle::CloseReason::DIALOG_DEACTIVATED); |
+ } |
+ return true; |
+} |
- always_button_ = new views::LabelButton( |
- this, l10n_util::GetStringUTF16(IDS_INTENT_PICKER_BUBBLE_VIEW_ALWAYS)); |
- always_button_->SetFocusBehavior(View::FocusBehavior::ALWAYS); |
- always_button_->SetFontList(gfx::FontList("Roboto-medium, 13px")); |
- always_button_->set_tag(static_cast<int>(Option::ALWAYS)); |
- always_button_->SetMinSize(gfx::Size(80, 32)); |
- always_button_->SetTextColor(views::Button::STATE_DISABLED, SK_ColorGRAY); |
- always_button_->SetTextColor(views::Button::STATE_NORMAL, button_text_color); |
- always_button_->SetTextColor(views::Button::STATE_HOVERED, button_text_color); |
- always_button_->SetHorizontalAlignment(gfx::ALIGN_CENTER); |
- always_button_->SetState(views::Button::STATE_DISABLED); |
- always_button_->SetBorder(views::Border::CreateEmptyBorder(gfx::Insets(16))); |
+int IntentPickerBubbleView::GetDefaultDialogButton() const { |
+ return ui::DIALOG_BUTTON_NONE; |
+} |
- just_once_button_ = new views::LabelButton( |
- this, l10n_util::GetStringUTF16(IDS_INTENT_PICKER_BUBBLE_VIEW_JUST_ONCE)); |
- just_once_button_->SetFocusBehavior(View::FocusBehavior::ALWAYS); |
- just_once_button_->SetFontList(gfx::FontList("Roboto-medium, 13px")); |
- just_once_button_->set_tag(static_cast<int>(Option::JUST_ONCE)); |
- just_once_button_->SetMinSize(gfx::Size(80, 32)); |
- just_once_button_->SetState(views::Button::STATE_DISABLED); |
- just_once_button_->SetTextColor(views::Button::STATE_DISABLED, SK_ColorGRAY); |
- just_once_button_->SetTextColor(views::Button::STATE_NORMAL, |
- button_text_color); |
- just_once_button_->SetTextColor(views::Button::STATE_HOVERED, |
- button_text_color); |
- just_once_button_->SetHorizontalAlignment(gfx::ALIGN_CENTER); |
- just_once_button_->SetBorder( |
- views::Border::CreateEmptyBorder(gfx::Insets(16))); |
+bool IntentPickerBubbleView::IsDialogButtonEnabled( |
+ ui::DialogButton button) const { |
+ // Both buttons are enabled only when the user selected one of the apps. |
+ return selected_app_tag_ != kAppTagNoneSelected; |
+} |
- header_layout->StartRow(0, 0); |
- AddChildView(header); |
+void IntentPickerBubbleView::Init() { |
+ views::BoxLayout* general_layout = |
+ new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 0); |
+ SetLayoutManager(general_layout); |
// Creates a view to hold the views for each app. |
views::View* scrollable_view = new views::View(); |
@@ -167,20 +141,20 @@ void IntentPickerBubbleView::Init() { |
new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 0); |
scrollable_view->SetLayoutManager(scrollable_layout); |
for (size_t i = 0; i < app_info_.size(); ++i) { |
- views::LabelButton* tmp_label = new views::LabelButton( |
- this, base::UTF8ToUTF16(base::StringPiece(app_info_[i].first))); |
- tmp_label->SetFocusBehavior(View::FocusBehavior::ALWAYS); |
- tmp_label->SetFontList(gfx::FontList("Roboto-regular, 13px")); |
- tmp_label->SetImageLabelSpacing(kLabelImageSeparation); |
- tmp_label->SetMinSize(gfx::Size(kMaxWidth, kRowHeight)); |
- tmp_label->SetMaxSize(gfx::Size(kMaxWidth, kRowHeight)); |
- tmp_label->set_tag(i); |
+ views::LabelButton* app_button = |
+ views::MdTextButton::CreateSecondaryUiButton( |
+ this, base::UTF8ToUTF16(base::StringPiece(app_info_[i].first))); |
+ app_button->set_ink_drop_base_color(SK_ColorBLACK); |
+ app_button->SetHorizontalAlignment(gfx::ALIGN_LEFT); |
+ app_button->SetFocusBehavior(View::FocusBehavior::ALWAYS); |
+ app_button->SetMinSize(gfx::Size(kMaxWidth, kRowHeight)); |
+ app_button->set_tag(i); |
if (!app_info_[i].second.IsEmpty()) { |
- tmp_label->SetImage(views::ImageButton::STATE_NORMAL, |
- *app_info_[i].second.ToImageSkia()); |
+ app_button->SetImage(views::ImageButton::STATE_NORMAL, |
+ *app_info_[i].second.ToImageSkia()); |
} |
- tmp_label->SetBorder(views::Border::CreateEmptyBorder(10, 16, 10, 0)); |
- scrollable_view->AddChildViewAt(tmp_label, i); |
+ app_button->SetBorder(views::Border::CreateEmptyBorder(10, 16, 10, 0)); |
+ scrollable_view->AddChildViewAt(app_button, i); |
} |
scroll_view_ = new views::ScrollView(); |
@@ -199,19 +173,22 @@ void IntentPickerBubbleView::Init() { |
} |
AddChildView(scroll_view_); |
- // The lower part of the Picker contains only the 2 buttons |
- // |just_once_button_| and |always_button_|. |
- View* footer = new View(); |
- footer->SetBorder(views::Border::CreateEmptyBorder(24, 0, 12, 12)); |
- views::BoxLayout* buttons_layout = new views::BoxLayout( |
- views::BoxLayout::kHorizontal, 0, 0, kButtonSeparation); |
- footer->SetLayoutManager(buttons_layout); |
+ if (ui::MaterialDesignController::IsModeMaterial()) { |
+ SetPaintToLayer(true); |
bruthig
2016/08/30 19:16:37
Why is this needed? Is it related to the InkDrop?
djacobo_
2016/09/06 23:21:23
I don't think it's related, I had some issues whil
|
+ layer()->SetMasksToBounds(true); |
+ layer()->SetFillsBoundsOpaquely(false); |
+ } |
+} |
- buttons_layout->set_main_axis_alignment( |
- views::BoxLayout::MAIN_AXIS_ALIGNMENT_END); |
- footer->AddChildView(just_once_button_); |
- footer->AddChildView(always_button_); |
- AddChildView(footer); |
+base::string16 IntentPickerBubbleView::GetWindowTitle() const { |
+ return l10n_util::GetStringUTF16(IDS_INTENT_PICKER_BUBBLE_VIEW_OPEN_WITH); |
+} |
+ |
+base::string16 IntentPickerBubbleView::GetDialogButtonLabel( |
+ ui::DialogButton button) const { |
+ if (button == ui::DIALOG_BUTTON_OK) |
+ return l10n_util::GetStringUTF16(IDS_INTENT_PICKER_BUBBLE_VIEW_JUST_ONCE); |
+ return l10n_util::GetStringUTF16(IDS_INTENT_PICKER_BUBBLE_VIEW_ALWAYS); |
} |
IntentPickerBubbleView::IntentPickerBubbleView( |
@@ -221,11 +198,8 @@ IntentPickerBubbleView::IntentPickerBubbleView( |
: views::BubbleDialogDelegateView(nullptr /* anchor_view */, |
views::BubbleBorder::TOP_CENTER), |
WebContentsObserver(web_contents), |
- was_callback_run_(false), |
throttle_cb_(throttle_cb), |
selected_app_tag_(kAppTagNoneSelected), |
- always_button_(nullptr), |
- just_once_button_(nullptr), |
scroll_view_(nullptr), |
app_info_(app_info) {} |
@@ -236,47 +210,26 @@ IntentPickerBubbleView::~IntentPickerBubbleView() { |
// If the widget gets closed without an app being selected we still need to use |
// the callback so the caller can Resume the navigation. |
void IntentPickerBubbleView::OnWidgetDestroying(views::Widget* widget) { |
- if (!was_callback_run_) { |
- throttle_cb_.Run( |
- kAppTagNoneSelected, |
- arc::ArcNavigationThrottle::CloseReason::DIALOG_DEACTIVATED); |
- was_callback_run_ = true; |
+ if (!throttle_cb_.is_null()) { |
+ auto callback = throttle_cb_; |
+ throttle_cb_.Reset(); |
+ callback.Run(kAppTagNoneSelected, |
+ arc::ArcNavigationThrottle::CloseReason::DIALOG_DEACTIVATED); |
} |
} |
-int IntentPickerBubbleView::GetDialogButtons() const { |
- return ui::DIALOG_BUTTON_NONE; |
-} |
- |
void IntentPickerBubbleView::ButtonPressed(views::Button* sender, |
const ui::Event& event) { |
- switch (sender->tag()) { |
- case static_cast<int>(Option::ALWAYS): |
- throttle_cb_.Run(selected_app_tag_, |
- arc::ArcNavigationThrottle::CloseReason::ALWAYS_PRESSED); |
- was_callback_run_ = true; |
- GetWidget()->Close(); |
- break; |
- case static_cast<int>(Option::JUST_ONCE): |
- throttle_cb_.Run( |
- selected_app_tag_, |
- arc::ArcNavigationThrottle::CloseReason::JUST_ONCE_PRESSED); |
- was_callback_run_ = true; |
- GetWidget()->Close(); |
- break; |
- default: |
- // The selected app must be a value in the range [0, app_info_.size()-1]. |
- DCHECK(static_cast<size_t>(sender->tag()) < app_info_.size()); |
- // The user cannot click on the |always_button_| or |just_once_button_| |
- // unless an explicit app has been selected. |
- if (selected_app_tag_ != kAppTagNoneSelected) |
- SetLabelButtonBackgroundColor(selected_app_tag_, SK_ColorWHITE); |
- selected_app_tag_ = sender->tag(); |
- SetLabelButtonBackgroundColor(selected_app_tag_, |
- SkColorSetRGB(0xeb, 0xeb, 0xeb)); |
- always_button_->SetState(views::Button::STATE_NORMAL); |
- just_once_button_->SetState(views::Button::STATE_NORMAL); |
- } |
+ // The selected app must be a value in the range [0, app_info_.size()-1]. |
+ DCHECK(static_cast<size_t>(sender->tag()) < app_info_.size()); |
+ // The user cannot click on the |always_button_| or |just_once_button_| |
+ // unless an explicit app has been selected. |
+ if (selected_app_tag_ != kAppTagNoneSelected) |
+ SetLabelButtonBackgroundColor(selected_app_tag_, SK_ColorWHITE); |
+ selected_app_tag_ = sender->tag(); |
+ SetLabelButtonBackgroundColor(selected_app_tag_, |
+ SkColorSetRGB(0xeb, 0xeb, 0xeb)); |
+ GetDialogClientView()->UpdateDialogButtons(); |
} |
gfx::Size IntentPickerBubbleView::GetPreferredSize() const { |
@@ -290,17 +243,18 @@ gfx::Size IntentPickerBubbleView::GetPreferredSize() const { |
} else { |
apps_height *= kRowHeight; |
} |
- ps.set_height(apps_height + kHeaderHeight + kFooterHeight); |
+ ps.set_height(apps_height); |
return ps; |
} |
// If the actual web_contents gets destroyed in the middle of the process we |
// should inform the caller about this error. |
void IntentPickerBubbleView::WebContentsDestroyed() { |
- if (!was_callback_run_) { |
- throttle_cb_.Run(kAppTagNoneSelected, |
- arc::ArcNavigationThrottle::CloseReason::ERROR); |
- was_callback_run_ = true; |
+ if (!throttle_cb_.is_null()) { |
+ auto callback = throttle_cb_; |
+ throttle_cb_.Reset(); |
+ callback.Run(kAppTagNoneSelected, |
+ arc::ArcNavigationThrottle::CloseReason::ERROR); |
} |
GetWidget()->Close(); |
} |
@@ -312,7 +266,13 @@ views::LabelButton* IntentPickerBubbleView::GetLabelButtonAt(size_t index) { |
void IntentPickerBubbleView::SetLabelButtonBackgroundColor(size_t index, |
SkColor color) { |
- views::LabelButton* temp_lb = GetLabelButtonAt(index); |
- temp_lb->set_background(views::Background::CreateSolidBackground(color)); |
- temp_lb->SchedulePaint(); |
+ views::LabelButton* button = GetLabelButtonAt(index); |
+ button->set_background(views::Background::CreateSolidBackground(color)); |
+ button->SchedulePaint(); |
+} |
+ |
+// Method for testing, this way we don't need to expose IntentPickerMenuButton |
+gfx::ImageSkia IntentPickerBubbleView::GetAppImageForTesting(size_t index) { |
+ return GetLabelButtonAt(index)->GetImage( |
+ views::Button::ButtonState::STATE_NORMAL); |
} |