diff options
Diffstat (limited to '')
-rw-r--r-- | linden/indra/llui/llmodaldialog.cpp | 307 |
1 files changed, 307 insertions, 0 deletions
diff --git a/linden/indra/llui/llmodaldialog.cpp b/linden/indra/llui/llmodaldialog.cpp new file mode 100644 index 0000000..c875e7c --- /dev/null +++ b/linden/indra/llui/llmodaldialog.cpp | |||
@@ -0,0 +1,307 @@ | |||
1 | /** | ||
2 | * @file llmodaldialog.cpp | ||
3 | * @brief LLModalDialog base class | ||
4 | * | ||
5 | * Copyright (c) 2002-2007, Linden Research, Inc. | ||
6 | * | ||
7 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
8 | * to you under the terms of the GNU General Public License, version 2.0 | ||
9 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
10 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
11 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
12 | * online at http://secondlife.com/developers/opensource/gplv2 | ||
13 | * | ||
14 | * There are special exceptions to the terms and conditions of the GPL as | ||
15 | * it is applied to this Source Code. View the full text of the exception | ||
16 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
17 | * online at http://secondlife.com/developers/opensource/flossexception | ||
18 | * | ||
19 | * By copying, modifying or distributing this software, you acknowledge | ||
20 | * that you have read and understood your obligations described above, | ||
21 | * and agree to abide by those obligations. | ||
22 | * | ||
23 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
24 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
25 | * COMPLETENESS OR PERFORMANCE. | ||
26 | */ | ||
27 | |||
28 | #include "linden_common.h" | ||
29 | |||
30 | #include "llmodaldialog.h" | ||
31 | |||
32 | #include "llfocusmgr.h" | ||
33 | #include "v4color.h" | ||
34 | #include "v2math.h" | ||
35 | #include "llui.h" | ||
36 | #include "llwindow.h" | ||
37 | #include "llkeyboard.h" | ||
38 | |||
39 | // static | ||
40 | std::list<LLModalDialog*> LLModalDialog::sModalStack; | ||
41 | |||
42 | LLModalDialog::LLModalDialog( const LLString& title, S32 width, S32 height, BOOL modal ) | ||
43 | : LLFloater( "modal container", | ||
44 | LLRect( 0, height, width, 0 ), | ||
45 | title, | ||
46 | FALSE, // resizable | ||
47 | DEFAULT_MIN_WIDTH, DEFAULT_MIN_HEIGHT, | ||
48 | FALSE, // drag_on_left | ||
49 | modal ? FALSE : TRUE, // minimizable | ||
50 | modal ? FALSE : TRUE, // close button | ||
51 | TRUE), // bordered | ||
52 | mModal( modal ) | ||
53 | { | ||
54 | setVisible( FALSE ); | ||
55 | setBackgroundVisible(TRUE); | ||
56 | setBackgroundOpaque(TRUE); | ||
57 | centerOnScreen(); // default position | ||
58 | } | ||
59 | |||
60 | LLModalDialog::~LLModalDialog() | ||
61 | { | ||
62 | // don't unlock focus unless we have it | ||
63 | if (gFocusMgr.childHasKeyboardFocus(this)) | ||
64 | { | ||
65 | gFocusMgr.unlockFocus(); | ||
66 | } | ||
67 | } | ||
68 | |||
69 | void LLModalDialog::reshape(S32 width, S32 height, BOOL called_from_parent) | ||
70 | { | ||
71 | LLFloater::reshape(width, height, called_from_parent); | ||
72 | centerOnScreen(); | ||
73 | } | ||
74 | |||
75 | void LLModalDialog::startModal() | ||
76 | { | ||
77 | if (mModal) | ||
78 | { | ||
79 | // If Modal, Hide the active modal dialog | ||
80 | if (!sModalStack.empty()) | ||
81 | { | ||
82 | LLModalDialog* front = sModalStack.front(); | ||
83 | front->setVisible(FALSE); | ||
84 | } | ||
85 | |||
86 | // This is a modal dialog. It sucks up all mouse and keyboard operations. | ||
87 | gFocusMgr.setMouseCapture( this, NULL ); | ||
88 | gFocusMgr.setTopView( this, NULL ); | ||
89 | setFocus(TRUE); | ||
90 | |||
91 | sModalStack.push_front( this ); | ||
92 | } | ||
93 | |||
94 | setVisible( TRUE ); | ||
95 | } | ||
96 | |||
97 | void LLModalDialog::stopModal() | ||
98 | { | ||
99 | gFocusMgr.unlockFocus(); | ||
100 | gFocusMgr.releaseFocusIfNeeded( this ); | ||
101 | |||
102 | if (mModal) | ||
103 | { | ||
104 | std::list<LLModalDialog*>::iterator iter = std::find(sModalStack.begin(), sModalStack.end(), this); | ||
105 | if (iter != sModalStack.end()) | ||
106 | { | ||
107 | sModalStack.erase(iter); | ||
108 | } | ||
109 | else | ||
110 | { | ||
111 | llwarns << "LLModalDialog::stopModal not in list!" << llendl; | ||
112 | } | ||
113 | } | ||
114 | if (!sModalStack.empty()) | ||
115 | { | ||
116 | LLModalDialog* front = sModalStack.front(); | ||
117 | front->setVisible(TRUE); | ||
118 | } | ||
119 | } | ||
120 | |||
121 | |||
122 | void LLModalDialog::setVisible( BOOL visible ) | ||
123 | { | ||
124 | if (mModal) | ||
125 | { | ||
126 | if( visible ) | ||
127 | { | ||
128 | // This is a modal dialog. It sucks up all mouse and keyboard operations. | ||
129 | gFocusMgr.setMouseCapture( this, NULL ); | ||
130 | |||
131 | // The dialog view is a root view | ||
132 | gFocusMgr.setTopView( this, NULL ); | ||
133 | setFocus( TRUE ); | ||
134 | } | ||
135 | else | ||
136 | { | ||
137 | gFocusMgr.releaseFocusIfNeeded( this ); | ||
138 | } | ||
139 | } | ||
140 | |||
141 | LLFloater::setVisible( visible ); | ||
142 | } | ||
143 | |||
144 | BOOL LLModalDialog::handleMouseDown(S32 x, S32 y, MASK mask) | ||
145 | { | ||
146 | if (!LLFloater::handleMouseDown(x, y, mask)) | ||
147 | { | ||
148 | if (mModal) | ||
149 | { | ||
150 | // Click was outside the panel | ||
151 | make_ui_sound("UISndInvalidOp"); | ||
152 | } | ||
153 | } | ||
154 | return TRUE; | ||
155 | } | ||
156 | |||
157 | BOOL LLModalDialog::handleHover(S32 x, S32 y, MASK mask) | ||
158 | { | ||
159 | if( childrenHandleHover(x, y, mask) == NULL ) | ||
160 | { | ||
161 | getWindow()->setCursor(UI_CURSOR_ARROW); | ||
162 | lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << llendl; | ||
163 | } | ||
164 | return TRUE; | ||
165 | } | ||
166 | |||
167 | BOOL LLModalDialog::handleMouseUp(S32 x, S32 y, MASK mask) | ||
168 | { | ||
169 | childrenHandleMouseUp(x, y, mask); | ||
170 | return TRUE; | ||
171 | } | ||
172 | |||
173 | BOOL LLModalDialog::handleScrollWheel(S32 x, S32 y, S32 clicks) | ||
174 | { | ||
175 | childrenHandleScrollWheel(x, y, clicks); | ||
176 | return TRUE; | ||
177 | } | ||
178 | |||
179 | BOOL LLModalDialog::handleDoubleClick(S32 x, S32 y, MASK mask) | ||
180 | { | ||
181 | if (!LLFloater::handleDoubleClick(x, y, mask)) | ||
182 | { | ||
183 | // Click outside the panel | ||
184 | make_ui_sound("UISndInvalidOp"); | ||
185 | } | ||
186 | return TRUE; | ||
187 | } | ||
188 | |||
189 | BOOL LLModalDialog::handleRightMouseDown(S32 x, S32 y, MASK mask) | ||
190 | { | ||
191 | childrenHandleRightMouseDown(x, y, mask); | ||
192 | return TRUE; | ||
193 | } | ||
194 | |||
195 | |||
196 | BOOL LLModalDialog::handleKeyHere(KEY key, MASK mask, BOOL called_from_parent ) | ||
197 | { | ||
198 | childrenHandleKey(key, mask); | ||
199 | |||
200 | LLFloater::handleKeyHere(key, mask, called_from_parent ); | ||
201 | |||
202 | if (mModal) | ||
203 | { | ||
204 | // Suck up all keystokes except CTRL-Q. | ||
205 | BOOL is_quit = ('Q' == key) && (MASK_CONTROL == mask); | ||
206 | return !is_quit; | ||
207 | } | ||
208 | else | ||
209 | { | ||
210 | // don't process escape key until message box has been on screen a minimal amount of time | ||
211 | // to avoid accidentally destroying the message box when user is hitting escape at the time it appears | ||
212 | BOOL enough_time_elapsed = mVisibleTime.getElapsedTimeF32() > 1.0f; | ||
213 | if (enough_time_elapsed && key == KEY_ESCAPE) | ||
214 | { | ||
215 | close(); | ||
216 | return TRUE; | ||
217 | } | ||
218 | return FALSE; | ||
219 | } | ||
220 | } | ||
221 | |||
222 | void LLModalDialog::onClose(bool app_quitting) | ||
223 | { | ||
224 | stopModal(); | ||
225 | LLFloater::onClose(app_quitting); | ||
226 | } | ||
227 | |||
228 | // virtual | ||
229 | void LLModalDialog::draw() | ||
230 | { | ||
231 | if (getVisible()) | ||
232 | { | ||
233 | LLColor4 shadow_color = LLUI::sColorsGroup->getColor("ColorDropShadow"); | ||
234 | S32 shadow_lines = LLUI::sConfigGroup->getS32("DropShadowFloater"); | ||
235 | |||
236 | gl_drop_shadow( 0, mRect.getHeight(), mRect.getWidth(), 0, | ||
237 | shadow_color, shadow_lines); | ||
238 | |||
239 | LLFloater::draw(); | ||
240 | |||
241 | if (mModal) | ||
242 | { | ||
243 | // If we've lost focus to a non-child, get it back ASAP. | ||
244 | if( gFocusMgr.getTopView() != this ) | ||
245 | { | ||
246 | gFocusMgr.setTopView( this, NULL); | ||
247 | } | ||
248 | |||
249 | if( !gFocusMgr.childHasKeyboardFocus( this ) ) | ||
250 | { | ||
251 | setFocus(TRUE); | ||
252 | } | ||
253 | |||
254 | if( !gFocusMgr.childHasMouseCapture( this ) ) | ||
255 | { | ||
256 | gFocusMgr.setMouseCapture( this, NULL ); | ||
257 | } | ||
258 | } | ||
259 | } | ||
260 | } | ||
261 | |||
262 | void LLModalDialog::centerOnScreen() | ||
263 | { | ||
264 | LLVector2 window_size = LLUI::getWindowSize(); | ||
265 | |||
266 | S32 dialog_left = (llround(window_size.mV[VX]) - mRect.getWidth()) / 2; | ||
267 | S32 dialog_bottom = (llround(window_size.mV[VY]) - mRect.getHeight()) / 2; | ||
268 | |||
269 | translate( dialog_left - mRect.mLeft, dialog_bottom - mRect.mBottom ); | ||
270 | } | ||
271 | |||
272 | |||
273 | // static | ||
274 | void LLModalDialog::onAppFocusLost() | ||
275 | { | ||
276 | if( !sModalStack.empty() ) | ||
277 | { | ||
278 | LLModalDialog* instance = LLModalDialog::sModalStack.front(); | ||
279 | if( gFocusMgr.childHasMouseCapture( instance ) ) | ||
280 | { | ||
281 | gFocusMgr.setMouseCapture( NULL, NULL ); | ||
282 | } | ||
283 | |||
284 | if( gFocusMgr.childHasKeyboardFocus( instance ) ) | ||
285 | { | ||
286 | gFocusMgr.setKeyboardFocus( NULL, NULL ); | ||
287 | } | ||
288 | } | ||
289 | } | ||
290 | |||
291 | // static | ||
292 | void LLModalDialog::onAppFocusGained() | ||
293 | { | ||
294 | if( !sModalStack.empty() ) | ||
295 | { | ||
296 | LLModalDialog* instance = LLModalDialog::sModalStack.front(); | ||
297 | |||
298 | // This is a modal dialog. It sucks up all mouse and keyboard operations. | ||
299 | gFocusMgr.setMouseCapture( instance, NULL ); | ||
300 | instance->setFocus(TRUE); | ||
301 | gFocusMgr.setTopView( instance, NULL ); | ||
302 | |||
303 | instance->centerOnScreen(); | ||
304 | } | ||
305 | } | ||
306 | |||
307 | |||