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.
5 #include "ui/views/window/dialog_delegate.h"
7 #include "base/logging.h"
8 #include "ui/accessibility/ax_view_state.h"
9 #include "ui/base/l10n/l10n_util.h"
10 #include "ui/strings/grit/ui_strings.h"
11 #include "ui/views/bubble/bubble_border.h"
12 #include "ui/views/bubble/bubble_frame_view.h"
13 #include "ui/views/controls/button/label_button.h"
14 #include "ui/views/widget/widget.h"
15 #include "ui/views/widget/widget_observer.h"
16 #include "ui/views/window/dialog_client_view.h"
19 #include "ui/base/win/shell.h"
24 ////////////////////////////////////////////////////////////////////////////////
27 DialogDelegate::DialogDelegate() : supports_new_style_(true) {
30 DialogDelegate::~DialogDelegate() {
34 Widget
* DialogDelegate::CreateDialogWidget(WidgetDelegate
* delegate
,
35 gfx::NativeWindow context
,
36 gfx::NativeView parent
) {
37 return CreateDialogWidgetWithBounds(delegate
, context
, parent
, gfx::Rect());
41 Widget
* DialogDelegate::CreateDialogWidgetWithBounds(WidgetDelegate
* delegate
,
42 gfx::NativeWindow context
,
43 gfx::NativeView parent
,
44 const gfx::Rect
& bounds
) {
45 views::Widget
* widget
= new views::Widget
;
46 views::Widget::InitParams params
;
47 params
.delegate
= delegate
;
48 params
.bounds
= bounds
;
49 DialogDelegate
* dialog
= delegate
->AsDialogDelegate();
51 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
52 // The new style doesn't support unparented dialogs on Linux desktop.
54 dialog
->supports_new_style_
&= parent
!= NULL
;
56 // The new style doesn't support unparented dialogs on Windows Classic themes.
57 if (dialog
&& !ui::win::IsAeroGlassEnabled())
58 dialog
->supports_new_style_
&= parent
!= NULL
;
61 if (!dialog
|| dialog
->UseNewStyleForThisDialog()) {
62 params
.opacity
= Widget::InitParams::TRANSLUCENT_WINDOW
;
63 params
.remove_standard_frame
= true;
64 #if !defined(OS_MACOSX)
65 // Except on Mac, the bubble frame includes its own shadow; remove any
66 // native shadowing. On Mac, the window server provides the shadow.
67 params
.shadow_type
= views::Widget::InitParams::SHADOW_TYPE_NONE
;
70 params
.context
= context
;
71 params
.parent
= parent
;
72 #if !defined(OS_MACOSX)
73 // Web-modal (ui::MODAL_TYPE_CHILD) dialogs with parents are marked as child
74 // widgets to prevent top-level window behavior (independent movement, etc).
75 // On Mac, however, the parent may be a native window (not a views::Widget),
76 // and so the dialog must be considered top-level to gain focus and input
78 params
.child
= parent
&& (delegate
->GetModalType() == ui::MODAL_TYPE_CHILD
);
84 View
* DialogDelegate::CreateExtraView() {
88 bool DialogDelegate::GetExtraViewPadding(int* padding
) {
92 View
* DialogDelegate::CreateTitlebarExtraView() {
96 View
* DialogDelegate::CreateFootnoteView() {
100 bool DialogDelegate::Cancel() {
104 bool DialogDelegate::Accept(bool window_closing
) {
108 bool DialogDelegate::Accept() {
112 bool DialogDelegate::Close() {
113 int buttons
= GetDialogButtons();
114 if ((buttons
& ui::DIALOG_BUTTON_CANCEL
) ||
115 (buttons
== ui::DIALOG_BUTTON_NONE
)) {
121 base::string16
DialogDelegate::GetDialogTitle() const {
122 return GetWindowTitle();
125 int DialogDelegate::GetDialogButtons() const {
126 return ui::DIALOG_BUTTON_OK
| ui::DIALOG_BUTTON_CANCEL
;
129 int DialogDelegate::GetDefaultDialogButton() const {
130 if (GetDialogButtons() & ui::DIALOG_BUTTON_OK
)
131 return ui::DIALOG_BUTTON_OK
;
132 if (GetDialogButtons() & ui::DIALOG_BUTTON_CANCEL
)
133 return ui::DIALOG_BUTTON_CANCEL
;
134 return ui::DIALOG_BUTTON_NONE
;
137 bool DialogDelegate::ShouldDefaultButtonBeBlue() const {
141 base::string16
DialogDelegate::GetDialogButtonLabel(
142 ui::DialogButton button
) const {
143 if (button
== ui::DIALOG_BUTTON_OK
)
144 return l10n_util::GetStringUTF16(IDS_APP_OK
);
145 if (button
== ui::DIALOG_BUTTON_CANCEL
) {
146 if (GetDialogButtons() & ui::DIALOG_BUTTON_OK
)
147 return l10n_util::GetStringUTF16(IDS_APP_CANCEL
);
148 return l10n_util::GetStringUTF16(IDS_APP_CLOSE
);
151 return base::string16();
154 bool DialogDelegate::IsDialogButtonEnabled(ui::DialogButton button
) const {
158 View
* DialogDelegate::GetInitiallyFocusedView() {
159 // Focus the default button if any.
160 const DialogClientView
* dcv
= GetDialogClientView();
161 int default_button
= GetDefaultDialogButton();
162 if (default_button
== ui::DIALOG_BUTTON_NONE
)
165 if ((default_button
& GetDialogButtons()) == 0) {
166 // The default button is a button we don't have.
171 if (default_button
& ui::DIALOG_BUTTON_OK
)
172 return dcv
->ok_button();
173 if (default_button
& ui::DIALOG_BUTTON_CANCEL
)
174 return dcv
->cancel_button();
178 DialogDelegate
* DialogDelegate::AsDialogDelegate() {
182 ClientView
* DialogDelegate::CreateClientView(Widget
* widget
) {
183 return new DialogClientView(widget
, GetContentsView());
186 NonClientFrameView
* DialogDelegate::CreateNonClientFrameView(Widget
* widget
) {
187 if (UseNewStyleForThisDialog())
188 return CreateDialogFrameView(widget
);
189 return WidgetDelegate::CreateNonClientFrameView(widget
);
193 NonClientFrameView
* DialogDelegate::CreateDialogFrameView(Widget
* widget
) {
194 BubbleFrameView
* frame
= new BubbleFrameView(gfx::Insets());
195 #if defined(OS_MACOSX)
196 // On Mac, dialogs have no border stroke and use a shadow provided by the OS.
197 const BubbleBorder::Shadow kShadow
= BubbleBorder::NO_ASSETS
;
199 const BubbleBorder::Shadow kShadow
= BubbleBorder::SMALL_SHADOW
;
201 scoped_ptr
<BubbleBorder
> border(
202 new BubbleBorder(BubbleBorder::FLOAT
, kShadow
, SK_ColorRED
));
203 border
->set_use_theme_background_color(true);
204 frame
->SetBubbleBorder(border
.Pass());
205 DialogDelegate
* delegate
= widget
->widget_delegate()->AsDialogDelegate();
207 View
* titlebar_view
= delegate
->CreateTitlebarExtraView();
209 frame
->SetTitlebarExtraView(titlebar_view
);
214 bool DialogDelegate::UseNewStyleForThisDialog() const {
215 return supports_new_style_
;
218 const DialogClientView
* DialogDelegate::GetDialogClientView() const {
219 return GetWidget()->client_view()->AsDialogClientView();
222 DialogClientView
* DialogDelegate::GetDialogClientView() {
223 return GetWidget()->client_view()->AsDialogClientView();
226 ui::AXRole
DialogDelegate::GetAccessibleWindowRole() const {
227 return ui::AX_ROLE_DIALOG
;
230 ////////////////////////////////////////////////////////////////////////////////
231 // DialogDelegateView:
233 DialogDelegateView::DialogDelegateView() {
234 // A WidgetDelegate should be deleted on DeleteDelegate.
235 set_owned_by_client();
238 DialogDelegateView::~DialogDelegateView() {}
240 void DialogDelegateView::DeleteDelegate() {
244 Widget
* DialogDelegateView::GetWidget() {
245 return View::GetWidget();
248 const Widget
* DialogDelegateView::GetWidget() const {
249 return View::GetWidget();
252 View
* DialogDelegateView::GetContentsView() {
256 void DialogDelegateView::GetAccessibleState(ui::AXViewState
* state
) {
257 state
->name
= GetDialogTitle();
258 state
->role
= ui::AX_ROLE_DIALOG
;
261 void DialogDelegateView::ViewHierarchyChanged(
262 const ViewHierarchyChangedDetails
& details
) {
263 if (details
.is_add
&& details
.child
== this && GetWidget())
264 NotifyAccessibilityEvent(ui::AX_EVENT_ALERT
, true);