OLD | NEW |
| (Empty) |
1 // Copyright 2014 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 "remoting/host/chromeos/message_box.h" | |
6 | |
7 #include "ui/base/l10n/l10n_util.h" | |
8 #include "ui/views/controls/message_box_view.h" | |
9 #include "ui/views/widget/widget.h" | |
10 #include "ui/views/window/dialog_delegate.h" | |
11 | |
12 namespace remoting { | |
13 | |
14 // MessageBox::Core creates the dialog using the views::DialogWidget. The | |
15 // DialogWidget is created by the caller but its lifetime is managed by the | |
16 // NativeWidget. The DialogWidget communicates with the caller using the | |
17 //.DialogDelegateView interface, which must remain valid until DeleteDelegate() | |
18 // is called, at which the DialogDelegateView deletes itself. | |
19 // | |
20 // The Core class is introduced to abstract this awkward ownership model. The | |
21 // Core and the MessageBox hold a raw references to each other, which is | |
22 // invalidated when either side are destroyed. | |
23 class MessageBox::Core : public views::DialogDelegateView { | |
24 public: | |
25 Core(const base::string16& title_label, | |
26 const base::string16& message_label, | |
27 const base::string16& ok_label, | |
28 const base::string16& cancel_label, | |
29 ResultCallback result_callback, | |
30 MessageBox* message_box); | |
31 | |
32 // Mirrors the public MessageBox interface. | |
33 void Show(); | |
34 void Hide(); | |
35 | |
36 // views::DialogDelegateView interface. | |
37 bool Accept() override; | |
38 bool Cancel() override; | |
39 ui::ModalType GetModalType() const override; | |
40 base::string16 GetWindowTitle() const override; | |
41 base::string16 GetDialogButtonLabel(ui::DialogButton button) const override; | |
42 | |
43 // views::WidgetDelegate interface. | |
44 views::View* GetContentsView() override; | |
45 views::Widget* GetWidget() override; | |
46 const views::Widget* GetWidget() const override; | |
47 void DeleteDelegate() override; | |
48 | |
49 // Called by MessageBox::Core when it is destroyed. | |
50 void OnMessageBoxDestroyed(); | |
51 | |
52 private: | |
53 const base::string16 title_label_; | |
54 const base::string16 ok_label_; | |
55 const base::string16 cancel_label_; | |
56 ResultCallback result_callback_; | |
57 MessageBox* message_box_; | |
58 | |
59 // Owned by the native widget hierarchy. | |
60 views::MessageBoxView* message_box_view_; | |
61 | |
62 DISALLOW_COPY_AND_ASSIGN(Core); | |
63 }; | |
64 | |
65 MessageBox::Core::Core(const base::string16& title_label, | |
66 const base::string16& message_label, | |
67 const base::string16& ok_label, | |
68 const base::string16& cancel_label, | |
69 ResultCallback result_callback, | |
70 MessageBox* message_box) | |
71 : title_label_(title_label), | |
72 ok_label_(ok_label), | |
73 cancel_label_(cancel_label), | |
74 result_callback_(result_callback), | |
75 message_box_(message_box), | |
76 message_box_view_(new views::MessageBoxView( | |
77 views::MessageBoxView::InitParams(message_label))) { | |
78 DCHECK(message_box_); | |
79 } | |
80 | |
81 void MessageBox::Core::Show() { | |
82 // The widget is owned by the NativeWidget. See comments in widget.h. | |
83 views::Widget* widget = | |
84 CreateDialogWidget(this, /* delegate */ | |
85 nullptr /* parent window*/, | |
86 nullptr /* parent view */); | |
87 | |
88 if (widget) { | |
89 widget->Show(); | |
90 } | |
91 } | |
92 | |
93 void MessageBox::Core::Hide() { | |
94 if (GetWidget()) { | |
95 GetWidget()->Close(); | |
96 } | |
97 } | |
98 | |
99 bool MessageBox::Core::Accept() { | |
100 if (!result_callback_.is_null()) { | |
101 base::ResetAndReturn(&result_callback_).Run(OK); | |
102 } | |
103 return true /* close the window*/; | |
104 } | |
105 | |
106 bool MessageBox::Core::Cancel() { | |
107 if (!result_callback_.is_null()) { | |
108 base::ResetAndReturn(&result_callback_).Run(CANCEL); | |
109 } | |
110 return true /* close the window*/; | |
111 } | |
112 | |
113 ui::ModalType MessageBox::Core::GetModalType() const { | |
114 return ui::MODAL_TYPE_SYSTEM; | |
115 } | |
116 | |
117 base::string16 MessageBox::Core::GetWindowTitle() const { | |
118 return title_label_; | |
119 } | |
120 | |
121 base::string16 MessageBox::Core::GetDialogButtonLabel( | |
122 ui::DialogButton button) const { | |
123 switch (button) { | |
124 case ui::DIALOG_BUTTON_OK: | |
125 return ok_label_; | |
126 case ui::DIALOG_BUTTON_CANCEL: | |
127 return cancel_label_; | |
128 default: | |
129 NOTREACHED(); | |
130 return base::string16(); | |
131 } | |
132 } | |
133 | |
134 views::View* MessageBox::Core::GetContentsView() { | |
135 return message_box_view_; | |
136 } | |
137 | |
138 views::Widget* MessageBox::Core::GetWidget() { | |
139 return message_box_view_->GetWidget(); | |
140 } | |
141 | |
142 const views::Widget* MessageBox::Core::GetWidget() const { | |
143 return message_box_view_->GetWidget(); | |
144 } | |
145 | |
146 void MessageBox::Core::DeleteDelegate() { | |
147 if (message_box_) { | |
148 message_box_->core_ = nullptr; | |
149 } | |
150 delete this; | |
151 } | |
152 | |
153 void MessageBox::Core::OnMessageBoxDestroyed() { | |
154 DCHECK(message_box_); | |
155 message_box_ = nullptr; | |
156 // The callback should not be invoked after MessageBox is destroyed. | |
157 result_callback_.Reset(); | |
158 } | |
159 | |
160 MessageBox::MessageBox(const base::string16& title_label, | |
161 const base::string16& message_label, | |
162 const base::string16& ok_label, | |
163 const base::string16& cancel_label, | |
164 ResultCallback result_callback) | |
165 : core_(new Core(title_label, | |
166 message_label, | |
167 ok_label, | |
168 cancel_label, | |
169 result_callback, | |
170 this)) { | |
171 thread_checker_.DetachFromThread(); | |
172 } | |
173 | |
174 MessageBox::~MessageBox() { | |
175 if (core_) { | |
176 core_->OnMessageBoxDestroyed(); | |
177 core_->Hide(); | |
178 core_ = nullptr; | |
179 } | |
180 } | |
181 | |
182 void MessageBox::Show() { | |
183 DCHECK(thread_checker_.CalledOnValidThread()); | |
184 core_->Show(); | |
185 } | |
186 | |
187 void MessageBox::Hide() { | |
188 DCHECK(thread_checker_.CalledOnValidThread()); | |
189 if (core_) { | |
190 core_->Hide(); | |
191 } | |
192 } | |
193 | |
194 } // namespace remoting | |
OLD | NEW |