invert_bubble_view.cc revision a1401311d1ab56c4ed0a474bd38c108f75cb0cd9
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/views/bubble/bubble_delegate.h"
19#include "ui/views/controls/label.h"
20#include "ui/views/controls/link.h"
21#include "ui/views/controls/link_listener.h"
22#include "ui/views/layout/grid_layout.h"
23#include "ui/views/layout/layout_constants.h"
24#include "ui/views/widget/widget.h"
25
26namespace {
27
28const char kHighContrastExtensionUrl[] =
29    "https://chrome.google.com/webstore/detail/djcfdncoelnlbldjfhinnjlhdjlikmph";
30const char kDarkThemeSearchUrl[] =
31    "https://chrome.google.com/webstore/search-themes/dark";
32const char kLearnMoreUrl[] =
33    "https://groups.google.com/a/googleproductforums.com/d/topic/chrome/Xrco2HsXS-8/discussion";
34const int kBubbleWidth = 500;
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      l10n_util::GetStringUTF16(IDS_HIGH_CONTRAST_NOTIFICATION),
79      original_font_list.Derive(2, gfx::Font::BOLD));
80  title->SetMultiLine(true);
81  title->SizeToFit(kBubbleWidth);
82
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);
86
87  high_contrast_ =
88      new views::Link(l10n_util::GetStringUTF16(IDS_HIGH_CONTRAST_EXT));
89  high_contrast_->SetFontList(original_font_list);
90  high_contrast_->set_listener(this);
91
92  dark_theme_ =
93      new views::Link(l10n_util::GetStringUTF16(IDS_DARK_THEME));
94  dark_theme_->SetFontList(original_font_list);
95  dark_theme_->set_listener(this);
96
97  close_ = new views::Link(l10n_util::GetStringUTF16(IDS_CLOSE));
98  close_->SetFontList(original_font_list);
99  close_->set_listener(this);
100
101  views::GridLayout* layout = views::GridLayout::CreatePanel(this);
102  SetLayoutManager(layout);
103
104  views::ColumnSet* columns = layout->AddColumnSet(0);
105  for (int i = 0; i < 4; i++) {
106    columns->AddColumn(views::GridLayout::LEADING,
107                       views::GridLayout::LEADING, 0,
108                       views::GridLayout::USE_PREF, 0, 0);
109  }
110
111  layout->StartRow(0, 0);
112  layout->AddView(title, 4, 1);
113  layout->StartRowWithPadding(0, 0, 0,
114                              views::kRelatedControlSmallVerticalSpacing);
115  layout->AddView(high_contrast_);
116  layout->AddView(dark_theme_);
117  layout->AddView(learn_more_);
118  layout->AddView(close_);
119
120  // Switching to high-contrast mode has a nasty habit of causing Chrome
121  // top-level windows to lose focus, so closing the bubble on deactivate
122  // makes it disappear before the user has even seen it. This forces the
123  // user to close it explicitly, which should be okay because it affects
124  // a small minority of users, and only once.
125  set_close_on_deactivate(false);
126  set_move_with_anchor(true);
127}
128
129void InvertBubbleView::LinkClicked(views::Link* source, int event_flags) {
130  if (source == high_contrast_)
131    OpenLink(kHighContrastExtensionUrl, event_flags);
132  else if (source == dark_theme_)
133    OpenLink(kDarkThemeSearchUrl, event_flags);
134  else if (source == learn_more_)
135    OpenLink(kLearnMoreUrl, event_flags);
136  else if (source == close_)
137    GetWidget()->Close();
138  else
139    NOTREACHED();
140}
141
142void InvertBubbleView::OpenLink(const std::string& url, int event_flags) {
143  WindowOpenDisposition disposition =
144      ui::DispositionFromEventFlags(event_flags);
145  content::OpenURLParams params(
146      GURL(url), content::Referrer(),
147      disposition == CURRENT_TAB ? NEW_FOREGROUND_TAB : disposition,
148      content::PAGE_TRANSITION_LINK, false);
149  browser_->OpenURL(params);
150}
151
152}  // namespace
153
154namespace chrome {
155
156void MaybeShowInvertBubbleView(BrowserView* browser_view) {
157  Browser* browser = browser_view->browser();
158  PrefService* pref_service = browser->profile()->GetPrefs();
159  views::View* anchor = browser_view->toolbar()->app_menu();
160  if (gfx::IsInvertedColorScheme() && anchor && anchor->GetWidget() &&
161      !pref_service->GetBoolean(prefs::kInvertNotificationShown)) {
162    pref_service->SetBoolean(prefs::kInvertNotificationShown, true);
163    InvertBubbleView* delegate = new InvertBubbleView(browser, anchor);
164    views::BubbleDelegateView::CreateBubble(delegate)->Show();
165  }
166}
167
168}  // namespace chrome
169