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 "ui/views/window/dialog_delegate.h"
6
7#include "base/logging.h"
8#include "ui/base/l10n/l10n_util.h"
9#include "ui/strings/grit/ui_strings.h"
10#include "ui/views/bubble/bubble_border.h"
11#include "ui/views/bubble/bubble_frame_view.h"
12#include "ui/views/controls/button/label_button.h"
13#include "ui/views/widget/widget.h"
14#include "ui/views/widget/widget_observer.h"
15#include "ui/views/window/dialog_client_view.h"
16
17#if defined(OS_WIN)
18#include "ui/base/win/shell.h"
19#endif
20
21namespace views {
22
23////////////////////////////////////////////////////////////////////////////////
24// DialogDelegate:
25
26DialogDelegate::DialogDelegate() : supports_new_style_(true) {
27}
28
29DialogDelegate::~DialogDelegate() {
30}
31
32// static
33Widget* DialogDelegate::CreateDialogWidget(WidgetDelegate* delegate,
34                                           gfx::NativeWindow context,
35                                           gfx::NativeView parent) {
36  return CreateDialogWidgetWithBounds(delegate, context, parent, gfx::Rect());
37}
38
39// static
40Widget* DialogDelegate::CreateDialogWidgetWithBounds(WidgetDelegate* delegate,
41                                                     gfx::NativeWindow context,
42                                                     gfx::NativeView parent,
43                                                     const gfx::Rect& bounds) {
44  views::Widget* widget = new views::Widget;
45  views::Widget::InitParams params;
46  params.delegate = delegate;
47  params.bounds = bounds;
48  DialogDelegate* dialog = delegate->AsDialogDelegate();
49
50#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
51  // The new style doesn't support unparented dialogs on Linux desktop.
52  if (dialog)
53    dialog->supports_new_style_ &= parent != NULL;
54#elif defined(OS_WIN)
55  // The new style doesn't support unparented dialogs on Windows Classic themes.
56  if (dialog && !ui::win::IsAeroGlassEnabled())
57    dialog->supports_new_style_ &= parent != NULL;
58#endif
59
60  if (!dialog || dialog->UseNewStyleForThisDialog()) {
61    params.opacity = Widget::InitParams::TRANSLUCENT_WINDOW;
62    params.remove_standard_frame = true;
63    // The bubble frame includes its own shadow; remove any native shadowing.
64    params.shadow_type = views::Widget::InitParams::SHADOW_TYPE_NONE;
65  }
66  params.context = context;
67  params.parent = parent;
68  // Web-modal (ui::MODAL_TYPE_CHILD) dialogs with parents are marked as child
69  // widgets to prevent top-level window behavior (independent movement, etc).
70  params.child = parent && (delegate->GetModalType() == ui::MODAL_TYPE_CHILD);
71  widget->Init(params);
72  return widget;
73}
74
75View* DialogDelegate::CreateExtraView() {
76  return NULL;
77}
78
79View* DialogDelegate::CreateTitlebarExtraView() {
80  return NULL;
81}
82
83View* DialogDelegate::CreateFootnoteView() {
84  return NULL;
85}
86
87bool DialogDelegate::Cancel() {
88  return true;
89}
90
91bool DialogDelegate::Accept(bool window_closing) {
92  return Accept();
93}
94
95bool DialogDelegate::Accept() {
96  return true;
97}
98
99bool DialogDelegate::Close() {
100  int buttons = GetDialogButtons();
101  if ((buttons & ui::DIALOG_BUTTON_CANCEL) ||
102      (buttons == ui::DIALOG_BUTTON_NONE)) {
103    return Cancel();
104  }
105  return Accept(true);
106}
107
108base::string16 DialogDelegate::GetDialogLabel() const {
109  return base::string16();
110}
111
112base::string16 DialogDelegate::GetDialogTitle() const {
113  return GetWindowTitle();
114}
115
116int DialogDelegate::GetDialogButtons() const {
117  return ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL;
118}
119
120int DialogDelegate::GetDefaultDialogButton() const {
121  if (GetDialogButtons() & ui::DIALOG_BUTTON_OK)
122    return ui::DIALOG_BUTTON_OK;
123  if (GetDialogButtons() & ui::DIALOG_BUTTON_CANCEL)
124    return ui::DIALOG_BUTTON_CANCEL;
125  return ui::DIALOG_BUTTON_NONE;
126}
127
128bool DialogDelegate::ShouldDefaultButtonBeBlue() const {
129  return false;
130}
131
132base::string16 DialogDelegate::GetDialogButtonLabel(
133    ui::DialogButton button) const {
134  if (button == ui::DIALOG_BUTTON_OK)
135    return l10n_util::GetStringUTF16(IDS_APP_OK);
136  if (button == ui::DIALOG_BUTTON_CANCEL) {
137    if (GetDialogButtons() & ui::DIALOG_BUTTON_OK)
138      return l10n_util::GetStringUTF16(IDS_APP_CANCEL);
139    return l10n_util::GetStringUTF16(IDS_APP_CLOSE);
140  }
141  NOTREACHED();
142  return base::string16();
143}
144
145bool DialogDelegate::IsDialogButtonEnabled(ui::DialogButton button) const {
146  return true;
147}
148
149View* DialogDelegate::GetInitiallyFocusedView() {
150  // Focus the default button if any.
151  const DialogClientView* dcv = GetDialogClientView();
152  int default_button = GetDefaultDialogButton();
153  if (default_button == ui::DIALOG_BUTTON_NONE)
154    return NULL;
155
156  if ((default_button & GetDialogButtons()) == 0) {
157    // The default button is a button we don't have.
158    NOTREACHED();
159    return NULL;
160  }
161
162  if (default_button & ui::DIALOG_BUTTON_OK)
163    return dcv->ok_button();
164  if (default_button & ui::DIALOG_BUTTON_CANCEL)
165    return dcv->cancel_button();
166  return NULL;
167}
168
169DialogDelegate* DialogDelegate::AsDialogDelegate() {
170  return this;
171}
172
173ClientView* DialogDelegate::CreateClientView(Widget* widget) {
174  return new DialogClientView(widget, GetContentsView());
175}
176
177NonClientFrameView* DialogDelegate::CreateNonClientFrameView(Widget* widget) {
178  if (UseNewStyleForThisDialog())
179    return CreateDialogFrameView(widget);
180  return WidgetDelegate::CreateNonClientFrameView(widget);
181}
182
183// static
184NonClientFrameView* DialogDelegate::CreateDialogFrameView(Widget* widget) {
185  BubbleFrameView* frame = new BubbleFrameView(gfx::Insets());
186  scoped_ptr<BubbleBorder> border(new BubbleBorder(
187      BubbleBorder::FLOAT, BubbleBorder::SMALL_SHADOW, SK_ColorRED));
188  border->set_use_theme_background_color(true);
189  frame->SetBubbleBorder(border.Pass());
190  DialogDelegate* delegate = widget->widget_delegate()->AsDialogDelegate();
191  if (delegate) {
192    View* titlebar_view = delegate->CreateTitlebarExtraView();
193    if (titlebar_view)
194      frame->SetTitlebarExtraView(titlebar_view);
195  }
196  return frame;
197}
198
199bool DialogDelegate::UseNewStyleForThisDialog() const {
200  return supports_new_style_;
201}
202
203const DialogClientView* DialogDelegate::GetDialogClientView() const {
204  return GetWidget()->client_view()->AsDialogClientView();
205}
206
207DialogClientView* DialogDelegate::GetDialogClientView() {
208  return GetWidget()->client_view()->AsDialogClientView();
209}
210
211ui::AXRole DialogDelegate::GetAccessibleWindowRole() const {
212  return ui::AX_ROLE_DIALOG;
213}
214
215////////////////////////////////////////////////////////////////////////////////
216// DialogDelegateView:
217
218DialogDelegateView::DialogDelegateView() {
219  // A WidgetDelegate should be deleted on DeleteDelegate.
220  set_owned_by_client();
221}
222
223DialogDelegateView::~DialogDelegateView() {}
224
225void DialogDelegateView::DeleteDelegate() {
226  delete this;
227}
228
229Widget* DialogDelegateView::GetWidget() {
230  return View::GetWidget();
231}
232
233const Widget* DialogDelegateView::GetWidget() const {
234  return View::GetWidget();
235}
236
237View* DialogDelegateView::GetContentsView() {
238  return this;
239}
240
241}  // namespace views
242