Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(212)

Side by Side Diff: chrome/browser/ui/views/website_settings/chooser_bubble_ui.cc

Issue 1408193003: Add chrome side webusb permission UI code (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: removed mac sources from chrome_browser_ui.gypi Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 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/website_settings/chooser_bubble_ui.h"
6
7 #include <string>
8
9 #include "base/prefs/pref_service.h"
10 #include "base/strings/string16.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "chrome/browser/profiles/profile.h"
13 #include "chrome/browser/ui/browser.h"
14 #include "chrome/browser/ui/views/exclusive_access_bubble_views.h"
15 #include "chrome/browser/ui/views/frame/browser_view.h"
16 #include "chrome/browser/ui/views/frame/top_container_view.h"
17 #include "chrome/browser/ui/views/location_bar/location_bar_view.h"
18 #include "chrome/browser/ui/views/location_bar/location_icon_view.h"
19 #include "chrome/browser/usb/web_usb_permission_bubble_request.h"
20 #include "chrome/common/pref_names.h"
21 #include "chrome/grit/generated_resources.h"
22 #include "ui/accessibility/ax_view_state.h"
23 #include "ui/base/l10n/l10n_util.h"
24 #include "ui/base/resource/resource_bundle.h"
25 #include "ui/gfx/paint_vector_icon.h"
26 #include "ui/gfx/text_constants.h"
27 #include "ui/gfx/vector_icons_public.h"
28 #include "ui/views/bubble/bubble_delegate.h"
29 #include "ui/views/bubble/bubble_frame_view.h"
30 #include "ui/views/controls/button/label_button.h"
31 #include "ui/views/controls/button/label_button_border.h"
32 #include "ui/views/controls/label.h"
33 #include "ui/views/controls/table/table_view.h"
34 #include "ui/views/controls/table/table_view_observer.h"
35 #include "ui/views/layout/box_layout.h"
36 #include "ui/views/layout/grid_layout.h"
37
38 namespace {
39
40 // chooser permission bubble width
41 const int kChooserPermissionBubbleWidth = 300;
42
43 // chooser permission bubble height
44 const int kChooserPermissionBubbleHeight = 200;
45
46 // text label height when no devices found
47 const int kLabelHeight = 30;
48
49 // Spacing constant for outer margin. This is added to the
50 // bubble margin itself to equalize the margins at 13px.
51 const int kBubbleOuterMargin = 5;
52
53 // Spacing between major items should be 9px.
54 const int kItemMajorSpacing = 9;
55
56 // Button border size, draws inside the spacing distance.
57 const int kButtonBorderSize = 2;
58
59 } // namespace
60
61 ///////////////////////////////////////////////////////////////////////////////
62 // View implementation for the chooser bubble.
63 class ChooserBubbleUiDelegate : public views::BubbleDelegateView,
64 public views::ButtonListener,
65 public views::TableViewObserver {
66 public:
67 ChooserBubbleUiDelegate(views::View* anchor_view,
68 views::BubbleBorder::Arrow anchor_arrow,
69 ChooserBubbleUi* owner,
70 const WebUsbPermissionBubbleRequest* request);
71 ~ChooserBubbleUiDelegate() override;
72
73 void Close();
74
75 // BubbleDelegateView:
76 bool ShouldShowCloseButton() const override;
77 bool ShouldShowWindowTitle() const override;
78 base::string16 GetWindowTitle() const override;
79 void OnWidgetDestroying(views::Widget* widget) override;
80
81 // ButtonListener:
82 void ButtonPressed(views::Button* button, const ui::Event& event) override;
83
84 // views::TableViewObserver:
85 void OnSelectionChanged() override;
86
87 // Updates the anchor's arrow and view. Also repositions the bubble so it's
88 // displayed in the correct location.
89 void UpdateAnchor(views::View* anchor_view,
90 views::BubbleBorder::Arrow anchor_arrow);
91
92 private:
93 ChooserBubbleUi* owner_;
94 views::Button* connect_;
95 views::Button* cancel_;
96 views::TableView* table_view_;
97
98 DISALLOW_COPY_AND_ASSIGN(ChooserBubbleUiDelegate);
99 };
100
101 ui::TableColumn ChooserTableColumn(int id, const std::string& title) {
102 ui::TableColumn column;
103 column.id = id;
104 column.title = base::ASCIIToUTF16(title.c_str());
105 return column;
106 }
107
108 class ChooserTableModel : public ui::TableModel {
109 public:
110 explicit ChooserTableModel(const std::vector<std::string>& device_names)
111 : observer_(nullptr) {
112 device_names_ = device_names;
113 row_count_ = static_cast<int>(device_names_.size());
114 }
115
116 // ui::TableModel:
117 int RowCount() override { return row_count_; }
118
119 base::string16 GetText(int row, int column_id) override {
120 if (row >= 0 && row < row_count_) {
121 return base::ASCIIToUTF16(device_names_[row]);
122 } else {
123 return base::string16();
124 }
125 }
126
127 void SetObserver(ui::TableModelObserver* observer) override {
128 observer_ = observer;
129 }
130
131 private:
132 ui::TableModelObserver* observer_;
133 std::vector<std::string> device_names_;
134 int row_count_;
135 };
136
137 ChooserBubbleUiDelegate::ChooserBubbleUiDelegate(
138 views::View* anchor_view,
139 views::BubbleBorder::Arrow anchor_arrow,
140 ChooserBubbleUi* owner,
141 const WebUsbPermissionBubbleRequest* request)
142 : views::BubbleDelegateView(anchor_view, anchor_arrow),
143 owner_(owner),
144 connect_(nullptr),
145 cancel_(nullptr) {
146 views::GridLayout* layout = new views::GridLayout(this);
147 SetLayoutManager(layout);
148
149 views::ColumnSet* column_set = layout->AddColumnSet(0);
150 column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 1,
151 views::GridLayout::USE_PREF, 0, 0);
152
153 layout->StartRow(1, 0);
154
155 const std::vector<std::string>& device_names = request->device_names();
156 if (!device_names.empty()) {
157 // create a table view and list the device names into it.
158 std::vector<ui::TableColumn> table_columns;
159 table_columns.push_back(ChooserTableColumn(
160 0, "" /* empty string makes the column title invisible */));
161 table_view_ = new views::TableView(new ChooserTableModel(device_names),
162 table_columns, views::TEXT_ONLY, true);
163 table_view_->SetObserver(this);
164 layout->AddView(table_view_->CreateParentIfNecessary(), 1, 1,
165 views::GridLayout::FILL, views::GridLayout::FILL,
166 kChooserPermissionBubbleWidth,
167 kChooserPermissionBubbleHeight);
168 } else {
169 // show a text label saying no devices found.
170 views::Label* label = new views::Label(l10n_util::GetStringUTF16(
171 IDS_WEBUSB_PERMISSIONS_BUBBLE_NO_DEVICES_FOUND_PROMPT));
172 label->SetHorizontalAlignment(gfx::ALIGN_CENTER);
173 layout->AddView(label, 1, 1, views::GridLayout::FILL,
174 views::GridLayout::FILL, kChooserPermissionBubbleWidth,
175 kLabelHeight);
176 }
177
178 layout->AddPaddingRow(0, kItemMajorSpacing);
179
180 views::View* button_row = new views::View();
181 views::GridLayout* button_layout = new views::GridLayout(button_row);
182 views::ColumnSet* button_columns = button_layout->AddColumnSet(0);
183 button_row->SetLayoutManager(button_layout);
184 layout->StartRow(1, 0);
185 layout->AddView(button_row);
186
187 // lay out the Connect/Cancel buttons.
188 button_columns->AddColumn(views::GridLayout::TRAILING,
189 views::GridLayout::FILL, 100,
190 views::GridLayout::USE_PREF, 0, 0);
191 button_columns->AddPaddingColumn(0,
192 kItemMajorSpacing - (2 * kButtonBorderSize));
193 button_columns->AddColumn(views::GridLayout::TRAILING,
194 views::GridLayout::FILL, 0,
195 views::GridLayout::USE_PREF, 0, 0);
196 button_layout->StartRow(0, 0);
197
198 base::string16 connect_text = base::ASCIIToUTF16("Connect");
199 views::LabelButton* connect_button =
200 new views::LabelButton(this, connect_text);
201 connect_button->SetStyle(views::Button::STYLE_BUTTON);
202 // disable the connect button at the beginning since no device selected yet.
203 connect_button->SetEnabled(false);
204 button_layout->AddView(connect_button);
205 connect_ = connect_button;
206
207 base::string16 cancel_text = base::ASCIIToUTF16("Cancel");
208 views::LabelButton* cancel_button = new views::LabelButton(this, cancel_text);
209 cancel_button->SetStyle(views::Button::STYLE_BUTTON);
210 button_layout->AddView(cancel_button);
211 cancel_ = cancel_button;
212
213 button_layout->AddPaddingRow(0, kBubbleOuterMargin);
214 }
215
216 ChooserBubbleUiDelegate::~ChooserBubbleUiDelegate() {
217 RemoveAllChildViews(true);
218 if (owner_)
219 owner_->Close();
220 }
221
222 void ChooserBubbleUiDelegate::Close() {
223 owner_ = nullptr;
224 GetWidget()->Close();
225 }
226
227 bool ChooserBubbleUiDelegate::ShouldShowCloseButton() const {
228 return true;
229 }
230
231 bool ChooserBubbleUiDelegate::ShouldShowWindowTitle() const {
232 return true;
233 }
234
235 base::string16 ChooserBubbleUiDelegate::GetWindowTitle() const {
236 return l10n_util::GetStringUTF16(IDS_WEBUSB_PERMISSIONS_BUBBLE_PROMPT);
237 }
238
239 void ChooserBubbleUiDelegate::OnWidgetDestroying(views::Widget* widget) {
240 views::BubbleDelegateView::OnWidgetDestroying(widget);
241 if (owner_) {
242 owner_->Close();
243 owner_ = nullptr;
244 }
245 }
246
247 void ChooserBubbleUiDelegate::ButtonPressed(views::Button* button,
248 const ui::Event& event) {
249 if (!owner_)
250 return;
251
252 if (button == connect_)
253 owner_->Connect(table_view_->selection_model().active());
254 else if (button == cancel_)
255 owner_->Cancel();
256 }
257
258 void ChooserBubbleUiDelegate::OnSelectionChanged() {
259 // enable the connect button since user has selected an item.
260 connect_->SetEnabled(true);
261 }
262
263 void ChooserBubbleUiDelegate::UpdateAnchor(
264 views::View* anchor_view,
265 views::BubbleBorder::Arrow anchor_arrow) {
266 if (GetAnchorView() == anchor_view && arrow() == anchor_arrow)
267 return;
268
269 set_arrow(anchor_arrow);
270
271 // Update the border in the bubble: will either add or remove the arrow.
272 views::BubbleFrameView* frame =
273 views::BubbleDelegateView::GetBubbleFrameView();
274 views::BubbleBorder::Arrow adjusted_arrow = anchor_arrow;
275 if (base::i18n::IsRTL())
276 adjusted_arrow = views::BubbleBorder::horizontal_mirror(adjusted_arrow);
277 frame->SetBubbleBorder(scoped_ptr<views::BubbleBorder>(
278 new views::BubbleBorder(adjusted_arrow, shadow(), color())));
279
280 // Reposition the bubble based on the updated arrow and view.
281 SetAnchorView(anchor_view);
282 }
283
284 //////////////////////////////////////////////////////////////////////////////
285 // ChooserBubbleUi
286
287 ChooserBubbleUi::ChooserBubbleUi(Browser* browser,
288 WebUsbPermissionBubbleRequest* request)
289 : browser_(browser), request_(request), bubble_delegate_(nullptr) {
290 DCHECK(browser);
291 }
292
293 ChooserBubbleUi::~ChooserBubbleUi() {}
294
295 void ChooserBubbleUi::Show(BubbleReference bubble_reference) {
296 if (bubble_delegate_)
297 bubble_delegate_->Close();
298 bubble_delegate_ = new ChooserBubbleUiDelegate(
299 GetAnchorView(), GetAnchorArrow(), this, request_);
300
301 // Set |parent_window| because some valid anchors can become hidden.
302 views::Widget* widget = views::Widget::GetWidgetForNativeWindow(
303 browser_->window()->GetNativeWindow());
304 bubble_delegate_->set_parent_window(widget->GetNativeView());
305
306 views::BubbleDelegateView::CreateBubble(bubble_delegate_)->Show();
307 }
308
309 void ChooserBubbleUi::Close() {
310 if (bubble_delegate_) {
311 bubble_delegate_->Close();
312 bubble_delegate_ = nullptr;
313 }
314 }
315
316 void ChooserBubbleUi::UpdateAnchorPosition() {
317 bubble_delegate_->UpdateAnchor(GetAnchorView(), GetAnchorArrow());
318 }
319
320 void ChooserBubbleUi::Connect(int index) {
321 request_->Connect(index);
322 Close();
323 }
324
325 void ChooserBubbleUi::Cancel() {
326 request_->Cancel();
327 Close();
328 }
329
330 views::View* ChooserBubbleUi::GetAnchorView() {
331 BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser_);
332
333 if (browser_->SupportsWindowFeature(Browser::FEATURE_LOCATIONBAR))
334 return browser_view->GetLocationBarView()->location_icon_view();
335
336 if (browser_view->IsFullscreenBubbleVisible())
337 return browser_view->exclusive_access_bubble()->GetView();
338
339 return browser_view->top_container();
340 }
341
342 views::BubbleBorder::Arrow ChooserBubbleUi::GetAnchorArrow() {
343 if (browser_->SupportsWindowFeature(Browser::FEATURE_LOCATIONBAR))
344 return views::BubbleBorder::TOP_LEFT;
345 return views::BubbleBorder::NONE;
346 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698