network_config_view.cc revision 90dce4d38c5ff5333bea97d859d4e484e27edf0c
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/chromeos/options/network_config_view.h"
6
7#include <algorithm>
8
9#include "ash/shell.h"
10#include "base/string_util.h"
11#include "base/utf_string_conversions.h"
12#include "chrome/browser/chromeos/cros/network_property_ui_data.h"
13#include "chrome/browser/chromeos/login/login_display_host_impl.h"
14#include "chrome/browser/chromeos/options/vpn_config_view.h"
15#include "chrome/browser/chromeos/options/wifi_config_view.h"
16#include "chrome/browser/chromeos/options/wimax_config_view.h"
17#include "chrome/browser/profiles/profile_manager.h"
18#include "chrome/browser/ui/browser.h"
19#include "chrome/browser/ui/browser_finder.h"
20#include "chrome/browser/ui/browser_window.h"
21#include "chrome/browser/ui/host_desktop.h"
22#include "grit/chromium_strings.h"
23#include "grit/generated_resources.h"
24#include "grit/locale_settings.h"
25#include "grit/theme_resources.h"
26#include "ui/aura/root_window.h"
27#include "ui/base/accessibility/accessible_view_state.h"
28#include "ui/base/l10n/l10n_util.h"
29#include "ui/base/resource/resource_bundle.h"
30#include "ui/gfx/image/image.h"
31#include "ui/gfx/rect.h"
32#include "ui/views/controls/button/label_button.h"
33#include "ui/views/controls/image_view.h"
34#include "ui/views/layout/layout_constants.h"
35#include "ui/views/widget/widget.h"
36
37using views::Widget;
38
39namespace {
40
41gfx::NativeWindow GetDialogParent() {
42  if (chromeos::LoginDisplayHostImpl::default_host()) {
43    return chromeos::LoginDisplayHostImpl::default_host()->GetNativeWindow();
44  } else {
45    Browser* browser = chrome::FindTabbedBrowser(
46        ProfileManager::GetDefaultProfileOrOffTheRecord(),
47        true,
48        chrome::HOST_DESKTOP_TYPE_ASH);
49    if (browser)
50      return browser->window()->GetNativeWindow();
51  }
52  return NULL;
53}
54
55// Avoid global static initializer.
56chromeos::NetworkConfigView** GetActiveDialogPointer() {
57  static chromeos::NetworkConfigView* active_dialog = NULL;
58  return &active_dialog;
59}
60
61chromeos::NetworkConfigView* GetActiveDialog() {
62  return *(GetActiveDialogPointer());
63}
64
65void SetActiveDialog(chromeos::NetworkConfigView* dialog) {
66  *(GetActiveDialogPointer()) = dialog;
67}
68
69}  // namespace
70
71namespace chromeos {
72
73// static
74const int ChildNetworkConfigView::kInputFieldMinWidth = 270;
75
76NetworkConfigView::NetworkConfigView(Network* network)
77    : child_config_view_(NULL),
78      delegate_(NULL),
79      advanced_button_(NULL) {
80  DCHECK(GetActiveDialog() == NULL);
81  SetActiveDialog(this);
82  if (network->type() == TYPE_WIFI) {
83    child_config_view_ =
84        new WifiConfigView(this, static_cast<WifiNetwork*>(network));
85  } else if (network->type() == TYPE_WIMAX) {
86    child_config_view_ =
87        new WimaxConfigView(this, static_cast<WimaxNetwork*>(network));
88  } else if (network->type() == TYPE_VPN) {
89    child_config_view_ =
90        new VPNConfigView(this, static_cast<VirtualNetwork*>(network));
91  } else {
92    NOTREACHED();
93  }
94}
95
96NetworkConfigView::NetworkConfigView(ConnectionType type)
97    : child_config_view_(NULL),
98      delegate_(NULL),
99      advanced_button_(NULL) {
100  DCHECK(GetActiveDialog() == NULL);
101  SetActiveDialog(this);
102  if (type == TYPE_WIFI) {
103    child_config_view_ = new WifiConfigView(this, false /* show_8021x */);
104    advanced_button_ = new views::LabelButton(this, l10n_util::GetStringUTF16(
105        IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_ADVANCED_BUTTON));
106    advanced_button_->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON);
107  } else if (type == TYPE_VPN) {
108    child_config_view_ = new VPNConfigView(this);
109  } else {
110    NOTREACHED();
111  }
112}
113
114NetworkConfigView::~NetworkConfigView() {
115  DCHECK(GetActiveDialog() == this);
116  SetActiveDialog(NULL);
117}
118
119// static
120bool NetworkConfigView::Show(Network* network, gfx::NativeWindow parent) {
121  if (GetActiveDialog() != NULL)
122    return false;
123  NetworkConfigView* view = new NetworkConfigView(network);
124  view->ShowDialog(parent);
125  return true;
126}
127
128// static
129bool NetworkConfigView::ShowForType(ConnectionType type,
130                                    gfx::NativeWindow parent) {
131  if (GetActiveDialog() != NULL)
132    return false;
133  NetworkConfigView* view = new NetworkConfigView(type);
134  view->ShowDialog(parent);
135  return true;
136}
137
138gfx::NativeWindow NetworkConfigView::GetNativeWindow() const {
139  return GetWidget()->GetNativeWindow();
140}
141
142string16 NetworkConfigView::GetDialogButtonLabel(
143    ui::DialogButton button) const {
144  if (button == ui::DIALOG_BUTTON_OK)
145    return l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_CONNECT);
146  return views::DialogDelegateView::GetDialogButtonLabel(button);
147}
148
149bool NetworkConfigView::IsDialogButtonEnabled(ui::DialogButton button) const {
150  // Disable connect button if cannot login.
151  if (button == ui::DIALOG_BUTTON_OK)
152    return child_config_view_->CanLogin();
153  return true;
154}
155
156bool NetworkConfigView::Cancel() {
157  if (delegate_)
158    delegate_->OnDialogCancelled();
159  child_config_view_->Cancel();
160  return true;
161}
162
163bool NetworkConfigView::Accept() {
164  // Do not attempt login if it is guaranteed to fail, keep the dialog open.
165  if (!child_config_view_->CanLogin())
166    return false;
167  bool result = child_config_view_->Login();
168  if (result && delegate_)
169    delegate_->OnDialogAccepted();
170  return result;
171}
172
173views::View* NetworkConfigView::CreateExtraView() {
174  return advanced_button_;
175}
176
177views::View* NetworkConfigView::GetInitiallyFocusedView() {
178  return child_config_view_->GetInitiallyFocusedView();
179}
180
181string16 NetworkConfigView::GetWindowTitle() const {
182  DCHECK(!child_config_view_->GetTitle().empty());
183  return child_config_view_->GetTitle();
184}
185
186ui::ModalType NetworkConfigView::GetModalType() const {
187  return ui::MODAL_TYPE_SYSTEM;
188}
189
190void NetworkConfigView::GetAccessibleState(ui::AccessibleViewState* state) {
191  state->name =
192      l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_OTHER_WIFI_NETWORKS);
193  state->role = ui::AccessibilityTypes::ROLE_DIALOG;
194}
195
196void NetworkConfigView::ButtonPressed(views::Button* sender,
197                                      const ui::Event& event) {
198  if (advanced_button_ && sender == advanced_button_) {
199    advanced_button_->SetVisible(false);
200    ShowAdvancedView();
201  }
202}
203
204void NetworkConfigView::ShowAdvancedView() {
205  // Clear out the old widgets and build new ones.
206  RemoveChildView(child_config_view_);
207  delete child_config_view_;
208  // For now, there is only an advanced view for Wi-Fi 802.1X.
209  child_config_view_ = new WifiConfigView(this, true /* show_8021x */);
210  AddChildView(child_config_view_);
211  // Resize the window to be able to hold the new widgets.
212  gfx::Size size = views::Widget::GetLocalizedContentsSize(
213      IDS_JOIN_WIFI_NETWORK_DIALOG_ADVANCED_WIDTH_CHARS,
214      IDS_JOIN_WIFI_NETWORK_DIALOG_ADVANCED_MINIMUM_HEIGHT_LINES);
215  // Get the new bounds with desired size at the same center point.
216  gfx::Rect bounds = GetWidget()->GetWindowBoundsInScreen();
217  int horiz_padding = bounds.width() - size.width();
218  int vert_padding = bounds.height() - size.height();
219  bounds.Inset(horiz_padding / 2, vert_padding / 2,
220               horiz_padding / 2, vert_padding / 2);
221  GetWidget()->SetBoundsConstrained(bounds);
222  Layout();
223  child_config_view_->InitFocus();
224}
225
226void NetworkConfigView::Layout() {
227  child_config_view_->SetBounds(0, 0, width(), height());
228}
229
230gfx::Size NetworkConfigView::GetPreferredSize() {
231  gfx::Size result(views::Widget::GetLocalizedContentsSize(
232      IDS_JOIN_WIFI_NETWORK_DIALOG_WIDTH_CHARS,
233      IDS_JOIN_WIFI_NETWORK_DIALOG_MINIMUM_HEIGHT_LINES));
234  gfx::Size size = child_config_view_->GetPreferredSize();
235  result.set_height(size.height());
236  if (size.width() > result.width())
237    result.set_width(size.width());
238  return result;
239}
240
241void NetworkConfigView::ViewHierarchyChanged(
242    const ViewHierarchyChangedDetails& details) {
243  // Can't init before we're inserted into a Container, because we require
244  // a HWND to parent native child controls to.
245  if (details.is_add && details.child == this) {
246    AddChildView(child_config_view_);
247  }
248}
249
250void NetworkConfigView::ShowDialog(gfx::NativeWindow parent) {
251  if (parent == NULL)
252    parent = GetDialogParent();
253  // Failed connections may result in a pop-up with no natural parent window,
254  // so provide a fallback context on the active display.
255  gfx::NativeWindow context = parent ? NULL : ash::Shell::GetActiveRootWindow();
256  Widget* window = DialogDelegate::CreateDialogWidget(this, context, parent);
257  window->SetAlwaysOnTop(true);
258  window->Show();
259}
260
261ControlledSettingIndicatorView::ControlledSettingIndicatorView()
262    : managed_(false),
263      image_view_(NULL) {
264  Init();
265}
266
267ControlledSettingIndicatorView::ControlledSettingIndicatorView(
268    const NetworkPropertyUIData& ui_data)
269    : managed_(false),
270      image_view_(NULL) {
271  Init();
272  Update(ui_data);
273}
274
275ControlledSettingIndicatorView::~ControlledSettingIndicatorView() {}
276
277void ControlledSettingIndicatorView::Update(
278    const NetworkPropertyUIData& ui_data) {
279  if (managed_ == ui_data.IsManaged())
280    return;
281
282  managed_ = ui_data.IsManaged();
283  PreferredSizeChanged();
284}
285
286gfx::Size ControlledSettingIndicatorView::GetPreferredSize() {
287  return (managed_ && visible()) ? image_view_->GetPreferredSize()
288                                 : gfx::Size();
289}
290
291void ControlledSettingIndicatorView::Layout() {
292  image_view_->SetBounds(0, 0, width(), height());
293}
294
295void ControlledSettingIndicatorView::OnMouseEntered(
296    const ui::MouseEvent& event) {
297  image_view_->SetImage(color_image_);
298}
299
300void ControlledSettingIndicatorView::OnMouseExited(
301    const ui::MouseEvent& event) {
302  image_view_->SetImage(gray_image_);
303}
304
305void ControlledSettingIndicatorView::Init() {
306  color_image_ = ResourceBundle::GetSharedInstance().GetImageNamed(
307      IDR_CONTROLLED_SETTING_MANDATORY).ToImageSkia();
308  gray_image_ = ResourceBundle::GetSharedInstance().GetImageNamed(
309      IDR_CONTROLLED_SETTING_MANDATORY_GRAY).ToImageSkia();
310  image_view_ = new views::ImageView();
311  // Disable |image_view_| so mouse events propagate to the parent.
312  image_view_->SetEnabled(false);
313  image_view_->SetImage(gray_image_);
314  image_view_->SetTooltipText(
315      l10n_util::GetStringUTF16(IDS_OPTIONS_CONTROLLED_SETTING_POLICY));
316  AddChildView(image_view_);
317}
318
319}  // namespace chromeos
320