diff options
author | Jacek Antonelli | 2008-08-15 23:44:46 -0500 |
---|---|---|
committer | Jacek Antonelli | 2008-08-15 23:44:46 -0500 |
commit | 38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch) | |
tree | adca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/newview/llpreview.cpp | |
parent | README.txt (diff) | |
download | meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.zip meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.gz meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.bz2 meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.xz |
Second Life viewer sources 1.13.2.12
Diffstat (limited to 'linden/indra/newview/llpreview.cpp')
-rw-r--r-- | linden/indra/newview/llpreview.cpp | 513 |
1 files changed, 513 insertions, 0 deletions
diff --git a/linden/indra/newview/llpreview.cpp b/linden/indra/newview/llpreview.cpp new file mode 100644 index 0000000..c5dc414 --- /dev/null +++ b/linden/indra/newview/llpreview.cpp | |||
@@ -0,0 +1,513 @@ | |||
1 | /** | ||
2 | * @file llpreview.cpp | ||
3 | * @brief LLPreview class implementation | ||
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 "llviewerprecompiledheaders.h" | ||
29 | #include "stdenums.h" | ||
30 | |||
31 | #include "llpreview.h" | ||
32 | #include "lllineeditor.h" | ||
33 | #include "llinventory.h" | ||
34 | #include "llinventorymodel.h" | ||
35 | #include "llresmgr.h" | ||
36 | #include "lltextbox.h" | ||
37 | #include "llfocusmgr.h" | ||
38 | #include "lltooldraganddrop.h" | ||
39 | #include "llradiogroup.h" | ||
40 | #include "llassetstorage.h" | ||
41 | #include "llviewerobject.h" | ||
42 | #include "llviewerobjectlist.h" | ||
43 | #include "lldbstrings.h" | ||
44 | #include "llagent.h" | ||
45 | #include "llvoavatar.h" | ||
46 | #include "llselectmgr.h" | ||
47 | #include "llinventoryview.h" | ||
48 | #include "llviewerinventory.h" | ||
49 | |||
50 | // Constants | ||
51 | |||
52 | // Globals and statics | ||
53 | LLPreview::preview_multimap_t LLPreview::sPreviewsBySource; | ||
54 | LLPreview::preview_map_t LLPreview::sInstances; | ||
55 | |||
56 | // Functions | ||
57 | LLPreview::LLPreview(const std::string& name) : | ||
58 | LLFloater(name), | ||
59 | mCopyToInvBtn(NULL), | ||
60 | mForceClose(FALSE), | ||
61 | mCloseAfterSave(FALSE), | ||
62 | mAssetStatus(PREVIEW_ASSET_UNLOADED) | ||
63 | { | ||
64 | // don't add to instance list, since ItemID is null | ||
65 | mAuxItem = new LLInventoryItem; // (LLPointer is auto-deleted) | ||
66 | // don't necessarily steal focus on creation -- sometimes these guys pop up without user action | ||
67 | mAutoFocus = FALSE; | ||
68 | } | ||
69 | |||
70 | LLPreview::LLPreview(const std::string& name, const LLRect& rect, const std::string& title, const LLUUID& item_uuid, const LLUUID& object_uuid, BOOL allow_resize, S32 min_width, S32 min_height ) | ||
71 | : LLFloater(name, rect, title, allow_resize, min_width, min_height ), | ||
72 | mItemUUID(item_uuid), | ||
73 | mSourceID(LLUUID::null), | ||
74 | mObjectUUID(object_uuid), | ||
75 | mCopyToInvBtn( NULL ), | ||
76 | mForceClose( FALSE ), | ||
77 | mCloseAfterSave(FALSE), | ||
78 | mAssetStatus(PREVIEW_ASSET_UNLOADED) | ||
79 | { | ||
80 | mAuxItem = new LLInventoryItem; | ||
81 | // don't necessarily steal focus on creation -- sometimes these guys pop up without user action | ||
82 | mAutoFocus = FALSE; | ||
83 | |||
84 | if (mItemUUID.notNull()) | ||
85 | { | ||
86 | sInstances[mItemUUID] = this; | ||
87 | } | ||
88 | |||
89 | } | ||
90 | |||
91 | LLPreview::~LLPreview() | ||
92 | { | ||
93 | gFocusMgr.releaseFocusIfNeeded( this ); // calls onCommit() | ||
94 | |||
95 | if (mItemUUID.notNull()) | ||
96 | { | ||
97 | sInstances.erase( mItemUUID ); | ||
98 | } | ||
99 | |||
100 | if (mSourceID.notNull()) | ||
101 | { | ||
102 | preview_multimap_t::iterator found_it = sPreviewsBySource.find(mSourceID); | ||
103 | for (; found_it != sPreviewsBySource.end(); ++found_it) | ||
104 | { | ||
105 | if (found_it->second == mViewHandle) | ||
106 | { | ||
107 | sPreviewsBySource.erase(found_it); | ||
108 | break; | ||
109 | } | ||
110 | } | ||
111 | } | ||
112 | } | ||
113 | |||
114 | void LLPreview::setItemID(const LLUUID& item_id) | ||
115 | { | ||
116 | if (mItemUUID.notNull()) | ||
117 | { | ||
118 | sInstances.erase(mItemUUID); | ||
119 | } | ||
120 | |||
121 | mItemUUID = item_id; | ||
122 | |||
123 | if (mItemUUID.notNull()) | ||
124 | { | ||
125 | sInstances[mItemUUID] = this; | ||
126 | } | ||
127 | } | ||
128 | |||
129 | void LLPreview::setObjectID(const LLUUID& object_id) | ||
130 | { | ||
131 | mObjectUUID = object_id; | ||
132 | } | ||
133 | |||
134 | void LLPreview::setSourceID(const LLUUID& source_id) | ||
135 | { | ||
136 | if (mSourceID.notNull()) | ||
137 | { | ||
138 | // erase old one | ||
139 | preview_multimap_t::iterator found_it = sPreviewsBySource.find(mSourceID); | ||
140 | for (; found_it != sPreviewsBySource.end(); ++found_it) | ||
141 | { | ||
142 | if (found_it->second == mViewHandle) | ||
143 | { | ||
144 | sPreviewsBySource.erase(found_it); | ||
145 | break; | ||
146 | } | ||
147 | } | ||
148 | } | ||
149 | mSourceID = source_id; | ||
150 | sPreviewsBySource.insert(preview_multimap_t::value_type(mSourceID, mViewHandle)); | ||
151 | } | ||
152 | |||
153 | LLViewerInventoryItem* LLPreview::getItem() const | ||
154 | { | ||
155 | LLViewerInventoryItem* item = NULL; | ||
156 | if(mObjectUUID.isNull()) | ||
157 | { | ||
158 | // it's an inventory item, so get the item. | ||
159 | item = gInventory.getItem(mItemUUID); | ||
160 | } | ||
161 | else | ||
162 | { | ||
163 | // it's an object's inventory item. | ||
164 | LLViewerObject* object = gObjectList.findObject(mObjectUUID); | ||
165 | if(object) | ||
166 | { | ||
167 | item = (LLViewerInventoryItem*)object->getInventoryObject(mItemUUID); | ||
168 | } | ||
169 | } | ||
170 | return item; | ||
171 | } | ||
172 | |||
173 | // Sub-classes should override this function if they allow editing | ||
174 | void LLPreview::onCommit() | ||
175 | { | ||
176 | LLViewerInventoryItem* item = getItem(); | ||
177 | if(item) | ||
178 | { | ||
179 | if (!item->isComplete()) | ||
180 | { | ||
181 | // We are attempting to save an item that was never loaded | ||
182 | llwarns << "LLPreview::onCommit() called with mIsComplete == FALSE" | ||
183 | << " Type: " << item->getType() | ||
184 | << " ID: " << item->getUUID() | ||
185 | << llendl; | ||
186 | return; | ||
187 | } | ||
188 | |||
189 | LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item); | ||
190 | BOOL has_sale_info = FALSE; | ||
191 | LLSaleInfo sale_info; | ||
192 | new_item->setDescription(childGetText("desc")); | ||
193 | if(mObjectUUID.notNull()) | ||
194 | { | ||
195 | // must be in an object | ||
196 | LLViewerObject* object = gObjectList.findObject(mObjectUUID); | ||
197 | if(object) | ||
198 | { | ||
199 | object->updateInventory( | ||
200 | new_item, | ||
201 | TASK_INVENTORY_ITEM_KEY, | ||
202 | false); | ||
203 | } | ||
204 | } | ||
205 | else if(item->getPermissions().getOwner() == gAgent.getID()) | ||
206 | { | ||
207 | new_item->updateServer(FALSE); | ||
208 | gInventory.updateItem(new_item); | ||
209 | |||
210 | // If the item is an attachment that is currently being worn, | ||
211 | // update the object itself. | ||
212 | if( item->getType() == LLAssetType::AT_OBJECT ) | ||
213 | { | ||
214 | LLVOAvatar* avatar = gAgent.getAvatarObject(); | ||
215 | if( avatar ) | ||
216 | { | ||
217 | LLViewerObject* obj = avatar->getWornAttachment( item->getUUID() ); | ||
218 | if( obj ) | ||
219 | { | ||
220 | gSelectMgr->deselectAll(); | ||
221 | gSelectMgr->addAsIndividual( obj, SELECT_ALL_TES, FALSE ); | ||
222 | gSelectMgr->setObjectDescription( childGetText("desc") ); | ||
223 | |||
224 | if( has_sale_info ) | ||
225 | { | ||
226 | gSelectMgr->setObjectSaleInfo( sale_info ); | ||
227 | } | ||
228 | |||
229 | gSelectMgr->deselectAll(); | ||
230 | } | ||
231 | } | ||
232 | } | ||
233 | } | ||
234 | } | ||
235 | } | ||
236 | |||
237 | // static | ||
238 | void LLPreview::onText(LLUICtrl*, void* userdata) | ||
239 | { | ||
240 | LLPreview* self = (LLPreview*) userdata; | ||
241 | self->onCommit(); | ||
242 | } | ||
243 | |||
244 | // static | ||
245 | void LLPreview::onRadio(LLUICtrl*, void* userdata) | ||
246 | { | ||
247 | LLPreview* self = (LLPreview*) userdata; | ||
248 | self->onCommit(); | ||
249 | } | ||
250 | |||
251 | // static | ||
252 | LLPreview* LLPreview::find(const LLUUID& item_uuid) | ||
253 | { | ||
254 | LLPreview* instance = NULL; | ||
255 | preview_map_t::iterator found_it = LLPreview::sInstances.find(item_uuid); | ||
256 | if(found_it != LLPreview::sInstances.end()) | ||
257 | { | ||
258 | instance = found_it->second; | ||
259 | } | ||
260 | return instance; | ||
261 | } | ||
262 | |||
263 | // static | ||
264 | LLPreview* LLPreview::show( const LLUUID& item_uuid, BOOL take_focus ) | ||
265 | { | ||
266 | LLPreview* instance = LLPreview::find(item_uuid); | ||
267 | if(instance) | ||
268 | { | ||
269 | if (LLFloater::getFloaterHost() && LLFloater::getFloaterHost() != instance->getHost()) | ||
270 | { | ||
271 | // this preview window is being opened in a new context | ||
272 | // needs to be rehosted | ||
273 | LLFloater::getFloaterHost()->addFloater(instance, TRUE); | ||
274 | } | ||
275 | instance->open(); | ||
276 | if (take_focus) | ||
277 | { | ||
278 | instance->setFocus(TRUE); | ||
279 | } | ||
280 | } | ||
281 | |||
282 | return instance; | ||
283 | } | ||
284 | |||
285 | // static | ||
286 | bool LLPreview::save( const LLUUID& item_uuid, LLPointer<LLInventoryItem>* itemptr ) | ||
287 | { | ||
288 | bool res = false; | ||
289 | LLPreview* instance = LLPreview::find(item_uuid); | ||
290 | if(instance) | ||
291 | { | ||
292 | res = instance->saveItem(itemptr); | ||
293 | } | ||
294 | if (!res) | ||
295 | { | ||
296 | delete itemptr; | ||
297 | } | ||
298 | return res; | ||
299 | } | ||
300 | |||
301 | // static | ||
302 | void LLPreview::hide(const LLUUID& item_uuid) | ||
303 | { | ||
304 | preview_map_t::iterator found_it = LLPreview::sInstances.find(item_uuid); | ||
305 | if(found_it != LLPreview::sInstances.end()) | ||
306 | { | ||
307 | LLPreview* instance = found_it->second; | ||
308 | instance->close(); | ||
309 | } | ||
310 | } | ||
311 | |||
312 | // static | ||
313 | void LLPreview::rename(const LLUUID& item_uuid, const std::string& new_name) | ||
314 | { | ||
315 | preview_map_t::iterator found_it = LLPreview::sInstances.find(item_uuid); | ||
316 | if(found_it != LLPreview::sInstances.end()) | ||
317 | { | ||
318 | LLPreview* instance = found_it->second; | ||
319 | instance->setTitle( new_name ); | ||
320 | } | ||
321 | } | ||
322 | |||
323 | BOOL LLPreview::handleMouseDown(S32 x, S32 y, MASK mask) | ||
324 | { | ||
325 | if(mClientRect.pointInRect(x, y)) | ||
326 | { | ||
327 | // No handler needed for focus lost since this class has no | ||
328 | // state that depends on it. | ||
329 | bringToFront(x, y); | ||
330 | gFocusMgr.setMouseCapture(this, NULL); | ||
331 | S32 screen_x; | ||
332 | S32 screen_y; | ||
333 | localPointToScreen(x, y, &screen_x, &screen_y ); | ||
334 | gToolDragAndDrop->setDragStart(screen_x, screen_y); | ||
335 | return TRUE; | ||
336 | } | ||
337 | return LLFloater::handleMouseDown(x, y, mask); | ||
338 | } | ||
339 | |||
340 | BOOL LLPreview::handleMouseUp(S32 x, S32 y, MASK mask) | ||
341 | { | ||
342 | if(gFocusMgr.getMouseCapture() == this) | ||
343 | { | ||
344 | gFocusMgr.setMouseCapture(NULL, NULL); | ||
345 | return TRUE; | ||
346 | } | ||
347 | return LLFloater::handleMouseUp(x, y, mask); | ||
348 | } | ||
349 | |||
350 | BOOL LLPreview::handleHover(S32 x, S32 y, MASK mask) | ||
351 | { | ||
352 | if(gFocusMgr.getMouseCapture() == this) | ||
353 | { | ||
354 | S32 screen_x; | ||
355 | S32 screen_y; | ||
356 | LLViewerInventoryItem *item = getItem(); | ||
357 | |||
358 | localPointToScreen(x, y, &screen_x, &screen_y ); | ||
359 | if(item | ||
360 | && item->getPermissions().allowCopyBy(gAgent.getID(), | ||
361 | gAgent.getGroupID()) | ||
362 | && gToolDragAndDrop->isOverThreshold(screen_x, screen_y)) | ||
363 | { | ||
364 | EDragAndDropType type; | ||
365 | type = LLAssetType::lookupDragAndDropType(item->getType()); | ||
366 | LLToolDragAndDrop::ESource src = LLToolDragAndDrop::SOURCE_LIBRARY; | ||
367 | if(!mObjectUUID.isNull()) | ||
368 | { | ||
369 | src = LLToolDragAndDrop::SOURCE_WORLD; | ||
370 | } | ||
371 | else if(item->getPermissions().getOwner() == gAgent.getID()) | ||
372 | { | ||
373 | src = LLToolDragAndDrop::SOURCE_AGENT; | ||
374 | } | ||
375 | gToolDragAndDrop->beginDrag(type, | ||
376 | item->getUUID(), | ||
377 | src, | ||
378 | mObjectUUID); | ||
379 | return gToolDragAndDrop->handleHover(x, y, mask ); | ||
380 | } | ||
381 | } | ||
382 | return LLFloater::handleHover(x,y,mask); | ||
383 | } | ||
384 | |||
385 | void LLPreview::open() | ||
386 | { | ||
387 | LLMultiFloater* hostp = getHost(); | ||
388 | if (!sHostp && !hostp && getAssetStatus() == PREVIEW_ASSET_UNLOADED) | ||
389 | { | ||
390 | loadAsset(); | ||
391 | } | ||
392 | LLFloater::open(); | ||
393 | } | ||
394 | |||
395 | // virtual | ||
396 | bool LLPreview::saveItem(LLPointer<LLInventoryItem>* itemptr) | ||
397 | { | ||
398 | return false; | ||
399 | } | ||
400 | |||
401 | |||
402 | // static | ||
403 | void LLPreview::onBtnCopyToInv(void* userdata) | ||
404 | { | ||
405 | LLPreview* self = (LLPreview*) userdata; | ||
406 | LLInventoryItem *item = self->mAuxItem; | ||
407 | |||
408 | if(item && item->getUUID().notNull()) | ||
409 | { | ||
410 | // Copy to inventory | ||
411 | if (self->mNotecardInventoryID.notNull()) | ||
412 | { | ||
413 | copy_inventory_from_notecard(self->mObjectID, | ||
414 | self->mNotecardInventoryID, item); | ||
415 | } | ||
416 | else | ||
417 | { | ||
418 | LLPointer<LLInventoryCallback> cb = NULL; | ||
419 | copy_inventory_item( | ||
420 | gAgent.getID(), | ||
421 | item->getPermissions().getOwner(), | ||
422 | item->getUUID(), | ||
423 | LLUUID::null, | ||
424 | std::string(), | ||
425 | cb); | ||
426 | } | ||
427 | } | ||
428 | } | ||
429 | |||
430 | // static | ||
431 | void LLPreview::onKeepBtn(void* data) | ||
432 | { | ||
433 | LLPreview* self = (LLPreview*)data; | ||
434 | self->close(); | ||
435 | } | ||
436 | |||
437 | // static | ||
438 | void LLPreview::onDiscardBtn(void* data) | ||
439 | { | ||
440 | LLPreview* self = (LLPreview*)data; | ||
441 | |||
442 | LLViewerInventoryItem* item = self->getItem(); | ||
443 | if (!item) return; | ||
444 | |||
445 | self->mForceClose = TRUE; | ||
446 | self->close(); | ||
447 | |||
448 | // Delete the item entirely | ||
449 | /* | ||
450 | item->removeFromServer(); | ||
451 | gInventory.deleteObject(item->getUUID()); | ||
452 | gInventory.notifyObservers(); | ||
453 | */ | ||
454 | |||
455 | // Move the item to the trash | ||
456 | LLUUID trash_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_TRASH); | ||
457 | if (item->getParentUUID() != trash_id) | ||
458 | { | ||
459 | LLInventoryModel::update_list_t update; | ||
460 | LLInventoryModel::LLCategoryUpdate old_folder(item->getParentUUID(),-1); | ||
461 | update.push_back(old_folder); | ||
462 | LLInventoryModel::LLCategoryUpdate new_folder(trash_id, 1); | ||
463 | update.push_back(new_folder); | ||
464 | gInventory.accountForUpdate(update); | ||
465 | |||
466 | LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item); | ||
467 | new_item->setParent(trash_id); | ||
468 | // no need to restamp it though it's a move into trash because | ||
469 | // it's a brand new item already. | ||
470 | new_item->updateParentOnServer(FALSE); | ||
471 | gInventory.updateItem(new_item); | ||
472 | gInventory.notifyObservers(); | ||
473 | } | ||
474 | } | ||
475 | |||
476 | //static | ||
477 | LLPreview* LLPreview::getFirstPreviewForSource(const LLUUID& source_id) | ||
478 | { | ||
479 | preview_multimap_t::iterator found_it = sPreviewsBySource.find(source_id); | ||
480 | if (found_it != sPreviewsBySource.end()) | ||
481 | { | ||
482 | // just return first one | ||
483 | return (LLPreview*)LLFloater::getFloaterByHandle(found_it->second); | ||
484 | } | ||
485 | return NULL; | ||
486 | } | ||
487 | |||
488 | // | ||
489 | // LLMultiPreview | ||
490 | // | ||
491 | |||
492 | LLMultiPreview::LLMultiPreview(const LLRect& rect) : LLMultiFloater("Preview", rect) | ||
493 | { | ||
494 | } | ||
495 | |||
496 | void LLMultiPreview::open() | ||
497 | { | ||
498 | LLMultiFloater::open(); | ||
499 | LLPreview* frontmost_preview = (LLPreview*)mTabContainer->getCurrentPanel(); | ||
500 | if (frontmost_preview && frontmost_preview->getAssetStatus() == LLPreview::PREVIEW_ASSET_UNLOADED) | ||
501 | { | ||
502 | frontmost_preview->loadAsset(); | ||
503 | } | ||
504 | } | ||
505 | |||
506 | void LLMultiPreview::tabOpen(LLFloater* opened_floater, bool from_click) | ||
507 | { | ||
508 | LLPreview* opened_preview = (LLPreview*)opened_floater; | ||
509 | if (opened_preview && opened_preview->getAssetStatus() == LLPreview::PREVIEW_ASSET_UNLOADED) | ||
510 | { | ||
511 | opened_preview->loadAsset(); | ||
512 | } | ||
513 | } | ||