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