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
3 // found in the LICENSE file.
5 #include "chrome/browser/ui/views/accessibility/invert_bubble_view.h"
7 #include "base/prefs/pref_service.h"
8 #include "chrome/browser/profiles/profile.h"
9 #include "chrome/browser/ui/browser.h"
10 #include "chrome/browser/ui/views/frame/browser_view.h"
11 #include "chrome/browser/ui/views/toolbar/toolbar_view.h"
12 #include "chrome/browser/ui/views/toolbar/wrench_toolbar_button.h"
13 #include "chrome/common/pref_names.h"
14 #include "chrome/grit/generated_resources.h"
15 #include "content/public/browser/page_navigator.h"
16 #include "grit/components_strings.h"
17 #include "ui/base/l10n/l10n_util.h"
18 #include "ui/base/resource/resource_bundle.h"
19 #include "ui/base/window_open_disposition.h"
20 #include "ui/gfx/color_utils.h"
21 #include "ui/views/bubble/bubble_delegate.h"
22 #include "ui/views/controls/label.h"
23 #include "ui/views/controls/link.h"
24 #include "ui/views/controls/link_listener.h"
25 #include "ui/views/layout/grid_layout.h"
26 #include "ui/views/layout/layout_constants.h"
27 #include "ui/views/widget/widget.h"
31 const char kHighContrastExtensionUrl
[] =
32 "https://chrome.google.com/webstore/detail/djcfdncoelnlbldjfhinnjlhdjlikmph";
33 const char kDarkThemeSearchUrl
[] =
34 "https://chrome.google.com/webstore/search-themes/dark";
35 const char kLearnMoreUrl
[] =
36 "https://groups.google.com/a/googleproductforums.com/d/topic/chrome/Xrco2HsXS-8/discussion";
38 class InvertBubbleView
: public views::BubbleDelegateView
,
39 public views::LinkListener
{
41 InvertBubbleView(Browser
* browser
, views::View
* anchor_view
);
42 ~InvertBubbleView() override
;
45 // Overridden from views::BubbleDelegateView:
48 // Overridden from views::LinkListener:
49 void LinkClicked(views::Link
* source
, int event_flags
) override
;
51 void OpenLink(const std::string
& url
, int event_flags
);
54 views::Link
* high_contrast_
;
55 views::Link
* dark_theme_
;
56 views::Link
* learn_more_
;
59 DISALLOW_COPY_AND_ASSIGN(InvertBubbleView
);
62 InvertBubbleView::InvertBubbleView(Browser
* browser
, views::View
* anchor_view
)
63 : views::BubbleDelegateView(anchor_view
, views::BubbleBorder::TOP_RIGHT
),
71 InvertBubbleView::~InvertBubbleView() {
74 void InvertBubbleView::Init() {
75 ui::ResourceBundle
& rb
= ui::ResourceBundle::GetSharedInstance();
76 const gfx::FontList
& original_font_list
=
77 rb
.GetFontList(ui::ResourceBundle::MediumFont
);
79 views::Label
* title
= new views::Label(
80 base::string16(), original_font_list
.Derive(2, gfx::Font::BOLD
));
81 title
->SetMultiLine(true);
83 learn_more_
= new views::Link(l10n_util::GetStringUTF16(IDS_LEARN_MORE
));
84 learn_more_
->SetFontList(original_font_list
);
85 learn_more_
->set_listener(this);
88 new views::Link(l10n_util::GetStringUTF16(IDS_HIGH_CONTRAST_EXT
));
89 high_contrast_
->SetFontList(original_font_list
);
90 high_contrast_
->set_listener(this);
92 dark_theme_
= new views::Link(l10n_util::GetStringUTF16(IDS_DARK_THEME
));
93 dark_theme_
->SetFontList(original_font_list
);
94 dark_theme_
->set_listener(this);
96 close_
= new views::Link(l10n_util::GetStringUTF16(IDS_CLOSE
));
97 close_
->SetFontList(original_font_list
);
98 close_
->set_listener(this);
100 views::GridLayout
* layout
= views::GridLayout::CreatePanel(this);
101 SetLayoutManager(layout
);
103 views::ColumnSet
* columns
= layout
->AddColumnSet(0);
104 for (int i
= 0; i
< 4; i
++) {
105 columns
->AddColumn(views::GridLayout::LEADING
,
106 views::GridLayout::LEADING
, 0,
107 views::GridLayout::USE_PREF
, 0, 0);
110 layout
->StartRow(0, 0);
111 layout
->AddView(title
, 4, 1);
112 layout
->StartRowWithPadding(0, 0, 0,
113 views::kRelatedControlSmallVerticalSpacing
);
114 layout
->AddView(high_contrast_
);
115 layout
->AddView(dark_theme_
);
116 layout
->AddView(learn_more_
);
117 layout
->AddView(close_
);
119 // Fit the message to the width of the links in the bubble.
120 const gfx::Size
size(GetPreferredSize());
121 title
->SetText(l10n_util::GetStringUTF16(IDS_HIGH_CONTRAST_NOTIFICATION
));
122 title
->SizeToFit(size
.width());
124 // Switching to high-contrast mode has a nasty habit of causing Chrome
125 // top-level windows to lose focus, so closing the bubble on deactivate
126 // makes it disappear before the user has even seen it. This forces the
127 // user to close it explicitly, which should be okay because it affects
128 // a small minority of users, and only once.
129 set_close_on_deactivate(false);
132 void InvertBubbleView::LinkClicked(views::Link
* source
, int event_flags
) {
133 if (source
== high_contrast_
)
134 OpenLink(kHighContrastExtensionUrl
, event_flags
);
135 else if (source
== dark_theme_
)
136 OpenLink(kDarkThemeSearchUrl
, event_flags
);
137 else if (source
== learn_more_
)
138 OpenLink(kLearnMoreUrl
, event_flags
);
139 else if (source
== close_
)
140 GetWidget()->Close();
145 void InvertBubbleView::OpenLink(const std::string
& url
, int event_flags
) {
146 WindowOpenDisposition disposition
=
147 ui::DispositionFromEventFlags(event_flags
);
148 content::OpenURLParams
params(
149 GURL(url
), content::Referrer(),
150 disposition
== CURRENT_TAB
? NEW_FOREGROUND_TAB
: disposition
,
151 ui::PAGE_TRANSITION_LINK
, false);
152 browser_
->OpenURL(params
);
159 void MaybeShowInvertBubbleView(BrowserView
* browser_view
) {
160 Browser
* browser
= browser_view
->browser();
161 PrefService
* pref_service
= browser
->profile()->GetPrefs();
162 views::View
* anchor
= browser_view
->toolbar()->app_menu();
163 if (color_utils::IsInvertedColorScheme() && anchor
&& anchor
->GetWidget() &&
164 !pref_service
->GetBoolean(prefs::kInvertNotificationShown
)) {
165 pref_service
->SetBoolean(prefs::kInvertNotificationShown
, true);
166 InvertBubbleView
* delegate
= new InvertBubbleView(browser
, anchor
);
167 views::BubbleDelegateView::CreateBubble(delegate
)->Show();
171 } // namespace chrome