| // 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/views/accessibility/invert_bubble_view.h" |
| |
| #include "base/macros.h" |
| #include "chrome/browser/profiles/profile.h" |
| #include "chrome/browser/ui/browser.h" |
| #include "chrome/browser/ui/browser_dialogs.h" |
| #include "chrome/browser/ui/views/chrome_layout_provider.h" |
| #include "chrome/browser/ui/views/chrome_typography.h" |
| #include "chrome/browser/ui/views/frame/app_menu_button.h" |
| #include "chrome/browser/ui/views/frame/browser_view.h" |
| #include "chrome/browser/ui/views/frame/toolbar_button_provider.h" |
| #include "chrome/common/pref_names.h" |
| #include "chrome/grit/generated_resources.h" |
| #include "components/prefs/pref_service.h" |
| #include "components/strings/grit/components_strings.h" |
| #include "components/vector_icons/vector_icons.h" |
| #include "content/public/browser/page_navigator.h" |
| #include "ui/base/l10n/l10n_util.h" |
| #include "ui/base/resource/resource_bundle.h" |
| #include "ui/base/window_open_disposition.h" |
| #include "ui/gfx/color_utils.h" |
| #include "ui/views/bubble/bubble_dialog_delegate_view.h" |
| #include "ui/views/controls/button/image_button.h" |
| #include "ui/views/controls/button/image_button_factory.h" |
| #include "ui/views/controls/button/menu_button.h" |
| #include "ui/views/controls/label.h" |
| #include "ui/views/controls/link.h" |
| #include "ui/views/controls/link_listener.h" |
| #include "ui/views/layout/box_layout.h" |
| #include "ui/views/widget/widget.h" |
| |
| namespace { |
| |
| constexpr char kHighContrastExtensionUrl[] = |
| "https://chrome.google.com/webstore/detail/" |
| "djcfdncoelnlbldjfhinnjlhdjlikmph"; |
| constexpr char kDarkThemeSearchUrl[] = |
| "https://chrome.google.com/webstore/category/collection/dark_themes"; |
| constexpr char kLearnMoreUrl[] = |
| "https://groups.google.com/a/googleproductforums.com/d/topic/chrome/" |
| "Xrco2HsXS-8/discussion"; |
| |
| // Tag value used to uniquely identify the "learn more" (?) button. |
| constexpr int kLearnMoreButton = 100; |
| |
| class InvertBubbleView : public views::BubbleDialogDelegateView, |
| public views::LinkListener, |
| public views::ButtonListener { |
| public: |
| InvertBubbleView(Browser* browser, views::View* anchor_view); |
| ~InvertBubbleView() override; |
| |
| private: |
| // Overridden from views::BubbleDialogDelegateView: |
| views::View* CreateExtraView() override; |
| int GetDialogButtons() const override; |
| base::string16 GetDialogButtonLabel(ui::DialogButton button) const override; |
| void Init() override; |
| |
| // Overridden from views::WidgetDelegate: |
| base::string16 GetWindowTitle() const override; |
| bool ShouldShowCloseButton() const override; |
| |
| // Overridden from views::LinkListener: |
| void LinkClicked(views::Link* source, int event_flags) override; |
| |
| // Overridden from views::ButtonListener: |
| void ButtonPressed(views::Button* sender, const ui::Event& event) override; |
| |
| void OpenLink(const std::string& url, int event_flags); |
| |
| Browser* browser_; |
| views::Link* high_contrast_; |
| views::Link* dark_theme_; |
| |
| DISALLOW_COPY_AND_ASSIGN(InvertBubbleView); |
| }; |
| |
| InvertBubbleView::InvertBubbleView(Browser* browser, views::View* anchor_view) |
| : views::BubbleDialogDelegateView(anchor_view, |
| views::BubbleBorder::TOP_RIGHT), |
| browser_(browser), |
| high_contrast_(nullptr), |
| dark_theme_(nullptr) { |
| set_margins(gfx::Insets()); |
| chrome::RecordDialogCreation(chrome::DialogIdentifier::INVERT); |
| } |
| |
| InvertBubbleView::~InvertBubbleView() { |
| } |
| |
| views::View* InvertBubbleView::CreateExtraView() { |
| views::ImageButton* learn_more = views::CreateVectorImageButton(this); |
| views::SetImageFromVectorIcon(learn_more, vector_icons::kHelpOutlineIcon); |
| learn_more->SetTooltipText(l10n_util::GetStringUTF16(IDS_LEARN_MORE)); |
| learn_more->set_tag(kLearnMoreButton); |
| return learn_more; |
| } |
| |
| int InvertBubbleView::GetDialogButtons() const { |
| return ui::DIALOG_BUTTON_OK; |
| } |
| |
| base::string16 InvertBubbleView::GetDialogButtonLabel( |
| ui::DialogButton button) const { |
| DCHECK_EQ(button, ui::DialogButton::DIALOG_BUTTON_OK); |
| return l10n_util::GetStringUTF16(IDS_DONE); |
| } |
| |
| void InvertBubbleView::Init() { |
| const ChromeLayoutProvider* provider = ChromeLayoutProvider::Get(); |
| SetBorder(views::CreateEmptyBorder( |
| provider->GetInsetsMetric(views::INSETS_DIALOG))); |
| |
| auto high_contrast = std::make_unique<views::Link>( |
| l10n_util::GetStringUTF16(IDS_HIGH_CONTRAST_EXT), |
| CONTEXT_BODY_TEXT_LARGE); |
| high_contrast->set_listener(this); |
| |
| auto dark_theme = std::make_unique<views::Link>( |
| l10n_util::GetStringUTF16(IDS_DARK_THEME), CONTEXT_BODY_TEXT_LARGE); |
| dark_theme->set_listener(this); |
| |
| views::BoxLayout* layout = SetLayoutManager( |
| std::make_unique<views::BoxLayout>(views::BoxLayout::kVertical)); |
| layout->set_cross_axis_alignment( |
| views::BoxLayout::CROSS_AXIS_ALIGNMENT_START); |
| |
| AddChildView(std::make_unique<views::Label>( |
| l10n_util::GetStringUTF16(IDS_HIGH_CONTRAST_HEADER), |
| CONTEXT_BODY_TEXT_LARGE)); |
| high_contrast_ = AddChildView(std::move(high_contrast)); |
| dark_theme_ = AddChildView(std::move(dark_theme)); |
| |
| // Switching to high-contrast mode has a nasty habit of causing Chrome |
| // top-level windows to lose focus, so closing the bubble on deactivate |
| // makes it disappear before the user has even seen it. This forces the |
| // user to close it explicitly, which should be okay because it affects |
| // a small minority of users, and only once. |
| set_close_on_deactivate(false); |
| } |
| |
| base::string16 InvertBubbleView::GetWindowTitle() const { |
| return l10n_util::GetStringUTF16(IDS_HIGH_CONTRAST_TITLE); |
| } |
| |
| bool InvertBubbleView::ShouldShowCloseButton() const { |
| return true; |
| } |
| |
| void InvertBubbleView::LinkClicked(views::Link* source, int event_flags) { |
| if (source == high_contrast_) |
| OpenLink(kHighContrastExtensionUrl, event_flags); |
| else if (source == dark_theme_) |
| OpenLink(kDarkThemeSearchUrl, event_flags); |
| else |
| NOTREACHED(); |
| } |
| |
| void InvertBubbleView::ButtonPressed(views::Button* sender, |
| const ui::Event& event) { |
| if (sender->tag() == kLearnMoreButton) |
| OpenLink(kLearnMoreUrl, event.flags()); |
| } |
| |
| void InvertBubbleView::OpenLink(const std::string& url, int event_flags) { |
| WindowOpenDisposition disposition = |
| ui::DispositionFromEventFlags(event_flags); |
| content::OpenURLParams params( |
| GURL(url), content::Referrer(), |
| disposition == WindowOpenDisposition::CURRENT_TAB |
| ? WindowOpenDisposition::NEW_FOREGROUND_TAB |
| : disposition, |
| ui::PAGE_TRANSITION_LINK, false); |
| browser_->OpenURL(params); |
| } |
| |
| } // namespace |
| |
| void MaybeShowInvertBubbleView(BrowserView* browser_view) { |
| Browser* browser = browser_view->browser(); |
| PrefService* pref_service = browser->profile()->GetPrefs(); |
| views::View* anchor = |
| browser_view->toolbar_button_provider()->GetAppMenuButton(); |
| if (color_utils::IsInvertedColorScheme() && anchor && anchor->GetWidget() && |
| !pref_service->GetBoolean(prefs::kInvertNotificationShown)) { |
| pref_service->SetBoolean(prefs::kInvertNotificationShown, true); |
| ShowInvertBubbleView(browser, anchor); |
| } |
| } |
| |
| void ShowInvertBubbleView(Browser* browser, views::View* anchor) { |
| InvertBubbleView* delegate = new InvertBubbleView(browser, anchor); |
| views::BubbleDialogDelegateView::CreateBubble(delegate)->Show(); |
| } |