diff --git a/indra/integration_tests/llui_libtest/llui_libtest.cpp b/indra/integration_tests/llui_libtest/llui_libtest.cpp index f8caa7990b3516aa3fe02101827466f42af2641b..1e5de74e92b2837eca3661a46e39eafa595e6675 100644 --- a/indra/integration_tests/llui_libtest/llui_libtest.cpp +++ b/indra/integration_tests/llui_libtest/llui_libtest.cpp @@ -104,25 +104,27 @@ static std::string get_xui_dir() return gDirUtilp->getAppRODataDir() + delim + std::string("skins") + delim + "default" + delim + "xui" + delim; } -int main(int argc, char** argv) +void init_llui() { - // Must init LLError for llerrs to actually cause errors. - LLError::initForApplication("."); - // Font lookup needs directory support - gDirUtilp->initAppDirs("SecondLife", "../../../newview"); +#if LL_DARWIN + const char* newview_path = "../../../../newview"; +#else + const char* newview_path = "../../../newview"; +#endif + gDirUtilp->initAppDirs("SecondLife", newview_path); gDirUtilp->setSkinFolder("default"); - + std::string config_filename = gDirUtilp->getExpandedFilename( - LL_PATH_APP_SETTINGS, "settings.xml"); + LL_PATH_APP_SETTINGS, "settings.xml"); LLControlGroup config_group("config"); config_group.loadFromFile(config_filename); - + std::string color_filename = gDirUtilp->getExpandedFilename( - LL_PATH_DEFAULT_SKIN, "colors.xml"); + LL_PATH_DEFAULT_SKIN, "colors.xml"); LLControlGroup color_group("color"); color_group.loadFromFile(color_filename); - + LLControlGroup floater_group("floater"); LLControlGroup ignores_group("ignores"); LLUI::settings_map_t settings; @@ -130,14 +132,14 @@ int main(int argc, char** argv) settings["color"] = &color_group; settings["floater"] = &floater_group; settings["ignores"] = &ignores_group; - + // Don't use real images as we don't have a GL context TestImageProvider image_provider; LLUI::initClass(settings, &image_provider); - + const bool no_register_widgets = false; LLWidgetReg::initClass( no_register_widgets ); - + // Unclear if this is needed LLUI::setupPaths(); // Otherwise we get translation warnings when setting up floaters @@ -146,14 +148,14 @@ int main(int argc, char** argv) LLTrans::parseStrings("strings.xml", default_args); LLFontManager::initClass(); - + // Creating widgets apparently requires fonts to be initialized, // otherwise it crashes. LLFontGL::initClass(96.f, 1.f, 1.f, - gDirUtilp->getAppRODataDir(), - LLUI::getXUIPaths(), - false ); // don't create gl textures - + gDirUtilp->getAppRODataDir(), + LLUI::getXUIPaths(), + false ); // don't create gl textures + LLFloaterView::Params fvparams; fvparams.name("Floater View"); fvparams.rect( LLRect(0,480,640,0) ); @@ -161,7 +163,10 @@ int main(int argc, char** argv) fvparams.follows.flags(FOLLOWS_ALL); fvparams.tab_stop(false); gFloaterView = LLUICtrlFactory::create<LLFloaterView> (fvparams); +} +void export_test_floaters() +{ // Convert all test floaters to new XML format std::string delim = gDirUtilp->getDirDelimiter(); std::string xui_dir = get_xui_dir() + "en" + delim; @@ -178,19 +183,30 @@ int main(int argc, char** argv) LLXMLNodePtr output_node = new LLXMLNode(); LLFloater* floater = new LLFloater(); LLUICtrlFactory::getInstance()->buildFloater(floater, - filename, - FALSE, // don't open floater - output_node); + filename, + FALSE, // don't open floater + output_node); std::string out_filename = xui_dir + filename; std::string::size_type extension_pos = out_filename.rfind(".xml"); out_filename.resize(extension_pos); out_filename += "_new.xml"; - + llinfos << "Output: " << out_filename << llendl; LLFILE* floater_file = LLFile::fopen(out_filename.c_str(), "w"); LLXMLNode::writeHeaderToFile(floater_file); output_node->writeToFile(floater_file); fclose(floater_file); } +} + +int main(int argc, char** argv) +{ + // Must init LLError for llerrs to actually cause errors. + LLError::initForApplication("."); + + init_llui(); + + export_test_floaters(); + return 0; } diff --git a/indra/integration_tests/llui_libtest/llwidgetreg.cpp b/indra/integration_tests/llui_libtest/llwidgetreg.cpp index 417f3059d6c8097c38ed89fc4cab2d73306e9ec9..4e59971f29d5f9b601ed8a62597262f9ea09634b 100644 --- a/indra/integration_tests/llui_libtest/llwidgetreg.cpp +++ b/indra/integration_tests/llui_libtest/llwidgetreg.cpp @@ -62,45 +62,45 @@ void LLWidgetReg::initClass(bool register_widgets) // references to the object files. if (register_widgets) { - LLDefaultWidgetRegistry::Register<LLButton> button("button"); - LLDefaultWidgetRegistry::Register<LLCheckBoxCtrl> check_box("check_box"); - LLDefaultWidgetRegistry::Register<LLComboBox> combo_box("combo_box"); - LLDefaultWidgetRegistry::Register<LLFlyoutButton> flyout_button("flyout_button"); - LLDefaultWidgetRegistry::Register<LLContainerView> container_view("container_view"); - LLDefaultWidgetRegistry::Register<LLIconCtrl> icon("icon"); - LLDefaultWidgetRegistry::Register<LLLineEditor> line_editor("line_editor"); - LLDefaultWidgetRegistry::Register<LLSearchEditor> search_editor("search_editor"); - LLDefaultWidgetRegistry::Register<LLMenuItemSeparatorGL> menu_item_separator("menu_item_separator"); - LLDefaultWidgetRegistry::Register<LLMenuItemCallGL> menu_item_call_gl("menu_item_call"); - LLDefaultWidgetRegistry::Register<LLMenuItemCheckGL> menu_item_check_gl("menu_item_check"); - LLDefaultWidgetRegistry::Register<LLMenuGL> menu("menu"); - LLDefaultWidgetRegistry::Register<LLMenuBarGL> menu_bar("menu_bar"); - LLDefaultWidgetRegistry::Register<LLContextMenu> context_menu("context_menu"); - LLDefaultWidgetRegistry::Register<LLMultiSlider> multi_slider_bar("multi_slider_bar"); - LLDefaultWidgetRegistry::Register<LLMultiSliderCtrl> multi_slider("multi_slider"); - LLDefaultWidgetRegistry::Register<LLPanel> panel("panel", &LLPanel::fromXML); - LLDefaultWidgetRegistry::Register<LLLayoutStack> layout_stack("layout_stack", &LLLayoutStack::fromXML); - LLDefaultWidgetRegistry::Register<LLProgressBar> progress_bar("progress_bar"); - LLDefaultWidgetRegistry::Register<LLRadioGroup> radio_group("radio_group"); - LLDefaultWidgetRegistry::Register<LLRadioCtrl> radio_item("radio_item"); - LLDefaultWidgetRegistry::Register<LLScrollContainer> scroll_container("scroll_container"); - LLDefaultWidgetRegistry::Register<LLScrollingPanelList> scrolling_panel_list("scrolling_panel_list"); - LLDefaultWidgetRegistry::Register<LLScrollListCtrl> scroll_list("scroll_list"); - LLDefaultWidgetRegistry::Register<LLSlider> slider_bar("slider_bar"); - LLDefaultWidgetRegistry::Register<LLSliderCtrl> slider("slider"); - LLDefaultWidgetRegistry::Register<LLSpinCtrl> spinner("spinner"); - LLDefaultWidgetRegistry::Register<LLStatBar> stat_bar("stat_bar"); - //LLDefaultWidgetRegistry::Register<LLPlaceHolderPanel> placeholder("placeholder"); - LLDefaultWidgetRegistry::Register<LLTabContainer> tab_container("tab_container"); - LLDefaultWidgetRegistry::Register<LLTextBox> text("text"); - LLDefaultWidgetRegistry::Register<LLTextEditor> simple_text_editor("simple_text_editor"); - LLDefaultWidgetRegistry::Register<LLUICtrl> ui_ctrl("ui_ctrl"); - LLDefaultWidgetRegistry::Register<LLStatView> stat_view("stat_view"); - //LLDefaultWidgetRegistry::Register<LLUICtrlLocate> locate("locate"); - //LLDefaultWidgetRegistry::Register<LLUICtrlLocate> pad("pad"); - LLDefaultWidgetRegistry::Register<LLViewBorder> view_border("view_border"); + LLDefaultChildRegistry::Register<LLButton> button("button"); + LLDefaultChildRegistry::Register<LLCheckBoxCtrl> check_box("check_box"); + LLDefaultChildRegistry::Register<LLComboBox> combo_box("combo_box"); + LLDefaultChildRegistry::Register<LLFlyoutButton> flyout_button("flyout_button"); + LLDefaultChildRegistry::Register<LLContainerView> container_view("container_view"); + LLDefaultChildRegistry::Register<LLIconCtrl> icon("icon"); + LLDefaultChildRegistry::Register<LLLineEditor> line_editor("line_editor"); + LLDefaultChildRegistry::Register<LLSearchEditor> search_editor("search_editor"); + LLDefaultChildRegistry::Register<LLMenuItemSeparatorGL> menu_item_separator("menu_item_separator"); + LLDefaultChildRegistry::Register<LLMenuItemCallGL> menu_item_call_gl("menu_item_call"); + LLDefaultChildRegistry::Register<LLMenuItemCheckGL> menu_item_check_gl("menu_item_check"); + LLDefaultChildRegistry::Register<LLMenuGL> menu("menu"); + LLDefaultChildRegistry::Register<LLMenuBarGL> menu_bar("menu_bar"); + LLDefaultChildRegistry::Register<LLContextMenu> context_menu("context_menu"); + LLDefaultChildRegistry::Register<LLMultiSlider> multi_slider_bar("multi_slider_bar"); + LLDefaultChildRegistry::Register<LLMultiSliderCtrl> multi_slider("multi_slider"); + LLDefaultChildRegistry::Register<LLPanel> panel("panel", &LLPanel::fromXML); + LLDefaultChildRegistry::Register<LLLayoutStack> layout_stack("layout_stack", &LLLayoutStack::fromXML); + LLDefaultChildRegistry::Register<LLProgressBar> progress_bar("progress_bar"); + LLDefaultChildRegistry::Register<LLRadioGroup> radio_group("radio_group"); + LLDefaultChildRegistry::Register<LLRadioCtrl> radio_item("radio_item"); + LLDefaultChildRegistry::Register<LLScrollContainer> scroll_container("scroll_container"); + LLDefaultChildRegistry::Register<LLScrollingPanelList> scrolling_panel_list("scrolling_panel_list"); + LLDefaultChildRegistry::Register<LLScrollListCtrl> scroll_list("scroll_list"); + LLDefaultChildRegistry::Register<LLSlider> slider_bar("slider_bar"); + LLDefaultChildRegistry::Register<LLSliderCtrl> slider("slider"); + LLDefaultChildRegistry::Register<LLSpinCtrl> spinner("spinner"); + LLDefaultChildRegistry::Register<LLStatBar> stat_bar("stat_bar"); + //LLDefaultChildRegistry::Register<LLPlaceHolderPanel> placeholder("placeholder"); + LLDefaultChildRegistry::Register<LLTabContainer> tab_container("tab_container"); + LLDefaultChildRegistry::Register<LLTextBox> text("text"); + LLDefaultChildRegistry::Register<LLTextEditor> simple_text_editor("simple_text_editor"); + LLDefaultChildRegistry::Register<LLUICtrl> ui_ctrl("ui_ctrl"); + LLDefaultChildRegistry::Register<LLStatView> stat_view("stat_view"); + //LLDefaultChildRegistry::Register<LLUICtrlLocate> locate("locate"); + //LLDefaultChildRegistry::Register<LLUICtrlLocate> pad("pad"); + LLDefaultChildRegistry::Register<LLViewBorder> view_border("view_border"); } // *HACK: Usually this is registered as a viewer text editor - LLDefaultWidgetRegistry::Register<LLTextEditor> text_editor("text_editor"); + LLDefaultChildRegistry::Register<LLTextEditor> text_editor("text_editor"); } diff --git a/indra/integration_tests/llui_libtest/llwidgetreg.h b/indra/integration_tests/llui_libtest/llwidgetreg.h index eac818608d2163e0ebb10cfb6783f042631eec53..4e0bc5377ae201e56cec0c30f7ee36491e84874d 100644 --- a/indra/integration_tests/llui_libtest/llwidgetreg.h +++ b/indra/integration_tests/llui_libtest/llwidgetreg.h @@ -33,7 +33,7 @@ // Register all widgets with the builder registry. // Useful on Windows where linker discards all references to the -// static LLDefaultWidgetRegistry::Register<> calls. +// static LLDefaultChildRegistry::Register<> calls. class LLWidgetReg { public: diff --git a/indra/llinventory/llpermissionsflags.h b/indra/llinventory/llpermissionsflags.h index afa2adbd90455bd0eb8171a83104ccf2689a7ff7..f810929d68685b718fe7a62af76e2b26d46db5db 100644 --- a/indra/llinventory/llpermissionsflags.h +++ b/indra/llinventory/llpermissionsflags.h @@ -32,9 +32,6 @@ #ifndef LL_LLPERMISSIONSFLAGS_H #define LL_LLPERMISSIONSFLAGS_H -// llpermissionsflags.h -// Copyright 2002, Linden Research, Inc. -// // Flags for various permissions bits. // Shared between viewer and simulator. diff --git a/indra/llrender/llfontgl.h b/indra/llrender/llfontgl.h index 204c6908af75cd2d59758246574799ef7914bc1d..77cd12250cf5536c2a73b2c9aec98b9e387480ce 100644 --- a/indra/llrender/llfontgl.h +++ b/indra/llrender/llfontgl.h @@ -264,7 +264,7 @@ protected: typedef std::map<llwchar,embedded_data_t*> embedded_map_t; mutable embedded_map_t mEmbeddedChars; - LLFontDescriptor mFontDesc; + LLFontDescriptor mFontDescriptor; // Registry holds all instantiated fonts. static LLFontRegistry* sFontRegistry; @@ -276,8 +276,8 @@ public: static LLCoordFont sCurOrigin; static std::vector<LLCoordFont> sOriginStack; - const LLFontDescriptor &getFontDesc() const { return mFontDesc; } - void setFontDesc(const LLFontDescriptor& font_desc) { mFontDesc = font_desc; } + const LLFontDescriptor &getFontDesc() const { return mFontDescriptor; } + void setFontDesc(const LLFontDescriptor& font_desc) { mFontDescriptor = font_desc; } }; #endif diff --git a/indra/llrender/llfontregistry.cpp b/indra/llrender/llfontregistry.cpp index 18e4a6915d8108850e3900c6d3bba69c950ede68..3b5c62a5ea6f194de3d38b8b6f49609b7d875412 100644 --- a/indra/llrender/llfontregistry.cpp +++ b/indra/llrender/llfontregistry.cpp @@ -104,7 +104,7 @@ bool removeSubString(std::string& str, const std::string& substr) size_t pos = str.find(substr); if (pos != string::npos) { - str.replace(pos,substr.length(),(const char *)NULL, 0); + str.erase(pos); return true; } return false; diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp index f2aa9c0d4c5d4c1dc4c0c1fcef084164f538e009..9ad27e7c4153ca30f4d1a5738ca1efc4317b2b99 100644 --- a/indra/llui/llbutton.cpp +++ b/indra/llui/llbutton.cpp @@ -32,7 +32,6 @@ #include "linden_common.h" -#define INSTANTIATE_GETCHILD_BUTTON #include "llbutton.h" // Linden library includes @@ -53,7 +52,7 @@ #include "llrender.h" #include "lluictrlfactory.h" -static LLDefaultWidgetRegistry::Register<LLButton> r("button"); +static LLDefaultChildRegistry::Register<LLButton> r("button"); // globals loaded from settings.xml S32 LLBUTTON_H_PAD = 0; @@ -61,8 +60,6 @@ S32 LLBUTTON_V_PAD = 0; S32 BTN_HEIGHT_SMALL= 0; S32 BTN_HEIGHT = 0; -template LLButton* LLView::getChild<LLButton>( const std::string& name, BOOL recurse, BOOL create_if_missing ) const; - LLButton::Params::Params() : label_selected("label_selected"), // requires is_toggle true label_dropshadow("label_shadow", true), @@ -146,7 +143,7 @@ LLButton::LLButton(const LLButton::Params& p) mFadeWhenDisabled(FALSE) { static LLUICachedControl<S32> llbutton_orig_h_pad ("UIButtonOrigHPad", 0); - static Params default_params(LLUICtrlFactory::getDefaultParams<Params>()); + static Params default_params(LLUICtrlFactory::getDefaultParams<LLButton>()); //if we aren't a picture_style button set label as name if not provided if (!p.picture_style.isProvided() || !p.picture_style) @@ -328,25 +325,27 @@ BOOL LLButton::handleKeyHere(KEY key, MASK mask ) BOOL LLButton::handleMouseDown(S32 x, S32 y, MASK mask) { - // Route future Mouse messages here preemptively. (Release on mouse up.) - gFocusMgr.setMouseCapture( this ); - - if (hasTabStop() && !getIsChrome()) + if (!childrenHandleMouseDown(x, y, mask)) { - setFocus(TRUE); - } + // Route future Mouse messages here preemptively. (Release on mouse up.) + gFocusMgr.setMouseCapture( this ); - mMouseDownSignal(this, LLSD()); + if (hasTabStop() && !getIsChrome()) + { + setFocus(TRUE); + } - mMouseDownTimer.start(); - mMouseDownFrame = (S32) LLFrameTimer::getFrameCount(); - mMouseHeldDownCount = 0; - - if (getSoundFlags() & MOUSE_DOWN) - { - make_ui_sound("UISndClick"); - } + mMouseDownSignal(this, LLSD()); + mMouseDownTimer.start(); + mMouseDownFrame = (S32) LLFrameTimer::getFrameCount(); + mMouseHeldDownCount = 0; + + if (getSoundFlags() & MOUSE_DOWN) + { + make_ui_sound("UISndClick"); + } + } return TRUE; } @@ -381,20 +380,26 @@ BOOL LLButton::handleMouseUp(S32 x, S32 y, MASK mask) LLUICtrl::onCommit(); } } + else + { + childrenHandleMouseUp(x, y, mask); + } return TRUE; } BOOL LLButton::handleRightMouseDown(S32 x, S32 y, MASK mask) { - // Route future Mouse messages here preemptively. (Release on mouse up.) - gFocusMgr.setMouseCapture( this ); - - if (hasTabStop() && !getIsChrome()) + if (!childrenHandleRightMouseDown(x, y, mask)) { - setFocus(TRUE); - } + // Route future Mouse messages here preemptively. (Release on mouse up.) + gFocusMgr.setMouseCapture( this ); + if (hasTabStop() && !getIsChrome()) + { + setFocus(TRUE); + } + } return TRUE; } @@ -412,6 +417,10 @@ BOOL LLButton::handleRightMouseUp(S32 x, S32 y, MASK mask) mRightClickSignal(this, getValue()); } } + else + { + childrenHandleRightMouseUp(x, y, mask); + } return TRUE; } @@ -429,21 +438,23 @@ void LLButton::onMouseLeave(S32 x, S32 y, MASK mask) BOOL LLButton::handleHover(S32 x, S32 y, MASK mask) { - if (mMouseDownTimer.getStarted()) + if (!childrenHandleHover(x, y, mask)) { - F32 elapsed = getHeldDownTime(); - if( mHeldDownDelay <= elapsed && mHeldDownFrameDelay <= (S32)LLFrameTimer::getFrameCount() - mMouseDownFrame) + if (mMouseDownTimer.getStarted()) { - LLSD param; - param["count"] = mMouseHeldDownCount++; - mHeldDownSignal(this, param); + F32 elapsed = getHeldDownTime(); + if( mHeldDownDelay <= elapsed && mHeldDownFrameDelay <= (S32)LLFrameTimer::getFrameCount() - mMouseDownFrame) + { + LLSD param; + param["count"] = mMouseHeldDownCount++; + mHeldDownSignal(this, param); + } } - } - - // We only handle the click if the click both started and ended within us - getWindow()->setCursor(UI_CURSOR_ARROW); - lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << llendl; + // We only handle the click if the click both started and ended within us + getWindow()->setCursor(UI_CURSOR_ARROW); + lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << llendl; + } return TRUE; } diff --git a/indra/llui/llbutton.h b/indra/llui/llbutton.h index 1398e5c14bd1d85837205cf7661e6317f16ccfc3..3fa62cc35165188db50ba28601f9a24e323f5ad9 100644 --- a/indra/llui/llbutton.h +++ b/indra/llui/llbutton.h @@ -352,11 +352,5 @@ private: LLFrameTimer mFlashingTimer; }; -#ifdef LL_WINDOWS -#ifndef INSTANTIATE_GETCHILD_BUTTON -#pragma warning (disable : 4231) -extern template LLButton* LLView::getChild<LLButton>( const std::string& name, BOOL recurse, BOOL create_if_missing ) const; -#endif -#endif #endif // LL_LLBUTTON_H diff --git a/indra/llui/llcheckboxctrl.cpp b/indra/llui/llcheckboxctrl.cpp index 932a1b6297b4a834108d17dae2d249e627ab1df8..b43f91e766cda3d6ef9f93e72a0c5ac6f3087332 100644 --- a/indra/llui/llcheckboxctrl.cpp +++ b/indra/llui/llcheckboxctrl.cpp @@ -31,8 +31,6 @@ */ // The mutants are coming! -#define INSTANTIATE_GETCHILD_CHECKBOX - #include "linden_common.h" #include "llcheckboxctrl.h" @@ -50,9 +48,7 @@ const U32 MAX_STRING_LENGTH = 10; -template LLCheckBoxCtrl* LLView::getChild<LLCheckBoxCtrl>( const std::string& name, BOOL recurse, BOOL create_if_missing ) const; - -static LLDefaultWidgetRegistry::Register<LLCheckBoxCtrl> r("check_box"); +static LLDefaultChildRegistry::Register<LLCheckBoxCtrl> r("check_box"); LLCheckBoxCtrl::Params::Params() : text_enabled_color("text_enabled_color"), diff --git a/indra/llui/llcheckboxctrl.h b/indra/llui/llcheckboxctrl.h index 2f8f088a3e7a72de6c1725394f51ff706a840f19..2f8e8fdd234b29f3ef163827ed40f13b9c050785 100644 --- a/indra/llui/llcheckboxctrl.h +++ b/indra/llui/llcheckboxctrl.h @@ -126,11 +126,4 @@ protected: }; -#ifdef LL_WINDOWS -#ifndef INSTANTIATE_GETCHILD_CHECKBOX -#pragma warning (disable : 4231) -extern template LLCheckBoxCtrl* LLView::getChild<LLCheckBoxCtrl>( const std::string& name, BOOL recurse, BOOL create_if_missing ) const; -#endif -#endif - #endif // LL_LLCHECKBOXCTRL_H diff --git a/indra/llui/llcombobox.cpp b/indra/llui/llcombobox.cpp index e19eacb774ade423eea93a25d3aeb9454ac83711..5dfca4be16f6a592471a8414dd625a62e5644c6d 100644 --- a/indra/llui/llcombobox.cpp +++ b/indra/llui/llcombobox.cpp @@ -33,8 +33,6 @@ // A control that displays the name of the chosen item, which when // clicked shows a scrolling box of options. -#define INSTANTIATE_GETCHILD_COMBOBOX - #include "linden_common.h" // file includes @@ -63,9 +61,7 @@ S32 LLCOMBOBOX_HEIGHT = 0; S32 LLCOMBOBOX_WIDTH = 0; S32 MAX_COMBO_WIDTH = 500; -template LLComboBox* LLView::getChild<LLComboBox>( const std::string& name, BOOL recurse, BOOL create_if_missing ) const; - -static LLDefaultWidgetRegistry::Register<LLComboBox> register_combo_box("combo_box"); +static LLDefaultChildRegistry::Register<LLComboBox> register_combo_box("combo_box"); void LLComboBox::PreferredPositionValues::declareValues() { diff --git a/indra/llui/llcombobox.h b/indra/llui/llcombobox.h index cb5f72dcbecaa378378bed4c4779a0ceb7d83aa8..4c0d10dc40c4e23fb77a39a785c168a7184f5e5c 100644 --- a/indra/llui/llcombobox.h +++ b/indra/llui/llcombobox.h @@ -234,12 +234,4 @@ private: commit_callback_t mTextEntryCallback; commit_callback_t mSelectionCallback; }; - -#ifdef LL_WINDOWS -#ifndef INSTANTIATE_GETCHILD_COMBOBOX -#pragma warning (disable : 4231) -extern template LLComboBox* LLView::getChild<LLComboBox>( const std::string& name, BOOL recurse, BOOL create_if_missing ) const; -#endif -#endif - #endif diff --git a/indra/llui/llcontainerview.cpp b/indra/llui/llcontainerview.cpp index 40cc430e2592e07925b319c8dd91a0d4b8188bfc..96948b659fd9434ea6b317924ce12394e85e743c 100644 --- a/indra/llui/llcontainerview.cpp +++ b/indra/llui/llcontainerview.cpp @@ -42,7 +42,7 @@ #include "llscrollcontainer.h" #include "lluictrlfactory.h" -static LLDefaultWidgetRegistry::Register<LLContainerView> r("container_view"); +static LLDefaultChildRegistry::Register<LLContainerView> r("container_view"); LLContainerView::LLContainerView(const LLContainerView::Params& p) : LLView(p), diff --git a/indra/llui/lldraghandle.h b/indra/llui/lldraghandle.h index 0448c200682780333354c3506872662ada6c9b96..86eef7c42c232355f1e355e26a5746b702d7f017 100644 --- a/indra/llui/lldraghandle.h +++ b/indra/llui/lldraghandle.h @@ -53,8 +53,8 @@ public: Optional<LLUIColor> drag_shadow_color; Params() - : drag_highlight_color("", LLUIColorTable::instance().getColor("DefaultHighlightLight")), - drag_shadow_color("", LLUIColorTable::instance().getColor("DefaultShadowDark")) + : drag_highlight_color("drag_highlight_color", LLUIColorTable::instance().getColor("DefaultHighlightLight")), + drag_shadow_color("drag_shadow_color", LLUIColorTable::instance().getColor("DefaultShadowDark")) { mouse_opaque(true); follows.flags(FOLLOWS_ALL); diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index d37459c0407c458ddc8e7de7926ed4a5a6074759..c8bbdb0a564d250f7be884771731b31c2e7f804d 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -191,7 +191,7 @@ bool LLFloater::KeyCompare::equate(const LLSD& a, const LLSD& b) //static const LLFloater::Params& LLFloater::getDefaultParams() { - return LLUICtrlFactory::getDefaultParams<LLFloater::Params>(); + return LLUICtrlFactory::getDefaultParams<LLFloater>(); } @@ -560,6 +560,7 @@ void LLFloater::openFloater(const LLSD& key) setVisibleAndFrontmost(mAutoFocus); } + mOpenSignal(this, getValue()); onOpen(key); } @@ -623,6 +624,7 @@ void LLFloater::closeFloater(bool app_quitting) } // Let floater do cleanup. + mCloseSignal(this, getValue()); onClose(app_quitting); } } @@ -1709,6 +1711,33 @@ void LLFloater::buildButtons() updateButtons(); } +void LLFloater::initOpenCallback(const OpenCallbackParam& cb, open_signal_t& sig) +{ + if (cb.function.isProvided()) + { + if (cb.parameter.isProvided()) + sig.connect(boost::bind(cb.function(), _1, cb.parameter)); + else + sig.connect(cb.function()); + } + else + { + std::string function_name = cb.function_name; + open_callback_t* func = (CallbackRegistry<open_callback_t>::getValue(function_name)); + if (func) + { + if (cb.parameter.isProvided()) + sig.connect(boost::bind((*func), _1, cb.parameter)); + else + sig.connect(*func); + } + else if (!function_name.empty()) + { + llwarns << "No callback found for: '" << function_name << "' in control: " << getName() << llendl; + } + } +} + ///////////////////////////////////////////////////// // LLFloaterView @@ -2462,18 +2491,25 @@ void LLFloater::initFromParams(const LLFloater::Params& p) { mVisibilityControl = "t"; // flag to build mVisibilityControl name once mInstanceName is set } + + // open callback + if (p.open_callback.isProvided()) + initOpenCallback(p.open_callback, mOpenSignal); + // close callback + if (p.close_callback.isProvided()) + initOpenCallback(p.close_callback, mCloseSignal); } void LLFloater::initFloaterXML(LLXMLNodePtr node, LLView *parent, BOOL open_floater, LLXMLNodePtr output_node) { - Params params(LLUICtrlFactory::getDefaultParams<LLFloater::Params>()); + Params params(LLUICtrlFactory::getDefaultParams<LLFloater>()); LLXUIParser::instance().readXUI(node, params); if (output_node) { Params output_params(params); setupParamsForExport(output_params, parent); - Params default_params(LLUICtrlFactory::getDefaultParams<LLFloater::Params>()); + Params default_params(LLUICtrlFactory::getDefaultParams<LLFloater>()); output_node->setName(node->getName()->mString); LLXUIParser::instance().writeXUI( output_node, output_params, &default_params); @@ -2490,7 +2526,7 @@ void LLFloater::initFloaterXML(LLXMLNodePtr node, LLView *parent, BOOL open_floa LLFloater::setFloaterHost((LLMultiFloater*) this); } - LLUICtrlFactory::createChildren(this, node, output_node); + LLUICtrlFactory::createChildren(this, node, child_registry_t::instance(), output_node); if (node->hasName("multi_floater")) { diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h index 3e80f1b28471d977d6d5ef04cd16a376483e24d9..c639f903903a1cfe81e3dc56b923fcfda8d847b7 100644 --- a/indra/llui/llfloater.h +++ b/indra/llui/llfloater.h @@ -105,6 +105,17 @@ public: BUTTON_COUNT }; + typedef boost::function<void (LLUICtrl* ctrl, const LLSD& param)> open_callback_t; + typedef boost::signals2::signal<void (LLUICtrl* ctrl, const LLSD& param)> open_signal_t; + + typedef boost::function<void (LLUICtrl* ctrl, const LLSD& param)> close_callback_t; + typedef boost::signals2::signal<void (LLUICtrl* ctrl, const LLSD& param)> close_signal_t; + + struct OpenCallbackParam : public LLInitParam::Block<OpenCallbackParam, CallbackParam > + { + Optional<open_callback_t> function; + }; + struct Params : public LLInitParam::Block<Params, LLPanel::Params> { @@ -120,7 +131,10 @@ public: can_tear_off, save_rect, save_visibility; - + + Optional<OpenCallbackParam> open_callback, + close_callback; + Params() : title("title"), short_title("short_title"), @@ -132,7 +146,9 @@ public: can_drag_on_left("can_drag_on_left", false), can_tear_off("can_tear_off", true), save_rect("save_rect", false), - save_visibility("save_visibility", false) + save_visibility("save_visibility", false), + open_callback("open_callback"), + close_callback("close_callback") { name = "floater"; // defaults that differ from LLPanel: @@ -289,8 +305,9 @@ protected: void destroy() { die(); } // Don't call this directly. You probably want to call close(). JC + void initOpenCallback(const OpenCallbackParam& cb, open_signal_t& sig); + private: - void setForeground(BOOL b); // called only by floaterview void cleanupHandles(); // remove handles to dead floaters void createMinimizeButton(); @@ -299,11 +316,15 @@ private: BOOL offerClickToButton(S32 x, S32 y, MASK mask, EFloaterButtons index); void addResizeCtrls(); void addDragHandle(); - + +public: + typedef CallbackRegistry<open_callback_t> OpenCallbackRegistry; + protected: std::string mRectControl; std::string mVisibilityControl; - + open_signal_t mOpenSignal; + open_signal_t mCloseSignal; LLSD mKey; // Key used for retrieving instances; set (for now) by LLFLoaterReg private: @@ -378,6 +399,7 @@ private: LLRootHandle<LLFloater> mHandle; }; + ///////////////////////////////////////////////////////////// // LLFloaterView // Parent of all floating panels @@ -441,9 +463,6 @@ private: S32 mSnapOffsetRight; }; -// singleton implementation for floaters -// https://wiki.lindenlab.com/mediawiki/index.php?title=LLFloaterSingleton&oldid=164990 - //******************************************************* //* TO BE DEPRECATED //******************************************************* @@ -460,14 +479,6 @@ public: static void hide(LLFloater* instance, const LLSD& key); }; - -// singleton implementation for floaters (provides visibility policy) -// https://wiki.lindenlab.com/mediawiki/index.php?title=LLFloaterSingleton&oldid=164990 - -template <class T> class LLFloaterSingleton : public LLUISingleton<T, VisibilityPolicy<LLFloater> > -{ -}; - // // Globals // diff --git a/indra/llui/llflyoutbutton.cpp b/indra/llui/llflyoutbutton.cpp index a99c3a4fe610a17c817d9c55486a37a58c8ff56f..536919c072821eb11918908fa2f18055a63718dc 100644 --- a/indra/llui/llflyoutbutton.cpp +++ b/indra/llui/llflyoutbutton.cpp @@ -35,7 +35,7 @@ // file includes #include "llflyoutbutton.h" -//static LLDefaultWidgetRegistry::Register<LLFlyoutButton> r2("flyout_button"); +//static LLDefaultChildRegistry::Register<LLFlyoutButton> r2("flyout_button"); const S32 FLYOUT_BUTTON_ARROW_WIDTH = 24; diff --git a/indra/llui/lliconctrl.cpp b/indra/llui/lliconctrl.cpp index eddfc7128495556b17f1472848bc9dfdf8d848ae..5c6ea663f364407c61b507b8914e31a307fe48c3 100644 --- a/indra/llui/lliconctrl.cpp +++ b/indra/llui/lliconctrl.cpp @@ -42,7 +42,7 @@ #include "lluictrlfactory.h" #include "lluiimage.h" -static LLDefaultWidgetRegistry::Register<LLIconCtrl> r("icon"); +static LLDefaultChildRegistry::Register<LLIconCtrl> r("icon"); LLIconCtrl::Params::Params() : image("image_name"), diff --git a/indra/llui/lllayoutstack.cpp b/indra/llui/lllayoutstack.cpp index 39dac296ea913bb04b341405ad086b9107388049..f1e7d791d434133030c05a7039a30eb0ba706eca 100644 --- a/indra/llui/lllayoutstack.cpp +++ b/indra/llui/lllayoutstack.cpp @@ -38,7 +38,7 @@ #include "llresizebar.h" #include "llcriticaldamp.h" -static LLDefaultWidgetRegistry::Register<LLLayoutStack> register_layout_stack("layout_stack", &LLLayoutStack::fromXML); +static LLDefaultChildRegistry::Register<LLLayoutStack> register_layout_stack("layout_stack", &LLLayoutStack::fromXML); // @@ -223,7 +223,7 @@ static void get_attribute_bool_and_write(LLXMLNodePtr node, //static LLView* LLLayoutStack::fromXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr output_node) { - LLLayoutStack::Params p(LLUICtrlFactory::getDefaultParams<LLLayoutStack::Params>()); + LLLayoutStack::Params p(LLUICtrlFactory::getDefaultParams<LLLayoutStack>()); LLXUIParser::instance().readXUI(node, p); // Export must happen before setupParams() mungles rectangles and before @@ -233,7 +233,7 @@ LLView* LLLayoutStack::fromXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr o { Params output_params(p); setupParamsForExport(output_params, parent); - LLLayoutStack::Params default_params(LLUICtrlFactory::getDefaultParams<LLLayoutStack::Params>()); + LLLayoutStack::Params default_params(LLUICtrlFactory::getDefaultParams<LLLayoutStack>()); output_node->setName(node->getName()->mString); LLXUIParser::instance().writeXUI( output_node, output_params, &default_params); @@ -296,7 +296,7 @@ LLView* LLLayoutStack::fromXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr o LLPanel::Params p; LLPanel* panelp = LLUICtrlFactory::create<LLPanel>(p); - LLView* new_child = LLUICtrlFactory::getInstance()->createFromXML(child_node, panelp, LLStringUtil::null, output_child, parent ? parent->getChildRegistry() : LLDefaultWidgetRegistry::instance()); + LLView* new_child = LLUICtrlFactory::getInstance()->createFromXML(child_node, panelp, LLStringUtil::null, LLPanel::child_registry_t::instance(), output_child); if (new_child) { // put child in new embedded panel diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp index 925f22d94efece2e109aee3d6418549aa3f2d733..f3afadca159aa85bb979c78740b1f6cac1b7d36b 100644 --- a/indra/llui/lllineeditor.cpp +++ b/indra/llui/lllineeditor.cpp @@ -34,8 +34,6 @@ #include "linden_common.h" -#define INSTANTIATE_GETCHILD_LINEEDITOR - #include "lllineeditor.h" #include "lltexteditor.h" @@ -72,9 +70,7 @@ const S32 SCROLL_INCREMENT_DEL = 4; // make space for baskspacing const F32 AUTO_SCROLL_TIME = 0.05f; const F32 TRIPLE_CLICK_INTERVAL = 0.3f; // delay between double and triple click. *TODO: make this equal to the double click interval? -static LLDefaultWidgetRegistry::Register<LLLineEditor> r1("line_editor"); - -template LLLineEditor* LLView::getChild<LLLineEditor>( const std::string& name, BOOL recurse, BOOL create_if_missing ) const; +static LLDefaultChildRegistry::Register<LLLineEditor> r1("line_editor"); // // Member functions @@ -180,7 +176,7 @@ LLLineEditor::LLLineEditor(const LLLineEditor::Params& p) LLViewBorder::Params border_p(p.border); border_p.rect = border_rect; border_p.follows.flags = FOLLOWS_ALL; - border_p.bevel_type = LLViewBorder::BEVEL_IN; + border_p.bevel_style = LLViewBorder::BEVEL_IN; mBorder = LLUICtrlFactory::create<LLViewBorder>(border_p); addChild( mBorder ); diff --git a/indra/llui/lllineeditor.h b/indra/llui/lllineeditor.h index eb021bace974318c4d674c7f1b2d17b4691d37ff..4362cff2fecda0754a779aaa1e51650bae6c3904 100644 --- a/indra/llui/lllineeditor.h +++ b/indra/llui/lllineeditor.h @@ -392,12 +392,6 @@ private: }; // end class LLLineEditor -#ifdef LL_WINDOWS -#ifndef INSTANTIATE_GETCHILD_LINEEDITOR -#pragma warning (disable : 4231) -extern template LLLineEditor* LLView::getChild<LLLineEditor>( const std::string& name, BOOL recurse, BOOL create_if_missing ) const; -#endif -#endif namespace LLInitParam { diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp index e79afe76d84dd0e1d12155afdd21f4694e9833bc..4d2374a7e870ec5c60c6af5c4c1d596ba23ef8b1 100644 --- a/indra/llui/llmenugl.cpp +++ b/indra/llui/llmenugl.cpp @@ -119,16 +119,12 @@ const F32 PIE_SHRINK_TIME = 0.2f; // time of transition between unbounded and bo const F32 ACTIVATE_HIGHLIGHT_TIME = 0.3f; -// widget registrars -struct MenuRegistry : public LLWidgetRegistry<MenuRegistry> -{}; - static MenuRegistry::Register<LLMenuItemSeparatorGL> register_separator("menu_item_separator"); static MenuRegistry::Register<LLMenuItemCallGL> register_menu_item_call("menu_item_call"); static MenuRegistry::Register<LLMenuItemCheckGL> register_menu_item_check("menu_item_check"); static MenuRegistry::Register<LLMenuGL> register_menu("menu"); -static LLDefaultWidgetRegistry::Register<LLMenuGL> register_menu_default("menu"); +static LLDefaultChildRegistry::Register<LLMenuGL> register_menu_default("menu"); @@ -1666,12 +1662,6 @@ BOOL LLMenuGL::postBuild() return LLUICtrl::postBuild(); } -const widget_registry_t& LLMenuGL::getChildRegistry() const -{ - return MenuRegistry::instance(); -} - - // are we the childmost active menu and hence our jump keys should be enabled? // or are we a free-standing torn-off menu (which uses jump keys too) BOOL LLMenuGL::jumpKeysActive() @@ -2885,7 +2875,7 @@ void LLMenuGL::showPopup(LLView* spawning_view, LLMenuGL* menu, S32 x, S32 y) /// Class LLMenuBarGL ///============================================================================ -static LLDefaultWidgetRegistry::Register<LLMenuBarGL> r2("menu_bar"); +static LLDefaultChildRegistry::Register<LLMenuBarGL> r2("menu_bar"); LLMenuBarGL::LLMenuBarGL( const Params& p ) : LLMenuGL(p), @@ -3571,7 +3561,7 @@ void LLContextMenuBranch::setHighlight( BOOL highlight ) // class LLContextMenu // A context menu //----------------------------------------------------------------------------- -static LLDefaultWidgetRegistry::Register<LLContextMenu> context_menu_register("context_menu"); +static LLDefaultChildRegistry::Register<LLContextMenu> context_menu_register("context_menu"); static MenuRegistry::Register<LLContextMenu> context_menu_register2("context_menu"); diff --git a/indra/llui/llmenugl.h b/indra/llui/llmenugl.h index ad257f46c25d761c3bfbb28c112f61bcf8433444..ef27c2c9c8610b315d5456b311abfb7ca5c0ac90 100644 --- a/indra/llui/llmenugl.h +++ b/indra/llui/llmenugl.h @@ -81,7 +81,7 @@ public: Params() : shortcut("shortcut"), - jump_key("", KEY_NONE), + jump_key("jump_key", KEY_NONE), use_mac_ctrl("use_mac_ctrl", false), rect("rect"), left("left"), @@ -356,6 +356,11 @@ private: // it in the appendMenu() method. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// child widget registry +struct MenuRegistry : public LLChildRegistry<MenuRegistry> +{}; + + class LLMenuGL : public LLUICtrl { @@ -374,7 +379,7 @@ public: Optional<LLUIColor> bg_color; Params() - : jump_key("", KEY_NONE), + : jump_key("jump_key", KEY_NONE), can_tear_off("tear_off", false), drop_shadow("drop_shadow", true), bg_visible("bg_visible", true), @@ -388,6 +393,10 @@ public: name = "menu"; } }; + + // my valid children are contained in MenuRegistry + typedef MenuRegistry child_registry_t; + void initFromParams(const Params&); protected: @@ -410,7 +419,6 @@ public: /*virtual*/ bool addChild(LLView* view, S32 tab_group = 0); /*virtual*/ void removeChild( LLView* ctrl); /*virtual*/ BOOL postBuild(); - /*virtual*/ const widget_registry_t& getChildRegistry() const; virtual BOOL handleAcceleratorKey(KEY key, MASK mask); diff --git a/indra/llui/llmultifloater.cpp b/indra/llui/llmultifloater.cpp index c0fe7ff32dc0945b03b8f5825832c63c874029a1..22683d795050ab7829b9243cd9fc430a38bf30b6 100644 --- a/indra/llui/llmultifloater.cpp +++ b/indra/llui/llmultifloater.cpp @@ -275,6 +275,7 @@ void LLMultiFloater::selectPrevFloater() void LLMultiFloater::showFloater(LLFloater* floaterp, LLTabContainer::eInsertionPoint insertion_point) { + if(!floaterp) return; // we won't select a panel that already is selected // it is hard to do this internally to tab container // as tab selection is handled via index and the tab at a given @@ -288,7 +289,7 @@ void LLMultiFloater::showFloater(LLFloater* floaterp, LLTabContainer::eInsertion void LLMultiFloater::removeFloater(LLFloater* floaterp) { - if ( floaterp->getHost() != this ) + if (!floaterp || floaterp->getHost() != this ) return; floater_data_map_t::iterator found_data_it = mFloaterDataMap.find(floaterp->getHandle()); diff --git a/indra/llui/llmultislider.cpp b/indra/llui/llmultislider.cpp index 099a79278a658225d1b1e11f9b5e9add9a7692d3..0454771511ea65f6bc1a0b53aa0976d1ca824504 100644 --- a/indra/llui/llmultislider.cpp +++ b/indra/llui/llmultislider.cpp @@ -45,7 +45,7 @@ #include <sstream> -static LLDefaultWidgetRegistry::Register<LLMultiSlider> r("multi_slider_bar"); +static LLDefaultChildRegistry::Register<LLMultiSlider> r("multi_slider_bar"); const F32 FLOAT_THRESHOLD = 0.00001f; diff --git a/indra/llui/llmultisliderctrl.cpp b/indra/llui/llmultisliderctrl.cpp index 312aceaaa27613d2f7cfc772bcf7683e21d3b455..1523d5d5276c51d8588f98b5d37f61d5654843da 100644 --- a/indra/llui/llmultisliderctrl.cpp +++ b/indra/llui/llmultisliderctrl.cpp @@ -52,7 +52,7 @@ #include "llresmgr.h" #include "lluictrlfactory.h" -static LLDefaultWidgetRegistry::Register<LLMultiSliderCtrl> r("multi_slider"); +static LLDefaultChildRegistry::Register<LLMultiSliderCtrl> r("multi_slider"); const U32 MAX_STRING_LENGTH = 10; LLMultiSliderCtrl::Params::Params() diff --git a/indra/llui/llpanel.cpp b/indra/llui/llpanel.cpp index 6a6e15867bbf429cefa415a45bbff98d5df7ea10..2119ed4dafbe2488917f3478ed53122e1a5f5272 100644 --- a/indra/llui/llpanel.cpp +++ b/indra/llui/llpanel.cpp @@ -56,11 +56,11 @@ #include "llbutton.h" #include "lltabcontainer.h" -static LLDefaultWidgetRegistry::Register<LLPanel> r1("panel", &LLPanel::fromXML); +static LLDefaultChildRegistry::Register<LLPanel> r1("panel", &LLPanel::fromXML); const LLPanel::Params& LLPanel::getDefaultParams() { - return LLUICtrlFactory::getDefaultParams<LLPanel::Params>(); + return LLUICtrlFactory::getDefaultParams<LLPanel>(); } LLPanel::Params::Params() @@ -433,7 +433,7 @@ void LLPanel::initFromParams(const LLPanel::Params& p) parseFollowsFlags(p); setToolTip(p.tool_tip()); - setSaveToXML(p.serializable); + setSaveToXML(p.from_xui); mHoverCursor = getCursorFromString(p.hover_cursor); @@ -462,7 +462,7 @@ static LLFastTimer::DeclareTimer FTM_PANEL_POSTBUILD("Panel PostBuild"); BOOL LLPanel::initPanelXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr output_node) { - const LLPanel::Params& default_params(LLUICtrlFactory::getDefaultParams<LLPanel::Params>()); + const LLPanel::Params& default_params(LLUICtrlFactory::getDefaultParams<LLPanel>()); Params params(default_params); { @@ -499,7 +499,7 @@ BOOL LLPanel::initPanelXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr outpu // add children using dimensions from referenced xml for consistent layout setShape(params.rect); - LLUICtrlFactory::createChildren(this, referenced_xml); + LLUICtrlFactory::createChildren(this, referenced_xml, child_registry_t::instance()); } LLXUIParser::instance().readXUI(node, params); @@ -520,7 +520,7 @@ BOOL LLPanel::initPanelXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr outpu } // add children - LLUICtrlFactory::createChildren(this, node, output_node); + LLUICtrlFactory::createChildren(this, node, child_registry_t::instance(), output_node); // Connect to parent after children are built, because tab containers // do a reshape() on their child panels, which requires that the children @@ -539,12 +539,6 @@ BOOL LLPanel::initPanelXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr outpu return TRUE; } -const widget_registry_t& LLPanel::getChildRegistry() const -{ - // use default widget registry - return LLDefaultWidgetRegistry::instance(); -} - bool LLPanel::hasString(const std::string& name) { return mUIStrings.find(name) != mUIStrings.end(); diff --git a/indra/llui/llpanel.h b/indra/llui/llpanel.h index c38e9df53b935a84f026a1b19b76d76922f36c63..ca3b2e7e23ffe00a290e2e61cf6571c56368dae3 100644 --- a/indra/llui/llpanel.h +++ b/indra/llui/llpanel.h @@ -93,6 +93,9 @@ public: Params(); }; + // valid children for LLPanel are stored in this registry + typedef LLDefaultChildRegistry child_registry_t; + protected: friend class LLUICtrlFactory; // RN: for some reason you can't just use LLUICtrlFactory::getDefaultParams as a default argument in VC8 @@ -165,7 +168,6 @@ public: void initFromParams(const Params& p); BOOL initPanelXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr output_node = NULL); - /*virtual*/ const widget_registry_t& getChildRegistry() const; bool hasString(const std::string& name); std::string getString(const std::string& name, const LLStringUtil::format_map_t& args) const; diff --git a/indra/llui/llprogressbar.cpp b/indra/llui/llprogressbar.cpp index 779967940af22721b97408db25e78aa1e9f98eb7..12353e4c3e15eba1cad66d627345fcb5665409e8 100644 --- a/indra/llui/llprogressbar.cpp +++ b/indra/llui/llprogressbar.cpp @@ -46,7 +46,7 @@ #include "llfocusmgr.h" #include "lluictrlfactory.h" -static LLDefaultWidgetRegistry::Register<LLProgressBar> r("progress_bar"); +static LLDefaultChildRegistry::Register<LLProgressBar> r("progress_bar"); LLProgressBar::Params::Params() : image_bar("image_bar"), diff --git a/indra/llui/llradiogroup.cpp b/indra/llui/llradiogroup.cpp index 70f98bd90850f62846ae8a799e8c427a6b762ad7..30adbb023cf9163ec50b9338c348dddf8fa9c223 100644 --- a/indra/llui/llradiogroup.cpp +++ b/indra/llui/llradiogroup.cpp @@ -44,10 +44,8 @@ #include "llfocusmgr.h" #include "lluictrlfactory.h" -static LLDefaultWidgetRegistry::Register<LLRadioGroup> r1("radio_group"); +static LLDefaultChildRegistry::Register<LLRadioGroup> r1("radio_group"); -struct RadioGroupRegistry : public LLWidgetRegistry<RadioGroupRegistry> -{}; static RadioGroupRegistry::Register<LLRadioCtrl> register_radio_ctrl("radio_item"); @@ -72,7 +70,7 @@ LLRadioGroup::LLRadioGroup(const LLRadioGroup::Params& p) LLViewBorder::Params params; params.name("radio group border"); params.rect(LLRect(0, getRect().getHeight(), getRect().getWidth(), 0)); - params.bevel_type(LLViewBorder::BEVEL_NONE); + params.bevel_style(LLViewBorder::BEVEL_NONE); LLViewBorder * vb = LLUICtrlFactory::create<LLViewBorder> (params); addChild (vb); } @@ -82,11 +80,6 @@ LLRadioGroup::~LLRadioGroup() { } -const widget_registry_t& LLRadioGroup::getChildRegistry() const -{ - return RadioGroupRegistry::instance(); -} - // virtual BOOL LLRadioGroup::postBuild() { diff --git a/indra/llui/llradiogroup.h b/indra/llui/llradiogroup.h index 850d896e29edc318c0f8270531d4fff8ab043c59..d04473fa448d767759026b539379b61814df7b19 100644 --- a/indra/llui/llradiogroup.h +++ b/indra/llui/llradiogroup.h @@ -70,6 +70,10 @@ protected: friend class LLUICtrlFactory; }; + +struct RadioGroupRegistry : public LLChildRegistry<RadioGroupRegistry> +{}; + /* * An invisible view containing multiple mutually exclusive toggling * buttons (usually radio buttons). Automatically handles the mutex @@ -86,6 +90,9 @@ public: Params(); }; + // my valid children are stored in this registry + typedef RadioGroupRegistry child_registry_t; + protected: LLRadioGroup(const Params&); friend class LLUICtrlFactory; @@ -118,8 +125,6 @@ public: // Update the control as needed. Userdata must be a pointer to the button. void onClickButton(LLUICtrl* clicked_radio); - virtual const widget_registry_t& getChildRegistry() const; - //======================================================================== LLCtrlSelectionInterface* getSelectionInterface() { return (LLCtrlSelectionInterface*)this; }; diff --git a/indra/llui/llresizebar.h b/indra/llui/llresizebar.h index 4ad3d5035ac59327e7652c4566b1fe6b17f593a1..a7bc3c60f50db8015cdfcb92c177af0939f5f4a4 100644 --- a/indra/llui/llresizebar.h +++ b/indra/llui/llresizebar.h @@ -52,11 +52,11 @@ public: Optional<bool> allow_double_click_snapping; Params() - : max_size("", S32_MAX), - snapping_enabled("", true), + : max_size("max_size", S32_MAX), + snapping_enabled("snapping_enabled", true), resizing_view("resizing_view"), side("side"), - allow_double_click_snapping("", true) + allow_double_click_snapping("allow_double_click_snapping", true) { name = "resize_bar"; } diff --git a/indra/llui/llscrollbar.cpp b/indra/llui/llscrollbar.cpp index 3f1ff34419555ec4547406f6409eb9976057b85f..331206413179f553e05ca6ea956e4150af6f6911 100644 --- a/indra/llui/llscrollbar.cpp +++ b/indra/llui/llscrollbar.cpp @@ -48,7 +48,7 @@ #include "llrender.h" #include "lluictrlfactory.h" -static LLDefaultWidgetRegistry::Register<LLScrollbar> register_scrollbar("scroll_bar"); +static LLDefaultChildRegistry::Register<LLScrollbar> register_scrollbar("scroll_bar"); LLScrollbar::Params::Params() : orientation ("orientation", HORIZONTAL), diff --git a/indra/llui/llscrollcontainer.cpp b/indra/llui/llscrollcontainer.cpp index 2a2e56a92c7707ee9ca9be69e026dd4001ca5d91..ea4bd2526ec6e2430b2760451d4d8b4d41ceff3b 100644 --- a/indra/llui/llscrollcontainer.cpp +++ b/indra/llui/llscrollcontainer.cpp @@ -63,7 +63,7 @@ static const F32 AUTO_SCROLL_RATE_ACCEL = 120.f; /// Class LLScrollContainer ///---------------------------------------------------------------------------- -static LLDefaultWidgetRegistry::Register<LLScrollContainer> r("scroll_container"); +static LLDefaultChildRegistry::Register<LLScrollContainer> r("scroll_container"); LLScrollContainer::Params::Params() : is_opaque("opaque"), @@ -91,7 +91,7 @@ LLScrollContainer::LLScrollContainer(const LLScrollContainer::Params& p) LLViewBorder::Params params; params.name("scroll border"); params.rect(border_rect); - params.bevel_type(LLViewBorder::BEVEL_IN); + params.bevel_style(LLViewBorder::BEVEL_IN); mBorder = LLUICtrlFactory::create<LLViewBorder> (params); LLView::addChild( mBorder ); @@ -517,12 +517,6 @@ bool LLScrollContainer::addChild(LLView* view, S32 tab_group) return ret_val; } -const widget_registry_t& LLScrollContainer::getChildRegistry() const -{ - // a scroll container can contain any default widget - return LLDefaultWidgetRegistry::instance(); -} - void LLScrollContainer::updateScroll() { if (!mScrolledView) diff --git a/indra/llui/llscrollcontainer.h b/indra/llui/llscrollcontainer.h index 26d8cc824eea2a9ed1a116673471a6a40bef3077..9cbfbc94a181ae9ef648e05927e3da0fb78ab646 100644 --- a/indra/llui/llscrollcontainer.h +++ b/indra/llui/llscrollcontainer.h @@ -68,6 +68,10 @@ public: Params(); }; + + // my valid children are stored in this registry + typedef LLDefaultChildRegistry child_registry_t; + protected: LLScrollContainer(const Params&); friend class LLUICtrlFactory; @@ -104,7 +108,6 @@ public: virtual BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect); virtual void draw(); virtual bool addChild(LLView* view, S32 tab_group = 0); - virtual const widget_registry_t& getChildRegistry() const; private: // internal scrollbar handlers diff --git a/indra/llui/llscrollingpanellist.cpp b/indra/llui/llscrollingpanellist.cpp index 1f3a7f9fcf497b88c07db262ea6d387aa78d38d7..0159cdd12c9b063f632347e6b7e4851a3dcf38c6 100644 --- a/indra/llui/llscrollingpanellist.cpp +++ b/indra/llui/llscrollingpanellist.cpp @@ -35,7 +35,7 @@ #include "llscrollingpanellist.h" -static LLDefaultWidgetRegistry::Register<LLScrollingPanelList> r("scrolling_panel_list"); +static LLDefaultChildRegistry::Register<LLScrollingPanelList> r("scrolling_panel_list"); ///////////////////////////////////////////////////////////////////// diff --git a/indra/llui/llscrolllistcolumn.cpp b/indra/llui/llscrolllistcolumn.cpp index 02f09bd9b4bd546f0d5f58b5b1d5a54f1e99df83..686e0b6cb74b7851400a0a26ae8e3f95bef5784d 100644 --- a/indra/llui/llscrolllistcolumn.cpp +++ b/indra/llui/llscrolllistcolumn.cpp @@ -291,7 +291,7 @@ void LLScrollListColumn::SortNames::declareValues() //static const LLScrollListColumn::Params& LLScrollListColumn::getDefaultParams() { - return LLUICtrlFactory::getDefaultParams<LLScrollListColumn::Params>(); + return LLUICtrlFactory::getDefaultParams<LLScrollListColumn>(); } diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp index 6d91c784f745a0a1f7f6cf927e8d787fd3000d01..75afbffc117a50d5721fa1808868576b98f86fe2 100644 --- a/indra/llui/llscrolllistctrl.cpp +++ b/indra/llui/llscrolllistctrl.cpp @@ -31,8 +31,6 @@ * $/LicenseInfo$ */ -#define INSTANTIATE_GETCHILD_SCROLLLIST - #include "linden_common.h" #include "llscrolllistctrl.h" @@ -60,9 +58,7 @@ #include "lltextbox.h" #include "llsdparam.h" -template LLScrollListCtrl* LLView::getChild<LLScrollListCtrl>( const std::string& name, BOOL recurse, BOOL create_if_missing ) const; - -static LLDefaultWidgetRegistry::Register<LLScrollListCtrl> r("scroll_list"); +static LLDefaultChildRegistry::Register<LLScrollListCtrl> r("scroll_list"); // local structures & classes. struct SortScrollListItem @@ -225,7 +221,7 @@ LLScrollListCtrl::LLScrollListCtrl(const LLScrollListCtrl::Params& p) LLViewBorder::Params params; params.name("dig border"); params.rect(border_rect); - params.bevel_type(LLViewBorder::BEVEL_IN); + params.bevel_style(LLViewBorder::BEVEL_IN); mBorder = LLUICtrlFactory::create<LLViewBorder> (params); addChild(mBorder); } diff --git a/indra/llui/llscrolllistctrl.h b/indra/llui/llscrolllistctrl.h index 8d200fb73fc80f9287f8de809f17a6640c8bf6ad..63d07cecfdc56c70e9795fd6926540063ddc3b83 100644 --- a/indra/llui/llscrolllistctrl.h +++ b/indra/llui/llscrolllistctrl.h @@ -453,11 +453,4 @@ private: LLTextBox* mCommentTextBox; }; // end class LLScrollListCtrl -#ifdef LL_WINDOWS -#ifndef INSTANTIATE_GETCHILD_SCROLLLIST -#pragma warning (disable : 4231) -extern template LLScrollListCtrl* LLView::getChild<LLScrollListCtrl>( const std::string& name, BOOL recurse, BOOL create_if_missing ) const; -#endif -#endif - #endif // LL_SCROLLLISTCTRL_H diff --git a/indra/llui/llsearcheditor.cpp b/indra/llui/llsearcheditor.cpp index 9522d32a8bba723b896a1d49cb5439e8c7cb2934..64583071a62a53008cf652d86a3869da5989ae96 100644 --- a/indra/llui/llsearcheditor.cpp +++ b/indra/llui/llsearcheditor.cpp @@ -36,7 +36,7 @@ #include "llsearcheditor.h" -//static LLDefaultWidgetRegistry::Register<LLSearchEditor> r2("search_editor"); +//static LLDefaultChildRegistry::Register<LLSearchEditor> r2("search_editor"); LLSearchEditor::LLSearchEditor(const LLSearchEditor::Params& p) : LLUICtrl(p) diff --git a/indra/llui/llslider.cpp b/indra/llui/llslider.cpp index 66ed0d4e884ff4bc91fe09b8f17ea7c11103b8a7..fa782a1063557bb81476fcb5abda6658614256c3 100644 --- a/indra/llui/llslider.cpp +++ b/indra/llui/llslider.cpp @@ -43,7 +43,7 @@ #include "llimagegl.h" #include "lluictrlfactory.h" -static LLDefaultWidgetRegistry::Register<LLSlider> r1("slider_bar"); +static LLDefaultChildRegistry::Register<LLSlider> r1("slider_bar"); LLSlider::Params::Params() : track_color("track_color"), diff --git a/indra/llui/llsliderctrl.cpp b/indra/llui/llsliderctrl.cpp index 3abd960792fcd42aed97883de0c02ef3f34a1fc5..12953fc261417f237758b1257e215bdffb137017 100644 --- a/indra/llui/llsliderctrl.cpp +++ b/indra/llui/llsliderctrl.cpp @@ -53,7 +53,7 @@ const U32 MAX_STRING_LENGTH = 10; -static LLDefaultWidgetRegistry::Register<LLSliderCtrl> r("slider"); +static LLDefaultChildRegistry::Register<LLSliderCtrl> r("slider"); LLSliderCtrl::LLSliderCtrl(const LLSliderCtrl::Params& p) : LLF32UICtrl(p), diff --git a/indra/llui/llspinctrl.cpp b/indra/llui/llspinctrl.cpp index 943891c5728fa21dd4d84f099cd591f179708499..5893fcd64b0f0222331bd106bc7d00a92b3263cd 100644 --- a/indra/llui/llspinctrl.cpp +++ b/indra/llui/llspinctrl.cpp @@ -53,7 +53,7 @@ const U32 MAX_STRING_LENGTH = 32; -static LLDefaultWidgetRegistry::Register<LLSpinCtrl> r2("spinner"); +static LLDefaultChildRegistry::Register<LLSpinCtrl> r2("spinner"); LLSpinCtrl::Params::Params() : label_width("label_width"), diff --git a/indra/llui/llstatview.cpp b/indra/llui/llstatview.cpp index 6691f16c1e1611a30b09f00b37cad3029a8945d4..ab4b0be97a3c8daf7c739053c7ca849f3f018a77 100644 --- a/indra/llui/llstatview.cpp +++ b/indra/llui/llstatview.cpp @@ -65,16 +65,6 @@ LLStatView::~LLStatView() } -// widget registrars -struct StatViewRegistry : public LLWidgetRegistry<StatViewRegistry> -{}; - static StatViewRegistry::Register<LLStatBar> r1("stat_bar"); -const widget_registry_t& LLStatView::getChildRegistry() const -{ - return StatViewRegistry::instance(); -} - - diff --git a/indra/llui/llstatview.h b/indra/llui/llstatview.h index 20aba7782bd6724532507783fe682afb71139d81..eee4e2b7e46dec18aa5579d8c11e95eb7af27583 100644 --- a/indra/llui/llstatview.h +++ b/indra/llui/llstatview.h @@ -39,6 +39,10 @@ class LLStatBar; +// widget registrars +struct StatViewRegistry : public LLChildRegistry<StatViewRegistry> +{}; + class LLStatView : public LLContainerView { public: @@ -51,9 +55,11 @@ public: follows.flags(FOLLOWS_TOP | FOLLOWS_LEFT); } }; - ~LLStatView(); - virtual const widget_registry_t& getChildRegistry() const; + // my valid children are stored in this registry + typedef StatViewRegistry child_registry_t; + + ~LLStatView(); protected: LLStatView(const Params&); diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp index 3391b1275c64f1f48a34edb0484e3eb74b72bf08..3d5b5caead7ad4aff0960d6da781a21bdc7e6c8b 100644 --- a/indra/llui/lltabcontainer.cpp +++ b/indra/llui/lltabcontainer.cpp @@ -99,8 +99,8 @@ struct LLPlaceHolderPanel : public LLPanel LLPlaceHolderPanel(const Params& p) : LLPanel(p) {} }; -static LLDefaultWidgetRegistry::Register<LLPlaceHolderPanel> r1("placeholder"); -static LLDefaultWidgetRegistry::Register<LLTabContainer> r2("tab_container"); +static LLDefaultChildRegistry::Register<LLPlaceHolderPanel> r1("placeholder"); +static LLDefaultChildRegistry::Register<LLTabContainer> r2("tab_container"); LLTabContainer::Params::Params() : tab_width("tab_width"), diff --git a/indra/llui/lltextbox.cpp b/indra/llui/lltextbox.cpp index b812e876efbd7d8514e9e14562ea7784bc7d426e..56019171e1bf3ea0a44b7c381a589f8c7922ecfd 100644 --- a/indra/llui/lltextbox.cpp +++ b/indra/llui/lltextbox.cpp @@ -30,17 +30,13 @@ * $/LicenseInfo$ */ -#define INSTANTIATE_GETCHILD_TEXTBOX - #include "linden_common.h" #include "lltextbox.h" #include "lluictrlfactory.h" #include "llfocusmgr.h" #include "llwindow.h" -template LLTextBox* LLView::getChild<LLTextBox>( const std::string& name, BOOL recurse, BOOL create_if_missing ) const; - -static LLDefaultWidgetRegistry::Register<LLTextBox> r("text"); +static LLDefaultChildRegistry::Register<LLTextBox> r("text"); LLTextBox::Params::Params() : text_color("text_color"), diff --git a/indra/llui/lltextbox.h b/indra/llui/lltextbox.h index dca906decc8ec88279f45ccfba4f596d99da6811..53d57ff785bbc8c35a2f87d3d237c801aefef73c 100644 --- a/indra/llui/lltextbox.h +++ b/indra/llui/lltextbox.h @@ -159,11 +159,4 @@ private: callback_t mClickedCallback; }; -#ifdef LL_WINDOWS -#ifndef INSTANTIATE_GETCHILD_TEXTBOX -#pragma warning (disable : 4231) -extern template LLTextBox* LLView::getChild<LLTextBox>( const std::string& name, BOOL recurse, BOOL create_if_missing ) const; -#endif -#endif - #endif diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index 6649264d9a8e4fd6764aec8f7f997acd032b56a5..ce16f11d3397b12476d38ea0a1c91012c8d13161 100644 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -63,7 +63,7 @@ // // Globals // -static LLDefaultWidgetRegistry::Register<LLTextEditor> r("simple_text_editor"); +static LLDefaultChildRegistry::Register<LLTextEditor> r("simple_text_editor"); // // Constants @@ -304,7 +304,7 @@ LLTextEditor::LLTextEditor(const LLTextEditor::Params& p) LLViewBorder::Params params; params.name("text ed border"); params.rect(getLocalRect()); - params.bevel_type(LLViewBorder::BEVEL_IN); + params.bevel_style(LLViewBorder::BEVEL_IN); params.border_thickness(text_editor_border); mBorder = LLUICtrlFactory::create<LLViewBorder> (params); addChild( mBorder ); diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp index 12875b4ed175f3d155ff13474067ebdfdf921df3..c08abf3caf47f76ff8ee67ce3fae6438506aecb5 100644 --- a/indra/llui/llui.cpp +++ b/indra/llui/llui.cpp @@ -90,8 +90,8 @@ std::list<std::string> gUntranslated; /*static*/ std::vector<std::string> LLUI::sXUIPaths; // register searcheditor here -static LLDefaultWidgetRegistry::Register<LLSearchEditor> register_search_editor("search_editor"); -static LLDefaultWidgetRegistry::Register<LLFlyoutButton> register_flyout_button("flyout_button"); +static LLDefaultChildRegistry::Register<LLSearchEditor> register_search_editor("search_editor"); +static LLDefaultChildRegistry::Register<LLFlyoutButton> register_flyout_button("flyout_button"); // @@ -1934,8 +1934,8 @@ LLLocalClipRect::LLLocalClipRect(const LLRect &rect, BOOL enabled) namespace LLInitParam { - TypedParam<LLUIColor >::TypedParam(BlockDescriptor& descriptor, const char* name, const LLUIColor& value, ParamDescriptor::validation_func_t func) - : super_t(descriptor, name, value, func), + TypedParam<LLUIColor >::TypedParam(BlockDescriptor& descriptor, const char* name, const LLUIColor& value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count) + : super_t(descriptor, name, value, func, min_count, max_count), red("red"), green("green"), blue("blue"), @@ -1964,11 +1964,11 @@ namespace LLInitParam declare("blue", LLColor4::blue); } - TypedParam<const LLFontGL*>::TypedParam(BlockDescriptor& descriptor, const char* name, const LLFontGL*const value, ParamDescriptor::validation_func_t func) - : super_t(descriptor, name, value, func), - name("", std::string("")), - size("size", std::string("")), - style("style", std::string("")) + TypedParam<const LLFontGL*>::TypedParam(BlockDescriptor& descriptor, const char* name, const LLFontGL*const value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count) + : super_t(descriptor, name, value, func, min_count, max_count), + name(""), + size("size"), + style("style") {} const LLFontGL* TypedParam<const LLFontGL*>::getValueFromBlock() const @@ -1995,8 +1995,8 @@ namespace LLInitParam return mData.mValue; } - TypedParam<LLRect>::TypedParam(BlockDescriptor& descriptor, const char* name, const LLRect& value, ParamDescriptor::validation_func_t func) - : super_t(descriptor, name, value, func), + TypedParam<LLRect>::TypedParam(BlockDescriptor& descriptor, const char* name, const LLRect& value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count) + : super_t(descriptor, name, value, func, min_count, max_count), left("left"), top("top"), right("right"), diff --git a/indra/llui/llui.h b/indra/llui/llui.h index c0873247c037296d6028b7d2a4ef9574b13f7838..c4cdbf2c149a0b1a2fbbf7be8275d39fc2425d20 100644 --- a/indra/llui/llui.h +++ b/indra/llui/llui.h @@ -706,7 +706,7 @@ namespace LLInitParam width, height; - TypedParam(BlockDescriptor& descriptor, const char* name, const LLRect& value, ParamDescriptor::validation_func_t func); + TypedParam(BlockDescriptor& descriptor, const char* name, const LLRect& value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count); LLRect getValueFromBlock() const; }; @@ -729,7 +729,7 @@ namespace LLInitParam Optional<F32> alpha; Optional<std::string> control; - TypedParam(BlockDescriptor& descriptor, const char* name, const LLUIColor& value, ParamDescriptor::validation_func_t func); + TypedParam(BlockDescriptor& descriptor, const char* name, const LLUIColor& value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count); LLUIColor getValueFromBlock() const; }; @@ -743,7 +743,7 @@ namespace LLInitParam Optional<std::string> size; Optional<std::string> style; - TypedParam(BlockDescriptor& descriptor, const char* name, const LLFontGL* const value, ParamDescriptor::validation_func_t func); + TypedParam(BlockDescriptor& descriptor, const char* name, const LLFontGL* const value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count); const LLFontGL* getValueFromBlock() const; }; diff --git a/indra/llui/lluictrl.cpp b/indra/llui/lluictrl.cpp index 395bed7959484401ec1e36f15c25c7a36545bf32..43430cba24303441242f012fbe76134cc70a5459 100644 --- a/indra/llui/lluictrl.cpp +++ b/indra/llui/lluictrl.cpp @@ -38,7 +38,7 @@ #include "llpanel.h" #include "lluictrlfactory.h" -static LLDefaultWidgetRegistry::Register<LLUICtrl> r("ui_ctrl"); +static LLDefaultChildRegistry::Register<LLUICtrl> r("ui_ctrl"); LLUICtrl::Params::Params() : tab_stop("tab_stop", true), @@ -116,7 +116,7 @@ void LLFocusableElement::setFocus(BOOL b) //static const LLUICtrl::Params& LLUICtrl::getDefaultParams() { - return LLUICtrlFactory::getDefaultParams<LLUICtrl::Params>(); + return LLUICtrlFactory::getDefaultParams<LLUICtrl>(); } diff --git a/indra/llui/lluictrl.h b/indra/llui/lluictrl.h index 2b9caa2a82f7f4fc4bc5e48d1db47969e34be707..f4c7cf36f253af21402f94af09f2115cffb74a61 100644 --- a/indra/llui/lluictrl.h +++ b/indra/llui/lluictrl.h @@ -130,8 +130,8 @@ public: Alternative<std::string> invisible; ControlVisibility() - : visible("make_visible_control"), - invisible("make_invisible_control") + : visible("visiblity_control"), + invisible("invisiblity_control") {} }; struct Params : public LLInitParam::Block<Params, LLView::Params> @@ -324,6 +324,10 @@ namespace LLInitParam bool ParamCompare<LLUICtrl::focus_callback_t>::equals( const LLUICtrl::focus_callback_t &a, const LLUICtrl::focus_callback_t &b); + + template<> + bool ParamCompare<LLLazyValue<LLColor4> >::equals( + const LLLazyValue<LLColor4> &a, const LLLazyValue<LLColor4> &b); } #endif // LL_LLUICTRL_H diff --git a/indra/llui/lluictrlfactory.cpp b/indra/llui/lluictrlfactory.cpp index 24caf51159b226320c5e119a20e147297f08f3db..9df22e39b4c0cec268078e95af2e1dc4bd434e81 100644 --- a/indra/llui/lluictrlfactory.cpp +++ b/indra/llui/lluictrlfactory.cpp @@ -85,7 +85,8 @@ LLFastTimer::DeclareTimer FTM_WIDGET_SETUP("Widget Setup"); //----------------------------------------------------------------------------- // Register widgets that are purely data driven here so they get linked in #include "llstatview.h" -static LLDefaultWidgetRegistry::Register<LLStatView> register_stat_view("stat_view"); +static LLDefaultChildRegistry::Register<LLStatView> + register_stat_view("stat_view"); //----------------------------------------------------------------------------- @@ -107,7 +108,7 @@ public: }; -static LLDefaultWidgetRegistry::Register<LLUICtrlLocate> r1("locate"); +static LLDefaultChildRegistry::Register<LLUICtrlLocate> r1("locate"); //----------------------------------------------------------------------------- // LLUICtrlFactory() @@ -135,7 +136,7 @@ void LLUICtrlFactory::loadWidgetTemplate(const std::string& widget_tag, LLInitPa } //static -void LLUICtrlFactory::createChildren(LLView* viewp, LLXMLNodePtr node, LLXMLNodePtr output_node) +void LLUICtrlFactory::createChildren(LLView* viewp, LLXMLNodePtr node, const widget_registry_t& registry, LLXMLNodePtr output_node) { if (node.isNull()) return; @@ -147,7 +148,7 @@ void LLUICtrlFactory::createChildren(LLView* viewp, LLXMLNodePtr node, LLXMLNode outputChild = output_node->createChild("", FALSE); } - if (!instance().createFromXML(child_node, viewp, LLStringUtil::null, outputChild, viewp->getChildRegistry())) + if (!instance().createFromXML(child_node, viewp, LLStringUtil::null, registry, outputChild)) { std::string child_name = std::string(child_node->getName()->mString); llwarns << "Could not create widget named " << child_node->getName()->mString << llendl; @@ -338,12 +339,12 @@ BOOL LLUICtrlFactory::buildPanel(LLPanel* panelp, const std::string& filename, L LLFastTimer::DeclareTimer FTM_CREATE_FROM_XML("Create child widget"); -LLView *LLUICtrlFactory::createFromXML(LLXMLNodePtr node, LLView* parent, const std::string& filename, LLXMLNodePtr output_node, const widget_registry_t& registry) +LLView *LLUICtrlFactory::createFromXML(LLXMLNodePtr node, LLView* parent, const std::string& filename, const widget_registry_t& registry, LLXMLNodePtr output_node) { LLFastTimer timer(FTM_CREATE_FROM_XML); std::string ctrl_type = node->getName()->mString; LLStringUtil::toLower(ctrl_type); - + const LLWidgetCreatorFunc* funcp = registry.getValue(ctrl_type); if (funcp == NULL) { @@ -448,11 +449,497 @@ void LLUICtrlFactory::popFactoryFunctions() } } -const widget_registry_t& LLUICtrlFactory::getWidgetRegistry(LLView* viewp) + +// +// LLRNGWriter - writes Relax NG schema files based on a param block +// +LLRNGWriter::LLRNGWriter() +{ + // register various callbacks for inspecting the contents of a param block + registerInspectFunc<bool>(boost::bind(&LLRNGWriter::writeAttribute, this, "boolean", _1, _2, _3, _4)); + registerInspectFunc<std::string>(boost::bind(&LLRNGWriter::writeAttribute, this, "string", _1, _2, _3, _4)); + registerInspectFunc<U8>(boost::bind(&LLRNGWriter::writeAttribute, this, "unsignedByte", _1, _2, _3, _4)); + registerInspectFunc<S8>(boost::bind(&LLRNGWriter::writeAttribute, this, "signedByte", _1, _2, _3, _4)); + registerInspectFunc<U16>(boost::bind(&LLRNGWriter::writeAttribute, this, "unsignedShort", _1, _2, _3, _4)); + registerInspectFunc<S16>(boost::bind(&LLRNGWriter::writeAttribute, this, "signedShort", _1, _2, _3, _4)); + registerInspectFunc<U32>(boost::bind(&LLRNGWriter::writeAttribute, this, "unsignedInt", _1, _2, _3, _4)); + registerInspectFunc<S32>(boost::bind(&LLRNGWriter::writeAttribute, this, "integer", _1, _2, _3, _4)); + registerInspectFunc<F32>(boost::bind(&LLRNGWriter::writeAttribute, this, "float", _1, _2, _3, _4)); + registerInspectFunc<F64>(boost::bind(&LLRNGWriter::writeAttribute, this, "double", _1, _2, _3, _4)); + registerInspectFunc<LLColor4>(boost::bind(&LLRNGWriter::writeAttribute, this, "string", _1, _2, _3, _4)); + registerInspectFunc<LLUIColor>(boost::bind(&LLRNGWriter::writeAttribute, this, "string", _1, _2, _3, _4)); + registerInspectFunc<LLUUID>(boost::bind(&LLRNGWriter::writeAttribute, this, "string", _1, _2, _3, _4)); + registerInspectFunc<LLSD>(boost::bind(&LLRNGWriter::writeAttribute, this, "string", _1, _2, _3, _4)); +} + +void LLRNGWriter::writeRNG(const std::string& type_name, LLXMLNodePtr node, const LLInitParam::BaseBlock& block, const std::string& xml_namespace) +{ + mGrammarNode = node; + mGrammarNode->setName("grammar"); + mGrammarNode->createChild("xmlns", true)->setStringValue("http://relaxng/ns/structure/1.0"); + mGrammarNode->createChild("datatypeLibrary", true)->setStringValue("http://www.w3.org/2001/XMLSchema-datatypes"); + mGrammarNode->createChild("ns", true)->setStringValue(xml_namespace); + + node = mGrammarNode->createChild("start", false); + node = node->createChild("ref", false); + node->createChild("name", true)->setStringValue(type_name); + + node = mGrammarNode->createChild("define", false); + node->createChild("name", true)->setStringValue(type_name); + + mElementNode = node->createChild("element", false); + mElementNode->createChild("name", true)->setStringValue(type_name); + + block.inspectBlock(*this); +} + +void LLRNGWriter::writeAttribute(const std::string& type, const Parser::name_stack_t& stack, S32 min_count, S32 max_count, const std::vector<std::string>* possible_values) +{ + name_stack_t non_empty_names; + std::string attribute_name; + for (name_stack_t::const_iterator it = stack.begin(); + it != stack.end(); + ++it) + { + const std::string& name = it->first; + if (!name.empty()) + { + non_empty_names.push_back(*it); + } + } + + if (non_empty_names.empty()) return; + + for (name_stack_t::const_iterator it = non_empty_names.begin(); + it != non_empty_names.end(); + ++it) + { + if (!attribute_name.empty()) + { + attribute_name += "."; + } + attribute_name += it->first; + } + + // singular attribute + if (non_empty_names.size() == 1) + { + if (max_count == 1) + { + LLXMLNodePtr node = getCardinalityNode(mElementNode, min_count, max_count)->createChild("attribute", false); + node->createChild("name", true)->setStringValue(attribute_name); + node->createChild("data", false)->createChild("type", true)->setStringValue(type); + } + } + // compound attribute + else + { + std::string element_name; + + // traverse all but last element, leaving that as an attribute name + name_stack_t::const_iterator end_it = non_empty_names.end(); + end_it--; + + for (name_stack_t::const_iterator it = non_empty_names.begin(); + it != end_it; + ++it) + { + if (it != non_empty_names.begin()) + { + element_name += "."; + } + element_name += it->first; + } + + elements_map_t::iterator found_it = mElementsWritten.find(element_name); + if (found_it != mElementsWritten.end()) + { + // reuse existing element + LLXMLNodePtr choice_node = found_it->second; + + LLXMLNodePtr node = choice_node->mChildren->head; + node = getCardinalityNode(node, min_count, max_count)->createChild("attribute", false); + node->createChild("name", true)->setStringValue(attribute_name); + node->createChild("data", false)->createChild("type", true)->setStringValue(type); + + node = choice_node->mChildren->head->mNext->mChildren->head; + node = getCardinalityNode(node, min_count, max_count)->createChild("attribute", false); + node->createChild("name", true)->setStringValue(non_empty_names.back().first); + node->createChild("data", false)->createChild("type", true)->setStringValue(type); + } + else + { + LLXMLNodePtr choice_node = mElementNode->createChild("choice", false); + + LLXMLNodePtr node = choice_node->createChild("group", false); + node = getCardinalityNode(node, min_count, max_count)->createChild("attribute", false); + node->createChild("name", true)->setStringValue(attribute_name); + node->createChild("data", false)->createChild("type", true)->setStringValue(type); + + node = choice_node->createChild("element", false); + node->createChild("name", true)->setStringValue(element_name); + node = getCardinalityNode(node, min_count, max_count)->createChild("attribute", false); + node->createChild("name", true)->setStringValue(non_empty_names.back().first); + node->createChild("data", false)->createChild("type", true)->setStringValue(type); + + node = choice_node->createChild("element", false); + node->createChild("name", true)->setStringValue(type + "." + element_name); + node->createChild("ref", true)->createChild("name", true)->setStringValue(element_name); + + mElementsWritten[element_name] = choice_node; + } + } +} + +LLXMLNodePtr LLRNGWriter::getCardinalityNode(LLXMLNodePtr parent_node, S32 min_count, S32 max_count) +{ + // unlinked by default, meaning this attribute is forbidden + LLXMLNodePtr count_node = new LLXMLNode(); + if (min_count >= 1) + { + if (max_count == 1 && min_count == 1) + { + // just add raw element, will count as 1 and only 1 + count_node = mElementNode; + } + else + { + count_node = mElementNode->createChild("oneOrMore", false); + } + } + else + { + if (max_count == 1) + { + count_node = mElementNode->createChild("optional", false); + } + else if (max_count > 1) + { + count_node = mElementNode->createChild("zeroOrMore", false); + } + } + return count_node; +} +// +// LLXSDWriter +// +LLXSDWriter::LLXSDWriter() +{ + registerInspectFunc<bool>(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:boolean", _1, _2, _3, _4)); + registerInspectFunc<std::string>(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:string", _1, _2, _3, _4)); + registerInspectFunc<U8>(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:unsignedByte", _1, _2, _3, _4)); + registerInspectFunc<S8>(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:signedByte", _1, _2, _3, _4)); + registerInspectFunc<U16>(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:unsignedShort", _1, _2, _3, _4)); + registerInspectFunc<S16>(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:signedShort", _1, _2, _3, _4)); + registerInspectFunc<U32>(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:unsignedInt", _1, _2, _3, _4)); + registerInspectFunc<S32>(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:integer", _1, _2, _3, _4)); + registerInspectFunc<F32>(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:float", _1, _2, _3, _4)); + registerInspectFunc<F64>(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:double", _1, _2, _3, _4)); + registerInspectFunc<LLColor4>(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:string", _1, _2, _3, _4)); + registerInspectFunc<LLUIColor>(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:string", _1, _2, _3, _4)); + registerInspectFunc<LLUUID>(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:string", _1, _2, _3, _4)); + registerInspectFunc<LLSD>(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:string", _1, _2, _3, _4)); +} + +void LLXSDWriter::writeXSD(const std::string& type_name, LLXMLNodePtr node, const LLInitParam::BaseBlock& block, const std::string& xml_namespace) +{ + mSchemaNode = node; + node->setName("xs:schema"); + node->createChild("attributeFormDefault", true)->setStringValue("unqualified"); + node->createChild("elementFormDefault", true)->setStringValue("qualified"); + node->createChild("targetNamespace", true)->setStringValue(xml_namespace); + node->createChild("xmlns:xs", true)->setStringValue("http://www.w3.org/2001/XMLSchema"); + node->createChild("xmlns", true)->setStringValue(xml_namespace); + + node = node->createChild("xs:complexType", false); + node->createChild("name", true)->setStringValue(type_name); + node->createChild("mixed", true)->setStringValue("true"); + + mAttributeNode = node; + mElementNode = node->createChild("xs:choice", false); + mElementNode->createChild("minOccurs", true)->setStringValue("0"); + mElementNode->createChild("maxOccurs", true)->setStringValue("unbounded"); + block.inspectBlock(*this); + + // duplicate element choices + LLXMLNodeList children; + mElementNode->getChildren("xs:element", children, FALSE); + for (LLXMLNodeList::iterator child_it = children.begin(); child_it != children.end(); ++child_it) + { + LLXMLNodePtr child_copy = child_it->second->deepCopy(); + std::string child_name; + child_copy->getAttributeString("name", child_name); + child_copy->setAttributeString("name", type_name + "." + child_name); + mElementNode->addChild(child_copy); + } + + LLXMLNodePtr element_declaration_node = mSchemaNode->createChild("xs:element", false); + element_declaration_node->createChild("name", true)->setStringValue(type_name); + element_declaration_node->createChild("type", true)->setStringValue(type_name); +} + +void LLXSDWriter::writeAttribute(const std::string& type, const Parser::name_stack_t& stack, S32 min_count, S32 max_count, const std::vector<std::string>* possible_values) +{ + name_stack_t non_empty_names; + std::string attribute_name; + for (name_stack_t::const_iterator it = stack.begin(); + it != stack.end(); + ++it) + { + const std::string& name = it->first; + if (!name.empty()) + { + non_empty_names.push_back(*it); + } + } + + for (name_stack_t::const_iterator it = non_empty_names.begin(); + it != non_empty_names.end(); + ++it) + { + if (!attribute_name.empty()) + { + attribute_name += "."; + } + attribute_name += it->first; + } + + // only flag non-nested attributes as mandatory, nested attributes have variant syntax + // that can't be properly constrained in XSD + // e.g. <foo mandatory.value="bar"/> vs <foo><mandatory value="bar"/></foo> + bool attribute_mandatory = min_count == 1 && max_count == 1 && non_empty_names.size() == 1; + + // don't bother supporting "Multiple" params as xml attributes + if (max_count <= 1) + { + // add compound attribute to root node + addAttributeToSchema(mAttributeNode, attribute_name, type, attribute_mandatory, possible_values); + } + + // now generated nested elements for compound attributes + if (non_empty_names.size() > 1 && !attribute_mandatory) + { + std::string element_name; + + // traverse all but last element, leaving that as an attribute name + name_stack_t::const_iterator end_it = non_empty_names.end(); + end_it--; + + for (name_stack_t::const_iterator it = non_empty_names.begin(); + it != end_it; + ++it) + { + if (it != non_empty_names.begin()) + { + element_name += "."; + } + element_name += it->first; + } + + std::string short_attribute_name = non_empty_names.back().first; + + LLXMLNodePtr complex_type_node; + + // find existing element node here, starting at tail of child list + if (mElementNode->mChildren.notNull()) + { + for(LLXMLNodePtr element = mElementNode->mChildren->tail; + element.notNull(); + element = element->mPrev) + { + std::string name; + if(element->getAttributeString("name", name) && name == element_name) + { + complex_type_node = element->mChildren->head; + break; + } + } + } + //create complex_type node + // + //<xs:element + // maxOccurs="1" + // minOccurs="0" + // name="name"> + // <xs:complexType> + // </xs:complexType> + //</xs:element> + if(complex_type_node.isNull()) + { + complex_type_node = mElementNode->createChild("xs:element", false); + + complex_type_node->createChild("minOccurs", true)->setIntValue(min_count); + complex_type_node->createChild("maxOccurs", true)->setIntValue(max_count); + complex_type_node->createChild("name", true)->setStringValue(element_name); + complex_type_node = complex_type_node->createChild("xs:complexType", false); + } + + addAttributeToSchema(complex_type_node, short_attribute_name, type, false, possible_values); + } +} + +void LLXSDWriter::addAttributeToSchema(LLXMLNodePtr type_declaration_node, const std::string& attribute_name, const std::string& type, bool mandatory, const std::vector<std::string>* possible_values) { - return viewp->getChildRegistry(); + if (!attribute_name.empty()) + { + LLXMLNodePtr new_enum_type_node; + if (possible_values != NULL) + { + // custom attribute type, for example + //<xs:simpleType> + // <xs:restriction + // base="xs:string"> + // <xs:enumeration + // value="a" /> + // <xs:enumeration + // value="b" /> + // </xs:restriction> + // </xs:simpleType> + new_enum_type_node = new LLXMLNode("xs:simpleType", false); + + LLXMLNodePtr restriction_node = new_enum_type_node->createChild("xs:restriction", false); + restriction_node->createChild("base", true)->setStringValue("xs:string"); + + for (std::vector<std::string>::const_iterator it = possible_values->begin(); + it != possible_values->end(); + ++it) + { + LLXMLNodePtr enum_node = restriction_node->createChild("xs:enumeration", false); + enum_node->createChild("value", true)->setStringValue(*it); + } + } + + string_set_t& attributes_written = mAttributesWritten[type_declaration_node]; + + string_set_t::iterator found_it = std::lower_bound(attributes_written.begin(), attributes_written.end(), attribute_name); + + // attribute not yet declared + if (found_it == attributes_written.end() || attributes_written.key_comp()(attribute_name, *found_it)) + { + attributes_written.insert(found_it, attribute_name); + + LLXMLNodePtr attribute_node = type_declaration_node->createChild("xs:attribute", false); + + // attribute name + attribute_node->createChild("name", true)->setStringValue(attribute_name); + + if (new_enum_type_node.notNull()) + { + attribute_node->addChild(new_enum_type_node); + } + else + { + // simple attribute type + attribute_node->createChild("type", true)->setStringValue(type); + } + + // required or optional + attribute_node->createChild("use", true)->setStringValue(mandatory ? "required" : "optional"); + } + // attribute exists...handle collision of same name attributes with potentially different types + else + { + LLXMLNodePtr attribute_declaration; + if (type_declaration_node.notNull()) + { + for(LLXMLNodePtr node = type_declaration_node->mChildren->tail; + node.notNull(); + node = node->mPrev) + { + std::string name; + if (node->getAttributeString("name", name) && name == attribute_name) + { + attribute_declaration = node; + break; + } + } + } + + bool new_type_is_enum = new_enum_type_node.notNull(); + bool existing_type_is_enum = !attribute_declaration->hasAttribute("type"); + + // either type is enum, revert to string in collision + // don't bother to check for enum equivalence + if (new_type_is_enum || existing_type_is_enum) + { + if (attribute_declaration->hasAttribute("type")) + { + attribute_declaration->setAttributeString("type", "xs:string"); + } + else + { + attribute_declaration->createChild("type", true)->setStringValue("xs:string"); + } + attribute_declaration->deleteChildren("xs:simpleType"); + } + else + { + // check for collision of different standard types + std::string existing_type; + attribute_declaration->getAttributeString("type", existing_type); + // if current type is not the same as the new type, revert to strnig + if (existing_type != type) + { + // ...than use most general type, string + attribute_declaration->setAttributeString("type", "string"); + } + } + } + } } +// +// LLXUIXSDWriter +// +void LLXUIXSDWriter::writeXSD(const std::string& type_name, const std::string& path, const LLInitParam::BaseBlock& block) +{ + std::string file_name(path); + file_name += type_name + ".xsd"; + LLXMLNodePtr root_nodep = new LLXMLNode(); + + LLXSDWriter::writeXSD(type_name, root_nodep, block, "http://www.lindenlab.com/xui"); + + // add includes for all possible children + const std::type_info* type = *LLWidgetTypeRegistry::instance().getValue(type_name); + const widget_registry_t* widget_registryp = LLChildRegistryRegistry::instance().getValue(type); + + // add include declarations for all valid children + for (widget_registry_t::Registrar::registry_map_t::const_iterator it = widget_registryp->currentRegistrar().beginItems(); + it != widget_registryp->currentRegistrar().endItems(); + ++it) + { + std::string widget_name = it->first; + if (widget_name == type_name) + { + continue; + } + LLXMLNodePtr nodep = new LLXMLNode("xs:include", false); + nodep->createChild("schemaLocation", true)->setStringValue(widget_name + ".xsd"); + + // add to front of schema + mSchemaNode->addChild(nodep, mSchemaNode); + } + + // add choices for valid children + if (widget_registryp) + { + for (widget_registry_t::Registrar::registry_map_t::const_iterator it = widget_registryp->currentRegistrar().beginItems(); + it != widget_registryp->currentRegistrar().endItems(); + ++it) + { + std::string widget_name = it->first; + //<xs:element name="widget_name" type="widget_name"> + LLXMLNodePtr widget_node = mElementNode->createChild("xs:element", false); + widget_node->createChild("name", true)->setStringValue(widget_name); + widget_node->createChild("type", true)->setStringValue(widget_name); + } + } + + LLFILE* xsd_file = LLFile::fopen(file_name.c_str(), "w"); + LLXMLNode::writeHeaderToFile(xsd_file); + root_nodep->writeToFile(xsd_file); + fclose(xsd_file); +} // // LLXUIParser diff --git a/indra/llui/lluictrlfactory.h b/indra/llui/lluictrlfactory.h index f8d584bc75549f5e7c0d5c314dc5a169bf68bb9e..894c77888ca5274ee4d2c8fdef2045d9873d2afb 100644 --- a/indra/llui/lluictrlfactory.h +++ b/indra/llui/lluictrlfactory.h @@ -41,11 +41,64 @@ #include <boost/function.hpp> #include <iosfwd> #include <stack> +#include <set> class LLPanel; class LLFloater; class LLView; +class LLRNGWriter : public LLInitParam::Parser +{ + LOG_CLASS(LLRNGWriter); +public: + void writeRNG(const std::string& name, LLXMLNodePtr node, const LLInitParam::BaseBlock& block, const std::string& xml_namespace); + + /*virtual*/ std::string getCurrentElementName() { return LLStringUtil::null; } + + LLRNGWriter(); + +private: + LLXMLNodePtr getCardinalityNode(LLXMLNodePtr parent_node, S32 min_count, S32 max_count); + + void writeAttribute(const std::string& type, const Parser::name_stack_t&, S32 min_count, S32 max_count, const std::vector<std::string>* possible_values); + LLXMLNodePtr mElementNode; + LLXMLNodePtr mGrammarNode; + + typedef std::map<std::string, LLXMLNodePtr> elements_map_t; + elements_map_t mElementsWritten; +}; + + +class LLXSDWriter : public LLInitParam::Parser +{ + LOG_CLASS(LLXSDWriter); +public: + void writeXSD(const std::string& name, LLXMLNodePtr node, const LLInitParam::BaseBlock& block, const std::string& xml_namespace); + + /*virtual*/ std::string getCurrentElementName() { return LLStringUtil::null; } + + LLXSDWriter(); + +protected: + void writeAttribute(const std::string& type, const Parser::name_stack_t&, S32 min_count, S32 max_count, const std::vector<std::string>* possible_values); + void addAttributeToSchema(LLXMLNodePtr nodep, const std::string& attribute_name, const std::string& type, bool mandatory, const std::vector<std::string>* possible_values); + LLXMLNodePtr mAttributeNode; + LLXMLNodePtr mElementNode; + LLXMLNodePtr mSchemaNode; + + typedef std::set<std::string> string_set_t; + typedef std::map<LLXMLNodePtr, string_set_t> attributes_map_t; + attributes_map_t mAttributesWritten; +}; + +// NOTE: DOES NOT WORK YET +// should support child widgets for XUI +class LLXUIXSDWriter : public LLXSDWriter +{ +public: + void writeXSD(const std::string& name, const std::string& path, const LLInitParam::BaseBlock& block); +}; + class LLXUIParser : public LLInitParam::Parser, public LLSingleton<LLXUIParser> { LOG_CLASS(LLXUIParser); @@ -118,13 +171,23 @@ typedef boost::function<LLView* (LLXMLNodePtr node, LLView *parent, LLXMLNodePtr typedef LLRegistry<std::string, LLWidgetCreatorFunc> widget_registry_t; +// sort functor for typeid maps +struct LLCompareTypeID +{ + bool operator()(const std::type_info* lhs, const std::type_info* rhs) const + { + return lhs->before(*rhs); + } +}; + +// lookup widget constructor funcs by widget name template <typename DERIVED_TYPE> -class LLWidgetRegistry : public LLRegistrySingleton<std::string, LLWidgetCreatorFunc, DERIVED_TYPE> +class LLChildRegistry : public LLRegistrySingleton<std::string, LLWidgetCreatorFunc, DERIVED_TYPE> { public: typedef LLRegistrySingleton<std::string, LLWidgetCreatorFunc, DERIVED_TYPE> super_t; // local static instance for registering a particular widget - template<typename T, typename PARAM_BLOCK = typename T::Params> + template<typename T> class Register : public super_t::StaticRegistrar { public: @@ -133,35 +196,40 @@ public: }; protected: - LLWidgetRegistry() {} + LLChildRegistry() {} }; -class LLDefaultWidgetRegistry : public LLWidgetRegistry<LLDefaultWidgetRegistry> +class LLDefaultChildRegistry : public LLChildRegistry<LLDefaultChildRegistry> { protected: - LLDefaultWidgetRegistry() {} - friend class LLSingleton<LLDefaultWidgetRegistry>; -}; - -struct LLCompareTypeID -{ - bool operator()(const std::type_info* lhs, const std::type_info* rhs) const - { - return lhs->before(*rhs); - } + LLDefaultChildRegistry(){} + friend class LLSingleton<LLDefaultChildRegistry>; }; +// lookup widget name by type +class LLWidgetNameRegistry +: public LLRegistrySingleton<const std::type_info*, std::string, LLWidgetNameRegistry , LLCompareTypeID> +{}; -class LLWidgetTemplateRegistry -: public LLRegistrySingleton<const std::type_info*, std::string, LLWidgetTemplateRegistry, LLCompareTypeID> +// lookup widget type by name +class LLWidgetTypeRegistry +: public LLRegistrySingleton<std::string, const std::type_info*, LLWidgetTypeRegistry> {}; -// function used to create new default widgets via LLView::getChild<T> +// lookup factory functions for default widget instances by widget type typedef LLView* (*dummy_widget_creator_func_t)(const std::string&); +class LLDefaultWidgetRegistry +: public LLRegistrySingleton<const std::type_info*, dummy_widget_creator_func_t, LLDefaultWidgetRegistry, LLCompareTypeID> +{}; -// used to register factory functions for default widget instances -class LLDummyWidgetRegistry -: public LLRegistrySingleton<const std::type_info*, dummy_widget_creator_func_t, LLDummyWidgetRegistry, LLCompareTypeID> +// lookup function for generating empty param block by widget type +typedef const LLInitParam::BaseBlock& (*empty_param_block_func_t)(); +class LLDefaultParamBlockRegistry +: public LLRegistrySingleton<const std::type_info*, empty_param_block_func_t, LLDefaultParamBlockRegistry, LLCompareTypeID> +{}; + +class LLChildRegistryRegistry +: public LLRegistrySingleton<const std::type_info*, widget_registry_t, LLChildRegistryRegistry> {}; extern LLFastTimer::DeclareTimer FTM_WIDGET_SETUP; @@ -176,26 +244,26 @@ private: ~LLUICtrlFactory(); // only partial specialization allowed in inner classes, so use extra dummy parameter - template <typename T, int DUMMY> - class ParamDefaults : public LLSingleton<ParamDefaults<T, DUMMY> > + template <typename PARAM_BLOCK, int DUMMY> + class ParamDefaults : public LLSingleton<ParamDefaults<PARAM_BLOCK, DUMMY> > { public: ParamDefaults() { // recursively initialize from base class param block - ((typename T::base_block_t&)mPrototype).fillFrom(ParamDefaults<typename T::base_block_t, DUMMY>::instance().get()); + ((typename PARAM_BLOCK::base_block_t&)mPrototype).fillFrom(ParamDefaults<typename PARAM_BLOCK::base_block_t, DUMMY>::instance().get()); // after initializing base classes, look up template file for this param block - std::string* param_block_tag = LLWidgetTemplateRegistry::instance().getValue(&typeid(T)); + std::string* param_block_tag = LLWidgetNameRegistry::instance().getValue(&typeid(PARAM_BLOCK)); if (param_block_tag) { LLUICtrlFactory::loadWidgetTemplate(*param_block_tag, mPrototype); } } - const T& get() { return mPrototype; } + const PARAM_BLOCK& get() { return mPrototype; } private: - T mPrototype; + PARAM_BLOCK mPrototype; }; // base case for recursion, there are NO base classes of LLInitParam::BaseBlock @@ -210,11 +278,12 @@ private: public: + // get default parameter block for widget of a specific type template<typename T> - static const T& getDefaultParams() + static const typename T::Params& getDefaultParams() { //#pragma message("Generating ParamDefaults") - return ParamDefaults<T, 0>::instance().get(); + return ParamDefaults<typename T::Params, 0>::instance().get(); } void buildFloater(LLFloater* floaterp, const std::string &filename, BOOL open_floater = TRUE, LLXMLNodePtr output_node = NULL); @@ -252,12 +321,10 @@ public: return widget; } - LLView* createFromXML(LLXMLNodePtr node, LLView* parent, const std::string& filename, LLXMLNodePtr output_node, const widget_registry_t& ); + LLView* createFromXML(LLXMLNodePtr node, LLView* parent, const std::string& filename, const widget_registry_t&, LLXMLNodePtr output_node ); - static const widget_registry_t& getWidgetRegistry(LLView*); - template<typename T> - static T* createFromFile(const std::string &filename, LLView *parent, LLXMLNodePtr output_node = NULL) + static T* createFromFile(const std::string &filename, LLView *parent, const widget_registry_t& registry, LLXMLNodePtr output_node = NULL) { //#pragma message("Generating LLUICtrlFactory::createFromFile") T* widget = NULL; @@ -283,7 +350,7 @@ public: goto fail; } - LLView* view = getInstance()->createFromXML(root_node, parent, filename, output_node, getWidgetRegistry(parent)); + LLView* view = getInstance()->createFromXML(root_node, parent, filename, registry, output_node); if (view) { widget = dynamic_cast<T*>(view); @@ -304,7 +371,7 @@ fail: template<class T> static T* getDefaultWidget(const std::string& name) { - dummy_widget_creator_func_t* dummy_func = LLDummyWidgetRegistry::instance().getValue(&typeid(T)); + dummy_widget_creator_func_t* dummy_func = LLDefaultWidgetRegistry::instance().getValue(&typeid(T)); return dummy_func ? dynamic_cast<T*>((*dummy_func)(name)) : NULL; } @@ -317,23 +384,23 @@ fail: return create<T>(params); } - template<typename T, typename PARAM_BLOCK> + template<typename T> static T* defaultBuilder(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr output_node) { LLFastTimer timer(FTM_WIDGET_SETUP); //#pragma message("Generating LLUICtrlFactory::defaultBuilder") - PARAM_BLOCK params(getDefaultParams<PARAM_BLOCK>()); + typename T::Params params(getDefaultParams<T>()); LLXUIParser::instance().readXUI(node, params); if (output_node) { // We always want to output top-left coordinates - PARAM_BLOCK output_params(params); + typename T::Params output_params(params); T::setupParamsForExport(output_params, parent); // Export only the differences between this any default params - PARAM_BLOCK default_params(getDefaultParams<PARAM_BLOCK>()); + typename T::Params default_params(getDefaultParams<T>()); output_node->setName(node->getName()->mString); LLXUIParser::instance().writeXUI( output_node, output_params, &default_params); @@ -361,8 +428,10 @@ fail: S32 tab_group = params.tab_group.isProvided() ? params.tab_group() : -1; setCtrlParent(widget, parent, tab_group); } + + typedef typename T::child_registry_t registry_t; - createChildren(widget, node, output_node); + createChildren(widget, node, registry_t::instance(), output_node); if (!widget->postBuild()) { @@ -373,7 +442,7 @@ fail: return widget; } - static void createChildren(LLView* viewp, LLXMLNodePtr node, LLXMLNodePtr output_node = NULL); + static void createChildren(LLView* viewp, LLXMLNodePtr node, const widget_registry_t&, LLXMLNodePtr output_node = NULL); static bool getLayeredXMLNode(const std::string &filename, LLXMLNodePtr& root); @@ -395,16 +464,28 @@ private: std::vector<std::string> mFileNames; }; +template<typename T> +const LLInitParam::BaseBlock& getEmptyParamBlock() +{ + static typename T::Params params; + return params; +} + // this is here to make gcc happy with reference to LLUICtrlFactory template<typename DERIVED> -template<typename T, typename PARAM_BLOCK> -LLWidgetRegistry<DERIVED>::Register<T, PARAM_BLOCK>::Register(const char* tag, LLWidgetCreatorFunc func) -: LLWidgetRegistry<DERIVED>::StaticRegistrar(tag, func.empty() ? (LLWidgetCreatorFunc)&LLUICtrlFactory::defaultBuilder<T, PARAM_BLOCK> : func) +template<typename T> +LLChildRegistry<DERIVED>::Register<T>::Register(const char* tag, LLWidgetCreatorFunc func) +: LLChildRegistry<DERIVED>::StaticRegistrar(tag, func.empty() ? (LLWidgetCreatorFunc)&LLUICtrlFactory::defaultBuilder<T> : func) { + const std::type_info* widget_type_infop = &typeid(T); // associate parameter block type with template .xml file - LLWidgetTemplateRegistry::instance().defaultRegistrar().add(&typeid(PARAM_BLOCK), tag); + LLWidgetNameRegistry ::instance().defaultRegistrar().add(&typeid(typename T::Params), tag); // associate widget type with factory function - LLDummyWidgetRegistry::instance().defaultRegistrar().add(&typeid(T), &LLUICtrlFactory::createDefaultWidget<T>); + LLDefaultWidgetRegistry::instance().defaultRegistrar().add(widget_type_infop, &LLUICtrlFactory::createDefaultWidget<T>); + LLWidgetTypeRegistry::instance().defaultRegistrar().add(tag, widget_type_infop); + LLDefaultParamBlockRegistry::instance().defaultRegistrar().add(widget_type_infop, &getEmptyParamBlock<T>); + typedef typename T::child_registry_t registry_t; + LLChildRegistryRegistry::instance().defaultRegistrar().add(widget_type_infop, registry_t::instance()); } diff --git a/indra/llui/lluiimage.h b/indra/llui/lluiimage.h index e3b473b5f6fae6cfd1f7ea85df05515efb5a83ee..0fb16876bf24760770911688a14193b5c075c388 100644 --- a/indra/llui/lluiimage.h +++ b/indra/llui/lluiimage.h @@ -95,8 +95,8 @@ namespace LLInitParam public: Optional<std::string> name; - TypedParam(BlockDescriptor& descriptor, const char* name, super_t::value_assignment_t value, ParamDescriptor::validation_func_t func) - : super_t(descriptor, name, value, func) + TypedParam(BlockDescriptor& descriptor, const char* name, super_t::value_assignment_t value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count) + : super_t(descriptor, name, value, func, min_count, max_count) { } diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp index 29d0f6a168718e37201eaa0afab2d26b00a4ecf2..777cf096acc3dc2810f2aca517378125e6e562ef 100644 --- a/indra/llui/llview.cpp +++ b/indra/llui/llview.cpp @@ -99,10 +99,15 @@ LLView::Params::Params() left_delta("left_delta", S32_MAX), center_horiz("center_horiz", false), center_vert("center_vert", false), - serializable("", false), + from_xui("from_xui", false), user_resize("user_resize"), auto_resize("auto_resize"), - needs_translate("translate") + needs_translate("translate"), + xmlns("xmlns"), + xmlns_xsi("xmlns:xsi"), + xsi_schemaLocation("xsi:schemaLocation"), + xsi_type("xsi:type") + { addSynonym(rect, ""); } @@ -111,7 +116,7 @@ LLView::LLView(const LLView::Params& p) : mName(p.name), mParentView(NULL), mReshapeFlags(FOLLOWS_NONE), - mSaveToXML(p.serializable), + mSaveToXML(p.from_xui), mIsFocusRoot(FALSE), mLastVisible(FALSE), mNextInsertionOrdinal(0), @@ -2291,13 +2296,6 @@ LLControlVariable *LLView::findControl(const std::string& name) return control_group.getControl(name); } -const widget_registry_t& LLView::getChildRegistry() const -{ - static widget_registry_t empty_registry; - return empty_registry; -} - - const S32 FLOATER_H_MARGIN = 15; const S32 MIN_WIDGET_HEIGHT = 10; const S32 VPAD = 4; @@ -2418,7 +2416,7 @@ void LLView::setupParams(LLView::Params& p, LLView* parent) const S32 VPAD = 4; const S32 MIN_WIDGET_HEIGHT = 10; - p.serializable(true); + p.from_xui(true); // *NOTE: This will confuse export of floater/panel coordinates unless // the default is also "topleft". JC diff --git a/indra/llui/llview.h b/indra/llui/llview.h index 422f62f602437a678a9adf622381e1a2b715e9e7..5f6341daa68f33f9b5b7e9a80ff142b106cceb5c 100644 --- a/indra/llui/llview.h +++ b/indra/llui/llview.h @@ -138,6 +138,9 @@ virtual BOOL handleUnicodeCharHere(llwchar uni_char); * */ +class LLViewWidgetRegistry : public LLChildRegistry<LLViewWidgetRegistry> +{}; + class LLView : public LLMouseHandler, public LLMortician { public: @@ -157,15 +160,16 @@ public: Mandatory<std::string> name; Optional<bool> enabled, - visible; - Optional<bool> mouse_opaque; - Optional<bool> use_bounding_rect; + visible, + mouse_opaque, + use_bounding_rect; + Optional<S32> tab_group, default_tab_group; Optional<std::string> tool_tip; Optional<S32> sound_flags; - Optional<bool> serializable; + Optional<bool> from_xui; Optional<Follows> follows; Optional<std::string> hover_cursor; @@ -192,10 +196,17 @@ public: //FIXME: get parent context involved in parsing traversal Ignored user_resize, auto_resize, - needs_translate; + needs_translate, + xmlns, + xmlns_xsi, + xsi_schemaLocation, + xsi_type; Params(); }; + + typedef LLViewWidgetRegistry child_registry_t; + void initFromParams(const LLView::Params&); protected: @@ -496,9 +507,6 @@ public: return dynamic_cast<T*>(found_it->second); } - // determines allowable children when parsing XUI - virtual const widget_registry_t& getChildRegistry() const; - ////////////////////////////////////////////// // statics ////////////////////////////////////////////// @@ -647,6 +655,9 @@ template <class T> T* LLView::getChild(const std::string& name, BOOL recurse, BO if (result) { + // *NOTE: You cannot call mFoo = getChild<LLFoo>("bar") + // in a floater or panel constructor. The widgets will not + // be ready. Instead, put it in postBuild(). llwarns << "Making dummy " << typeid(T).name() << " named \"" << name << "\" in " << getName() << llendl; } else diff --git a/indra/llui/llviewborder.cpp b/indra/llui/llviewborder.cpp index a5b09671bbd952a5aae6d7bda83aa54551c208b2..860aa3302e8c8901479565a82f8a293def09cd14 100644 --- a/indra/llui/llviewborder.cpp +++ b/indra/llui/llviewborder.cpp @@ -35,7 +35,7 @@ #include "llfocusmgr.h" #include "lluictrlfactory.h" -static LLDefaultWidgetRegistry::Register<LLViewBorder> r("view_border"); +static LLDefaultChildRegistry::Register<LLViewBorder> r("view_border"); void LLViewBorder::BevelValues::declareValues() { @@ -52,7 +52,7 @@ void LLViewBorder::StyleValues::declareValues() } LLViewBorder::Params::Params() -: bevel_type("bevel_style", BEVEL_OUT), +: bevel_style("bevel_style", BEVEL_OUT), render_style("border_style", STYLE_LINE), border_thickness("border_thickness"), highlight_light_color("highlight_light_color"), @@ -60,6 +60,8 @@ LLViewBorder::Params::Params() shadow_light_color("shadow_light_color"), shadow_dark_color("shadow_dark_color") { + addSynonym(border_thickness, "thickness"); + addSynonym(render_style, "style"); name = "view_border"; mouse_opaque = false; follows.flags = FOLLOWS_ALL; @@ -75,7 +77,7 @@ LLViewBorder::LLViewBorder(const LLViewBorder::Params& p) mHighlightDark(p.highlight_dark_color()), mShadowLight(p.shadow_light_color()), mShadowDark(p.shadow_dark_color()), - mBevel(p.bevel_type), + mBevel(p.bevel_style), mStyle(p.render_style) {} diff --git a/indra/llui/llviewborder.h b/indra/llui/llviewborder.h index 37e13fb18196f1b1204e38bbb805f137d820b1fa..92fd5693250a9d82df65bf52adb0d5d40e6bd05f 100644 --- a/indra/llui/llviewborder.h +++ b/indra/llui/llviewborder.h @@ -55,7 +55,7 @@ public: struct Params : public LLInitParam::Block<Params, LLView::Params> { - Optional<EBevel, BevelValues> bevel_type; + Optional<EBevel, BevelValues> bevel_style; Optional<EStyle, StyleValues> render_style; Optional<S32> border_thickness; diff --git a/indra/llxml/llxmlnode.cpp b/indra/llxml/llxmlnode.cpp index e97aa55190d334e58605cbe6ed8376a8d68d6623..5d43ac11e465d87e4d7a9630920762c9a6c64ace 100644 --- a/indra/llxml/llxmlnode.cpp +++ b/indra/llxml/llxmlnode.cpp @@ -149,7 +149,7 @@ LLXMLNodePtr LLXMLNode::deepCopy() if (mChildren.notNull()) { for (LLXMLChildList::iterator iter = mChildren->map.begin(); - iter != mChildren->map.end(); ++iter) + iter != mChildren->map.end(); ++iter) { newnode->addChild(iter->second->deepCopy()); } @@ -302,6 +302,22 @@ void LLXMLNode::addChild(LLXMLNodePtr new_child, LLXMLNodePtr after_child) mChildren->tail = new_child; } } + // if after_child == parent, then put new_child at beginning + else if (after_child == this) + { + // add to front of list + new_child->mNext = mChildren->head; + if (mChildren->head) + { + mChildren->head->mPrev = new_child; + mChildren->head = new_child; + } + else // no children + { + mChildren->head = new_child; + mChildren->tail = new_child; + } + } else { if (after_child->mNext.notNull()) diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index f96c8fdca048c8f233967af7b6ae986bcc71b8d7..6ec4fbbcd5a3956478945abba73114a48b02d9a2 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -82,6 +82,7 @@ set(viewer_SOURCE_FILES llbbox.cpp llbottomtray.cpp llbox.cpp + llbreadcrumbview.cpp llcallbacklist.cpp llcallingcard.cpp llcapabilitylistener.cpp @@ -173,6 +174,7 @@ set(viewer_SOURCE_FILES llfloaterhud.cpp llfloaterimagepreview.cpp llfloaterinspect.cpp + llfloaterinventory.cpp llfloaterjoystick.cpp llfloaterlagmeter.cpp llfloaterland.cpp @@ -198,6 +200,7 @@ set(viewer_SOURCE_FILES llfloatersettingsdebug.cpp llfloatersnapshot.cpp llfloatertelehub.cpp + llfloatertestlistview.cpp llfloatertools.cpp llfloatertopobjects.cpp llfloatertos.cpp @@ -209,6 +212,7 @@ set(viewer_SOURCE_FILES llfloaterwindlight.cpp llfloaterworldmap.cpp llfolderview.cpp + llfolderviewitem.cpp llfollowcam.cpp llfriendactions.cpp llgesturemgr.cpp @@ -236,10 +240,12 @@ set(viewer_SOURCE_FILES llimcontrolpanel.cpp llinventorybridge.cpp llinventoryclipboard.cpp + llinventoryfilter.cpp llinventorymodel.cpp - llinventoryview.cpp lljoystickbutton.cpp lllandmarklist.cpp + lllistbrowser.cpp + lllistview.cpp lllocationhistory.cpp lllocationinputctrl.cpp lllogchat.cpp @@ -495,6 +501,7 @@ set(viewer_HEADER_FILES llbbox.h llbottomtray.h llbox.h + llbreadcrumbview.h llcallbacklist.h llcallingcard.h llcapabilitylistener.h @@ -588,6 +595,7 @@ set(viewer_HEADER_FILES llfloaterhud.h llfloaterimagepreview.h llfloaterinspect.h + llfloaterinventory.h llfloaterjoystick.h llfloaterlagmeter.h llfloaterland.h @@ -613,6 +621,7 @@ set(viewer_HEADER_FILES llfloatersettingsdebug.h llfloatersnapshot.h llfloatertelehub.h + llfloatertestlistview.h llfloatertools.h llfloatertopobjects.h llfloatertos.h @@ -624,6 +633,8 @@ set(viewer_HEADER_FILES llfloaterwindlight.h llfloaterworldmap.h llfolderview.h + llfoldervieweventlistener.h + llfolderviewitem.h llfollowcam.h llfriendactions.h llgesturemgr.h @@ -650,11 +661,13 @@ set(viewer_HEADER_FILES llimcontrolpanel.h llinventorybridge.h llinventoryclipboard.h + llinventoryfilter.h llinventorymodel.h - llinventoryview.h lljoystickbutton.h lllandmarklist.h lllightconstants.h + lllistbrowser.h + lllistview.h lllocationhistory.h lllocationinputctrl.h lllogchat.h diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 567fda0034017edb93ea5a4cede01d722d95ec50..38eeca2bf8f7f77ec66990c0d8d5b57deb33fef8 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -9425,6 +9425,17 @@ <key>Value</key> <real>150000.0</real> </map> + <key>XUIEditor</key> + <map> + <key>Comment</key> + <string>Path to program used to edit XUI files</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>String</string> + <key>Value</key> + <real>150000.0</real> + </map> <key>YawFromMousePosition</key> <map> <key>Comment</key> diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 22d54fe62771fb940153e8b9e31626051c65a525..c8240de0a7fc5481d0ddb9112c7e0c7de48c6e86 100644 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -2153,7 +2153,6 @@ void LLAgent::setBusy() { gBusyMenu->setLabel(LLTrans::getString("AvatarSetNotBusy")); } - LLFloaterReg::getTypedInstance<LLFloaterMute>("mute")->updateButtons(); } //----------------------------------------------------------------------------- @@ -2167,7 +2166,6 @@ void LLAgent::clearBusy() { gBusyMenu->setLabel(LLTrans::getString("AvatarSetBusy")); } - LLFloaterReg::getTypedInstance<LLFloaterMute>("mute")->updateButtons(); } //----------------------------------------------------------------------------- @@ -2490,7 +2488,7 @@ void LLAgent::autoPilot(F32 *delta_yaw) void LLAgent::propagate(const F32 dt) { // Update UI based on agent motion - LLFloaterMove *floater_move = LLFloaterMove::getInstance(); + LLFloaterMove *floater_move = LLFloaterReg::getTypedInstance<LLFloaterMove>("moveview"); if (floater_move) { floater_move->mForwardButton ->setToggleState( mAtKey > 0 || mWalkKey > 0 ); @@ -3056,21 +3054,25 @@ void LLAgent::updateCamera() } // Update UI with our camera inputs - LLFloaterCamera::getInstance()->mRotate->setToggleState( - mOrbitRightKey > 0.f, // left - mOrbitUpKey > 0.f, // top - mOrbitLeftKey > 0.f, // right - mOrbitDownKey > 0.f); // bottom - - LLFloaterCamera::getInstance()->mZoom->setToggleState( - mOrbitInKey > 0.f, // top - mOrbitOutKey > 0.f); // bottom - - LLFloaterCamera::getInstance()->mTrack->setToggleState( - mPanLeftKey > 0.f, // left - mPanUpKey > 0.f, // top - mPanRightKey > 0.f, // right - mPanDownKey > 0.f); // bottom + LLFloaterCamera* camera_instance = LLFloaterReg::getTypedInstance<LLFloaterCamera>("camera"); + if(camera_instance) + { + camera_instance->mRotate->setToggleState( + mOrbitRightKey > 0.f, // left + mOrbitUpKey > 0.f, // top + mOrbitLeftKey > 0.f, // right + mOrbitDownKey > 0.f); // bottom + + camera_instance->mZoom->setToggleState( + mOrbitInKey > 0.f, // top + mOrbitOutKey > 0.f); // bottom + + camera_instance->mTrack->setToggleState( + mPanLeftKey > 0.f, // left + mPanUpKey > 0.f, // top + mPanRightKey > 0.f, // right + mPanDownKey > 0.f); // bottom + } // Handle camera movement based on keyboard. const F32 ORBIT_OVER_RATE = 90.f * DEG_TO_RAD; // radians per second @@ -6074,7 +6076,7 @@ bool LLAgent::teleportCore(bool is_local) LLFloaterReg::hideInstance("search"); // hide land floater too - it'll be out of date - LLFloaterLand::hideInstance(); + LLFloaterReg::hideInstance("about_land"); LLViewerParcelMgr::getInstance()->deselectLand(); diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h index 743784b2ef88954b6c09f6939912028c5c18720b..22b3790c6be7ddc039c98d5ac73ba0e75e3505fd 100644 --- a/indra/newview/llagent.h +++ b/indra/newview/llagent.h @@ -182,10 +182,7 @@ private: public: LLVOAvatarSelf* getAvatarObject() const { return mAvatarObject; } - const LLUUID& getInventoryRootID() const { return mInventoryRootID; } - LLUUID& getInventoryRootID() { return mInventoryRootID; } private: - LLUUID mInventoryRootID; LLPointer<LLVOAvatarSelf> mAvatarObject; // NULL until avatar object sent down from simulator /** General Accessors diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp index 1da54ad08c5b18f6dcce1d7a6a707391e8ce21b6..f053bfe118501d9aba17de796716c5dd81f8e094 100644 --- a/indra/newview/llagentwearables.cpp +++ b/indra/newview/llagentwearables.cpp @@ -36,7 +36,7 @@ #include "llagentwearables.h" #include "llfloatercustomize.h" -#include "llinventoryview.h" +#include "llfloaterinventory.h" #include "llinventorymodel.h" #include "llnotify.h" #include "llviewerregion.h" @@ -1076,7 +1076,7 @@ void LLAgentWearables::makeNewOutfitDone(S32 type, U32 index) // Open the inventory and select the first item we added. if (first_item_id.notNull()) { - LLInventoryView* view = LLInventoryView::getActiveInventory(); + LLFloaterInventory* view = LLFloaterInventory::getActiveInventory(); if (view) { view->getPanel()->setSelection(first_item_id, TAKE_FOCUS_NO); diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 0253d9e8d56951213e826532267f0424d600ef65..de3cf1a81b8a6352385373ed97f930c7da6212b5 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -152,8 +152,9 @@ #include "llviewerfloaterreg.h" #include "llcommandlineparser.h" #include "llfloatermemleak.h" +#include "llfloaterreg.h" #include "llfloatersnapshot.h" -#include "llinventoryview.h" +#include "llfloaterinventory.h" // includes for idle() idleShutdown() #include "llviewercontrol.h" @@ -235,9 +236,6 @@ LLTimer gLogoutTimer; static const F32 LOGOUT_REQUEST_TIME = 6.f; // this will be cut short by the LogoutReply msg. F32 gLogoutMaxTime = LOGOUT_REQUEST_TIME; -LLUUID gInventoryLibraryOwner; -LLUUID gInventoryLibraryRoot; - BOOL gDisconnected = FALSE; // Map scale in pixels per region @@ -930,9 +928,10 @@ bool LLAppViewer::mainLoop() #endif //memory leaking simulation - if(LLFloaterMemLeak::getInstance()) + LLFloaterMemLeak* mem_leak_instance = LLFloaterReg::getTypedInstance<LLFloaterMemLeak>("mem_leaking"); + if(mem_leak_instance) { - LLFloaterMemLeak::getInstance()->idle() ; + mem_leak_instance->idle() ; } // canonical per-frame event @@ -1099,9 +1098,10 @@ bool LLAppViewer::mainLoop() catch(std::bad_alloc) { //stop memory leaking simulation - if(LLFloaterMemLeak::getInstance()) + LLFloaterMemLeak* mem_leak_instance = LLFloaterReg::getTypedInstance<LLFloaterMemLeak>("mem_leaking"); + if(mem_leak_instance) { - LLFloaterMemLeak::getInstance()->stop() ; + mem_leak_instance->stop() ; llwarns << "Bad memory allocation in LLAppViewer::mainLoop()!" << llendl ; } else @@ -1126,9 +1126,10 @@ bool LLAppViewer::mainLoop() llwarns << "Bad memory allocation when saveFinalSnapshot() is called!" << llendl ; //stop memory leaking simulation - if(LLFloaterMemLeak::getInstance()) + LLFloaterMemLeak* mem_leak_instance = LLFloaterReg::getTypedInstance<LLFloaterMemLeak>("mem_leaking"); + if(mem_leak_instance) { - LLFloaterMemLeak::getInstance()->stop() ; + mem_leak_instance->stop() ; } } } @@ -3864,20 +3865,20 @@ void LLAppViewer::disconnectViewer() LLSelectMgr::getInstance()->deselectAll(); } - if (!gNoRender) + // save inventory if appropriate + gInventory.cache(gInventory.getRootFolderID(), gAgent.getID()); + if (gInventory.getLibraryRootFolderID().notNull() + && gInventory.getLibraryOwnerID().notNull()) { - // save inventory if appropriate - gInventory.cache(gAgent.getInventoryRootID(), gAgent.getID()); - if(gInventoryLibraryRoot.notNull() && gInventoryLibraryOwner.notNull()) - { - gInventory.cache(gInventoryLibraryRoot, gInventoryLibraryOwner); - } + gInventory.cache( + gInventory.getLibraryRootFolderID(), + gInventory.getLibraryOwnerID()); } saveNameCache(); // close inventory interface, close all windows - LLInventoryView::cleanup(); + LLFloaterInventory::cleanup(); gAgentWearables.cleanup(); diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h index 3e3b52316935e07f6638aa688f92ccb1bf7be38c..7bda16d256bf3181f6edb2e11353467028d58352 100644 --- a/indra/newview/llappviewer.h +++ b/indra/newview/llappviewer.h @@ -313,9 +313,6 @@ extern LLTimer gLogoutTimer; extern F32 gSimLastTime; extern F32 gSimFrames; -extern LLUUID gInventoryLibraryOwner; -extern LLUUID gInventoryLibraryRoot; - extern BOOL gDisconnected; // Map scale in pixels per region diff --git a/indra/newview/llassetuploadresponders.cpp b/indra/newview/llassetuploadresponders.cpp index 1379073bba69b48467848be53b3648bce8834971..802c90f531cf1c37221d96f251763c2df4817d36 100644 --- a/indra/newview/llassetuploadresponders.cpp +++ b/indra/newview/llassetuploadresponders.cpp @@ -41,7 +41,7 @@ #include "llfilepicker.h" #include "llnotify.h" #include "llinventorymodel.h" -#include "llinventoryview.h" +#include "llfloaterinventory.h" #include "llpermissionsflags.h" #include "llpreviewnotecard.h" #include "llpreviewscript.h" @@ -285,7 +285,7 @@ void LLNewAgentInventoryResponder::uploadComplete(const LLSD& content) // Show the preview panel for textures and sounds to let // user know that the image (or snapshot) arrived intact. - LLInventoryView* view = LLInventoryView::getActiveInventory(); + LLFloaterInventory* view = LLFloaterInventory::getActiveInventory(); if(view) { LLUICtrl* focus_ctrl = gFocusMgr.getKeyboardFocus(); @@ -295,7 +295,7 @@ void LLNewAgentInventoryResponder::uploadComplete(const LLSD& content) { view->getPanel()->openSelected(); } - //LLInventoryView::dumpSelectionInformation((void*)view); + //LLFloaterInventory::dumpSelectionInformation((void*)view); // restore keyboard focus gFocusMgr.setKeyboardFocus(focus_ctrl); } diff --git a/indra/newview/llavatariconctrl.cpp b/indra/newview/llavatariconctrl.cpp index 3cd612673928f886b48bf0d90f8d6c28a02fdef5..bf18abfdb3498776340a2e4fb609f4ecc16a8f5b 100644 --- a/indra/newview/llavatariconctrl.cpp +++ b/indra/newview/llavatariconctrl.cpp @@ -46,7 +46,7 @@ #define MENU_ITEM_VIEW_PROFILE 0 #define MENU_ITEM_SEND_IM 1 -static LLDefaultWidgetRegistry::Register<LLAvatarIconCtrl> r("avatar_icon"); +static LLDefaultChildRegistry::Register<LLAvatarIconCtrl> r("avatar_icon"); LLAvatarIconCtrl::LLAvatarIconCtrl(const LLAvatarIconCtrl::Params& p) : LLIconCtrl(p), @@ -106,7 +106,7 @@ LLAvatarIconCtrl::LLAvatarIconCtrl(const LLAvatarIconCtrl::Params& p) registrar.add("AvatarIcon.Action", boost::bind(&LLAvatarIconCtrl::onAvatarIconContextMenuItemClicked, this, _2)); - LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_avatar_icon.xml", gMenuHolder); + LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_avatar_icon.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); mPopupMenuHandle = menu->getHandle(); } diff --git a/indra/newview/llavatarlist.cpp b/indra/newview/llavatarlist.cpp index 449bcc4f0b949589c43d4f9873e7f5124774e0c8..7b5ce765d3b052e43c2b61e26d4e01297128bfc0 100644 --- a/indra/newview/llavatarlist.cpp +++ b/indra/newview/llavatarlist.cpp @@ -38,7 +38,7 @@ #include "llcallingcard.h" // for LLAvatarTracker #include "llcachename.h" -static LLDefaultWidgetRegistry::Register<LLAvatarList> r("avatar_list"); +static LLDefaultChildRegistry::Register<LLAvatarList> r("avatar_list"); LLAvatarList::Params::Params() { diff --git a/indra/newview/llbreadcrumbview.cpp b/indra/newview/llbreadcrumbview.cpp new file mode 100644 index 0000000000000000000000000000000000000000..342994ee3060f0d24f897fc00eb45accce10d2f7 --- /dev/null +++ b/indra/newview/llbreadcrumbview.cpp @@ -0,0 +1,37 @@ +/** + * @file llbreadcrumbview.cpp + * @brief UI widget for displaying position in a folder hierarchy and allowing + * the user to click on a location in the hierarchy. + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ +#include "llviewerprecompiledheaders.h" + +#include "llbreadcrumbview.h" + +// TODO diff --git a/indra/newview/llbreadcrumbview.h b/indra/newview/llbreadcrumbview.h new file mode 100644 index 0000000000000000000000000000000000000000..ca6fbe7fb2c7099e574fff3fe5c74a6fe5195489 --- /dev/null +++ b/indra/newview/llbreadcrumbview.h @@ -0,0 +1,36 @@ +/** + * @file llbreadcrumbview.h + * @brief UI widget for displaying position in a folder hierarchy and allowing + * the user to click on a location in the hierarchy. + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ +#ifndef LLBREADCRUMBVIEW_H +#define LLBREADCRUMBVIEW_H + +#endif // LLBREADCRUMBVIEW_H diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp index a97e56d60b48da57a1023fe6d1945dbc4ec30954..29845fff5e565e4648a28170690dd90b69e94a58 100644 --- a/indra/newview/llchiclet.cpp +++ b/indra/newview/llchiclet.cpp @@ -41,6 +41,7 @@ #include "lloutputmonitorctrl.h" #include "llimview.h" #include "llbottomtray.h" +#include "llimpanel.h" static const S32 CHICLET_HEIGHT = 25; static const S32 CHICLET_SPACING = 0; @@ -52,10 +53,10 @@ static const S32 SCROLL_BUTTON_WIDTH = 19; static const S32 SCROLL_BUTTON_HEIGHT = 20; static const S32 NOTIFICATION_TEXT_TOP_PAD = 5; -static LLDefaultWidgetRegistry::Register<LLChicletPanel> t1("chiclet_panel"); -static LLDefaultWidgetRegistry::Register<LLTalkButton> t2("chiclet_talk"); -static LLDefaultWidgetRegistry::Register<LLNotificationChiclet> t3("chiclet_notification"); -static LLDefaultWidgetRegistry::Register<LLChicletPanel> t4("chiclet_panel"); +static LLDefaultChildRegistry::Register<LLChicletPanel> t1("chiclet_panel"); +static LLDefaultChildRegistry::Register<LLTalkButton> t2("chiclet_talk"); +static LLDefaultChildRegistry::Register<LLNotificationChiclet> t3("chiclet_notification"); +static LLDefaultChildRegistry::Register<LLChicletPanel> t4("chiclet_panel"); ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// @@ -317,6 +318,29 @@ LLChicletPanel::~LLChicletPanel() } +void im_chiclet_callback(LLChicletPanel* panel, const LLSD& data){ + + LLChiclet* chiclet = panel->findIMChiclet(&data["session_id"]); + + if (chiclet) + { + chiclet->setCounter(data["num_unread"].asInteger()); + } + else + { + llwarns << "Unable to set counter for chiclet " << data["session_id"].asUUID() << llendl; + } +} + + +BOOL LLChicletPanel::postBuild() +{ + LLPanel::postBuild(); + LLIMModel::instance().addChangedCallback(boost::bind(im_chiclet_callback, this, _1)); + + return TRUE; +} + LLChiclet* LLChicletPanel::createChiclet(LLSD* imSessionId, S32 pos) { LLChiclet* chiclet = LLIMChiclet::create(imSessionId); @@ -366,11 +390,18 @@ void LLChicletPanel::onChicletClick(LLUICtrl*ctrl,const LLSD¶m) { LLFloaterReg::showInstance("communicate", chiclet->getIMSessionId().asUUID()); } + + S32 x, y; + LLRect rect = chiclet->getRect(); + + localPointToScreen(rect.getCenterX(), 0, &x, &y); + LLIMFloater::show(chiclet->getIMSessionId().asUUID(), x); mCommitSignal(ctrl,param); } -LLChiclet* LLChicletPanel::findIMChiclet(LLSD* imSessionId) + +LLChiclet* LLChicletPanel::findIMChiclet(const LLSD* imSessionId) { chiclet_list_t::const_iterator it = mChicletList.begin(); for( ; mChicletList.end() != it; ++it) @@ -441,7 +472,7 @@ void LLChicletPanel::removeChiclet(LLChiclet*chiclet) } } -void LLChicletPanel::removeIMChiclet(LLSD* imSessionId) +void LLChicletPanel::removeIMChiclet(const LLSD* imSessionId) { chiclet_list_t::iterator it = mChicletList.begin(); for( ; mChicletList.end() != it; ++it) diff --git a/indra/newview/llchiclet.h b/indra/newview/llchiclet.h index 65be9e183a4503042ecf838ff6eb19a6abc1ce76..d861a528b51df1e74d2dd898d121a7b316acd157 100644 --- a/indra/newview/llchiclet.h +++ b/indra/newview/llchiclet.h @@ -188,7 +188,7 @@ public: LLChiclet* getChiclet(S32 pos); - LLChiclet* findIMChiclet(LLSD* imSessionId); + LLChiclet* findIMChiclet(const LLSD* imSessionId); S32 getChicletCount() {return mChicletList.size();}; @@ -196,7 +196,7 @@ public: void removeChiclet(LLChiclet*); - void removeIMChiclet(LLSD* imSessionId); + void removeIMChiclet(const LLSD* imSessionId); void removeAll(); @@ -215,6 +215,7 @@ public: //overrides public: + /*virtual*/ BOOL postBuild(); void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE ); diff --git a/indra/newview/llcolorswatch.cpp b/indra/newview/llcolorswatch.cpp index 33aaac542bd58b9b6f1a278add85cf0b606965de..531e6d709a838916290ac9efa294489a1a56f5ec 100644 --- a/indra/newview/llcolorswatch.cpp +++ b/indra/newview/llcolorswatch.cpp @@ -51,7 +51,7 @@ #include "llviewerimagelist.h" #include "llfocusmgr.h" -static LLDefaultWidgetRegistry::Register<LLColorSwatchCtrl> r("color_swatch"); +static LLDefaultChildRegistry::Register<LLColorSwatchCtrl> r("color_swatch"); LLColorSwatchCtrl::Params::Params() : color("color", LLColor4::white), diff --git a/indra/newview/llcolorswatch.h b/indra/newview/llcolorswatch.h index a05926c2f5c8cf1ed9fb086be48fbe362d83cc9b..db771df6b3fac7ab748350fa6d2281a294167a82 100644 --- a/indra/newview/llcolorswatch.h +++ b/indra/newview/llcolorswatch.h @@ -60,13 +60,13 @@ public: struct Params : public LLInitParam::Block<Params, LLUICtrl::Params> { - Optional<LLColor4> color; - Optional<bool> can_apply_immediately; - Optional<LLUIImage*> alpha_background_image; - Optional<commit_callback_t> cancel_callback; - Optional<commit_callback_t> select_callback; - Optional<LLUIColor> border_color; - Optional<S32> label_width; + Optional<LLColor4> color; + Optional<bool> can_apply_immediately; + Optional<LLUIImage*> alpha_background_image; + Optional<commit_callback_t> cancel_callback; + Optional<commit_callback_t> select_callback; + Optional<LLUIColor> border_color; + Optional<S32> label_width; Optional<LLTextBox::Params> caption_text; Optional<LLViewBorder::Params> border; diff --git a/indra/newview/lleventnotifier.cpp b/indra/newview/lleventnotifier.cpp index c0fe327815af91f3e676150f5fb316bf4179bf5c..2c52cf9565e5341163788cbf8d34345ddfa62606 100644 --- a/indra/newview/lleventnotifier.cpp +++ b/indra/newview/lleventnotifier.cpp @@ -192,9 +192,12 @@ bool LLEventNotification::handleResponse(const LLSD& notification, const LLSD& r switch (option) { case 0: - gAgent.teleportViaLocation(getEventPosGlobal()); - LLFloaterWorldMap::getInstance()->trackLocation(getEventPosGlobal()); - break; + { + gAgent.teleportViaLocation(getEventPosGlobal()); + LLFloaterWorldMap* floater_world_map = LLFloaterWorldMap::getInstance(); + if(floater_world_map) floater_world_map->trackLocation(getEventPosGlobal()); + break; + } case 1: gDisplayEventHack = TRUE; LLFloaterReg::showInstance("search", LLSD().insert("panel", "event").insert("id", S32(getEventID()))); diff --git a/indra/newview/llfavoritesbar.cpp b/indra/newview/llfavoritesbar.cpp index f43b625d17de053c365efad71d63b88631a7a5e1..92e2d3563a893a773670cd23fcee164fd864fb11 100644 --- a/indra/newview/llfavoritesbar.cpp +++ b/indra/newview/llfavoritesbar.cpp @@ -47,7 +47,7 @@ #include "llviewermenu.h" #include "llviewermenu.h" -static LLDefaultWidgetRegistry::Register<LLFavoritesBarCtrl> r("favorites_bar"); +static LLDefaultChildRegistry::Register<LLFavoritesBarCtrl> r("favorites_bar"); // updateButtons's helper struct LLFavoritesSort @@ -213,7 +213,7 @@ void LLFavoritesBarCtrl::updateButtons(U32 bar_width) const S32 buttonHPad = LLUI::sSettingGroups["config"]->getS32("ButtonHPad"); const S32 buttonHGap = 2; const S32 buttonVGap = 2; - static LLButton::Params default_button_params(LLUICtrlFactory::getDefaultParams<LLButton::Params>()); + static LLButton::Params default_button_params(LLUICtrlFactory::getDefaultParams<LLButton>()); std::string flat_icon = "transparent.j2c"; std::string hover_icon = default_button_params.image_unselected.name; std::string hover_icon_selected = default_button_params.image_selected.name; @@ -364,7 +364,7 @@ void LLFavoritesBarCtrl::updateButtons(U32 bar_width) BOOL LLFavoritesBarCtrl::postBuild() { // make the popup menu available - LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_favorites.xml", gMenuHolder); + LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_favorites.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); if (!menu) { menu = LLUICtrlFactory::getDefaultWidget<LLMenuGL>("inventory_menu"); diff --git a/indra/newview/llfloaterabout.cpp b/indra/newview/llfloaterabout.cpp index bdd34dfca8e4a8f22b0582d649cb846c69dfcbf0..7332ca4b5c77f3806f3af0b98b2d17c883ce2655 100644 --- a/indra/newview/llfloaterabout.cpp +++ b/indra/newview/llfloaterabout.cpp @@ -78,7 +78,7 @@ static std::string get_viewer_release_notes_url(); // Default constructor LLFloaterAbout::LLFloaterAbout(const LLSD& key) -: LLFloater() +: LLFloater(key) { //LLUICtrlFactory::getInstance()->buildFloater(this, "floater_about.xml"); diff --git a/indra/newview/llfloaterabout.h b/indra/newview/llfloaterabout.h index 1b0f3cddd3479b607e9c79f18e8ab9c26bf5bce0..c15a20d54987ea2ab262e9784414436012cb5118 100644 --- a/indra/newview/llfloaterabout.h +++ b/indra/newview/llfloaterabout.h @@ -36,12 +36,11 @@ #include "llfloater.h" class LLFloaterAbout - : public LLFloater, public LLFloaterSingleton<LLFloaterAbout> + : public LLFloater { - friend class LLUISingleton<LLFloaterAbout, VisibilityPolicy<LLFloater> >; -public: + friend class LLFloaterReg; +private: LLFloaterAbout(const LLSD& key); -protected: virtual ~LLFloaterAbout(); public: diff --git a/indra/newview/llfloaterauction.cpp b/indra/newview/llfloaterauction.cpp index 8ad5a19d02c2f1a9625c09778bd10e48edc89a72..f5d950a9a5f011258a855adc327b2f80f0dfa4a9 100644 --- a/indra/newview/llfloaterauction.cpp +++ b/indra/newview/llfloaterauction.cpp @@ -72,7 +72,7 @@ void auction_tga_upload_done(const LLUUID& asset_id, // Default constructor LLFloaterAuction::LLFloaterAuction(const LLSD& key) - : LLFloater(), + : LLFloater(key), mParcelID(-1) { // LLUICtrlFactory::getInstance()->buildFloater(this, "floater_auction.xml"); diff --git a/indra/newview/llfloaterauction.h b/indra/newview/llfloaterauction.h index b018316c64d5063f8795e3fc1214822e6c9ef408..ebb1a0d1aee0c47944ad4ff16442dc153e566587 100644 --- a/indra/newview/llfloaterauction.h +++ b/indra/newview/llfloaterauction.h @@ -46,18 +46,20 @@ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ class LLParcelSelection; -class LLFloaterAuction : public LLFloater, public LLFloaterSingleton<LLFloaterAuction> +class LLFloaterAuction : public LLFloater { - friend class LLUISingleton<LLFloaterAuction, VisibilityPolicy<LLFloater> >; + friend class LLFloaterReg; public: // LLFloater interface /*virtual*/ void onClose(bool app_quitting) { setVisible(FALSE); } /*virtual*/ void onOpen(const LLSD& key); /*virtual*/ void draw(); + +private: LLFloaterAuction(const LLSD& key); ~LLFloaterAuction(); -private: + void initialize(); static void onClickSnapshot(void* data); diff --git a/indra/newview/llfloateravatarpicker.cpp b/indra/newview/llfloateravatarpicker.cpp index 2c2dcda633648671d282337a92a8f53ba3e90dfe..92ce44fa42de7c3ea34d6e188fe38e7abf1856ba 100644 --- a/indra/newview/llfloateravatarpicker.cpp +++ b/indra/newview/llfloateravatarpicker.cpp @@ -33,22 +33,25 @@ #include "llfloateravatarpicker.h" -#include "message.h" - +// Viewer includes #include "llagent.h" -#include "llbutton.h" #include "llfocusmgr.h" -#include "llinventoryview.h" +#include "llfloaterinventory.h" +#include "llfoldervieweventlistener.h" #include "llinventorymodel.h" +#include "llviewercontrol.h" +#include "llworld.h" + +// Linden libraries +#include "llbutton.h" #include "lllineeditor.h" #include "llscrolllistctrl.h" #include "llscrolllistitem.h" #include "llscrolllistcell.h" +#include "lltabcontainer.h" #include "lltextbox.h" #include "lluictrlfactory.h" -#include "llviewercontrol.h" -#include "llworld.h" -#include "lltabcontainer.h" +#include "message.h" // static LLFloaterAvatarPicker* LLFloaterAvatarPicker::sInstance = NULL; diff --git a/indra/newview/llfloateravatarpicker.h b/indra/newview/llfloateravatarpicker.h index 0f47401f23886a3d2847ccfe9d52f47dc6b3cfac..0f28d8250b45342547e55027cb60b078d6cd6ea4 100644 --- a/indra/newview/llfloateravatarpicker.h +++ b/indra/newview/llfloateravatarpicker.h @@ -87,6 +87,7 @@ private: static LLFloaterAvatarPicker* sInstance; +private: // do not call these directly LLFloaterAvatarPicker(); virtual ~LLFloaterAvatarPicker(); diff --git a/indra/newview/llfloaterbeacons.cpp b/indra/newview/llfloaterbeacons.cpp index 052f334285734e473f5b2adb171a6727c381983b..1c7ef77718eac78a85cdaa802a204455a4cd8e3a 100644 --- a/indra/newview/llfloaterbeacons.cpp +++ b/indra/newview/llfloaterbeacons.cpp @@ -40,9 +40,9 @@ LLFloaterBeacons::LLFloaterBeacons(const LLSD& seed) -: LLFloater() +: LLFloater(seed) { - LLUICtrlFactory::getInstance()->buildFloater(this, "floater_beacons.xml"); +// LLUICtrlFactory::getInstance()->buildFloater(this, "floater_beacons.xml"); // Initialize pipeline states from saved settings. // OK to do at floater constructor time because beacons do not display unless the floater is open @@ -56,17 +56,11 @@ LLFloaterBeacons::LLFloaterBeacons(const LLSD& seed) LLPipeline::setRenderParticleBeacons( gSavedSettings.getBOOL("particlesbeacon")); LLPipeline::setRenderHighlights( gSavedSettings.getBOOL("renderhighlights")); LLPipeline::setRenderBeacons( gSavedSettings.getBOOL("renderbeacons")); + mCommitCallbackRegistrar.add("Beacons.UICheck", boost::bind(&LLFloaterBeacons::onClickUICheck, this,_1)); } BOOL LLFloaterBeacons::postBuild() { - childSetCommitCallback("touch_only", onClickUICheck, this); - childSetCommitCallback("scripted", onClickUICheck, this); - childSetCommitCallback("physical", onClickUICheck, this); - childSetCommitCallback("sounds", onClickUICheck, this); - childSetCommitCallback("particles", onClickUICheck, this); - childSetCommitCallback("highlights", onClickUICheck, this); - childSetCommitCallback("beacons", onClickUICheck, this); return TRUE; } @@ -87,12 +81,11 @@ void LLFloaterBeacons::onClose(bool app_quitting) // Callback attached to each check box control to both affect their main purpose // and to implement the couple screwy interdependency rules that some have. -//static -void LLFloaterBeacons::onClickUICheck(LLUICtrl *ctrl, void* data) + +void LLFloaterBeacons::onClickUICheck(LLUICtrl *ctrl) { LLCheckBoxCtrl *check = (LLCheckBoxCtrl *)ctrl; std::string name = check->getName(); - LLFloaterBeacons* view = (LLFloaterBeacons*)data; if( name == "touch_only") { LLPipeline::toggleRenderScriptedTouchBeacons(NULL); @@ -102,8 +95,8 @@ void LLFloaterBeacons::onClickUICheck(LLUICtrl *ctrl, void* data) LLPipeline::getRenderScriptedBeacons(NULL) ) { LLPipeline::setRenderScriptedBeacons(FALSE); - view->getChild<LLCheckBoxCtrl>("scripted")->setControlValue(LLSD(FALSE)); - view->getChild<LLCheckBoxCtrl>("touch_only")->setControlValue(LLSD(TRUE)); // just to be sure it's in sync with llpipeline + getChild<LLCheckBoxCtrl>("scripted")->setControlValue(LLSD(FALSE)); + getChild<LLCheckBoxCtrl>("touch_only")->setControlValue(LLSD(TRUE)); // just to be sure it's in sync with llpipeline } } else if(name == "scripted") @@ -115,8 +108,8 @@ void LLFloaterBeacons::onClickUICheck(LLUICtrl *ctrl, void* data) LLPipeline::getRenderScriptedBeacons(NULL) ) { LLPipeline::setRenderScriptedTouchBeacons(FALSE); - view->getChild<LLCheckBoxCtrl>("touch_only")->setControlValue(LLSD(FALSE)); - view->getChild<LLCheckBoxCtrl>("scripted")->setControlValue(LLSD(TRUE)); // just to be sure it's in sync with llpipeline + getChild<LLCheckBoxCtrl>("touch_only")->setControlValue(LLSD(FALSE)); + getChild<LLCheckBoxCtrl>("scripted")->setControlValue(LLSD(TRUE)); // just to be sure it's in sync with llpipeline } } else if(name == "physical") LLPipeline::setRenderPhysicalBeacons(check->get()); @@ -131,8 +124,8 @@ void LLFloaterBeacons::onClickUICheck(LLUICtrl *ctrl, void* data) !LLPipeline::getRenderHighlights(NULL) ) { LLPipeline::setRenderBeacons(TRUE); - view->getChild<LLCheckBoxCtrl>("beacons")->setControlValue(LLSD(TRUE)); - view->getChild<LLCheckBoxCtrl>("highlights")->setControlValue(LLSD(FALSE)); // just to be sure it's in sync with llpipeline + getChild<LLCheckBoxCtrl>("beacons")->setControlValue(LLSD(TRUE)); + getChild<LLCheckBoxCtrl>("highlights")->setControlValue(LLSD(FALSE)); // just to be sure it's in sync with llpipeline } } else if(name == "beacons") @@ -144,8 +137,8 @@ void LLFloaterBeacons::onClickUICheck(LLUICtrl *ctrl, void* data) !LLPipeline::getRenderHighlights(NULL) ) { LLPipeline::setRenderHighlights(TRUE); - view->getChild<LLCheckBoxCtrl>("highlights")->setControlValue(LLSD(TRUE)); - view->getChild<LLCheckBoxCtrl>("beacons")->setControlValue(LLSD(FALSE)); // just to be sure it's in sync with llpipeline + getChild<LLCheckBoxCtrl>("highlights")->setControlValue(LLSD(TRUE)); + getChild<LLCheckBoxCtrl>("beacons")->setControlValue(LLSD(FALSE)); // just to be sure it's in sync with llpipeline } } } diff --git a/indra/newview/llfloaterbeacons.h b/indra/newview/llfloaterbeacons.h index 8156e82ac38be2c8d0d79d3d5dbb43385be5b1f2..94f853978a7bd91cbdfecc836c9a179c9eb44357 100644 --- a/indra/newview/llfloaterbeacons.h +++ b/indra/newview/llfloaterbeacons.h @@ -36,22 +36,22 @@ #include "llfloater.h" -class LLFloaterBeacons : public LLFloater, public LLFloaterSingleton<LLFloaterBeacons> +class LLFloaterBeacons : public LLFloater { - friend class LLUISingleton<LLFloaterBeacons, VisibilityPolicy<LLFloater> >; + friend class LLFloaterReg; public: + /*virtual*/ BOOL postBuild(); // Needed to make the floater visibility toggle the beacons. // Too bad we can't just add control_name="BeaconAlwaysOn" to the XML. /*virtual*/ void onOpen(const LLSD& key); /*virtual*/ void onClose(bool app_quitting); + void onClickUICheck(LLUICtrl *ctrl); private: LLFloaterBeacons(const LLSD& seed); - - static void onClickUICheck(LLUICtrl *ctrl, void* data); }; #endif diff --git a/indra/newview/llfloaterbuildoptions.cpp b/indra/newview/llfloaterbuildoptions.cpp index 9dbd1db38e9a1f2e7c7a3f803adfedbc7446a9c5..30e9428df9fd4d8cd2f449465ca030b53548fdec 100644 --- a/indra/newview/llfloaterbuildoptions.cpp +++ b/indra/newview/llfloaterbuildoptions.cpp @@ -44,7 +44,7 @@ // Methods // LLFloaterBuildOptions::LLFloaterBuildOptions(const LLSD& key) - : LLFloater() + : LLFloater(key) { //LLUICtrlFactory::getInstance()->buildFloater(this, "floater_build_options.xml"); } diff --git a/indra/newview/llfloaterbuildoptions.h b/indra/newview/llfloaterbuildoptions.h index 61db303ba2303f645d215a348da1f904dfdf92a8..43cbb201c2c6e107daa45244db13ba7a517be729 100644 --- a/indra/newview/llfloaterbuildoptions.h +++ b/indra/newview/llfloaterbuildoptions.h @@ -42,10 +42,10 @@ class LLFloaterBuildOptions - : public LLFloater, public LLFloaterSingleton<LLFloaterBuildOptions> + : public LLFloater { - friend class LLUISingleton<LLFloaterBuildOptions, VisibilityPolicy<LLFloater> >; -public: + friend class LLFloaterReg; +private: LLFloaterBuildOptions(const LLSD& key); ~LLFloaterBuildOptions(); }; diff --git a/indra/newview/llfloaterbulkpermission.cpp b/indra/newview/llfloaterbulkpermission.cpp index 65dc3cd9f0552362571931378585a056953f1080..efaebe311a925006afae0a1e6bf56fa3f9d00e93 100644 --- a/indra/newview/llfloaterbulkpermission.cpp +++ b/indra/newview/llfloaterbulkpermission.cpp @@ -58,22 +58,22 @@ LLFloaterBulkPermission::LLFloaterBulkPermission(const LLSD& seed) -: LLFloater(), +: LLFloater(seed), mDone(FALSE) { mID.generate(); - LLUICtrlFactory::getInstance()->buildFloater(this,"floater_bulk_perms.xml"); +// LLUICtrlFactory::getInstance()->buildFloater(this,"floater_bulk_perms.xml"); + mCommitCallbackRegistrar.add("BulkPermission.Apply", boost::bind(&LLFloaterBulkPermission::onApplyBtn, this)); + mCommitCallbackRegistrar.add("BulkPermission.Close", boost::bind(&LLFloaterBulkPermission::onCloseBtn, this)); + mCommitCallbackRegistrar.add("BulkPermission.CheckAll", boost::bind(&LLFloaterBulkPermission::onCheckAll, this)); + mCommitCallbackRegistrar.add("BulkPermission.UncheckAll", boost::bind(&LLFloaterBulkPermission::onUncheckAll, this)); + mCommitCallbackRegistrar.add("BulkPermission.CommitCopy", boost::bind(&LLFloaterBulkPermission::onCommitCopy, this)); } BOOL LLFloaterBulkPermission::postBuild() { - childSetEnabled("next_owner_transfer", gSavedSettings.getBOOL("BulkChangeNextOwnerCopy")); - childSetAction("help", onHelpBtn, this); - childSetAction("apply", onApplyBtn, this); - childSetAction("close", onCloseBtn, this); - childSetAction("check_all", onCheckAll, this); - childSetAction("check_none", onUncheckAll, this); - childSetCommitCallback("next_owner_copy", &onCommitCopy, this); +// childSetAction("help", onHelpBtn, this); // this is not in use + return TRUE; } @@ -152,34 +152,32 @@ void LLFloaterBulkPermission::inventoryChanged(LLViewerObject* viewer_object, } } -void LLFloaterBulkPermission::onApplyBtn(void* user_data) +void LLFloaterBulkPermission::onApplyBtn() { - LLFloaterBulkPermission* self = static_cast<LLFloaterBulkPermission*>(user_data); - self->doApply(); + doApply(); } -void LLFloaterBulkPermission::onHelpBtn(void* user_data) -{ - LLNotifications::instance().add("HelpBulkPermission"); -} +// angela -- this is not in use +//void LLFloaterBulkPermission::onHelpBtn(void* user_data) +//{ +// LLNotifications::instance().add("HelpBulkPermission"); +//} -void LLFloaterBulkPermission::onCloseBtn(void* user_data) +void LLFloaterBulkPermission::onCloseBtn() { - LLFloaterBulkPermission* self = static_cast<LLFloaterBulkPermission*>(user_data); - self->onClose(false); + onClose(false); } //static -void LLFloaterBulkPermission::onCommitCopy(LLUICtrl* ctrl, void* data) +void LLFloaterBulkPermission::onCommitCopy() { - LLFloaterBulkPermission* self = static_cast<LLFloaterBulkPermission*>(data); // Implements fair use BOOL copyable = gSavedSettings.getBOOL("BulkChangeNextOwnerCopy"); if(!copyable) { gSavedSettings.setBOOL("BulkChangeNextOwnerTransfer", TRUE); } - LLCheckBoxCtrl* xfer = self->getChild<LLCheckBoxCtrl>("next_owner_transfer"); + LLCheckBoxCtrl* xfer =getChild<LLCheckBoxCtrl>("next_owner_transfer"); xfer->setEnabled(copyable); } diff --git a/indra/newview/llfloaterbulkpermission.h b/indra/newview/llfloaterbulkpermission.h index 2ea12fbe69ed0b9f6bd9d0f3dc7f42e1755a7c0c..c34e4413ccc94ed412f871be3de21f58b615af0c 100644 --- a/indra/newview/llfloaterbulkpermission.h +++ b/indra/newview/llfloaterbulkpermission.h @@ -46,14 +46,16 @@ #include "llviewerinventory.h" -class LLFloaterBulkPermission : public LLFloater, public LLVOInventoryListener, public LLFloaterSingleton<LLFloaterBulkPermission> +class LLFloaterBulkPermission : public LLFloater, public LLVOInventoryListener { + friend class LLFloaterReg; public: - LLFloaterBulkPermission(const LLSD& seed); BOOL postBuild(); private: + + LLFloaterBulkPermission(const LLSD& seed); virtual ~LLFloaterBulkPermission() {} BOOL start(); // returns TRUE if the queue has started, otherwise FALSE. @@ -77,12 +79,12 @@ private: U8 key, bool is_new); - static void onHelpBtn(void* user_data); - static void onCloseBtn(void* user_data); - static void onApplyBtn(void* user_data); - static void onCommitCopy(LLUICtrl* ctrl, void* data); - static void onCheckAll( void* user_data) { ((LLFloaterBulkPermission*)user_data)->doCheckUncheckAll(TRUE); } - static void onUncheckAll(void* user_data) { ((LLFloaterBulkPermission*)user_data)->doCheckUncheckAll(FALSE); } +// static void onHelpBtn(void* user_data); + void onCloseBtn(); + void onApplyBtn(); + void onCommitCopy(); + void onCheckAll() { doCheckUncheckAll(TRUE); } + void onUncheckAll() { doCheckUncheckAll(FALSE); } // returns true if this is done BOOL isDone() const { return (mCurrentObjectID.isNull() || (mObjectIDs.count() == 0)); } diff --git a/indra/newview/llfloaterbump.cpp b/indra/newview/llfloaterbump.cpp index e4e1c7efa2ce9ab9b5ad6de69629c81c5dd42c59..8b64f913e02b58fc70e5a930cd78a4d4245bcaf9 100644 --- a/indra/newview/llfloaterbump.cpp +++ b/indra/newview/llfloaterbump.cpp @@ -45,11 +45,13 @@ ///---------------------------------------------------------------------------- /// Class LLFloaterBump ///---------------------------------------------------------------------------- +extern BOOL gNoRender; // Default constructor LLFloaterBump::LLFloaterBump(const LLSD& key) -: LLFloater() +: LLFloater(key) { + if(gNoRender) return; //LLUICtrlFactory::getInstance()->buildFloater(this, "floater_bumps.xml"); } diff --git a/indra/newview/llfloaterbump.h b/indra/newview/llfloaterbump.h index b56817436c8ba21ba6746e739d79beb3f7b6b47c..1f2cb6d6abbf1188370959c651bc82933e57720c 100644 --- a/indra/newview/llfloaterbump.h +++ b/indra/newview/llfloaterbump.h @@ -40,14 +40,17 @@ class LLMeanCollisionData; class LLScrollListCtrl; class LLFloaterBump -: public LLFloater, public LLFloaterSingleton<LLFloaterBump> +: public LLFloater { - friend class LLUISingleton<LLFloaterBump, VisibilityPolicy<LLFloater> >; + friend class LLFloaterReg; protected: void add(LLScrollListCtrl* list, LLMeanCollisionData *mcd); public: /*virtual*/ void onOpen(const LLSD& key); + +private: + LLFloaterBump(const LLSD& key); virtual ~LLFloaterBump(); }; diff --git a/indra/newview/llfloaterbuy.cpp b/indra/newview/llfloaterbuy.cpp index 9c523522fd0622781b8e61ff929fa15b65201bfe..aba2402b0c4572d574b603cdd545a899ae73c6a5 100644 --- a/indra/newview/llfloaterbuy.cpp +++ b/indra/newview/llfloaterbuy.cpp @@ -43,7 +43,7 @@ #include "llagent.h" // for agent id #include "llalertdialog.h" #include "llinventorymodel.h" // for gInventory -#include "llinventoryview.h" // for get_item_icon +#include "llfloaterinventory.h" // for get_item_icon #include "llselectmgr.h" #include "llscrolllistctrl.h" #include "llviewerobject.h" diff --git a/indra/newview/llfloaterbuycontents.cpp b/indra/newview/llfloaterbuycontents.cpp index 7a902752011bd80e095f50bbe4d4c4a34bdb9546..db4547e5bc275649683d36ab66d46705fa199e36 100644 --- a/indra/newview/llfloaterbuycontents.cpp +++ b/indra/newview/llfloaterbuycontents.cpp @@ -46,7 +46,7 @@ #include "llalertdialog.h" #include "llcheckboxctrl.h" #include "llinventorymodel.h" // for gInventory -#include "llinventoryview.h" // for get_item_icon +#include "llfloaterinventory.h" // for get_item_icon #include "llselectmgr.h" #include "llscrolllistctrl.h" #include "llviewerobject.h" @@ -287,7 +287,7 @@ void LLFloaterBuyContents::onClickBuy(void*) // We may want to wear this item if (sInstance->childGetValue("wear_check")) { - LLInventoryView::sWearNewClothing = TRUE; + LLFloaterInventory::sWearNewClothing = TRUE; } // Put the items where we put new folders. diff --git a/indra/newview/llfloatercamera.cpp b/indra/newview/llfloatercamera.cpp index e79142513ba9548abe904fe2af1ac039fc829ccc..1c99776c11a0273aa61feb55f1ab295fcaafd970 100644 --- a/indra/newview/llfloatercamera.cpp +++ b/indra/newview/llfloatercamera.cpp @@ -48,11 +48,11 @@ const F32 CAMERA_BUTTON_DELAY = 0.0f; // Member functions // LLFloaterCamera::LLFloaterCamera(const LLSD& val) -: LLFloater() +: LLFloater(val) { - // For now, only used for size and tooltip strings - const BOOL DONT_OPEN = FALSE; - LLUICtrlFactory::getInstance()->buildFloater(this, "floater_camera.xml", DONT_OPEN); + //// For now, only used for size and tooltip strings + //const BOOL DONT_OPEN = FALSE; + //LLUICtrlFactory::getInstance()->buildFloater(this, "floater_camera.xml", DONT_OPEN); } // virtual diff --git a/indra/newview/llfloatercamera.h b/indra/newview/llfloatercamera.h index f954e329eba751ce68c3588041d03a8ac278169b..daea9ecee178cc20fae751ce9ac34abe40a6fd3b 100644 --- a/indra/newview/llfloatercamera.h +++ b/indra/newview/llfloatercamera.h @@ -40,12 +40,12 @@ class LLJoystickCameraZoom; class LLJoystickCameraTrack; class LLFloaterCamera - : public LLFloater, - public LLFloaterSingleton<LLFloaterCamera> + : public LLFloater { - friend class LLUISingleton<LLFloaterCamera, VisibilityPolicy<LLFloater> >; + friend class LLFloaterReg; private: + LLFloaterCamera(const LLSD& val); ~LLFloaterCamera() {}; @@ -53,6 +53,7 @@ private: /*virtual*/ void onClose(bool app_quitting); /*virtual*/ BOOL postBuild(); public: + LLJoystickCameraRotate* mRotate; LLJoystickCameraZoom* mZoom; LLJoystickCameraTrack* mTrack; diff --git a/indra/newview/llfloaterchat.cpp b/indra/newview/llfloaterchat.cpp index 5250c798f9cf41b1fe13539e844d0e7a69af39a2..1bfb11e3aee4b28c06f7dbe94af2348a06322441 100644 --- a/indra/newview/llfloaterchat.cpp +++ b/indra/newview/llfloaterchat.cpp @@ -96,7 +96,7 @@ LLColor4 get_text_color(const LLChat& chat); // Member Functions // LLFloaterChat::LLFloaterChat(const LLSD& seed) - : LLFloater(), + : LLFloater(seed), mPanel(NULL) { mFactoryMap["chat_panel"] = LLCallbackMap(createChatPanel, NULL); @@ -558,6 +558,6 @@ void LLFloaterChat::onClickToggleActiveSpeakers(void* userdata) //static LLFloaterChat* LLFloaterChat::getInstance() { - LLFloater* inst = LLFloaterReg::getInstance("chat", LLSD()) ; - return dynamic_cast<LLFloaterChat*>(inst); + return LLFloaterReg::getTypedInstance<LLFloaterChat>("chat", LLSD()) ; + } diff --git a/indra/newview/llfloaterchatterbox.cpp b/indra/newview/llfloaterchatterbox.cpp index a283b445f50967b17b6d9ef997600c30e23a9aef..3389770b2fe9df71596e4f17bbf88aa8ed166b86 100644 --- a/indra/newview/llfloaterchatterbox.cpp +++ b/indra/newview/llfloaterchatterbox.cpp @@ -98,8 +98,7 @@ void* LLFloaterMyFriends::createGroupsPanel(void* data) //static LLFloaterMyFriends* LLFloaterMyFriends::getInstance() { - LLFloater* inst = LLFloaterReg::getInstance("contacts", "friends") ; - return dynamic_cast<LLFloaterMyFriends*>(inst); + return LLFloaterReg::getTypedInstance<LLFloaterMyFriends>("contacts", "friends") ; } // @@ -123,11 +122,14 @@ BOOL LLFloaterChatterBox::postBuild() if (gSavedSettings.getBOOL("ContactsTornOff")) { LLFloaterMyFriends* floater_contacts = LLFloaterMyFriends::getInstance(); - // add then remove to set up relationship for re-attach - addFloater(floater_contacts, FALSE); - removeFloater(floater_contacts); - // reparent to floater view - gFloaterView->addChild(floater_contacts); + if(floater_contacts) + { + // add then remove to set up relationship for re-attach + addFloater(floater_contacts, FALSE); + removeFloater(floater_contacts); + // reparent to floater view + gFloaterView->addChild(floater_contacts); + } } else { @@ -137,11 +139,14 @@ BOOL LLFloaterChatterBox::postBuild() if (gSavedSettings.getBOOL("ChatHistoryTornOff")) { LLFloaterChat* floater_chat = LLFloaterChat::getInstance(); - // add then remove to set up relationship for re-attach - addFloater(floater_chat, FALSE); - removeFloater(floater_chat); - // reparent to floater view - gFloaterView->addChild(floater_chat); + if(floater_chat) + { + // add then remove to set up relationship for re-attach + addFloater(floater_chat, FALSE); + removeFloater(floater_chat); + // reparent to floater view + gFloaterView->addChild(floater_chat); + } } else { @@ -249,11 +254,17 @@ void LLFloaterChatterBox::setMinimized(BOOL minimized) { LLFloater::setMinimized(minimized); // HACK: potentially need to toggle console - LLFloaterChat::getInstance()->updateConsoleVisibility(); + LLFloaterChat* instance = LLFloaterChat::getInstance(); + if(instance) + { + instance->updateConsoleVisibility(); + } } void LLFloaterChatterBox::removeFloater(LLFloater* floaterp) { + if(!floaterp) return; + if (floaterp->getName() == "chat floater") { // only my friends floater now locked @@ -275,6 +286,8 @@ void LLFloaterChatterBox::addFloater(LLFloater* floaterp, BOOL select_added_floater, LLTabContainer::eInsertionPoint insertion_point) { + if(!floaterp) return; + S32 num_locked_tabs = mTabContainer->getNumLockedTabs(); // already here @@ -332,8 +345,7 @@ void LLFloaterChatterBox::addFloater(LLFloater* floaterp, //static LLFloaterChatterBox* LLFloaterChatterBox::getInstance() { - LLFloater* inst = LLFloaterReg::getInstance("communicate", LLSD()) ; - return dynamic_cast<LLFloaterChatterBox*>(inst); + return LLFloaterReg::getTypedInstance<LLFloaterChatterBox>("communicate", LLSD()) ; } //static @@ -351,6 +363,7 @@ LLFloater* LLFloaterChatterBox::getCurrentVoiceFloater() else { LLFloaterChatterBox* floater = LLFloaterChatterBox::getInstance(); + if(!floater) return NULL; // iterator over all IM tabs (skip friends and near me) for (S32 i = 0; i < floater->getFloaterCount(); i++) { diff --git a/indra/newview/llfloaterfonttest.cpp b/indra/newview/llfloaterfonttest.cpp index 02791b711eb21cc9afb93e5acac4f55d42ebd0a5..413992910e59defeaecb86d7458f4c628e93d6ab 100644 --- a/indra/newview/llfloaterfonttest.cpp +++ b/indra/newview/llfloaterfonttest.cpp @@ -42,25 +42,11 @@ #include "lluictrlfactory.h" -LLFloaterFontTest* LLFloaterFontTest::sInstance = NULL; - -LLFloaterFontTest::LLFloaterFontTest() +LLFloaterFontTest::LLFloaterFontTest(const LLSD& key) : LLFloater("floater_font_test") { - LLUICtrlFactory::getInstance()->buildFloater(this, "floater_font_test.xml"); } LLFloaterFontTest::~LLFloaterFontTest() { - sInstance = NULL; -} - -// static -void LLFloaterFontTest::show(void *unused) -{ - if (!sInstance) - sInstance = new LLFloaterFontTest(); - - sInstance->openFloater(); - sInstance->setFocus(TRUE); } diff --git a/indra/newview/llfloaterfonttest.h b/indra/newview/llfloaterfonttest.h index eb2d410387b762ecab20922c36825badf0cf9c6d..4406a9f36a93bbf471ccfd2776f334bcd8feba4a 100644 --- a/indra/newview/llfloaterfonttest.h +++ b/indra/newview/llfloaterfonttest.h @@ -39,14 +39,10 @@ class LLFloaterFontTest: public LLFloater { -public: - static void show(void* unused); - + friend class LLFloaterReg; private: - LLFloaterFontTest(); + LLFloaterFontTest(const LLSD& key); ~LLFloaterFontTest(); - - static LLFloaterFontTest* sInstance; }; #endif diff --git a/indra/newview/llfloatergesture.cpp b/indra/newview/llfloatergesture.cpp index c3448d52c95a86483bb0ed2ec248d6e307fbeb89..9999b58e5bd6c057afade5a8433a78a20e46dced 100644 --- a/indra/newview/llfloatergesture.cpp +++ b/indra/newview/llfloatergesture.cpp @@ -44,7 +44,7 @@ #include "llcombobox.h" #include "llgesturemgr.h" #include "llinventorymodel.h" -#include "llinventoryview.h" +#include "llfloaterinventory.h" #include "llkeyboard.h" #include "lllineeditor.h" #include "llpreviewgesture.h" @@ -322,7 +322,7 @@ void LLFloaterGesture::onClickInventory(void* data) if (!list) return; const LLUUID& item_id = list->getCurrentID(); - LLInventoryView* inv = LLInventoryView::showAgentInventory(); + LLFloaterInventory* inv = LLFloaterInventory::showAgentInventory(); if (!inv) return; inv->getPanel()->setSelection(item_id, TRUE); } diff --git a/indra/newview/llfloatergodtools.cpp b/indra/newview/llfloatergodtools.cpp index 58cbe02d6d0e839b6be3bd86859c7f877e2a7ad7..6d603fa5c8ae250f9829ed63215bcb09ed24c2c5 100644 --- a/indra/newview/llfloatergodtools.cpp +++ b/indra/newview/llfloatergodtools.cpp @@ -50,6 +50,7 @@ #include "llcombobox.h" #include "lldraghandle.h" #include "llfloater.h" +#include "llfloaterreg.h" #include "llfocusmgr.h" #include "llfloatertopobjects.h" #include "lllineeditor.h" @@ -105,7 +106,7 @@ void LLFloaterGodTools::onOpen(const LLSD& key) // static void LLFloaterGodTools::refreshAll() { - LLFloaterGodTools* god_tools = getInstance(); + LLFloaterGodTools* god_tools = LLFloaterReg::getTypedInstance<LLFloaterGodTools>("god_tools"); if (god_tools) { if (gAgent.getRegionHost() != god_tools->mCurrentHost) @@ -119,7 +120,7 @@ void LLFloaterGodTools::refreshAll() LLFloaterGodTools::LLFloaterGodTools(const LLSD& key) -: LLFloater(), +: LLFloater(key), mCurrentHost(LLHost::invalid), mUpdateTimer() { @@ -127,13 +128,16 @@ LLFloaterGodTools::LLFloaterGodTools(const LLSD& key) mFactoryMap["region"] = LLCallbackMap(createPanelRegion, this); mFactoryMap["objects"] = LLCallbackMap(createPanelObjects, this); mFactoryMap["request"] = LLCallbackMap(createPanelRequest, this); - LLUICtrlFactory::getInstance()->buildFloater(this, "floater_god_tools.xml"); +// LLUICtrlFactory::getInstance()->buildFloater(this, "floater_god_tools.xml"); - sendRegionInfoRequest(); +} +BOOL LLFloaterGodTools::postBuild() +{ + sendRegionInfoRequest(); childShowTab("GodTools Tabs", "region"); + return TRUE; } - // static void* LLFloaterGodTools::createPanelGrid(void *userdata) { @@ -166,10 +170,7 @@ LLFloaterGodTools::~LLFloaterGodTools() { // children automatically deleted } -BOOL LLFloaterGodTools::postBuild() -{ - return TRUE; -} + U32 LLFloaterGodTools::computeRegionFlags() const { @@ -187,10 +188,10 @@ void LLFloaterGodTools::updatePopup(LLCoordGL center, MASK mask) // virtual void LLFloaterGodTools::onClose(bool app_quitting) { - if (getInstance()) - { - getInstance()->setVisible(FALSE); - } + LLFloaterGodTools* god_tools = LLFloaterReg::getTypedInstance<LLFloaterGodTools>("god_tools"); + if(!god_tools) return; + god_tools->setVisible(FALSE); + } // virtual @@ -271,16 +272,19 @@ void LLFloaterGodTools::processRegionInfo(LLMessageSystem* msg) regionp->setWaterHeight(water_height); regionp->setBillableFactor(billable_factor); } + + LLFloaterGodTools* god_tools = LLFloaterReg::getTypedInstance<LLFloaterGodTools>("god_tools"); + if (!god_tools) return; // push values to god tools, if available if ( gAgent.isGodlike() - && instanceVisible() - && getInstance()->mPanelRegionTools - && getInstance()->mPanelObjectTools + && LLFloaterReg::instanceVisible("god_tools") + && god_tools->mPanelRegionTools + && god_tools->mPanelObjectTools && msg ) { - LLPanelRegionTools* rtool = getInstance()->mPanelRegionTools; - getInstance()->mCurrentHost = host; + LLPanelRegionTools* rtool = god_tools->mPanelRegionTools; + god_tools->mCurrentHost = host; // store locally rtool->setSimName(sim_name); @@ -293,7 +297,7 @@ void LLFloaterGodTools::processRegionInfo(LLMessageSystem* msg) rtool->setRedirectGridY(redirect_grid_y); rtool->enableAllWidgets(); - LLPanelObjectTools *otool = getInstance()->mPanelObjectTools; + LLPanelObjectTools *otool = god_tools->mPanelObjectTools; otool->setCheckFlags(region_flags); otool->enableAllWidgets(); @@ -336,14 +340,17 @@ void LLFloaterGodTools::sendRegionInfoRequest() void LLFloaterGodTools::sendGodUpdateRegionInfo() { + LLFloaterGodTools* god_tools = LLFloaterReg::getTypedInstance<LLFloaterGodTools>("god_tools"); + if (!god_tools) return; + LLViewerRegion *regionp = gAgent.getRegion(); if (gAgent.isGodlike() - && getInstance()->mPanelRegionTools + && god_tools->mPanelRegionTools && regionp && gAgent.getRegionHost() == mCurrentHost) { LLMessageSystem *msg = gMessageSystem; - LLPanelRegionTools *rtool = getInstance()->mPanelRegionTools; + LLPanelRegionTools *rtool = god_tools->mPanelRegionTools; msg->newMessage("GodUpdateRegionInfo"); msg->nextBlockFast(_PREHASH_AgentData); @@ -403,58 +410,31 @@ const F32 PRICE_PER_METER_MAX = 100.f; LLPanelRegionTools::LLPanelRegionTools() : LLPanel() { + mCommitCallbackRegistrar.add("RegionTools.ChangeAnything", boost::bind(&LLPanelRegionTools::onChangeAnything, this)); + mCommitCallbackRegistrar.add("RegionTools.ChangePrelude", boost::bind(&LLPanelRegionTools::onChangePrelude, this)); + mCommitCallbackRegistrar.add("RegionTools.BakeTerrain", boost::bind(&LLPanelRegionTools::onBakeTerrain, this)); + mCommitCallbackRegistrar.add("RegionTools.RevertTerrain", boost::bind(&LLPanelRegionTools::onRevertTerrain, this)); + mCommitCallbackRegistrar.add("RegionTools.SwapTerrain", boost::bind(&LLPanelRegionTools::onSwapTerrain, this)); + mCommitCallbackRegistrar.add("RegionTools.Refresh", boost::bind(&LLPanelRegionTools::onRefresh, this)); + mCommitCallbackRegistrar.add("RegionTools.ApplyChanges", boost::bind(&LLPanelRegionTools::onApplyChanges, this)); + mCommitCallbackRegistrar.add("RegionTools.SelectRegion", boost::bind(&LLPanelRegionTools::onSelectRegion, this)); + mCommitCallbackRegistrar.add("RegionTools.SaveState", boost::bind(&LLPanelRegionTools::onSaveState, this)); } BOOL LLPanelRegionTools::postBuild() { - childSetCommitCallback("region name", onChangeAnything, this); getChild<LLLineEditor>("region name")->setKeystrokeCallback(onChangeSimName, this); childSetPrevalidate("region name", &LLLineEditor::prevalidatePrintableNotPipe); - - childSetCommitCallback("check prelude", onChangePrelude, this); - childSetCommitCallback("check fixed sun", onChangeAnything, this); - childSetCommitCallback("check reset home", onChangeAnything, this); - childSetCommitCallback("check visible", onChangeAnything, this); - childSetCommitCallback("check damage", onChangeAnything, this); - childSetCommitCallback("block dwell", onChangeAnything, this); - childSetCommitCallback("block terraform", onChangeAnything, this); - childSetCommitCallback("allow transfer", onChangeAnything, this); - childSetCommitCallback("is sandbox", onChangeAnything, this); - - childSetAction("Bake Terrain", onBakeTerrain, this); - childSetAction("Revert Terrain", onRevertTerrain, this); - childSetAction("Swap Terrain", onSwapTerrain, this); - - childSetCommitCallback("estate", onChangeAnything, this); childSetPrevalidate("estate", &LLLineEditor::prevalidatePositiveS32); - - childSetCommitCallback("parentestate", onChangeAnything, this); childSetPrevalidate("parentestate", &LLLineEditor::prevalidatePositiveS32); childDisable("parentestate"); - - childSetCommitCallback("gridposx", onChangeAnything, this); childSetPrevalidate("gridposx", &LLLineEditor::prevalidatePositiveS32); childDisable("gridposx"); - - childSetCommitCallback("gridposy", onChangeAnything, this); childSetPrevalidate("gridposy", &LLLineEditor::prevalidatePositiveS32); childDisable("gridposy"); - - childSetCommitCallback("redirectx", onChangeAnything, this); + childSetPrevalidate("redirectx", &LLLineEditor::prevalidatePositiveS32); - - childSetCommitCallback("redirecty", onChangeAnything, this); childSetPrevalidate("redirecty", &LLLineEditor::prevalidatePositiveS32); - - childSetCommitCallback("billable factor", onChangeAnything, this); - - childSetCommitCallback("land cost", onChangeAnything, this); - - childSetAction("Refresh", onRefresh, this); - childSetAction("Apply", onApplyChanges, this); - - childSetAction("Select Region", onSelectRegion, this); - childSetAction("Autosave now", onSaveState, this); return TRUE; } @@ -541,8 +521,6 @@ void LLPanelRegionTools::enableAllWidgets() childEnable("Autosave now"); } - -// static void LLPanelRegionTools::onSaveState(void* userdata) { if (gAgent.isGodlike()) @@ -739,28 +717,25 @@ void LLPanelRegionTools::setPricePerMeter(S32 price) childSetValue("land cost", price); } -// static -void LLPanelRegionTools::onChangeAnything(LLUICtrl* ctrl, void* userdata) +void LLPanelRegionTools::onChangeAnything() { - if (userdata && gAgent.isGodlike()) + if (gAgent.isGodlike()) { - LLPanelRegionTools* region_tools = (LLPanelRegionTools*) userdata; - region_tools->childEnable("Apply"); + childEnable("Apply"); } } -// static -void LLPanelRegionTools::onChangePrelude(LLUICtrl* ctrl, void* data) +void LLPanelRegionTools::onChangePrelude() { // checking prelude auto-checks fixed sun - LLPanelRegionTools* self = (LLPanelRegionTools*)data; - if (self->childGetValue("check prelude").asBoolean()) + if (childGetValue("check prelude").asBoolean()) { - self->childSetValue("check fixed sun", TRUE); - self->childSetValue("check reset home", TRUE); + childSetValue("check fixed sun", TRUE); + childSetValue("check reset home", TRUE); + onChangeAnything(); } // pass on to default onChange handler - onChangeAnything(ctrl, data); + } // static @@ -773,49 +748,50 @@ void LLPanelRegionTools::onChangeSimName(LLLineEditor* caller, void* userdata ) } } -//static -void LLPanelRegionTools::onRefresh(void* userdata) + +void LLPanelRegionTools::onRefresh() { + LLFloaterGodTools* god_tools = LLFloaterReg::getTypedInstance<LLFloaterGodTools>("god_tools"); + if(!god_tools) return; LLViewerRegion *region = gAgent.getRegion(); if (region && gAgent.isGodlike()) { - LLFloaterGodTools::getInstance()->sendRegionInfoRequest(); + god_tools->sendRegionInfoRequest(); + //LLFloaterGodTools::getInstance()->sendRegionInfoRequest(); + //LLFloaterReg::getTypedInstance<LLFloaterGodTools>("god_tools")->sendRegionInfoRequest(); } } -// static -void LLPanelRegionTools::onApplyChanges(void* userdata) +void LLPanelRegionTools::onApplyChanges() { + LLFloaterGodTools* god_tools = LLFloaterReg::getTypedInstance<LLFloaterGodTools>("god_tools"); + if(!god_tools) return; LLViewerRegion *region = gAgent.getRegion(); - if (region && userdata && gAgent.isGodlike()) + if (region && gAgent.isGodlike()) { - LLPanelRegionTools* region_tools = (LLPanelRegionTools*) userdata; - - region_tools->childDisable("Apply"); - LLFloaterGodTools::getInstance()->sendGodUpdateRegionInfo(); + childDisable("Apply"); + god_tools->sendGodUpdateRegionInfo(); + //LLFloaterReg::getTypedInstance<LLFloaterGodTools>("god_tools")->sendGodUpdateRegionInfo(); } } -// static -void LLPanelRegionTools::onBakeTerrain(void *userdata) +void LLPanelRegionTools::onBakeTerrain() { LLPanelRequestTools::sendRequest("terrain", "bake", gAgent.getRegionHost()); } -// static -void LLPanelRegionTools::onRevertTerrain(void *userdata) +void LLPanelRegionTools::onRevertTerrain() { LLPanelRequestTools::sendRequest("terrain", "revert", gAgent.getRegionHost()); } -// static -void LLPanelRegionTools::onSwapTerrain(void *userdata) + +void LLPanelRegionTools::onSwapTerrain() { LLPanelRequestTools::sendRequest("terrain", "swap", gAgent.getRegionHost()); } -// static -void LLPanelRegionTools::onSelectRegion(void* userdata) +void LLPanelRegionTools::onSelectRegion() { llinfos << "LLPanelRegionTools::onSelectRegion" << llendl; @@ -860,6 +836,8 @@ const F32 HOURS_TO_RADIANS = (2.f*F_PI)/24.f; LLPanelGridTools::LLPanelGridTools() : LLPanel() { + mCommitCallbackRegistrar.add("GridTools.KickAll", boost::bind(&LLPanelGridTools::onClickKickAll, this)); + mCommitCallbackRegistrar.add("GridTools.FlushMapVisibilityCaches", boost::bind(&LLPanelGridTools::onClickFlushMapVisibilityCaches, this)); } // Destroys the object @@ -869,9 +847,6 @@ LLPanelGridTools::~LLPanelGridTools() BOOL LLPanelGridTools::postBuild() { - childSetAction("Kick all users", onClickKickAll, this); - childSetAction("Flush This Region's Map Visibility Caches", onClickFlushMapVisibilityCaches, this); - return TRUE; } @@ -879,9 +854,7 @@ void LLPanelGridTools::refresh() { } - -// static -void LLPanelGridTools::onClickKickAll(void* userdata) +void LLPanelGridTools::onClickKickAll() { LLNotifications::instance().add("KickAllUsers", LLSD(), LLSD(), LLPanelGridTools::confirmKick); } @@ -921,9 +894,7 @@ bool LLPanelGridTools::finishKick(const LLSD& notification, const LLSD& response return false; } - -// static -void LLPanelGridTools::onClickFlushMapVisibilityCaches(void* data) +void LLPanelGridTools::onClickFlushMapVisibilityCaches() { LLNotifications::instance().add("FlushMapVisibilityCaches", LLSD(), LLSD(), flushMapVisibilityCachesConfirm); } @@ -981,6 +952,15 @@ LLPanelObjectTools::LLPanelObjectTools() : LLPanel(), mTargetAvatar() { + mCommitCallbackRegistrar.add("ObjectTools.ChangeAnything", boost::bind(&LLPanelObjectTools::onChangeAnything, this)); + mCommitCallbackRegistrar.add("ObjectTools.DeletePublicOwnedBy", boost::bind(&LLPanelObjectTools::onClickDeletePublicOwnedBy, this)); + mCommitCallbackRegistrar.add("ObjectTools.DeleteAllScriptedOwnedBy", boost::bind(&LLPanelObjectTools::onClickDeleteAllScriptedOwnedBy, this)); + mCommitCallbackRegistrar.add("ObjectTools.DeleteAllOwnedBy", boost::bind(&LLPanelObjectTools::onClickDeleteAllOwnedBy, this)); + mCommitCallbackRegistrar.add("ObjectTools.ApplyChanges", boost::bind(&LLPanelObjectTools::onApplyChanges, this)); + mCommitCallbackRegistrar.add("ObjectTools.Set", boost::bind(&LLPanelObjectTools::onClickSet, this)); + mCommitCallbackRegistrar.add("ObjectTools.GetTopColliders", boost::bind(&LLPanelObjectTools::onGetTopColliders, this)); + mCommitCallbackRegistrar.add("ObjectTools.GetTopScripts", boost::bind(&LLPanelObjectTools::onGetTopScripts, this)); + mCommitCallbackRegistrar.add("ObjectTools.GetScriptDigest", boost::bind(&LLPanelObjectTools::onGetScriptDigest, this)); } // Destroys the object @@ -991,22 +971,6 @@ LLPanelObjectTools::~LLPanelObjectTools() BOOL LLPanelObjectTools::postBuild() { - childSetCommitCallback("disable scripts", onChangeAnything, this); - childSetCommitCallback("disable collisions", onChangeAnything, this); - childSetCommitCallback("disable physics", onChangeAnything, this); - - childSetAction("Apply", onApplyChanges, this); - - childSetAction("Set Target", onClickSet, this); - - childSetAction("Delete Target's Scripted Objects On Others Land", onClickDeletePublicOwnedBy, this); - childSetAction("Delete Target's Scripted Objects On *Any* Land", onClickDeleteAllScriptedOwnedBy, this); - childSetAction("Delete *ALL* Of Target's Objects", onClickDeleteAllOwnedBy, this); - - childSetAction("Get Top Colliders", onGetTopColliders, this); - childSetAction("Get Top Scripts", onGetTopScripts, this); - childSetAction("Scripts digest", onGetScriptDigest, this); - return TRUE; } @@ -1095,30 +1059,33 @@ void LLPanelObjectTools::enableAllWidgets() } -// static -void LLPanelObjectTools::onGetTopColliders(void* userdata) +void LLPanelObjectTools::onGetTopColliders() { + LLFloaterTopObjects* instance = LLFloaterReg::getTypedInstance<LLFloaterTopObjects>("top_objects"); + if(!instance) return; + if (gAgent.isGodlike()) { - LLFloaterTopObjects::show(); + LLFloaterReg::showInstance("top_objects"); LLFloaterTopObjects::setMode(STAT_REPORT_TOP_COLLIDERS); - LLFloaterTopObjects::onRefresh(NULL); + instance->onRefresh(); } } -// static -void LLPanelObjectTools::onGetTopScripts(void* userdata) +void LLPanelObjectTools::onGetTopScripts() { + LLFloaterTopObjects* instance = LLFloaterReg::getTypedInstance<LLFloaterTopObjects>("top_objects"); + if(!instance) return; + if (gAgent.isGodlike()) { - LLFloaterTopObjects::show(); + LLFloaterReg::showInstance("top_objects"); LLFloaterTopObjects::setMode(STAT_REPORT_TOP_SCRIPTS); - LLFloaterTopObjects::onRefresh(NULL); + instance->onRefresh(); } } -// static -void LLPanelObjectTools::onGetScriptDigest(void* userdata) +void LLPanelObjectTools::onGetScriptDigest() { if (gAgent.isGodlike()) { @@ -1128,20 +1095,20 @@ void LLPanelObjectTools::onGetScriptDigest(void* userdata) } } -void LLPanelObjectTools::onClickDeletePublicOwnedBy(void* userdata) +void LLPanelObjectTools::onClickDeletePublicOwnedBy() { // Bring up view-modal dialog - LLPanelObjectTools* panelp = (LLPanelObjectTools*)userdata; - if (!panelp->mTargetAvatar.isNull()) + + if (!mTargetAvatar.isNull()) { - panelp->mSimWideDeletesFlags = + mSimWideDeletesFlags = SWD_SCRIPTED_ONLY | SWD_OTHERS_LAND_ONLY; LLSD args; - args["AVATAR_NAME"] = panelp->childGetValue("target_avatar_name").asString(); + args["AVATAR_NAME"] = childGetValue("target_avatar_name").asString(); LLSD payload; - payload["avatar_id"] = panelp->mTargetAvatar; - payload["flags"] = (S32)panelp->mSimWideDeletesFlags; + payload["avatar_id"] = mTargetAvatar; + payload["flags"] = (S32)mSimWideDeletesFlags; LLNotifications::instance().add( "GodDeleteAllScriptedPublicObjectsByUser", args, @@ -1150,20 +1117,18 @@ void LLPanelObjectTools::onClickDeletePublicOwnedBy(void* userdata) } } -// static -void LLPanelObjectTools::onClickDeleteAllScriptedOwnedBy(void* userdata) +void LLPanelObjectTools::onClickDeleteAllScriptedOwnedBy() { // Bring up view-modal dialog - LLPanelObjectTools* panelp = (LLPanelObjectTools*)userdata; - if (!panelp->mTargetAvatar.isNull()) + if (!mTargetAvatar.isNull()) { - panelp->mSimWideDeletesFlags = SWD_SCRIPTED_ONLY; + mSimWideDeletesFlags = SWD_SCRIPTED_ONLY; LLSD args; - args["AVATAR_NAME"] = panelp->childGetValue("target_avatar_name").asString(); + args["AVATAR_NAME"] = childGetValue("target_avatar_name").asString(); LLSD payload; - payload["avatar_id"] = panelp->mTargetAvatar; - payload["flags"] = (S32)panelp->mSimWideDeletesFlags; + payload["avatar_id"] = mTargetAvatar; + payload["flags"] = (S32)mSimWideDeletesFlags; LLNotifications::instance().add( "GodDeleteAllScriptedObjectsByUser", args, @@ -1172,20 +1137,18 @@ void LLPanelObjectTools::onClickDeleteAllScriptedOwnedBy(void* userdata) } } -// static -void LLPanelObjectTools::onClickDeleteAllOwnedBy(void* userdata) +void LLPanelObjectTools::onClickDeleteAllOwnedBy() { // Bring up view-modal dialog - LLPanelObjectTools* panelp = (LLPanelObjectTools*)userdata; - if (!panelp->mTargetAvatar.isNull()) + if (!mTargetAvatar.isNull()) { - panelp->mSimWideDeletesFlags = 0; + mSimWideDeletesFlags = 0; LLSD args; - args["AVATAR_NAME"] = panelp->childGetValue("target_avatar_name").asString(); + args["AVATAR_NAME"] = childGetValue("target_avatar_name").asString(); LLSD payload; - payload["avatar_id"] = panelp->mTargetAvatar; - payload["flags"] = (S32)panelp->mSimWideDeletesFlags; + payload["avatar_id"] = mTargetAvatar; + payload["flags"] = (S32)mSimWideDeletesFlags; LLNotifications::instance().add( "GodDeleteAllObjectsByUser", args, @@ -1209,11 +1172,10 @@ bool LLPanelObjectTools::callbackSimWideDeletes( const LLSD& notification, const return false; } -void LLPanelObjectTools::onClickSet(void* data) +void LLPanelObjectTools::onClickSet() { - LLPanelObjectTools* panelp = (LLPanelObjectTools*) data; // grandparent is a floater, which can have a dependent - gFloaterView->getParentFloater(panelp)->addDependentFloater(LLFloaterAvatarPicker::show(callbackAvatarID, data)); + gFloaterView->getParentFloater(this)->addDependentFloater(LLFloaterAvatarPicker::show(callbackAvatarID, this)); } void LLPanelObjectTools::onClickSetBySelection(void* data) @@ -1247,28 +1209,25 @@ void LLPanelObjectTools::callbackAvatarID(const std::vector<std::string>& names, object_tools->refresh(); } - -// static -void LLPanelObjectTools::onChangeAnything(LLUICtrl* ctrl, void* userdata) +void LLPanelObjectTools::onChangeAnything() { - if (userdata && gAgent.isGodlike()) + if (gAgent.isGodlike()) { - LLPanelObjectTools* object_tools = (LLPanelObjectTools*) userdata; - object_tools->childEnable("Apply"); + childEnable("Apply"); } } -// static -void LLPanelObjectTools::onApplyChanges(void* userdata) +void LLPanelObjectTools::onApplyChanges() { + LLFloaterGodTools* god_tools = LLFloaterReg::getTypedInstance<LLFloaterGodTools>("god_tools"); + if(!god_tools) return; LLViewerRegion *region = gAgent.getRegion(); if (region && gAgent.isGodlike()) { - LLPanelObjectTools* object_tools = (LLPanelObjectTools*) userdata; // TODO -- implement this - - object_tools->childDisable("Apply"); - LLFloaterGodTools::getInstance()->sendGodUpdateRegionInfo(); + childDisable("Apply"); + god_tools->sendGodUpdateRegionInfo(); + //LLFloaterReg::getTypedInstance<LLFloaterGodTools>("god_tools")->sendGodUpdateRegionInfo(); } } @@ -1283,6 +1242,7 @@ const std::string AGENT_REGION = "Agent Region"; LLPanelRequestTools::LLPanelRequestTools(): LLPanel() { + mCommitCallbackRegistrar.add("GodTools.Request", boost::bind(&LLPanelRequestTools::onClickRequest, this)); } LLPanelRequestTools::~LLPanelRequestTools() @@ -1291,8 +1251,6 @@ LLPanelRequestTools::~LLPanelRequestTools() BOOL LLPanelRequestTools::postBuild() { - childSetAction("Make Request", onClickRequest, this); - refresh(); return TRUE; @@ -1353,21 +1311,19 @@ void LLPanelRequestTools::sendRequest(const std::string& request, msg->sendReliable(host); } -// static -void LLPanelRequestTools::onClickRequest(void* data) +void LLPanelRequestTools::onClickRequest() { - LLPanelRequestTools* self = (LLPanelRequestTools*)data; - const std::string dest = self->childGetValue("destination").asString(); + const std::string dest = childGetValue("destination").asString(); if(dest == SELECTION) { - std::string req = self->childGetValue("request"); + std::string req =childGetValue("request"); req = req.substr(0, req.find_first_of(" ")); - std::string param = self->childGetValue("parameter"); + std::string param = childGetValue("parameter"); LLSelectMgr::getInstance()->sendGodlikeRequest(req, param); } else if(dest == AGENT_REGION) { - self->sendRequest(gAgent.getRegionHost()); + sendRequest(gAgent.getRegionHost()); } else { @@ -1379,7 +1335,7 @@ void LLPanelRequestTools::onClickRequest(void* data) if(dest == regionp->getName()) { // found it - self->sendRequest(regionp->getHost()); + sendRequest(regionp->getHost()); } } } diff --git a/indra/newview/llfloatergodtools.h b/indra/newview/llfloatergodtools.h index 6c4b43880806f73fdb8e1be392a25077c2e951f3..2564b15b37b3447b1e63e442daad2cf70f983581 100644 --- a/indra/newview/llfloatergodtools.h +++ b/indra/newview/llfloatergodtools.h @@ -57,9 +57,9 @@ class LLTextBox; class LLMessageSystem; class LLFloaterGodTools - : public LLFloater, public LLFloaterSingleton<LLFloaterGodTools> + : public LLFloater { - friend class LLUISingleton<LLFloaterGodTools, VisibilityPolicy<LLFloater> >; + friend class LLFloaterReg; public: enum EGodPanel @@ -98,12 +98,16 @@ public: // Send possibly changed values to simulator. void sendGodUpdateRegionInfo(); +private: + + LLFloaterGodTools(const LLSD& key); + ~LLFloaterGodTools(); + protected: U32 computeRegionFlags() const; protected: - LLFloaterGodTools(const LLSD& key); - ~LLFloaterGodTools(); + /*virtual*/ BOOL postBuild(); // When the floater is going away, reset any options that need to be // cleared. @@ -133,16 +137,17 @@ public: /*virtual*/ void refresh(); - static void onSaveState(void* data); - static void onChangeAnything(LLUICtrl* ctrl, void* userdata); - static void onChangePrelude(LLUICtrl* ctrl, void* data); + static void onSaveState(void* userdata); static void onChangeSimName(LLLineEditor* caller, void* userdata); - static void onApplyChanges(void* userdata); - static void onBakeTerrain(void *userdata); - static void onRevertTerrain(void *userdata); - static void onSwapTerrain(void *userdata); - static void onSelectRegion(void *userdata); - static void onRefresh(void* userdata); + + void onChangeAnything(); + void onChangePrelude(); + void onApplyChanges(); + void onBakeTerrain(); + void onRevertTerrain(); + void onSwapTerrain(); + void onSelectRegion(); + void onRefresh(); // set internal checkboxes/spinners/combos const std::string getSimName() const; @@ -194,11 +199,11 @@ public: void refresh(); - static void onClickKickAll(void *data); + void onClickKickAll(); static bool confirmKick(const LLSD& notification, const LLSD& response); static bool finishKick(const LLSD& notification, const LLSD& response); static void onDragSunPhase(LLUICtrl *ctrl, void *userdata); - static void onClickFlushMapVisibilityCaches(void* data); + void onClickFlushMapVisibilityCaches(); static bool flushMapVisibilityCachesConfirm(const LLSD& notification, const LLSD& response); protected: @@ -227,17 +232,17 @@ public: void enableAllWidgets(); void setCheckFlags(U32 flags); - static void onChangeAnything(LLUICtrl* ctrl, void* data); - static void onApplyChanges(void* data); - static void onClickSet(void* data); + void onChangeAnything(); + void onApplyChanges(); + void onClickSet(); static void callbackAvatarID(const std::vector<std::string>& names, const std::vector<LLUUID>& ids, void* data); - static void onClickDeletePublicOwnedBy(void* data); - static void onClickDeleteAllScriptedOwnedBy(void* data); - static void onClickDeleteAllOwnedBy(void* data); + void onClickDeletePublicOwnedBy(); + void onClickDeleteAllScriptedOwnedBy(); + void onClickDeleteAllOwnedBy(); static bool callbackSimWideDeletes(const LLSD& notification, const LLSD& response); - static void onGetTopColliders(void* data); - static void onGetTopScripts(void* data); - static void onGetScriptDigest(void* data); + void onGetTopColliders(); + void onGetTopScripts(); + void onGetScriptDigest(); static void onClickSetBySelection(void* data); protected: @@ -267,7 +272,7 @@ public: const LLHost& host); protected: - static void onClickRequest(void *data); + void onClickRequest(); void sendRequest(const LLHost& host); }; diff --git a/indra/newview/llfloaterhud.cpp b/indra/newview/llfloaterhud.cpp index 4379d25a66ec764e2d83e8b3e1c7e7ecaf319cb1..dd70560bb7dac9be47d25442a84f76c5a87bc37b 100644 --- a/indra/newview/llfloaterhud.cpp +++ b/indra/newview/llfloaterhud.cpp @@ -42,8 +42,6 @@ // Linden libs #include "lluictrlfactory.h" -// statics -LLFloaterHUD* LLFloaterHUD::sInstance = 0; ///---------------------------------------------------------------------------- /// Class LLFloaterHUD @@ -51,12 +49,18 @@ LLFloaterHUD* LLFloaterHUD::sInstance = 0; #define super LLFloater /* superclass */ // Default constructor -LLFloaterHUD::LLFloaterHUD() -: LLFloater(), +LLFloaterHUD::LLFloaterHUD(const LLSD& key) +: LLFloater(key), mWebBrowser(0) { - // Create floater from its XML definition - LLUICtrlFactory::getInstance()->buildFloater(this, "floater_hud.xml"); + // do not build the floater if there the url is empty + if (gSavedSettings.getString("TutorialURL") == "") + { + LLNotifications::instance().add("TutorialNotFound"); + return; + } + + //LLUICtrlFactory::getInstance()->buildFloater(this, "floater_hud.xml"); // Don't grab the focus as it will impede performing in-world actions // while using the HUD @@ -68,62 +72,35 @@ LLFloaterHUD::LLFloaterHUD() // Opaque background since we never get the focus setBackgroundOpaque(TRUE); +} +BOOL LLFloaterHUD::postBuild() +{ mWebBrowser = getChild<LLWebBrowserCtrl>("floater_hud_browser" ); if (mWebBrowser) { // Open links in internal browser mWebBrowser->setOpenInExternalBrowser(false); - + // This is a "chrome" floater, so we don't want anything to // take focus (as the user needs to be able to walk with // arrow keys during tutorial). mWebBrowser->setTakeFocusOnClick(false); - + std::string language = LLUI::getLanguage(); std::string base_url = gSavedSettings.getString("TutorialURL"); - + std::string url = base_url + language + "/"; mWebBrowser->navigateTo(url); } -} - -// Get the instance -LLFloaterHUD* LLFloaterHUD::getInstance() -{ - if (!sInstance) - { - sInstance = new LLFloaterHUD(); - } - return sInstance; + + return TRUE; } // Destructor LLFloaterHUD::~LLFloaterHUD() { - // Clear out the one instance if it's ours - if (sInstance == this) - { - sInstance = NULL; - } } - -// Show the HUD -void LLFloaterHUD::showHUD() -{ - // do not build the floater if there the url is empty - if (gSavedSettings.getString("TutorialURL") == "") - { - LLNotifications::instance().add("TutorialNotFound"); - return; - } - - // Create the instance if necessary - LLFloaterHUD* hud = getInstance(); - hud->openFloater(); - hud->setFrontmost(FALSE); -} - // Save our visibility state on close in case the user accidentally // quit the application while the tutorial was visible. // virtual diff --git a/indra/newview/llfloaterhud.h b/indra/newview/llfloaterhud.h index 2d58685b58e2bd8e2bd550139afc1367ab8c9eb7..33ed9faa678cfc6ab68b61fd9ef80d2e7e7e9971 100644 --- a/indra/newview/llfloaterhud.h +++ b/indra/newview/llfloaterhud.h @@ -39,22 +39,20 @@ class LLWebBrowserCtrl; class LLFloaterHUD : public LLFloater { + friend class LLFloaterReg; public: - static LLFloaterHUD* getInstance(); ///< get instance creating if necessary - - static void showHUD(); ///< show the HUD // Save our visibility state during close /*virtual*/ void onClose(bool app_quitting); - + BOOL postBuild(); + private: // Handles its own construction and destruction, so private. - LLFloaterHUD(); + LLFloaterHUD(const LLSD& key); /*virtual*/ ~LLFloaterHUD(); private: LLWebBrowserCtrl* mWebBrowser; ///< the actual web browser control - static LLFloaterHUD* sInstance; }; #endif // LL_LLFLOATERHUD_H diff --git a/indra/newview/llfloaterinspect.cpp b/indra/newview/llfloaterinspect.cpp index 4b29a304acf9fd1522008ffeb72509263d9d70a5..aa615ef342ab3140dea08db1b8471670f54a2ae0 100644 --- a/indra/newview/llfloaterinspect.cpp +++ b/indra/newview/llfloaterinspect.cpp @@ -47,13 +47,32 @@ #include "llviewerobject.h" #include "lluictrlfactory.h" -LLFloaterInspect* LLFloaterInspect::sInstance = NULL; +//LLFloaterInspect* LLFloaterInspect::sInstance = NULL; -LLFloaterInspect::LLFloaterInspect(void) - : LLFloater(), +LLFloaterInspect::LLFloaterInspect(const LLSD& key) + : LLFloater(key), mDirty(FALSE) { - LLUICtrlFactory::getInstance()->buildFloater(this, "floater_inspect.xml"); + //LLUICtrlFactory::getInstance()->buildFloater(this, "floater_inspect.xml"); + mCommitCallbackRegistrar.add("Inspect.OwnerProfile", boost::bind(&LLFloaterInspect::onClickOwnerProfile, this)); + mCommitCallbackRegistrar.add("Inspect.CreatorProfile", boost::bind(&LLFloaterInspect::onClickCreatorProfile, this)); + mCommitCallbackRegistrar.add("Inspect.SelectObject", boost::bind(&LLFloaterInspect::onSelectObject, this)); +} + +BOOL LLFloaterInspect::postBuild() +{ + mObjectList = getChild<LLScrollListCtrl>("object_list"); +// childSetAction("button owner",onClickOwnerProfile, this); +// childSetAction("button creator",onClickCreatorProfile, this); +// childSetCommitCallback("object_list", onSelectObject, NULL); + + BOOL forcesel = LLSelectMgr::getInstance()->setForceSelection(TRUE); + LLToolMgr::getInstance()->setTransientTool(LLToolCompInspect::getInstance()); + LLSelectMgr::getInstance()->setForceSelection(forcesel); // restore previouis value + mObjectSelection = LLSelectMgr::getInstance()->getSelection(); + refresh(); + + return TRUE; } LLFloaterInspect::~LLFloaterInspect(void) @@ -71,14 +90,14 @@ LLFloaterInspect::~LLFloaterInspect(void) { LLFloaterReg::showInstance("build", LLSD(), TRUE); } - sInstance = NULL; + //sInstance = NULL; } - +/* BOOL LLFloaterInspect::isVisible() { return (!!sInstance); -} - +}*/ +/* void LLFloaterInspect::show(void* ignored) { // setForceSelection ensures that the pie menu does not deselect things when it @@ -98,15 +117,14 @@ void LLFloaterInspect::show(void* ignored) sInstance->mObjectSelection = LLSelectMgr::getInstance()->getSelection(); sInstance->refresh(); } - -void LLFloaterInspect::onClickCreatorProfile(void* ctrl) +*/ +void LLFloaterInspect::onClickCreatorProfile() { - if(sInstance->mObjectList->getAllSelected().size() == 0) + if(mObjectList->getAllSelected().size() == 0) { return; } - LLScrollListItem* first_selected = - sInstance->mObjectList->getFirstSelected(); + LLScrollListItem* first_selected =mObjectList->getFirstSelected(); if (first_selected) { @@ -119,7 +137,7 @@ void LLFloaterInspect::onClickCreatorProfile(void* ctrl) return (obj_id == node->getObject()->getID()); } } func(first_selected->getUUID()); - LLSelectNode* node = sInstance->mObjectSelection->getFirstNode(&func); + LLSelectNode* node = mObjectSelection->getFirstNode(&func); if(node) { LLFriendActions::showProfile(node->mPermissions->getCreator()); @@ -127,11 +145,10 @@ void LLFloaterInspect::onClickCreatorProfile(void* ctrl) } } -void LLFloaterInspect::onClickOwnerProfile(void* ctrl) +void LLFloaterInspect::onClickOwnerProfile() { - if(sInstance->mObjectList->getAllSelected().size() == 0) return; - LLScrollListItem* first_selected = - sInstance->mObjectList->getFirstSelected(); + if(mObjectList->getAllSelected().size() == 0) return; + LLScrollListItem* first_selected =mObjectList->getFirstSelected(); if (first_selected) { @@ -145,7 +162,7 @@ void LLFloaterInspect::onClickOwnerProfile(void* ctrl) return (obj_id == node->getObject()->getID()); } } func(selected_id); - LLSelectNode* node = sInstance->mObjectSelection->getFirstNode(&func); + LLSelectNode* node = mObjectSelection->getFirstNode(&func); if(node) { const LLUUID& owner_id = node->mPermissions->getOwner(); @@ -154,37 +171,25 @@ void LLFloaterInspect::onClickOwnerProfile(void* ctrl) } } -BOOL LLFloaterInspect::postBuild() -{ - mObjectList = getChild<LLScrollListCtrl>("object_list"); - childSetAction("button owner",onClickOwnerProfile, this); - childSetAction("button creator",onClickCreatorProfile, this); - childSetCommitCallback("object_list", onSelectObject, NULL); - return TRUE; -} - -void LLFloaterInspect::onSelectObject(LLUICtrl* ctrl, void* user_data) +void LLFloaterInspect::onSelectObject() { if(LLFloaterInspect::getSelectedUUID() != LLUUID::null) { - sInstance->childSetEnabled("button owner", true); - sInstance->childSetEnabled("button creator", true); + childSetEnabled("button owner", true); + childSetEnabled("button creator", true); } } LLUUID LLFloaterInspect::getSelectedUUID() { - if(sInstance) + if(mObjectList->getAllSelected().size() > 0) { - if(sInstance->mObjectList->getAllSelected().size() > 0) + LLScrollListItem* first_selected =mObjectList->getFirstSelected(); + if (first_selected) { - LLScrollListItem* first_selected = - sInstance->mObjectList->getFirstSelected(); - if (first_selected) - { - return first_selected->getUUID(); - } + return first_selected->getUUID(); } + } return LLUUID::null; } @@ -262,7 +267,7 @@ void LLFloaterInspect::refresh() { mObjectList->selectNthItem(0); } - onSelectObject(this, NULL); + onSelectObject(); mObjectList->setScrollPos(pos); } @@ -274,10 +279,7 @@ void LLFloaterInspect::onFocusReceived() void LLFloaterInspect::dirty() { - if(sInstance) - { - sInstance->setDirty(); - } + setDirty(); } void LLFloaterInspect::draw() diff --git a/indra/newview/llfloaterinspect.h b/indra/newview/llfloaterinspect.h index 57bba6864fac1328eae95ba4c5656daedf37bb4e..a65ccaa66e660dfb9b71803677098c72e4f1b4f8 100644 --- a/indra/newview/llfloaterinspect.h +++ b/indra/newview/llfloaterinspect.h @@ -44,29 +44,32 @@ class LLUICtrl; class LLFloaterInspect : public LLFloater { + friend class LLFloaterReg; public: - virtual ~LLFloaterInspect(void); - static void show(void* ignored = NULL); + +// static void show(void* ignored = NULL); virtual BOOL postBuild(); - static void dirty(); - static LLUUID getSelectedUUID(); + void dirty(); + LLUUID getSelectedUUID(); virtual void draw(); virtual void refresh(); - static BOOL isVisible(); +// static BOOL isVisible(); virtual void onFocusReceived(); - static void onClickCreatorProfile(void* ctrl); - static void onClickOwnerProfile(void* ctrl); - static void onSelectObject(LLUICtrl* ctrl, void* user_data); + void onClickCreatorProfile(); + void onClickOwnerProfile(); + void onSelectObject(); LLScrollListCtrl* mObjectList; protected: // protected members - LLFloaterInspect(); void setDirty() { mDirty = TRUE; } bool mDirty; private: + + LLFloaterInspect(const LLSD& key); + virtual ~LLFloaterInspect(void); // static data - static LLFloaterInspect* sInstance; +// static LLFloaterInspect* sInstance; LLSafeHandle<LLObjectSelection> mObjectSelection; }; diff --git a/indra/newview/llfloaterinventory.cpp b/indra/newview/llfloaterinventory.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0dd1d6adcd1254f230d523a9cd7df03258ed0801 --- /dev/null +++ b/indra/newview/llfloaterinventory.cpp @@ -0,0 +1,1941 @@ +/** + * @file llfloaterinventory.cpp + * @brief Implementation of the inventory view and associated stuff. + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include <utility> // for std::pair<> + +#include "llfloaterinventory.h" + +// library includes +#include "llagent.h" +#include "llagentwearables.h" +#include "llcallingcard.h" +#include "llfloaterreg.h" +#include "llsdserialize.h" +#include "llsearcheditor.h" +#include "llspinctrl.h" +#include "llui.h" +#include "message.h" + +// newview includes +#include "llappviewer.h" +#include "llfirstuse.h" +#include "llfloateravatarinfo.h" +#include "llfloaterchat.h" +#include "llfloatercustomize.h" +#include "llfocusmgr.h" +#include "llfolderview.h" +#include "llgesturemgr.h" +#include "lliconctrl.h" +#include "llimview.h" +#include "llinventorybridge.h" +#include "llinventoryclipboard.h" +#include "llinventorymodel.h" +#include "lllineeditor.h" +#include "llmenugl.h" +#include "llpreviewanim.h" +#include "llpreviewgesture.h" +#include "llpreviewlandmark.h" +#include "llpreviewnotecard.h" +#include "llpreviewscript.h" +#include "llpreviewsound.h" +#include "llpreviewtexture.h" +#include "llresmgr.h" +#include "llscrollbar.h" +#include "llscrollcontainer.h" +#include "llselectmgr.h" +#include "lltabcontainer.h" +#include "lltooldraganddrop.h" +#include "lluictrlfactory.h" +#include "llviewerimagelist.h" +#include "llviewerinventory.h" +#include "llviewermessage.h" +#include "llviewerobjectlist.h" +#include "llviewerregion.h" +#include "llviewerwindow.h" +#include "llvoavatarself.h" +#include "llwearablelist.h" + +static LLDefaultChildRegistry::Register<LLInventoryPanel> r("inventory_panel"); + +//BOOL LLFloaterInventory::sOpenNextNewItem = FALSE; +BOOL LLFloaterInventory::sWearNewClothing = FALSE; +LLUUID LLFloaterInventory::sWearNewClothingTransactionID; + +///---------------------------------------------------------------------------- +/// LLFloaterInventoryFinder +///---------------------------------------------------------------------------- + +LLFloaterInventoryFinder::LLFloaterInventoryFinder(LLFloaterInventory* inventory_view) +: LLFloater(), + mFloaterInventory(inventory_view), + mFilter(inventory_view->mActivePanel->getFilter()) +{ + LLUICtrlFactory::getInstance()->buildFloater(this, "floater_inventory_view_finder.xml"); + updateElementsFromFilter(); +} + + +void LLFloaterInventoryFinder::onCheckSinceLogoff(LLUICtrl *ctrl, void *user_data) +{ + LLFloaterInventoryFinder *self = (LLFloaterInventoryFinder *)user_data; + if (!self) return; + + bool since_logoff= self->childGetValue("check_since_logoff"); + + if (!since_logoff && + !( self->mSpinSinceDays->get() || self->mSpinSinceHours->get() ) ) + { + self->mSpinSinceHours->set(1.0f); + } +} +BOOL LLFloaterInventoryFinder::postBuild() +{ + const LLRect& viewrect = mFloaterInventory->getRect(); + setRect(LLRect(viewrect.mLeft - getRect().getWidth(), viewrect.mTop, viewrect.mLeft, viewrect.mTop - getRect().getHeight())); + + childSetAction("All", selectAllTypes, this); + childSetAction("None", selectNoTypes, this); + + mSpinSinceHours = getChild<LLSpinCtrl>("spin_hours_ago"); + childSetCommitCallback("spin_hours_ago", onTimeAgo, this); + + mSpinSinceDays = getChild<LLSpinCtrl>("spin_days_ago"); + childSetCommitCallback("spin_days_ago", onTimeAgo, this); + + // mCheckSinceLogoff = getChild<LLSpinCtrl>("check_since_logoff"); + childSetCommitCallback("check_since_logoff", onCheckSinceLogoff, this); + + childSetAction("Close", onCloseBtn, this); + + updateElementsFromFilter(); + return TRUE; +} +void LLFloaterInventoryFinder::onTimeAgo(LLUICtrl *ctrl, void *user_data) +{ + LLFloaterInventoryFinder *self = (LLFloaterInventoryFinder *)user_data; + if (!self) return; + + bool since_logoff=true; + if ( self->mSpinSinceDays->get() || self->mSpinSinceHours->get() ) + { + since_logoff = false; + } + self->childSetValue("check_since_logoff", since_logoff); +} + +void LLFloaterInventoryFinder::changeFilter(LLInventoryFilter* filter) +{ + mFilter = filter; + updateElementsFromFilter(); +} + +void LLFloaterInventoryFinder::updateElementsFromFilter() +{ + if (!mFilter) + return; + + // Get data needed for filter display + U32 filter_types = mFilter->getFilterTypes(); + std::string filter_string = mFilter->getFilterSubString(); + LLInventoryFilter::EFolderShow show_folders = mFilter->getShowFolderState(); + U32 hours = mFilter->getHoursAgo(); + + // update the ui elements + LLFloater::setTitle(mFilter->getName()); + childSetValue("check_animation", (S32) (filter_types & 0x1 << LLInventoryType::IT_ANIMATION)); + + childSetValue("check_calling_card", (S32) (filter_types & 0x1 << LLInventoryType::IT_CALLINGCARD)); + childSetValue("check_clothing", (S32) (filter_types & 0x1 << LLInventoryType::IT_WEARABLE)); + childSetValue("check_gesture", (S32) (filter_types & 0x1 << LLInventoryType::IT_GESTURE)); + childSetValue("check_landmark", (S32) (filter_types & 0x1 << LLInventoryType::IT_LANDMARK)); + childSetValue("check_notecard", (S32) (filter_types & 0x1 << LLInventoryType::IT_NOTECARD)); + childSetValue("check_object", (S32) (filter_types & 0x1 << LLInventoryType::IT_OBJECT)); + childSetValue("check_script", (S32) (filter_types & 0x1 << LLInventoryType::IT_LSL)); + childSetValue("check_sound", (S32) (filter_types & 0x1 << LLInventoryType::IT_SOUND)); + childSetValue("check_texture", (S32) (filter_types & 0x1 << LLInventoryType::IT_TEXTURE)); + childSetValue("check_snapshot", (S32) (filter_types & 0x1 << LLInventoryType::IT_SNAPSHOT)); + childSetValue("check_show_empty", show_folders == LLInventoryFilter::SHOW_ALL_FOLDERS); + childSetValue("check_since_logoff", mFilter->isSinceLogoff()); + mSpinSinceHours->set((F32)(hours % 24)); + mSpinSinceDays->set((F32)(hours / 24)); +} + +void LLFloaterInventoryFinder::draw() +{ + LLMemType mt(LLMemType::MTYPE_INVENTORY_DRAW); + U32 filter = 0xffffffff; + BOOL filtered_by_all_types = TRUE; + + if (!childGetValue("check_animation")) + { + filter &= ~(0x1 << LLInventoryType::IT_ANIMATION); + filtered_by_all_types = FALSE; + } + + + if (!childGetValue("check_calling_card")) + { + filter &= ~(0x1 << LLInventoryType::IT_CALLINGCARD); + filtered_by_all_types = FALSE; + } + + if (!childGetValue("check_clothing")) + { + filter &= ~(0x1 << LLInventoryType::IT_WEARABLE); + filtered_by_all_types = FALSE; + } + + if (!childGetValue("check_gesture")) + { + filter &= ~(0x1 << LLInventoryType::IT_GESTURE); + filtered_by_all_types = FALSE; + } + + if (!childGetValue("check_landmark")) + + + { + filter &= ~(0x1 << LLInventoryType::IT_LANDMARK); + filtered_by_all_types = FALSE; + } + + if (!childGetValue("check_notecard")) + { + filter &= ~(0x1 << LLInventoryType::IT_NOTECARD); + filtered_by_all_types = FALSE; + } + + if (!childGetValue("check_object")) + { + filter &= ~(0x1 << LLInventoryType::IT_OBJECT); + filter &= ~(0x1 << LLInventoryType::IT_ATTACHMENT); + filtered_by_all_types = FALSE; + } + + if (!childGetValue("check_script")) + { + filter &= ~(0x1 << LLInventoryType::IT_LSL); + filtered_by_all_types = FALSE; + } + + if (!childGetValue("check_sound")) + { + filter &= ~(0x1 << LLInventoryType::IT_SOUND); + filtered_by_all_types = FALSE; + } + + if (!childGetValue("check_texture")) + { + filter &= ~(0x1 << LLInventoryType::IT_TEXTURE); + filtered_by_all_types = FALSE; + } + + if (!childGetValue("check_snapshot")) + { + filter &= ~(0x1 << LLInventoryType::IT_SNAPSHOT); + filtered_by_all_types = FALSE; + } + + if (!filtered_by_all_types) + { + // don't include folders in filter, unless I've selected everything + filter &= ~(0x1 << LLInventoryType::IT_CATEGORY); + } + + // update the panel, panel will update the filter + mFloaterInventory->mActivePanel->setShowFolderState(getCheckShowEmpty() ? + LLInventoryFilter::SHOW_ALL_FOLDERS : LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS); + mFloaterInventory->mActivePanel->setFilterTypes(filter); + if (getCheckSinceLogoff()) + { + mSpinSinceDays->set(0); + mSpinSinceHours->set(0); + } + U32 days = (U32)mSpinSinceDays->get(); + U32 hours = (U32)mSpinSinceHours->get(); + if (hours > 24) + { + days += hours / 24; + hours = (U32)hours % 24; + mSpinSinceDays->set((F32)days); + mSpinSinceHours->set((F32)hours); + } + hours += days * 24; + mFloaterInventory->mActivePanel->setHoursAgo(hours); + mFloaterInventory->mActivePanel->setSinceLogoff(getCheckSinceLogoff()); + mFloaterInventory->setFilterTextFromFilter(); + + LLFloater::draw(); +} + +void LLFloaterInventoryFinder::onClose(bool app_quitting) +{ + gSavedSettings.setBOOL("Inventory.ShowFilters", FALSE); + // If you want to reset the filter on close, do it here. This functionality was + // hotly debated - Paulm +#if 0 + if (mFloaterInventory) + { + LLFloaterInventory::onResetFilter((void *)mFloaterInventory); + } +#endif + destroy(); +} + + +BOOL LLFloaterInventoryFinder::getCheckShowEmpty() +{ + return childGetValue("check_show_empty"); +} + +BOOL LLFloaterInventoryFinder::getCheckSinceLogoff() +{ + return childGetValue("check_since_logoff"); +} + +void LLFloaterInventoryFinder::onCloseBtn(void* user_data) +{ + LLFloaterInventoryFinder* finderp = (LLFloaterInventoryFinder*)user_data; + finderp->closeFloater(); +} + +// static +void LLFloaterInventoryFinder::selectAllTypes(void* user_data) +{ + LLFloaterInventoryFinder* self = (LLFloaterInventoryFinder*)user_data; + if(!self) return; + + self->childSetValue("check_animation", TRUE); + self->childSetValue("check_calling_card", TRUE); + self->childSetValue("check_clothing", TRUE); + self->childSetValue("check_gesture", TRUE); + self->childSetValue("check_landmark", TRUE); + self->childSetValue("check_notecard", TRUE); + self->childSetValue("check_object", TRUE); + self->childSetValue("check_script", TRUE); + self->childSetValue("check_sound", TRUE); + self->childSetValue("check_texture", TRUE); + self->childSetValue("check_snapshot", TRUE); + +/* + self->mCheckCallingCard->set(TRUE); + self->mCheckClothing->set(TRUE); + self->mCheckGesture->set(TRUE); + self->mCheckLandmark->set(TRUE); + self->mCheckNotecard->set(TRUE); + self->mCheckObject->set(TRUE); + self->mCheckScript->set(TRUE); + self->mCheckSound->set(TRUE); + self->mCheckTexture->set(TRUE); + self->mCheckSnapshot->set(TRUE);*/ +} + +//static +void LLFloaterInventoryFinder::selectNoTypes(void* user_data) +{ + LLFloaterInventoryFinder* self = (LLFloaterInventoryFinder*)user_data; + if(!self) return; + + /* + self->childSetValue("check_animation", FALSE); + self->mCheckCallingCard->set(FALSE); + self->mCheckClothing->set(FALSE); + self->mCheckGesture->set(FALSE); + self->mCheckLandmark->set(FALSE); + self->mCheckNotecard->set(FALSE); + self->mCheckObject->set(FALSE); + self->mCheckScript->set(FALSE); + self->mCheckSound->set(FALSE); + self->mCheckTexture->set(FALSE); + self->mCheckSnapshot->set(FALSE);*/ + + + self->childSetValue("check_animation", FALSE); + self->childSetValue("check_calling_card", FALSE); + self->childSetValue("check_clothing", FALSE); + self->childSetValue("check_gesture", FALSE); + self->childSetValue("check_landmark", FALSE); + self->childSetValue("check_notecard", FALSE); + self->childSetValue("check_object", FALSE); + self->childSetValue("check_script", FALSE); + self->childSetValue("check_sound", FALSE); + self->childSetValue("check_texture", FALSE); + self->childSetValue("check_snapshot", FALSE); +} + + +///---------------------------------------------------------------------------- +/// LLFloaterInventory +///---------------------------------------------------------------------------- +void LLSaveFolderState::setApply(BOOL apply) +{ + mApply = apply; + // before generating new list of open folders, clear the old one + if(!apply) + { + clearOpenFolders(); + } +} + +void LLSaveFolderState::doFolder(LLFolderViewFolder* folder) +{ + LLMemType mt(LLMemType::MTYPE_INVENTORY_DO_FOLDER); + if(mApply) + { + // we're applying the open state + LLInvFVBridge* bridge = (LLInvFVBridge*)folder->getListener(); + if(!bridge) return; + LLUUID id(bridge->getUUID()); + if(mOpenFolders.find(id) != mOpenFolders.end()) + { + folder->setOpen(TRUE); + } + else + { + // keep selected filter in its current state, this is less jarring to user + if (!folder->isSelected()) + { + folder->setOpen(FALSE); + } + } + } + else + { + // we're recording state at this point + if(folder->isOpen()) + { + LLInvFVBridge* bridge = (LLInvFVBridge*)folder->getListener(); + if(!bridge) return; + mOpenFolders.insert(bridge->getUUID()); + } + } +} + +LLFloaterInventory::LLFloaterInventory(const LLSD& key) + : LLFloater(key) +{ + LLMemType mt(LLMemType::MTYPE_INVENTORY_VIEW_INIT); + // Menu Callbacks (non contex menus) + mCommitCallbackRegistrar.add("Inventory.DoToSelected", boost::bind(&LLFloaterInventory::doToSelected, this, _2)); + mCommitCallbackRegistrar.add("Inventory.CloseAllFolders", boost::bind(&LLFloaterInventory::closeAllFolders, this)); + mCommitCallbackRegistrar.add("Inventory.EmptyTrash", boost::bind(&LLInventoryModel::emptyFolderType, &gInventory, "ConfirmEmptyTrash", LLAssetType::AT_TRASH)); + mCommitCallbackRegistrar.add("Inventory.EmptyLostAndFound", boost::bind(&LLInventoryModel::emptyFolderType, &gInventory, "ConfirmEmptyLostAndFound", LLAssetType::AT_LOST_AND_FOUND)); + mCommitCallbackRegistrar.add("Inventory.DoCreate", boost::bind(&LLFloaterInventory::doCreate, this, _2)); + mCommitCallbackRegistrar.add("Inventory.NewWindow", boost::bind(&LLFloaterInventory::newWindow, this)); + mCommitCallbackRegistrar.add("Inventory.ShowFilters", boost::bind(&LLFloaterInventory::toggleFindOptions, this)); + mCommitCallbackRegistrar.add("Inventory.ResetFilters", boost::bind(&LLFloaterInventory::resetFilters, this)); + mCommitCallbackRegistrar.add("Inventory.SetSortBy", boost::bind(&LLFloaterInventory::setSortBy, this, _2)); + + // Controls + // *TODO: Just use persistant settings for each of these + U32 sort_order = gSavedSettings.getU32("InventorySortOrder"); + BOOL sort_by_name = ! ( sort_order & LLInventoryFilter::SO_DATE ); + BOOL sort_folders_by_name = ( sort_order & LLInventoryFilter::SO_FOLDERS_BY_NAME ); + BOOL sort_system_folders_to_top = ( sort_order & LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP ); + + gSavedSettings.declareBOOL("Inventory.ShowFilters", FALSE, "Declared in code", FALSE); + gSavedSettings.declareBOOL("Inventory.SortByName", sort_by_name, "Declared in code", FALSE); + gSavedSettings.declareBOOL("Inventory.SortByDate", !sort_by_name, "Declared in code", FALSE); + gSavedSettings.declareBOOL("Inventory.FoldersAlwaysByName", sort_folders_by_name, "Declared in code", FALSE); + gSavedSettings.declareBOOL("Inventory.SystemFoldersToTop", sort_system_folders_to_top, "Declared in code", FALSE); + + mSavedFolderState = new LLSaveFolderState(); + mSavedFolderState->setApply(FALSE); + + //Called from floater reg: LLUICtrlFactory::getInstance()->buildFloater(this, "floater_inventory.xml"); +} + +BOOL LLFloaterInventory::postBuild() +{ + gInventory.addObserver(this); + + mFilterTabs = getChild<LLTabContainer>("inventory filter tabs"); + mFilterTabs->setCommitCallback(boost::bind(&LLFloaterInventory::onFilterSelected, this)); + + //panel->getFilter()->markDefault(); + + // Set up the default inv. panel/filter settings. + mActivePanel = getChild<LLInventoryPanel>("All Items"); + if (mActivePanel) + { + // "All Items" is the previous only view, so it gets the InventorySortOrder + mActivePanel->setSortOrder(gSavedSettings.getU32("InventorySortOrder")); + mActivePanel->getFilter()->markDefault(); + mActivePanel->getRootFolder()->applyFunctorRecursively(*mSavedFolderState); + mActivePanel->setSelectCallback(boost::bind(&LLInventoryPanel::onSelectionChange, mActivePanel, _1, _2)); + } + LLInventoryPanel* recent_items_panel = getChild<LLInventoryPanel>("Recent Items"); + if (recent_items_panel) + { + recent_items_panel->setSinceLogoff(TRUE); + recent_items_panel->setSortOrder(LLInventoryFilter::SO_DATE); + recent_items_panel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS); + recent_items_panel->getFilter()->markDefault(); + recent_items_panel->setSelectCallback(boost::bind(&LLInventoryPanel::onSelectionChange, recent_items_panel, _1, _2)); + } + + // Now load the stored settings from disk, if available. + std::ostringstream filterSaveName; + filterSaveName << gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "filters.xml"); + llinfos << "LLFloaterInventory::init: reading from " << filterSaveName << llendl; + llifstream file(filterSaveName.str()); + LLSD savedFilterState; + if (file.is_open()) + { + LLSDSerialize::fromXML(savedFilterState, file); + file.close(); + + // Load the persistent "Recent Items" settings. + // Note that the "All Items" settings do not persist. + if(recent_items_panel) + { + if(savedFilterState.has(recent_items_panel->getFilter()->getName())) + { + LLSD recent_items = savedFilterState.get( + recent_items_panel->getFilter()->getName()); + recent_items_panel->getFilter()->fromLLSD(recent_items); + } + } + + } + + + mSearchEditor = getChild<LLSearchEditor>("inventory search editor"); + if (mSearchEditor) + { + mSearchEditor->setSearchCallback(boost::bind(&LLFloaterInventory::onSearchEdit, this, _1)); + } + + // *TODO:Get the cost info from the server + const std::string upload_cost("10"); + childSetLabelArg("Upload Image", "[COST]", upload_cost); + childSetLabelArg("Upload Sound", "[COST]", upload_cost); + childSetLabelArg("Upload Animation", "[COST]", upload_cost); + childSetLabelArg("Bulk Upload", "[COST]", upload_cost); + + return TRUE; +} + +// Destroys the object +LLFloaterInventory::~LLFloaterInventory( void ) +{ + // Save the filters state. + LLSD filterRoot; + LLInventoryPanel* all_items_panel = getChild<LLInventoryPanel>("All Items"); + if (all_items_panel) + { + LLInventoryFilter* filter = all_items_panel->getFilter(); + LLSD filterState; + filter->toLLSD(filterState); + filterRoot[filter->getName()] = filterState; + } + + LLInventoryPanel* recent_items_panel = getChild<LLInventoryPanel>("Recent Items"); + if (recent_items_panel) + { + LLInventoryFilter* filter = recent_items_panel->getFilter(); + LLSD filterState; + filter->toLLSD(filterState); + filterRoot[filter->getName()] = filterState; + } + + std::ostringstream filterSaveName; + filterSaveName << gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "filters.xml"); + llofstream filtersFile(filterSaveName.str()); + if(!LLSDSerialize::toPrettyXML(filterRoot, filtersFile)) + { + llwarns << "Could not write to filters save file " << filterSaveName << llendl; + } + else + filtersFile.close(); + + gInventory.removeObserver(this); + delete mSavedFolderState; +} + +void LLFloaterInventory::draw() +{ + if (LLInventoryModel::isEverythingFetched()) + { + LLLocale locale(LLLocale::USER_LOCALE); + std::ostringstream title; + //title << "Inventory"; + title<<getString("Title"); + std::string item_count_string; + LLResMgr::getInstance()->getIntegerString(item_count_string, gInventory.getItemCount()); + title << " (" << item_count_string << getString("Items")<<")"; + //TODO:: Translate mFilterText + title << mFilterText; + setTitle(title.str()); + } + if (mActivePanel && mSearchEditor) + { + mSearchEditor->setText(mActivePanel->getFilterSubString()); + } + LLFloater::draw(); +} + +void LLOpenFilteredFolders::doItem(LLFolderViewItem *item) +{ + if (item->getFiltered()) + { + item->getParentFolder()->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP); + } +} + +void LLOpenFilteredFolders::doFolder(LLFolderViewFolder* folder) +{ + if (folder->getFiltered() && folder->getParentFolder()) + { + folder->getParentFolder()->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP); + } + // if this folder didn't pass the filter, and none of its descendants did + else if (!folder->getFiltered() && !folder->hasFilteredDescendants()) + { + folder->setOpenArrangeRecursively(FALSE, LLFolderViewFolder::RECURSE_NO); + } +} + +void LLSelectFirstFilteredItem::doItem(LLFolderViewItem *item) +{ + if (item->getFiltered() && !mItemSelected) + { + item->getRoot()->setSelection(item, FALSE, FALSE); + if (item->getParentFolder()) + { + item->getParentFolder()->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP); + } + item->getRoot()->scrollToShowSelection(); + mItemSelected = TRUE; + } +} + +void LLSelectFirstFilteredItem::doFolder(LLFolderViewFolder* folder) +{ + if (folder->getFiltered() && !mItemSelected) + { + folder->getRoot()->setSelection(folder, FALSE, FALSE); + if (folder->getParentFolder()) + { + folder->getParentFolder()->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP); + } + folder->getRoot()->scrollToShowSelection(); + mItemSelected = TRUE; + } +} + +void LLOpenFoldersWithSelection::doItem(LLFolderViewItem *item) +{ + if (item->getParentFolder() && item->isSelected()) + { + item->getParentFolder()->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP); + } +} + +void LLOpenFoldersWithSelection::doFolder(LLFolderViewFolder* folder) +{ + if (folder->getParentFolder() && folder->isSelected()) + { + folder->getParentFolder()->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP); + } +} + +void LLFloaterInventory::startSearch() +{ + // this forces focus to line editor portion of search editor + if (mSearchEditor) + { + mSearchEditor->focusFirstItem(TRUE); + } +} + +// virtual, from LLView +void LLFloaterInventory::setVisible( BOOL visible ) +{ + LLFloater::setVisible(visible); +} + +void LLFloaterInventory::onOpen(const LLSD& key) +{ + LLFirstUse::useInventory(); +} + +// Destroy all but the last floater, which is made invisible. +void LLFloaterInventory::onClose(bool app_quitting) +{ + if (getKey().asInteger() != 0) + { + destroy(); + } + else + { + // clear filters, but save user's folder state first + if (!mActivePanel->getRootFolder()->isFilterModified()) + { + mSavedFolderState->setApply(FALSE); + mActivePanel->getRootFolder()->applyFunctorRecursively(*mSavedFolderState); + } + setVisible(FALSE); + } +} + +BOOL LLFloaterInventory::handleKeyHere(KEY key, MASK mask) +{ + LLFolderView* root_folder = mActivePanel ? mActivePanel->getRootFolder() : NULL; + if (root_folder) + { + // first check for user accepting current search results + if (mSearchEditor + && mSearchEditor->hasFocus() + && (key == KEY_RETURN + || key == KEY_DOWN) + && mask == MASK_NONE) + { + // move focus to inventory proper + mActivePanel->setFocus(TRUE); + root_folder->scrollToShowSelection(); + return TRUE; + } + + if (mActivePanel->hasFocus() && key == KEY_UP) + { + startSearch(); + } + } + + return LLFloater::handleKeyHere(key, mask); + +} + +void LLFloaterInventory::changed(U32 mask) +{ + std::ostringstream title; + //title << "Inventory"; + title<<getString("Title"); + if (LLInventoryModel::backgroundFetchActive()) + { + LLLocale locale(LLLocale::USER_LOCALE); + std::string item_count_string; + LLResMgr::getInstance()->getIntegerString(item_count_string, gInventory.getItemCount()); + title << " ( "<< getString("Fetched") << item_count_string << getString("Items")<<")"; + } + //TODO:: Translate mFilterText + title << mFilterText; + setTitle(title.str()); + +} + +//static +LLFloaterInventory* LLFloaterInventory::newInstance() +{ + LLMemType mt(LLMemType::MTYPE_INVENTORY_VIEW_SHOW); + static S32 inst_count = 1; + return LLFloaterReg::getTypedInstance<LLFloaterInventory>("inventory", LLSD(inst_count++)); +} + +//---------------------------------------------------------------------------- +// menu callbacks + +void LLFloaterInventory::doToSelected(const LLSD& userdata) +{ + getPanel()->getRootFolder()->doToSelected(&gInventory, userdata); +} + +void LLFloaterInventory::closeAllFolders() +{ + getPanel()->getRootFolder()->closeAllFolders(); +} + +void LLFloaterInventory::doCreate(const LLSD& userdata) +{ + menu_create_inventory_item(getPanel()->getRootFolder(), NULL, userdata); +} + +void LLFloaterInventory::newWindow() +{ + LLFloaterInventory* iv = newInstance(); + iv->getActivePanel()->setFilterTypes(getActivePanel()->getFilterTypes()); + iv->getActivePanel()->setFilterSubString(getActivePanel()->getFilterSubString()); + iv->openFloater(); + + // force onscreen + gFloaterView->adjustToFitScreen(iv, FALSE); +} + +void LLFloaterInventory::resetFilters() +{ + LLFloaterInventoryFinder *finder = getFinder(); + getActivePanel()->getFilter()->resetDefault(); + if (finder) + { + finder->updateElementsFromFilter(); + } + + setFilterTextFromFilter(); +} + +void LLFloaterInventory::setSortBy(const LLSD& userdata) +{ + std::string sort_field = userdata.asString(); + if (sort_field == "name") + { + U32 order = getActivePanel()->getSortOrder(); + getActivePanel()->setSortOrder( order & ~LLInventoryFilter::SO_DATE ); + + gSavedSettings.setBOOL("Inventory.SortByName", TRUE ); + gSavedSettings.setBOOL("Inventory.SortByDate", FALSE ); + } + else if (sort_field == "date") + { + U32 order = getActivePanel()->getSortOrder(); + getActivePanel()->setSortOrder( order | LLInventoryFilter::SO_DATE ); + + gSavedSettings.setBOOL("Inventory.SortByName", FALSE ); + gSavedSettings.setBOOL("Inventory.SortByDate", TRUE ); + } + else if (sort_field == "foldersalwaysbyname") + { + U32 order = getActivePanel()->getSortOrder(); + if ( order & LLInventoryFilter::SO_FOLDERS_BY_NAME ) + { + order &= ~LLInventoryFilter::SO_FOLDERS_BY_NAME; + + gSavedSettings.setBOOL("Inventory.FoldersAlwaysByName", FALSE ); + } + else + { + order |= LLInventoryFilter::SO_FOLDERS_BY_NAME; + + gSavedSettings.setBOOL("Inventory.FoldersAlwaysByName", TRUE ); + } + getActivePanel()->setSortOrder( order ); + } + else if (sort_field == "systemfolderstotop") + { + U32 order = getActivePanel()->getSortOrder(); + if ( order & LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP ) + { + order &= ~LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP; + + gSavedSettings.setBOOL("Inventory.SystemFoldersToTop", FALSE ); + } + else + { + order |= LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP; + + gSavedSettings.setBOOL("Inventory.SystemFoldersToTop", TRUE ); + } + getActivePanel()->setSortOrder( order ); + } +} + +//---------------------------------------------------------------------------- + +// static +LLFloaterInventory* LLFloaterInventory::showAgentInventory() +{ + LLFloaterInventory* iv = NULL; + if (!gAgent.cameraMouselook()) + { + iv = LLFloaterReg::showTypedInstance<LLFloaterInventory>("inventory", LLSD()); + } + return iv; +} + +// static +LLFloaterInventory* LLFloaterInventory::getActiveInventory() +{ + LLFloaterInventory* res = NULL; + LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("inventory"); + S32 z_min = S32_MAX; + for (LLFloaterReg::const_instance_list_t::const_iterator iter = inst_list.begin(); iter != inst_list.end(); ++iter) + { + LLFloaterInventory* iv = dynamic_cast<LLFloaterInventory*>(*iter); + if (iv) + { + S32 z_order = gFloaterView->getZOrder(iv); + if (z_order < z_min) + { + res = iv; + z_min = z_order; + } + } + } + return res; +} + +// static +void LLFloaterInventory::cleanup() +{ + LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("inventory"); + for (LLFloaterReg::const_instance_list_t::const_iterator iter = inst_list.begin(); iter != inst_list.end();) + { + LLFloaterInventory* iv = dynamic_cast<LLFloaterInventory*>(*iter++); + if (iv) + { + iv->destroy(); + } + } +} + +void LLFloaterInventory::toggleFindOptions() +{ + LLMemType mt(LLMemType::MTYPE_INVENTORY_VIEW_TOGGLE); + LLFloater *floater = getFinder(); + if (!floater) + { + LLFloaterInventoryFinder * finder = new LLFloaterInventoryFinder(this); + mFinderHandle = finder->getHandle(); + finder->openFloater(); + addDependentFloater(mFinderHandle); + + // start background fetch of folders + gInventory.startBackgroundFetch(); + + gSavedSettings.setBOOL("Inventory.ShowFilters", TRUE); + } + else + { + floater->closeFloater(); + + gSavedSettings.setBOOL("Inventory.ShowFilters", FALSE); + } +} + +// static +BOOL LLFloaterInventory::filtersVisible(void* user_data) +{ + LLFloaterInventory* self = (LLFloaterInventory*)user_data; + if(!self) return FALSE; + + return self->getFinder() != NULL; +} + +void LLFloaterInventory::onClearSearch() +{ + LLFloater *finder = getFinder(); + if (mActivePanel) + { + mActivePanel->setFilterSubString(LLStringUtil::null); + mActivePanel->setFilterTypes(0xffffffff); + } + + if (finder) + { + LLFloaterInventoryFinder::selectAllTypes(finder); + } + + // re-open folders that were initially open + if (mActivePanel) + { + mSavedFolderState->setApply(TRUE); + mActivePanel->getRootFolder()->applyFunctorRecursively(*mSavedFolderState); + LLOpenFoldersWithSelection opener; + mActivePanel->getRootFolder()->applyFunctorRecursively(opener); + mActivePanel->getRootFolder()->scrollToShowSelection(); + } +} + +void LLFloaterInventory::onSearchEdit(const std::string& search_string ) +{ + if (search_string == "") + { + onClearSearch(); + } + if (!mActivePanel) + { + return; + } + + gInventory.startBackgroundFetch(); + + std::string filter_text = search_string; + std::string uppercase_search_string = filter_text; + LLStringUtil::toUpper(uppercase_search_string); + if (mActivePanel->getFilterSubString().empty() && uppercase_search_string.empty()) + { + // current filter and new filter empty, do nothing + return; + } + + // save current folder open state if no filter currently applied + if (!mActivePanel->getRootFolder()->isFilterModified()) + { + mSavedFolderState->setApply(FALSE); + mActivePanel->getRootFolder()->applyFunctorRecursively(*mSavedFolderState); + } + + // set new filter string + mActivePanel->setFilterSubString(uppercase_search_string); +} + + + //static + BOOL LLFloaterInventory::incrementalFind(LLFolderViewItem* first_item, const char *find_text, BOOL backward) + { + LLFloaterInventory* active_view = NULL; + + LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("inventory"); + for (LLFloaterReg::const_instance_list_t::const_iterator iter = inst_list.begin(); iter != inst_list.end(); ++iter) + { + LLFloaterInventory* iv = dynamic_cast<LLFloaterInventory*>(*iter); + if (iv) + { + if (gFocusMgr.childHasKeyboardFocus(iv)) + { + active_view = iv; + break; + } + } + } + + if (!active_view) + { + return FALSE; + } + + std::string search_string(find_text); + + if (search_string.empty()) + { + return FALSE; + } + + if (active_view->mActivePanel && + active_view->mActivePanel->getRootFolder()->search(first_item, search_string, backward)) + { + return TRUE; + } + + return FALSE; + } + +void LLFloaterInventory::onFilterSelected() +{ + // Find my index + mActivePanel = (LLInventoryPanel*)childGetVisibleTab("inventory filter tabs"); + + if (!mActivePanel) + { + return; + } + LLInventoryFilter* filter = mActivePanel->getFilter(); + LLFloaterInventoryFinder *finder = getFinder(); + if (finder) + { + finder->changeFilter(filter); + } + if (filter->isActive()) + { + // If our filter is active we may be the first thing requiring a fetch so we better start it here. + gInventory.startBackgroundFetch(); + } + setFilterTextFromFilter(); +} + +BOOL LLFloaterInventory::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg) +{ + // Check to see if we are auto scrolling from the last frame + LLInventoryPanel* panel = (LLInventoryPanel*)this->getActivePanel(); + BOOL needsToScroll = panel->getScrollableContainer()->needsToScroll(x, y, LLScrollContainer::VERTICAL); + if(mFilterTabs) + { + if(needsToScroll) + { + mFilterTabs->startDragAndDropDelayTimer(); + } + } + + BOOL handled = LLFloater::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg); + + return handled; +} +const std::string& get_item_icon_name(LLAssetType::EType asset_type, + LLInventoryType::EType inventory_type, + U32 attachment_point, + BOOL item_is_multi ) +{ + EInventoryIcon idx = OBJECT_ICON_NAME; + if ( item_is_multi ) + { + idx = OBJECT_MULTI_ICON_NAME; + } + + switch(asset_type) + { + case LLAssetType::AT_TEXTURE: + if(LLInventoryType::IT_SNAPSHOT == inventory_type) + { + idx = SNAPSHOT_ICON_NAME; + } + else + { + idx = TEXTURE_ICON_NAME; + } + break; + + case LLAssetType::AT_SOUND: + idx = SOUND_ICON_NAME; + break; + case LLAssetType::AT_CALLINGCARD: + if(attachment_point!= 0) + { + idx = CALLINGCARD_ONLINE_ICON_NAME; + } + else + { + idx = CALLINGCARD_OFFLINE_ICON_NAME; + } + break; + case LLAssetType::AT_LANDMARK: + if(attachment_point!= 0) + { + idx = LANDMARK_VISITED_ICON_NAME; + } + else + { + idx = LANDMARK_ICON_NAME; + } + break; + case LLAssetType::AT_SCRIPT: + case LLAssetType::AT_LSL_TEXT: + case LLAssetType::AT_LSL_BYTECODE: + idx = SCRIPT_ICON_NAME; + break; + case LLAssetType::AT_CLOTHING: + idx = CLOTHING_ICON_NAME; + case LLAssetType::AT_BODYPART : + if(LLAssetType::AT_BODYPART == asset_type) + { + idx = BODYPART_ICON_NAME; + } + switch(LLInventoryItem::II_FLAGS_WEARABLES_MASK & attachment_point) + { + case WT_SHAPE: + idx = BODYPART_SHAPE_ICON_NAME; + break; + case WT_SKIN: + idx = BODYPART_SKIN_ICON_NAME; + break; + case WT_HAIR: + idx = BODYPART_HAIR_ICON_NAME; + break; + case WT_EYES: + idx = BODYPART_EYES_ICON_NAME; + break; + case WT_SHIRT: + idx = CLOTHING_SHIRT_ICON_NAME; + break; + case WT_PANTS: + idx = CLOTHING_PANTS_ICON_NAME; + break; + case WT_SHOES: + idx = CLOTHING_SHOES_ICON_NAME; + break; + case WT_SOCKS: + idx = CLOTHING_SOCKS_ICON_NAME; + break; + case WT_JACKET: + idx = CLOTHING_JACKET_ICON_NAME; + break; + case WT_GLOVES: + idx = CLOTHING_GLOVES_ICON_NAME; + break; + case WT_UNDERSHIRT: + idx = CLOTHING_UNDERSHIRT_ICON_NAME; + break; + case WT_UNDERPANTS: + idx = CLOTHING_UNDERPANTS_ICON_NAME; + break; + case WT_SKIRT: + idx = CLOTHING_SKIRT_ICON_NAME; + break; + case WT_ALPHA: + idx = CLOTHING_ALPHA_ICON_NAME; + break; + case WT_TATTOO: + idx = CLOTHING_TATTOO_ICON_NAME; + break; + default: + // no-op, go with choice above + break; + } + break; + case LLAssetType::AT_NOTECARD: + idx = NOTECARD_ICON_NAME; + break; + case LLAssetType::AT_ANIMATION: + idx = ANIMATION_ICON_NAME; + break; + case LLAssetType::AT_GESTURE: + idx = GESTURE_ICON_NAME; + break; + case LLAssetType::AT_FAVORITE: + //TODO - need bette idx + idx = LANDMARK_ICON_NAME; + break; + default: + break; + } + + return ICON_NAME[idx]; +} + +LLUIImagePtr get_item_icon(LLAssetType::EType asset_type, + LLInventoryType::EType inventory_type, + U32 attachment_point, + BOOL item_is_multi) +{ + const std::string& icon_name = get_item_icon_name(asset_type, inventory_type, attachment_point, item_is_multi ); + return LLUI::getUIImage(icon_name); +} + +const std::string LLInventoryPanel::DEFAULT_SORT_ORDER = std::string("InventorySortOrder"); +const std::string LLInventoryPanel::RECENTITEMS_SORT_ORDER = std::string("RecentItemsSortOrder"); +const std::string LLInventoryPanel::INHERIT_SORT_ORDER = std::string(""); + +LLInventoryPanel::LLInventoryPanel(const LLInventoryPanel::Params& p) +: LLPanel(p), + mInventoryObserver(NULL), + mFolders(NULL), + mScroller(NULL), + mSortOrderSetting(p.sort_order_setting), + mInventory(p.inventory), + mAllowMultiSelect(p.allow_multi_select) +{ + // contex menu callbacks + mCommitCallbackRegistrar.add("Inventory.DoToSelected", boost::bind(&LLInventoryPanel::doToSelected, this, _2)); + mCommitCallbackRegistrar.add("Inventory.EmptyTrash", boost::bind(&LLInventoryModel::emptyFolderType, &gInventory, "ConfirmEmptyTrash", LLAssetType::AT_TRASH)); + mCommitCallbackRegistrar.add("Inventory.EmptyLostAndFound", boost::bind(&LLInventoryModel::emptyFolderType, &gInventory, "ConfirmEmptyLostAndFound", LLAssetType::AT_LOST_AND_FOUND)); + mCommitCallbackRegistrar.add("Inventory.DoCreate", boost::bind(&LLInventoryPanel::doCreate, this, _2)); + mCommitCallbackRegistrar.add("Inventory.AttachObject", boost::bind(&LLInventoryPanel::attachObject, this, _2)); + mCommitCallbackRegistrar.add("Inventory.BeginIMSession", boost::bind(&LLInventoryPanel::beginIMSession, this)); + + setBackgroundColor(LLUIColorTable::instance().getColor("InventoryBackgroundColor")); + setBackgroundVisible(TRUE); + setBackgroundOpaque(TRUE); +} + +BOOL LLInventoryPanel::postBuild() +{ + LLMemType mt(LLMemType::MTYPE_INVENTORY_POST_BUILD); + + mCommitCallbackRegistrar.pushScope(); // registered as a widget; need to push callback scope ourselves + + // create root folder + { + LLRect folder_rect(0, + 0, + getRect().getWidth(), + 0); + LLFolderView::Params p; + p.name = getName(); + p.rect = folder_rect; + p.parent_panel = this; + mFolders = LLUICtrlFactory::create<LLFolderView>(p); + mFolders->setAllowMultiSelect(mAllowMultiSelect); + } + + mCommitCallbackRegistrar.popScope(); + + mFolders->setCallbackRegistrar(&mCommitCallbackRegistrar); + + // scroller + { + LLRect scroller_view_rect = getRect(); + scroller_view_rect.translate(-scroller_view_rect.mLeft, -scroller_view_rect.mBottom); + LLScrollContainer::Params p; + p.name("Inventory Scroller"); + p.rect(scroller_view_rect); + p.follows.flags(FOLLOWS_ALL); + p.reserve_scroll_corner(true); + p.tab_stop(true); + mScroller = LLUICtrlFactory::create<LLScrollContainer>(p); + } + addChild(mScroller); + mScroller->addChild(mFolders); + + mFolders->setScrollContainer(mScroller); + + // set up the callbacks from the inventory we're viewing, and then + // build everything. + mInventoryObserver = new LLInventoryPanelObserver(this); + mInventory->addObserver(mInventoryObserver); + rebuildViewsFor(LLUUID::null, LLInventoryObserver::ADD); + + // bit of a hack to make sure the inventory is open. + mFolders->openFolder(std::string("My Inventory")); + + if (mSortOrderSetting != INHERIT_SORT_ORDER) + { + setSortOrder(gSavedSettings.getU32(mSortOrderSetting)); + } + else + { + setSortOrder(gSavedSettings.getU32(DEFAULT_SORT_ORDER)); + } + mFolders->setSortOrder(mFolders->getFilter()->getSortOrder()); + + return TRUE; +} + +LLInventoryPanel::~LLInventoryPanel() +{ + // should this be a global setting? + U32 sort_order = mFolders->getSortOrder(); + if (mSortOrderSetting != INHERIT_SORT_ORDER) + { + gSavedSettings.setU32(mSortOrderSetting, sort_order); + } + + // LLView destructor will take care of the sub-views. + mInventory->removeObserver(mInventoryObserver); + delete mInventoryObserver; + mScroller = NULL; +} + + LLMemType mt(LLMemType::MTYPE_INVENTORY_FROM_XML); +void LLInventoryPanel::draw() +{ + // select the desired item (in case it wasn't loaded when the selection was requested) + mFolders->updateSelection(); + LLPanel::draw(); +} + +void LLInventoryPanel::setFilterTypes(U32 filter_types) +{ + mFolders->getFilter()->setFilterTypes(filter_types); +} + +void LLInventoryPanel::setFilterPermMask(PermissionMask filter_perm_mask) +{ + mFolders->getFilter()->setFilterPermissions(filter_perm_mask); +} + +void LLInventoryPanel::setFilterSubString(const std::string& string) +{ + mFolders->getFilter()->setFilterSubString(string); +} + +void LLInventoryPanel::setSortOrder(U32 order) +{ + mFolders->getFilter()->setSortOrder(order); + if (mFolders->getFilter()->isModified()) + { + mFolders->setSortOrder(order); + // try to keep selection onscreen, even if it wasn't to start with + mFolders->scrollToShowSelection(); + } +} + +void LLInventoryPanel::setSinceLogoff(BOOL sl) +{ + mFolders->getFilter()->setDateRangeLastLogoff(sl); +} + +void LLInventoryPanel::setHoursAgo(U32 hours) +{ + mFolders->getFilter()->setHoursAgo(hours); +} + +void LLInventoryPanel::setShowFolderState(LLInventoryFilter::EFolderShow show) +{ + mFolders->getFilter()->setShowFolderState(show); +} + +LLInventoryFilter::EFolderShow LLInventoryPanel::getShowFolderState() +{ + return mFolders->getFilter()->getShowFolderState(); +} + +void LLInventoryPanel::modelChanged(U32 mask) +{ + LLFastTimer t2(LLFastTimer::FTM_REFRESH); + + bool handled = false; + if(mask & LLInventoryObserver::LABEL) + { + handled = true; + // label change - empty out the display name for each object + // in this change set. + const std::set<LLUUID>& changed_items = gInventory.getChangedIDs(); + std::set<LLUUID>::const_iterator id_it = changed_items.begin(); + std::set<LLUUID>::const_iterator id_end = changed_items.end(); + LLFolderViewItem* view = NULL; + LLInvFVBridge* bridge = NULL; + for (;id_it != id_end; ++id_it) + { + view = mFolders->getItemByID(*id_it); + if(view) + { + // request refresh on this item (also flags for filtering) + bridge = (LLInvFVBridge*)view->getListener(); + if(bridge) + { // Clear the display name first, so it gets properly re-built during refresh() + bridge->clearDisplayName(); + } + view->refresh(); + } + } + } + if((mask & (LLInventoryObserver::STRUCTURE + | LLInventoryObserver::ADD + | LLInventoryObserver::REMOVE)) != 0) + { + handled = true; + // Record which folders are open by uuid. + LLInventoryModel* model = getModel(); + if (model) + { + const std::set<LLUUID>& changed_items = gInventory.getChangedIDs(); + + std::set<LLUUID>::const_iterator id_it = changed_items.begin(); + std::set<LLUUID>::const_iterator id_end = changed_items.end(); + for (;id_it != id_end; ++id_it) + { + // sync view with model + LLInventoryObject* model_item = model->getObject(*id_it); + LLFolderViewItem* view_item = mFolders->getItemByID(*id_it); + + if (model_item) + { + if (!view_item) + { + // this object was just created, need to build a view for it + if ((mask & LLInventoryObserver::ADD) != LLInventoryObserver::ADD) + { + llwarns << *id_it << " is in model but not in view, but ADD flag not set" << llendl; + } + buildNewViews(*id_it); + + // select any newly created object + // that has the auto rename at top of folder + // root set + if(mFolders->getRoot()->needsAutoRename()) + { + setSelection(*id_it, FALSE); + } + } + else + { + // this object was probably moved, check its parent + if ((mask & LLInventoryObserver::STRUCTURE) != LLInventoryObserver::STRUCTURE) + { + llwarns << *id_it << " is in model and in view, but STRUCTURE flag not set" << llendl; + } + + LLFolderViewFolder* new_parent = (LLFolderViewFolder*)mFolders->getItemByID(model_item->getParentUUID()); + if (view_item->getParentFolder() != new_parent) + { + view_item->getParentFolder()->extractItem(view_item); + view_item->addToFolder(new_parent, mFolders); + } + } + } + else + { + if (view_item) + { + if ((mask & LLInventoryObserver::REMOVE) != LLInventoryObserver::REMOVE) + { + llwarns << *id_it << " is not in model but in view, but REMOVE flag not set" << llendl; + } + // item in view but not model, need to delete view + view_item->destroyView(); + } + else + { + llwarns << *id_it << "Item does not exist in either view or model, but notification triggered" << llendl; + } + } + } + } + } + + if (!handled) + { + // it's a small change that only requires a refresh. + // *TODO: figure out a more efficient way to do the refresh + // since it is expensive on large inventories + mFolders->refresh(); + } +} + +void LLInventoryPanel::rebuildViewsFor(const LLUUID& id, U32 mask) +{ + LLFolderViewItem* old_view = NULL; + + // get old LLFolderViewItem + old_view = mFolders->getItemByID(id); + if (old_view && id.notNull()) + { + old_view->destroyView(); + } + + buildNewViews(id); +} + +void LLInventoryPanel::buildNewViews(const LLUUID& id) +{ + LLMemType mt(LLMemType::MTYPE_INVENTORY_BUILD_NEW_VIEWS); + LLFolderViewItem* itemp = NULL; + LLInventoryObject* objectp = gInventory.getObject(id); + + if (objectp) + { + if (objectp->getType() <= LLAssetType::AT_NONE || + objectp->getType() >= LLAssetType::AT_COUNT) + { + llwarns << "LLInventoryPanel::buildNewViews called with objectp->mType == " + << ((S32) objectp->getType()) + << " (shouldn't happen)" << llendl; + } + else if (objectp->getType() == LLAssetType::AT_CATEGORY) // build new view for category + { + LLInvFVBridge* new_listener = LLInvFVBridge::createBridge(objectp->getType(), + LLInventoryType::IT_CATEGORY, + this, + objectp->getUUID()); + + if (new_listener) + { + LLFolderViewFolder::Params p; + p.name = new_listener->getDisplayName(); + p.icon = new_listener->getIcon(); + p.root = mFolders; + p.listener = new_listener; + LLFolderViewFolder* folderp = LLUICtrlFactory::create<LLFolderViewFolder>(p); + + folderp->setItemSortOrder(mFolders->getSortOrder()); + itemp = folderp; + } + } + else // build new view for item + { + LLInventoryItem* item = (LLInventoryItem*)objectp; + LLInvFVBridge* new_listener = LLInvFVBridge::createBridge( + item->getType(), + item->getInventoryType(), + this, + item->getUUID(), + item->getFlags()); + if (new_listener) + { + LLFolderViewItem::Params params; + params.name(new_listener->getDisplayName()); + params.icon(new_listener->getIcon()); + params.creation_date(new_listener->getCreationDate()); + params.root(mFolders); + params.listener(new_listener); + params.rect(LLRect (0, 0, 0, 0)); + itemp = LLUICtrlFactory::create<LLFolderViewItem> (params); + } + } + + LLFolderViewFolder* parent_folder = (LLFolderViewFolder*)mFolders->getItemByID(objectp->getParentUUID()); + + if (itemp) + { + if (parent_folder) + { + itemp->addToFolder(parent_folder, mFolders); + } + else + { + llwarns << "Couldn't find parent folder for child " << itemp->getLabel() << llendl; + delete itemp; + } + } + } + if ((id.isNull() || + (objectp && objectp->getType() == LLAssetType::AT_CATEGORY))) + { + LLViewerInventoryCategory::cat_array_t* categories; + LLViewerInventoryItem::item_array_t* items; + + mInventory->lockDirectDescendentArrays(id, categories, items); + if(categories) + { + S32 count = categories->count(); + for(S32 i = 0; i < count; ++i) + { + LLInventoryCategory* cat = categories->get(i); + buildNewViews(cat->getUUID()); + } + } + if(items) + { + S32 count = items->count(); + for(S32 i = 0; i < count; ++i) + { + LLInventoryItem* item = items->get(i); + buildNewViews(item->getUUID()); + } + } + mInventory->unlockDirectDescendentArrays(id); + } +} + +struct LLConfirmPurgeData +{ + LLUUID mID; + LLInventoryModel* mModel; +}; + +class LLIsNotWorn : public LLInventoryCollectFunctor +{ +public: + LLIsNotWorn() {} + virtual ~LLIsNotWorn() {} + virtual bool operator()(LLInventoryCategory* cat, + LLInventoryItem* item) + { + return !gAgentWearables.isWearingItem(item->getUUID()); + } +}; + +class LLOpenFolderByID : public LLFolderViewFunctor +{ +public: + LLOpenFolderByID(const LLUUID& id) : mID(id) {} + virtual ~LLOpenFolderByID() {} + virtual void doFolder(LLFolderViewFolder* folder) + { + if (folder->getListener() && folder->getListener()->getUUID() == mID) folder->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP); + } + virtual void doItem(LLFolderViewItem* item) {} +protected: + const LLUUID& mID; +}; + + +void LLInventoryPanel::openSelected() +{ + LLFolderViewItem* folder_item = mFolders->getCurSelectedItem(); + if(!folder_item) return; + LLInvFVBridge* bridge = (LLInvFVBridge*)folder_item->getListener(); + if(!bridge) return; + bridge->openItem(); +} + +BOOL LLInventoryPanel::handleHover(S32 x, S32 y, MASK mask) +{ + BOOL handled = LLView::handleHover(x, y, mask); + if(handled) + { + ECursorType cursor = getWindow()->getCursor(); + if (LLInventoryModel::backgroundFetchActive() && cursor == UI_CURSOR_ARROW) + { + // replace arrow cursor with arrow and hourglass cursor + getWindow()->setCursor(UI_CURSOR_WORKING); + } + } + else + { + getWindow()->setCursor(UI_CURSOR_ARROW); + } + return TRUE; +} + +BOOL LLInventoryPanel::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg) +{ + + BOOL handled = LLPanel::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg); + + if (handled) + { + mFolders->setDragAndDropThisFrame(); + } + + return handled; +} + +void LLInventoryPanel::onFocusLost() +{ + // inventory no longer handles cut/copy/paste/delete + if (LLEditMenuHandler::gEditMenuHandler == mFolders) + { + LLEditMenuHandler::gEditMenuHandler = NULL; + } + + LLPanel::onFocusLost(); +} + +void LLInventoryPanel::onFocusReceived() +{ + // inventory now handles cut/copy/paste/delete + LLEditMenuHandler::gEditMenuHandler = mFolders; + + LLPanel::onFocusReceived(); +} + + +void LLInventoryPanel::openAllFolders() +{ + mFolders->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_DOWN); + mFolders->arrangeAll(); +} + +void LLInventoryPanel::openDefaultFolderForType(LLAssetType::EType type) +{ + LLUUID category_id = mInventory->findCategoryUUIDForType(type); + LLOpenFolderByID opener(category_id); + mFolders->applyFunctorRecursively(opener); +} + +void LLInventoryPanel::setSelection(const LLUUID& obj_id, BOOL take_keyboard_focus) +{ + mFolders->setSelectionByID(obj_id, take_keyboard_focus); +} + +void LLInventoryPanel::clearSelection() +{ + mFolders->clearSelection(); +} + +void LLInventoryPanel::onSelectionChange(const std::deque<LLFolderViewItem*>& items, BOOL user_action) +{ + LLFolderView* fv = getRootFolder(); + if (fv->needsAutoRename()) // auto-selecting a new user-created asset and preparing to rename + { + fv->setNeedsAutoRename(FALSE); + if (items.size()) // new asset is visible and selected + { + fv->startRenamingSelectedItem(); + } + } +} + +//---------------------------------------------------------------------------- + +void LLInventoryPanel::doToSelected(const LLSD& userdata) +{ + mFolders->doToSelected(&gInventory, userdata); +} + +void LLInventoryPanel::doCreate(const LLSD& userdata) +{ + menu_create_inventory_item(mFolders, LLFolderBridge::sSelf, userdata); +} + +bool LLInventoryPanel::beginIMSession() +{ + std::set<LLUUID> selected_items; + mFolders->getSelectionList(selected_items); + + std::string name; + static int session_num = 1; + + LLDynamicArray<LLUUID> members; + EInstantMessage type = IM_SESSION_CONFERENCE_START; + + std::set<LLUUID>::const_iterator iter; + for (iter = selected_items.begin(); iter != selected_items.end(); iter++) + { + + LLUUID item = *iter; + LLFolderViewItem* folder_item = mFolders->getItemByID(item); + + if(folder_item) + { + LLFolderViewEventListener* fve_listener = folder_item->getListener(); + if (fve_listener && (fve_listener->getInventoryType() == LLInventoryType::IT_CATEGORY)) + { + + LLFolderBridge* bridge = (LLFolderBridge*)folder_item->getListener(); + if(!bridge) return true; + LLViewerInventoryCategory* cat = bridge->getCategory(); + if(!cat) return true; + name = cat->getName(); + LLUniqueBuddyCollector is_buddy; + LLInventoryModel::cat_array_t cat_array; + LLInventoryModel::item_array_t item_array; + gInventory.collectDescendentsIf(bridge->getUUID(), + cat_array, + item_array, + LLInventoryModel::EXCLUDE_TRASH, + is_buddy); + S32 count = item_array.count(); + if(count > 0) + { + LLFloaterReg::showInstance("communicate"); + // create the session + LLAvatarTracker& at = LLAvatarTracker::instance(); + LLUUID id; + for(S32 i = 0; i < count; ++i) + { + id = item_array.get(i)->getCreatorUUID(); + if(at.isBuddyOnline(id)) + { + members.put(id); + } + } + } + } + else + { + LLFolderViewItem* folder_item = mFolders->getItemByID(item); + if(!folder_item) return true; + LLInvFVBridge* listenerp = (LLInvFVBridge*)folder_item->getListener(); + + if (listenerp->getInventoryType() == LLInventoryType::IT_CALLINGCARD) + { + LLInventoryItem* inv_item = gInventory.getItem(listenerp->getUUID()); + + if (inv_item) + { + LLAvatarTracker& at = LLAvatarTracker::instance(); + LLUUID id = inv_item->getCreatorUUID(); + + if(at.isBuddyOnline(id)) + { + members.put(id); + } + } + } //if IT_CALLINGCARD + } //if !IT_CATEGORY + } + } //for selected_items + + // the session_id is randomly generated UUID which will be replaced later + // with a server side generated number + + if (name.empty()) + { + name = llformat("Session %d", session_num++); + } + + gIMMgr->addSession(name, type, members[0], members); + + return true; +} + +bool LLInventoryPanel::attachObject(const LLSD& userdata) +{ + std::set<LLUUID> selected_items; + mFolders->getSelectionList(selected_items); + LLUUID id = *selected_items.begin(); + + std::string joint_name = userdata.asString(); + LLVOAvatar *avatarp = static_cast<LLVOAvatar*>(gAgent.getAvatarObject()); + LLViewerJointAttachment* attachmentp = NULL; + for (LLVOAvatar::attachment_map_t::iterator iter = avatarp->mAttachmentPoints.begin(); + iter != avatarp->mAttachmentPoints.end(); ) + { + LLVOAvatar::attachment_map_t::iterator curiter = iter++; + LLViewerJointAttachment* attachment = curiter->second; + if (attachment->getName() == joint_name) + { + attachmentp = attachment; + break; + } + } + if (attachmentp == NULL) + { + return true; + } + LLViewerInventoryItem* item = (LLViewerInventoryItem*)gInventory.getItem(id); + + if(item && gInventory.isObjectDescendentOf(id, gInventory.getRootFolderID())) + { + rez_attachment(item, attachmentp); + } + else if(item && item->isComplete()) + { + // must be in library. copy it to our inventory and put it on. + LLPointer<LLInventoryCallback> cb = new RezAttachmentCallback(attachmentp); + copy_inventory_item(gAgent.getID(), + item->getPermissions().getOwner(), + item->getUUID(), + LLUUID::null, + std::string(), + cb); + } + gFocusMgr.setKeyboardFocus(NULL); + + return true; +} + + +//---------------------------------------------------------------------------- + +// static DEBUG ONLY: +void LLInventoryPanel::dumpSelectionInformation(void* user_data) +{ + LLInventoryPanel* iv = (LLInventoryPanel*)user_data; + iv->mFolders->dumpSelectionInformation(); +} + +BOOL LLInventoryPanel::getSinceLogoff() +{ + return mFolders->getFilter()->isSinceLogoff(); +} + +void example_param_block_usage() +{ + LLInventoryPanel::Params param_block; + param_block.name(std::string("inventory")); + + param_block.sort_order_setting(LLInventoryPanel::RECENTITEMS_SORT_ORDER); + param_block.allow_multi_select(true); + param_block.filter(LLInventoryPanel::Filter() + .sort_order(1) + .types(0xffff0000)); + param_block.inventory(&gInventory); + param_block.has_border(true); + + LLUICtrlFactory::create<LLInventoryPanel>(param_block); + + param_block = LLInventoryPanel::Params(); + param_block.name(std::string("inventory")); + + //LLSD param_block_sd; + //param_block_sd["sort_order_setting"] = LLInventoryPanel::RECENTITEMS_SORT_ORDER; + //param_block_sd["allow_multi_select"] = true; + //param_block_sd["filter"]["sort_order"] = 1; + //param_block_sd["filter"]["types"] = (S32)0xffff0000; + //param_block_sd["has_border"] = true; + + //LLInitParam::LLSDParser(param_block_sd).parse(param_block); + + LLUICtrlFactory::create<LLInventoryPanel>(param_block); +} diff --git a/indra/newview/llfloaterinventory.h b/indra/newview/llfloaterinventory.h new file mode 100644 index 0000000000000000000000000000000000000000..cd604075072ca10b01f46359986a74f5301bb24a --- /dev/null +++ b/indra/newview/llfloaterinventory.h @@ -0,0 +1,369 @@ +/** + * @file llfloaterinventory.h + * @brief LLFloaterInventory, LLInventoryFolder, and LLInventoryItem + * class definition + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLINVENTORYVIEW_H +#define LL_LLINVENTORYVIEW_H + +#include "llassetstorage.h" +#include "lldarray.h" +#include "llfloater.h" +#include "llinventory.h" +#include "llinventoryfilter.h" +#include "llfolderview.h" +#include "llinventorymodel.h" +#include "lluictrlfactory.h" +#include <set> + + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Class LLFloaterInventory +// +// This is the agent inventory _floater_. +// It deals with the buttons and views used to navigate as +// well as controls the behavior of the overall object. +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class LLFolderViewItem; +class LLInventoryFilter; +class LLInventoryModel; +class LLInvFVBridge; +class LLMenuBarGL; +class LLCheckBoxCtrl; +class LLSpinCtrl; +class LLScrollContainer; +class LLTextBox; +class LLIconCtrl; +class LLSaveFolderState; +class LLSearchEditor; +class LLTabContainer; + +class LLInventoryPanel : public LLPanel +{ +public: + static const std::string DEFAULT_SORT_ORDER; + static const std::string RECENTITEMS_SORT_ORDER; + static const std::string INHERIT_SORT_ORDER; + + struct Filter : public LLInitParam::Block<Filter> + { + Optional<U32> sort_order; + Optional<U32> types; + Optional<std::string> search_string; + + Filter() + : sort_order("sort_order"), + types("types", 0xffffffff), + search_string("search_string") + {} + }; + + struct Params + : public LLInitParam::Block<Params, LLPanel::Params> + { + Optional<std::string> sort_order_setting; + Optional<LLInventoryModel*> inventory; + Optional<bool> allow_multi_select; + Optional<Filter> filter; + + Params() + : sort_order_setting("sort_order_setting"), + inventory("", &gInventory), + allow_multi_select("allow_multi_select", true), + filter("filter") + {} + }; + +protected: + LLInventoryPanel(const Params&); + friend class LLUICtrlFactory; + +public: + ~LLInventoryPanel(); + + LLInventoryModel* getModel() { return mInventory; } + + BOOL postBuild(); + + // LLView methods + void draw(); + BOOL handleHover(S32 x, S32 y, MASK mask); + BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg); + // LLUICtrl methods + /*virtual*/ void onFocusLost(); + /*virtual*/ void onFocusReceived(); + + // Call this method to set the selection. + void openAllFolders(); + void openDefaultFolderForType(LLAssetType::EType); + void setSelection(const LLUUID& obj_id, BOOL take_keyboard_focus); + void setSelectCallback(const LLFolderView::signal_t::slot_type& cb) { if (mFolders) mFolders->setSelectCallback(cb); } + void clearSelection(); + LLInventoryFilter* getFilter() { return mFolders->getFilter(); } + void setFilterTypes(U32 filter); + U32 getFilterTypes() const { return mFolders->getFilterTypes(); } + void setFilterPermMask(PermissionMask filter_perm_mask); + U32 getFilterPermMask() const { return mFolders->getFilterPermissions(); } + void setFilterSubString(const std::string& string); + const std::string getFilterSubString() { return mFolders->getFilterSubString(); } + void setSortOrder(U32 order); + U32 getSortOrder() { return mFolders->getSortOrder(); } + void setSinceLogoff(BOOL sl); + void setHoursAgo(U32 hours); + BOOL getSinceLogoff(); + + void setShowFolderState(LLInventoryFilter::EFolderShow show); + LLInventoryFilter::EFolderShow getShowFolderState(); + void setAllowMultiSelect(BOOL allow) { mFolders->setAllowMultiSelect(allow); } + // This method is called when something has changed about the inventory. + void modelChanged(U32 mask); + LLFolderView* getRootFolder() { return mFolders; } + LLScrollContainer* getScrollableContainer() { return mScroller; } + + void onSelectionChange(const std::deque<LLFolderViewItem*> &items, BOOL user_action); + + // Callbacks + void doToSelected(const LLSD& userdata); + void doCreate(const LLSD& userdata); + bool beginIMSession(); + bool attachObject(const LLSD& userdata); + + // DEBUG ONLY: + static void dumpSelectionInformation(void* user_data); + + void openSelected(); + void unSelectAll() { mFolders->setSelection(NULL, FALSE, FALSE); } + +protected: + // Given the id and the parent, build all of the folder views. + void rebuildViewsFor(const LLUUID& id, U32 mask); + void buildNewViews(const LLUUID& id); + +protected: + LLInventoryModel* mInventory; + LLInventoryObserver* mInventoryObserver; + LLFolderView* mFolders; + LLScrollContainer* mScroller; + BOOL mAllowMultiSelect; + std::string mSortOrderSetting; +}; + +class LLFloaterInventory; + +class LLFloaterInventoryFinder : public LLFloater +{ +public: + LLFloaterInventoryFinder( LLFloaterInventory* inventory_view); + virtual void draw(); + virtual void onClose(bool app_quitting); + /*virtual*/ BOOL postBuild(); + void changeFilter(LLInventoryFilter* filter); + void updateElementsFromFilter(); + BOOL getCheckShowEmpty(); + BOOL getCheckSinceLogoff(); + + static void onTimeAgo(LLUICtrl*, void *); + static void onCheckSinceLogoff(LLUICtrl*, void *); + static void onCloseBtn(void* user_data); + static void selectAllTypes(void* user_data); + static void selectNoTypes(void* user_data); + +protected: + LLFloaterInventory* mFloaterInventory; + LLSpinCtrl* mSpinSinceDays; + LLSpinCtrl* mSpinSinceHours; + LLInventoryFilter* mFilter; +}; + +class LLFloaterInventory : public LLFloater, LLInventoryObserver +{ +friend class LLFloaterInventoryFinder; + +public: + LLFloaterInventory(const LLSD& key); + ~LLFloaterInventory(); + + /*virtual*/ void changed(U32 mask); + + BOOL postBuild(); + + // + // Misc functions + // + void setFilterTextFromFilter() { mFilterText = mActivePanel->getFilter()->getFilterText(); } + void startSearch(); + + // Spawn a new inventory view + static LLFloaterInventory* newInstance(); + + // This method makes sure that an inventory view exists, is + // visible, and has focus. The view chosen is returned. + static LLFloaterInventory* showAgentInventory(); + + // Return the active inventory view if there is one. Active is + // defined as the inventory that is the closest to the front, and + // is visible. + static LLFloaterInventory* getActiveInventory(); + + // This method calls showAgentInventory() if no views are visible, + // or hides/destroyes them all if any are visible. + static void toggleVisibility(); + static void toggleVisibility(void*) { toggleVisibility(); } + + // Final cleanup, destroy all open inventory views. + static void cleanup(); + + // LLView & LLFloater functionality + virtual void onOpen(const LLSD& key); + virtual void onClose(bool app_quitting); + virtual void setVisible(BOOL visible); + virtual void draw(); + virtual BOOL handleKeyHere(KEY key, MASK mask); + + BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg); + + + LLInventoryPanel* getPanel() { return mActivePanel; } + LLInventoryPanel* getActivePanel() { return mActivePanel; } + + static BOOL filtersVisible(void* user_data); + void onClearSearch(); + static void onFoldersByName(void *user_data); + static BOOL checkFoldersByName(void *user_data); + void onSearchEdit(const std::string& search_string ); + static BOOL incrementalFind(LLFolderViewItem* first_item, const char *find_text, BOOL backward); + void onFilterSelected(); + + const std::string getFilterSubString() { return mActivePanel->getFilterSubString(); } + void setFilterSubString(const std::string& string) { mActivePanel->setFilterSubString(string); } + + // menu callbacks + void doToSelected(const LLSD& userdata); + void closeAllFolders(); + void doCreate(const LLSD& userdata); + void newWindow(); + void resetFilters(); + void setSortBy(const LLSD& userdata); + + // HACK: Until we can route this info through the instant message hierarchy + static BOOL sWearNewClothing; + static LLUUID sWearNewClothingTransactionID; // wear all clothing in this transaction + + void toggleFindOptions(); + + LLFloaterInventoryFinder* getFinder() { return (LLFloaterInventoryFinder*)mFinderHandle.get(); } + +protected: + LLSearchEditor* mSearchEditor; + LLTabContainer* mFilterTabs; + LLHandle<LLFloater> mFinderHandle; + LLInventoryPanel* mActivePanel; + LLSaveFolderState* mSavedFolderState; + + std::string mFilterText; +}; + +class LLSelectFirstFilteredItem : public LLFolderViewFunctor +{ +public: + LLSelectFirstFilteredItem() : mItemSelected(FALSE) {} + virtual ~LLSelectFirstFilteredItem() {} + virtual void doFolder(LLFolderViewFolder* folder); + virtual void doItem(LLFolderViewItem* item); + BOOL wasItemSelected() { return mItemSelected; } +protected: + BOOL mItemSelected; +}; + +class LLOpenFilteredFolders : public LLFolderViewFunctor +{ +public: + LLOpenFilteredFolders() {} + virtual ~LLOpenFilteredFolders() {} + virtual void doFolder(LLFolderViewFolder* folder); + virtual void doItem(LLFolderViewItem* item); +}; + +class LLSaveFolderState : public LLFolderViewFunctor +{ +public: + LLSaveFolderState() : mApply(FALSE) {} + virtual ~LLSaveFolderState() {} + virtual void doFolder(LLFolderViewFolder* folder); + virtual void doItem(LLFolderViewItem* item) {} + void setApply(BOOL apply); + void clearOpenFolders() { mOpenFolders.clear(); } +protected: + std::set<LLUUID> mOpenFolders; + BOOL mApply; +}; + +class LLOpenFoldersWithSelection : public LLFolderViewFunctor +{ +public: + LLOpenFoldersWithSelection() {} + virtual ~LLOpenFoldersWithSelection() {} + virtual void doFolder(LLFolderViewFolder* folder); + virtual void doItem(LLFolderViewItem* item); +}; + +///---------------------------------------------------------------------------- +/// Function declarations, constants, enums, and typedefs +///---------------------------------------------------------------------------- + +// useful functions with the inventory view + +class LLInventoryCategory; +class LLInventoryItem; + +const std::string& get_item_icon_name(LLAssetType::EType asset_type, + LLInventoryType::EType inventory_type, + U32 attachment_point, + BOOL item_is_multi ); + +LLUIImagePtr get_item_icon(LLAssetType::EType asset_type, + LLInventoryType::EType inventory_type, + U32 attachment_point, + BOOL item_is_multi ); + +#endif // LL_LLINVENTORYVIEW_H + + + diff --git a/indra/newview/llfloaterjoystick.cpp b/indra/newview/llfloaterjoystick.cpp index c73218cd0f287a550f44e4b37ffe2223461a714a..06fe2a84c8908d05000d928aa5196373540589b8 100644 --- a/indra/newview/llfloaterjoystick.cpp +++ b/indra/newview/llfloaterjoystick.cpp @@ -48,7 +48,7 @@ #include "llcheckboxctrl.h" LLFloaterJoystick::LLFloaterJoystick(const LLSD& data) - : LLFloater() + : LLFloater(data) { //Called from floater reg: LLUICtrlFactory::getInstance()->buildFloater(this, "floater_joystick.xml"); diff --git a/indra/newview/llfloaterjoystick.h b/indra/newview/llfloaterjoystick.h index 9c66b3a8952f74152206238e9322410b6c9c6619..f3559c28e9e3e1914046000c7ef6b45687997409 100644 --- a/indra/newview/llfloaterjoystick.h +++ b/indra/newview/llfloaterjoystick.h @@ -38,11 +38,11 @@ class LLCheckBoxCtrl; -class LLFloaterJoystick : public LLFloater, public LLFloaterSingleton<LLFloaterJoystick > +class LLFloaterJoystick : public LLFloater { + friend class LLFloaterReg; + public: - LLFloaterJoystick(const LLSD& data); - virtual ~LLFloaterJoystick(); virtual BOOL postBuild(); virtual void refresh(); @@ -52,6 +52,10 @@ public: static void setSNDefaults(); private: + + LLFloaterJoystick(const LLSD& data); + virtual ~LLFloaterJoystick(); + static void onCommitJoystickEnabled(LLUICtrl*, void*); static void onClickRestoreSNDefaults(void*); static void onClickCancel(void*); diff --git a/indra/newview/llfloaterlagmeter.cpp b/indra/newview/llfloaterlagmeter.cpp index 82deaef4a9bc86026e34ae262a4f6d6f17655e20..262102b820e472858843095ea2bd51e023a58b13 100644 --- a/indra/newview/llfloaterlagmeter.cpp +++ b/indra/newview/llfloaterlagmeter.cpp @@ -51,7 +51,7 @@ const std::string LAG_WARNING_IMAGE_NAME = "lag_status_warning.tga"; const std::string LAG_GOOD_IMAGE_NAME = "lag_status_good.tga"; LLFloaterLagMeter::LLFloaterLagMeter(const LLSD& key) - : LLFloater() + : LLFloater(key) { // LLUICtrlFactory::getInstance()->buildFloater(this, "floater_lagmeter.xml"); mCommitCallbackRegistrar.add("LagMeter.ClickShrink", boost::bind(&LLFloaterLagMeter::onClickShrink, this)); diff --git a/indra/newview/llfloaterlagmeter.h b/indra/newview/llfloaterlagmeter.h index 6d2086839efb879c7b74083ba62fe82d355f32e9..592630636a1c91876f93f282075dc4ce3295300a 100644 --- a/indra/newview/llfloaterlagmeter.h +++ b/indra/newview/llfloaterlagmeter.h @@ -37,18 +37,17 @@ class LLTextBox; -class LLFloaterLagMeter : public LLFloater, public LLFloaterSingleton<LLFloaterLagMeter> +class LLFloaterLagMeter : public LLFloater { - friend class LLUISingleton<LLFloaterLagMeter, VisibilityPolicy<LLFloater> >; + friend class LLFloaterReg; public: - LLFloaterLagMeter(const LLSD& key); - /*virtual*/ ~LLFloaterLagMeter(); - /*virtual*/ void draw(); /*virtual*/ BOOL postBuild(); private: - + + LLFloaterLagMeter(const LLSD& key); + /*virtual*/ ~LLFloaterLagMeter(); void determineClient(); void determineNetwork(); void determineServer(); diff --git a/indra/newview/llfloaterland.cpp b/indra/newview/llfloaterland.cpp index f3275913e4c600d7ca3509d87d89dc808a7f2d5e..039873691df13b720b7a094d55ba2849391ce9ea 100644 --- a/indra/newview/llfloaterland.cpp +++ b/indra/newview/llfloaterland.cpp @@ -149,23 +149,50 @@ void send_parcel_select_objects(S32 parcel_local_id, S32 return_type, //static LLPanelLandObjects* LLFloaterLand::getCurrentPanelLandObjects() { - return LLFloaterLand::getInstance()->mPanelObjects; + LLFloaterLand* land_instance = LLFloaterReg::getTypedInstance<LLFloaterLand>("about_land"); + if(land_instance) + { + return land_instance->mPanelObjects; + } + else + { + return NULL; + } } //static LLPanelLandCovenant* LLFloaterLand::getCurrentPanelLandCovenant() { - return LLFloaterLand::getInstance()->mPanelCovenant; + LLFloaterLand* land_instance = LLFloaterReg::getTypedInstance<LLFloaterLand>("about_land"); + if(land_instance) + { + return land_instance->mPanelCovenant; + } + else + { + return NULL; + } } // static void LLFloaterLand::refreshAll() { - LLFloaterLand::getInstance()->refresh(); + LLFloaterLand* land_instance = LLFloaterReg::getTypedInstance<LLFloaterLand>("about_land"); + if(land_instance) + { + land_instance->refresh(); + } } void LLFloaterLand::onOpen(const LLSD& key) { + // moved from triggering show instance in llviwermenu.cpp + + if (LLViewerParcelMgr::getInstance()->selectionEmpty()) + { + LLViewerParcelMgr::getInstance()->selectParcelAt(gAgent.getPositionGlobal()); + } + // Done automatically when the selected parcel's properties arrive // (and hence we have the local id). // LLViewerParcelMgr::getInstance()->sendParcelAccessListRequest(AL_ACCESS | AL_BAN | AL_RENTER); @@ -196,7 +223,7 @@ void LLFloaterLand::onClose(bool app_quitting) LLFloaterLand::LLFloaterLand(const LLSD& seed) -: LLFloater() +: LLFloater(seed) { mFactoryMap["land_general_panel"] = LLCallbackMap(createPanelLandGeneral, this); mFactoryMap["land_covenant_panel"] = LLCallbackMap(createPanelLandCovenant, this); @@ -205,7 +232,7 @@ LLFloaterLand::LLFloaterLand(const LLSD& seed) mFactoryMap["land_media_panel"] = LLCallbackMap(createPanelLandMedia, this); mFactoryMap["land_access_panel"] = LLCallbackMap(createPanelLandAccess, this); - LLUICtrlFactory::getInstance()->buildFloater(this, "floater_about_land.xml", false); + //LLUICtrlFactory::getInstance()->buildFloater(this, "floater_about_land.xml", false); sObserver = new LLParcelSelectionObserver(); LLViewerParcelMgr::getInstance()->addObserver( sObserver ); diff --git a/indra/newview/llfloaterland.h b/indra/newview/llfloaterland.h index 74c1205e1f0cdb6ab9ccd75784faed78eb00ad7d..ee49da3f05c78a4e8d13c0c0fb62f48332cfa819 100644 --- a/indra/newview/llfloaterland.h +++ b/indra/newview/llfloaterland.h @@ -71,9 +71,9 @@ class LLPanelLandRenters; class LLPanelLandCovenant; class LLFloaterLand -: public LLFloater, public LLFloaterSingleton<LLFloaterLand> +: public LLFloater { - friend class LLUISingleton<LLFloaterLand, VisibilityPolicy<LLFloater> >; + friend class LLFloaterReg; public: static void refreshAll(); @@ -85,13 +85,14 @@ public: virtual void onOpen(const LLSD& key); virtual BOOL postBuild(); -protected: - +private: // Does its own instance management, so clients not allowed // to allocate or destroy. LLFloaterLand(const LLSD& seed); virtual ~LLFloaterLand(); +protected: + /*virtual*/ void refresh(); static void* createPanelLandGeneral(void* data); diff --git a/indra/newview/llfloaterlandholdings.cpp b/indra/newview/llfloaterlandholdings.cpp index 223cca50b28c4d77105604fca6e584482518115b..fbefd40c608fe4a04eedb28f2f0f6f9d9a31a887 100644 --- a/indra/newview/llfloaterlandholdings.cpp +++ b/indra/newview/llfloaterlandholdings.cpp @@ -292,15 +292,16 @@ void LLFloaterLandHoldings::buttonCore(S32 which) F64 global_z = gAgent.getPositionGlobal().mdV[VZ]; LLVector3d pos_global(global_x, global_y, global_z); + LLFloaterWorldMap* floater_world_map = LLFloaterWorldMap::getInstance(); switch(which) { case 0: gAgent.teleportViaLocation(pos_global); - LLFloaterWorldMap::getInstance()->trackLocation(pos_global); + if(floater_world_map) floater_world_map->trackLocation(pos_global); break; case 1: - LLFloaterWorldMap::getInstance()->trackLocation(pos_global); + if(floater_world_map) floater_world_map->trackLocation(pos_global); LLFloaterReg::showInstance("world_map", "center"); break; default: diff --git a/indra/newview/llfloatermap.cpp b/indra/newview/llfloatermap.cpp index 6660650c56d8d1211fd7b09c1c66e2bf0709d223..f9fc467c05375174ad5f1bebe2a5ef3fa1a73878 100644 --- a/indra/newview/llfloatermap.cpp +++ b/indra/newview/llfloatermap.cpp @@ -94,7 +94,7 @@ BOOL LLFloaterMap::postBuild() registrar.add("Minimap.Zoom", boost::bind(&LLFloaterMap::handleZoom, this, _2)); registrar.add("Minimap.Tracker", boost::bind(&LLFloaterMap::handleStopTracking, this, _2)); - mPopupMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_minimap.xml", gMenuHolder); + mPopupMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_minimap.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); if (mPopupMenu && !LLTracker::isTracking(0)) { mPopupMenu->setItemEnabled ("Stop Tracking", false); diff --git a/indra/newview/llfloatermemleak.cpp b/indra/newview/llfloatermemleak.cpp index 3f2fcc26db8038892b89c304874e1e4650b6eef6..529bd68e03725b7c6b5919cdfdbd45debca70587 100644 --- a/indra/newview/llfloatermemleak.cpp +++ b/indra/newview/llfloatermemleak.cpp @@ -42,26 +42,56 @@ #include "llmath.h" #include "llviewerwindow.h" -LLFloaterMemLeak* LLFloaterMemLeak::sInstance = NULL; U32 LLFloaterMemLeak::sMemLeakingSpeed = 0 ; //bytes leaked per frame U32 LLFloaterMemLeak::sMaxLeakedMem = 0 ; //maximum allowed leaked memory U32 LLFloaterMemLeak::sTotalLeaked = 0 ; S32 LLFloaterMemLeak::sStatus = LLFloaterMemLeak::STOP ; BOOL LLFloaterMemLeak::sbAllocationFailed = FALSE ; -LLFloaterMemLeak::LLFloaterMemLeak() - : LLFloater() +LLFloaterMemLeak::LLFloaterMemLeak(const LLSD& key) + : LLFloater(key) { setTitle("Memory Leaking Simulation Floater"); + mCommitCallbackRegistrar.add("MemLeak.ChangeLeakingSpeed", boost::bind(&LLFloaterMemLeak::onChangeLeakingSpeed, this)); + mCommitCallbackRegistrar.add("MemLeak.ChangeMaxMemLeaking", boost::bind(&LLFloaterMemLeak::onChangeMaxMemLeaking, this)); + mCommitCallbackRegistrar.add("MemLeak.Start", boost::bind(&LLFloaterMemLeak::onClickStart, this)); + mCommitCallbackRegistrar.add("MemLeak.Stop", boost::bind(&LLFloaterMemLeak::onClickStop, this)); + mCommitCallbackRegistrar.add("MemLeak.Release", boost::bind(&LLFloaterMemLeak::onClickRelease, this)); + mCommitCallbackRegistrar.add("MemLeak.Close", boost::bind(&LLFloaterMemLeak::onClickClose, this)); } +//---------------------------------------------- +BOOL LLFloaterMemLeak::postBuild(void) +{ + F32 a, b ; + a = childGetValue("leak_speed").asReal(); + if(a > (F32)(0xFFFFFFFF)) + { + sMemLeakingSpeed = 0xFFFFFFFF ; + } + else + { + sMemLeakingSpeed = (U32)a ; + } + b = childGetValue("max_leak").asReal(); + if(b > (F32)0xFFF) + { + sMaxLeakedMem = 0xFFFFFFFF ; + } + else + { + sMaxLeakedMem = ((U32)b) << 20 ; + } + + sbAllocationFailed = FALSE ; + return TRUE ; +} LLFloaterMemLeak::~LLFloaterMemLeak() { release() ; sMemLeakingSpeed = 0 ; //bytes leaked per frame sMaxLeakedMem = 0 ; //maximum allowed leaked memory - sInstance = NULL ; } void LLFloaterMemLeak::release() @@ -117,79 +147,56 @@ void LLFloaterMemLeak::idle() } //---------------------- -void LLFloaterMemLeak::onChangeLeakingSpeed(LLUICtrl* ctrl, void* userData) +void LLFloaterMemLeak::onChangeLeakingSpeed() { - LLFloaterMemLeak *mem_leak = (LLFloaterMemLeak *)userData; - if (mem_leak) - { - F32 tmp ; - tmp = mem_leak->childGetValue("leak_speed").asReal(); + F32 tmp ; + tmp =childGetValue("leak_speed").asReal(); - if(tmp > (F32)0xFFFFFFFF) - { - sMemLeakingSpeed = 0xFFFFFFFF ; - } - else - { - sMemLeakingSpeed = (U32)tmp ; - } + if(tmp > (F32)0xFFFFFFFF) + { + sMemLeakingSpeed = 0xFFFFFFFF ; } + else + { + sMemLeakingSpeed = (U32)tmp ; + } + } -void LLFloaterMemLeak::onChangeMaxMemLeaking(LLUICtrl* ctrl, void* userData) +void LLFloaterMemLeak::onChangeMaxMemLeaking() { - LLFloaterMemLeak *mem_leak = (LLFloaterMemLeak *)userData; - if (mem_leak) + + F32 tmp ; + tmp =childGetValue("max_leak").asReal(); + if(tmp > (F32)0xFFF) { - F32 tmp ; - tmp = mem_leak->childGetValue("max_leak").asReal(); - if(tmp > (F32)0xFFF) - { - sMaxLeakedMem = 0xFFFFFFFF ; - } - else - { - sMaxLeakedMem = ((U32)tmp) << 20 ; - } + sMaxLeakedMem = 0xFFFFFFFF ; } + else + { + sMaxLeakedMem = ((U32)tmp) << 20 ; + } + } -void LLFloaterMemLeak::onClickStart(void* userData) +void LLFloaterMemLeak::onClickStart() { sStatus = START ; } -void LLFloaterMemLeak::onClickStop(void* userData) +void LLFloaterMemLeak::onClickStop() { sStatus = STOP ; } -void LLFloaterMemLeak::onClickRelease(void* userData) +void LLFloaterMemLeak::onClickRelease() { sStatus = RELEASE ; } -void LLFloaterMemLeak::onClickClose(void* userData) -{ - if (sInstance) - { - sInstance->setVisible(FALSE); - } -} - -//---------------------------------------------- - -BOOL LLFloaterMemLeak::postBuild(void) +void LLFloaterMemLeak::onClickClose() { - childSetCommitCallback("leak_speed", onChangeLeakingSpeed, this); - childSetCommitCallback("max_leak", onChangeMaxMemLeaking, this); - - childSetAction("start_btn", onClickStart, this); - childSetAction("stop_btn", onClickStop, this); - childSetAction("release_btn", onClickRelease, this); - childSetAction("close_btn", onClickClose, this); - - return TRUE ; + setVisible(FALSE); } void LLFloaterMemLeak::draw() @@ -219,50 +226,3 @@ void LLFloaterMemLeak::draw() LLFloater::draw(); } - -// static instance of it -LLFloaterMemLeak* LLFloaterMemLeak::instance() -{ - if (!sInstance) - { - sInstance = new LLFloaterMemLeak(); - LLUICtrlFactory::getInstance()->buildFloater(sInstance, "floater_mem_leaking.xml", FALSE); - - if(sInstance) - { - F32 a, b ; - a = sInstance->childGetValue("leak_speed").asReal(); - if(a > (F32)(0xFFFFFFFF)) - { - sMemLeakingSpeed = 0xFFFFFFFF ; - } - else - { - sMemLeakingSpeed = (U32)a ; - } - b = sInstance->childGetValue("max_leak").asReal(); - if(b > (F32)0xFFF) - { - sMaxLeakedMem = 0xFFFFFFFF ; - } - else - { - sMaxLeakedMem = ((U32)b) << 20 ; - } - - sbAllocationFailed = FALSE ; - } - } - return sInstance ; -} - -void LLFloaterMemLeak::show(void*) -{ - instance()->openFloater(); -} - -LLFloaterMemLeak* LLFloaterMemLeak::getInstance() -{ - return sInstance ; -} - diff --git a/indra/newview/llfloatermemleak.h b/indra/newview/llfloatermemleak.h index 7d9d5f9c5f09916c808c271b34e16a71b72ae582..763af943ba173fe23237299d2033c6fff4385b4c 100644 --- a/indra/newview/llfloatermemleak.h +++ b/indra/newview/llfloatermemleak.h @@ -37,34 +37,28 @@ class LLFloaterMemLeak : public LLFloater { + friend class LLFloaterReg; public: - LLFloaterMemLeak(); - virtual ~LLFloaterMemLeak(); - /// initialize all the callbacks for the menu - //void initCallbacks(void); + virtual BOOL postBuild() ; virtual void draw() ; - - /// one and one instance only - static LLFloaterMemLeak* instance(); - static void onChangeLeakingSpeed(LLUICtrl* ctrl, void* userData); - static void onChangeMaxMemLeaking(LLUICtrl* ctrl, void* userData); - static void onClickStart(void* userData); - static void onClickStop(void* userData); - static void onClickRelease(void* userData); - static void onClickClose(void* userData); - - /// show off our menu - static void show(void*); + void onChangeLeakingSpeed(); + void onChangeMaxMemLeaking(); + void onClickStart(); + void onClickStop(); + void onClickRelease(); + void onClickClose(); public: - static LLFloaterMemLeak* getInstance() ; void idle() ; void stop() ; private: + + LLFloaterMemLeak(const LLSD& key); + virtual ~LLFloaterMemLeak(); void release() ; private: @@ -75,9 +69,6 @@ private: START } ; - // one instance on the inside - static LLFloaterMemLeak* sInstance; - static U32 sMemLeakingSpeed ; //bytes leaked per frame static U32 sMaxLeakedMem ; //maximum allowed leaked memory static U32 sTotalLeaked ; diff --git a/indra/newview/llfloaternotificationsconsole.cpp b/indra/newview/llfloaternotificationsconsole.cpp index 3d5d2b733f88a739cb5ac6165e97e8b9c433cee4..f06af5ca1efaa04c9129f9ab21ade33e780a25b9 100644 --- a/indra/newview/llfloaternotificationsconsole.cpp +++ b/indra/newview/llfloaternotificationsconsole.cpp @@ -161,7 +161,7 @@ bool LLNotificationChannelPanel::update(const LLSD& payload, bool passed_filter) // LLFloaterNotificationConsole // LLFloaterNotificationConsole::LLFloaterNotificationConsole(const LLSD& key) -: LLFloater() +: LLFloater(key) { mCommitCallbackRegistrar.add("ClickAdd", boost::bind(&LLFloaterNotificationConsole::onClickAdd, this)); diff --git a/indra/newview/llfloaternotificationsconsole.h b/indra/newview/llfloaternotificationsconsole.h index b85437c3c5fde739f9b204441fa4a13616cd5f8e..fe161e66f07349972dc285b584490c6e3f47757b 100644 --- a/indra/newview/llfloaternotificationsconsole.h +++ b/indra/newview/llfloaternotificationsconsole.h @@ -38,11 +38,11 @@ #include "llnotifications.h" class LLFloaterNotificationConsole : - public LLFloater, - public LLFloaterSingleton<LLFloaterNotificationConsole> + public LLFloater { + friend class LLFloaterReg; + public: - LLFloaterNotificationConsole(const LLSD& key); // LLPanel BOOL postBuild(); @@ -55,6 +55,7 @@ public: void updateResizeLimits(); private: + LLFloaterNotificationConsole(const LLSD& key); void onClickAdd(); }; diff --git a/indra/newview/llfloateropenobject.cpp b/indra/newview/llfloateropenobject.cpp index 4d782a1814c12beee5b93d38fb4f8cc1b75d3a1b..09460e41add5df601aa87c3b87f6edef52af511c 100644 --- a/indra/newview/llfloateropenobject.cpp +++ b/indra/newview/llfloateropenobject.cpp @@ -46,9 +46,10 @@ #include "llagent.h" // for agent id #include "llalertdialog.h" #include "llinventorybridge.h" -#include "llinventoryview.h" +#include "llfloaterinventory.h" #include "llinventorymodel.h" #include "llpanelinventory.h" +#include "llfloaterreg.h" #include "llselectmgr.h" #include "lluiconstants.h" #include "llviewerobject.h" @@ -56,29 +57,44 @@ #include "llviewerwindow.h" -LLFloaterOpenObject* LLFloaterOpenObject::sInstance = NULL; - -LLFloaterOpenObject::LLFloaterOpenObject() -: LLFloater(), +LLFloaterOpenObject::LLFloaterOpenObject(const LLSD& key) +: LLFloater(key), mPanelInventory(NULL), mDirty(TRUE) { - LLUICtrlFactory::getInstance()->buildFloater(this,"floater_openobject.xml"); +// LLUICtrlFactory::getInstance()->buildFloater(this,"floater_openobject.xml"); + mCommitCallbackRegistrar.add("OpenObject.MoveToInventory", boost::bind(&LLFloaterOpenObject::onClickMoveToInventory, this)); + mCommitCallbackRegistrar.add("OpenObject.MoveAndWear", boost::bind(&LLFloaterOpenObject::onClickMoveAndWear, this)); } LLFloaterOpenObject::~LLFloaterOpenObject() { - sInstance = NULL; +// sInstance = NULL; } // virtual BOOL LLFloaterOpenObject::postBuild() { - childSetAction("copy_to_inventory_button", onClickMoveToInventory, this); - childSetAction("copy_and_wear_button", onClickMoveAndWear, this); + mObjectSelection = LLSelectMgr::getInstance()->getEditSelection(); childSetTextArg("object_name", "[DESC]", std::string("Object") ); // *Note: probably do not want to translate this mPanelInventory = getChild<LLPanelInventory>("object_contents"); return TRUE; } + +void LLFloaterOpenObject::onOpen(const LLSD& key) +{ + LLObjectSelectionHandle object_selection = LLSelectMgr::getInstance()->getSelection(); + if (object_selection->getRootObjectCount() != 1) + { + LLNotifications::instance().add("UnableToViewContentsMoreThanOne"); + closeFloater(); + return; + } + if(!(object_selection->getPrimaryObject())) + { + closeFloater(); + return; + } +} void LLFloaterOpenObject::refresh() { mPanelInventory->refresh(); @@ -99,7 +115,6 @@ void LLFloaterOpenObject::refresh() } childSetTextArg("object_name", "[DESC]", name); - childSetEnabled("copy_to_inventory_button", enabled); childSetEnabled("copy_and_wear_button", enabled); @@ -115,34 +130,11 @@ void LLFloaterOpenObject::draw() LLFloater::draw(); } -// static void LLFloaterOpenObject::dirty() { - if (sInstance) sInstance->mDirty = TRUE; + mDirty = TRUE; } -// static -void LLFloaterOpenObject::show() -{ - LLObjectSelectionHandle object_selection = LLSelectMgr::getInstance()->getSelection(); - if (object_selection->getRootObjectCount() != 1) - { - LLNotifications::instance().add("UnableToViewContentsMoreThanOne"); - return; - } - - // Create a new instance only if needed - if (!sInstance) - { - sInstance = new LLFloaterOpenObject(); - sInstance->center(); - } - - sInstance->openFloater(); - sInstance->setFocus(TRUE); - - sInstance->mObjectSelection = LLSelectMgr::getInstance()->getEditSelection(); -} void LLFloaterOpenObject::moveToInventory(bool wear) @@ -170,7 +162,7 @@ void LLFloaterOpenObject::moveToInventory(bool wear) } else { - parent_category_id = gAgent.getInventoryRootID(); + parent_category_id = gInventory.getRootFolderID(); } LLUUID category_id = gInventory.createNewCategory(parent_category_id, LLAssetType::AT_NONE, @@ -201,8 +193,8 @@ void LLFloaterOpenObject::callbackMoveInventory(S32 result, void* data) if (result == 0) { - LLInventoryView::showAgentInventory(); - LLInventoryView* view = LLInventoryView::getActiveInventory(); + LLFloaterInventory::showAgentInventory(); + LLFloaterInventory* view = LLFloaterInventory::getActiveInventory(); if (view) { view->getPanel()->setSelection(cat->mCatID, TAKE_FOCUS_NO); @@ -212,20 +204,15 @@ void LLFloaterOpenObject::callbackMoveInventory(S32 result, void* data) delete cat; } - -// static -void LLFloaterOpenObject::onClickMoveToInventory(void* data) +void LLFloaterOpenObject::onClickMoveToInventory() { - LLFloaterOpenObject* self = (LLFloaterOpenObject*)data; - self->moveToInventory(false); - self->closeFloater(); + moveToInventory(false); + closeFloater(); } -// static -void LLFloaterOpenObject::onClickMoveAndWear(void* data) +void LLFloaterOpenObject::onClickMoveAndWear() { - LLFloaterOpenObject* self = (LLFloaterOpenObject*)data; - self->moveToInventory(true); - self->closeFloater(); + moveToInventory(true); + closeFloater(); } diff --git a/indra/newview/llfloateropenobject.h b/indra/newview/llfloateropenobject.h index 0097a856901df85298bfb1459438bafc3da80c26..0df3780ac45d3e7276bdffb9d84e4af4555bf5b8 100644 --- a/indra/newview/llfloateropenobject.h +++ b/indra/newview/llfloateropenobject.h @@ -46,9 +46,10 @@ class LLPanelInventory; class LLFloaterOpenObject : public LLFloater { + friend class LLFloaterReg; public: - static void show(); - static void dirty(); + + void dirty(); struct LLCatAndWear { @@ -57,20 +58,25 @@ public: }; protected: - LLFloaterOpenObject(); - ~LLFloaterOpenObject(); + /*virtual*/ BOOL postBuild(); void refresh(); void draw(); + virtual void onOpen(const LLSD& key); +// virtual void onClose(); void moveToInventory(bool wear); - static void onClickMoveToInventory(void* data); - static void onClickMoveAndWear(void* data); + void onClickMoveToInventory(); + void onClickMoveAndWear(); static void callbackMoveInventory(S32 result, void* data); +private: + + LLFloaterOpenObject(const LLSD& key); + ~LLFloaterOpenObject(); + protected: - static LLFloaterOpenObject* sInstance; LLPanelInventory* mPanelInventory; LLSafeHandle<LLObjectSelection> mObjectSelection; diff --git a/indra/newview/llfloaterperms.cpp b/indra/newview/llfloaterperms.cpp index 1ef71a9d532efe9eff743db30edd295e65cc3dde..c4f1ebe8aa409b5dfd7ca622297696ff41e6f4cf 100644 --- a/indra/newview/llfloaterperms.cpp +++ b/indra/newview/llfloaterperms.cpp @@ -42,51 +42,44 @@ LLFloaterPerms::LLFloaterPerms(const LLSD& seed) -: LLFloater() +: LLFloater(seed) { - LLUICtrlFactory::getInstance()->buildFloater(this, "floater_perm_prefs.xml"); + //LLUICtrlFactory::getInstance()->buildFloater(this, "floater_perm_prefs.xml"); + mCommitCallbackRegistrar.add("Perms.Copy", boost::bind(&LLFloaterPerms::onCommitCopy, this)); + mCommitCallbackRegistrar.add("Perms.OK", boost::bind(&LLFloaterPerms::onClickOK, this)); + mCommitCallbackRegistrar.add("Perms.Cancel", boost::bind(&LLFloaterPerms::onClickCancel, this)); + } BOOL LLFloaterPerms::postBuild() { - childSetEnabled("next_owner_transfer", gSavedSettings.getBOOL("NextOwnerCopy")); - childSetAction("help", onClickHelp, this); - childSetAction("ok", onClickOK, this); - childSetAction("cancel", onClickCancel, this); - childSetCommitCallback("next_owner_copy", &onCommitCopy, this); refresh(); return TRUE; } -//static -void LLFloaterPerms::onClickOK(void* data) +void LLFloaterPerms::onClickOK() { - LLFloaterPerms* self = static_cast<LLFloaterPerms*>(data); - self->ok(); - self->closeFloater(); + ok(); + closeFloater(); } -//static -void LLFloaterPerms::onClickCancel(void* data) +void LLFloaterPerms::onClickCancel() { - LLFloaterPerms* self = static_cast<LLFloaterPerms*>(data); - self->cancel(); - self->closeFloater(); + cancel(); + closeFloater(); } -//static -void LLFloaterPerms::onCommitCopy(LLUICtrl* ctrl, void* data) +void LLFloaterPerms::onCommitCopy() { - LLFloaterPerms* self = static_cast<LLFloaterPerms*>(data); // Implements fair use BOOL copyable = gSavedSettings.getBOOL("NextOwnerCopy"); if(!copyable) { gSavedSettings.setBOOL("NextOwnerTransfer", TRUE); } - LLCheckBoxCtrl* xfer = self->getChild<LLCheckBoxCtrl>("next_owner_transfer"); + LLCheckBoxCtrl* xfer = getChild<LLCheckBoxCtrl>("next_owner_transfer"); xfer->setEnabled(copyable); } @@ -152,9 +145,3 @@ U32 LLFloaterPerms::getNextOwnerPerms(std::string prefix) return flags; } - -//static -void LLFloaterPerms::onClickHelp(void* data) -{ - LLNotifications::instance().add("ClickUploadHelpPermissions"); -} diff --git a/indra/newview/llfloaterperms.h b/indra/newview/llfloaterperms.h index 805039efe496bff3455a6004dec9a7b20d064433..a1897a5c0028a09bd9b02d4695c31213f7f9ca91 100644 --- a/indra/newview/llfloaterperms.h +++ b/indra/newview/llfloaterperms.h @@ -36,18 +36,18 @@ #include "llfloater.h" -class LLFloaterPerms : public LLFloater, public LLFloaterSingleton<LLFloaterPerms> +class LLFloaterPerms : public LLFloater { - friend class LLUISingleton<LLFloaterPerms, VisibilityPolicy<LLFloater> >; + friend class LLFloaterReg; public: /*virtual*/ void onClose(bool app_quitting = false); /*virtual*/ BOOL postBuild(); void ok(); void cancel(); - static void onClickOK(void*); - static void onClickCancel(void*); - static void onCommitCopy(LLUICtrl* ctrl, void* data); + void onClickOK(); + void onClickCancel(); + void onCommitCopy(); // Convenience methods to get current permission preference bitfields from saved settings: static U32 getEveryonePerms(std::string prefix=""); // prefix + "EveryoneCopy" static U32 getGroupPerms(std::string prefix=""); // prefix + "ShareWithGroup" @@ -57,9 +57,6 @@ private: LLFloaterPerms(const LLSD& seed); void refresh(); - /// callback for the menus help button - static void onClickHelp(void* data); - BOOL // cached values only for implementing cancel. mShareWithGroup, mEveryoneCopy, diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp index 57a3bf9445cba12c3df5a0fa2db1133521a7ae7a..99c1414461bf902c8c79f12346c35f64540bd1e7 100644 --- a/indra/newview/llfloaterregioninfo.cpp +++ b/indra/newview/llfloaterregioninfo.cpp @@ -58,6 +58,7 @@ #include "llfloatergodtools.h" // for send_sim_wide_deletes() #include "llfloatertopobjects.h" // added to fix SL-32336 #include "llfloatergroups.h" +#include "llfloaterreg.h" #include "llfloatertelehub.h" #include "llfloaterwindlight.h" #include "llinventorymodel.h" @@ -164,9 +165,9 @@ bool estate_dispatch_initialized = false; LLUUID LLFloaterRegionInfo::sRequestInvoice; LLFloaterRegionInfo::LLFloaterRegionInfo(const LLSD& seed) - : LLFloater() + : LLFloater(seed) { - LLUICtrlFactory::getInstance()->buildFloater(this, "floater_region_info.xml", FALSE); + //LLUICtrlFactory::getInstance()->buildFloater(this, "floater_region_info.xml", FALSE); } BOOL LLFloaterRegionInfo::postBuild() @@ -247,7 +248,8 @@ void LLFloaterRegionInfo::requestRegionInfo() void LLFloaterRegionInfo::processEstateOwnerRequest(LLMessageSystem* msg,void**) { static LLDispatcher dispatch; - if(!findInstance()) + LLFloaterRegionInfo* floater = LLFloaterReg::getTypedInstance<LLFloaterRegionInfo>("region_info"); + if(!floater) { return; } @@ -257,7 +259,7 @@ void LLFloaterRegionInfo::processEstateOwnerRequest(LLMessageSystem* msg,void**) LLPanelEstateInfo::initDispatch(dispatch); } - LLTabContainer* tab = findInstance()->getChild<LLTabContainer>("region_panels"); + LLTabContainer* tab = floater->getChild<LLTabContainer>("region_panels"); LLPanelEstateInfo* panel = (LLPanelEstateInfo*)tab->getChild<LLPanel>("Estate"); // unpack the message @@ -283,14 +285,14 @@ void LLFloaterRegionInfo::processEstateOwnerRequest(LLMessageSystem* msg,void**) void LLFloaterRegionInfo::processRegionInfo(LLMessageSystem* msg) { LLPanel* panel; - + LLFloaterRegionInfo* floater = LLFloaterReg::getTypedInstance<LLFloaterRegionInfo>("region_info"); llinfos << "LLFloaterRegionInfo::processRegionInfo" << llendl; - if(!findInstance()) + if(!floater) { return; } - LLTabContainer* tab = findInstance()->getChild<LLTabContainer>("region_panels"); + LLTabContainer* tab = floater->getChild<LLTabContainer>("region_panels"); LLViewerRegion* region = gAgent.getRegion(); BOOL allow_modify = gAgent.isGodlike() || (region && region->canManageEstate()); @@ -377,13 +379,13 @@ void LLFloaterRegionInfo::processRegionInfo(LLMessageSystem* msg) panel->childSetEnabled("sun_hour_slider", allow_modify && !use_estate_sun); panel->setCtrlsEnabled(allow_modify); - getInstance()->refreshFromRegion( gAgent.getRegion() ); + floater->refreshFromRegion( gAgent.getRegion() ); } // static LLPanelEstateInfo* LLFloaterRegionInfo::getPanelEstate() { - LLFloaterRegionInfo* floater = LLFloaterRegionInfo::getInstance(); + LLFloaterRegionInfo* floater = LLFloaterReg::getTypedInstance<LLFloaterRegionInfo>("region_info"); if (!floater) return NULL; LLTabContainer* tab = floater->getChild<LLTabContainer>("region_panels"); LLPanelEstateInfo* panel = (LLPanelEstateInfo*)tab->getChild<LLPanel>("Estate"); @@ -393,7 +395,7 @@ LLPanelEstateInfo* LLFloaterRegionInfo::getPanelEstate() // static LLPanelEstateCovenant* LLFloaterRegionInfo::getPanelCovenant() { - LLFloaterRegionInfo* floater = LLFloaterRegionInfo::getInstance(); + LLFloaterRegionInfo* floater = LLFloaterReg::getTypedInstance<LLFloaterRegionInfo>("region_info"); if (!floater) return NULL; LLTabContainer* tab = floater->getChild<LLTabContainer>("region_panels"); LLPanelEstateCovenant* panel = (LLPanelEstateCovenant*)tab->getChild<LLPanel>("Covenant"); @@ -611,7 +613,8 @@ BOOL LLPanelRegionGeneralInfo::postBuild() childSetAction("kick_btn", onClickKick, this); childSetAction("kick_all_btn", onClickKickAll, this); childSetAction("im_btn", onClickMessage, this); - childSetAction("manage_telehub_btn", onClickManageTelehub, this); +// childSetAction("manage_telehub_btn", onClickManageTelehub, this); + mCommitCallbackRegistrar.add("RegionInfo.Cancel", boost::bind(&LLPanelRegionGeneralInfo::onClickManageTelehub, this)); return LLPanelRegionInfo::postBuild(); } @@ -719,11 +722,9 @@ bool LLPanelRegionGeneralInfo::onMessageCommit(const LLSD& notification, const L return false; } -// static -void LLPanelRegionGeneralInfo::onClickManageTelehub(void* data) +void LLPanelRegionGeneralInfo::onClickManageTelehub() { - LLFloaterRegionInfo::getInstance()->closeFloater(); - + LLFloaterReg::getInstance("region_info")->closeFloater(); LLFloaterTelehub::show(); } @@ -958,8 +959,10 @@ void LLPanelRegionDebugInfo::onClickTopColliders(void* data) strings_t strings; strings.push_back("1"); // one physics step LLUUID invoice(LLFloaterRegionInfo::getLastInvoice()); - LLFloaterTopObjects::show(); - LLFloaterTopObjects::clearList(); + LLFloaterTopObjects* instance = LLFloaterReg::getTypedInstance<LLFloaterTopObjects>("top_objects"); + if(!instance) return; + LLFloaterReg::showInstance("top_objects"); + instance->clearList(); self->sendEstateOwnerMessage(gMessageSystem, "colliders", invoice, strings); } @@ -970,8 +973,10 @@ void LLPanelRegionDebugInfo::onClickTopScripts(void* data) strings_t strings; strings.push_back("6"); // top 5 scripts LLUUID invoice(LLFloaterRegionInfo::getLastInvoice()); - LLFloaterTopObjects::show(); - LLFloaterTopObjects::clearList(); + LLFloaterTopObjects* instance = LLFloaterReg::getTypedInstance<LLFloaterTopObjects>("top_objects"); + if(!instance) return; + LLFloaterReg::showInstance("top_objects"); + instance->clearList(); self->sendEstateOwnerMessage(gMessageSystem, "scripts", invoice, strings); } @@ -1254,7 +1259,7 @@ BOOL LLPanelRegionTerrainInfo::sendUpdate() // Grab estate information in case the user decided to set the // region back to estate time. JC - LLFloaterRegionInfo* floater = LLFloaterRegionInfo::getInstance(); + LLFloaterRegionInfo* floater = LLFloaterReg::getTypedInstance<LLFloaterRegionInfo>("region_info"); if (!floater) return true; LLTabContainer* tab = floater->getChild<LLTabContainer>("region_panels"); diff --git a/indra/newview/llfloaterregioninfo.h b/indra/newview/llfloaterregioninfo.h index b3a1fcb7caf0f1d509ca18957d513c73c1052bd0..be4becf7e77b79eddb18eb9fba293690152459fd 100644 --- a/indra/newview/llfloaterregioninfo.h +++ b/indra/newview/llfloaterregioninfo.h @@ -59,11 +59,11 @@ class LLPanelRegionTerrainInfo; class LLPanelEstateInfo; class LLPanelEstateCovenant; -class LLFloaterRegionInfo : public LLFloater, public LLFloaterSingleton<LLFloaterRegionInfo> +class LLFloaterRegionInfo : public LLFloater { - friend class LLUISingleton<LLFloaterRegionInfo, VisibilityPolicy<LLFloater> >; + friend class LLFloaterReg; public: - ~LLFloaterRegionInfo(); + /*virtual*/ void onOpen(const LLSD& key); /*virtual*/ BOOL postBuild(); @@ -86,8 +86,12 @@ public: void requestRegionInfo(); -protected: +private: + LLFloaterRegionInfo(const LLSD& seed); + ~LLFloaterRegionInfo(); + +protected: void refreshFromRegion(LLViewerRegion* region); // member data @@ -166,7 +170,7 @@ protected: bool onKickAllCommit(const LLSD& notification, const LLSD& response); static void onClickMessage(void* userdata); bool onMessageCommit(const LLSD& notification, const LLSD& response); - static void onClickManageTelehub(void* data); + void onClickManageTelehub(); }; ///////////////////////////////////////////////////////////////////////////// diff --git a/indra/newview/llfloaterreporter.cpp b/indra/newview/llfloaterreporter.cpp index 4b175cdc2770fcc3f6ecbb7c179c507c141cf905..513a6a06b1f57234098276718580abcce0db97ef 100644 --- a/indra/newview/llfloaterreporter.cpp +++ b/indra/newview/llfloaterreporter.cpp @@ -53,7 +53,7 @@ #include "llagent.h" #include "llbutton.h" #include "llcheckboxctrl.h" -#include "llinventoryview.h" +#include "llfloaterinventory.h" #include "lllineeditor.h" #include "lltexturectrl.h" #include "llscrolllistctrl.h" diff --git a/indra/newview/llfloatersettingsdebug.h b/indra/newview/llfloatersettingsdebug.h index 87833793af047a4c1ace7f3088e3bb6501285498..e7dda3a5f425528363c882751c5450da5a5ce68a 100644 --- a/indra/newview/llfloatersettingsdebug.h +++ b/indra/newview/llfloatersettingsdebug.h @@ -38,14 +38,11 @@ #include "lltexteditor.h" class LLFloaterSettingsDebug -: public LLFloater, - public LLFloaterSingleton<LLFloaterSettingsDebug> +: public LLFloater { + friend class LLFloaterReg; + public: - // key - selects which settings to show, one of: - // "all", "base", "account", "skin" - LLFloaterSettingsDebug(const LLSD& key); - virtual ~LLFloaterSettingsDebug(); virtual BOOL postBuild(); virtual void draw(); @@ -56,6 +53,12 @@ public: void onCommitSettings(); void onClickDefault(); +private: + // key - selects which settings to show, one of: + // "all", "base", "account", "skin" + LLFloaterSettingsDebug(const LLSD& key); + virtual ~LLFloaterSettingsDebug(); + protected: LLTextEditor* mComment; }; diff --git a/indra/newview/llfloatertestlistview.cpp b/indra/newview/llfloatertestlistview.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f7a327c0883a184ce3f661fb3fa6b036bd9ea6fa --- /dev/null +++ b/indra/newview/llfloatertestlistview.cpp @@ -0,0 +1,77 @@ +/** +* @file llfloatertestlistview.cpp +* @brief Tests of programmatic manipulation of LLListView widgets +* +* $LicenseInfo:firstyear=2009&license=viewergpl$ +* +* Copyright (c) 2009, Linden Research, Inc. +* +* Second Life Viewer Source Code +* The source code in this file ("Source Code") is provided by Linden Lab +* to you under the terms of the GNU General Public License, version 2.0 +* ("GPL"), unless you have obtained a separate licensing agreement +* ("Other License"), formally executed by you and Linden Lab. Terms of +* the GPL can be found in doc/GPL-license.txt in this distribution, or +* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 +* +* There are special exceptions to the terms and conditions of the GPL as +* it is applied to this Source Code. View the full text of the exception +* in the file doc/FLOSS-exception.txt in this software distribution, or +* online at +* http://secondlifegrid.net/programs/open_source/licensing/flossexception +* +* By copying, modifying or distributing this software, you acknowledge +* that you have read and understood your obligations described above, +* and agree to abide by those obligations. +* +* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO +* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, +* COMPLETENESS OR PERFORMANCE. +* $/LicenseInfo$ +*/ +#include "llviewerprecompiledheaders.h" + +#include "llfloatertestlistview.h" + +// Viewer includes +#include "lllistview.h" + +// Linden library includes +//#include "lluictrlfactory.h" + +LLFloaterTestListView::LLFloaterTestListView(const LLSD& seed) +: LLFloater(seed), + mListView(NULL) +{ + // set up named callback functions for test buttons + mCommitCallbackRegistrar.add("TestListView.Test1", + boost::bind(&LLFloaterTestListView::onClickTest1, this)); + mCommitCallbackRegistrar.add("TestListView.Test2", + boost::bind(&LLFloaterTestListView::onClickTest2, this)); +} + +LLFloaterTestListView::~LLFloaterTestListView() +{} + +BOOL LLFloaterTestListView::postBuild() +{ + mListView = getChild<LLListView>("test_list_view"); + // just set a random property + mListView->setString("set programmatically"); + return LLFloater::postBuild(); +} + +void LLFloaterTestListView::onListViewChanged() +{ + llinfos << "JAMESDEBUG list view changed" << llendl; +} + +void LLFloaterTestListView::onClickTest1() +{ + llinfos << "JAMESDEBUG test 1" << llendl; +} + +void LLFloaterTestListView::onClickTest2() +{ + llinfos << "JAMESDEBUG test 2" << llendl; +} diff --git a/indra/newview/llfloatertestlistview.h b/indra/newview/llfloatertestlistview.h new file mode 100644 index 0000000000000000000000000000000000000000..053da95def6db5ef5f7e7f857cf7f1ee3f6560af --- /dev/null +++ b/indra/newview/llfloatertestlistview.h @@ -0,0 +1,64 @@ +/** +* @file llfloatertestlistview.h +* @brief Tests of programmatic manipulation of LLListView widgets +* +* $LicenseInfo:firstyear=2009&license=viewergpl$ +* +* Copyright (c) 2009, Linden Research, Inc. +* +* Second Life Viewer Source Code +* The source code in this file ("Source Code") is provided by Linden Lab +* to you under the terms of the GNU General Public License, version 2.0 +* ("GPL"), unless you have obtained a separate licensing agreement +* ("Other License"), formally executed by you and Linden Lab. Terms of +* the GPL can be found in doc/GPL-license.txt in this distribution, or +* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 +* +* There are special exceptions to the terms and conditions of the GPL as +* it is applied to this Source Code. View the full text of the exception +* in the file doc/FLOSS-exception.txt in this software distribution, or +* online at +* http://secondlifegrid.net/programs/open_source/licensing/flossexception +* +* By copying, modifying or distributing this software, you acknowledge +* that you have read and understood your obligations described above, +* and agree to abide by those obligations. +* +* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO +* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, +* COMPLETENESS OR PERFORMANCE. +* $/LicenseInfo$ +*/ +#ifndef LLFLOATERTESTLISTVIEW_H +#define LLFLOATERTESTLISTVIEW_H + +#include "llfloater.h" + +class LLListView; +class LLSD; + +class LLFloaterTestListView : public LLFloater +{ + friend class LLFloaterReg; +public: + // nothing yet + +private: + // Construction handled by LLFloaterReg + LLFloaterTestListView(const LLSD& seed); + ~LLFloaterTestListView(); + + /*virtual*/ BOOL postBuild(); + + // Perform some debug action when the list-view sends change notification + void onListViewChanged(); + + // Debug function hookups for buttons + void onClickTest1(); + void onClickTest2(); + +private: + LLListView* mListView; +}; + +#endif diff --git a/indra/newview/llfloatertools.cpp b/indra/newview/llfloatertools.cpp index 4bcf470317e8c718505e1e65789e694795130f14..470463014714677b936e1be957a04ecf1a6fe3d7 100644 --- a/indra/newview/llfloatertools.cpp +++ b/indra/newview/llfloatertools.cpp @@ -445,7 +445,8 @@ void LLFloaterTools::draw() void LLFloaterTools::dirty() { mDirty = TRUE; - LLFloaterOpenObject::dirty(); + LLFloaterOpenObject* instance = LLFloaterReg::getTypedInstance<LLFloaterOpenObject>("openobject"); + if (instance) instance->dirty(); } // Clean up any tool state that should not persist when the diff --git a/indra/newview/llfloatertopobjects.cpp b/indra/newview/llfloatertopobjects.cpp index 29ac0c66f867177d5bd2fe8dd13e84c689c417c5..bf5a1141a6c1d190408ba60122f1e693976908b5 100644 --- a/indra/newview/llfloatertopobjects.cpp +++ b/indra/newview/llfloatertopobjects.cpp @@ -40,6 +40,7 @@ #include "llagent.h" #include "llbutton.h" #include "llfloatergodtools.h" +#include "llfloaterreg.h" #include "llparcel.h" #include "llscrolllistctrl.h" #include "llscrolllistitem.h" @@ -53,11 +54,11 @@ #include "lluictrlfactory.h" #include "llviewerwindow.h" -LLFloaterTopObjects* LLFloaterTopObjects::sInstance = NULL; +//LLFloaterTopObjects* LLFloaterTopObjects::sInstance = NULL; // Globals // const U32 TIME_STR_LENGTH = 30; - +/* // static void LLFloaterTopObjects::show() { @@ -68,21 +69,28 @@ void LLFloaterTopObjects::show() } sInstance = new LLFloaterTopObjects(); - LLUICtrlFactory::getInstance()->buildFloater(sInstance, "floater_top_objects.xml"); +// LLUICtrlFactory::getInstance()->buildFloater(sInstance, "floater_top_objects.xml"); sInstance->center(); } - -LLFloaterTopObjects::LLFloaterTopObjects() -: LLFloater(), +*/ +LLFloaterTopObjects::LLFloaterTopObjects(const LLSD& key) +: LLFloater(key), mInitialized(FALSE), mtotalScore(0.f) { - sInstance = this; + mCommitCallbackRegistrar.add("TopObjects.ShowBeacon", boost::bind(&LLFloaterTopObjects::onClickShowBeacon, this)); + mCommitCallbackRegistrar.add("TopObjects.ReturnSelected", boost::bind(&LLFloaterTopObjects::onReturnSelected, this)); + mCommitCallbackRegistrar.add("TopObjects.ReturnAll", boost::bind(&LLFloaterTopObjects::onReturnAll, this)); + mCommitCallbackRegistrar.add("TopObjects.DisableSelected", boost::bind(&LLFloaterTopObjects::onDisableSelected, this)); + mCommitCallbackRegistrar.add("TopObjects.DisableAll", boost::bind(&LLFloaterTopObjects::onDisableAll, this)); + mCommitCallbackRegistrar.add("TopObjects.Refresh", boost::bind(&LLFloaterTopObjects::onRefresh, this)); + mCommitCallbackRegistrar.add("TopObjects.GetByObjectName", boost::bind(&LLFloaterTopObjects::onGetByObjectName, this)); + mCommitCallbackRegistrar.add("TopObjects.GetByOwnerName", boost::bind(&LLFloaterTopObjects::onGetByOwnerName, this)); + mCommitCallbackRegistrar.add("TopObjects.CommitObjectsList",boost::bind(&LLFloaterTopObjects::onCommitObjectsList, this)); } LLFloaterTopObjects::~LLFloaterTopObjects() { - sInstance = NULL; } // virtual @@ -90,24 +98,11 @@ BOOL LLFloaterTopObjects::postBuild() { LLScrollListCtrl *objects_list = getChild<LLScrollListCtrl>("objects_list"); childSetFocus("objects_list"); - childSetCommitCallback("objects_list", onCommitObjectsList, this); objects_list->setDoubleClickCallback(onDoubleClickObjectsList, this); objects_list->setCommitOnSelectionChange(TRUE); - childSetAction("show_beacon_btn", onClickShowBeacon, this); setDefaultBtn("show_beacon_btn"); - childSetAction("return_selected_btn", onReturnSelected, this); - childSetAction("return_all_btn", onReturnAll, this); - childSetAction("disable_selected_btn", onDisableSelected, this); - childSetAction("disable_all_btn", onDisableAll, this); - childSetAction("refresh_btn", onRefresh, this); - - - childSetAction("filter_object_btn", onGetByObjectNameClicked, this); - childSetAction("filter_owner_btn", onGetByOwnerNameClicked, this); - - /* LLLineEditor* line_editor = getChild<LLLineEditor>("owner_name_editor"); if (line_editor) @@ -129,19 +124,29 @@ BOOL LLFloaterTopObjects::postBuild() return TRUE; } +// static +void LLFloaterTopObjects::setMode(U32 mode) +{ + LLFloaterTopObjects* instance = LLFloaterReg::getTypedInstance<LLFloaterTopObjects>("top_objects"); + if(!instance) return; + instance->mCurrentMode = mode; +} +// static void LLFloaterTopObjects::handle_land_reply(LLMessageSystem* msg, void** data) { + LLFloaterTopObjects* instance = LLFloaterReg::getTypedInstance<LLFloaterTopObjects>("top_objects"); + if(!instance) return; // Make sure dialog is on screen - show(); - sInstance->handleReply(msg, data); + LLFloaterReg::showInstance("top_objects"); + instance->handleReply(msg, data); //HACK: for some reason sometimes top scripts originally comes back //with no results even though they're there - if (!sInstance->mObjectListIDs.size() && !sInstance->mInitialized) + if (!instance->mObjectListIDs.size() && !instance->mInitialized) { - sInstance->onRefresh(NULL); - sInstance->mInitialized = TRUE; + instance->onRefresh(); + instance->mInitialized = TRUE; } } @@ -260,12 +265,9 @@ void LLFloaterTopObjects::handleReply(LLMessageSystem *msg, void** data) } } -// static -void LLFloaterTopObjects::onCommitObjectsList(LLUICtrl* ctrl, void* data) +void LLFloaterTopObjects::onCommitObjectsList() { - LLFloaterTopObjects* self = (LLFloaterTopObjects*)data; - - self->updateSelectionInfo(); + updateSelectionInfo(); } void LLFloaterTopObjects::updateSelectionInfo() @@ -292,11 +294,9 @@ void LLFloaterTopObjects::onDoubleClickObjectsList(void* data) } // static -void LLFloaterTopObjects::onClickShowBeacon(void* data) +void LLFloaterTopObjects::onClickShowBeacon() { - LLFloaterTopObjects* self = (LLFloaterTopObjects*)data; - if (!self) return; - self->showBeacon(); + showBeacon(); } void LLFloaterTopObjects::doToObjects(int action, bool all) @@ -360,22 +360,24 @@ void LLFloaterTopObjects::doToObjects(int action, bool all) bool LLFloaterTopObjects::callbackReturnAll(const LLSD& notification, const LLSD& response) { S32 option = LLNotification::getSelectedOption(notification, response); + LLFloaterTopObjects* instance = LLFloaterReg::getTypedInstance<LLFloaterTopObjects>("top_objects"); + if(!instance) return false; if (option == 0) { - sInstance->doToObjects(ACTION_RETURN, true); + instance->doToObjects(ACTION_RETURN, true); } return false; } -void LLFloaterTopObjects::onReturnAll(void* data) +void LLFloaterTopObjects::onReturnAll() { LLNotifications::instance().add("ReturnAllTopObjects", LLSD(), LLSD(), &callbackReturnAll); } -void LLFloaterTopObjects::onReturnSelected(void* data) +void LLFloaterTopObjects::onReturnSelected() { - sInstance->doToObjects(ACTION_RETURN, false); + doToObjects(ACTION_RETURN, false); } @@ -383,52 +385,52 @@ void LLFloaterTopObjects::onReturnSelected(void* data) bool LLFloaterTopObjects::callbackDisableAll(const LLSD& notification, const LLSD& response) { S32 option = LLNotification::getSelectedOption(notification, response); + LLFloaterTopObjects* instance = LLFloaterReg::getTypedInstance<LLFloaterTopObjects>("top_objects"); + if(!instance) return false; if (option == 0) { - sInstance->doToObjects(ACTION_DISABLE, true); + instance->doToObjects(ACTION_DISABLE, true); } return false; } -void LLFloaterTopObjects::onDisableAll(void* data) +void LLFloaterTopObjects::onDisableAll() { LLNotifications::instance().add("DisableAllTopObjects", LLSD(), LLSD(), callbackDisableAll); } -void LLFloaterTopObjects::onDisableSelected(void* data) +void LLFloaterTopObjects::onDisableSelected() { - sInstance->doToObjects(ACTION_DISABLE, false); + doToObjects(ACTION_DISABLE, false); } -//static + void LLFloaterTopObjects::clearList() { - LLCtrlListInterface *list = sInstance->childGetListInterface("objects_list"); + LLCtrlListInterface *list = childGetListInterface("objects_list"); if (list) { list->operateOnAll(LLCtrlListInterface::OP_DELETE); } - sInstance->mObjectListData.clear(); - sInstance->mObjectListIDs.clear(); - sInstance->mtotalScore = 0.f; + mObjectListData.clear(); + mObjectListIDs.clear(); + mtotalScore = 0.f; } -//static -void LLFloaterTopObjects::onRefresh(void* data) + +void LLFloaterTopObjects::onRefresh() { U32 mode = STAT_REPORT_TOP_SCRIPTS; U32 flags = 0; std::string filter = ""; - if (sInstance) - { - mode = sInstance->mCurrentMode; - flags = sInstance->mFlags; - filter = sInstance->mFilter; - sInstance->clearList(); - } + mode = mCurrentMode; + flags = mFlags; + filter = mFilter; + clearList(); + LLMessageSystem *msg = gMessageSystem; msg->newMessageFast(_PREHASH_LandStatRequest); @@ -443,31 +445,22 @@ void LLFloaterTopObjects::onRefresh(void* data) msg->sendReliable(gAgent.getRegionHost()); - if (sInstance) - { - sInstance->mFilter.clear(); - sInstance->mFlags = 0; - } + mFilter.clear(); + mFlags = 0; } -void LLFloaterTopObjects::onGetByObjectName(LLUICtrl* ctrl, void* data) +void LLFloaterTopObjects::onGetByObjectName() { - if (sInstance) - { - sInstance->mFlags = STAT_FILTER_BY_OBJECT; - sInstance->mFilter = sInstance->childGetText("object_name_editor"); - onRefresh(NULL); - } + mFlags = STAT_FILTER_BY_OBJECT; + mFilter = childGetText("object_name_editor"); + onRefresh(); } -void LLFloaterTopObjects::onGetByOwnerName(LLUICtrl* ctrl, void* data) +void LLFloaterTopObjects::onGetByOwnerName() { - if (sInstance) - { - sInstance->mFlags = STAT_FILTER_BY_OWNER; - sInstance->mFilter = sInstance->childGetText("owner_name_editor"); - onRefresh(NULL); - } + mFlags = STAT_FILTER_BY_OWNER; + mFilter = childGetText("owner_name_editor"); + onRefresh(); } void LLFloaterTopObjects::showBeacon() diff --git a/indra/newview/llfloatertopobjects.h b/indra/newview/llfloatertopobjects.h index 58cbf5d2ceaa6e4b9d9ad4563e657037c195390d..ee3c5d3cceefdd080594d217ffda5050d2d3dd64 100644 --- a/indra/newview/llfloatertopobjects.h +++ b/indra/newview/llfloatertopobjects.h @@ -39,48 +39,49 @@ class LLUICtrl; class LLFloaterTopObjects : public LLFloater { + friend class LLFloaterReg; public: // Opens the floater on screen. - static void show(); +// static void show(); // Opens the floater if it's not on-screen. // Juggles the UI based on method = "scripts" or "colliders" static void handle_land_reply(LLMessageSystem* msg, void** data); void handleReply(LLMessageSystem* msg, void** data); - static void clearList(); + void clearList(); void updateSelectionInfo(); virtual BOOL postBuild(); - static void onRefresh(void* data); + void onRefresh(); - static void setMode(U32 mode) { if (sInstance) sInstance->mCurrentMode = mode; } + static void setMode(U32 mode); private: - LLFloaterTopObjects(); + LLFloaterTopObjects(const LLSD& key); ~LLFloaterTopObjects(); void initColumns(LLCtrlListInterface *list); - static void onCommitObjectsList(LLUICtrl* ctrl, void* data); + void onCommitObjectsList(); static void onDoubleClickObjectsList(void* data); - static void onClickShowBeacon(void* data); + void onClickShowBeacon(); void doToObjects(int action, bool all); - static void onReturnAll(void* data); - static void onReturnSelected(void* data); - static void onDisableAll(void* data); - static void onDisableSelected(void* data); + void onReturnAll(); + void onReturnSelected(); + void onDisableAll(); + void onDisableSelected(); static bool callbackReturnAll(const LLSD& notification, const LLSD& response); static bool callbackDisableAll(const LLSD& notification, const LLSD& response); - static void onGetByOwnerName(LLUICtrl* ctrl, void* data); - static void onGetByObjectName(LLUICtrl* ctrl, void* data); + void onGetByOwnerName(); + void onGetByObjectName(); - static void onGetByOwnerNameClicked(void* data) { onGetByOwnerName(NULL, data); }; - static void onGetByObjectNameClicked(void* data) { onGetByObjectName(NULL, data); }; +// static void onGetByOwnerNameClicked(void* data) { onGetByOwnerName(NULL, data); }; +// static void onGetByObjectNameClicked(void* data) { onGetByObjectName(NULL, data); }; void showBeacon(); diff --git a/indra/newview/llfloateruipreview.cpp b/indra/newview/llfloateruipreview.cpp index 34db895b5289307d9b2be1d74a60b8c6343508f2..e7304ea5a99cd43683681466c428c9d8971f5994 100644 --- a/indra/newview/llfloateruipreview.cpp +++ b/indra/newview/llfloateruipreview.cpp @@ -264,6 +264,8 @@ BOOL LLFloaterUIPreview::postBuild() main_panel_tmp->getChild<LLButton>("save_floater")->setClickedCallback(onClickSaveFloater, (void*)&PRIMARY_FLOATER); main_panel_tmp->getChild<LLButton>("save_all_floaters")->setClickedCallback(onClickSaveAll, (void*)&PRIMARY_FLOATER); + getChild<LLButton>("export_schema")->setClickedCallback(boost::bind(&LLFloaterUIPreview::onClickExportSchema, this)); + // get pointers to text fields mEditorPathTextBox = editor_panel_tmp->getChild<LLLineEditor>("executable_path_field"); mEditorArgsTextBox = editor_panel_tmp->getChild<LLLineEditor>("executable_args_field"); @@ -354,6 +356,34 @@ void LLFloaterUIPreview::onLanguageComboSelect(LLUICtrl* ctrl) } +void LLFloaterUIPreview::onClickExportSchema() +{ + std::string template_path = gDirUtilp->getExpandedFilename(LL_PATH_DEFAULT_SKIN, "xui", "schema"); + + typedef LLWidgetTypeRegistry::Registrar::registry_map_t::const_iterator registry_it; + registry_it end_it = LLWidgetTypeRegistry::defaultRegistrar().endItems(); + for(registry_it it = LLWidgetTypeRegistry::defaultRegistrar().beginItems(); + it != end_it; + ++it) + { + std::string widget_name = it->first; + const LLInitParam::BaseBlock& block = + (*LLDefaultParamBlockRegistry::instance().getValue(*LLWidgetTypeRegistry::instance().getValue(widget_name)))(); + LLXMLNodePtr root_nodep = new LLXMLNode(); + LLRNGWriter().writeRNG(widget_name, root_nodep, block, "http://www.lindenlab.com/xui"); + + std::string file_name(template_path + gDirUtilp->getDirDelimiter() + widget_name + ".rng"); + + LLFILE* rng_file = LLFile::fopen(file_name.c_str(), "w"); + { + LLXMLNode::writeHeaderToFile(rng_file); + root_nodep->writeToFile(rng_file); + } + fclose(rng_file); + } +} + + // Close click handler -- delete my displayed floater if it exists void LLFloaterUIPreview::onClose(bool app_quitting) { @@ -614,7 +644,7 @@ void LLFloaterUIPreview::displayFloater(BOOL click, S32 ID, bool save) if (save) { LLXMLNodePtr menu_write = new LLXMLNode(); - LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>(path, gMenuHolder, menu_write); + LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>(path, gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance(), menu_write); if (!menu_write->isNull()) { @@ -779,6 +809,10 @@ void LLFloaterUIPreview::onClickEditFloater(void*) { exe_path_char = path_in_textfield.c_str(); } + else if (!LLUI::sSettingGroups["config"]->getString("XUIEditor").empty()) + { + exe_path_char = LLUI::sSettingGroups["config"]->getString("XUIEditor").c_str(); + } else // otherwise use the path specified by the environment variable { exe_path_char = getenv("LL_XUI_EDITOR"); diff --git a/indra/newview/llfloateruipreview.h b/indra/newview/llfloateruipreview.h index b0af841e11507801797d03ac0f3d6e6270a40a42..1307d606897369f71e5b1c0a66b1b0b86e3af790 100644 --- a/indra/newview/llfloateruipreview.h +++ b/indra/newview/llfloateruipreview.h @@ -211,6 +211,7 @@ private: static void onClickToggleOverlapping(void*); static void onClickCloseDisplayedFloater(void*); void onLanguageComboSelect(LLUICtrl* ctrl); + void onClickExportSchema(); }; #endif // LL_LLUIPREVIEW_H diff --git a/indra/newview/llfloaterurldisplay.cpp b/indra/newview/llfloaterurldisplay.cpp index 7f7d05e1d2793e19c24aa69ee442bf33b1832ff5..3b9321a87697a72307b0fa200fc7dc3e6cf61e33 100644 --- a/indra/newview/llfloaterurldisplay.cpp +++ b/indra/newview/llfloaterurldisplay.cpp @@ -45,11 +45,10 @@ LLFloaterURLDisplay::LLFloaterURLDisplay(const LLSD& sd) - : LLFloater() + : LLFloater(sd) { mFactoryMap["place_details_panel"] = LLCallbackMap(LLFloaterURLDisplay::createPlaceDetail, this); - LLUICtrlFactory::getInstance()->buildFloater(this, "floater_preview_url.xml"); - this->setVisible(false); +// LLUICtrlFactory::getInstance()->buildFloater(this, "floater_preview_url.xml"); // If positioned at 0,0 the teleport button is behind the toolbar. LLRect r = getRect(); diff --git a/indra/newview/llfloaterurldisplay.h b/indra/newview/llfloaterurldisplay.h index 91c544ae86da3219ae5a033407fe6bdd79ef62e6..22f5a95ad01d205e5f101f1e7dbee0bd5ecea388 100644 --- a/indra/newview/llfloaterurldisplay.h +++ b/indra/newview/llfloaterurldisplay.h @@ -40,11 +40,10 @@ class LLPanelPlace; class LLSD; class LLUUID; -class LLFloaterURLDisplay : public LLFloater, public LLFloaterSingleton<LLFloaterURLDisplay> +class LLFloaterURLDisplay : public LLFloater { + friend class LLFloaterReg; public: - LLFloaterURLDisplay(const LLSD& sd); - virtual ~LLFloaterURLDisplay(); void displayParcelInfo(U64 region_handle, const LLVector3& pos); void setSnapshotDisplay(const LLUUID& snapshot_id); @@ -54,6 +53,9 @@ public: static void* createPlaceDetail(void* userdata); private: + LLFloaterURLDisplay(const LLSD& sd); + virtual ~LLFloaterURLDisplay(); + LLVector3 mRegionPosition; U64 mRegionHandle; LLPanelPlace* mPlacePanel; diff --git a/indra/newview/llfloatervoicedevicesettings.cpp b/indra/newview/llfloatervoicedevicesettings.cpp index 16f4ecef076b7fe18a1ce8183013fd8fb9836b21..0cbeaa591d16a790c0bbc1e9dea1aec3d22d1a76 100644 --- a/indra/newview/llfloatervoicedevicesettings.cpp +++ b/indra/newview/llfloatervoicedevicesettings.cpp @@ -284,7 +284,7 @@ void LLPanelVoiceDeviceSettings::onCommitOutputDevice(LLUICtrl* ctrl, void* user // LLFloaterVoiceDeviceSettings::LLFloaterVoiceDeviceSettings(const LLSD& seed) - : LLFloater(), + : LLFloater(seed), mDevicePanel(NULL) { mFactoryMap["device_settings"] = LLCallbackMap(createPanelVoiceDeviceSettings, this); diff --git a/indra/newview/llfloatervoicedevicesettings.h b/indra/newview/llfloatervoicedevicesettings.h index 47f41d6d7ec9a0c3c04c0be7b4b8b458bf4da22b..ed8840a9f9919a5b3007cd967d7688e515197128 100644 --- a/indra/newview/llfloatervoicedevicesettings.h +++ b/indra/newview/llfloatervoicedevicesettings.h @@ -62,17 +62,21 @@ protected: BOOL mDevicesUpdated; }; -class LLFloaterVoiceDeviceSettings : public LLFloater, public LLFloaterSingleton<LLFloaterVoiceDeviceSettings> +class LLFloaterVoiceDeviceSettings : public LLFloater { + friend class LLFloaterReg; + public: - LLFloaterVoiceDeviceSettings(const LLSD& seed); + virtual BOOL postBuild(); /*virtual*/ void onOpen(const LLSD& key); /*virtual*/ void onClose(bool app_quitting); /*virtual*/ void draw(); void apply(); void cancel(); - +private: + LLFloaterVoiceDeviceSettings(const LLSD& seed); + protected: static void* createPanelVoiceDeviceSettings(void* user_data); diff --git a/indra/newview/llfloaterworldmap.cpp b/indra/newview/llfloaterworldmap.cpp index 9711e02f698073be3c55ac91eb88837e7afc1ce4..d435ec86a269bcc36fa9837462d1deeb56e8465f 100644 --- a/indra/newview/llfloaterworldmap.cpp +++ b/indra/newview/llfloaterworldmap.cpp @@ -161,6 +161,16 @@ LLFloaterWorldMap::LLFloaterWorldMap(const LLSD& key) mFactoryMap["terrain_mapview"] = LLCallbackMap(createWorldMapView, NULL); //Called from floater reg: LLUICtrlFactory::getInstance()->buildFloater(this, "floater_world_map.xml", FALSE); + mCommitCallbackRegistrar.add("WMap.Location", boost::bind(&LLFloaterWorldMap::onLocationCommit, this)); + mCommitCallbackRegistrar.add("WMap.AvatarCombo", boost::bind(&LLFloaterWorldMap::onAvatarComboCommit, this)); + mCommitCallbackRegistrar.add("WMap.SearchResult", boost::bind(&LLFloaterWorldMap::onCommitSearchResult, this)); + mCommitCallbackRegistrar.add("WMap.CommitLocation", boost::bind(&LLFloaterWorldMap::onCommitLocation, this)); + mCommitCallbackRegistrar.add("WMap.GoHome", boost::bind(&LLFloaterWorldMap::onGoHome, this)); + mCommitCallbackRegistrar.add("WMap.Teleport", boost::bind(&LLFloaterWorldMap::onClickTeleportBtn, this)); + mCommitCallbackRegistrar.add("WMap.ShowTarget", boost::bind(&LLFloaterWorldMap::onShowTargetBtn, this)); + mCommitCallbackRegistrar.add("WMap.ShowAgent", boost::bind(&LLFloaterWorldMap::onShowAgentBtn, this)); + mCommitCallbackRegistrar.add("WMap.Clear", boost::bind(&LLFloaterWorldMap::onClearBtn, this)); + mCommitCallbackRegistrar.add("WMap.CopySLURL", boost::bind(&LLFloaterWorldMap::onCopySLURL, this)); } // static @@ -183,8 +193,6 @@ BOOL LLFloaterWorldMap::postBuild() // //onCommitBackground(); - childSetCommitCallback("friend combo", onAvatarComboCommit, this); - LLComboBox *avatar_combo = getChild<LLComboBox>("friend combo"); if (avatar_combo) { @@ -193,8 +201,6 @@ BOOL LLFloaterWorldMap::postBuild() avatar_combo->setTextEntryCallback( boost::bind(&LLFloaterWorldMap::onComboTextEntry, this) ); } - childSetAction("DoSearch", onLocationCommit, this); - getChild<LLScrollListCtrl>("location")->setFocusChangedCallback(boost::bind(&LLFloaterWorldMap::onLocationFocusChanged, this, _1)); LLLineEditor *location_editor = getChild<LLLineEditor>("location"); @@ -203,13 +209,7 @@ BOOL LLFloaterWorldMap::postBuild() location_editor->setKeystrokeCallback( boost::bind(&LLFloaterWorldMap::onSearchTextEntry, this, _1), NULL ); } - childSetCommitCallback("search_results", onCommitSearchResult, this); getChild<LLScrollListCtrl>("search_results")->setDoubleClickCallback(onClickTeleportBtn, this); - childSetCommitCallback("spin x", onCommitLocation, this); - childSetCommitCallback("spin y", onCommitLocation, this); - childSetCommitCallback("spin z", onCommitLocation, this); - - childSetCommitCallback("landmark combo", onLandmarkComboCommit, this); LLComboBox *landmark_combo = getChild<LLComboBox>( "landmark combo"); if (landmark_combo) @@ -219,15 +219,6 @@ BOOL LLFloaterWorldMap::postBuild() landmark_combo->setTextEntryCallback( boost::bind(&LLFloaterWorldMap::onComboTextEntry, this) ); } - childSetAction("Go Home", onGoHome, this); - - childSetAction("Teleport", onClickTeleportBtn, this); - - childSetAction("Show Destination", onShowTargetBtn, this); - childSetAction("Show My Location", onShowAgentBtn, this); - childSetAction("Clear", onClearBtn, this); - childSetAction("copy_slurl", onCopySLURL, this); - mCurZoomVal = log(gMapScale)/log(2.f); childSetValue("zoom slider", gMapScale); @@ -863,7 +854,7 @@ void LLFloaterWorldMap::buildLandmarkIDLists() LLInventoryModel::cat_array_t cats; LLInventoryModel::item_array_t items; LLIsType is_landmark(LLAssetType::AT_LANDMARK); - gInventory.collectDescendentsIf(gAgent.getInventoryRootID(), + gInventory.collectDescendentsIf(gInventory.getRootFolderID(), cats, items, LLInventoryModel::EXCLUDE_TRASH, @@ -1020,8 +1011,7 @@ void LLFloaterWorldMap::onPanBtn( void* userdata ) map_panel->translatePan( pan_x, pan_y ); } -// static -void LLFloaterWorldMap::onGoHome(void*) +void LLFloaterWorldMap::onGoHome() { gAgent.teleportHome(); gFloaterWorldMap->closeFloater(); @@ -1063,8 +1053,8 @@ void LLFloaterWorldMap::onSearchTextEntry( LLLineEditor* ctrl ) updateSearchEnabled(); } -// static -void LLFloaterWorldMap::onLandmarkComboCommit( LLUICtrl* ctrl, void* userdata ) + +void LLFloaterWorldMap::onLandmarkComboCommit() { LLFloaterWorldMap* self = gFloaterWorldMap; @@ -1106,7 +1096,7 @@ void LLFloaterWorldMap::onLandmarkComboCommit( LLUICtrl* ctrl, void* userdata ) } self->trackLandmark( item_id); - onShowTargetBtn(self); + onShowTargetBtn(); // Reset to user postion if nothing is tracked self->mSetToUserPosition = ( LLTracker::getTrackingStatus() == LLTracker::TRACKING_NOTHING ); @@ -1138,9 +1128,7 @@ void LLFloaterWorldMap::onAvatarComboPrearrange( ) } } - -// static -void LLFloaterWorldMap::onAvatarComboCommit( LLUICtrl* ctrl, void* userdata ) +void LLFloaterWorldMap::onAvatarComboCommit() { LLFloaterWorldMap* self = gFloaterWorldMap; if( !self || self->mIsClosing ) @@ -1158,7 +1146,7 @@ void LLFloaterWorldMap::onAvatarComboCommit( LLUICtrl* ctrl, void* userdata ) LLComboBox* combo = gFloaterWorldMap->getChild<LLComboBox>("friend combo"); if (combo) name = combo->getSimple(); self->trackAvatar(new_avatar_id, name); - onShowTargetBtn(self); + onShowTargetBtn(); } else { // Reset to user postion if nothing is tracked @@ -1184,8 +1172,7 @@ void LLFloaterWorldMap::updateSearchEnabled() } } -// static -void LLFloaterWorldMap::onLocationCommit( void* userdata ) +void LLFloaterWorldMap::onLocationCommit() { LLFloaterWorldMap *self = gFloaterWorldMap; if( !self || self->mIsClosing ) @@ -1222,16 +1209,13 @@ void LLFloaterWorldMap::onLocationCommit( void* userdata ) } } - -// static -void LLFloaterWorldMap::onClearBtn(void* data) +void LLFloaterWorldMap::onClearBtn() { - LLFloaterWorldMap* self = (LLFloaterWorldMap*)data; - self->mTrackedStatus = LLTracker::TRACKING_NOTHING; + mTrackedStatus = LLTracker::TRACKING_NOTHING; LLTracker::stopTracking((void *)(intptr_t)TRUE); LLWorldMap::getInstance()->mIsTrackingUnknownLocation = FALSE; - self->mSLURL = ""; // Clear the SLURL since it's invalid - self->mSetToUserPosition = TRUE; // Revert back to the current user position + mSLURL = ""; // Clear the SLURL since it's invalid + mSetToUserPosition = TRUE; // Revert back to the current user position } // static @@ -1241,36 +1225,30 @@ void LLFloaterWorldMap::onFlyBtn(void* data) self->fly(); } -void LLFloaterWorldMap::onShowTargetBtn(void* data) +void LLFloaterWorldMap::onShowTargetBtn() { - LLFloaterWorldMap* self = (LLFloaterWorldMap*)data; - self->centerOnTarget(TRUE); + centerOnTarget(TRUE); } -void LLFloaterWorldMap::onShowAgentBtn(void* data) +void LLFloaterWorldMap::onShowAgentBtn() { LLWorldMapView::setPan( 0, 0, FALSE); // FALSE == animate - // Set flag so user's location will be displayed if not tracking anything else - LLFloaterWorldMap* self = (LLFloaterWorldMap*)data; - self->mSetToUserPosition = TRUE; + mSetToUserPosition = TRUE; } -// static void LLFloaterWorldMap::onClickTeleportBtn(void* data) { LLFloaterWorldMap* self = (LLFloaterWorldMap*)data; self->teleport(); } -// static -void LLFloaterWorldMap::onCopySLURL(void* data) +void LLFloaterWorldMap::onCopySLURL() { - LLFloaterWorldMap* self = (LLFloaterWorldMap*)data; - self->getWindow()->copyTextToClipboard(utf8str_to_wstring(self->mSLURL)); + getWindow()->copyTextToClipboard(utf8str_to_wstring(mSLURL)); LLSD args; - args["SLURL"] = self->mSLURL; + args["SLURL"] = mSLURL; LLNotifications::instance().add("CopySLURL", args); } @@ -1553,13 +1531,13 @@ void LLFloaterWorldMap::updateSims(bool found_null_sim) { mExactMatch = TRUE; childSetFocus("search_results"); - onCommitSearchResult(NULL, this); + onCommitSearchResult(); } else if (!mExactMatch && num_results > 0) { list->selectFirstItem(); // select first item by default childSetFocus("search_results"); - onCommitSearchResult(NULL, this); + onCommitSearchResult(); } else if (num_results == 0) { @@ -1568,30 +1546,25 @@ void LLFloaterWorldMap::updateSims(bool found_null_sim) } } -// static -void LLFloaterWorldMap::onCommitLocation(LLUICtrl* ctrl, void* userdata) +void LLFloaterWorldMap::onCommitLocation() { - LLFloaterWorldMap* self = (LLFloaterWorldMap*) userdata; LLTracker::ETrackingStatus tracking_status = LLTracker::getTrackingStatus(); if ( LLTracker::TRACKING_LOCATION == tracking_status) { LLVector3d pos_global = LLTracker::getTrackedPositionGlobal(); - F64 local_x = self->childGetValue("spin x"); - F64 local_y = self->childGetValue("spin y"); - F64 local_z = self->childGetValue("spin z"); + F64 local_x = childGetValue("spin x"); + F64 local_y = childGetValue("spin y"); + F64 local_z = childGetValue("spin z"); pos_global.mdV[VX] += -fmod(pos_global.mdV[VX], 256.0) + local_x; pos_global.mdV[VY] += -fmod(pos_global.mdV[VY], 256.0) + local_y; pos_global.mdV[VZ] = local_z; - self->trackLocation(pos_global); + trackLocation(pos_global); } } -// static -void LLFloaterWorldMap::onCommitSearchResult(LLUICtrl*, void* userdata) +void LLFloaterWorldMap::onCommitSearchResult() { - LLFloaterWorldMap* self = (LLFloaterWorldMap*) userdata; - - LLCtrlListInterface *list = self->childGetListInterface("search_results"); + LLCtrlListInterface *list = childGetListInterface("search_results"); if (!list) return; LLSD selected_value = list->getSelectedValue(); @@ -1612,19 +1585,19 @@ void LLFloaterWorldMap::onCommitSearchResult(LLUICtrl*, void* userdata) if (sim_name == info_sim_name) { LLVector3d pos_global = from_region_handle( info->mHandle ); - F64 local_x = self->childGetValue("spin x"); - F64 local_y = self->childGetValue("spin y"); - F64 local_z = self->childGetValue("spin z"); + F64 local_x = childGetValue("spin x"); + F64 local_y = childGetValue("spin y"); + F64 local_z = childGetValue("spin z"); pos_global.mdV[VX] += local_x; pos_global.mdV[VY] += local_y; pos_global.mdV[VZ] = local_z; - self->childSetValue("location", sim_name); - self->trackLocation(pos_global); - self->setDefaultBtn("Teleport"); + childSetValue("location", sim_name); + trackLocation(pos_global); + setDefaultBtn("Teleport"); break; } } - onShowTargetBtn(self); + onShowTargetBtn(); } diff --git a/indra/newview/llfloaterworldmap.h b/indra/newview/llfloaterworldmap.h index a7d7051b4074ad54ff5058aadadda7f6a81c4998..2f537fb735effba0095f4a4317507f8f4e6a23a7 100644 --- a/indra/newview/llfloaterworldmap.h +++ b/indra/newview/llfloaterworldmap.h @@ -114,25 +114,25 @@ public: protected: static void onPanBtn( void* userdata ); - static void onGoHome(void* data); + void onGoHome(); - void onLandmarkComboPrearrange( ); - static void onLandmarkComboCommit( LLUICtrl* ctrl, void* data ); + void onLandmarkComboPrearrange(); + void onLandmarkComboCommit(); - void onAvatarComboPrearrange( ); - static void onAvatarComboCommit( LLUICtrl* ctrl, void* data ); + void onAvatarComboPrearrange(); + void onAvatarComboCommit(); void onCommitBackground(); void onComboTextEntry( ); void onSearchTextEntry( LLLineEditor* ctrl ); - static void onClearBtn(void*); + void onClearBtn(); static void onFlyBtn(void*); static void onClickTeleportBtn(void*); - static void onShowTargetBtn(void*); - static void onShowAgentBtn(void*); - static void onCopySLURL(void*); + void onShowTargetBtn(); + void onShowAgentBtn(); + void onCopySLURL(); static void onCheckEvents(LLUICtrl* ctrl, void*); @@ -152,11 +152,11 @@ protected: void flyToAvatar(); void teleportToAvatar(); - void updateSearchEnabled( ); + void updateSearchEnabled(); void onLocationFocusChanged( LLFocusableElement* ctrl ); - static void onLocationCommit( void* userdata ); - static void onCommitLocation( LLUICtrl* ctrl, void* userdata ); - static void onCommitSearchResult( LLUICtrl* ctrl, void* userdata ); + void onLocationCommit(); + void onCommitLocation(); + void onCommitSearchResult(); void cacheLandmarkPosition(); diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp index ebda8b25fdc4dfe859ae107eb04044299d913eed..d0a82f283c30b64d35fcbb0174deec4817669de1 100644 --- a/indra/newview/llfolderview.cpp +++ b/indra/newview/llfolderview.cpp @@ -34,20 +34,11 @@ #include "llfolderview.h" -#include <algorithm> - -#include "llviewercontrol.h" -#include "lldbstrings.h" -#include "llfocusmgr.h" -#include "llfontgl.h" -#include "llgl.h" -#include "llrender.h" -#include "llinventory.h" - #include "llcallbacklist.h" #include "llinventorybridge.h" #include "llinventoryclipboard.h" // *TODO: remove this once hack below gone. -#include "llinventoryview.h"// hacked in for the bonus context menu items. +#include "llinventoryfilter.h" +#include "llfloaterinventory.h"// hacked in for the bonus context menu items. #include "llkeyboard.h" #include "lllineeditor.h" #include "llmenugl.h" @@ -61,34 +52,35 @@ #include "llviewerjointattachment.h" #include "llviewermenu.h" #include "lluictrlfactory.h" +#include "llviewercontrol.h" #include "llviewerwindow.h" #include "llvoavatar.h" #include "llfloaterproperties.h" -// RN: HACK -// We need these because some of the code below relies on things like -// gAgent root folder. Remove them once the abstraction leak is fixed. -#include "llagent.h" -#include "llappviewer.h" +// Linden library includes +#include "lldbstrings.h" +#include "llfocusmgr.h" +#include "llfontgl.h" +#include "llgl.h" +#include "llrender.h" +#include "llinventory.h" + +// Third-party library includes +#include <algorithm> ///---------------------------------------------------------------------------- /// Local function declarations, constants, enums, and typedefs ///---------------------------------------------------------------------------- -const S32 LEFT_PAD = 5; -const S32 LEFT_INDENTATION = 13; -const S32 ICON_PAD = 2; -const S32 ICON_WIDTH = 16; -const S32 TEXT_PAD = 1; -const S32 ARROW_SIZE = 12; const S32 RENAME_WIDTH_PAD = 4; const S32 RENAME_HEIGHT_PAD = 2; const S32 AUTO_OPEN_STACK_DEPTH = 16; -const S32 MIN_ITEM_WIDTH_VISIBLE = ICON_WIDTH + ICON_PAD + ARROW_SIZE + TEXT_PAD + /*first few characters*/ 40; +const S32 MIN_ITEM_WIDTH_VISIBLE = LLFolderViewItem::ICON_WIDTH + + LLFolderViewItem::ICON_PAD + + LLFolderViewItem::ARROW_SIZE + + LLFolderViewItem::TEXT_PAD + + /*first few characters*/ 40; const S32 MINIMUM_RENAMER_WIDTH = 80; -const F32 FOLDER_CLOSE_TIME_CONSTANT = 0.02f; -const F32 FOLDER_OPEN_TIME_CONSTANT = 0.03f; -const S32 MAX_FOLDER_ITEM_OVERLAP = 2; enum { SIGNAL_NO_KEYBOARD_FOCUS = 1, @@ -104,5030 +96,2071 @@ void properties_selected_items(void* user_data); void paste_items(void* user_data); void renamer_focus_lost( LLFocusableElement* handler, void* user_data ); -///---------------------------------------------------------------------------- -/// Class LLFolderViewItem -///---------------------------------------------------------------------------- - -// statics -const LLFontGL* LLFolderViewItem::sFont = NULL; -const LLFontGL* LLFolderViewItem::sSmallFont = NULL; -LLUIImagePtr LLFolderViewItem::sArrowImage; -LLUIImagePtr LLFolderViewItem::sBoxImage; -const LLColor4U DEFAULT_WHITE(255, 255, 255); - -//static -void LLFolderViewItem::initClass() -{ - sFont = LLFontGL::getFontSansSerifSmall(); - sSmallFont = LLFontGL::getFontMonospace(); - sArrowImage = LLUI::getUIImage("folder_arrow.tga"); - sBoxImage = LLUI::getUIImage("rounded_square.tga"); -} +//--------------------------------------------------------------------------- -//static -void LLFolderViewItem::cleanupClass() +// Tells all folders in a folderview to sort their items +// (and only their items, not folders) by a certain function. +class LLSetItemSortFunction : public LLFolderViewFunctor { - sArrowImage = NULL; - sBoxImage = NULL; -} +public: + LLSetItemSortFunction(U32 ordering) + : mSortOrder(ordering) {} + virtual ~LLSetItemSortFunction() {} + virtual void doFolder(LLFolderViewFolder* folder); + virtual void doItem(LLFolderViewItem* item); -// NOTE: Optimize this, we call it a *lot* when opening a large inventory + U32 mSortOrder; +}; -// Default constructor -LLFolderViewItem::LLFolderViewItem(LLFolderViewItem::Params p) -: LLView(p), - mLabelWidth(0), - mLabelWidthDirty(false), - mParentFolder( NULL ), - mIsSelected( FALSE ), - mIsCurSelection( FALSE ), - mSelectPending(FALSE), - mLabelStyle( LLFontGL::NORMAL ), - mHasVisibleChildren(FALSE), - mIndentation(0), - mNumDescendantsSelected(0), - mFiltered(FALSE), - mLastFilterGeneration(-1), - mStringMatchOffset(std::string::npos), - mControlLabelRotation(0.f), - mDragAndDropTarget(FALSE), - mIsLoading(FALSE), - mLabel(p.name), - mRoot(p.root), - mCreationDate(p.creation_date), - mListener(p.listener), - mArrowImage(p.folder_arrow_image), - mBoxImage(p.selection_image) -{ - refresh(); -} -// Destroys the object -LLFolderViewItem::~LLFolderViewItem( void ) +// Set the sort order. +void LLSetItemSortFunction::doFolder(LLFolderViewFolder* folder) { - delete mListener; - mListener = NULL; + folder->setItemSortOrder(mSortOrder); } -LLFolderView* LLFolderViewItem::getRoot() +// Do nothing. +void LLSetItemSortFunction::doItem(LLFolderViewItem* item) { - return mRoot; + return; } -// Returns true if this object is a child (or grandchild, etc.) of potential_ancestor. -BOOL LLFolderViewItem::isDescendantOf( const LLFolderViewFolder* potential_ancestor ) -{ - LLFolderViewItem* root = this; - while( root->mParentFolder ) - { - if( root->mParentFolder == potential_ancestor ) - { - return TRUE; - } - root = root->mParentFolder; - } - return FALSE; -} +//--------------------------------------------------------------------------- -LLFolderViewItem* LLFolderViewItem::getNextOpenNode(BOOL include_children) +// Tells all folders in a folderview to close themselves +// For efficiency, calls setOpenArrangeRecursively(). +// The calling function must then call: +// LLFolderView* root = getRoot(); +// if( root ) +// { +// root->arrange( NULL, NULL ); +// root->scrollToShowSelection(); +// } +// to patch things up. +class LLCloseAllFoldersFunctor : public LLFolderViewFunctor { - if (!mParentFolder) - { - return NULL; - } - - LLFolderViewItem* itemp = mParentFolder->getNextFromChild( this, include_children ); - while(itemp && !itemp->getVisible()) - { - LLFolderViewItem* next_itemp = itemp->mParentFolder->getNextFromChild( itemp, include_children ); - if (itemp == next_itemp) - { - // hit last item - return itemp->getVisible() ? itemp : this; - } - itemp = next_itemp; - } - - return itemp; -} +public: + LLCloseAllFoldersFunctor(BOOL close) { mOpen = !close; } + virtual ~LLCloseAllFoldersFunctor() {} + virtual void doFolder(LLFolderViewFolder* folder); + virtual void doItem(LLFolderViewItem* item); -LLFolderViewItem* LLFolderViewItem::getPreviousOpenNode(BOOL include_children) -{ - if (!mParentFolder) - { - return NULL; - } - - LLFolderViewItem* itemp = mParentFolder->getPreviousFromChild( this, include_children ); - while(itemp && !itemp->getVisible()) - { - LLFolderViewItem* next_itemp = itemp->mParentFolder->getPreviousFromChild( itemp, include_children ); - if (itemp == next_itemp) - { - // hit first item - return itemp->getVisible() ? itemp : this; - } - itemp = next_itemp; - } + BOOL mOpen; +}; - return itemp; -} -// is this item something we think we should be showing? -// for example, if we haven't gotten around to filtering it yet, then the answer is yes -// until we find out otherwise -BOOL LLFolderViewItem::potentiallyVisible() +// Set the sort order. +void LLCloseAllFoldersFunctor::doFolder(LLFolderViewFolder* folder) { - // we haven't been checked against min required filter - // or we have and we passed - return getLastFilterGeneration() < getRoot()->getFilter()->getMinRequiredGeneration() || getFiltered(); + folder->setOpenArrangeRecursively(mOpen); } -BOOL LLFolderViewItem::getFiltered() -{ - return mFiltered && mLastFilterGeneration >= getRoot()->getFilter()->getMinRequiredGeneration(); -} +// Do nothing. +void LLCloseAllFoldersFunctor::doItem(LLFolderViewItem* item) +{ } -BOOL LLFolderViewItem::getFiltered(S32 filter_generation) -{ - return mFiltered && mLastFilterGeneration >= filter_generation; -} +///---------------------------------------------------------------------------- +/// Class LLFolderView +///---------------------------------------------------------------------------- -void LLFolderViewItem::setFiltered(BOOL filtered, S32 filter_generation) -{ - mFiltered = filtered; - mLastFilterGeneration = filter_generation; -} +// Default constructor +LLFolderView::LLFolderView(const Params& p) +: LLFolderViewFolder(p), + mScrollContainer( NULL ), + mPopupMenuHandle(), + mAllowMultiSelect(TRUE), + mShowFolderHierarchy(FALSE), + mSourceID(p.task_id), + mRenameItem( NULL ), + mNeedsScroll( FALSE ), + mLastScrollItem( NULL ), + mNeedsAutoSelect( FALSE ), + mAutoSelectOverride(FALSE), + mNeedsAutoRename(FALSE), + mDebugFilters(FALSE), + mSortOrder(LLInventoryFilter::SO_FOLDERS_BY_NAME), // This gets overridden by a pref immediately + mFilter( new LLInventoryFilter(p.name) ), + mShowSelectionContext(FALSE), + mShowSingleSelection(FALSE), + mArrangeGeneration(0), + mSignalSelectCallback(0), + mMinWidth(0), + mDragAndDropThisFrame(FALSE), + mCallbackRegistrar(NULL), + mParentPanel(p.parent_panel) -void LLFolderViewItem::setIcon(LLUIImagePtr icon) { - mIcon = icon; -} + LLRect rect = p.rect; + LLRect new_rect(rect.mLeft, rect.mBottom + getRect().getHeight(), rect.mLeft + getRect().getWidth(), rect.mBottom); + setRect( rect ); + reshape(rect.getWidth(), rect.getHeight()); + mIsOpen = TRUE; // this view is always open. + mAutoOpenItems.setDepth(AUTO_OPEN_STACK_DEPTH); + mAutoOpenCandidate = NULL; + mAutoOpenTimer.stop(); + mKeyboardSelection = FALSE; + mIndentation = -LEFT_INDENTATION; // children start at indentation 0 + gIdleCallbacks.addFunction(idle, this); -// refresh information from the listener -void LLFolderViewItem::refreshFromListener() -{ - if(mListener) - { - mLabel = mListener->getDisplayName(); - LLAssetType::EType preferred_type = mListener->getPreferredType(); + //clear label + // go ahead and render root folder as usual + // just make sure the label ("Inventory Folder") never shows up + mLabel = LLStringUtil::null; - // *TODO: to be removed when database supports multi language. This is a - // temporary attempt to display the inventory folder in the user locale. - if (preferred_type != LLAssetType::AT_NONE) - { - mLabel = LLTrans::getString("InvFolder " + mLabel); - }; + //mRenamer->setWriteableBgColor(LLColor4::white); + // Escape is handled by reverting the rename, not commiting it (default behavior) + LLLineEditor::Params params; + params.name("ren"); + params.rect(getRect()); + params.font(sFont); + params.max_length_bytes(DB_INV_ITEM_NAME_STR_LEN); + params.commit_callback.function(boost::bind(&LLFolderView::commitRename, this, _2)); + params.prevalidate_callback(&LLLineEditor::prevalidatePrintableNotPipe); + params.commit_on_focus_lost(true); + params.visible(false); + mRenamer = LLUICtrlFactory::create<LLLineEditor> (params); + addChild(mRenamer); - setIcon(mListener->getIcon()); - time_t creation_date = mListener->getCreationDate(); - if (mCreationDate != creation_date) - { - mCreationDate = mListener->getCreationDate(); - dirtyFilter(); - } - mLabelStyle = mListener->getLabelStyle(); - mLabelSuffix = mListener->getLabelSuffix(); + // make the popup menu available + LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_inventory.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); + if (!menu) + { + menu = LLUICtrlFactory::getDefaultWidget<LLMenuGL>("inventory_menu"); } + menu->setBackgroundColor(LLUIColorTable::instance().getColor("MenuPopupBgColor")); + mPopupMenuHandle = menu->getHandle(); + } -void LLFolderViewItem::refresh() +// Destroys the object +LLFolderView::~LLFolderView( void ) { - refreshFromListener(); - - std::string searchable_label(mLabel); - searchable_label.append(mLabelSuffix); - LLStringUtil::toUpper(searchable_label); + // The release focus call can potentially call the + // scrollcontainer, which can potentially be called with a partly + // destroyed scollcontainer. Just null it out here, and no worries + // about calling into the invalid scroll container. + // Same with the renamer. + mScrollContainer = NULL; + mRenameItem = NULL; + mRenamer = NULL; - if (mSearchableLabel.compare(searchable_label)) + if( gEditMenuHandler == this ) { - mSearchableLabel.assign(searchable_label); - dirtyFilter(); - // some part of label has changed, so overall width has potentially changed, and sort order too - if (mParentFolder) - { - mParentFolder->requestSort(); - mParentFolder->requestArrange(); - } + gEditMenuHandler = NULL; } - mLabelWidthDirty = true; -} - -void LLFolderViewItem::applyListenerFunctorRecursively(LLFolderViewListenerFunctor& functor) -{ - functor(mListener); -} - -// This function is called when items are added or view filters change. It's -// implemented here but called by derived classes when folding the -// views. -void LLFolderViewItem::filterFromRoot( void ) -{ - LLFolderViewItem* root = getRoot(); + mAutoOpenItems.removeAllNodes(); + gIdleCallbacks.deleteFunction(idle, this); - root->filter(*((LLFolderView*)root)->getFilter()); -} + LLView::deleteViewByHandle(mPopupMenuHandle); -// This function is called when the folder view is dirty. It's -// implemented here but called by derived classes when folding the -// views. -void LLFolderViewItem::arrangeFromRoot() -{ - LLFolderViewItem* root = getRoot(); + if(mRenamer == gFocusMgr.getTopCtrl()) + { + gFocusMgr.setTopCtrl(NULL); + } - S32 height = 0; - S32 width = 0; - root->arrange( &width, &height, 0 ); -} + mAutoOpenItems.removeAllNodes(); + clearSelection(); + mItems.clear(); + mFolders.clear(); -// This function clears the currently selected item, and records the -// specified selected item appropriately for display and use in the -// UI. If open is TRUE, then folders are opened up along the way to -// the selection. -void LLFolderViewItem::setSelectionFromRoot(LLFolderViewItem* selection, - BOOL openitem, - BOOL take_keyboard_focus) -{ - getRoot()->setSelection(selection, openitem, take_keyboard_focus); -} + mItemMap.clear(); -// helper function to change the selection from the root. -void LLFolderViewItem::changeSelectionFromRoot(LLFolderViewItem* selection, BOOL selected) -{ - getRoot()->changeSelection(selection, selected); + delete mFilter; + mFilter = NULL; } -void LLFolderViewItem::extendSelectionFromRoot(LLFolderViewItem* selection) +BOOL LLFolderView::canFocusChildren() const { - LLDynamicArray<LLFolderViewItem*> selected_items; - - getRoot()->extendSelection(selection, NULL, selected_items); -} - -EInventorySortGroup LLFolderViewItem::getSortGroup() const -{ - return SG_ITEM; + return FALSE; } -// addToFolder() returns TRUE if it succeeds. FALSE otherwise -BOOL LLFolderViewItem::addToFolder(LLFolderViewFolder* folder, LLFolderView* root) +void LLFolderView::checkTreeResortForModelChanged() { - if (!folder) + if (mSortOrder & LLInventoryFilter::SO_DATE && !(mSortOrder & LLInventoryFilter::SO_FOLDERS_BY_NAME)) { - return FALSE; + // This is the case where something got added or removed. If we are date sorting + // everything including folders, then we need to rebuild the whole tree. + // Just set to something not SO_DATE to force the folder most resent date resort. + mSortOrder = mSortOrder & ~LLInventoryFilter::SO_DATE; + setSortOrder(mSortOrder | LLInventoryFilter::SO_DATE); } - mParentFolder = folder; - root->addItemID(getListener()->getUUID(), this); - return folder->addItem(this); } - -// Finds width and height of this object and it's children. Also -// makes sure that this view and it's children are the right size. -S32 LLFolderViewItem::arrange( S32* width, S32* height, S32 filter_generation) +void LLFolderView::setSortOrder(U32 order) { - mIndentation = mParentFolder ? mParentFolder->getIndentation() + LEFT_INDENTATION : 0; - if (mLabelWidthDirty) + if (order != mSortOrder) { - mLabelWidth = ARROW_SIZE + TEXT_PAD + ICON_WIDTH + ICON_PAD + sFont->getWidth(mSearchableLabel); - mLabelWidthDirty = false; - } - - *width = llmax(*width, mLabelWidth + mIndentation); - *height = getItemHeight(); - return *height; -} - -S32 LLFolderViewItem::getItemHeight() -{ - S32 icon_height = mIcon->getHeight(); - S32 label_height = llround(sFont->getLineHeight()); - return llmax( icon_height, label_height ) + ICON_PAD; -} + LLFastTimer t(LLFastTimer::FTM_SORT); + mSortOrder = order; -void LLFolderViewItem::filter( LLInventoryFilter& filter) -{ - BOOL filtered = mListener && filter.check(this); - - // if our visibility will change as a result of this filter, then - // we need to be rearranged in our parent folder - if (getVisible() != filtered) - { - if (mParentFolder) + for (folders_t::iterator iter = mFolders.begin(); + iter != mFolders.end();) { - mParentFolder->requestArrange(); + folders_t::iterator fit = iter++; + (*fit)->sortBy(order); } - } - setFiltered(filtered, filter.getCurrentGeneration()); - mStringMatchOffset = filter.getStringMatchOffset(); - filter.decrementFilterCount(); - - if (getRoot()->getDebugFilters()) - { - mStatusText = llformat("%d", mLastFilterGeneration); + arrangeAll(); } } -void LLFolderViewItem::dirtyFilter() + +U32 LLFolderView::getSortOrder() const { - mLastFilterGeneration = -1; - // bubble up dirty flag all the way to root - if (getParentFolder()) - { - getParentFolder()->setCompletedFilterGeneration(-1, TRUE); - } + return mSortOrder; } -// *TODO: This can be optimized a lot by simply recording that it is -// selected in the appropriate places, and assuming that set selection -// means 'deselect' for a leaf item. Do this optimization after -// multiple selection is implemented to make sure it all plays nice -// together. -BOOL LLFolderViewItem::setSelection(LLFolderViewItem* selection, BOOL openitem, BOOL take_keyboard_focus) +BOOL LLFolderView::addFolder( LLFolderViewFolder* folder) { - if( selection == this ) + // enforce sort order of My Inventory followed by Library + if (folder->getListener()->getUUID() == gInventory.getLibraryRootFolderID()) { - mIsSelected = TRUE; - if(mListener) - { - mListener->selectItem(); - } + mFolders.push_back(folder); } else { - mIsSelected = FALSE; + mFolders.insert(mFolders.begin(), folder); } - return mIsSelected; + folder->setOrigin(0, 0); + folder->reshape(getRect().getWidth(), 0); + folder->setVisible(FALSE); + addChild( folder ); + folder->dirtyFilter(); + folder->requestArrange(); + return TRUE; } -BOOL LLFolderViewItem::changeSelection(LLFolderViewItem* selection, BOOL selected) +void LLFolderView::closeAllFolders() { - if(selection == this && mIsSelected != selected) - { - mIsSelected = selected; - if(mListener) - { - mListener->selectItem(); - } - return TRUE; - } - return FALSE; + // Close all the folders + setOpenArrangeRecursively(FALSE, LLFolderViewFolder::RECURSE_DOWN); + arrangeAll(); } -void LLFolderViewItem::recursiveDeselect(BOOL deselect_self) +void LLFolderView::openFolder(const std::string& foldername) { - if (mIsSelected && deselect_self) + LLFolderViewFolder* inv = findChild<LLFolderViewFolder>(foldername); + if (inv) { - mIsSelected = FALSE; - - // update ancestors' count of selected descendents - LLFolderViewFolder* parent_folder = getParentFolder(); - while(parent_folder) - { - parent_folder->mNumDescendantsSelected--; - parent_folder = parent_folder->getParentFolder(); - } + setSelection(inv, FALSE, FALSE); + inv->setOpen(TRUE); } } - -BOOL LLFolderViewItem::isMovable() +void LLFolderView::setOpenArrangeRecursively(BOOL openitem, ERecurseType recurse) { - if( mListener ) - { - return mListener->isItemMovable(); - } - else - { - return TRUE; - } + // call base class to do proper recursion + LLFolderViewFolder::setOpenArrangeRecursively(openitem, recurse); + // make sure root folder is always open + mIsOpen = TRUE; } -BOOL LLFolderViewItem::isRemovable() +// This view grows and shinks to enclose all of its children items and folders. +S32 LLFolderView::arrange( S32* unused_width, S32* unused_height, S32 filter_generation ) { - if( mListener ) - { - return mListener->isItemRemovable(); - } - else - { - return TRUE; - } -} + LLFastTimer t2(LLFastTimer::FTM_ARRANGE); -void LLFolderViewItem::destroyView() -{ - if (mParentFolder) - { - // removeView deletes me - mParentFolder->removeView(this); - } -} + filter_generation = mFilter->getMinRequiredGeneration(); + mMinWidth = 0; -// Call through to the viewed object and return true if it can be -// removed. -//BOOL LLFolderViewItem::removeRecursively(BOOL single_item) -BOOL LLFolderViewItem::remove() -{ - if(!isRemovable()) + mHasVisibleChildren = hasFilteredDescendants(filter_generation); + // arrange always finishes, so optimistically set the arrange generation to the most current + mLastArrangeGeneration = getRoot()->getArrangeGeneration(); + + LLInventoryFilter::EFolderShow show_folder_state = + getRoot()->getFilter()->getShowFolderState(); + + S32 total_width = LEFT_PAD; + S32 running_height = mDebugFilters ? llceil(sSmallFont->getLineHeight()) : 0; + S32 target_height = running_height; + S32 parent_item_height = getRect().getHeight(); + + for (folders_t::iterator iter = mFolders.begin(); + iter != mFolders.end();) { - return FALSE; + folders_t::iterator fit = iter++; + LLFolderViewFolder* folderp = (*fit); + if (getDebugFilters()) + { + folderp->setVisible(TRUE); + } + else + { + folderp->setVisible(show_folder_state == LLInventoryFilter::SHOW_ALL_FOLDERS || // always show folders? + (folderp->getFiltered(filter_generation) || folderp->hasFilteredDescendants(filter_generation))); // passed filter or has descendants that passed filter + } + if (folderp->getVisible()) + { + S32 child_height = 0; + S32 child_width = 0; + S32 child_top = parent_item_height - running_height; + + target_height += folderp->arrange( &child_width, &child_height, filter_generation ); + + mMinWidth = llmax(mMinWidth, child_width); + total_width = llmax( total_width, child_width ); + running_height += child_height; + folderp->setOrigin( ICON_PAD, child_top - (*fit)->getRect().getHeight() ); + } } - if(mListener) + + for (items_t::iterator iter = mItems.begin(); + iter != mItems.end();) { - return mListener->removeItem(); + items_t::iterator iit = iter++; + LLFolderViewItem* itemp = (*iit); + itemp->setVisible(itemp->getFiltered(filter_generation)); + + if (itemp->getVisible()) + { + S32 child_width = 0; + S32 child_height = 0; + S32 child_top = parent_item_height - running_height; + + target_height += itemp->arrange( &child_width, &child_height, filter_generation ); + itemp->reshape(itemp->getRect().getWidth(), child_height); + + mMinWidth = llmax(mMinWidth, child_width); + total_width = llmax( total_width, child_width ); + running_height += child_height; + itemp->setOrigin( ICON_PAD, child_top - itemp->getRect().getHeight() ); + } } - return TRUE; -} -// Build an appropriate context menu for the item. -void LLFolderViewItem::buildContextMenu(LLMenuGL& menu, U32 flags) -{ - if(mListener) + S32 dummy_s32; + BOOL dummy_bool; + S32 min_width; + mScrollContainer->calcVisibleSize( &min_width, &dummy_s32, &dummy_bool, &dummy_bool); + reshape( llmax(min_width, total_width), running_height ); + + S32 new_min_width; + mScrollContainer->calcVisibleSize( &new_min_width, &dummy_s32, &dummy_bool, &dummy_bool); + if (new_min_width != min_width) { - mListener->buildContextMenu(menu, flags); + reshape( llmax(min_width, total_width), running_height ); } + + // move item renamer text field to item's new position + updateRenamerPosition(); + + mTargetHeight = (F32)target_height; + return llround(mTargetHeight); } -void LLFolderViewItem::openItem( void ) +const std::string LLFolderView::getFilterSubString(BOOL trim) { - if( mListener ) - { - mListener->openItem(); - } + return mFilter->getFilterSubString(trim); } -void LLFolderViewItem::preview( void ) +void LLFolderView::filter( LLInventoryFilter& filter ) { - if (mListener) + LLFastTimer t2(LLFastTimer::FTM_FILTER); + filter.setFilterCount(llclamp(gSavedSettings.getS32("FilterItemsPerFrame"), 1, 5000)); + + if (getCompletedFilterGeneration() < filter.getCurrentGeneration()) { - mListener->previewItem(); + mFiltered = FALSE; + mMinWidth = 0; + LLFolderViewFolder::filter(filter); } } -void LLFolderViewItem::rename(const std::string& new_name) +void LLFolderView::reshape(S32 width, S32 height, BOOL called_from_parent) { - if( !new_name.empty() ) + S32 min_width = 0; + S32 dummy_height; + BOOL dummy_bool; + if (mScrollContainer) { - if( mListener ) - { - mListener->renameItem(new_name); - - if(mParentFolder) - { - mParentFolder->requestSort(); - } - } + mScrollContainer->calcVisibleSize( &min_width, &dummy_height, &dummy_bool, &dummy_bool); } -} + width = llmax(mMinWidth, min_width); + LLView::reshape(width, height, called_from_parent); -const std::string& LLFolderViewItem::getSearchableLabel() const -{ - return mSearchableLabel; + mReshapeSignal(mSelectedItems, FALSE); } -const std::string& LLFolderViewItem::getName( void ) const +void LLFolderView::addToSelectionList(LLFolderViewItem* item) { - if(mListener) + if (item->isSelected()) { - return mListener->getName(); + removeFromSelectionList(item); } - return mLabel; -} - -// LLView functionality -BOOL LLFolderViewItem::handleRightMouseDown( S32 x, S32 y, MASK mask ) -{ - if(!mIsSelected) + if (mSelectedItems.size()) { - setSelectionFromRoot(this, FALSE); + mSelectedItems.back()->setIsCurSelection(FALSE); } - make_ui_sound("UISndClick"); - return TRUE; + item->setIsCurSelection(TRUE); + mSelectedItems.push_back(item); } -BOOL LLFolderViewItem::handleMouseDown( S32 x, S32 y, MASK mask ) +void LLFolderView::removeFromSelectionList(LLFolderViewItem* item) { - // No handler needed for focus lost since this class has no - // state that depends on it. - gFocusMgr.setMouseCapture( this ); + if (mSelectedItems.size()) + { + mSelectedItems.back()->setIsCurSelection(FALSE); + } - if (!mIsSelected) + selected_items_t::iterator item_iter; + for (item_iter = mSelectedItems.begin(); item_iter != mSelectedItems.end();) { - if(mask & MASK_CONTROL) - { - changeSelectionFromRoot(this, !mIsSelected); - } - else if (mask & MASK_SHIFT) + if (*item_iter == item) { - extendSelectionFromRoot(this); + item_iter = mSelectedItems.erase(item_iter); } else { - setSelectionFromRoot(this, FALSE); + ++item_iter; } - make_ui_sound("UISndClick"); } - else + if (mSelectedItems.size()) { - mSelectPending = TRUE; + mSelectedItems.back()->setIsCurSelection(TRUE); } +} - if( isMovable() ) +LLFolderViewItem* LLFolderView::getCurSelectedItem( void ) +{ + if(mSelectedItems.size()) { - S32 screen_x; - S32 screen_y; - localPointToScreen(x, y, &screen_x, &screen_y ); - LLToolDragAndDrop::getInstance()->setDragStart( screen_x, screen_y ); + LLFolderViewItem* itemp = mSelectedItems.back(); + llassert(itemp->getIsCurSelection()); + return itemp; } - return TRUE; + return NULL; } -BOOL LLFolderViewItem::handleHover( S32 x, S32 y, MASK mask ) + +// Record the selected item and pass it down the hierachy. +BOOL LLFolderView::setSelection(LLFolderViewItem* selection, BOOL openitem, + BOOL take_keyboard_focus) { - if( hasMouseCapture() && isMovable() ) + if( selection == this ) { - S32 screen_x; - S32 screen_y; - localPointToScreen(x, y, &screen_x, &screen_y ); - BOOL can_drag = TRUE; - if( LLToolDragAndDrop::getInstance()->isOverThreshold( screen_x, screen_y ) ) - { - LLFolderView* root = getRoot(); - - if(root->getCurSelectedItem()) - { - LLToolDragAndDrop::ESource src = LLToolDragAndDrop::SOURCE_WORLD; - - // *TODO: push this into listener and remove - // dependency on llagent - if(mListener && gInventory.isObjectDescendentOf(mListener->getUUID(), gAgent.getInventoryRootID())) - { - src = LLToolDragAndDrop::SOURCE_AGENT; - } - else if (mListener && gInventory.isObjectDescendentOf(mListener->getUUID(), gInventoryLibraryRoot)) - { - src = LLToolDragAndDrop::SOURCE_LIBRARY; - } - - can_drag = root->startDrag(src); - if (can_drag) - { - // if (mListener) mListener->startDrag(); - // RN: when starting drag and drop, clear out last auto-open - root->autoOpenTest(NULL); - root->setShowSelectionContext(TRUE); + return FALSE; + } - // Release keyboard focus, so that if stuff is dropped into the - // world, pressing the delete key won't blow away the inventory - // item. - gFocusMgr.setKeyboardFocus(NULL); + if( selection && take_keyboard_focus) + { + mParentPanel->setFocus(TRUE); + } - return LLToolDragAndDrop::getInstance()->handleHover( x, y, mask ); - } - } - } + // clear selection down here because change of keyboard focus can potentially + // affect selection + clearSelection(); - if (can_drag) - { - gViewerWindow->setCursor(UI_CURSOR_ARROW); - } - else - { - gViewerWindow->setCursor(UI_CURSOR_NOLOCKED); - } - return TRUE; + if(selection) + { + addToSelectionList(selection); } - else + + BOOL rv = LLFolderViewFolder::setSelection(selection, openitem, take_keyboard_focus); + if(openitem && selection) { - getRoot()->setShowSelectionContext(FALSE); - gViewerWindow->setCursor(UI_CURSOR_ARROW); - // let parent handle this then... - return FALSE; + selection->getParentFolder()->requestArrange(); } -} + llassert(mSelectedItems.size() <= 1); -BOOL LLFolderViewItem::handleDoubleClick( S32 x, S32 y, MASK mask ) -{ - preview(); - return TRUE; + mSignalSelectCallback = take_keyboard_focus ? SIGNAL_KEYBOARD_FOCUS : SIGNAL_NO_KEYBOARD_FOCUS; + + return rv; } -BOOL LLFolderViewItem::handleScrollWheel(S32 x, S32 y, S32 clicks) +void LLFolderView::setSelectionByID(const LLUUID& obj_id, BOOL take_keyboard_focus) { - if (getParent()) + LLFolderViewItem* itemp = getItemByID(obj_id); + if(itemp && itemp->getListener()) + { + itemp->arrangeAndSet(TRUE, take_keyboard_focus); + mSelectThisID.setNull(); + return; + } + else { - return getParent()->handleScrollWheel(x, y, clicks); + // save the desired item to be selected later (if/when ready) + mSelectThisID = obj_id; } - return FALSE; } -BOOL LLFolderViewItem::handleMouseUp( S32 x, S32 y, MASK mask ) +void LLFolderView::updateSelection() { - // if mouse hasn't moved since mouse down... - if ( pointInView(x, y) && mSelectPending ) + if (mSelectThisID.notNull()) { - //...then select - if(mask & MASK_CONTROL) - { - changeSelectionFromRoot(this, !mIsSelected); - } - else if (mask & MASK_SHIFT) - { - extendSelectionFromRoot(this); - } - else - { - setSelectionFromRoot(this, FALSE); - } + setSelectionByID(mSelectThisID, false); + } +} + +BOOL LLFolderView::changeSelection(LLFolderViewItem* selection, BOOL selected) +{ + BOOL rv = FALSE; + + // can't select root folder + if(!selection || selection == this) + { + return FALSE; } - - mSelectPending = FALSE; - if( hasMouseCapture() ) + if (!mAllowMultiSelect) { - getRoot()->setShowSelectionContext(FALSE); - gFocusMgr.setMouseCapture( NULL ); + clearSelection(); } - return TRUE; -} -BOOL LLFolderViewItem::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, - EDragAndDropType cargo_type, - void* cargo_data, - EAcceptance* accept, - std::string& tooltip_msg) -{ - BOOL accepted = FALSE; - BOOL handled = FALSE; - if(mListener) + selected_items_t::iterator item_iter; + for (item_iter = mSelectedItems.begin(); item_iter != mSelectedItems.end(); ++item_iter) { - accepted = mListener->dragOrDrop(mask,drop,cargo_type,cargo_data); - handled = accepted; - if (accepted) - { - mDragAndDropTarget = TRUE; - *accept = ACCEPT_YES_MULTI; - } - else + if (*item_iter == selection) { - *accept = ACCEPT_NO; + break; } } - if(mParentFolder && !handled) + + BOOL on_list = (item_iter != mSelectedItems.end()); + + if(selected && !on_list) { - handled = mParentFolder->handleDragAndDropFromChild(mask,drop,cargo_type,cargo_data,accept,tooltip_msg); + addToSelectionList(selection); } - if (handled) + if(!selected && on_list) { - lldebugst(LLERR_USER_INPUT) << "dragAndDrop handled by LLFolderViewItem" << llendl; + removeFromSelectionList(selection); } - return handled; -} + rv = LLFolderViewFolder::changeSelection(selection, selected); + mSignalSelectCallback = SIGNAL_KEYBOARD_FOCUS; + + return rv; +} -void LLFolderViewItem::draw() +S32 LLFolderView::extendSelection(LLFolderViewItem* selection, LLFolderViewItem* last_selected, LLDynamicArray<LLFolderViewItem*>& items) { - static LLUIColor sFgColor = LLUIColorTable::instance().getColor("MenuItemEnabledColor", DEFAULT_WHITE); - static LLUIColor sHighlightBgColor = LLUIColorTable::instance().getColor("MenuItemHighlightBgColor", DEFAULT_WHITE); - static LLUIColor sHighlightFgColor = LLUIColorTable::instance().getColor("MenuItemHighlightFgColor", DEFAULT_WHITE); - static LLUIColor sFilterBGColor = LLUIColorTable::instance().getColor("FilterBackgroundColor", DEFAULT_WHITE); - static LLUIColor sFilterTextColor = LLUIColorTable::instance().getColor("FilterTextColor", DEFAULT_WHITE); - static LLUIColor sSuffixColor = LLUIColorTable::instance().getColor("InventoryItemSuffixColor", DEFAULT_WHITE); - static LLUIColor sSearchStatusColor = LLUIColorTable::instance().getColor("InventorySearchStatusColor", DEFAULT_WHITE); - - bool possibly_has_children = false; - bool up_to_date = mListener && mListener->isUpToDate(); - if((up_to_date && hasVisibleChildren() ) || // we fetched our children and some of them have passed the filter... - (!up_to_date && mListener && mListener->hasChildren())) // ...or we know we have children but haven't fetched them (doesn't obey filter) - { - possibly_has_children = true; - } - if(/*mControlLabel[0] != '\0' && */possibly_has_children) + S32 rv = 0; + + // now store resulting selection + if (mAllowMultiSelect) { - if (sArrowImage) + LLFolderViewItem *cur_selection = getCurSelectedItem(); + rv = LLFolderViewFolder::extendSelection(selection, cur_selection, items); + for (S32 i = 0; i < items.count(); i++) { - gl_draw_scaled_rotated_image(mIndentation, getRect().getHeight() - ARROW_SIZE - TEXT_PAD, - ARROW_SIZE, ARROW_SIZE, mControlLabelRotation, sArrowImage->getImage(), sFgColor); + addToSelectionList(items[i]); + rv++; } } + else + { + setSelection(selection, FALSE, FALSE); + rv++; + } + + mSignalSelectCallback = SIGNAL_KEYBOARD_FOCUS; + return rv; +} - F32 text_left = (F32)(ARROW_SIZE + TEXT_PAD + ICON_WIDTH + ICON_PAD + mIndentation); +void LLFolderView::sanitizeSelection() +{ + // store off current item in case it is automatically deselected + // and we want to preserve context + LLFolderViewItem* original_selected_item = getCurSelectedItem(); - // If we have keyboard focus, draw selection filled - BOOL show_context = getRoot()->getShowSelectionContext(); - BOOL filled = show_context || (getRoot()->getParentPanel()->hasFocus()); + // Cache "Show all folders" filter setting + BOOL show_all_folders = (getRoot()->getFilter()->getShowFolderState() == LLInventoryFilter::SHOW_ALL_FOLDERS); - // always render "current" item, only render other selected items if - // mShowSingleSelection is FALSE - if( mIsSelected ) + std::vector<LLFolderViewItem*> items_to_remove; + selected_items_t::iterator item_iter; + for (item_iter = mSelectedItems.begin(); item_iter != mSelectedItems.end(); ++item_iter) { - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - LLColor4 bg_color = sHighlightBgColor; - //const S32 TRAILING_PAD = 5; // It just looks better with this. - if (!mIsCurSelection) + LLFolderViewItem* item = *item_iter; + + // ensure that each ancestor is open and potentially passes filtering + BOOL visible = item->potentiallyVisible(); // initialize from filter state for this item + // modify with parent open and filters states + LLFolderViewFolder* parent_folder = item->getParentFolder(); + if ( parent_folder ) { - // do time-based fade of extra objects - F32 fade_time = getRoot()->getSelectionFadeElapsedTime(); - if (getRoot()->getShowSingleSelection()) - { - // fading out - bg_color.mV[VALPHA] = clamp_rescale(fade_time, 0.f, 0.4f, bg_color.mV[VALPHA], 0.f); + if ( show_all_folders ) + { // "Show all folders" is on, so this folder is visible + visible = TRUE; } else - { - // fading in - bg_color.mV[VALPHA] = clamp_rescale(fade_time, 0.f, 0.4f, 0.f, bg_color.mV[VALPHA]); + { // Move up through parent folders and see what's visible + while(parent_folder) + { + visible = visible && parent_folder->isOpen() && parent_folder->potentiallyVisible(); + parent_folder = parent_folder->getParentFolder(); + } } } - gl_rect_2d( - 0, - getRect().getHeight(), - getRect().getWidth() - 2, - llfloor(getRect().getHeight() - sFont->getLineHeight() - ICON_PAD), - bg_color, filled); - if (mIsCurSelection) + // deselect item if any ancestor is closed or didn't pass filter requirements. + if (!visible) { - gl_rect_2d( - 0, - getRect().getHeight(), - getRect().getWidth() - 2, - llfloor(getRect().getHeight() - sFont->getLineHeight() - ICON_PAD), - sHighlightFgColor, FALSE); + items_to_remove.push_back(item); } - if (getRect().getHeight() > llround(sFont->getLineHeight()) + ICON_PAD + 2) + + // disallow nested selections (i.e. folder items plus one or more ancestors) + // could check cached mum selections count and only iterate if there are any + // but that may be a premature optimization. + selected_items_t::iterator other_item_iter; + for (other_item_iter = mSelectedItems.begin(); other_item_iter != mSelectedItems.end(); ++other_item_iter) { - gl_rect_2d( - 0, - llfloor(getRect().getHeight() - sFont->getLineHeight() - ICON_PAD) - 2, - getRect().getWidth() - 2, - 2, - sHighlightFgColor, FALSE); - if (show_context) + LLFolderViewItem* other_item = *other_item_iter; + for( parent_folder = other_item->getParentFolder(); parent_folder; parent_folder = parent_folder->getParentFolder()) { - gl_rect_2d( - 0, - llfloor(getRect().getHeight() - sFont->getLineHeight() - ICON_PAD) - 2, - getRect().getWidth() - 2, - 2, - sHighlightBgColor, TRUE); + if (parent_folder == item) + { + // this is a descendent of the current folder, remove from list + items_to_remove.push_back(other_item); + break; + } } } } - if (mDragAndDropTarget) - { - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gl_rect_2d( - 0, - getRect().getHeight(), - getRect().getWidth() - 2, - llfloor(getRect().getHeight() - sFont->getLineHeight() - ICON_PAD), - sHighlightBgColor, FALSE); - - if (getRect().getHeight() > llround(sFont->getLineHeight()) + ICON_PAD + 2) - { - gl_rect_2d( - 0, - llfloor(getRect().getHeight() - sFont->getLineHeight() - ICON_PAD) - 2, - getRect().getWidth() - 2, - 2, - sHighlightBgColor, FALSE); - } - mDragAndDropTarget = FALSE; - } - - if(mIcon) + std::vector<LLFolderViewItem*>::iterator item_it; + for (item_it = items_to_remove.begin(); item_it != items_to_remove.end(); ++item_it ) { - mIcon->draw(mIndentation + ARROW_SIZE + TEXT_PAD, getRect().getHeight() - mIcon->getHeight()); + changeSelection(*item_it, FALSE); // toggle selection (also removes from list) } - if (!mLabel.empty()) + // if nothing selected after prior constraints... + if (mSelectedItems.empty()) { - // highlight filtered text - BOOL debug_filters = getRoot()->getDebugFilters(); - LLColor4 color = ( (mIsSelected && filled) ? sHighlightFgColor : sFgColor ); - F32 right_x; - F32 y = (F32)getRect().getHeight() - sFont->getLineHeight() - (F32)TEXT_PAD; - - if (debug_filters) + // ...select first available parent of original selection, or "My Inventory" otherwise + LLFolderViewItem* new_selection = NULL; + if (original_selected_item) { - if (!getFiltered() && !possibly_has_children) + for(LLFolderViewFolder* parent_folder = original_selected_item->getParentFolder(); + parent_folder; + parent_folder = parent_folder->getParentFolder()) { - color.mV[VALPHA] *= 0.5f; + if (parent_folder->potentiallyVisible()) + { + // give initial selection to first ancestor folder that potentially passes the filter + if (!new_selection) + { + new_selection = parent_folder; + } + + // if any ancestor folder of original item is closed, move the selection up + // to the highest closed + if (!parent_folder->isOpen()) + { + new_selection = parent_folder; + } + } } - - LLColor4 filter_color = mLastFilterGeneration >= getRoot()->getFilter()->getCurrentGeneration() ? LLColor4(0.5f, 0.8f, 0.5f, 1.f) : LLColor4(0.8f, 0.5f, 0.5f, 1.f); - sSmallFont->renderUTF8(mStatusText, 0, text_left, y, filter_color, - LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, - S32_MAX, S32_MAX, &right_x, FALSE ); - text_left = right_x; } - - - if ( mIsLoading && mTimeSinceRequestStart.getElapsedTimeF32() >= gSavedSettings.getF32("FolderLoadingMessageWaitTime") ) + else { - sFont->renderUTF8(LLTrans::getString("LoadingData"), 0, text_left, y, sSearchStatusColor, - LLFontGL::LEFT, LLFontGL::BOTTOM, mLabelStyle, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, &right_x, FALSE); - text_left = right_x; + // nothing selected to start with, so pick "My Inventory" as best guess + new_selection = getItemByID(gInventory.getRootFolderID()); } - sFont->renderUTF8( mLabel, 0, text_left, y, color, - LLFontGL::LEFT, LLFontGL::BOTTOM, mLabelStyle, LLFontGL::NO_SHADOW, - S32_MAX, S32_MAX, &right_x, FALSE ); - if (!mLabelSuffix.empty()) + if (new_selection) { - sFont->renderUTF8( mLabelSuffix, 0, right_x, y, sSuffixColor, - LLFontGL::LEFT, LLFontGL::BOTTOM, mLabelStyle, LLFontGL::NO_SHADOW, - S32_MAX, S32_MAX, &right_x, FALSE ); + setSelection(new_selection, FALSE, FALSE); } + } +} - if (sBoxImage.notNull() && mStringMatchOffset != std::string::npos) - { - // don't draw backgrounds for zero-length strings - S32 filter_string_length = getRoot()->getFilterSubString().size(); - if (filter_string_length > 0) - { - std::string combined_string = mLabel + mLabelSuffix; - S32 left = llround(text_left) + sFont->getWidth(combined_string, 0, mStringMatchOffset) - 1; - S32 right = left + sFont->getWidth(combined_string, mStringMatchOffset, filter_string_length) + 2; - S32 bottom = llfloor(getRect().getHeight() - sFont->getLineHeight() - 3); - S32 top = getRect().getHeight(); - - LLRect box_rect(left, top, right, bottom); - sBoxImage->draw(box_rect, sFilterBGColor); - F32 match_string_left = text_left + sFont->getWidthF32(combined_string, 0, mStringMatchOffset); - F32 y = (F32)getRect().getHeight() - sFont->getLineHeight() - (F32)TEXT_PAD; - sFont->renderUTF8( combined_string, mStringMatchOffset, match_string_left, y, - sFilterTextColor, LLFontGL::LEFT, LLFontGL::BOTTOM, mLabelStyle, LLFontGL::NO_SHADOW, - filter_string_length, S32_MAX, &right_x, FALSE ); - } - } +void LLFolderView::clearSelection() +{ + if (mSelectedItems.size() > 0) + { + recursiveDeselect(FALSE); + mSelectedItems.clear(); } + mSelectThisID.setNull(); +} - if( sDebugRects ) +BOOL LLFolderView::getSelectionList(std::set<LLUUID> &selection) +{ + selected_items_t::iterator item_it; + for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) { - drawDebugRect(); + selection.insert((*item_it)->getListener()->getUUID()); } - //// *HACK: also draw debug rectangles around currently-being-edited LLView, and any elements that are being highlighted by GUI preview code (see LLFloaterUIPreview) - //std::set<LLView*>::iterator iter = std::find(sPreviewHighlightedElements.begin(), sPreviewHighlightedElements.end(), this); - //if ((sEditingUI && this == sEditingUIView) || (iter != sPreviewHighlightedElements.end() && sDrawPreviewHighlights)) - //{ - // drawDebugRect(); - //} + return (selection.size() != 0); } +BOOL LLFolderView::startDrag(LLToolDragAndDrop::ESource source) +{ + std::vector<EDragAndDropType> types; + std::vector<LLUUID> cargo_ids; + selected_items_t::iterator item_it; + BOOL can_drag = TRUE; + if (!mSelectedItems.empty()) + { + for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) + { + EDragAndDropType type = DAD_NONE; + LLUUID id = LLUUID::null; + can_drag = can_drag && (*item_it)->getListener()->startDrag(&type, &id); -///---------------------------------------------------------------------------- -/// Class LLFolderViewFolder -///---------------------------------------------------------------------------- + types.push_back(type); + cargo_ids.push_back(id); + } -LLFolderViewFolder::LLFolderViewFolder( const LLFolderViewItem::Params& p ): - LLFolderViewItem( p ), // 0 = no create time - mIsOpen(FALSE), - mExpanderHighlighted(FALSE), - mCurHeight(0.f), - mTargetHeight(0.f), - mAutoOpenCountdown(0.f), - mSubtreeCreationDate(0), - mAmTrash(LLFolderViewFolder::UNKNOWN), - mLastArrangeGeneration( -1 ), - mLastCalculatedWidth(0), - mCompletedFilterGeneration(-1), - mMostFilteredDescendantGeneration(-1), - mNeedsSort(false) -{} + LLToolDragAndDrop::getInstance()->beginMultiDrag(types, cargo_ids, source, mSourceID); + } + return can_drag; +} -// Destroys the object -LLFolderViewFolder::~LLFolderViewFolder( void ) +void LLFolderView::commitRename( const LLSD& data ) { - // The LLView base class takes care of object destruction. make sure that we - // don't have mouse or keyboard focus - gFocusMgr.releaseFocusIfNeeded( this ); // calls onCommit() + finishRenamingItem(); } -// addToFolder() returns TRUE if it succeeds. FALSE otherwise -BOOL LLFolderViewFolder::addToFolder(LLFolderViewFolder* folder, LLFolderView* root) +void LLFolderView::draw() { - if (!folder) + static LLUIColor sSearchStatusColor = LLUIColorTable::instance().getColor("InventorySearchStatusColor", LLColor4::white); + if (mDebugFilters) { - return FALSE; + std::string current_filter_string = llformat("Current Filter: %d, Least Filter: %d, Auto-accept Filter: %d", + mFilter->getCurrentGeneration(), mFilter->getMinRequiredGeneration(), mFilter->getMustPassGeneration()); + sSmallFont->renderUTF8(current_filter_string, 0, 2, + getRect().getHeight() - sSmallFont->getLineHeight(), LLColor4(0.5f, 0.5f, 0.8f, 1.f), + LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE ); } - mParentFolder = folder; - root->addItemID(getListener()->getUUID(), this); - return folder->addFolder(this); -} -// Finds width and height of this object and it's children. Also -// makes sure that this view and it's children are the right size. -S32 LLFolderViewFolder::arrange( S32* width, S32* height, S32 filter_generation) -{ - // sort before laying out contents - if (mNeedsSort) + // if cursor has moved off of me during drag and drop + // close all auto opened folders + if (!mDragAndDropThisFrame) { - mFolders.sort(mSortFunction); - mItems.sort(mSortFunction); - mNeedsSort = false; + closeAutoOpenedFolders(); } - mHasVisibleChildren = hasFilteredDescendants(filter_generation); - - LLInventoryFilter::EFolderShow show_folder_state = getRoot()->getShowFolderState(); - - // calculate height as a single item (without any children), and reshapes rectangle to match - LLFolderViewItem::arrange( width, height, filter_generation ); - - // clamp existing animated height so as to never get smaller than a single item - mCurHeight = llmax((F32)*height, mCurHeight); - - // initialize running height value as height of single item in case we have no children - *height = getItemHeight(); - F32 running_height = (F32)*height; - F32 target_height = (F32)*height; - - // are my children visible? - if (needsArrange()) + // while dragging, update selection rendering to reflect single/multi drag status + if (LLToolDragAndDrop::getInstance()->hasMouseCapture()) { - // set last arrange generation first, in case children are animating - // and need to be arranged again - mLastArrangeGeneration = getRoot()->getArrangeGeneration(); - if (mIsOpen) + EAcceptance last_accept = LLToolDragAndDrop::getInstance()->getLastAccept(); + if (last_accept == ACCEPT_YES_SINGLE || last_accept == ACCEPT_YES_COPY_SINGLE) { - // Add sizes of children - S32 parent_item_height = getRect().getHeight(); - - for(folders_t::iterator fit = mFolders.begin(); fit != mFolders.end(); ++fit) - { - LLFolderViewFolder* folderp = (*fit); - if (getRoot()->getDebugFilters()) - { - folderp->setVisible(TRUE); - } - else - { - folderp->setVisible(show_folder_state == LLInventoryFilter::SHOW_ALL_FOLDERS || // always show folders? - (folderp->getFiltered(filter_generation) || folderp->hasFilteredDescendants(filter_generation))); // passed filter or has descendants that passed filter - } - - if (folderp->getVisible()) - { - S32 child_width = *width; - S32 child_height = 0; - S32 child_top = parent_item_height - llround(running_height); - - target_height += folderp->arrange( &child_width, &child_height, filter_generation ); - - running_height += (F32)child_height; - *width = llmax(*width, child_width); - folderp->setOrigin( 0, child_top - folderp->getRect().getHeight() ); - } - } - for(items_t::iterator iit = mItems.begin(); - iit != mItems.end(); ++iit) - { - LLFolderViewItem* itemp = (*iit); - if (getRoot()->getDebugFilters()) - { - itemp->setVisible(TRUE); - } - else - { - itemp->setVisible(itemp->getFiltered(filter_generation)); - } - - if (itemp->getVisible()) - { - S32 child_width = *width; - S32 child_height = 0; - S32 child_top = parent_item_height - llround(running_height); - - target_height += itemp->arrange( &child_width, &child_height, filter_generation ); - // don't change width, as this item is as wide as its parent folder by construction - itemp->reshape( itemp->getRect().getWidth(), child_height); - - running_height += (F32)child_height; - *width = llmax(*width, child_width); - itemp->setOrigin( 0, child_top - itemp->getRect().getHeight() ); - } - } + setShowSingleSelection(TRUE); + } + else + { + setShowSingleSelection(FALSE); } - - mTargetHeight = target_height; - // cache this width so next time we can just return it - mLastCalculatedWidth = *width; } else { - // just use existing width - *width = mLastCalculatedWidth; + setShowSingleSelection(FALSE); } - // animate current height towards target height - if (llabs(mCurHeight - mTargetHeight) > 1.f) - { - mCurHeight = lerp(mCurHeight, mTargetHeight, LLCriticalDamp::getInterpolant(mIsOpen ? FOLDER_OPEN_TIME_CONSTANT : FOLDER_CLOSE_TIME_CONSTANT)); - - requestArrange(); - // hide child elements that fall out of current animated height - for (folders_t::iterator iter = mFolders.begin(); - iter != mFolders.end();) - { - folders_t::iterator fit = iter++; - // number of pixels that bottom of folder label is from top of parent folder - if (getRect().getHeight() - (*fit)->getRect().mTop + (*fit)->getItemHeight() - > llround(mCurHeight) + MAX_FOLDER_ITEM_OVERLAP) - { - // hide if beyond current folder height - (*fit)->setVisible(FALSE); - } - } - - for (items_t::iterator iter = mItems.begin(); - iter != mItems.end();) - { - items_t::iterator iit = iter++; - // number of pixels that bottom of item label is from top of parent folder - if (getRect().getHeight() - (*iit)->getRect().mBottom - > llround(mCurHeight) + MAX_FOLDER_ITEM_OVERLAP) - { - (*iit)->setVisible(FALSE); - } - } - } - else - { - mCurHeight = mTargetHeight; - } - - // don't change width as this item is already as wide as its parent folder - reshape(getRect().getWidth(),llround(mCurHeight)); - - // pass current height value back to parent - *height = llround(mCurHeight); - - return llround(mTargetHeight); -} - -BOOL LLFolderViewFolder::needsArrange() -{ - return mLastArrangeGeneration < getRoot()->getArrangeGeneration(); -} - -void LLFolderViewFolder::requestSort() -{ - mNeedsSort = true; - // whenever item order changes, we need to lay things out again - requestArrange(); -} - -void LLFolderViewFolder::setCompletedFilterGeneration(S32 generation, BOOL recurse_up) -{ - mMostFilteredDescendantGeneration = llmin(mMostFilteredDescendantGeneration, generation); - mCompletedFilterGeneration = generation; - // only aggregate up if we are a lower (older) value - if (recurse_up && mParentFolder && generation < mParentFolder->getCompletedFilterGeneration()) + if (mSearchTimer.getElapsedTimeF32() > gSavedSettings.getF32("TypeAheadTimeout") || !mSearchString.size()) { - mParentFolder->setCompletedFilterGeneration(generation, TRUE); + mSearchString.clear(); } -} -void LLFolderViewFolder::filter( LLInventoryFilter& filter) -{ - S32 filter_generation = filter.getCurrentGeneration(); - // if failed to pass filter newer than must_pass_generation - // you will automatically fail this time, so we only - // check against items that have passed the filter - S32 must_pass_generation = filter.getMustPassGeneration(); - - // if we have already been filtered against this generation, skip out - if (getCompletedFilterGeneration() >= filter_generation) + if (hasVisibleChildren() + || mFilter->getShowFolderState() == LLInventoryFilter::SHOW_ALL_FOLDERS) { - return; + mStatusText.clear(); } - - // filter folder itself - if (getLastFilterGeneration() < filter_generation) + else { - if (getLastFilterGeneration() >= must_pass_generation && // folder has been compared to a valid precursor filter - !mFiltered) // and did not pass the filter + if (gInventory.backgroundFetchActive() || mCompletedFilterGeneration < mFilter->getMinRequiredGeneration()) { - // go ahead and flag this folder as done - mLastFilterGeneration = filter_generation; + mStatusText = LLTrans::getString("Searching"); + sFont->renderUTF8(mStatusText, 0, 2, 1, sSearchStatusColor, LLFontGL::LEFT, LLFontGL::TOP, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE ); } else { - // filter self only on first pass through - LLFolderViewItem::filter( filter ); + mStatusText = LLTrans::getString("InventoryNoMatchingItems"); + sFont->renderUTF8(mStatusText, 0, 2, 1, sSearchStatusColor, LLFontGL::LEFT, LLFontGL::TOP, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE ); } } - if (getRoot()->getDebugFilters()) - { - mStatusText = llformat("%d", mLastFilterGeneration); - mStatusText += llformat("(%d)", mCompletedFilterGeneration); - mStatusText += llformat("+%d", mMostFilteredDescendantGeneration); - } + LLFolderViewFolder::draw(); + + mDragAndDropThisFrame = FALSE; +} - // all descendants have been filtered later than must pass generation - // but none passed - if(getCompletedFilterGeneration() >= must_pass_generation && !hasFilteredDescendants(must_pass_generation)) +void LLFolderView::finishRenamingItem( void ) +{ + if(!mRenamer) { - // don't traverse children if we've already filtered them since must_pass_generation - // and came back with nothing return; } + if( mRenameItem ) + { + mRenameItem->rename( mRenamer->getText() ); + } + + mRenamer->setCommitOnFocusLost( FALSE ); + mRenamer->setFocus( FALSE ); + mRenamer->setVisible( FALSE ); + mRenamer->setCommitOnFocusLost( TRUE ); + gFocusMgr.setTopCtrl( NULL ); - // we entered here with at least one filter iteration left - // check to see if we have any more before continuing on to children - if (filter.getFilterCount() < 0) + if( mRenameItem ) { - return; + setSelectionFromRoot( mRenameItem, TRUE ); + mRenameItem = NULL; } - // when applying a filter, matching folders get their contents downloaded first - if (filter.isNotDefault() && getFiltered(filter.getMinRequiredGeneration()) && (mListener && !gInventory.isCategoryComplete(mListener->getUUID()))) + // List is re-sorted alphabeticly, so scroll to make sure the selected item is visible. + scrollToShowSelection(); +} + +void LLFolderView::closeRenamer( void ) +{ + // will commit current name (which could be same as original name) + mRenamer->setFocus( FALSE ); + mRenamer->setVisible( FALSE ); + gFocusMgr.setTopCtrl( NULL ); + + if( mRenameItem ) { - gInventory.startBackgroundFetch(mListener->getUUID()); + setSelectionFromRoot( mRenameItem, TRUE ); + mRenameItem = NULL; } +} - // now query children - for (folders_t::iterator iter = mFolders.begin(); - iter != mFolders.end();) +void LLFolderView::removeSelectedItems( void ) +{ + if(getVisible() && getEnabled()) { - folders_t::iterator fit = iter++; - // have we run out of iterations this frame? - if (filter.getFilterCount() < 0) + // just in case we're removing the renaming item. + mRenameItem = NULL; + + // create a temporary structure which we will use to remove + // items, since the removal will futz with internal data + // structures. + std::vector<LLFolderViewItem*> items; + S32 count = mSelectedItems.size(); + if(count == 0) return; + LLFolderViewItem* item = NULL; + selected_items_t::iterator item_it; + for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) { - break; + item = *item_it; + if(item->isRemovable()) + { + items.push_back(item); + } + else + { + llinfos << "Cannot delete " << item->getName() << llendl; + return; + } } - // mMostFilteredDescendantGeneration might have been reset - // in which case we need to update it even for folders that - // don't need to be filtered anymore - if ((*fit)->getCompletedFilterGeneration() >= filter_generation) + // iterate through the new container. + count = items.size(); + LLUUID new_selection_id; + if(count == 1) { - // track latest generation to pass any child items - if ((*fit)->getFiltered() || (*fit)->hasFilteredDescendants(filter.getMinRequiredGeneration())) + LLFolderViewItem* item_to_delete = items[0]; + LLFolderViewFolder* parent = item_to_delete->getParentFolder(); + LLFolderViewItem* new_selection = item_to_delete->getNextOpenNode(FALSE); + if (!new_selection) + { + new_selection = item_to_delete->getPreviousOpenNode(FALSE); + } + if(parent) { - mMostFilteredDescendantGeneration = filter_generation; - if (getRoot()->needsAutoSelect()) + if (parent->removeItem(item_to_delete)) { - (*fit)->setOpenArrangeRecursively(TRUE); + // change selection on successful delete + if (new_selection) + { + setSelectionFromRoot(new_selection, new_selection->isOpen(), mParentPanel->hasFocus()); + } + else + { + setSelectionFromRoot(NULL, mParentPanel->hasFocus()); + } } } - // just skip it, it has already been filtered - continue; + arrangeAll(); } - - // update this folders filter status (and children) - (*fit)->filter( filter ); - - // track latest generation to pass any child items - if ((*fit)->getFiltered() || (*fit)->hasFilteredDescendants(filter_generation)) + else if (count > 1) { - mMostFilteredDescendantGeneration = filter_generation; - if (getRoot()->needsAutoSelect()) + LLDynamicArray<LLFolderViewEventListener*> listeners; + LLFolderViewEventListener* listener; + LLFolderViewItem* last_item = items[count - 1]; + LLFolderViewItem* new_selection = last_item->getNextOpenNode(FALSE); + while(new_selection && new_selection->isSelected()) + { + new_selection = new_selection->getNextOpenNode(FALSE); + } + if (!new_selection) + { + new_selection = last_item->getPreviousOpenNode(FALSE); + while (new_selection && new_selection->isSelected()) + { + new_selection = new_selection->getPreviousOpenNode(FALSE); + } + } + if (new_selection) + { + setSelectionFromRoot(new_selection, new_selection->isOpen(), mParentPanel->hasFocus()); + } + else + { + setSelectionFromRoot(NULL, mParentPanel->hasFocus()); + } + + for(S32 i = 0; i < count; ++i) + { + listener = items[i]->getListener(); + if(listener && (listeners.find(listener) == LLDynamicArray<LLFolderViewEventListener*>::FAIL)) + { + listeners.put(listener); + } + } + listener = listeners.get(0); + if(listener) { - (*fit)->setOpenArrangeRecursively(TRUE); + listener->removeBatch(listeners); } } + arrangeAll(); + scrollToShowSelection(); } +} - for (items_t::iterator iter = mItems.begin(); - iter != mItems.end();) +// open the selected item. +void LLFolderView::openSelectedItems( void ) +{ + if(getVisible() && getEnabled()) { - items_t::iterator iit = iter++; - if (filter.getFilterCount() < 0) + if (mSelectedItems.size() == 1) { - break; + mSelectedItems.front()->openItem(); } - if ((*iit)->getLastFilterGeneration() >= filter_generation) + else { - if ((*iit)->getFiltered()) + LLMultiPreview* multi_previewp = new LLMultiPreview(); + LLMultiProperties* multi_propertiesp = new LLMultiProperties(); + + selected_items_t::iterator item_it; + for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) { - mMostFilteredDescendantGeneration = filter_generation; + // IT_{OBJECT,ATTACHMENT} creates LLProperties + // floaters; others create LLPreviews. Put + // each one in the right type of container. + LLFolderViewEventListener* listener = (*item_it)->getListener(); + bool is_prop = listener && (listener->getInventoryType() == LLInventoryType::IT_OBJECT || listener->getInventoryType() == LLInventoryType::IT_ATTACHMENT); + if (is_prop) + LLFloater::setFloaterHost(multi_propertiesp); + else + LLFloater::setFloaterHost(multi_previewp); + (*item_it)->openItem(); } - continue; + + LLFloater::setFloaterHost(NULL); + // *NOTE: LLMulti* will safely auto-delete when open'd + // without any children. + multi_previewp->openFloater(LLSD()); + multi_propertiesp->openFloater(LLSD()); } + } +} - if ((*iit)->getLastFilterGeneration() >= must_pass_generation && - !(*iit)->getFiltered(must_pass_generation)) +void LLFolderView::propertiesSelectedItems( void ) +{ + if(getVisible() && getEnabled()) + { + if (mSelectedItems.size() == 1) { - // failed to pass an earlier filter that was a subset of the current one - // go ahead and flag this item as done - (*iit)->setFiltered(FALSE, filter_generation); - continue; + LLFolderViewItem* folder_item = mSelectedItems.front(); + if(!folder_item) return; + folder_item->getListener()->showProperties(); } - - (*iit)->filter( filter ); - - if ((*iit)->getFiltered(filter.getMinRequiredGeneration())) + else { - mMostFilteredDescendantGeneration = filter_generation; + LLMultiProperties* multi_propertiesp = new LLMultiProperties(); + + LLFloater::setFloaterHost(multi_propertiesp); + + selected_items_t::iterator item_it; + for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) + { + (*item_it)->getListener()->showProperties(); + } + + LLFloater::setFloaterHost(NULL); + multi_propertiesp->openFloater(LLSD()); } } - - // if we didn't use all filter iterations - // that means we filtered all of our descendants - // instead of exhausting the filter count for this frame - if (filter.getFilterCount() > 0) - { - // flag this folder as having completed filter pass for all descendants - setCompletedFilterGeneration(filter_generation, FALSE/*dont recurse up to root*/); - } } -void LLFolderViewFolder::setFiltered(BOOL filtered, S32 filter_generation) +void LLFolderView::autoOpenItem( LLFolderViewFolder* item ) { - // if this folder is now filtered, but wasn't before - // (it just passed) - if (filtered && !mFiltered) + if (mAutoOpenItems.check() == item || mAutoOpenItems.getDepth() >= (U32)AUTO_OPEN_STACK_DEPTH) { - // reset current height, because last time we drew it - // it might have had more visible items than now - mCurHeight = 0.f; + return; } - LLFolderViewItem::setFiltered(filtered, filter_generation); -} + // close auto-opened folders + LLFolderViewFolder* close_item = mAutoOpenItems.check(); + while (close_item && close_item != item->getParentFolder()) + { + mAutoOpenItems.pop(); + close_item->setOpenArrangeRecursively(FALSE); + close_item = mAutoOpenItems.check(); + } -void LLFolderViewFolder::dirtyFilter() -{ - // we're a folder, so invalidate our completed generation - setCompletedFilterGeneration(-1, FALSE); - LLFolderViewItem::dirtyFilter(); -} + item->requestArrange(); -BOOL LLFolderViewFolder::hasFilteredDescendants() -{ - return mMostFilteredDescendantGeneration >= getRoot()->getFilter()->getCurrentGeneration(); + mAutoOpenItems.push(item); + + item->setOpen(TRUE); + scrollToShowItem(item); } -// Passes selection information on to children and record selection -// information if necessary. -BOOL LLFolderViewFolder::setSelection(LLFolderViewItem* selection, BOOL openitem, - BOOL take_keyboard_focus) +void LLFolderView::closeAutoOpenedFolders() { - BOOL rv = FALSE; - if( selection == this ) + while (mAutoOpenItems.check()) { - mIsSelected = TRUE; - if(mListener) - { - mListener->selectItem(); - } - rv = TRUE; - } - else - { - mIsSelected = FALSE; - rv = FALSE; - } - BOOL child_selected = FALSE; - - for (folders_t::iterator iter = mFolders.begin(); - iter != mFolders.end();) - { - folders_t::iterator fit = iter++; - if((*fit)->setSelection(selection, openitem, take_keyboard_focus)) - { - rv = TRUE; - child_selected = TRUE; - mNumDescendantsSelected++; - } - } - for (items_t::iterator iter = mItems.begin(); - iter != mItems.end();) - { - items_t::iterator iit = iter++; - if((*iit)->setSelection(selection, openitem, take_keyboard_focus)) - { - rv = TRUE; - child_selected = TRUE; - mNumDescendantsSelected++; - } + LLFolderViewFolder* close_item = mAutoOpenItems.pop(); + close_item->setOpen(FALSE); } - if(openitem && child_selected) + + if (mAutoOpenCandidate) { - setOpenArrangeRecursively(TRUE); + mAutoOpenCandidate->setAutoOpenCountdown(0.f); } - return rv; + mAutoOpenCandidate = NULL; + mAutoOpenTimer.stop(); } -// This method is used to change the selection of an item. If -// selection is 'this', then note selection as true. Returns TRUE -// if this or a child is now selected. -BOOL LLFolderViewFolder::changeSelection(LLFolderViewItem* selection, - BOOL selected) +BOOL LLFolderView::autoOpenTest(LLFolderViewFolder* folder) { - BOOL rv = FALSE; - if(selection == this) - { - mIsSelected = selected; - if(mListener && selected) - { - mListener->selectItem(); - } - rv = TRUE; - } - - for (folders_t::iterator iter = mFolders.begin(); - iter != mFolders.end();) + if (folder && mAutoOpenCandidate == folder) { - folders_t::iterator fit = iter++; - if((*fit)->changeSelection(selection, selected)) + if (mAutoOpenTimer.getStarted()) { - if (selected) + if (!mAutoOpenCandidate->isOpen()) { - mNumDescendantsSelected++; + mAutoOpenCandidate->setAutoOpenCountdown(clamp_rescale(mAutoOpenTimer.getElapsedTimeF32(), 0.f, sAutoOpenTime, 0.f, 1.f)); } - else + if (mAutoOpenTimer.getElapsedTimeF32() > sAutoOpenTime) { - mNumDescendantsSelected--; + autoOpenItem(folder); + mAutoOpenTimer.stop(); + return TRUE; } - rv = TRUE; } + return FALSE; } - for (items_t::iterator iter = mItems.begin(); - iter != mItems.end();) + + // otherwise new candidate, restart timer + if (mAutoOpenCandidate) { - items_t::iterator iit = iter++; - if((*iit)->changeSelection(selection, selected)) - { - if (selected) - { - mNumDescendantsSelected++; - } - else - { - mNumDescendantsSelected--; - } - rv = TRUE; - } + mAutoOpenCandidate->setAutoOpenCountdown(0.f); } - return rv; + mAutoOpenCandidate = folder; + mAutoOpenTimer.start(); + return FALSE; } -S32 LLFolderViewFolder::extendSelection(LLFolderViewItem* selection, LLFolderViewItem* last_selected, LLDynamicArray<LLFolderViewItem*>& selected_items) +BOOL LLFolderView::canCopy() const { - S32 num_selected = 0; - - // pass on to child folders first - for (folders_t::iterator iter = mFolders.begin(); - iter != mFolders.end();) + if (!(getVisible() && getEnabled() && (mSelectedItems.size() > 0))) { - folders_t::iterator fit = iter++; - num_selected += (*fit)->extendSelection(selection, last_selected, selected_items); - mNumDescendantsSelected += num_selected; + return FALSE; } - - // handle selection of our immediate children... - BOOL reverse_select = FALSE; - BOOL found_last_selected = FALSE; - BOOL found_selection = FALSE; - LLDynamicArray<LLFolderViewItem*> items_to_select; - LLFolderViewItem* item; - - //...folders first... - for (folders_t::iterator iter = mFolders.begin(); - iter != mFolders.end();) + + for (selected_items_t::const_iterator selected_it = mSelectedItems.begin(); selected_it != mSelectedItems.end(); ++selected_it) { - folders_t::iterator fit = iter++; - item = (*fit); - if(item == selection) - { - found_selection = TRUE; - } - else if (item == last_selected) + const LLFolderViewItem* item = *selected_it; + if (!item->getListener()->isItemCopyable()) { - found_last_selected = TRUE; - if (found_selection) - { - reverse_select = TRUE; - } + return FALSE; } + } + return TRUE; +} - if (found_selection || found_last_selected) +// copy selected item +void LLFolderView::copy() +{ + // *NOTE: total hack to clear the inventory clipboard + LLInventoryClipboard::instance().reset(); + S32 count = mSelectedItems.size(); + if(getVisible() && getEnabled() && (count > 0)) + { + LLFolderViewEventListener* listener = NULL; + selected_items_t::iterator item_it; + for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) { - // deselect currently selected items so they can be pushed back on queue - if (item->isSelected()) + listener = (*item_it)->getListener(); + if(listener) { - item->changeSelection(item, FALSE); + listener->copyToClipboard(); } - items_to_select.put(item); } + } + mSearchString.clear(); +} - if (found_selection && found_last_selected) - { - break; - } +BOOL LLFolderView::canCut() const +{ + return FALSE; +} + +void LLFolderView::cut() +{ + // implement Windows-style cut-and-leave +} + +BOOL LLFolderView::canPaste() const +{ + if (mSelectedItems.empty()) + { + return FALSE; } - if (!(found_selection && found_last_selected)) + if(getVisible() && getEnabled()) { - //,,,then items - for (items_t::iterator iter = mItems.begin(); - iter != mItems.end();) + for (selected_items_t::const_iterator item_it = mSelectedItems.begin(); + item_it != mSelectedItems.end(); ++item_it) { - items_t::iterator iit = iter++; - item = (*iit); - if(item == selection) - { - found_selection = TRUE; - } - else if (item == last_selected) - { - found_last_selected = TRUE; - if (found_selection) - { - reverse_select = TRUE; - } - } - - if (found_selection || found_last_selected) + // *TODO: only check folders and parent folders of items + const LLFolderViewItem* item = (*item_it); + const LLFolderViewEventListener* listener = item->getListener(); + if(!listener || !listener->isClipboardPasteable()) { - // deselect currently selected items so they can be pushed back on queue - if (item->isSelected()) + const LLFolderViewFolder* folderp = item->getParentFolder(); + listener = folderp->getListener(); + if (!listener || !listener->isClipboardPasteable()) { - item->changeSelection(item, FALSE); + return FALSE; } - items_to_select.put(item); - } - - if (found_selection && found_last_selected) - { - break; } } + return TRUE; } + return FALSE; +} - if (found_last_selected && found_selection) +// paste selected item +void LLFolderView::paste() +{ + if(getVisible() && getEnabled()) { - // we have a complete selection inside this folder - for (S32 index = reverse_select ? items_to_select.getLength() - 1 : 0; - reverse_select ? index >= 0 : index < items_to_select.getLength(); reverse_select ? index-- : index++) + // find set of unique folders to paste into + std::set<LLFolderViewItem*> folder_set; + + selected_items_t::iterator selected_it; + for (selected_it = mSelectedItems.begin(); selected_it != mSelectedItems.end(); ++selected_it) { - LLFolderViewItem* item = items_to_select[index]; - if (item->changeSelection(item, TRUE)) + LLFolderViewItem* item = *selected_it; + LLFolderViewEventListener* listener = item->getListener(); + if (listener->getInventoryType() != LLInventoryType::IT_CATEGORY) { - selected_items.put(item); - mNumDescendantsSelected++; - num_selected++; + item = item->getParentFolder(); } + folder_set.insert(item); } - } - else if (found_selection) - { - // last selection was not in this folder....go ahead and select just the new item - if (selection->changeSelection(selection, TRUE)) + + std::set<LLFolderViewItem*>::iterator set_iter; + for(set_iter = folder_set.begin(); set_iter != folder_set.end(); ++set_iter) { - selected_items.put(selection); - mNumDescendantsSelected++; - num_selected++; + LLFolderViewEventListener* listener = (*set_iter)->getListener(); + if(listener && listener->isClipboardPasteable()) + { + listener->pasteFromClipboard(); + } } } - - return num_selected; + mSearchString.clear(); } -void LLFolderViewFolder::recursiveDeselect(BOOL deselect_self) +// public rename functionality - can only start the process +void LLFolderView::startRenamingSelectedItem( void ) { - // make sure we don't have negative values - llassert(mNumDescendantsSelected >= 0); + // make sure selection is visible + scrollToShowSelection(); - if (mIsSelected && deselect_self) + S32 count = mSelectedItems.size(); + LLFolderViewItem* item = NULL; + if(count > 0) { - mIsSelected = FALSE; - - // update ancestors' count of selected descendents - LLFolderViewFolder* parent_folder = getParentFolder(); - while(parent_folder) - { - parent_folder->mNumDescendantsSelected--; - parent_folder = parent_folder->getParentFolder(); - } + item = mSelectedItems.front(); } - - if (0 == mNumDescendantsSelected) + if(getVisible() && getEnabled() && (count == 1) && item && item->getListener() && + item->getListener()->isItemRenameable()) { - return; - } + mRenameItem = item; - for (items_t::iterator iter = mItems.begin(); - iter != mItems.end();) - { - items_t::iterator iit = iter++; - LLFolderViewItem* item = (*iit); - item->recursiveDeselect(TRUE); - } + updateRenamerPosition(); - for (folders_t::iterator iter = mFolders.begin(); - iter != mFolders.end();) - { - folders_t::iterator fit = iter++; - LLFolderViewFolder* folder = (*fit); - folder->recursiveDeselect(TRUE); - } + mRenamer->setText(item->getName()); + mRenamer->selectAll(); + mRenamer->setVisible( TRUE ); + // set focus will fail unless item is visible + mRenamer->setFocus( TRUE ); + mRenamer->setTopLostCallback(onRenamerLost); + gFocusMgr.setTopCtrl( mRenamer ); + } } -void LLFolderViewFolder::destroyView() +BOOL LLFolderView::handleKeyHere( KEY key, MASK mask ) { - for (items_t::iterator iter = mItems.begin(); - iter != mItems.end();) - { - items_t::iterator iit = iter++; - LLFolderViewItem* item = (*iit); - getRoot()->removeItemID(item->getListener()->getUUID()); - } - - std::for_each(mItems.begin(), mItems.end(), DeletePointer()); - mItems.clear(); - - while (!mFolders.empty()) - { - LLFolderViewFolder *folderp = mFolders.back(); - folderp->destroyView(); // removes entry from mFolders - } + BOOL handled = FALSE; - deleteAllChildren(); - - if (mParentFolder) + // SL-51858: Key presses are not being passed to the Popup menu. + // A proper fix is non-trivial so instead just close the menu. + LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get(); + if (menu && menu->isOpen()) { - mParentFolder->removeView(this); + LLMenuGL::sMenuContainer->hideMenus(); } -} -// remove the specified item (and any children) if possible. Return -// TRUE if the item was deleted. -BOOL LLFolderViewFolder::removeItem(LLFolderViewItem* item) -{ - if(item->remove()) + LLView *item = NULL; + if (getChildCount() > 0) { - //RN: this seem unneccessary as remove() moves to trash - //removeView(item); - return TRUE; + item = *(getChildList()->begin()); } - return FALSE; -} -// simply remove the view (and any children) Don't bother telling the -// listeners. -void LLFolderViewFolder::removeView(LLFolderViewItem* item) -{ - if (!item || item->getParentFolder() != this) + switch( key ) { - return; - } - // deselect without traversing hierarchy - item->recursiveDeselect(TRUE); - getRoot()->removeFromSelectionList(item); - extractItem(item); - delete item; -} + case KEY_F2: + mSearchString.clear(); + startRenamingSelectedItem(); + handled = TRUE; + break; -// extractItem() removes the specified item from the folder, but -// doesn't delete it. -void LLFolderViewFolder::extractItem( LLFolderViewItem* item ) -{ - items_t::iterator it = std::find(mItems.begin(), mItems.end(), item); - if(it == mItems.end()) - { - // This is an evil downcast. However, it's only doing - // pointer comparison to find if (which it should be ) the - // item is in the container, so it's pretty safe. - LLFolderViewFolder* f = reinterpret_cast<LLFolderViewFolder*>(item); - folders_t::iterator ft; - ft = std::find(mFolders.begin(), mFolders.end(), f); - if(ft != mFolders.end()) + case KEY_RETURN: + if (mask == MASK_NONE) { - mFolders.erase(ft); - } - } - else - { - mItems.erase(it); - } - //item has been removed, need to update filter - dirtyFilter(); - //because an item is going away regardless of filter status, force rearrange - requestArrange(); - getRoot()->removeItemID(item->getListener()->getUUID()); - removeChild(item); -} - -bool LLFolderViewFolder::isTrash() const -{ - if (mAmTrash == LLFolderViewFolder::UNKNOWN) - { - mAmTrash = mListener->getUUID() == gInventory.findCategoryUUIDForType(LLAssetType::AT_TRASH, false) ? LLFolderViewFolder::TRASH : LLFolderViewFolder::NOT_TRASH; - } - return mAmTrash == LLFolderViewFolder::TRASH; -} - -void LLFolderViewFolder::sortBy(U32 order) -{ - if (!mSortFunction.updateSort(order)) - { - // No changes. - return; - } - - // Propegate this change to sub folders - for (folders_t::iterator iter = mFolders.begin(); - iter != mFolders.end();) - { - folders_t::iterator fit = iter++; - (*fit)->sortBy(order); - } - - mFolders.sort(mSortFunction); - mItems.sort(mSortFunction); - - if (order & LLInventoryFilter::SO_DATE) - { - time_t latest = 0; - - if (!mItems.empty()) - { - LLFolderViewItem* item = *(mItems.begin()); - latest = item->getCreationDate(); - } - - if (!mFolders.empty()) - { - LLFolderViewFolder* folder = *(mFolders.begin()); - if (folder->getCreationDate() > latest) + if( mRenameItem && mRenamer->getVisible() ) + { + finishRenamingItem(); + mSearchString.clear(); + handled = TRUE; + } + else { - latest = folder->getCreationDate(); + LLFolderView::openSelectedItems(); + handled = TRUE; } } - mSubtreeCreationDate = latest; - } -} + break; -void LLFolderViewFolder::setItemSortOrder(U32 ordering) -{ - if (mSortFunction.updateSort(ordering)) - { - for (folders_t::iterator iter = mFolders.begin(); - iter != mFolders.end();) + case KEY_ESCAPE: + if( mRenameItem && mRenamer->getVisible() ) { - folders_t::iterator fit = iter++; - (*fit)->setItemSortOrder(ordering); + closeRenamer(); + handled = TRUE; } + mSearchString.clear(); + break; - mFolders.sort(mSortFunction); - mItems.sort(mSortFunction); - } -} + case KEY_PAGE_UP: + mSearchString.clear(); + mScrollContainer->pageUp(30); + handled = TRUE; + break; -EInventorySortGroup LLFolderViewFolder::getSortGroup() const -{ - if (isTrash()) - { - return SG_TRASH_FOLDER; - } + case KEY_PAGE_DOWN: + mSearchString.clear(); + mScrollContainer->pageDown(30); + handled = TRUE; + break; - // Folders that can't be moved are 'system' folders. - if( mListener ) - { - if( !(mListener->isItemMovable()) ) - { - return SG_SYSTEM_FOLDER; - } - } - - return SG_NORMAL_FOLDER; -} + case KEY_HOME: + mSearchString.clear(); + mScrollContainer->goToTop(); + handled = TRUE; + break; -BOOL LLFolderViewFolder::isMovable() -{ - if( mListener ) - { - if( !(mListener->isItemMovable()) ) - { - return FALSE; - } + case KEY_END: + mSearchString.clear(); + mScrollContainer->goToBottom(); + break; - for (items_t::iterator iter = mItems.begin(); - iter != mItems.end();) + case KEY_DOWN: + if((mSelectedItems.size() > 0) && mScrollContainer) { - items_t::iterator iit = iter++; - if(!(*iit)->isMovable()) + LLFolderViewItem* last_selected = getCurSelectedItem(); + + if (!mKeyboardSelection) + { + setSelection(last_selected, FALSE, TRUE); + mKeyboardSelection = TRUE; + } + + LLFolderViewItem* next = NULL; + if (mask & MASK_SHIFT) + { + // don't shift select down to children of folders (they are implicitly selected through parent) + next = last_selected->getNextOpenNode(FALSE); + if (next) + { + if (next->isSelected()) + { + // shrink selection + changeSelectionFromRoot(last_selected, FALSE); + } + else if (last_selected->getParentFolder() == next->getParentFolder()) + { + // grow selection + changeSelectionFromRoot(next, TRUE); + } + } + } + else { - return FALSE; + next = last_selected->getNextOpenNode(); + if( next ) + { + if (next == last_selected) + { + return FALSE; + } + setSelection( next, FALSE, TRUE ); + } } + scrollToShowSelection(); + mSearchString.clear(); + handled = TRUE; } + break; - for (folders_t::iterator iter = mFolders.begin(); - iter != mFolders.end();) + case KEY_UP: + if((mSelectedItems.size() > 0) && mScrollContainer) { - folders_t::iterator fit = iter++; - if(!(*fit)->isMovable()) + LLFolderViewItem* last_selected = mSelectedItems.back(); + + if (!mKeyboardSelection) { - return FALSE; + setSelection(last_selected, FALSE, TRUE); + mKeyboardSelection = TRUE; } - } - } - return TRUE; -} + LLFolderViewItem* prev = NULL; + if (mask & MASK_SHIFT) + { + // don't shift select down to children of folders (they are implicitly selected through parent) + prev = last_selected->getPreviousOpenNode(FALSE); + if (prev) + { + if (prev->isSelected()) + { + // shrink selection + changeSelectionFromRoot(last_selected, FALSE); + } + else if (last_selected->getParentFolder() == prev->getParentFolder()) + { + // grow selection + changeSelectionFromRoot(prev, TRUE); + } + } + } + else + { + prev = last_selected->getPreviousOpenNode(); + if( prev ) + { + if (prev == this) + { + return FALSE; + } + setSelection( prev, FALSE, TRUE ); + } + } + scrollToShowSelection(); + mSearchString.clear(); + + handled = TRUE; + } + break; -BOOL LLFolderViewFolder::isRemovable() -{ - if( mListener ) - { - if( !(mListener->isItemRemovable()) ) + case KEY_RIGHT: + if(mSelectedItems.size()) { - return FALSE; + LLFolderViewItem* last_selected = getCurSelectedItem(); + last_selected->setOpen( TRUE ); + mSearchString.clear(); + handled = TRUE; } + break; - for (items_t::iterator iter = mItems.begin(); - iter != mItems.end();) + case KEY_LEFT: + if(mSelectedItems.size()) { - items_t::iterator iit = iter++; - if(!(*iit)->isRemovable()) + LLFolderViewItem* last_selected = getCurSelectedItem(); + LLFolderViewItem* parent_folder = last_selected->getParentFolder(); + if (!last_selected->isOpen() && parent_folder && parent_folder->getParentFolder()) + { + setSelection(parent_folder, FALSE, TRUE); + } + else { - return FALSE; + last_selected->setOpen( FALSE ); } + mSearchString.clear(); + scrollToShowSelection(); + handled = TRUE; } + break; + } - for (folders_t::iterator iter = mFolders.begin(); - iter != mFolders.end();) + if (!handled && mParentPanel->hasFocus()) + { + if (key == KEY_BACKSPACE) { - folders_t::iterator fit = iter++; - if(!(*fit)->isRemovable()) + mSearchTimer.reset(); + if (mSearchString.size()) { - return FALSE; + mSearchString.erase(mSearchString.size() - 1, 1); } + search(getCurSelectedItem(), mSearchString, FALSE); + handled = TRUE; } } - return TRUE; -} -// this is an internal method used for adding items to folders. -BOOL LLFolderViewFolder::addItem(LLFolderViewItem* item) -{ - mItems.push_back(item); - item->setRect(LLRect(0, 0, getRect().getWidth(), 0)); - item->setVisible(FALSE); - addChild( item ); - item->dirtyFilter(); - requestArrange(); - requestSort(); - return TRUE; + return handled; } -// this is an internal method used for adding items to folders. -BOOL LLFolderViewFolder::addFolder(LLFolderViewFolder* folder) -{ - mFolders.push_back(folder); - folder->setOrigin(0, 0); - folder->reshape(getRect().getWidth(), 0); - folder->setVisible(FALSE); - addChild( folder ); - folder->dirtyFilter(); - // rearrange all descendants too, as our indentation level might have changed - folder->requestArrange(TRUE); - requestSort(); - return TRUE; -} -void LLFolderViewFolder::requestArrange(BOOL include_descendants) -{ - mLastArrangeGeneration = -1; - // flag all items up to root - if (mParentFolder) +BOOL LLFolderView::handleUnicodeCharHere(llwchar uni_char) +{ + if ((uni_char < 0x20) || (uni_char == 0x7F)) // Control character or DEL { - mParentFolder->requestArrange(); + return FALSE; } - if (include_descendants) + if (uni_char > 0x7f) { - for (folders_t::iterator iter = mFolders.begin(); - iter != mFolders.end(); - ++iter) - { - (*iter)->requestArrange(TRUE); - } + llwarns << "LLFolderView::handleUnicodeCharHere - Don't handle non-ascii yet, aborting" << llendl; + return FALSE; } -} - -void LLFolderViewFolder::toggleOpen() -{ - setOpen(!mIsOpen); -} - -// Force a folder open or closed -void LLFolderViewFolder::setOpen(BOOL openitem) -{ - setOpenArrangeRecursively(openitem); -} -void LLFolderViewFolder::setOpenArrangeRecursively(BOOL openitem, ERecurseType recurse) -{ - BOOL was_open = mIsOpen; - mIsOpen = openitem; - if(!was_open && openitem) + BOOL handled = FALSE; + if (gFocusMgr.childHasKeyboardFocus(getRoot())) { - if(mListener) + // SL-51858: Key presses are not being passed to the Popup menu. + // A proper fix is non-trivial so instead just close the menu. + LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get(); + if (menu && menu->isOpen()) { - mListener->openItem(); + LLMenuGL::sMenuContainer->hideMenus(); } - } - if (recurse == RECURSE_DOWN || recurse == RECURSE_UP_DOWN) - { - for (folders_t::iterator iter = mFolders.begin(); - iter != mFolders.end();) + //do text search + if (mSearchTimer.getElapsedTimeF32() > gSavedSettings.getF32("TypeAheadTimeout")) { - folders_t::iterator fit = iter++; - (*fit)->setOpenArrangeRecursively(openitem, RECURSE_DOWN); /* Flawfinder: ignore */ - } - } - if (mParentFolder && (recurse == RECURSE_UP || recurse == RECURSE_UP_DOWN)) - { - mParentFolder->setOpenArrangeRecursively(openitem, RECURSE_UP); - } - - if (was_open != mIsOpen) - { - requestArrange(); - } -} - -BOOL LLFolderViewFolder::handleDragAndDropFromChild(MASK mask, - BOOL drop, - EDragAndDropType c_type, - void* cargo_data, - EAcceptance* accept, - std::string& tooltip_msg) -{ - BOOL accepted = mListener && mListener->dragOrDrop(mask,drop,c_type,cargo_data); - if (accepted) - { - mDragAndDropTarget = TRUE; - *accept = ACCEPT_YES_MULTI; - } - else - { - *accept = ACCEPT_NO; - } - - // drag and drop to child item, so clear pending auto-opens - getRoot()->autoOpenTest(NULL); - - return TRUE; -} - -void LLFolderViewFolder::openItem( void ) -{ - toggleOpen(); -} - -void LLFolderViewFolder::applyFunctorRecursively(LLFolderViewFunctor& functor) -{ - functor.doFolder(this); - - for (folders_t::iterator iter = mFolders.begin(); - iter != mFolders.end();) - { - folders_t::iterator fit = iter++; - (*fit)->applyFunctorRecursively(functor); - } - for (items_t::iterator iter = mItems.begin(); - iter != mItems.end();) - { - items_t::iterator iit = iter++; - functor.doItem((*iit)); - } -} - -void LLFolderViewFolder::applyListenerFunctorRecursively(LLFolderViewListenerFunctor& functor) -{ - functor(mListener); - for (folders_t::iterator iter = mFolders.begin(); - iter != mFolders.end();) - { - folders_t::iterator fit = iter++; - (*fit)->applyListenerFunctorRecursively(functor); - } - for (items_t::iterator iter = mItems.begin(); - iter != mItems.end();) - { - items_t::iterator iit = iter++; - (*iit)->applyListenerFunctorRecursively(functor); - } -} - -// LLView functionality -BOOL LLFolderViewFolder::handleDragAndDrop(S32 x, S32 y, MASK mask, - BOOL drop, - EDragAndDropType cargo_type, - void* cargo_data, - EAcceptance* accept, - std::string& tooltip_msg) -{ - LLFolderView* root_view = getRoot(); - - BOOL handled = FALSE; - if(mIsOpen) - { - handled = childrenHandleDragAndDrop(x, y, mask, drop, cargo_type, - cargo_data, accept, tooltip_msg) != NULL; - } - - if (!handled) - { - BOOL accepted = mListener && mListener->dragOrDrop(mask, drop,cargo_type,cargo_data); - - if (accepted) - { - mDragAndDropTarget = TRUE; - *accept = ACCEPT_YES_MULTI; - } - else - { - *accept = ACCEPT_NO; - } - - if (!drop && accepted) - { - root_view->autoOpenTest(this); - } - - lldebugst(LLERR_USER_INPUT) << "dragAndDrop handled by LLFolderViewFolder" << llendl; - } - - return TRUE; -} - - -BOOL LLFolderViewFolder::handleRightMouseDown( S32 x, S32 y, MASK mask ) -{ - BOOL handled = FALSE; - // fetch contents of this folder, as context menu can depend on contents - // still, user would have to open context menu again to see the changes - gInventory.fetchDescendentsOf(mListener->getUUID()); - - if( mIsOpen ) - { - handled = childrenHandleRightMouseDown( x, y, mask ) != NULL; - } - if (!handled) - { - handled = LLFolderViewItem::handleRightMouseDown( x, y, mask ); - } - return handled; -} - - -BOOL LLFolderViewFolder::handleHover(S32 x, S32 y, MASK mask) -{ - BOOL handled = LLView::handleHover(x, y, mask); - - if (!handled) - { - // this doesn't do child processing - handled = LLFolderViewItem::handleHover(x, y, mask); - } - - //if(x < LEFT_INDENTATION + mIndentation && x > mIndentation - LEFT_PAD && y > getRect().getHeight() - ) - //{ - // gViewerWindow->setCursor(UI_CURSOR_ARROW); - // mExpanderHighlighted = TRUE; - // handled = TRUE; - //} - return handled; -} - -BOOL LLFolderViewFolder::handleMouseDown( S32 x, S32 y, MASK mask ) -{ - BOOL handled = FALSE; - if( mIsOpen ) - { - handled = childrenHandleMouseDown(x,y,mask) != NULL; - } - if( !handled ) - { - if(x < LEFT_INDENTATION + mIndentation && x > mIndentation - LEFT_PAD) - { - toggleOpen(); - handled = TRUE; - } - else - { - // do normal selection logic - handled = LLFolderViewItem::handleMouseDown(x, y, mask); - } - } - - return handled; -} - -BOOL LLFolderViewFolder::handleDoubleClick( S32 x, S32 y, MASK mask ) -{ - BOOL handled = FALSE; - if( mIsOpen ) - { - handled = childrenHandleDoubleClick( x, y, mask ) != NULL; - } - if( !handled ) - { - if(x < LEFT_INDENTATION + mIndentation && x > mIndentation - LEFT_PAD) - { - // don't select when user double-clicks plus sign - // so as not to contradict single-click behavior - toggleOpen(); - } - else - { - setSelectionFromRoot(this, FALSE); - toggleOpen(); - } - handled = TRUE; - } - return handled; -} - -void LLFolderViewFolder::draw() -{ - if (mAutoOpenCountdown != 0.f) - { - mControlLabelRotation = mAutoOpenCountdown * -90.f; - } - else if (mIsOpen) - { - mControlLabelRotation = lerp(mControlLabelRotation, -90.f, LLCriticalDamp::getInterpolant(0.04f)); - } - else - { - mControlLabelRotation = lerp(mControlLabelRotation, 0.f, LLCriticalDamp::getInterpolant(0.025f)); - } - - bool possibly_has_children = false; - bool up_to_date = mListener && mListener->isUpToDate(); - if(!up_to_date && mListener && mListener->hasChildren()) // we know we have children but haven't fetched them (doesn't obey filter) - { - possibly_has_children = true; - } - - - BOOL loading = ( mIsOpen && possibly_has_children && !up_to_date ); - - if ( loading && !mIsLoading ) - { - // Measure how long we've been in the loading state - mTimeSinceRequestStart.reset(); - } - - mIsLoading = loading; - - LLFolderViewItem::draw(); - - // draw children if root folder, or any other folder that is open or animating to closed state - if( getRoot() == this || (mIsOpen || mCurHeight != mTargetHeight )) - { - LLView::draw(); - } - - mExpanderHighlighted = FALSE; -} - -time_t LLFolderViewFolder::getCreationDate() const -{ - return llmax<time_t>(mCreationDate, mSubtreeCreationDate); -} - - -BOOL LLFolderViewFolder::potentiallyVisible() -{ - // folder should be visible by it's own filter status - return LLFolderViewItem::potentiallyVisible() - // or one or more of its descendants have passed the minimum filter requirement - || hasFilteredDescendants(getRoot()->getFilter()->getMinRequiredGeneration()) - // or not all of its descendants have been checked against minimum filter requirement - || getCompletedFilterGeneration() < getRoot()->getFilter()->getMinRequiredGeneration(); -} - -// this does prefix traversal, as folders are listed above their contents -LLFolderViewItem* LLFolderViewFolder::getNextFromChild( LLFolderViewItem* item, BOOL include_children ) -{ - BOOL found_item = FALSE; - - LLFolderViewItem* result = NULL; - // when not starting from a given item, start at beginning - if(item == NULL) - { - found_item = TRUE; - } - - // find current item among children - folders_t::iterator fit = mFolders.begin(); - folders_t::iterator fend = mFolders.end(); - - items_t::iterator iit = mItems.begin(); - items_t::iterator iend = mItems.end(); - - // if not trivially starting at the beginning, we have to find the current item - if (!found_item) - { - // first, look among folders, since they are always above items - for(; fit != fend; ++fit) - { - if(item == (*fit)) - { - found_item = TRUE; - // if we are on downwards traversal - if (include_children && (*fit)->isOpen()) - { - // look for first descendant - return (*fit)->getNextFromChild(NULL, TRUE); - } - // otherwise advance to next folder - ++fit; - include_children = TRUE; - break; - } - } - - // didn't find in folders? Check items... - if (!found_item) - { - for(; iit != iend; ++iit) - { - if(item == (*iit)) - { - found_item = TRUE; - // point to next item - ++iit; - break; - } - } - } - } - - if (!found_item) - { - // you should never call this method with an item that isn't a child - // so we should always find something - llassert(FALSE); - return NULL; - } - - // at this point, either iit or fit point to a candidate "next" item - // if both are out of range, we need to punt up to our parent - - // now, starting from found folder, continue through folders - // searching for next visible folder - while(fit != fend && !(*fit)->getVisible()) - { - // turn on downwards traversal for next folder - ++fit; - } - - if (fit != fend) - { - result = (*fit); - } - else - { - // otherwise, scan for next visible item - while(iit != iend && !(*iit)->getVisible()) - { - ++iit; - } - - // check to see if we have a valid item - if (iit != iend) - { - result = (*iit); - } - } - - if( !result && mParentFolder ) - { - // If there are no siblings or children to go to, recurse up one level in the tree - // and skip children for this folder, as we've already discounted them - result = mParentFolder->getNextFromChild(this, FALSE); - } - - return result; -} - -// this does postfix traversal, as folders are listed above their contents -LLFolderViewItem* LLFolderViewFolder::getPreviousFromChild( LLFolderViewItem* item, BOOL include_children ) -{ - BOOL found_item = FALSE; - - LLFolderViewItem* result = NULL; - // when not starting from a given item, start at end - if(item == NULL) - { - found_item = TRUE; - } - - // find current item among children - folders_t::reverse_iterator fit = mFolders.rbegin(); - folders_t::reverse_iterator fend = mFolders.rend(); - - items_t::reverse_iterator iit = mItems.rbegin(); - items_t::reverse_iterator iend = mItems.rend(); - - // if not trivially starting at the end, we have to find the current item - if (!found_item) - { - // first, look among items, since they are always below the folders - for(; iit != iend; ++iit) - { - if(item == (*iit)) - { - found_item = TRUE; - // point to next item - ++iit; - break; - } - } - - // didn't find in items? Check folders... - if (!found_item) - { - for(; fit != fend; ++fit) - { - if(item == (*fit)) - { - found_item = TRUE; - // point to next folder - ++fit; - break; - } - } - } - } - - if (!found_item) - { - // you should never call this method with an item that isn't a child - // so we should always find something - llassert(FALSE); - return NULL; - } - - // at this point, either iit or fit point to a candidate "next" item - // if both are out of range, we need to punt up to our parent - - // now, starting from found item, continue through items - // searching for next visible item - while(iit != iend && !(*iit)->getVisible()) - { - ++iit; - } - - if (iit != iend) - { - // we found an appropriate item - result = (*iit); - } - else - { - // otherwise, scan for next visible folder - while(fit != fend && !(*fit)->getVisible()) - { - ++fit; - } - - // check to see if we have a valid folder - if (fit != fend) - { - // try selecting child element of this folder - if ((*fit)->isOpen()) - { - result = (*fit)->getPreviousFromChild(NULL); - } - else - { - result = (*fit); - } - } - } - - if( !result ) - { - // If there are no siblings or children to go to, recurse up one level in the tree - // which gets back to this folder, which will only be visited if it is a valid, visible item - result = this; - } - - return result; -} - - -//--------------------------------------------------------------------------- - -// Tells all folders in a folderview to sort their items -// (and only their items, not folders) by a certain function. -class LLSetItemSortFunction : public LLFolderViewFunctor -{ -public: - LLSetItemSortFunction(U32 ordering) - : mSortOrder(ordering) {} - virtual ~LLSetItemSortFunction() {} - virtual void doFolder(LLFolderViewFolder* folder); - virtual void doItem(LLFolderViewItem* item); - - U32 mSortOrder; -}; - - -// Set the sort order. -void LLSetItemSortFunction::doFolder(LLFolderViewFolder* folder) -{ - folder->setItemSortOrder(mSortOrder); -} - -// Do nothing. -void LLSetItemSortFunction::doItem(LLFolderViewItem* item) -{ - return; -} - -//--------------------------------------------------------------------------- - -// Tells all folders in a folderview to close themselves -// For efficiency, calls setOpenArrangeRecursively(). -// The calling function must then call: -// LLFolderView* root = getRoot(); -// if( root ) -// { -// root->arrange( NULL, NULL ); -// root->scrollToShowSelection(); -// } -// to patch things up. -class LLCloseAllFoldersFunctor : public LLFolderViewFunctor -{ -public: - LLCloseAllFoldersFunctor(BOOL close) { mOpen = !close; } - virtual ~LLCloseAllFoldersFunctor() {} - virtual void doFolder(LLFolderViewFolder* folder); - virtual void doItem(LLFolderViewItem* item); - - BOOL mOpen; -}; - - -// Set the sort order. -void LLCloseAllFoldersFunctor::doFolder(LLFolderViewFolder* folder) -{ - folder->setOpenArrangeRecursively(mOpen); -} - -// Do nothing. -void LLCloseAllFoldersFunctor::doItem(LLFolderViewItem* item) -{ } - -///---------------------------------------------------------------------------- -/// Class LLFolderView -///---------------------------------------------------------------------------- - -// Default constructor -LLFolderView::LLFolderView(const Params& p) -: LLFolderViewFolder(p), - mScrollContainer( NULL ), - mPopupMenuHandle(), - mAllowMultiSelect(TRUE), - mShowFolderHierarchy(FALSE), - mSourceID(p.task_id), - mRenameItem( NULL ), - mNeedsScroll( FALSE ), - mLastScrollItem( NULL ), - mNeedsAutoSelect( FALSE ), - mAutoSelectOverride(FALSE), - mNeedsAutoRename(FALSE), - mDebugFilters(FALSE), - mSortOrder(LLInventoryFilter::SO_FOLDERS_BY_NAME), // This gets overridden by a pref immediately - mFilter(p.name), - mShowSelectionContext(FALSE), - mShowSingleSelection(FALSE), - mArrangeGeneration(0), - mSignalSelectCallback(0), - mMinWidth(0), - mDragAndDropThisFrame(FALSE), - mCallbackRegistrar(NULL), - mParentPanel(p.parent_panel) - -{ - LLRect rect = p.rect; - LLRect new_rect(rect.mLeft, rect.mBottom + getRect().getHeight(), rect.mLeft + getRect().getWidth(), rect.mBottom); - setRect( rect ); - reshape(rect.getWidth(), rect.getHeight()); - mIsOpen = TRUE; // this view is always open. - mAutoOpenItems.setDepth(AUTO_OPEN_STACK_DEPTH); - mAutoOpenCandidate = NULL; - mAutoOpenTimer.stop(); - mKeyboardSelection = FALSE; - mIndentation = -LEFT_INDENTATION; // children start at indentation 0 - gIdleCallbacks.addFunction(idle, this); - - //clear label - // go ahead and render root folder as usual - // just make sure the label ("Inventory Folder") never shows up - mLabel = LLStringUtil::null; - - //mRenamer->setWriteableBgColor(LLColor4::white); - // Escape is handled by reverting the rename, not commiting it (default behavior) - LLLineEditor::Params params; - params.name("ren"); - params.rect(getRect()); - params.font(sFont); - params.max_length_bytes(DB_INV_ITEM_NAME_STR_LEN); - params.commit_callback.function(boost::bind(&LLFolderView::commitRename, this, _2)); - params.prevalidate_callback(&LLLineEditor::prevalidatePrintableNotPipe); - params.commit_on_focus_lost(true); - params.visible(false); - mRenamer = LLUICtrlFactory::create<LLLineEditor> (params); - addChild(mRenamer); - - // make the popup menu available - LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_inventory.xml", gMenuHolder); - if (!menu) - { - menu = LLUICtrlFactory::getDefaultWidget<LLMenuGL>("inventory_menu"); - } - menu->setBackgroundColor(LLUIColorTable::instance().getColor("MenuPopupBgColor")); - mPopupMenuHandle = menu->getHandle(); - -} - -// Destroys the object -LLFolderView::~LLFolderView( void ) -{ - // The release focus call can potentially call the - // scrollcontainer, which can potentially be called with a partly - // destroyed scollcontainer. Just null it out here, and no worries - // about calling into the invalid scroll container. - // Same with the renamer. - mScrollContainer = NULL; - mRenameItem = NULL; - mRenamer = NULL; - - if( gEditMenuHandler == this ) - { - gEditMenuHandler = NULL; - } - - mAutoOpenItems.removeAllNodes(); - gIdleCallbacks.deleteFunction(idle, this); - - LLView::deleteViewByHandle(mPopupMenuHandle); - - if(mRenamer == gFocusMgr.getTopCtrl()) - { - gFocusMgr.setTopCtrl(NULL); - } - - mAutoOpenItems.removeAllNodes(); - clearSelection(); - mItems.clear(); - mFolders.clear(); - - mItemMap.clear(); -} - -BOOL LLFolderView::canFocusChildren() const -{ - return FALSE; -} - -void LLFolderView::checkTreeResortForModelChanged() -{ - if (mSortOrder & LLInventoryFilter::SO_DATE && !(mSortOrder & LLInventoryFilter::SO_FOLDERS_BY_NAME)) - { - // This is the case where something got added or removed. If we are date sorting - // everything including folders, then we need to rebuild the whole tree. - // Just set to something not SO_DATE to force the folder most resent date resort. - mSortOrder = mSortOrder & ~LLInventoryFilter::SO_DATE; - setSortOrder(mSortOrder | LLInventoryFilter::SO_DATE); - } -} - -void LLFolderView::setSortOrder(U32 order) -{ - if (order != mSortOrder) - { - LLFastTimer t(LLFastTimer::FTM_SORT); - mSortOrder = order; - - for (folders_t::iterator iter = mFolders.begin(); - iter != mFolders.end();) - { - folders_t::iterator fit = iter++; - (*fit)->sortBy(order); - } - - arrangeAll(); - } -} - - -U32 LLFolderView::getSortOrder() const -{ - return mSortOrder; -} - -BOOL LLFolderView::addFolder( LLFolderViewFolder* folder) -{ - // enforce sort order of My Inventory followed by Library - if (folder->getListener()->getUUID() == gInventoryLibraryRoot) - { - mFolders.push_back(folder); - } - else - { - mFolders.insert(mFolders.begin(), folder); - } - folder->setOrigin(0, 0); - folder->reshape(getRect().getWidth(), 0); - folder->setVisible(FALSE); - addChild( folder ); - folder->dirtyFilter(); - folder->requestArrange(); - return TRUE; -} - -void LLFolderView::closeAllFolders() -{ - // Close all the folders - setOpenArrangeRecursively(FALSE, LLFolderViewFolder::RECURSE_DOWN); - arrangeAll(); -} - -void LLFolderView::openFolder(const std::string& foldername) -{ - LLFolderViewFolder* inv = findChild<LLFolderViewFolder>(foldername); - if (inv) - { - setSelection(inv, FALSE, FALSE); - inv->setOpen(TRUE); - } -} - -void LLFolderView::setOpenArrangeRecursively(BOOL openitem, ERecurseType recurse) -{ - // call base class to do proper recursion - LLFolderViewFolder::setOpenArrangeRecursively(openitem, recurse); - // make sure root folder is always open - mIsOpen = TRUE; -} - -// This view grows and shinks to enclose all of its children items and folders. -S32 LLFolderView::arrange( S32* unused_width, S32* unused_height, S32 filter_generation ) -{ - LLFastTimer t2(LLFastTimer::FTM_ARRANGE); - - filter_generation = mFilter.getMinRequiredGeneration(); - mMinWidth = 0; - - mHasVisibleChildren = hasFilteredDescendants(filter_generation); - // arrange always finishes, so optimistically set the arrange generation to the most current - mLastArrangeGeneration = getRoot()->getArrangeGeneration(); - - LLInventoryFilter::EFolderShow show_folder_state = getRoot()->getShowFolderState(); - - S32 total_width = LEFT_PAD; - S32 running_height = mDebugFilters ? llceil(sSmallFont->getLineHeight()) : 0; - S32 target_height = running_height; - S32 parent_item_height = getRect().getHeight(); - - for (folders_t::iterator iter = mFolders.begin(); - iter != mFolders.end();) - { - folders_t::iterator fit = iter++; - LLFolderViewFolder* folderp = (*fit); - if (getDebugFilters()) - { - folderp->setVisible(TRUE); - } - else - { - folderp->setVisible(show_folder_state == LLInventoryFilter::SHOW_ALL_FOLDERS || // always show folders? - (folderp->getFiltered(filter_generation) || folderp->hasFilteredDescendants(filter_generation))); // passed filter or has descendants that passed filter - } - if (folderp->getVisible()) - { - S32 child_height = 0; - S32 child_width = 0; - S32 child_top = parent_item_height - running_height; - - target_height += folderp->arrange( &child_width, &child_height, filter_generation ); - - mMinWidth = llmax(mMinWidth, child_width); - total_width = llmax( total_width, child_width ); - running_height += child_height; - folderp->setOrigin( ICON_PAD, child_top - (*fit)->getRect().getHeight() ); - } - } - - for (items_t::iterator iter = mItems.begin(); - iter != mItems.end();) - { - items_t::iterator iit = iter++; - LLFolderViewItem* itemp = (*iit); - itemp->setVisible(itemp->getFiltered(filter_generation)); - - if (itemp->getVisible()) - { - S32 child_width = 0; - S32 child_height = 0; - S32 child_top = parent_item_height - running_height; - - target_height += itemp->arrange( &child_width, &child_height, filter_generation ); - itemp->reshape(itemp->getRect().getWidth(), child_height); - - mMinWidth = llmax(mMinWidth, child_width); - total_width = llmax( total_width, child_width ); - running_height += child_height; - itemp->setOrigin( ICON_PAD, child_top - itemp->getRect().getHeight() ); - } - } - - S32 dummy_s32; - BOOL dummy_bool; - S32 min_width; - mScrollContainer->calcVisibleSize( &min_width, &dummy_s32, &dummy_bool, &dummy_bool); - reshape( llmax(min_width, total_width), running_height ); - - S32 new_min_width; - mScrollContainer->calcVisibleSize( &new_min_width, &dummy_s32, &dummy_bool, &dummy_bool); - if (new_min_width != min_width) - { - reshape( llmax(min_width, total_width), running_height ); - } - - // move item renamer text field to item's new position - updateRenamerPosition(); - - mTargetHeight = (F32)target_height; - return llround(mTargetHeight); -} - -const std::string LLFolderView::getFilterSubString(BOOL trim) -{ - return mFilter.getFilterSubString(trim); -} - -void LLFolderView::filter( LLInventoryFilter& filter ) -{ - LLFastTimer t2(LLFastTimer::FTM_FILTER); - filter.setFilterCount(llclamp(gSavedSettings.getS32("FilterItemsPerFrame"), 1, 5000)); - - if (getCompletedFilterGeneration() < filter.getCurrentGeneration()) - { - mFiltered = FALSE; - mMinWidth = 0; - LLFolderViewFolder::filter(filter); - } -} - -void LLFolderView::reshape(S32 width, S32 height, BOOL called_from_parent) -{ - S32 min_width = 0; - S32 dummy_height; - BOOL dummy_bool; - if (mScrollContainer) - { - mScrollContainer->calcVisibleSize( &min_width, &dummy_height, &dummy_bool, &dummy_bool); - } - width = llmax(mMinWidth, min_width); - LLView::reshape(width, height, called_from_parent); - - mReshapeSignal(mSelectedItems, FALSE); -} - -void LLFolderView::addToSelectionList(LLFolderViewItem* item) -{ - if (item->isSelected()) - { - removeFromSelectionList(item); - } - if (mSelectedItems.size()) - { - mSelectedItems.back()->setIsCurSelection(FALSE); - } - item->setIsCurSelection(TRUE); - mSelectedItems.push_back(item); -} - -void LLFolderView::removeFromSelectionList(LLFolderViewItem* item) -{ - if (mSelectedItems.size()) - { - mSelectedItems.back()->setIsCurSelection(FALSE); - } - - selected_items_t::iterator item_iter; - for (item_iter = mSelectedItems.begin(); item_iter != mSelectedItems.end();) - { - if (*item_iter == item) - { - item_iter = mSelectedItems.erase(item_iter); - } - else - { - ++item_iter; - } - } - if (mSelectedItems.size()) - { - mSelectedItems.back()->setIsCurSelection(TRUE); - } -} - -LLFolderViewItem* LLFolderView::getCurSelectedItem( void ) -{ - if(mSelectedItems.size()) - { - LLFolderViewItem* itemp = mSelectedItems.back(); - llassert(itemp->getIsCurSelection()); - return itemp; - } - return NULL; -} - - -// Record the selected item and pass it down the hierachy. -BOOL LLFolderView::setSelection(LLFolderViewItem* selection, BOOL openitem, - BOOL take_keyboard_focus) -{ - if( selection == this ) - { - return FALSE; - } - - if( selection && take_keyboard_focus) - { - mParentPanel->setFocus(TRUE); - } - - // clear selection down here because change of keyboard focus can potentially - // affect selection - clearSelection(); - - if(selection) - { - addToSelectionList(selection); - } - - BOOL rv = LLFolderViewFolder::setSelection(selection, openitem, take_keyboard_focus); - if(openitem && selection) - { - selection->getParentFolder()->requestArrange(); - } - - llassert(mSelectedItems.size() <= 1); - - mSignalSelectCallback = take_keyboard_focus ? SIGNAL_KEYBOARD_FOCUS : SIGNAL_NO_KEYBOARD_FOCUS; - - return rv; -} - -void LLFolderView::setSelectionByID(const LLUUID& obj_id, BOOL take_keyboard_focus) -{ - LLFolderViewItem* itemp = getItemByID(obj_id); - if(itemp && itemp->getListener()) - { - itemp->getListener()->arrangeAndSet(itemp, TRUE, take_keyboard_focus); - mSelectThisID.setNull(); - return; - } - else - { - // save the desired item to be selected later (if/when ready) - mSelectThisID = obj_id; - } -} - -void LLFolderView::updateSelection() -{ - if (mSelectThisID.notNull()) - { - setSelectionByID(mSelectThisID, false); - } -} - -BOOL LLFolderView::changeSelection(LLFolderViewItem* selection, BOOL selected) -{ - BOOL rv = FALSE; - - // can't select root folder - if(!selection || selection == this) - { - return FALSE; - } - - if (!mAllowMultiSelect) - { - clearSelection(); - } - - selected_items_t::iterator item_iter; - for (item_iter = mSelectedItems.begin(); item_iter != mSelectedItems.end(); ++item_iter) - { - if (*item_iter == selection) - { - break; - } - } - - BOOL on_list = (item_iter != mSelectedItems.end()); - - if(selected && !on_list) - { - addToSelectionList(selection); - } - if(!selected && on_list) - { - removeFromSelectionList(selection); - } - - rv = LLFolderViewFolder::changeSelection(selection, selected); - - mSignalSelectCallback = SIGNAL_KEYBOARD_FOCUS; - - return rv; -} - -S32 LLFolderView::extendSelection(LLFolderViewItem* selection, LLFolderViewItem* last_selected, LLDynamicArray<LLFolderViewItem*>& items) -{ - S32 rv = 0; - - // now store resulting selection - if (mAllowMultiSelect) - { - LLFolderViewItem *cur_selection = getCurSelectedItem(); - rv = LLFolderViewFolder::extendSelection(selection, cur_selection, items); - for (S32 i = 0; i < items.count(); i++) - { - addToSelectionList(items[i]); - rv++; - } - } - else - { - setSelection(selection, FALSE, FALSE); - rv++; - } - - mSignalSelectCallback = SIGNAL_KEYBOARD_FOCUS; - return rv; -} - -void LLFolderView::sanitizeSelection() -{ - // store off current item in case it is automatically deselected - // and we want to preserve context - LLFolderViewItem* original_selected_item = getCurSelectedItem(); - - // Cache "Show all folders" filter setting - BOOL show_all_folders = (getRoot()->getShowFolderState() == LLInventoryFilter::SHOW_ALL_FOLDERS); - - std::vector<LLFolderViewItem*> items_to_remove; - selected_items_t::iterator item_iter; - for (item_iter = mSelectedItems.begin(); item_iter != mSelectedItems.end(); ++item_iter) - { - LLFolderViewItem* item = *item_iter; - - // ensure that each ancestor is open and potentially passes filtering - BOOL visible = item->potentiallyVisible(); // initialize from filter state for this item - // modify with parent open and filters states - LLFolderViewFolder* parent_folder = item->getParentFolder(); - if ( parent_folder ) - { - if ( show_all_folders ) - { // "Show all folders" is on, so this folder is visible - visible = TRUE; - } - else - { // Move up through parent folders and see what's visible - while(parent_folder) - { - visible = visible && parent_folder->isOpen() && parent_folder->potentiallyVisible(); - parent_folder = parent_folder->getParentFolder(); - } - } - } - - // deselect item if any ancestor is closed or didn't pass filter requirements. - if (!visible) - { - items_to_remove.push_back(item); - } - - // disallow nested selections (i.e. folder items plus one or more ancestors) - // could check cached mum selections count and only iterate if there are any - // but that may be a premature optimization. - selected_items_t::iterator other_item_iter; - for (other_item_iter = mSelectedItems.begin(); other_item_iter != mSelectedItems.end(); ++other_item_iter) - { - LLFolderViewItem* other_item = *other_item_iter; - for( parent_folder = other_item->getParentFolder(); parent_folder; parent_folder = parent_folder->getParentFolder()) - { - if (parent_folder == item) - { - // this is a descendent of the current folder, remove from list - items_to_remove.push_back(other_item); - break; - } - } - } - } - - std::vector<LLFolderViewItem*>::iterator item_it; - for (item_it = items_to_remove.begin(); item_it != items_to_remove.end(); ++item_it ) - { - changeSelection(*item_it, FALSE); // toggle selection (also removes from list) - } - - // if nothing selected after prior constraints... - if (mSelectedItems.empty()) - { - // ...select first available parent of original selection, or "My Inventory" otherwise - LLFolderViewItem* new_selection = NULL; - if (original_selected_item) - { - for(LLFolderViewFolder* parent_folder = original_selected_item->getParentFolder(); - parent_folder; - parent_folder = parent_folder->getParentFolder()) - { - if (parent_folder->potentiallyVisible()) - { - // give initial selection to first ancestor folder that potentially passes the filter - if (!new_selection) - { - new_selection = parent_folder; - } - - // if any ancestor folder of original item is closed, move the selection up - // to the highest closed - if (!parent_folder->isOpen()) - { - new_selection = parent_folder; - } - } - } - } - else - { - // nothing selected to start with, so pick "My Inventory" as best guess - new_selection = getItemByID(gAgent.getInventoryRootID()); - } - - if (new_selection) - { - setSelection(new_selection, FALSE, FALSE); - } - } -} - -void LLFolderView::clearSelection() -{ - if (mSelectedItems.size() > 0) - { - recursiveDeselect(FALSE); - mSelectedItems.clear(); - } - mSelectThisID.setNull(); -} - -BOOL LLFolderView::getSelectionList(std::set<LLUUID> &selection) -{ - selected_items_t::iterator item_it; - for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) - { - selection.insert((*item_it)->getListener()->getUUID()); - } - - return (selection.size() != 0); -} - -BOOL LLFolderView::startDrag(LLToolDragAndDrop::ESource source) -{ - std::vector<EDragAndDropType> types; - std::vector<LLUUID> cargo_ids; - selected_items_t::iterator item_it; - BOOL can_drag = TRUE; - if (!mSelectedItems.empty()) - { - for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) - { - EDragAndDropType type = DAD_NONE; - LLUUID id = LLUUID::null; - can_drag = can_drag && (*item_it)->getListener()->startDrag(&type, &id); - - types.push_back(type); - cargo_ids.push_back(id); - } - - LLToolDragAndDrop::getInstance()->beginMultiDrag(types, cargo_ids, source, mSourceID); - } - return can_drag; -} - -void LLFolderView::commitRename( const LLSD& data ) -{ - finishRenamingItem(); -} - -void LLFolderView::draw() -{ - static LLUIColor sSearchStatusColor = LLUIColorTable::instance().getColor("InventorySearchStatusColor", DEFAULT_WHITE); - if (mDebugFilters) - { - std::string current_filter_string = llformat("Current Filter: %d, Least Filter: %d, Auto-accept Filter: %d", - mFilter.getCurrentGeneration(), mFilter.getMinRequiredGeneration(), mFilter.getMustPassGeneration()); - sSmallFont->renderUTF8(current_filter_string, 0, 2, - getRect().getHeight() - sSmallFont->getLineHeight(), LLColor4(0.5f, 0.5f, 0.8f, 1.f), - LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE ); - } - - // if cursor has moved off of me during drag and drop - // close all auto opened folders - if (!mDragAndDropThisFrame) - { - closeAutoOpenedFolders(); - } - - // while dragging, update selection rendering to reflect single/multi drag status - if (LLToolDragAndDrop::getInstance()->hasMouseCapture()) - { - EAcceptance last_accept = LLToolDragAndDrop::getInstance()->getLastAccept(); - if (last_accept == ACCEPT_YES_SINGLE || last_accept == ACCEPT_YES_COPY_SINGLE) - { - setShowSingleSelection(TRUE); - } - else - { - setShowSingleSelection(FALSE); - } - } - else - { - setShowSingleSelection(FALSE); - } - - - if (mSearchTimer.getElapsedTimeF32() > gSavedSettings.getF32("TypeAheadTimeout") || !mSearchString.size()) - { - mSearchString.clear(); - } - - if (hasVisibleChildren() || getShowFolderState() == LLInventoryFilter::SHOW_ALL_FOLDERS) - { - mStatusText.clear(); - } - else - { - if (gInventory.backgroundFetchActive() || mCompletedFilterGeneration < mFilter.getMinRequiredGeneration()) - { - mStatusText = LLTrans::getString("Searching"); - sFont->renderUTF8(mStatusText, 0, 2, 1, sSearchStatusColor, LLFontGL::LEFT, LLFontGL::TOP, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE ); - } - else - { - mStatusText = LLTrans::getString("InventoryNoMatchingItems"); - sFont->renderUTF8(mStatusText, 0, 2, 1, sSearchStatusColor, LLFontGL::LEFT, LLFontGL::TOP, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE ); - } - } - - LLFolderViewFolder::draw(); - - mDragAndDropThisFrame = FALSE; -} - -void LLFolderView::finishRenamingItem( void ) -{ - if(!mRenamer) - { - return; - } - if( mRenameItem ) - { - mRenameItem->rename( mRenamer->getText() ); - } - - mRenamer->setCommitOnFocusLost( FALSE ); - mRenamer->setFocus( FALSE ); - mRenamer->setVisible( FALSE ); - mRenamer->setCommitOnFocusLost( TRUE ); - gFocusMgr.setTopCtrl( NULL ); - - if( mRenameItem ) - { - setSelectionFromRoot( mRenameItem, TRUE ); - mRenameItem = NULL; - } - - // List is re-sorted alphabeticly, so scroll to make sure the selected item is visible. - scrollToShowSelection(); -} - -void LLFolderView::closeRenamer( void ) -{ - // will commit current name (which could be same as original name) - mRenamer->setFocus( FALSE ); - mRenamer->setVisible( FALSE ); - gFocusMgr.setTopCtrl( NULL ); - - if( mRenameItem ) - { - setSelectionFromRoot( mRenameItem, TRUE ); - mRenameItem = NULL; - } -} - -void LLFolderView::removeSelectedItems( void ) -{ - if(getVisible() && getEnabled()) - { - // just in case we're removing the renaming item. - mRenameItem = NULL; - - // create a temporary structure which we will use to remove - // items, since the removal will futz with internal data - // structures. - std::vector<LLFolderViewItem*> items; - S32 count = mSelectedItems.size(); - if(count == 0) return; - LLFolderViewItem* item = NULL; - selected_items_t::iterator item_it; - for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) - { - item = *item_it; - if(item->isRemovable()) - { - items.push_back(item); - } - else - { - llinfos << "Cannot delete " << item->getName() << llendl; - return; - } - } - - // iterate through the new container. - count = items.size(); - LLUUID new_selection_id; - if(count == 1) - { - LLFolderViewItem* item_to_delete = items[0]; - LLFolderViewFolder* parent = item_to_delete->getParentFolder(); - LLFolderViewItem* new_selection = item_to_delete->getNextOpenNode(FALSE); - if (!new_selection) - { - new_selection = item_to_delete->getPreviousOpenNode(FALSE); - } - if(parent) - { - if (parent->removeItem(item_to_delete)) - { - // change selection on successful delete - if (new_selection) - { - setSelectionFromRoot(new_selection, new_selection->isOpen(), mParentPanel->hasFocus()); - } - else - { - setSelectionFromRoot(NULL, mParentPanel->hasFocus()); - } - } - } - arrangeAll(); - } - else if (count > 1) - { - LLDynamicArray<LLFolderViewEventListener*> listeners; - LLFolderViewEventListener* listener; - LLFolderViewItem* last_item = items[count - 1]; - LLFolderViewItem* new_selection = last_item->getNextOpenNode(FALSE); - while(new_selection && new_selection->isSelected()) - { - new_selection = new_selection->getNextOpenNode(FALSE); - } - if (!new_selection) - { - new_selection = last_item->getPreviousOpenNode(FALSE); - while (new_selection && new_selection->isSelected()) - { - new_selection = new_selection->getPreviousOpenNode(FALSE); - } - } - if (new_selection) - { - setSelectionFromRoot(new_selection, new_selection->isOpen(), mParentPanel->hasFocus()); - } - else - { - setSelectionFromRoot(NULL, mParentPanel->hasFocus()); - } - - for(S32 i = 0; i < count; ++i) - { - listener = items[i]->getListener(); - if(listener && (listeners.find(listener) == LLDynamicArray<LLFolderViewEventListener*>::FAIL)) - { - listeners.put(listener); - } - } - listener = listeners.get(0); - if(listener) - { - listener->removeBatch(listeners); - } - } - arrangeAll(); - scrollToShowSelection(); - } -} - -// open the selected item. -void LLFolderView::openSelectedItems( void ) -{ - if(getVisible() && getEnabled()) - { - if (mSelectedItems.size() == 1) - { - mSelectedItems.front()->openItem(); - } - else - { - LLMultiPreview* multi_previewp = new LLMultiPreview(); - LLMultiProperties* multi_propertiesp = new LLMultiProperties(); - - selected_items_t::iterator item_it; - for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) - { - // IT_{OBJECT,ATTACHMENT} creates LLProperties - // floaters; others create LLPreviews. Put - // each one in the right type of container. - LLFolderViewEventListener* listener = (*item_it)->getListener(); - bool is_prop = listener && (listener->getInventoryType() == LLInventoryType::IT_OBJECT || listener->getInventoryType() == LLInventoryType::IT_ATTACHMENT); - if (is_prop) - LLFloater::setFloaterHost(multi_propertiesp); - else - LLFloater::setFloaterHost(multi_previewp); - (*item_it)->openItem(); - } - - LLFloater::setFloaterHost(NULL); - // *NOTE: LLMulti* will safely auto-delete when open'd - // without any children. - multi_previewp->openFloater(LLSD()); - multi_propertiesp->openFloater(LLSD()); - } - } -} - -void LLFolderView::propertiesSelectedItems( void ) -{ - if(getVisible() && getEnabled()) - { - if (mSelectedItems.size() == 1) - { - LLFolderViewItem* folder_item = mSelectedItems.front(); - if(!folder_item) return; - folder_item->getListener()->showProperties(); - } - else - { - LLMultiProperties* multi_propertiesp = new LLMultiProperties(); - - LLFloater::setFloaterHost(multi_propertiesp); - - selected_items_t::iterator item_it; - for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) - { - (*item_it)->getListener()->showProperties(); - } - - LLFloater::setFloaterHost(NULL); - multi_propertiesp->openFloater(LLSD()); - } - } -} - -void LLFolderView::autoOpenItem( LLFolderViewFolder* item ) -{ - if (mAutoOpenItems.check() == item || mAutoOpenItems.getDepth() >= (U32)AUTO_OPEN_STACK_DEPTH) - { - return; - } - - // close auto-opened folders - LLFolderViewFolder* close_item = mAutoOpenItems.check(); - while (close_item && close_item != item->getParentFolder()) - { - mAutoOpenItems.pop(); - close_item->setOpenArrangeRecursively(FALSE); - close_item = mAutoOpenItems.check(); - } - - item->requestArrange(); - - mAutoOpenItems.push(item); - - item->setOpen(TRUE); - scrollToShowItem(item); -} - -void LLFolderView::closeAutoOpenedFolders() -{ - while (mAutoOpenItems.check()) - { - LLFolderViewFolder* close_item = mAutoOpenItems.pop(); - close_item->setOpen(FALSE); - } - - if (mAutoOpenCandidate) - { - mAutoOpenCandidate->setAutoOpenCountdown(0.f); - } - mAutoOpenCandidate = NULL; - mAutoOpenTimer.stop(); -} - -BOOL LLFolderView::autoOpenTest(LLFolderViewFolder* folder) -{ - if (folder && mAutoOpenCandidate == folder) - { - if (mAutoOpenTimer.getStarted()) - { - if (!mAutoOpenCandidate->isOpen()) - { - mAutoOpenCandidate->setAutoOpenCountdown(clamp_rescale(mAutoOpenTimer.getElapsedTimeF32(), 0.f, sAutoOpenTime, 0.f, 1.f)); - } - if (mAutoOpenTimer.getElapsedTimeF32() > sAutoOpenTime) - { - autoOpenItem(folder); - mAutoOpenTimer.stop(); - return TRUE; - } - } - return FALSE; - } - - // otherwise new candidate, restart timer - if (mAutoOpenCandidate) - { - mAutoOpenCandidate->setAutoOpenCountdown(0.f); - } - mAutoOpenCandidate = folder; - mAutoOpenTimer.start(); - return FALSE; -} - -BOOL LLFolderView::canCopy() const -{ - if (!(getVisible() && getEnabled() && (mSelectedItems.size() > 0))) - { - return FALSE; - } - - for (selected_items_t::const_iterator selected_it = mSelectedItems.begin(); selected_it != mSelectedItems.end(); ++selected_it) - { - const LLFolderViewItem* item = *selected_it; - if (!item->getListener()->isItemCopyable()) - { - return FALSE; - } - } - return TRUE; -} - -// copy selected item -void LLFolderView::copy() -{ - // *NOTE: total hack to clear the inventory clipboard - LLInventoryClipboard::instance().reset(); - S32 count = mSelectedItems.size(); - if(getVisible() && getEnabled() && (count > 0)) - { - LLFolderViewEventListener* listener = NULL; - selected_items_t::iterator item_it; - for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) - { - listener = (*item_it)->getListener(); - if(listener) - { - listener->copyToClipboard(); - } - } - } - mSearchString.clear(); -} - -BOOL LLFolderView::canCut() const -{ - return FALSE; -} - -void LLFolderView::cut() -{ - // implement Windows-style cut-and-leave -} - -BOOL LLFolderView::canPaste() const -{ - if (mSelectedItems.empty()) - { - return FALSE; - } - - if(getVisible() && getEnabled()) - { - for (selected_items_t::const_iterator item_it = mSelectedItems.begin(); - item_it != mSelectedItems.end(); ++item_it) - { - // *TODO: only check folders and parent folders of items - const LLFolderViewItem* item = (*item_it); - const LLFolderViewEventListener* listener = item->getListener(); - if(!listener || !listener->isClipboardPasteable()) - { - const LLFolderViewFolder* folderp = item->getParentFolder(); - listener = folderp->getListener(); - if (!listener || !listener->isClipboardPasteable()) - { - return FALSE; - } - } - } - return TRUE; - } - return FALSE; -} - -// paste selected item -void LLFolderView::paste() -{ - if(getVisible() && getEnabled()) - { - // find set of unique folders to paste into - std::set<LLFolderViewItem*> folder_set; - - selected_items_t::iterator selected_it; - for (selected_it = mSelectedItems.begin(); selected_it != mSelectedItems.end(); ++selected_it) - { - LLFolderViewItem* item = *selected_it; - LLFolderViewEventListener* listener = item->getListener(); - if (listener->getInventoryType() != LLInventoryType::IT_CATEGORY) - { - item = item->getParentFolder(); - } - folder_set.insert(item); - } - - std::set<LLFolderViewItem*>::iterator set_iter; - for(set_iter = folder_set.begin(); set_iter != folder_set.end(); ++set_iter) - { - LLFolderViewEventListener* listener = (*set_iter)->getListener(); - if(listener && listener->isClipboardPasteable()) - { - listener->pasteFromClipboard(); - } - } - } - mSearchString.clear(); -} - -// public rename functionality - can only start the process -void LLFolderView::startRenamingSelectedItem( void ) -{ - // make sure selection is visible - scrollToShowSelection(); - - S32 count = mSelectedItems.size(); - LLFolderViewItem* item = NULL; - if(count > 0) - { - item = mSelectedItems.front(); - } - if(getVisible() && getEnabled() && (count == 1) && item && item->getListener() && - item->getListener()->isItemRenameable()) - { - mRenameItem = item; - - updateRenamerPosition(); - - - mRenamer->setText(item->getName()); - mRenamer->selectAll(); - mRenamer->setVisible( TRUE ); - // set focus will fail unless item is visible - mRenamer->setFocus( TRUE ); - mRenamer->setTopLostCallback(onRenamerLost); - gFocusMgr.setTopCtrl( mRenamer ); - } -} - -BOOL LLFolderView::handleKeyHere( KEY key, MASK mask ) -{ - BOOL handled = FALSE; - - // SL-51858: Key presses are not being passed to the Popup menu. - // A proper fix is non-trivial so instead just close the menu. - LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get(); - if (menu && menu->isOpen()) - { - LLMenuGL::sMenuContainer->hideMenus(); - } - - LLView *item = NULL; - if (getChildCount() > 0) - { - item = *(getChildList()->begin()); - } - - switch( key ) - { - case KEY_F2: - mSearchString.clear(); - startRenamingSelectedItem(); - handled = TRUE; - break; - - case KEY_RETURN: - if (mask == MASK_NONE) - { - if( mRenameItem && mRenamer->getVisible() ) - { - finishRenamingItem(); - mSearchString.clear(); - handled = TRUE; - } - else - { - LLFolderView::openSelectedItems(); - handled = TRUE; - } - } - break; - - case KEY_ESCAPE: - if( mRenameItem && mRenamer->getVisible() ) - { - closeRenamer(); - handled = TRUE; - } - mSearchString.clear(); - break; - - case KEY_PAGE_UP: - mSearchString.clear(); - mScrollContainer->pageUp(30); - handled = TRUE; - break; - - case KEY_PAGE_DOWN: - mSearchString.clear(); - mScrollContainer->pageDown(30); - handled = TRUE; - break; - - case KEY_HOME: - mSearchString.clear(); - mScrollContainer->goToTop(); - handled = TRUE; - break; - - case KEY_END: - mSearchString.clear(); - mScrollContainer->goToBottom(); - break; - - case KEY_DOWN: - if((mSelectedItems.size() > 0) && mScrollContainer) - { - LLFolderViewItem* last_selected = getCurSelectedItem(); - - if (!mKeyboardSelection) - { - setSelection(last_selected, FALSE, TRUE); - mKeyboardSelection = TRUE; - } - - LLFolderViewItem* next = NULL; - if (mask & MASK_SHIFT) - { - // don't shift select down to children of folders (they are implicitly selected through parent) - next = last_selected->getNextOpenNode(FALSE); - if (next) - { - if (next->isSelected()) - { - // shrink selection - changeSelectionFromRoot(last_selected, FALSE); - } - else if (last_selected->getParentFolder() == next->getParentFolder()) - { - // grow selection - changeSelectionFromRoot(next, TRUE); - } - } - } - else - { - next = last_selected->getNextOpenNode(); - if( next ) - { - if (next == last_selected) - { - return FALSE; - } - setSelection( next, FALSE, TRUE ); - } - } - scrollToShowSelection(); - mSearchString.clear(); - handled = TRUE; - } - break; - - case KEY_UP: - if((mSelectedItems.size() > 0) && mScrollContainer) - { - LLFolderViewItem* last_selected = mSelectedItems.back(); - - if (!mKeyboardSelection) - { - setSelection(last_selected, FALSE, TRUE); - mKeyboardSelection = TRUE; - } - - LLFolderViewItem* prev = NULL; - if (mask & MASK_SHIFT) - { - // don't shift select down to children of folders (they are implicitly selected through parent) - prev = last_selected->getPreviousOpenNode(FALSE); - if (prev) - { - if (prev->isSelected()) - { - // shrink selection - changeSelectionFromRoot(last_selected, FALSE); - } - else if (last_selected->getParentFolder() == prev->getParentFolder()) - { - // grow selection - changeSelectionFromRoot(prev, TRUE); - } - } - } - else - { - prev = last_selected->getPreviousOpenNode(); - if( prev ) - { - if (prev == this) - { - return FALSE; - } - setSelection( prev, FALSE, TRUE ); - } - } - scrollToShowSelection(); - mSearchString.clear(); - - handled = TRUE; - } - break; - - case KEY_RIGHT: - if(mSelectedItems.size()) - { - LLFolderViewItem* last_selected = getCurSelectedItem(); - last_selected->setOpen( TRUE ); - mSearchString.clear(); - handled = TRUE; - } - break; - - case KEY_LEFT: - if(mSelectedItems.size()) - { - LLFolderViewItem* last_selected = getCurSelectedItem(); - LLFolderViewItem* parent_folder = last_selected->getParentFolder(); - if (!last_selected->isOpen() && parent_folder && parent_folder->getParentFolder()) - { - setSelection(parent_folder, FALSE, TRUE); - } - else - { - last_selected->setOpen( FALSE ); - } - mSearchString.clear(); - scrollToShowSelection(); - handled = TRUE; - } - break; - } - - if (!handled && mParentPanel->hasFocus()) - { - if (key == KEY_BACKSPACE) - { - mSearchTimer.reset(); - if (mSearchString.size()) - { - mSearchString.erase(mSearchString.size() - 1, 1); - } - search(getCurSelectedItem(), mSearchString, FALSE); - handled = TRUE; - } - } - - return handled; -} - - -BOOL LLFolderView::handleUnicodeCharHere(llwchar uni_char) -{ - if ((uni_char < 0x20) || (uni_char == 0x7F)) // Control character or DEL - { - return FALSE; - } - - if (uni_char > 0x7f) - { - llwarns << "LLFolderView::handleUnicodeCharHere - Don't handle non-ascii yet, aborting" << llendl; - return FALSE; - } - - BOOL handled = FALSE; - if (gFocusMgr.childHasKeyboardFocus(getRoot())) - { - // SL-51858: Key presses are not being passed to the Popup menu. - // A proper fix is non-trivial so instead just close the menu. - LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get(); - if (menu && menu->isOpen()) - { - LLMenuGL::sMenuContainer->hideMenus(); - } - - //do text search - if (mSearchTimer.getElapsedTimeF32() > gSavedSettings.getF32("TypeAheadTimeout")) - { - mSearchString.clear(); - } - mSearchTimer.reset(); - if (mSearchString.size() < 128) - { - mSearchString += uni_char; - } - search(getCurSelectedItem(), mSearchString, FALSE); - - handled = TRUE; - } - - return handled; -} - - -BOOL LLFolderView::canDoDelete() const -{ - if (mSelectedItems.size() == 0) return FALSE; - - for (selected_items_t::const_iterator item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) - { - if (!(*item_it)->getListener()->isItemRemovable()) - { - return FALSE; - } - } - return TRUE; -} - -void LLFolderView::doDelete() -{ - if(mSelectedItems.size() > 0) - { - removeSelectedItems(); - } -} - - -BOOL LLFolderView::handleMouseDown( S32 x, S32 y, MASK mask ) -{ - mKeyboardSelection = FALSE; - mSearchString.clear(); - - mParentPanel->setFocus(TRUE); - - return LLView::handleMouseDown( x, y, mask ); -} - -BOOL LLFolderView::search(LLFolderViewItem* first_item, const std::string &search_string, BOOL backward) -{ - // get first selected item - LLFolderViewItem* search_item = first_item; - - // make sure search string is upper case - std::string upper_case_string = search_string; - LLStringUtil::toUpper(upper_case_string); - - // if nothing selected, select first item in folder - if (!search_item) - { - // start from first item - search_item = getNextFromChild(NULL); - } - - // search over all open nodes for first substring match (with wrapping) - BOOL found = FALSE; - LLFolderViewItem* original_search_item = search_item; - do - { - // wrap at end - if (!search_item) - { - if (backward) - { - search_item = getPreviousFromChild(NULL); - } - else - { - search_item = getNextFromChild(NULL); - } - if (!search_item || search_item == original_search_item) - { - break; - } - } - - const std::string current_item_label(search_item->getSearchableLabel()); - S32 search_string_length = llmin(upper_case_string.size(), current_item_label.size()); - if (!current_item_label.compare(0, search_string_length, upper_case_string)) - { - found = TRUE; - break; - } - if (backward) - { - search_item = search_item->getPreviousOpenNode(); - } - else - { - search_item = search_item->getNextOpenNode(); - } - - } while(search_item != original_search_item); - - - if (found) - { - setSelection(search_item, FALSE, TRUE); - scrollToShowSelection(); - } - - return found; -} - -BOOL LLFolderView::handleDoubleClick( S32 x, S32 y, MASK mask ) -{ - // skip LLFolderViewFolder::handleDoubleClick() - return LLView::handleDoubleClick( x, y, mask ); -} - -BOOL LLFolderView::handleRightMouseDown( S32 x, S32 y, MASK mask ) -{ - // all user operations move keyboard focus to inventory - // this way, we know when to stop auto-updating a search - mParentPanel->setFocus(TRUE); - - BOOL handled = childrenHandleRightMouseDown(x, y, mask) != NULL; - S32 count = mSelectedItems.size(); - LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get(); - if(handled && (count > 0) && menu) - { - if (mCallbackRegistrar) - mCallbackRegistrar->pushScope(); - //menu->empty(); - const LLView::child_list_t *list = menu->getChildList(); - - LLView::child_list_t::const_iterator menu_itor; - for (menu_itor = list->begin(); menu_itor != list->end(); ++menu_itor) - { - (*menu_itor)->setVisible(TRUE); - (*menu_itor)->setEnabled(TRUE); - } - - // Successively filter out invalid options - selected_items_t::iterator item_itor; - U32 flags = FIRST_SELECTED_ITEM; - for (item_itor = mSelectedItems.begin(); item_itor != mSelectedItems.end(); ++item_itor) - { - (*item_itor)->buildContextMenu(*menu, flags); - flags = 0x0; - } - - menu->updateParent(LLMenuGL::sMenuContainer); - LLMenuGL::showPopup(this, menu, x, y); - if (mCallbackRegistrar) - mCallbackRegistrar->popScope(); - } - else - { - if(menu && menu->getVisible()) - { - menu->setVisible(FALSE); - } - setSelection(NULL, FALSE, TRUE); - } - return handled; -} - -BOOL LLFolderView::handleHover( S32 x, S32 y, MASK mask ) -{ - return LLView::handleHover( x, y, mask ); -} - -BOOL LLFolderView::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, - EDragAndDropType cargo_type, - void* cargo_data, - EAcceptance* accept, - std::string& tooltip_msg) -{ - mDragAndDropThisFrame = TRUE; - BOOL handled = LLView::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, - accept, tooltip_msg); - - if (handled) - { - lldebugst(LLERR_USER_INPUT) << "dragAndDrop handled by LLFolderView" << llendl; - } - - return handled; -} - -BOOL LLFolderView::handleScrollWheel(S32 x, S32 y, S32 clicks) -{ - if (mScrollContainer) - { - return mScrollContainer->handleScrollWheel(x, y, clicks); - } - return FALSE; -} - -void LLFolderView::deleteAllChildren() -{ - if(mRenamer == gFocusMgr.getTopCtrl()) - { - gFocusMgr.setTopCtrl(NULL); - } - LLView::deleteViewByHandle(mPopupMenuHandle); - mPopupMenuHandle = LLHandle<LLView>(); - mRenamer = NULL; - mRenameItem = NULL; - clearSelection(); - LLView::deleteAllChildren(); -} - -void LLFolderView::scrollToShowSelection() -{ - if (mSelectedItems.size()) - { - mNeedsScroll = TRUE; - } -} - -// If the parent is scroll containter, scroll it to make the selection -// is maximally visible. -void LLFolderView::scrollToShowItem(LLFolderViewItem* item) -{ - // don't scroll to items when mouse is being used to scroll/drag and drop - if (gFocusMgr.childHasMouseCapture(mScrollContainer)) - { - mNeedsScroll = FALSE; - return; - } - if(item && mScrollContainer) - { - LLRect local_rect = item->getRect(); - LLRect item_scrolled_rect; // item position relative to display area of scroller - - S32 icon_height = mIcon.isNull() ? 0 : mIcon->getHeight(); - S32 label_height = llround(sFont->getLineHeight()); - // when navigating with keyboard, only move top of folders on screen, otherwise show whole folder - S32 max_height_to_show = gFocusMgr.childHasKeyboardFocus(this) ? (llmax( icon_height, label_height ) + ICON_PAD) : local_rect.getHeight(); - item->localPointToOtherView(item->getIndentation(), llmax(0, local_rect.getHeight() - max_height_to_show), &item_scrolled_rect.mLeft, &item_scrolled_rect.mBottom, mScrollContainer); - item->localPointToOtherView(local_rect.getWidth(), local_rect.getHeight(), &item_scrolled_rect.mRight, &item_scrolled_rect.mTop, mScrollContainer); - - item_scrolled_rect.mRight = llmin(item_scrolled_rect.mLeft + MIN_ITEM_WIDTH_VISIBLE, item_scrolled_rect.mRight); - LLCoordGL scroll_offset(-mScrollContainer->getBorderWidth() - item_scrolled_rect.mLeft, - mScrollContainer->getRect().getHeight() - item_scrolled_rect.mTop - 1); - - S32 max_scroll_offset = getVisibleRect().getHeight() - item_scrolled_rect.getHeight(); - if (item != mLastScrollItem || // if we're scrolling to focus on a new item - // or the item has just appeared on screen and it wasn't onscreen before - (scroll_offset.mY > 0 && scroll_offset.mY < max_scroll_offset && - (mLastScrollOffset.mY < 0 || mLastScrollOffset.mY > max_scroll_offset))) - { - // we now have a position on screen that we want to keep stable - // offset of selection relative to top of visible area - mLastScrollOffset = scroll_offset; - mLastScrollItem = item; - } - - mScrollContainer->scrollToShowRect( item_scrolled_rect, mLastScrollOffset ); - - // after scrolling, store new offset - // in case we don't have room to maintain the original position - LLCoordGL new_item_left_top; - item->localPointToOtherView(item->getIndentation(), item->getRect().getHeight(), &new_item_left_top.mX, &new_item_left_top.mY, mScrollContainer); - mLastScrollOffset.set(-mScrollContainer->getBorderWidth() - new_item_left_top.mX, mScrollContainer->getRect().getHeight() - new_item_left_top.mY - 1); - } -} - -LLRect LLFolderView::getVisibleRect() -{ - S32 visible_height = mScrollContainer->getRect().getHeight(); - S32 visible_width = mScrollContainer->getRect().getWidth(); - LLRect visible_rect; - visible_rect.setLeftTopAndSize(-getRect().mLeft, visible_height - getRect().mBottom, visible_width, visible_height); - return visible_rect; -} - -BOOL LLFolderView::getShowSelectionContext() -{ - if (mShowSelectionContext) - { - return TRUE; - } - LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get(); - if (menu && menu->getVisible()) - { - return TRUE; - } - return FALSE; -} - -void LLFolderView::setShowSingleSelection(BOOL show) -{ - if (show != mShowSingleSelection) - { - mMultiSelectionFadeTimer.reset(); - mShowSingleSelection = show; - } -} - -void LLFolderView::addItemID(const LLUUID& id, LLFolderViewItem* itemp) -{ - mItemMap[id] = itemp; -} - -void LLFolderView::removeItemID(const LLUUID& id) -{ - mItemMap.erase(id); -} - -LLFolderViewItem* LLFolderView::getItemByID(const LLUUID& id) -{ - if (id.isNull()) - { - return this; - } - - std::map<LLUUID, LLFolderViewItem*>::iterator map_it; - map_it = mItemMap.find(id); - if (map_it != mItemMap.end()) - { - return map_it->second; - } - - return NULL; -} - -bool LLFolderView::doToSelected(LLInventoryModel* model, const LLSD& userdata) -{ - std::string action = userdata.asString(); - - if ("rename" == action) - { - startRenamingSelectedItem(); - return true; - } - if ("delete" == action) - { - removeSelectedItems(); - return true; - } - - if ("copy" == action) - { - LLInventoryClipboard::instance().reset(); - } - - std::set<LLUUID> selected_items; - getSelectionList(selected_items); - - LLMultiPreview* multi_previewp = NULL; - LLMultiProperties* multi_propertiesp = NULL; - - if (("task_open" == action || "open" == action) && selected_items.size() > 1) - { - multi_previewp = new LLMultiPreview(); - gFloaterView->addChild(multi_previewp); - - LLFloater::setFloaterHost(multi_previewp); - - } - else if (("task_properties" == action || "properties" == action) && selected_items.size() > 1) - { - multi_propertiesp = new LLMultiProperties(); - gFloaterView->addChild(multi_propertiesp); - - LLFloater::setFloaterHost(multi_propertiesp); - } - - std::set<LLUUID>::iterator set_iter; - - for (set_iter = selected_items.begin(); set_iter != selected_items.end(); ++set_iter) - { - LLFolderViewItem* folder_item = getItemByID(*set_iter); - if(!folder_item) continue; - LLInvFVBridge* bridge = (LLInvFVBridge*)folder_item->getListener(); - if(!bridge) continue; - - bridge->performAction(this, model, action); - } - - LLFloater::setFloaterHost(NULL); - if (multi_previewp) - { - multi_previewp->openFloater(LLSD()); - } - else if (multi_propertiesp) - { - multi_propertiesp->openFloater(LLSD()); - } - - return true; -} - -// Main idle routine -void LLFolderView::doIdle() -{ - LLFastTimer t2(LLFastTimer::FTM_INVENTORY); - - BOOL debug_filters = gSavedSettings.getBOOL("DebugInventoryFilters"); - if (debug_filters != getDebugFilters()) - { - mDebugFilters = debug_filters; - arrangeAll(); - } - - mFilter.clearModified(); - BOOL filter_modified_and_active = mCompletedFilterGeneration < mFilter.getCurrentGeneration() && - mFilter.isNotDefault(); - mNeedsAutoSelect = filter_modified_and_active && - !(gFocusMgr.childHasKeyboardFocus(this) || gFocusMgr.getMouseCapture()); - - // filter to determine visiblity before arranging - filterFromRoot(); - - // automatically show matching items, and select first one - // do this every frame until user puts keyboard focus into the inventory window - // signaling the end of the automatic update - // only do this when mNeedsFilter is set, meaning filtered items have - // potentially changed - if (mNeedsAutoSelect) - { - LLFastTimer t3(LLFastTimer::FTM_AUTO_SELECT); - // select new item only if a filtered item not currently selected - LLFolderViewItem* selected_itemp = mSelectedItems.empty() ? NULL : mSelectedItems.back(); - if ((!selected_itemp || !selected_itemp->getFiltered()) && !mAutoSelectOverride) - { - // select first filtered item - LLSelectFirstFilteredItem filter; - applyFunctorRecursively(filter); - } - scrollToShowSelection(); - } - - BOOL is_visible = isInVisibleChain(); - - if ( is_visible ) - { - sanitizeSelection(); - if( needsArrange() ) - { - arrangeFromRoot(); - } - } - - if (mSelectedItems.size() && mNeedsScroll) - { - scrollToShowItem(mSelectedItems.back()); - // continue scrolling until animated layout change is done - if (getCompletedFilterGeneration() >= mFilter.getMinRequiredGeneration() && - (!needsArrange() || !is_visible)) - { - mNeedsScroll = FALSE; - } - } - - if (mSignalSelectCallback) - { - //RN: we use keyboard focus as a proxy for user-explicit actions - BOOL take_keyboard_focus = (mSignalSelectCallback == SIGNAL_KEYBOARD_FOCUS); - mSelectSignal(mSelectedItems, take_keyboard_focus); - } - mSignalSelectCallback = FALSE; -} - - -//static -void LLFolderView::idle(void* user_data) -{ - LLFolderView* self = (LLFolderView*)user_data; - if ( self ) - { // Do the real idle - self->doIdle(); - } -} - -void LLFolderView::dumpSelectionInformation() -{ - llinfos << "LLFolderView::dumpSelectionInformation()" << llendl; - llinfos << "****************************************" << llendl; - selected_items_t::iterator item_it; - for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) - { - llinfos << " " << (*item_it)->getName() << llendl; - } - llinfos << "****************************************" << llendl; -} - -void LLFolderView::updateRenamerPosition() -{ - if(mRenameItem) - { - S32 x = ARROW_SIZE + TEXT_PAD + ICON_WIDTH + ICON_PAD - 1 + mRenameItem->getIndentation(); - S32 y = llfloor(mRenameItem->getRect().getHeight()-sFont->getLineHeight()-2); - mRenameItem->localPointToScreen( x, y, &x, &y ); - screenPointToLocal( x, y, &x, &y ); - mRenamer->setOrigin( x, y ); - - S32 scroller_height = 0; - S32 scroller_width = gViewerWindow->getWindowWidth(); - BOOL dummy_bool; - if (mScrollContainer) - { - mScrollContainer->calcVisibleSize( &scroller_width, &scroller_height, &dummy_bool, &dummy_bool); - } - - S32 width = llmax(llmin(mRenameItem->getRect().getWidth() - x, scroller_width - x - getRect().mLeft), MINIMUM_RENAMER_WIDTH); - S32 height = llfloor(sFont->getLineHeight() + RENAME_HEIGHT_PAD); - mRenamer->reshape( width, height, TRUE ); - } -} - - -///---------------------------------------------------------------------------- -/// Local function definitions -///---------------------------------------------------------------------------- -bool LLInventorySort::updateSort(U32 order) -{ - if (order != mSortOrder) - { - mSortOrder = order; - mByDate = (order & LLInventoryFilter::SO_DATE); - mSystemToTop = (order & LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP); - mFoldersByName = (order & LLInventoryFilter::SO_FOLDERS_BY_NAME); - return true; - } - return false; -} - -bool LLInventorySort::operator()(const LLFolderViewItem* const& a, const LLFolderViewItem* const& b) -{ - // We sort by name if we aren't sorting by date - // OR if these are folders and we are sorting folders by name. - bool by_name = (!mByDate - || (mFoldersByName - && (a->getSortGroup() != SG_ITEM))); - - if (a->getSortGroup() != b->getSortGroup()) - { - if (mSystemToTop) - { - // Group order is System Folders, Trash, Normal Folders, Items - return (a->getSortGroup() < b->getSortGroup()); - } - else if (mByDate) - { - // Trash needs to go to the bottom if we are sorting by date - if ( (a->getSortGroup() == SG_TRASH_FOLDER) - || (b->getSortGroup() == SG_TRASH_FOLDER)) - { - return (b->getSortGroup() == SG_TRASH_FOLDER); - } - } - } - - if (by_name) - { - S32 compare = LLStringUtil::compareDict(a->getLabel(), b->getLabel()); - if (0 == compare) - { - return (a->getCreationDate() > b->getCreationDate()); - } - else - { - return (compare < 0); - } - } - else - { - // BUG: This is very very slow. The getCreationDate() is log n in number - // of inventory items. - time_t first_create = a->getCreationDate(); - time_t second_create = b->getCreationDate(); - if (first_create == second_create) - { - return (LLStringUtil::compareDict(a->getLabel(), b->getLabel()) < 0); - } - else - { - return (first_create > second_create); - } - } -} - -//static -void LLFolderView::onRenamerLost( LLFocusableElement* renamer, void* user_data) -{ - LLUICtrl* uictrl = dynamic_cast<LLUICtrl*>(renamer); - if (uictrl) - { - uictrl->setVisible(FALSE); - } -} - -void delete_selected_item(void* user_data) -{ - if(user_data) - { - LLFolderView* fv = reinterpret_cast<LLFolderView*>(user_data); - fv->removeSelectedItems(); - } -} - -void copy_selected_item(void* user_data) -{ - if(user_data) - { - LLFolderView* fv = reinterpret_cast<LLFolderView*>(user_data); - fv->copy(); - } -} - -void paste_items(void* user_data) -{ - if(user_data) - { - LLFolderView* fv = reinterpret_cast<LLFolderView*>(user_data); - fv->paste(); - } -} - -void open_selected_items(void* user_data) -{ - if(user_data) - { - LLFolderView* fv = reinterpret_cast<LLFolderView*>(user_data); - fv->openSelectedItems(); - } -} - -void properties_selected_items(void* user_data) -{ - if(user_data) - { - LLFolderView* fv = reinterpret_cast<LLFolderView*>(user_data); - fv->propertiesSelectedItems(); - } -} - -///---------------------------------------------------------------------------- -/// Class LLFolderViewEventListener -///---------------------------------------------------------------------------- - -void LLFolderViewEventListener::arrangeAndSet(LLFolderViewItem* focus, - BOOL set_selection, - BOOL take_keyboard_focus) -{ - if(!focus) return; - LLFolderView* root = focus->getRoot(); - focus->getParentFolder()->requestArrange(); - if(set_selection) - { - focus->setSelectionFromRoot(focus, TRUE, take_keyboard_focus); - if(root) - { - root->scrollToShowSelection(); + mSearchString.clear(); } - } -} - - -///---------------------------------------------------------------------------- -/// Class LLInventoryFilter -///---------------------------------------------------------------------------- -LLInventoryFilter::LLInventoryFilter(const std::string& name) : - mName(name), - mModified(FALSE), - mNeedTextRebuild(TRUE) -{ - mFilterOps.mFilterTypes = 0xffffffff; - mFilterOps.mMinDate = time_min(); - mFilterOps.mMaxDate = time_max(); - mFilterOps.mHoursAgo = 0; - mFilterOps.mShowFolderState = SHOW_NON_EMPTY_FOLDERS; - mFilterOps.mPermissions = PERM_NONE; - - mOrder = SO_FOLDERS_BY_NAME; // This gets overridden by a pref immediately - - mSubStringMatchOffset = 0; - mFilterSubString.clear(); - mFilterGeneration = 0; - mMustPassGeneration = S32_MAX; - mMinRequiredGeneration = 0; - mFilterCount = 0; - mNextFilterGeneration = mFilterGeneration + 1; + mSearchTimer.reset(); + if (mSearchString.size() < 128) + { + mSearchString += uni_char; + } + search(getCurSelectedItem(), mSearchString, FALSE); - mLastLogoff = gSavedPerAccountSettings.getU32("LastLogoff"); - mFilterBehavior = FILTER_NONE; + handled = TRUE; + } - // copy mFilterOps into mDefaultFilterOps - markDefault(); + return handled; } -LLInventoryFilter::~LLInventoryFilter() -{ -} -BOOL LLInventoryFilter::check(LLFolderViewItem* item) +BOOL LLFolderView::canDoDelete() const { - time_t earliest; + if (mSelectedItems.size() == 0) return FALSE; - earliest = time_corrected() - mFilterOps.mHoursAgo * 3600; - if (mFilterOps.mMinDate > time_min() && mFilterOps.mMinDate < earliest) - { - earliest = mFilterOps.mMinDate; - } - else if (!mFilterOps.mHoursAgo) + for (selected_items_t::const_iterator item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) { - earliest = 0; + if (!(*item_it)->getListener()->isItemRemovable()) + { + return FALSE; + } } - LLFolderViewEventListener* listener = item->getListener(); - mSubStringMatchOffset = mFilterSubString.size() ? item->getSearchableLabel().find(mFilterSubString) : std::string::npos; - BOOL passed = (0x1 << listener->getInventoryType() & mFilterOps.mFilterTypes || listener->getInventoryType() == LLInventoryType::IT_NONE) - && (mFilterSubString.size() == 0 || mSubStringMatchOffset != std::string::npos) - && ((listener->getPermissionMask() & mFilterOps.mPermissions) == mFilterOps.mPermissions) - && (listener->getCreationDate() >= earliest && listener->getCreationDate() <= mFilterOps.mMaxDate); - return passed; + return TRUE; } -const std::string LLInventoryFilter::getFilterSubString(BOOL trim) +void LLFolderView::doDelete() { - return mFilterSubString; + if(mSelectedItems.size() > 0) + { + removeSelectedItems(); + } } -std::string::size_type LLInventoryFilter::getStringMatchOffset() const -{ - return mSubStringMatchOffset; -} -// has user modified default filter params? -BOOL LLInventoryFilter::isNotDefault() +BOOL LLFolderView::handleMouseDown( S32 x, S32 y, MASK mask ) { - return mFilterOps.mFilterTypes != mDefaultFilterOps.mFilterTypes - || mFilterSubString.size() - || mFilterOps.mPermissions != mDefaultFilterOps.mPermissions - || mFilterOps.mMinDate != mDefaultFilterOps.mMinDate - || mFilterOps.mMaxDate != mDefaultFilterOps.mMaxDate - || mFilterOps.mHoursAgo != mDefaultFilterOps.mHoursAgo; -} + mKeyboardSelection = FALSE; + mSearchString.clear(); -BOOL LLInventoryFilter::isActive() -{ - return mFilterOps.mFilterTypes != 0xffffffff - || mFilterSubString.size() - || mFilterOps.mPermissions != PERM_NONE - || mFilterOps.mMinDate != time_min() - || mFilterOps.mMaxDate != time_max() - || mFilterOps.mHoursAgo != 0; -} + mParentPanel->setFocus(TRUE); -BOOL LLInventoryFilter::isModified() -{ - return mModified; + return LLView::handleMouseDown( x, y, mask ); } -BOOL LLInventoryFilter::isModifiedAndClear() +BOOL LLFolderView::search(LLFolderViewItem* first_item, const std::string &search_string, BOOL backward) { - BOOL ret = mModified; - mModified = FALSE; - return ret; -} + // get first selected item + LLFolderViewItem* search_item = first_item; -void LLInventoryFilter::setFilterTypes(U32 types) -{ - if (mFilterOps.mFilterTypes != types) - { - // keep current items only if no type bits getting turned off - BOOL fewer_bits_set = (mFilterOps.mFilterTypes & ~types); - BOOL more_bits_set = (~mFilterOps.mFilterTypes & types); - - mFilterOps.mFilterTypes = types; - if (more_bits_set && fewer_bits_set) - { - // neither less or more restrive, both simultaneously - // so we need to filter from scratch - setModified(FILTER_RESTART); - } - else if (more_bits_set) - { - // target is only one of all requested types so more type bits == less restrictive - setModified(FILTER_LESS_RESTRICTIVE); - } - else if (fewer_bits_set) - { - setModified(FILTER_MORE_RESTRICTIVE); - } + // make sure search string is upper case + std::string upper_case_string = search_string; + LLStringUtil::toUpper(upper_case_string); + // if nothing selected, select first item in folder + if (!search_item) + { + // start from first item + search_item = getNextFromChild(NULL); } -} -void LLInventoryFilter::setFilterSubString(const std::string& string) -{ - if (mFilterSubString != string) + // search over all open nodes for first substring match (with wrapping) + BOOL found = FALSE; + LLFolderViewItem* original_search_item = search_item; + do { - // hitting BACKSPACE, for example - BOOL less_restrictive = mFilterSubString.size() >= string.size() && !mFilterSubString.substr(0, string.size()).compare(string); - // appending new characters - BOOL more_restrictive = mFilterSubString.size() < string.size() && !string.substr(0, mFilterSubString.size()).compare(mFilterSubString); - mFilterSubString = string; - LLStringUtil::toUpper(mFilterSubString); - LLStringUtil::trimHead(mFilterSubString); - - if (less_restrictive) + // wrap at end + if (!search_item) { - setModified(FILTER_LESS_RESTRICTIVE); + if (backward) + { + search_item = getPreviousFromChild(NULL); + } + else + { + search_item = getNextFromChild(NULL); + } + if (!search_item || search_item == original_search_item) + { + break; + } + } + + const std::string current_item_label(search_item->getSearchableLabel()); + S32 search_string_length = llmin(upper_case_string.size(), current_item_label.size()); + if (!current_item_label.compare(0, search_string_length, upper_case_string)) + { + found = TRUE; + break; } - else if (more_restrictive) + if (backward) { - setModified(FILTER_MORE_RESTRICTIVE); + search_item = search_item->getPreviousOpenNode(); } else { - setModified(FILTER_RESTART); + search_item = search_item->getNextOpenNode(); } + + } while(search_item != original_search_item); + + + if (found) + { + setSelection(search_item, FALSE, TRUE); + scrollToShowSelection(); } + + return found; +} + +BOOL LLFolderView::handleDoubleClick( S32 x, S32 y, MASK mask ) +{ + // skip LLFolderViewFolder::handleDoubleClick() + return LLView::handleDoubleClick( x, y, mask ); } -void LLInventoryFilter::setFilterPermissions(PermissionMask perms) +BOOL LLFolderView::handleRightMouseDown( S32 x, S32 y, MASK mask ) { - if (mFilterOps.mPermissions != perms) + // all user operations move keyboard focus to inventory + // this way, we know when to stop auto-updating a search + mParentPanel->setFocus(TRUE); + + BOOL handled = childrenHandleRightMouseDown(x, y, mask) != NULL; + S32 count = mSelectedItems.size(); + LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get(); + if(handled && (count > 0) && menu) { - // keep current items only if no perm bits getting turned off - BOOL fewer_bits_set = (mFilterOps.mPermissions & ~perms); - BOOL more_bits_set = (~mFilterOps.mPermissions & perms); - mFilterOps.mPermissions = perms; + if (mCallbackRegistrar) + mCallbackRegistrar->pushScope(); + //menu->empty(); + const LLView::child_list_t *list = menu->getChildList(); - if (more_bits_set && fewer_bits_set) + LLView::child_list_t::const_iterator menu_itor; + for (menu_itor = list->begin(); menu_itor != list->end(); ++menu_itor) { - setModified(FILTER_RESTART); + (*menu_itor)->setVisible(TRUE); + (*menu_itor)->setEnabled(TRUE); } - else if (more_bits_set) + + // Successively filter out invalid options + selected_items_t::iterator item_itor; + U32 flags = FIRST_SELECTED_ITEM; + for (item_itor = mSelectedItems.begin(); item_itor != mSelectedItems.end(); ++item_itor) { - // target must have all requested permission bits, so more bits == more restrictive - setModified(FILTER_MORE_RESTRICTIVE); + (*item_itor)->buildContextMenu(*menu, flags); + flags = 0x0; } - else if (fewer_bits_set) + + menu->updateParent(LLMenuGL::sMenuContainer); + LLMenuGL::showPopup(this, menu, x, y); + if (mCallbackRegistrar) + mCallbackRegistrar->popScope(); + } + else + { + if(menu && menu->getVisible()) { - setModified(FILTER_LESS_RESTRICTIVE); + menu->setVisible(FALSE); } + setSelection(NULL, FALSE, TRUE); } + return handled; } -void LLInventoryFilter::setDateRange(time_t min_date, time_t max_date) +BOOL LLFolderView::handleHover( S32 x, S32 y, MASK mask ) { - mFilterOps.mHoursAgo = 0; - if (mFilterOps.mMinDate != min_date) - { - mFilterOps.mMinDate = min_date; - setModified(); - } - if (mFilterOps.mMaxDate != llmax(mFilterOps.mMinDate, max_date)) + return LLView::handleHover( x, y, mask ); +} + +BOOL LLFolderView::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg) +{ + mDragAndDropThisFrame = TRUE; + BOOL handled = LLView::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, + accept, tooltip_msg); + + if (handled) { - mFilterOps.mMaxDate = llmax(mFilterOps.mMinDate, max_date); - setModified(); + lldebugst(LLERR_USER_INPUT) << "dragAndDrop handled by LLFolderView" << llendl; } + + return handled; } -void LLInventoryFilter::setDateRangeLastLogoff(BOOL sl) +BOOL LLFolderView::handleScrollWheel(S32 x, S32 y, S32 clicks) { - if (sl && !isSinceLogoff()) + if (mScrollContainer) { - setDateRange(mLastLogoff, time_max()); - setModified(); + return mScrollContainer->handleScrollWheel(x, y, clicks); } - if (!sl && isSinceLogoff()) + return FALSE; +} + +void LLFolderView::deleteAllChildren() +{ + if(mRenamer == gFocusMgr.getTopCtrl()) { - setDateRange(0, time_max()); - setModified(); + gFocusMgr.setTopCtrl(NULL); } + LLView::deleteViewByHandle(mPopupMenuHandle); + mPopupMenuHandle = LLHandle<LLView>(); + mRenamer = NULL; + mRenameItem = NULL; + clearSelection(); + LLView::deleteAllChildren(); } -BOOL LLInventoryFilter::isSinceLogoff() +void LLFolderView::scrollToShowSelection() { - return (mFilterOps.mMinDate == (time_t)mLastLogoff) && - (mFilterOps.mMaxDate == time_max()); + if (mSelectedItems.size()) + { + mNeedsScroll = TRUE; + } } -void LLInventoryFilter::setHoursAgo(U32 hours) +// If the parent is scroll containter, scroll it to make the selection +// is maximally visible. +void LLFolderView::scrollToShowItem(LLFolderViewItem* item) { - if (mFilterOps.mHoursAgo != hours) + // don't scroll to items when mouse is being used to scroll/drag and drop + if (gFocusMgr.childHasMouseCapture(mScrollContainer)) { - // *NOTE: need to cache last filter time, in case filter goes stale - BOOL less_restrictive = (mFilterOps.mMinDate == time_min() && mFilterOps.mMaxDate == time_max() && hours > mFilterOps.mHoursAgo); - BOOL more_restrictive = (mFilterOps.mMinDate == time_min() && mFilterOps.mMaxDate == time_max() && hours <= mFilterOps.mHoursAgo); - mFilterOps.mHoursAgo = hours; - mFilterOps.mMinDate = time_min(); - mFilterOps.mMaxDate = time_max(); - if (less_restrictive) - { - setModified(FILTER_LESS_RESTRICTIVE); - } - else if (more_restrictive) - { - setModified(FILTER_MORE_RESTRICTIVE); - } - else + mNeedsScroll = FALSE; + return; + } + if(item && mScrollContainer) + { + LLRect local_rect = item->getRect(); + LLRect item_scrolled_rect; // item position relative to display area of scroller + + S32 icon_height = mIcon.isNull() ? 0 : mIcon->getHeight(); + S32 label_height = llround(sFont->getLineHeight()); + // when navigating with keyboard, only move top of folders on screen, otherwise show whole folder + S32 max_height_to_show = gFocusMgr.childHasKeyboardFocus(this) ? (llmax( icon_height, label_height ) + ICON_PAD) : local_rect.getHeight(); + item->localPointToOtherView(item->getIndentation(), llmax(0, local_rect.getHeight() - max_height_to_show), &item_scrolled_rect.mLeft, &item_scrolled_rect.mBottom, mScrollContainer); + item->localPointToOtherView(local_rect.getWidth(), local_rect.getHeight(), &item_scrolled_rect.mRight, &item_scrolled_rect.mTop, mScrollContainer); + + item_scrolled_rect.mRight = llmin(item_scrolled_rect.mLeft + MIN_ITEM_WIDTH_VISIBLE, item_scrolled_rect.mRight); + LLCoordGL scroll_offset(-mScrollContainer->getBorderWidth() - item_scrolled_rect.mLeft, + mScrollContainer->getRect().getHeight() - item_scrolled_rect.mTop - 1); + + S32 max_scroll_offset = getVisibleRect().getHeight() - item_scrolled_rect.getHeight(); + if (item != mLastScrollItem || // if we're scrolling to focus on a new item + // or the item has just appeared on screen and it wasn't onscreen before + (scroll_offset.mY > 0 && scroll_offset.mY < max_scroll_offset && + (mLastScrollOffset.mY < 0 || mLastScrollOffset.mY > max_scroll_offset))) { - setModified(FILTER_RESTART); + // we now have a position on screen that we want to keep stable + // offset of selection relative to top of visible area + mLastScrollOffset = scroll_offset; + mLastScrollItem = item; } + + mScrollContainer->scrollToShowRect( item_scrolled_rect, mLastScrollOffset ); + + // after scrolling, store new offset + // in case we don't have room to maintain the original position + LLCoordGL new_item_left_top; + item->localPointToOtherView(item->getIndentation(), item->getRect().getHeight(), &new_item_left_top.mX, &new_item_left_top.mY, mScrollContainer); + mLastScrollOffset.set(-mScrollContainer->getBorderWidth() - new_item_left_top.mX, mScrollContainer->getRect().getHeight() - new_item_left_top.mY - 1); } } -void LLInventoryFilter::setShowFolderState(EFolderShow state) + +LLRect LLFolderView::getVisibleRect() +{ + S32 visible_height = mScrollContainer->getRect().getHeight(); + S32 visible_width = mScrollContainer->getRect().getWidth(); + LLRect visible_rect; + visible_rect.setLeftTopAndSize(-getRect().mLeft, visible_height - getRect().mBottom, visible_width, visible_height); + return visible_rect; +} + +BOOL LLFolderView::getShowSelectionContext() { - if (mFilterOps.mShowFolderState != state) + if (mShowSelectionContext) { - mFilterOps.mShowFolderState = state; - if (state == SHOW_NON_EMPTY_FOLDERS) - { - // showing fewer folders than before - setModified(FILTER_MORE_RESTRICTIVE); - } - else if (state == SHOW_ALL_FOLDERS) - { - // showing same folders as before and then some - setModified(FILTER_LESS_RESTRICTIVE); - } - else - { - setModified(); - } + return TRUE; + } + LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get(); + if (menu && menu->getVisible()) + { + return TRUE; } + return FALSE; } -void LLInventoryFilter::setSortOrder(U32 order) +void LLFolderView::setShowSingleSelection(BOOL show) { - if (mOrder != order) + if (show != mShowSingleSelection) { - mOrder = order; - setModified(); + mMultiSelectionFadeTimer.reset(); + mShowSingleSelection = show; } } -void LLInventoryFilter::markDefault() +void LLFolderView::addItemID(const LLUUID& id, LLFolderViewItem* itemp) { - mDefaultFilterOps = mFilterOps; + mItemMap[id] = itemp; } -void LLInventoryFilter::resetDefault() +void LLFolderView::removeItemID(const LLUUID& id) { - mFilterOps = mDefaultFilterOps; - setModified(); + mItemMap.erase(id); } -void LLInventoryFilter::setModified(EFilterBehavior behavior) +LLFolderViewItem* LLFolderView::getItemByID(const LLUUID& id) { - mModified = TRUE; - mNeedTextRebuild = TRUE; - mFilterGeneration = mNextFilterGeneration++; - - if (mFilterBehavior == FILTER_NONE) - { - mFilterBehavior = behavior; - } - else if (mFilterBehavior != behavior) + if (id.isNull()) { - // trying to do both less restrictive and more restrictive filter - // basically means restart from scratch - mFilterBehavior = FILTER_RESTART; + return this; } - if (isNotDefault()) - { - // if not keeping current filter results, update last valid as well - switch(mFilterBehavior) - { - case FILTER_RESTART: - mMustPassGeneration = mFilterGeneration; - mMinRequiredGeneration = mFilterGeneration; - break; - case FILTER_LESS_RESTRICTIVE: - mMustPassGeneration = mFilterGeneration; - break; - case FILTER_MORE_RESTRICTIVE: - mMinRequiredGeneration = mFilterGeneration; - // must have passed either current filter generation (meaningless, as it hasn't been run yet) - // or some older generation, so keep the value - mMustPassGeneration = llmin(mMustPassGeneration, mFilterGeneration); - break; - default: - llerrs << "Bad filter behavior specified" << llendl; - } - } - else + std::map<LLUUID, LLFolderViewItem*>::iterator map_it; + map_it = mItemMap.find(id); + if (map_it != mItemMap.end()) { - // shortcut disabled filters to show everything immediately - mMinRequiredGeneration = 0; - mMustPassGeneration = S32_MAX; + return map_it->second; } -} -BOOL LLInventoryFilter::isFilterWith(LLInventoryType::EType t) -{ - return mFilterOps.mFilterTypes & (0x01 << t); + return NULL; } -std::string LLInventoryFilter::getFilterText() +bool LLFolderView::doToSelected(LLInventoryModel* model, const LLSD& userdata) { - if (!mNeedTextRebuild) + std::string action = userdata.asString(); + + if ("rename" == action) { - return mFilterText; + startRenamingSelectedItem(); + return true; } - - mNeedTextRebuild = FALSE; - std::string filtered_types; - std::string not_filtered_types; - BOOL filtered_by_type = FALSE; - BOOL filtered_by_all_types = TRUE; - S32 num_filter_types = 0; - mFilterText.clear(); - - if (isFilterWith(LLInventoryType::IT_ANIMATION)) + if ("delete" == action) { - //filtered_types += " Animations,"; - filtered_types += LLTrans::getString("Animations"); - filtered_by_type = TRUE; - num_filter_types++; + removeSelectedItems(); + return true; } - else - { - //not_filtered_types += " Animations,"; - not_filtered_types += LLTrans::getString("Animations"); - filtered_by_all_types = FALSE; + if ("copy" == action) + { + LLInventoryClipboard::instance().reset(); } - if (isFilterWith(LLInventoryType::IT_CALLINGCARD)) - { - //filtered_types += " Calling Cards,"; - filtered_types += LLTrans::getString("Calling Cards"); - filtered_by_type = TRUE; - num_filter_types++; - } - else - { - //not_filtered_types += " Calling Cards,"; - not_filtered_types += LLTrans::getString("Calling Cards"); - filtered_by_all_types = FALSE; - } + std::set<LLUUID> selected_items; + getSelectionList(selected_items); - if (isFilterWith(LLInventoryType::IT_WEARABLE)) - { - //filtered_types += " Clothing,"; - filtered_types += LLTrans::getString("Clothing"); - filtered_by_type = TRUE; - num_filter_types++; - } - else - { - //not_filtered_types += " Clothing,"; - not_filtered_types += LLTrans::getString("Clothing"); - filtered_by_all_types = FALSE; - } + LLMultiPreview* multi_previewp = NULL; + LLMultiProperties* multi_propertiesp = NULL; - if (isFilterWith(LLInventoryType::IT_GESTURE)) - { - //filtered_types += " Gestures,"; - filtered_types += LLTrans::getString("Gestures"); - filtered_by_type = TRUE; - num_filter_types++; - } - else + if (("task_open" == action || "open" == action) && selected_items.size() > 1) { - //not_filtered_types += " Gestures,"; - not_filtered_types += LLTrans::getString("Gestures"); - filtered_by_all_types = FALSE; - } + multi_previewp = new LLMultiPreview(); + gFloaterView->addChild(multi_previewp); - if (isFilterWith(LLInventoryType::IT_LANDMARK)) - { - //filtered_types += " Landmarks,"; - filtered_types += LLTrans::getString("Landmarks"); - filtered_by_type = TRUE; - num_filter_types++; + LLFloater::setFloaterHost(multi_previewp); + } - else + else if (("task_properties" == action || "properties" == action) && selected_items.size() > 1) { - //not_filtered_types += " Landmarks,"; - not_filtered_types += LLTrans::getString("Landmarks"); - filtered_by_all_types = FALSE; - } + multi_propertiesp = new LLMultiProperties(); + gFloaterView->addChild(multi_propertiesp); - if (isFilterWith(LLInventoryType::IT_NOTECARD)) - { - //filtered_types += " Notecards,"; - filtered_types += LLTrans::getString("Notecards"); - filtered_by_type = TRUE; - num_filter_types++; - } - else - { - //not_filtered_types += " Notecards,"; - not_filtered_types += LLTrans::getString("Notecards"); - filtered_by_all_types = FALSE; + LLFloater::setFloaterHost(multi_propertiesp); } - - if (isFilterWith(LLInventoryType::IT_OBJECT) && isFilterWith(LLInventoryType::IT_ATTACHMENT)) + + std::set<LLUUID>::iterator set_iter; + + for (set_iter = selected_items.begin(); set_iter != selected_items.end(); ++set_iter) { - //filtered_types += " Objects,"; - filtered_types += LLTrans::getString("Objects"); - filtered_by_type = TRUE; - num_filter_types++; + LLFolderViewItem* folder_item = getItemByID(*set_iter); + if(!folder_item) continue; + LLInvFVBridge* bridge = (LLInvFVBridge*)folder_item->getListener(); + if(!bridge) continue; + + bridge->performAction(this, model, action); } - else + + LLFloater::setFloaterHost(NULL); + if (multi_previewp) { - //not_filtered_types += " Objects,"; - not_filtered_types += LLTrans::getString("Objects"); - filtered_by_all_types = FALSE; + multi_previewp->openFloater(LLSD()); } - - if (isFilterWith(LLInventoryType::IT_LSL)) + else if (multi_propertiesp) { - //filtered_types += " Scripts,"; - filtered_types += LLTrans::getString("Scripts"); - filtered_by_type = TRUE; - num_filter_types++; + multi_propertiesp->openFloater(LLSD()); } - else + + return true; +} + +// Main idle routine +void LLFolderView::doIdle() +{ + LLFastTimer t2(LLFastTimer::FTM_INVENTORY); + + BOOL debug_filters = gSavedSettings.getBOOL("DebugInventoryFilters"); + if (debug_filters != getDebugFilters()) { - //not_filtered_types += " Scripts,"; - not_filtered_types += LLTrans::getString("Scripts"); - filtered_by_all_types = FALSE; + mDebugFilters = debug_filters; + arrangeAll(); } + + mFilter->clearModified(); + BOOL filter_modified_and_active = mCompletedFilterGeneration < mFilter->getCurrentGeneration() && + mFilter->isNotDefault(); + mNeedsAutoSelect = filter_modified_and_active && + !(gFocusMgr.childHasKeyboardFocus(this) || gFocusMgr.getMouseCapture()); - if (isFilterWith(LLInventoryType::IT_SOUND)) + // filter to determine visiblity before arranging + filterFromRoot(); + + // automatically show matching items, and select first one + // do this every frame until user puts keyboard focus into the inventory window + // signaling the end of the automatic update + // only do this when mNeedsFilter is set, meaning filtered items have + // potentially changed + if (mNeedsAutoSelect) { - //filtered_types += " Sounds,"; - filtered_types += LLTrans::getString("Sounds"); - filtered_by_type = TRUE; - num_filter_types++; + LLFastTimer t3(LLFastTimer::FTM_AUTO_SELECT); + // select new item only if a filtered item not currently selected + LLFolderViewItem* selected_itemp = mSelectedItems.empty() ? NULL : mSelectedItems.back(); + if ((!selected_itemp || !selected_itemp->getFiltered()) && !mAutoSelectOverride) + { + // select first filtered item + LLSelectFirstFilteredItem filter; + applyFunctorRecursively(filter); + } + scrollToShowSelection(); } - else + + BOOL is_visible = isInVisibleChain(); + + if ( is_visible ) { - //not_filtered_types += " Sounds,"; - not_filtered_types += LLTrans::getString("Sounds"); - filtered_by_all_types = FALSE; + sanitizeSelection(); + if( needsArrange() ) + { + arrangeFromRoot(); + } } - if (isFilterWith(LLInventoryType::IT_TEXTURE)) + if (mSelectedItems.size() && mNeedsScroll) { - //filtered_types += " Textures,"; - filtered_types += LLTrans::getString("Textures"); - filtered_by_type = TRUE; - num_filter_types++; + scrollToShowItem(mSelectedItems.back()); + // continue scrolling until animated layout change is done + if (getCompletedFilterGeneration() >= mFilter->getMinRequiredGeneration() && + (!needsArrange() || !is_visible)) + { + mNeedsScroll = FALSE; + } } - else + + if (mSignalSelectCallback) { - //not_filtered_types += " Textures,"; - not_filtered_types += LLTrans::getString("Textures"); - filtered_by_all_types = FALSE; + //RN: we use keyboard focus as a proxy for user-explicit actions + BOOL take_keyboard_focus = (mSignalSelectCallback == SIGNAL_KEYBOARD_FOCUS); + mSelectSignal(mSelectedItems, take_keyboard_focus); } + mSignalSelectCallback = FALSE; +} - if (isFilterWith(LLInventoryType::IT_SNAPSHOT)) - { - //filtered_types += " Snapshots,"; - filtered_types += LLTrans::getString("Snapshots"); - filtered_by_type = TRUE; - num_filter_types++; + +//static +void LLFolderView::idle(void* user_data) +{ + LLFolderView* self = (LLFolderView*)user_data; + if ( self ) + { // Do the real idle + self->doIdle(); } - else +} + +void LLFolderView::dumpSelectionInformation() +{ + llinfos << "LLFolderView::dumpSelectionInformation()" << llendl; + llinfos << "****************************************" << llendl; + selected_items_t::iterator item_it; + for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) { - //not_filtered_types += " Snapshots,"; - not_filtered_types += LLTrans::getString("Snapshots"); - filtered_by_all_types = FALSE; + llinfos << " " << (*item_it)->getName() << llendl; } + llinfos << "****************************************" << llendl; +} - if (!gInventory.backgroundFetchActive() && filtered_by_type && !filtered_by_all_types) +void LLFolderView::updateRenamerPosition() +{ + if(mRenameItem) { - mFilterText += " - "; - if (num_filter_types < 5) - { - mFilterText += filtered_types; - } - else + S32 x = ARROW_SIZE + TEXT_PAD + ICON_WIDTH + ICON_PAD - 1 + mRenameItem->getIndentation(); + S32 y = llfloor(mRenameItem->getRect().getHeight()-sFont->getLineHeight()-2); + mRenameItem->localPointToScreen( x, y, &x, &y ); + screenPointToLocal( x, y, &x, &y ); + mRenamer->setOrigin( x, y ); + + S32 scroller_height = 0; + S32 scroller_width = gViewerWindow->getWindowWidth(); + BOOL dummy_bool; + if (mScrollContainer) { - //mFilterText += "No "; - mFilterText += LLTrans::getString("No Filters"); - mFilterText += not_filtered_types; + mScrollContainer->calcVisibleSize( &scroller_width, &scroller_height, &dummy_bool, &dummy_bool); } - // remove the ',' at the end - mFilterText.erase(mFilterText.size() - 1, 1); + + S32 width = llmax(llmin(mRenameItem->getRect().getWidth() - x, scroller_width - x - getRect().mLeft), MINIMUM_RENAMER_WIDTH); + S32 height = llfloor(sFont->getLineHeight() + RENAME_HEIGHT_PAD); + mRenamer->reshape( width, height, TRUE ); } +} + + +///---------------------------------------------------------------------------- +/// Local function definitions +///---------------------------------------------------------------------------- - if (isSinceLogoff()) +//static +void LLFolderView::onRenamerLost( LLFocusableElement* renamer, void* user_data) +{ + LLUICtrl* uictrl = dynamic_cast<LLUICtrl*>(renamer); + if (uictrl) { - //mFilterText += " - Since Logoff"; - mFilterText += LLTrans::getString("Since Logoff"); + uictrl->setVisible(FALSE); } - return mFilterText; } -void LLInventoryFilter::toLLSD(LLSD& data) +LLInventoryFilter* LLFolderView::getFilter() { - data["filter_types"] = (LLSD::Integer)getFilterTypes(); - data["min_date"] = (LLSD::Integer)getMinDate(); - data["max_date"] = (LLSD::Integer)getMaxDate(); - data["hours_ago"] = (LLSD::Integer)getHoursAgo(); - data["show_folder_state"] = (LLSD::Integer)getShowFolderState(); - data["permissions"] = (LLSD::Integer)getFilterPermissions(); - data["substring"] = (LLSD::String)getFilterSubString(); - data["sort_order"] = (LLSD::Integer)getSortOrder(); - data["since_logoff"] = (LLSD::Boolean)isSinceLogoff(); + return mFilter; } -void LLInventoryFilter::fromLLSD(LLSD& data) +void LLFolderView::setFilterPermMask( PermissionMask filter_perm_mask ) { - if(data.has("filter_types")) - { - setFilterTypes((U32)data["filter_types"].asInteger()); - } + mFilter->setFilterPermissions(filter_perm_mask); +} - if(data.has("min_date") && data.has("max_date")) - { - setDateRange(data["min_date"].asInteger(), data["max_date"].asInteger()); - } +U32 LLFolderView::getFilterTypes() const +{ + return mFilter->getFilterTypes(); +} - if(data.has("hours_ago")) - { - setHoursAgo((U32)data["hours_ago"].asInteger()); - } +PermissionMask LLFolderView::getFilterPermissions() const +{ + return mFilter->getFilterPermissions(); +} + +// JAMESDEBUG +//LLInventoryFilter::EFolderShow LLFolderView::getShowFolderState() +//{ +// return mFilter->getShowFolderState(); +//} + +BOOL LLFolderView::isFilterModified() +{ + return mFilter->isNotDefault(); +} - if(data.has("show_folder_state")) +BOOL LLFolderView::getAllowMultiSelect() +{ + return mAllowMultiSelect; +} + +void delete_selected_item(void* user_data) +{ + if(user_data) { - setShowFolderState((EFolderShow)data["show_folder_state"].asInteger()); + LLFolderView* fv = reinterpret_cast<LLFolderView*>(user_data); + fv->removeSelectedItems(); } +} - if(data.has("permissions")) +void copy_selected_item(void* user_data) +{ + if(user_data) { - setFilterPermissions((PermissionMask)data["permissions"].asInteger()); + LLFolderView* fv = reinterpret_cast<LLFolderView*>(user_data); + fv->copy(); } +} - if(data.has("substring")) +void paste_items(void* user_data) +{ + if(user_data) { - setFilterSubString(std::string(data["substring"].asString())); + LLFolderView* fv = reinterpret_cast<LLFolderView*>(user_data); + fv->paste(); } +} - if(data.has("sort_order")) +void open_selected_items(void* user_data) +{ + if(user_data) { - setSortOrder((U32)data["sort_order"].asInteger()); + LLFolderView* fv = reinterpret_cast<LLFolderView*>(user_data); + fv->openSelectedItems(); } +} - if(data.has("since_logoff")) +void properties_selected_items(void* user_data) +{ + if(user_data) { - setDateRangeLastLogoff((bool)data["since_logoff"].asBoolean()); + LLFolderView* fv = reinterpret_cast<LLFolderView*>(user_data); + fv->propertiesSelectedItems(); } } diff --git a/indra/newview/llfolderview.h b/indra/newview/llfolderview.h index 3386a7fb0e03aa8b048c76f88337ae6467099bb0..e8f0c4130e6aded1b1100ffe7de2e39e0b785871 100644 --- a/indra/newview/llfolderview.h +++ b/indra/newview/llfolderview.h @@ -41,6 +41,7 @@ #ifndef LL_LLFOLDERVIEW_H #define LL_LLFOLDERVIEW_H +// JAMESDEBUG - trim this list #include <vector> #include <map> #include <deque> @@ -57,96 +58,8 @@ #include "llviewerimage.h" #include "lldepthstack.h" #include "lltooldraganddrop.h" - -class LLMenuGL; - -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// Class LLFolderViewEventListener -// -// This is an abstract base class that users of the folderview classes -// would use to catch the useful events emitted from the folder -// views. -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - -class LLFolderViewItem; -class LLFolderView; -class LLInventoryModel; -class LLScrollContainer; - -class LLFolderViewEventListener -{ -public: - virtual ~LLFolderViewEventListener( void ) {} - virtual const std::string& getName() const = 0; - virtual const std::string& getDisplayName() const = 0; - virtual const LLUUID& getUUID() const = 0; - virtual time_t getCreationDate() const = 0; // UTC seconds - virtual PermissionMask getPermissionMask() const = 0; - virtual LLAssetType::EType getPreferredType() const {return LLAssetType::AT_NONE;}; - virtual LLUIImagePtr getIcon() const = 0; - virtual LLFontGL::StyleFlags getLabelStyle() const = 0; - virtual std::string getLabelSuffix() const = 0; - virtual void openItem( void ) = 0; - virtual void previewItem( void ) = 0; - virtual void selectItem(void) = 0; - virtual void showProperties(void) = 0; - virtual BOOL isItemRenameable() const = 0; - virtual BOOL renameItem(const std::string& new_name) = 0; - virtual BOOL isItemMovable( void ) = 0; // Can be moved to another folder - virtual BOOL isItemRemovable( void ) = 0; // Can be destroyed - virtual BOOL removeItem() = 0; - virtual void removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batch) = 0; - virtual void move( LLFolderViewEventListener* parent_listener ) = 0; - virtual BOOL isItemCopyable() const = 0; - virtual BOOL copyToClipboard() const = 0; - virtual void cutToClipboard() = 0; - virtual BOOL isClipboardPasteable() const = 0; - virtual void pasteFromClipboard() = 0; - virtual void pasteLinkFromClipboard() = 0; - virtual void buildContextMenu(LLMenuGL& menu, U32 flags) = 0; - virtual BOOL isUpToDate() const = 0; - virtual BOOL hasChildren() const = 0; - virtual LLInventoryType::EType getInventoryType() const = 0; - virtual void performAction(LLFolderView* folder, LLInventoryModel* model, std::string action) {} - - // This method should be called when a drag begins. returns TRUE - // if the drag can begin, otherwise FALSE. - virtual BOOL startDrag(EDragAndDropType* type, LLUUID* id) const = 0; - - // This method will be called to determine if a drop can be - // performed, and will set drop to TRUE if a drop is - // requested. Returns TRUE if a drop is possible/happened, - // otherwise FALSE. - virtual BOOL dragOrDrop(MASK mask, BOOL drop, - EDragAndDropType cargo_type, - void* cargo_data) = 0; - - // This method is called when the object being referenced by the - // bridge is actually dropped. This allows for cleanup of the old - // view, reference counting, etc. -// virtual void dropped() = 0; - - // this method accesses the parent and arranges and sets it as - // specified. - void arrangeAndSet(LLFolderViewItem* focus, BOOL set_selection, - BOOL take_keyboard_focus = TRUE); -}; - - -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// Class LLFolderViewListenerFunctor -// -// This simple abstract base class can be used to applied to all -// listeners in a hierarchy. -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -class LLFolderViewListenerFunctor -{ -public: - virtual ~LLFolderViewListenerFunctor() {} - virtual void operator()(LLFolderViewEventListener* listener) = 0; -}; +// JAMESDEBUG - move this up +#include "llfolderviewitem.h" // because LLFolderView is-a LLFolderViewFolder //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Class LLFolderViewFunctor @@ -168,571 +81,6 @@ public: virtual void doItem(LLFolderViewItem* item) = 0; }; -class LLInventoryFilter -{ -public: - typedef enum e_folder_show - { - SHOW_ALL_FOLDERS, - SHOW_NON_EMPTY_FOLDERS, - SHOW_NO_FOLDERS - } EFolderShow; - - typedef enum e_filter_behavior - { - FILTER_NONE, // nothing to do, already filtered - FILTER_RESTART, // restart filtering from scratch - FILTER_LESS_RESTRICTIVE, // existing filtered items will certainly pass this filter - FILTER_MORE_RESTRICTIVE // if you didn't pass the previous filter, you definitely won't pass this one - } EFilterBehavior; - - static const U32 SO_DATE = 1; - static const U32 SO_FOLDERS_BY_NAME = 2; - static const U32 SO_SYSTEM_FOLDERS_TO_TOP = 4; - - LLInventoryFilter(const std::string& name); - virtual ~LLInventoryFilter(); - - void setFilterTypes(U32 types); - U32 getFilterTypes() const { return mFilterOps.mFilterTypes; } - - void setFilterSubString(const std::string& string); - const std::string getFilterSubString(BOOL trim = FALSE); - - void setFilterPermissions(PermissionMask perms); - PermissionMask getFilterPermissions() const { return mFilterOps.mPermissions; } - - void setDateRange(time_t min_date, time_t max_date); - void setDateRangeLastLogoff(BOOL sl); - time_t getMinDate() const { return mFilterOps.mMinDate; } - time_t getMaxDate() const { return mFilterOps.mMaxDate; } - - void setHoursAgo(U32 hours); - U32 getHoursAgo() const { return mFilterOps.mHoursAgo; } - - void setShowFolderState( EFolderShow state); - EFolderShow getShowFolderState() { return mFilterOps.mShowFolderState; } - - void setSortOrder(U32 order); - U32 getSortOrder() { return mOrder; } - - BOOL check(LLFolderViewItem* item); - std::string::size_type getStringMatchOffset() const; - BOOL isActive(); - BOOL isNotDefault(); - BOOL isModified(); - BOOL isModifiedAndClear(); - BOOL isSinceLogoff(); - void clearModified() { mModified = FALSE; mFilterBehavior = FILTER_NONE; } - const std::string getName() const { return mName; } - std::string getFilterText(); - - void setFilterCount(S32 count) { mFilterCount = count; } - S32 getFilterCount() { return mFilterCount; } - void decrementFilterCount() { mFilterCount--; } - - void markDefault(); - void resetDefault(); - - BOOL isFilterWith(LLInventoryType::EType t); - - S32 getCurrentGeneration() const { return mFilterGeneration; } - S32 getMinRequiredGeneration() const { return mMinRequiredGeneration; } - S32 getMustPassGeneration() const { return mMustPassGeneration; } - - //RN: this is public to allow system to externally force a global refilter - void setModified(EFilterBehavior behavior = FILTER_RESTART); - - void toLLSD(LLSD& data); - void fromLLSD(LLSD& data); - -protected: - struct filter_ops - { - U32 mFilterTypes; - time_t mMinDate; - time_t mMaxDate; - U32 mHoursAgo; - EFolderShow mShowFolderState; - PermissionMask mPermissions; - }; - filter_ops mFilterOps; - filter_ops mDefaultFilterOps; - std::string::size_type mSubStringMatchOffset; - std::string mFilterSubString; - U32 mOrder; - const std::string mName; - S32 mFilterGeneration; - S32 mMustPassGeneration; - S32 mMinRequiredGeneration; - S32 mFilterCount; - S32 mNextFilterGeneration; - EFilterBehavior mFilterBehavior; - -private: - U32 mLastLogoff; - BOOL mModified; - BOOL mNeedTextRebuild; - std::string mFilterText; -}; - -// These are grouping of inventory types. -// Order matters when sorting system folders to the top. -enum EInventorySortGroup -{ - SG_SYSTEM_FOLDER, - SG_TRASH_FOLDER, - SG_NORMAL_FOLDER, - SG_ITEM -}; - -class LLInventorySort -{ -public: - LLInventorySort() - : mSortOrder(0), - mByDate(false), - mSystemToTop(false), - mFoldersByName(false) { } - - // Returns true if order has changed - bool updateSort(U32 order); - U32 getSort() { return mSortOrder; } - - bool operator()(const LLFolderViewItem* const& a, const LLFolderViewItem* const& b); -private: - U32 mSortOrder; - bool mByDate; - bool mSystemToTop; - bool mFoldersByName; -}; - -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// Class LLFolderViewItem -// -// An instance of this class represents a single item in a folder view -// such as an inventory item or a file. -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -class LLFontGL; -class LLFolderViewFolder; -class LLFolderView; - -class LLFolderViewItem : public LLView -{ -public: - static void initClass(); - static void cleanupClass(); - struct Params : public LLInitParam::Block<Params, LLUICtrl::Params> - { - Optional<LLUIImage*> icon; - Optional<LLFolderView*> root; - Optional<LLFolderViewEventListener*> listener; - - Optional<LLUIImage*> folder_arrow_image; - Optional<LLUIImage*> selection_image; - - Optional<S32> creation_date; //UTC seconds - Params() - : folder_arrow_image("", LLUI::getUIImage("folder_arrow.tga")), - selection_image("", LLUI::getUIImage("rounded_square.tga")) - { - mouse_opaque(true); - follows.flags(FOLLOWS_LEFT|FOLLOWS_TOP|FOLLOWS_RIGHT); - tab_stop(false); - } - }; - -protected: - friend class LLUICtrlFactory; - friend class LLFolderViewEventListener; - - LLFolderViewItem(Params = LLFolderViewItem::Params()); - - static const LLFontGL* sFont; - static const LLFontGL* sSmallFont; - static LLUIImagePtr sArrowImage; - static LLUIImagePtr sBoxImage; - std::string mLabel; - std::string mSearchableLabel; - S32 mLabelWidth; - bool mLabelWidthDirty; - time_t mCreationDate; - LLFolderViewFolder* mParentFolder; - LLFolderViewEventListener* mListener; - BOOL mIsSelected; - BOOL mIsCurSelection; - BOOL mSelectPending; - LLFontGL::StyleFlags mLabelStyle; - std::string mLabelSuffix; - LLUIImagePtr mIcon; - std::string mStatusText; - BOOL mHasVisibleChildren; - S32 mIndentation; - S32 mNumDescendantsSelected; - BOOL mFiltered; - S32 mLastFilterGeneration; - std::string::size_type mStringMatchOffset; - F32 mControlLabelRotation; - LLFolderView* mRoot; - BOOL mDragAndDropTarget; - LLUIImagePtr mArrowImage; - LLUIImagePtr mBoxImage; - BOOL mIsLoading; - LLTimer mTimeSinceRequestStart; - - // This function clears the currently selected item, and records - // the specified selected item appropriately for display and use - // in the UI. If open is TRUE, then folders are opened up along - // the way to the selection. - void setSelectionFromRoot(LLFolderViewItem* selection, BOOL openitem, - BOOL take_keyboard_focus = TRUE); - - // helper function to change the selection from the root. - void changeSelectionFromRoot(LLFolderViewItem* selection, BOOL selected); - - // helper function to change the selection from the root. - void extendSelectionFromRoot(LLFolderViewItem* selection); - - // this is an internal method used for adding items to folders. A - // no-op at this leve, but reimplemented in derived classes. - virtual BOOL addItem(LLFolderViewItem*) { return FALSE; } - virtual BOOL addFolder(LLFolderViewFolder*) { return FALSE; } - -public: - // This function is called when the folder view is dirty. It's - // implemented here but called by derived classes when folding the - // views. - void arrangeFromRoot(); - void filterFromRoot( void ); - - virtual ~LLFolderViewItem( void ); - - // addToFolder() returns TRUE if it succeeds. FALSE otherwise - enum { ARRANGE = TRUE, DO_NOT_ARRANGE = FALSE }; - virtual BOOL addToFolder(LLFolderViewFolder* folder, LLFolderView* root); - - virtual EInventorySortGroup getSortGroup() const; - - // Finds width and height of this object and it's children. Also - // makes sure that this view and it's children are the right size. - virtual S32 arrange( S32* width, S32* height, S32 filter_generation ); - virtual S32 getItemHeight(); - - // applies filters to control visibility of inventory items - virtual void filter( LLInventoryFilter& filter); - - // updates filter serial number and optionally propagated value up to root - S32 getLastFilterGeneration() { return mLastFilterGeneration; } - - virtual void dirtyFilter(); - - // If the selection is 'this' then note that otherwise - // ignore. Returns TRUE if this object was affected. If open is - // TRUE, then folders are opened up along the way to the - // selection. - virtual BOOL setSelection(LLFolderViewItem* selection, BOOL openitem, - BOOL take_keyboard_focus); - - // This method is used to toggle the selection of an item. If - // selection is 'this', then note selection, and return TRUE. - virtual BOOL changeSelection(LLFolderViewItem* selection, BOOL selected); - - // this method is used to group select items - virtual S32 extendSelection(LLFolderViewItem* selection, LLFolderViewItem* last_selected, LLDynamicArray<LLFolderViewItem*>& items){ return FALSE; } - - // this method is used to group select items - virtual void recursiveDeselect(BOOL deselect_self); - - // gets multiple-element selection - virtual BOOL getSelectionList(std::set<LLUUID> &selection){return TRUE;} - - // Returns true is this object and all of its children can be removed (deleted by user) - virtual BOOL isRemovable(); - - // Returns true is this object and all of its children can be moved - virtual BOOL isMovable(); - - // destroys this item recursively - virtual void destroyView(); - - S32 getNumSelectedDescendants() { return mNumDescendantsSelected; } - - BOOL isSelected() { return mIsSelected; } - - void setIsCurSelection(BOOL select) { mIsCurSelection = select; } - - BOOL getIsCurSelection() { return mIsCurSelection; } - - BOOL hasVisibleChildren() { return mHasVisibleChildren; } - - // Call through to the viewed object and return true if it can be - // removed. Returns true if it's removed. - //virtual BOOL removeRecursively(BOOL single_item); - BOOL remove(); - - // Build an appropriate context menu for the item. Flags unused. - void buildContextMenu(LLMenuGL& menu, U32 flags); - - // This method returns the actual name of the thing being - // viewed. This method will ask the viewed object itself. - const std::string& getName( void ) const; - - const std::string& getSearchableLabel( void ) const; - - // This method returns the label displayed on the view. This - // method was primarily added to allow sorting on the folder - // contents possible before the entire view has been constructed. - const std::string& getLabel() const { return mLabel; } - - // Used for sorting, like getLabel() above. - virtual time_t getCreationDate() const { return mCreationDate; } - - LLFolderViewFolder* getParentFolder( void ) { return mParentFolder; } - const LLFolderViewFolder* getParentFolder( void ) const { return mParentFolder; } - - LLFolderViewItem* getNextOpenNode( BOOL include_children = TRUE ); - LLFolderViewItem* getPreviousOpenNode( BOOL include_children = TRUE ); - - const LLFolderViewEventListener* getListener( void ) const { return mListener; } - LLFolderViewEventListener* getListener( void ) { return mListener; } - - // just rename the object. - void rename(const std::string& new_name); - - // open - virtual void openItem( void ); - virtual void preview(void); - - // Show children (unfortunate that this is called "open") - virtual void setOpen(BOOL open = TRUE) {}; - - virtual BOOL isOpen() { return FALSE; } - - virtual LLFolderView* getRoot(); - BOOL isDescendantOf( const LLFolderViewFolder* potential_ancestor ); - S32 getIndentation() { return mIndentation; } - - virtual BOOL potentiallyVisible(); // do we know for a fact that this item has been filtered out? - - virtual BOOL getFiltered(); - virtual BOOL getFiltered(S32 filter_generation); - virtual void setFiltered(BOOL filtered, S32 filter_generation); - - // change the icon - void setIcon(LLUIImagePtr icon); - - // refresh information from the object being viewed. - void refreshFromListener(); - virtual void refresh(); - - virtual void applyListenerFunctorRecursively(LLFolderViewListenerFunctor& functor); - - // LLView functionality - virtual BOOL handleRightMouseDown( S32 x, S32 y, MASK mask ); - virtual BOOL handleMouseDown( S32 x, S32 y, MASK mask ); - virtual BOOL handleHover( S32 x, S32 y, MASK mask ); - virtual BOOL handleMouseUp( S32 x, S32 y, MASK mask ); - virtual BOOL handleDoubleClick( S32 x, S32 y, MASK mask ); - virtual BOOL handleScrollWheel(S32 x, S32 y, S32 clicks); - - // virtual void handleDropped(); - virtual void draw(); - virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, - EDragAndDropType cargo_type, - void* cargo_data, - EAcceptance* accept, - std::string& tooltip_msg); -}; - - -// function used for sorting. -typedef bool (*sort_order_f)(LLFolderViewItem* a, LLFolderViewItem* b); - - -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// Class LLFolderViewFolder -// -// An instance of an LLFolderViewFolder represents a collection of -// more folders and items. This is used to build the hierarchy of -// items found in the folder view. :) -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -class LLFolderViewFolder : public LLFolderViewItem -{ -protected: - LLFolderViewFolder( const LLFolderViewItem::Params& ); - friend class LLUICtrlFactory; - -public: - typedef enum e_trash - { - UNKNOWN, TRASH, NOT_TRASH - } ETrash; - -protected: - typedef std::list<LLFolderViewItem*> items_t; - typedef std::list<LLFolderViewFolder*> folders_t; - items_t mItems; - folders_t mFolders; - LLInventorySort mSortFunction; - - BOOL mIsOpen; - BOOL mExpanderHighlighted; - F32 mCurHeight; - F32 mTargetHeight; - F32 mAutoOpenCountdown; - time_t mSubtreeCreationDate; - mutable ETrash mAmTrash; - S32 mLastArrangeGeneration; - S32 mLastCalculatedWidth; - S32 mCompletedFilterGeneration; - S32 mMostFilteredDescendantGeneration; - bool mNeedsSort; -public: - typedef enum e_recurse_type - { - RECURSE_NO, - RECURSE_UP, - RECURSE_DOWN, - RECURSE_UP_DOWN - } ERecurseType; - - - virtual ~LLFolderViewFolder( void ); - - virtual BOOL potentiallyVisible(); - - LLFolderViewItem* getNextFromChild( LLFolderViewItem*, BOOL include_children = TRUE ); - LLFolderViewItem* getPreviousFromChild( LLFolderViewItem*, BOOL include_children = TRUE ); - - // addToFolder() returns TRUE if it succeeds. FALSE otherwise - virtual BOOL addToFolder(LLFolderViewFolder* folder, LLFolderView* root); - - // Finds width and height of this object and it's children. Also - // makes sure that this view and it's children are the right size. - virtual S32 arrange( S32* width, S32* height, S32 filter_generation ); - - BOOL needsArrange(); - void requestSort(); - - // Returns the sort group (system, trash, folder) for this folder. - virtual EInventorySortGroup getSortGroup() const; - - virtual void setCompletedFilterGeneration(S32 generation, BOOL recurse_up); - virtual S32 getCompletedFilterGeneration() { return mCompletedFilterGeneration; } - - BOOL hasFilteredDescendants(S32 filter_generation) { return mMostFilteredDescendantGeneration >= filter_generation; } - BOOL hasFilteredDescendants(); - - // applies filters to control visibility of inventory items - virtual void filter( LLInventoryFilter& filter); - virtual void setFiltered(BOOL filtered, S32 filter_generation); - virtual void dirtyFilter(); - - // Passes selection information on to children and record - // selection information if necessary. Returns TRUE if this object - // (or a child) was affected. - virtual BOOL setSelection(LLFolderViewItem* selection, BOOL openitem, - BOOL take_keyboard_focus); - - // This method is used to change the selection of an item. If - // selection is 'this', then note selection as true. Returns TRUE - // if this or a child is now selected. - virtual BOOL changeSelection(LLFolderViewItem* selection, BOOL selected); - - // this method is used to group select items - virtual S32 extendSelection(LLFolderViewItem* selection, LLFolderViewItem* last_selected, LLDynamicArray<LLFolderViewItem*>& items); - - virtual void recursiveDeselect(BOOL deselect_self); - - // Returns true is this object and all of its children can be removed. - virtual BOOL isRemovable(); - - // Returns true is this object and all of its children can be moved - virtual BOOL isMovable(); - - // destroys this folder, and all children - virtual void destroyView(); - - // If this folder can be removed, remove all children that can be - // removed, return TRUE if this is empty after the operation and - // it's viewed folder object can be removed. - //virtual BOOL removeRecursively(BOOL single_item); - //virtual BOOL remove(); - - // remove the specified item (and any children) if - // possible. Return TRUE if the item was deleted. - BOOL removeItem(LLFolderViewItem* item); - - // simply remove the view (and any children) Don't bother telling - // the listeners. - void removeView(LLFolderViewItem* item); - - // extractItem() removes the specified item from the folder, but - // doesn't delete it. - void extractItem( LLFolderViewItem* item ); - - // This function is called by a child that needs to be resorted. - void resort(LLFolderViewItem* item); - - void setItemSortOrder(U32 ordering); - void sortBy(U32); - //BOOL (*func)(LLFolderViewItem* a, LLFolderViewItem* b)); - - void setAutoOpenCountdown(F32 countdown) { mAutoOpenCountdown = countdown; } - - // folders can be opened. This will usually be called by internal - // methods. - virtual void toggleOpen(); - - // Force a folder open or closed - virtual void setOpen(BOOL openitem = TRUE); - - // Called when a child is refreshed. - // don't rearrange child folder contents unless explicitly requested - virtual void requestArrange(BOOL include_descendants = FALSE); - - // internal method which doesn't update the entire view. This - // method was written because the list iterators destroy the state - // of other iterations, thus, we can't arrange while iterating - // through the children (such as when setting which is selected. - virtual void setOpenArrangeRecursively(BOOL openitem, ERecurseType recurse = RECURSE_NO); - - // Get the current state of the folder. - virtual BOOL isOpen() { return mIsOpen; } - - // special case if an object is dropped on the child. - BOOL handleDragAndDropFromChild(MASK mask, - BOOL drop, - EDragAndDropType cargo_type, - void* cargo_data, - EAcceptance* accept, - std::string& tooltip_msg); - - void applyFunctorRecursively(LLFolderViewFunctor& functor); - virtual void applyListenerFunctorRecursively(LLFolderViewListenerFunctor& functor); - - virtual void openItem( void ); - virtual BOOL addItem(LLFolderViewItem* item); - virtual BOOL addFolder( LLFolderViewFolder* folder); - - // LLView functionality - virtual BOOL handleHover(S32 x, S32 y, MASK mask); - virtual BOOL handleRightMouseDown( S32 x, S32 y, MASK mask ); - virtual BOOL handleMouseDown( S32 x, S32 y, MASK mask ); - virtual BOOL handleDoubleClick( S32 x, S32 y, MASK mask ); - virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, - EDragAndDropType cargo_type, - void* cargo_data, - EAcceptance* accept, - std::string& tooltip_msg); - virtual void draw(); - - time_t getCreationDate() const; - bool isTrash() const; -}; - //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Class LLFolderView @@ -741,8 +89,12 @@ public: // manages the screen region of the folder view. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -class LLUICtrl; +class LLFolderViewEventListener; +class LLInventoryModel; class LLLineEditor; +class LLMenuGL; +class LLScrollContainer; +class LLUICtrl; class LLFolderView : public LLFolderViewFolder, public LLEditMenuHandler { @@ -765,21 +117,23 @@ public: // and resort the items if necessary. void setSortOrder(U32 order); void checkTreeResortForModelChanged(); - void setFilterPermMask(PermissionMask filter_perm_mask) { mFilter.setFilterPermissions(filter_perm_mask); } + void setFilterPermMask(PermissionMask filter_perm_mask); void setAllowMultiSelect(BOOL allow) { mAllowMultiSelect = allow; } typedef boost::signals2::signal<void (const std::deque<LLFolderViewItem*>& items, BOOL user_action)> signal_t; void setSelectCallback(const signal_t::slot_type& cb) { mSelectSignal.connect(cb); } void setReshapeCallback(const signal_t::slot_type& cb) { mReshapeSignal.connect(cb); } - LLInventoryFilter* getFilter() { return &mFilter; } + // filter is never null + LLInventoryFilter* getFilter(); const std::string getFilterSubString(BOOL trim = FALSE); - U32 getFilterTypes() const { return mFilter.getFilterTypes(); } - PermissionMask getFilterPermissions() const { return mFilter.getFilterPermissions(); } - LLInventoryFilter::EFolderShow getShowFolderState() { return mFilter.getShowFolderState(); } + U32 getFilterTypes() const; + PermissionMask getFilterPermissions() const; + // JAMESDEBUG use getFilter()->getShowFolderState(); + //LLInventoryFilter::EFolderShow getShowFolderState(); U32 getSortOrder() const; - BOOL isFilterModified() { return mFilter.isNotDefault(); } - BOOL getAllowMultiSelect() { return mAllowMultiSelect; } + BOOL isFilterModified(); + BOOL getAllowMultiSelect(); // Close all folders in the view void closeAllFolders(); @@ -914,7 +268,7 @@ public: LLPanel* getParentPanel() { return mParentPanel; } // DEBUG only void dumpSelectionInformation(); - + private: void updateRenamerPosition(); @@ -955,7 +309,7 @@ protected: LLFrameTimer mAutoOpenTimer; LLFrameTimer mSearchTimer; std::string mSearchString; - LLInventoryFilter mFilter; + LLInventoryFilter* mFilter; BOOL mShowSelectionContext; BOOL mShowSingleSelection; LLFrameTimer mMultiSelectionFadeTimer; diff --git a/indra/newview/llfoldervieweventlistener.h b/indra/newview/llfoldervieweventlistener.h new file mode 100644 index 0000000000000000000000000000000000000000..eb06123b467b3b774889bca5cb9f6074bbb3fa3b --- /dev/null +++ b/indra/newview/llfoldervieweventlistener.h @@ -0,0 +1,100 @@ +/** + * @file llfoldervieweventlistener.h + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ +#ifndef LLFOLDERVIEWEVENTLISTENER_H +#define LLFOLDERVIEWEVENTLISTENER_H + +#include "lldarray.h" // JAMESDEBUG convert to std::vector +#include "llfontgl.h" // just for StyleFlags enum +#include "llpointer.h" + + +class LLFolderViewItem; +class LLFolderView; +class LLFontGL; +class LLInventoryModel; +class LLMenuGL; +class LLScrollContainer; +class LLUIImage; +class LLUUID; + +// This is an abstract base class that users of the folderview classes +// would use to catch the useful events emitted from the folder +// views. +class LLFolderViewEventListener +{ +public: + virtual ~LLFolderViewEventListener( void ) {} + virtual const std::string& getName() const = 0; + virtual const std::string& getDisplayName() const = 0; + virtual const LLUUID& getUUID() const = 0; + virtual time_t getCreationDate() const = 0; // UTC seconds + virtual PermissionMask getPermissionMask() const = 0; + virtual LLAssetType::EType getPreferredType() const = 0; + virtual LLPointer<LLUIImage> getIcon() const = 0; + virtual LLFontGL::StyleFlags getLabelStyle() const = 0; + virtual std::string getLabelSuffix() const = 0; + virtual void openItem( void ) = 0; + virtual void previewItem( void ) = 0; + virtual void selectItem(void) = 0; + virtual void showProperties(void) = 0; + virtual BOOL isItemRenameable() const = 0; + virtual BOOL renameItem(const std::string& new_name) = 0; + virtual BOOL isItemMovable( void ) = 0; // Can be moved to another folder + virtual BOOL isItemRemovable( void ) = 0; // Can be destroyed + virtual BOOL removeItem() = 0; + virtual void removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batch) = 0; + virtual void move( LLFolderViewEventListener* parent_listener ) = 0; + virtual BOOL isItemCopyable() const = 0; + virtual BOOL copyToClipboard() const = 0; + virtual void cutToClipboard() = 0; + virtual BOOL isClipboardPasteable() const = 0; + virtual void pasteFromClipboard() = 0; + virtual void pasteLinkFromClipboard() = 0; + virtual void buildContextMenu(LLMenuGL& menu, U32 flags) = 0; + virtual BOOL isUpToDate() const = 0; + virtual BOOL hasChildren() const = 0; + virtual LLInventoryType::EType getInventoryType() const = 0; + virtual void performAction(LLFolderView* folder, LLInventoryModel* model, std::string action) = 0; + + // This method should be called when a drag begins. returns TRUE + // if the drag can begin, otherwise FALSE. + virtual BOOL startDrag(EDragAndDropType* type, LLUUID* id) const = 0; + + // This method will be called to determine if a drop can be + // performed, and will set drop to TRUE if a drop is + // requested. Returns TRUE if a drop is possible/happened, + // otherwise FALSE. + virtual BOOL dragOrDrop(MASK mask, BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data) = 0; +}; + +#endif diff --git a/indra/newview/llfolderviewitem.cpp b/indra/newview/llfolderviewitem.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7032e8695890007437ebbc7437ae5bae18928458 --- /dev/null +++ b/indra/newview/llfolderviewitem.cpp @@ -0,0 +1,2474 @@ +/** +* @file llfolderviewitem.cpp +* @brief Items and folders that can appear in a hierarchical folder view +* +* $LicenseInfo:firstyear=2001&license=viewergpl$ +* +* Copyright (c) 2001-2009, Linden Research, Inc. +* +* Second Life Viewer Source Code +* The source code in this file ("Source Code") is provided by Linden Lab +* to you under the terms of the GNU General Public License, version 2.0 +* ("GPL"), unless you have obtained a separate licensing agreement +* ("Other License"), formally executed by you and Linden Lab. Terms of +* the GPL can be found in doc/GPL-license.txt in this distribution, or +* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 +* +* There are special exceptions to the terms and conditions of the GPL as +* it is applied to this Source Code. View the full text of the exception +* in the file doc/FLOSS-exception.txt in this software distribution, or +* online at +* http://secondlifegrid.net/programs/open_source/licensing/flossexception +* +* By copying, modifying or distributing this software, you acknowledge +* that you have read and understood your obligations described above, +* and agree to abide by those obligations. +* +* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO +* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, +* COMPLETENESS OR PERFORMANCE. +* $/LicenseInfo$ +*/ +#include "llviewerprecompiledheaders.h" + +#include "llfolderviewitem.h" + +// viewer includes +#include "llfolderview.h" // Items depend extensively on LLFolderViews +#include "llfoldervieweventlistener.h" +#include "llinventoryfilter.h" +#include "llinventorymodel.h" // *TODO: make it take a pointer to an inventory-model interface +#include "llviewercontrol.h" // gSavedSettings +#include "llviewerwindow.h" // Argh, only for setCursor() + +// linden library includes +#include "llfocusmgr.h" // gFocusMgr +#include "llpanel.h" // panel->hasFocus() +#include "lltrans.h" + +///---------------------------------------------------------------------------- +/// Class LLFolderViewItem +///---------------------------------------------------------------------------- + +// statics +const LLFontGL* LLFolderViewItem::sFont = NULL; +const LLFontGL* LLFolderViewItem::sSmallFont = NULL; +LLUIImagePtr LLFolderViewItem::sArrowImage; +LLUIImagePtr LLFolderViewItem::sBoxImage; + +// only integers can be initialized in header +const F32 LLFolderViewItem::FOLDER_CLOSE_TIME_CONSTANT = 0.02f; +const F32 LLFolderViewItem::FOLDER_OPEN_TIME_CONSTANT = 0.03f; + +const LLColor4U DEFAULT_WHITE(255, 255, 255); + +//static +void LLFolderViewItem::initClass() +{ + sFont = LLFontGL::getFontSansSerifSmall(); + sSmallFont = LLFontGL::getFontMonospace(); + sArrowImage = LLUI::getUIImage("folder_arrow.tga"); + sBoxImage = LLUI::getUIImage("rounded_square.tga"); +} + +//static +void LLFolderViewItem::cleanupClass() +{ + sArrowImage = NULL; + sBoxImage = NULL; +} + + +// NOTE: Optimize this, we call it a *lot* when opening a large inventory +LLFolderViewItem::Params::Params() +: folder_arrow_image("", LLUI::getUIImage("folder_arrow.tga")), + selection_image("", LLUI::getUIImage("rounded_square.tga")) +{ + mouse_opaque(true); + follows.flags(FOLLOWS_LEFT|FOLLOWS_TOP|FOLLOWS_RIGHT); + // JAMESDEBUG tab_stop(false); +} + +// Default constructor +LLFolderViewItem::LLFolderViewItem(LLFolderViewItem::Params p) +: LLView(p), + mLabelWidth(0), + mLabelWidthDirty(false), + mParentFolder( NULL ), + mIsSelected( FALSE ), + mIsCurSelection( FALSE ), + mSelectPending(FALSE), + mLabelStyle( LLFontGL::NORMAL ), + mHasVisibleChildren(FALSE), + mIndentation(0), + mNumDescendantsSelected(0), + mFiltered(FALSE), + mLastFilterGeneration(-1), + mStringMatchOffset(std::string::npos), + mControlLabelRotation(0.f), + mDragAndDropTarget(FALSE), + mIsLoading(FALSE), + mLabel(p.name), + mRoot(p.root), + mCreationDate(p.creation_date), + mListener(p.listener), + mArrowImage(p.folder_arrow_image), + mBoxImage(p.selection_image) +{ + refresh(); +} + +// Destroys the object +LLFolderViewItem::~LLFolderViewItem( void ) +{ + delete mListener; + mListener = NULL; +} + +LLFolderView* LLFolderViewItem::getRoot() +{ + return mRoot; +} + +// Returns true if this object is a child (or grandchild, etc.) of potential_ancestor. +BOOL LLFolderViewItem::isDescendantOf( const LLFolderViewFolder* potential_ancestor ) +{ + LLFolderViewItem* root = this; + while( root->mParentFolder ) + { + if( root->mParentFolder == potential_ancestor ) + { + return TRUE; + } + root = root->mParentFolder; + } + return FALSE; +} + +LLFolderViewItem* LLFolderViewItem::getNextOpenNode(BOOL include_children) +{ + if (!mParentFolder) + { + return NULL; + } + + LLFolderViewItem* itemp = mParentFolder->getNextFromChild( this, include_children ); + while(itemp && !itemp->getVisible()) + { + LLFolderViewItem* next_itemp = itemp->mParentFolder->getNextFromChild( itemp, include_children ); + if (itemp == next_itemp) + { + // hit last item + return itemp->getVisible() ? itemp : this; + } + itemp = next_itemp; + } + + return itemp; +} + +LLFolderViewItem* LLFolderViewItem::getPreviousOpenNode(BOOL include_children) +{ + if (!mParentFolder) + { + return NULL; + } + + LLFolderViewItem* itemp = mParentFolder->getPreviousFromChild( this, include_children ); + while(itemp && !itemp->getVisible()) + { + LLFolderViewItem* next_itemp = itemp->mParentFolder->getPreviousFromChild( itemp, include_children ); + if (itemp == next_itemp) + { + // hit first item + return itemp->getVisible() ? itemp : this; + } + itemp = next_itemp; + } + + return itemp; +} + +// is this item something we think we should be showing? +// for example, if we haven't gotten around to filtering it yet, then the answer is yes +// until we find out otherwise +BOOL LLFolderViewItem::potentiallyVisible() +{ + // we haven't been checked against min required filter + // or we have and we passed + return getLastFilterGeneration() < getRoot()->getFilter()->getMinRequiredGeneration() || getFiltered(); +} + +BOOL LLFolderViewItem::getFiltered() +{ + return mFiltered && mLastFilterGeneration >= getRoot()->getFilter()->getMinRequiredGeneration(); +} + +BOOL LLFolderViewItem::getFiltered(S32 filter_generation) +{ + return mFiltered && mLastFilterGeneration >= filter_generation; +} + +void LLFolderViewItem::setFiltered(BOOL filtered, S32 filter_generation) +{ + mFiltered = filtered; + mLastFilterGeneration = filter_generation; +} + +void LLFolderViewItem::setIcon(LLUIImagePtr icon) +{ + mIcon = icon; +} + +// refresh information from the listener +void LLFolderViewItem::refreshFromListener() +{ + if(mListener) + { + mLabel = mListener->getDisplayName(); + LLAssetType::EType preferred_type = mListener->getPreferredType(); + + // *TODO: to be removed when database supports multi language. This is a + // temporary attempt to display the inventory folder in the user locale. + if (preferred_type != LLAssetType::AT_NONE) + { + mLabel = LLTrans::getString("InvFolder " + mLabel); + }; + + setIcon(mListener->getIcon()); + time_t creation_date = mListener->getCreationDate(); + if (mCreationDate != creation_date) + { + mCreationDate = mListener->getCreationDate(); + dirtyFilter(); + } + mLabelStyle = mListener->getLabelStyle(); + mLabelSuffix = mListener->getLabelSuffix(); + } +} + +void LLFolderViewItem::refresh() +{ + refreshFromListener(); + + std::string searchable_label(mLabel); + searchable_label.append(mLabelSuffix); + LLStringUtil::toUpper(searchable_label); + + if (mSearchableLabel.compare(searchable_label)) + { + mSearchableLabel.assign(searchable_label); + dirtyFilter(); + // some part of label has changed, so overall width has potentially changed, and sort order too + if (mParentFolder) + { + mParentFolder->requestSort(); + mParentFolder->requestArrange(); + } + } + + mLabelWidthDirty = true; +} + +void LLFolderViewItem::applyListenerFunctorRecursively(LLFolderViewListenerFunctor& functor) +{ + functor(mListener); +} + +// This function is called when items are added or view filters change. It's +// implemented here but called by derived classes when folding the +// views. +void LLFolderViewItem::filterFromRoot( void ) +{ + LLFolderViewItem* root = getRoot(); + + root->filter(*((LLFolderView*)root)->getFilter()); +} + +// This function is called when the folder view is dirty. It's +// implemented here but called by derived classes when folding the +// views. +void LLFolderViewItem::arrangeFromRoot() +{ + LLFolderViewItem* root = getRoot(); + + S32 height = 0; + S32 width = 0; + root->arrange( &width, &height, 0 ); +} + +// Utility function for LLFolderView +void LLFolderViewItem::arrangeAndSet(BOOL set_selection, + BOOL take_keyboard_focus) +{ + LLFolderView* root = getRoot(); + getParentFolder()->requestArrange(); + if(set_selection) + { + setSelectionFromRoot(this, TRUE, take_keyboard_focus); + if(root) + { + root->scrollToShowSelection(); + } + } +} + +// This function clears the currently selected item, and records the +// specified selected item appropriately for display and use in the +// UI. If open is TRUE, then folders are opened up along the way to +// the selection. +void LLFolderViewItem::setSelectionFromRoot(LLFolderViewItem* selection, + BOOL openitem, + BOOL take_keyboard_focus) +{ + getRoot()->setSelection(selection, openitem, take_keyboard_focus); +} + +// helper function to change the selection from the root. +void LLFolderViewItem::changeSelectionFromRoot(LLFolderViewItem* selection, BOOL selected) +{ + getRoot()->changeSelection(selection, selected); +} + +void LLFolderViewItem::extendSelectionFromRoot(LLFolderViewItem* selection) +{ + LLDynamicArray<LLFolderViewItem*> selected_items; + + getRoot()->extendSelection(selection, NULL, selected_items); +} + +EInventorySortGroup LLFolderViewItem::getSortGroup() const +{ + return SG_ITEM; +} + +// addToFolder() returns TRUE if it succeeds. FALSE otherwise +BOOL LLFolderViewItem::addToFolder(LLFolderViewFolder* folder, LLFolderView* root) +{ + if (!folder) + { + return FALSE; + } + mParentFolder = folder; + root->addItemID(getListener()->getUUID(), this); + return folder->addItem(this); +} + + +// Finds width and height of this object and it's children. Also +// makes sure that this view and it's children are the right size. +S32 LLFolderViewItem::arrange( S32* width, S32* height, S32 filter_generation) +{ + mIndentation = mParentFolder ? mParentFolder->getIndentation() + LEFT_INDENTATION : 0; + if (mLabelWidthDirty) + { + mLabelWidth = ARROW_SIZE + TEXT_PAD + ICON_WIDTH + ICON_PAD + sFont->getWidth(mSearchableLabel); + mLabelWidthDirty = false; + } + + *width = llmax(*width, mLabelWidth + mIndentation); + *height = getItemHeight(); + return *height; +} + +S32 LLFolderViewItem::getItemHeight() +{ + S32 icon_height = mIcon->getHeight(); + S32 label_height = llround(sFont->getLineHeight()); + return llmax( icon_height, label_height ) + ICON_PAD; +} + +void LLFolderViewItem::filter( LLInventoryFilter& filter) +{ + BOOL filtered = mListener && filter.check(this); + + // if our visibility will change as a result of this filter, then + // we need to be rearranged in our parent folder + if (getVisible() != filtered) + { + if (mParentFolder) + { + mParentFolder->requestArrange(); + } + } + + setFiltered(filtered, filter.getCurrentGeneration()); + mStringMatchOffset = filter.getStringMatchOffset(); + filter.decrementFilterCount(); + + if (getRoot()->getDebugFilters()) + { + mStatusText = llformat("%d", mLastFilterGeneration); + } +} + +void LLFolderViewItem::dirtyFilter() +{ + mLastFilterGeneration = -1; + // bubble up dirty flag all the way to root + if (getParentFolder()) + { + getParentFolder()->setCompletedFilterGeneration(-1, TRUE); + } +} + +// *TODO: This can be optimized a lot by simply recording that it is +// selected in the appropriate places, and assuming that set selection +// means 'deselect' for a leaf item. Do this optimization after +// multiple selection is implemented to make sure it all plays nice +// together. +BOOL LLFolderViewItem::setSelection(LLFolderViewItem* selection, BOOL openitem, BOOL take_keyboard_focus) +{ + if( selection == this ) + { + mIsSelected = TRUE; + if(mListener) + { + mListener->selectItem(); + } + } + else + { + mIsSelected = FALSE; + } + return mIsSelected; +} + +BOOL LLFolderViewItem::changeSelection(LLFolderViewItem* selection, BOOL selected) +{ + if(selection == this && mIsSelected != selected) + { + mIsSelected = selected; + if(mListener) + { + mListener->selectItem(); + } + return TRUE; + } + return FALSE; +} + +void LLFolderViewItem::recursiveDeselect(BOOL deselect_self) +{ + if (mIsSelected && deselect_self) + { + mIsSelected = FALSE; + + // update ancestors' count of selected descendents + LLFolderViewFolder* parent_folder = getParentFolder(); + while(parent_folder) + { + parent_folder->mNumDescendantsSelected--; + parent_folder = parent_folder->getParentFolder(); + } + } +} + + +BOOL LLFolderViewItem::isMovable() +{ + if( mListener ) + { + return mListener->isItemMovable(); + } + else + { + return TRUE; + } +} + +BOOL LLFolderViewItem::isRemovable() +{ + if( mListener ) + { + return mListener->isItemRemovable(); + } + else + { + return TRUE; + } +} + +void LLFolderViewItem::destroyView() +{ + if (mParentFolder) + { + // removeView deletes me + mParentFolder->removeView(this); + } +} + +// Call through to the viewed object and return true if it can be +// removed. +//BOOL LLFolderViewItem::removeRecursively(BOOL single_item) +BOOL LLFolderViewItem::remove() +{ + if(!isRemovable()) + { + return FALSE; + } + if(mListener) + { + return mListener->removeItem(); + } + return TRUE; +} + +// Build an appropriate context menu for the item. +void LLFolderViewItem::buildContextMenu(LLMenuGL& menu, U32 flags) +{ + if(mListener) + { + mListener->buildContextMenu(menu, flags); + } +} + +void LLFolderViewItem::openItem( void ) +{ + if( mListener ) + { + mListener->openItem(); + } +} + +void LLFolderViewItem::preview( void ) +{ + if (mListener) + { + mListener->previewItem(); + } +} + +void LLFolderViewItem::rename(const std::string& new_name) +{ + if( !new_name.empty() ) + { + if( mListener ) + { + mListener->renameItem(new_name); + + if(mParentFolder) + { + mParentFolder->requestSort(); + } + } + } +} + +const std::string& LLFolderViewItem::getSearchableLabel() const +{ + return mSearchableLabel; +} + +const std::string& LLFolderViewItem::getName( void ) const +{ + if(mListener) + { + return mListener->getName(); + } + return mLabel; +} + +// LLView functionality +BOOL LLFolderViewItem::handleRightMouseDown( S32 x, S32 y, MASK mask ) +{ + if(!mIsSelected) + { + setSelectionFromRoot(this, FALSE); + } + make_ui_sound("UISndClick"); + return TRUE; +} + +BOOL LLFolderViewItem::handleMouseDown( S32 x, S32 y, MASK mask ) +{ + // No handler needed for focus lost since this class has no + // state that depends on it. + gFocusMgr.setMouseCapture( this ); + + if (!mIsSelected) + { + if(mask & MASK_CONTROL) + { + changeSelectionFromRoot(this, !mIsSelected); + } + else if (mask & MASK_SHIFT) + { + extendSelectionFromRoot(this); + } + else + { + setSelectionFromRoot(this, FALSE); + } + make_ui_sound("UISndClick"); + } + else + { + mSelectPending = TRUE; + } + + if( isMovable() ) + { + S32 screen_x; + S32 screen_y; + localPointToScreen(x, y, &screen_x, &screen_y ); + LLToolDragAndDrop::getInstance()->setDragStart( screen_x, screen_y ); + } + return TRUE; +} + +BOOL LLFolderViewItem::handleHover( S32 x, S32 y, MASK mask ) +{ + if( hasMouseCapture() && isMovable() ) + { + S32 screen_x; + S32 screen_y; + localPointToScreen(x, y, &screen_x, &screen_y ); + BOOL can_drag = TRUE; + if( LLToolDragAndDrop::getInstance()->isOverThreshold( screen_x, screen_y ) ) + { + LLFolderView* root = getRoot(); + + if(root->getCurSelectedItem()) + { + LLToolDragAndDrop::ESource src = LLToolDragAndDrop::SOURCE_WORLD; + + // *TODO: push this into listener and remove + // dependency on llagent + if (mListener + && gInventory.isObjectDescendentOf(mListener->getUUID(), gInventory.getRootFolderID())) + { + src = LLToolDragAndDrop::SOURCE_AGENT; + } + else if (mListener + && gInventory.isObjectDescendentOf(mListener->getUUID(), gInventory.getLibraryRootFolderID())) + { + src = LLToolDragAndDrop::SOURCE_LIBRARY; + } + + can_drag = root->startDrag(src); + if (can_drag) + { + // if (mListener) mListener->startDrag(); + // RN: when starting drag and drop, clear out last auto-open + root->autoOpenTest(NULL); + root->setShowSelectionContext(TRUE); + + // Release keyboard focus, so that if stuff is dropped into the + // world, pressing the delete key won't blow away the inventory + // item. + gFocusMgr.setKeyboardFocus(NULL); + + return LLToolDragAndDrop::getInstance()->handleHover( x, y, mask ); + } + } + } + + if (can_drag) + { + gViewerWindow->setCursor(UI_CURSOR_ARROW); + } + else + { + gViewerWindow->setCursor(UI_CURSOR_NOLOCKED); + } + return TRUE; + } + else + { + getRoot()->setShowSelectionContext(FALSE); + gViewerWindow->setCursor(UI_CURSOR_ARROW); + // let parent handle this then... + return FALSE; + } +} + + +BOOL LLFolderViewItem::handleDoubleClick( S32 x, S32 y, MASK mask ) +{ + preview(); + return TRUE; +} + +BOOL LLFolderViewItem::handleScrollWheel(S32 x, S32 y, S32 clicks) +{ + if (getParent()) + { + return getParent()->handleScrollWheel(x, y, clicks); + } + return FALSE; +} + +BOOL LLFolderViewItem::handleMouseUp( S32 x, S32 y, MASK mask ) +{ + // if mouse hasn't moved since mouse down... + if ( pointInView(x, y) && mSelectPending ) + { + //...then select + if(mask & MASK_CONTROL) + { + changeSelectionFromRoot(this, !mIsSelected); + } + else if (mask & MASK_SHIFT) + { + extendSelectionFromRoot(this); + } + else + { + setSelectionFromRoot(this, FALSE); + } + } + + mSelectPending = FALSE; + + if( hasMouseCapture() ) + { + getRoot()->setShowSelectionContext(FALSE); + gFocusMgr.setMouseCapture( NULL ); + } + return TRUE; +} + +BOOL LLFolderViewItem::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg) +{ + BOOL accepted = FALSE; + BOOL handled = FALSE; + if(mListener) + { + accepted = mListener->dragOrDrop(mask,drop,cargo_type,cargo_data); + handled = accepted; + if (accepted) + { + mDragAndDropTarget = TRUE; + *accept = ACCEPT_YES_MULTI; + } + else + { + *accept = ACCEPT_NO; + } + } + if(mParentFolder && !handled) + { + handled = mParentFolder->handleDragAndDropFromChild(mask,drop,cargo_type,cargo_data,accept,tooltip_msg); + } + if (handled) + { + lldebugst(LLERR_USER_INPUT) << "dragAndDrop handled by LLFolderViewItem" << llendl; + } + + return handled; +} + + +void LLFolderViewItem::draw() +{ + static LLUIColor sFgColor = LLUIColorTable::instance().getColor("MenuItemEnabledColor", DEFAULT_WHITE); + static LLUIColor sHighlightBgColor = LLUIColorTable::instance().getColor("MenuItemHighlightBgColor", DEFAULT_WHITE); + static LLUIColor sHighlightFgColor = LLUIColorTable::instance().getColor("MenuItemHighlightFgColor", DEFAULT_WHITE); + static LLUIColor sFilterBGColor = LLUIColorTable::instance().getColor("FilterBackgroundColor", DEFAULT_WHITE); + static LLUIColor sFilterTextColor = LLUIColorTable::instance().getColor("FilterTextColor", DEFAULT_WHITE); + static LLUIColor sSuffixColor = LLUIColorTable::instance().getColor("InventoryItemSuffixColor", DEFAULT_WHITE); + static LLUIColor sSearchStatusColor = LLUIColorTable::instance().getColor("InventorySearchStatusColor", DEFAULT_WHITE); + + bool possibly_has_children = false; + bool up_to_date = mListener && mListener->isUpToDate(); + if((up_to_date && hasVisibleChildren() ) || // we fetched our children and some of them have passed the filter... + (!up_to_date && mListener && mListener->hasChildren())) // ...or we know we have children but haven't fetched them (doesn't obey filter) + { + possibly_has_children = true; + } + if(/*mControlLabel[0] != '\0' && */possibly_has_children) + { + if (sArrowImage) + { + gl_draw_scaled_rotated_image(mIndentation, getRect().getHeight() - ARROW_SIZE - TEXT_PAD, + ARROW_SIZE, ARROW_SIZE, mControlLabelRotation, sArrowImage->getImage(), sFgColor); + } + } + + F32 text_left = (F32)(ARROW_SIZE + TEXT_PAD + ICON_WIDTH + ICON_PAD + mIndentation); + + // If we have keyboard focus, draw selection filled + BOOL show_context = getRoot()->getShowSelectionContext(); + BOOL filled = show_context || (getRoot()->getParentPanel()->hasFocus()); + + // always render "current" item, only render other selected items if + // mShowSingleSelection is FALSE + if( mIsSelected ) + { + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + LLColor4 bg_color = sHighlightBgColor; + //const S32 TRAILING_PAD = 5; // It just looks better with this. + if (!mIsCurSelection) + { + // do time-based fade of extra objects + F32 fade_time = getRoot()->getSelectionFadeElapsedTime(); + if (getRoot()->getShowSingleSelection()) + { + // fading out + bg_color.mV[VALPHA] = clamp_rescale(fade_time, 0.f, 0.4f, bg_color.mV[VALPHA], 0.f); + } + else + { + // fading in + bg_color.mV[VALPHA] = clamp_rescale(fade_time, 0.f, 0.4f, 0.f, bg_color.mV[VALPHA]); + } + } + + gl_rect_2d( + 0, + getRect().getHeight(), + getRect().getWidth() - 2, + llfloor(getRect().getHeight() - sFont->getLineHeight() - ICON_PAD), + bg_color, filled); + if (mIsCurSelection) + { + gl_rect_2d( + 0, + getRect().getHeight(), + getRect().getWidth() - 2, + llfloor(getRect().getHeight() - sFont->getLineHeight() - ICON_PAD), + sHighlightFgColor, FALSE); + } + if (getRect().getHeight() > llround(sFont->getLineHeight()) + ICON_PAD + 2) + { + gl_rect_2d( + 0, + llfloor(getRect().getHeight() - sFont->getLineHeight() - ICON_PAD) - 2, + getRect().getWidth() - 2, + 2, + sHighlightFgColor, FALSE); + if (show_context) + { + gl_rect_2d( + 0, + llfloor(getRect().getHeight() - sFont->getLineHeight() - ICON_PAD) - 2, + getRect().getWidth() - 2, + 2, + sHighlightBgColor, TRUE); + } + } + } + if (mDragAndDropTarget) + { + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + gl_rect_2d( + 0, + getRect().getHeight(), + getRect().getWidth() - 2, + llfloor(getRect().getHeight() - sFont->getLineHeight() - ICON_PAD), + sHighlightBgColor, FALSE); + + if (getRect().getHeight() > llround(sFont->getLineHeight()) + ICON_PAD + 2) + { + gl_rect_2d( + 0, + llfloor(getRect().getHeight() - sFont->getLineHeight() - ICON_PAD) - 2, + getRect().getWidth() - 2, + 2, + sHighlightBgColor, FALSE); + } + mDragAndDropTarget = FALSE; + } + + + if(mIcon) + { + mIcon->draw(mIndentation + ARROW_SIZE + TEXT_PAD, getRect().getHeight() - mIcon->getHeight()); + } + + if (!mLabel.empty()) + { + // highlight filtered text + BOOL debug_filters = getRoot()->getDebugFilters(); + LLColor4 color = ( (mIsSelected && filled) ? sHighlightFgColor : sFgColor ); + F32 right_x; + F32 y = (F32)getRect().getHeight() - sFont->getLineHeight() - (F32)TEXT_PAD; + + if (debug_filters) + { + if (!getFiltered() && !possibly_has_children) + { + color.mV[VALPHA] *= 0.5f; + } + + LLColor4 filter_color = mLastFilterGeneration >= getRoot()->getFilter()->getCurrentGeneration() ? LLColor4(0.5f, 0.8f, 0.5f, 1.f) : LLColor4(0.8f, 0.5f, 0.5f, 1.f); + sSmallFont->renderUTF8(mStatusText, 0, text_left, y, filter_color, + LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, + S32_MAX, S32_MAX, &right_x, FALSE ); + text_left = right_x; + } + + + if ( mIsLoading + && mTimeSinceRequestStart.getElapsedTimeF32() >= gSavedSettings.getF32("FolderLoadingMessageWaitTime") ) + { + sFont->renderUTF8(LLTrans::getString("LoadingData"), 0, text_left, y, sSearchStatusColor, + LLFontGL::LEFT, LLFontGL::BOTTOM, mLabelStyle, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, &right_x, FALSE); + text_left = right_x; + } + + sFont->renderUTF8( mLabel, 0, text_left, y, color, + LLFontGL::LEFT, LLFontGL::BOTTOM, mLabelStyle, LLFontGL::NO_SHADOW, + S32_MAX, S32_MAX, &right_x, FALSE ); + if (!mLabelSuffix.empty()) + { + sFont->renderUTF8( mLabelSuffix, 0, right_x, y, sSuffixColor, + LLFontGL::LEFT, LLFontGL::BOTTOM, mLabelStyle, LLFontGL::NO_SHADOW, + S32_MAX, S32_MAX, &right_x, FALSE ); + } + + if (sBoxImage.notNull() && mStringMatchOffset != std::string::npos) + { + // don't draw backgrounds for zero-length strings + S32 filter_string_length = getRoot()->getFilterSubString().size(); + if (filter_string_length > 0) + { + std::string combined_string = mLabel + mLabelSuffix; + S32 left = llround(text_left) + sFont->getWidth(combined_string, 0, mStringMatchOffset) - 1; + S32 right = left + sFont->getWidth(combined_string, mStringMatchOffset, filter_string_length) + 2; + S32 bottom = llfloor(getRect().getHeight() - sFont->getLineHeight() - 3); + S32 top = getRect().getHeight(); + + LLRect box_rect(left, top, right, bottom); + sBoxImage->draw(box_rect, sFilterBGColor); + F32 match_string_left = text_left + sFont->getWidthF32(combined_string, 0, mStringMatchOffset); + F32 y = (F32)getRect().getHeight() - sFont->getLineHeight() - (F32)TEXT_PAD; + sFont->renderUTF8( combined_string, mStringMatchOffset, match_string_left, y, + sFilterTextColor, LLFontGL::LEFT, LLFontGL::BOTTOM, mLabelStyle, LLFontGL::NO_SHADOW, + filter_string_length, S32_MAX, &right_x, FALSE ); + } + } + } + + if( sDebugRects ) + { + drawDebugRect(); + } + + //// *HACK: also draw debug rectangles around currently-being-edited LLView, and any elements that are being highlighted by GUI preview code (see LLFloaterUIPreview) + //std::set<LLView*>::iterator iter = std::find(sPreviewHighlightedElements.begin(), sPreviewHighlightedElements.end(), this); + //if ((sEditingUI && this == sEditingUIView) || (iter != sPreviewHighlightedElements.end() && sDrawPreviewHighlights)) + //{ + // drawDebugRect(); + //} +} + + +///---------------------------------------------------------------------------- +/// Class LLFolderViewFolder +///---------------------------------------------------------------------------- + +LLFolderViewFolder::LLFolderViewFolder( const LLFolderViewItem::Params& p ): +LLFolderViewItem( p ), // 0 = no create time +mIsOpen(FALSE), +mExpanderHighlighted(FALSE), +mCurHeight(0.f), +mTargetHeight(0.f), +mAutoOpenCountdown(0.f), +mSubtreeCreationDate(0), +mAmTrash(LLFolderViewFolder::UNKNOWN), +mLastArrangeGeneration( -1 ), +mLastCalculatedWidth(0), +mCompletedFilterGeneration(-1), +mMostFilteredDescendantGeneration(-1), +mNeedsSort(false) +{} + +// Destroys the object +LLFolderViewFolder::~LLFolderViewFolder( void ) +{ + // The LLView base class takes care of object destruction. make sure that we + // don't have mouse or keyboard focus + gFocusMgr.releaseFocusIfNeeded( this ); // calls onCommit() +} + +// addToFolder() returns TRUE if it succeeds. FALSE otherwise +BOOL LLFolderViewFolder::addToFolder(LLFolderViewFolder* folder, LLFolderView* root) +{ + if (!folder) + { + return FALSE; + } + mParentFolder = folder; + root->addItemID(getListener()->getUUID(), this); + return folder->addFolder(this); +} + +// Finds width and height of this object and it's children. Also +// makes sure that this view and it's children are the right size. +S32 LLFolderViewFolder::arrange( S32* width, S32* height, S32 filter_generation) +{ + // sort before laying out contents + if (mNeedsSort) + { + mFolders.sort(mSortFunction); + mItems.sort(mSortFunction); + mNeedsSort = false; + } + + mHasVisibleChildren = hasFilteredDescendants(filter_generation); + + LLInventoryFilter::EFolderShow show_folder_state = getRoot()->getFilter()->getShowFolderState(); + + // calculate height as a single item (without any children), and reshapes rectangle to match + LLFolderViewItem::arrange( width, height, filter_generation ); + + // clamp existing animated height so as to never get smaller than a single item + mCurHeight = llmax((F32)*height, mCurHeight); + + // initialize running height value as height of single item in case we have no children + *height = getItemHeight(); + F32 running_height = (F32)*height; + F32 target_height = (F32)*height; + + // are my children visible? + if (needsArrange()) + { + // set last arrange generation first, in case children are animating + // and need to be arranged again + mLastArrangeGeneration = getRoot()->getArrangeGeneration(); + if (mIsOpen) + { + // Add sizes of children + S32 parent_item_height = getRect().getHeight(); + + for(folders_t::iterator fit = mFolders.begin(); fit != mFolders.end(); ++fit) + { + LLFolderViewFolder* folderp = (*fit); + if (getRoot()->getDebugFilters()) + { + folderp->setVisible(TRUE); + } + else + { + folderp->setVisible(show_folder_state == LLInventoryFilter::SHOW_ALL_FOLDERS || // always show folders? + (folderp->getFiltered(filter_generation) || folderp->hasFilteredDescendants(filter_generation))); // passed filter or has descendants that passed filter + } + + if (folderp->getVisible()) + { + S32 child_width = *width; + S32 child_height = 0; + S32 child_top = parent_item_height - llround(running_height); + + target_height += folderp->arrange( &child_width, &child_height, filter_generation ); + + running_height += (F32)child_height; + *width = llmax(*width, child_width); + folderp->setOrigin( 0, child_top - folderp->getRect().getHeight() ); + } + } + for(items_t::iterator iit = mItems.begin(); + iit != mItems.end(); ++iit) + { + LLFolderViewItem* itemp = (*iit); + if (getRoot()->getDebugFilters()) + { + itemp->setVisible(TRUE); + } + else + { + itemp->setVisible(itemp->getFiltered(filter_generation)); + } + + if (itemp->getVisible()) + { + S32 child_width = *width; + S32 child_height = 0; + S32 child_top = parent_item_height - llround(running_height); + + target_height += itemp->arrange( &child_width, &child_height, filter_generation ); + // don't change width, as this item is as wide as its parent folder by construction + itemp->reshape( itemp->getRect().getWidth(), child_height); + + running_height += (F32)child_height; + *width = llmax(*width, child_width); + itemp->setOrigin( 0, child_top - itemp->getRect().getHeight() ); + } + } + } + + mTargetHeight = target_height; + // cache this width so next time we can just return it + mLastCalculatedWidth = *width; + } + else + { + // just use existing width + *width = mLastCalculatedWidth; + } + + // animate current height towards target height + if (llabs(mCurHeight - mTargetHeight) > 1.f) + { + mCurHeight = lerp(mCurHeight, mTargetHeight, LLCriticalDamp::getInterpolant(mIsOpen ? FOLDER_OPEN_TIME_CONSTANT : FOLDER_CLOSE_TIME_CONSTANT)); + + requestArrange(); + + // hide child elements that fall out of current animated height + for (folders_t::iterator iter = mFolders.begin(); + iter != mFolders.end();) + { + folders_t::iterator fit = iter++; + // number of pixels that bottom of folder label is from top of parent folder + if (getRect().getHeight() - (*fit)->getRect().mTop + (*fit)->getItemHeight() + > llround(mCurHeight) + MAX_FOLDER_ITEM_OVERLAP) + { + // hide if beyond current folder height + (*fit)->setVisible(FALSE); + } + } + + for (items_t::iterator iter = mItems.begin(); + iter != mItems.end();) + { + items_t::iterator iit = iter++; + // number of pixels that bottom of item label is from top of parent folder + if (getRect().getHeight() - (*iit)->getRect().mBottom + > llround(mCurHeight) + MAX_FOLDER_ITEM_OVERLAP) + { + (*iit)->setVisible(FALSE); + } + } + } + else + { + mCurHeight = mTargetHeight; + } + + // don't change width as this item is already as wide as its parent folder + reshape(getRect().getWidth(),llround(mCurHeight)); + + // pass current height value back to parent + *height = llround(mCurHeight); + + return llround(mTargetHeight); +} + +BOOL LLFolderViewFolder::needsArrange() +{ + return mLastArrangeGeneration < getRoot()->getArrangeGeneration(); +} + +void LLFolderViewFolder::requestSort() +{ + mNeedsSort = true; + // whenever item order changes, we need to lay things out again + requestArrange(); +} + +void LLFolderViewFolder::setCompletedFilterGeneration(S32 generation, BOOL recurse_up) +{ + mMostFilteredDescendantGeneration = llmin(mMostFilteredDescendantGeneration, generation); + mCompletedFilterGeneration = generation; + // only aggregate up if we are a lower (older) value + if (recurse_up && mParentFolder && generation < mParentFolder->getCompletedFilterGeneration()) + { + mParentFolder->setCompletedFilterGeneration(generation, TRUE); + } +} + +void LLFolderViewFolder::filter( LLInventoryFilter& filter) +{ + S32 filter_generation = filter.getCurrentGeneration(); + // if failed to pass filter newer than must_pass_generation + // you will automatically fail this time, so we only + // check against items that have passed the filter + S32 must_pass_generation = filter.getMustPassGeneration(); + + // if we have already been filtered against this generation, skip out + if (getCompletedFilterGeneration() >= filter_generation) + { + return; + } + + // filter folder itself + if (getLastFilterGeneration() < filter_generation) + { + if (getLastFilterGeneration() >= must_pass_generation && // folder has been compared to a valid precursor filter + !mFiltered) // and did not pass the filter + { + // go ahead and flag this folder as done + mLastFilterGeneration = filter_generation; + } + else + { + // filter self only on first pass through + LLFolderViewItem::filter( filter ); + } + } + + if (getRoot()->getDebugFilters()) + { + mStatusText = llformat("%d", mLastFilterGeneration); + mStatusText += llformat("(%d)", mCompletedFilterGeneration); + mStatusText += llformat("+%d", mMostFilteredDescendantGeneration); + } + + // all descendants have been filtered later than must pass generation + // but none passed + if(getCompletedFilterGeneration() >= must_pass_generation && !hasFilteredDescendants(must_pass_generation)) + { + // don't traverse children if we've already filtered them since must_pass_generation + // and came back with nothing + return; + } + + // we entered here with at least one filter iteration left + // check to see if we have any more before continuing on to children + if (filter.getFilterCount() < 0) + { + return; + } + + // when applying a filter, matching folders get their contents downloaded first + if (filter.isNotDefault() && getFiltered(filter.getMinRequiredGeneration()) && (mListener && !gInventory.isCategoryComplete(mListener->getUUID()))) + { + gInventory.startBackgroundFetch(mListener->getUUID()); + } + + // now query children + for (folders_t::iterator iter = mFolders.begin(); + iter != mFolders.end();) + { + folders_t::iterator fit = iter++; + // have we run out of iterations this frame? + if (filter.getFilterCount() < 0) + { + break; + } + + // mMostFilteredDescendantGeneration might have been reset + // in which case we need to update it even for folders that + // don't need to be filtered anymore + if ((*fit)->getCompletedFilterGeneration() >= filter_generation) + { + // track latest generation to pass any child items + if ((*fit)->getFiltered() || (*fit)->hasFilteredDescendants(filter.getMinRequiredGeneration())) + { + mMostFilteredDescendantGeneration = filter_generation; + if (getRoot()->needsAutoSelect()) + { + (*fit)->setOpenArrangeRecursively(TRUE); + } + } + // just skip it, it has already been filtered + continue; + } + + // update this folders filter status (and children) + (*fit)->filter( filter ); + + // track latest generation to pass any child items + if ((*fit)->getFiltered() || (*fit)->hasFilteredDescendants(filter_generation)) + { + mMostFilteredDescendantGeneration = filter_generation; + if (getRoot()->needsAutoSelect()) + { + (*fit)->setOpenArrangeRecursively(TRUE); + } + } + } + + for (items_t::iterator iter = mItems.begin(); + iter != mItems.end();) + { + items_t::iterator iit = iter++; + if (filter.getFilterCount() < 0) + { + break; + } + if ((*iit)->getLastFilterGeneration() >= filter_generation) + { + if ((*iit)->getFiltered()) + { + mMostFilteredDescendantGeneration = filter_generation; + } + continue; + } + + if ((*iit)->getLastFilterGeneration() >= must_pass_generation && + !(*iit)->getFiltered(must_pass_generation)) + { + // failed to pass an earlier filter that was a subset of the current one + // go ahead and flag this item as done + (*iit)->setFiltered(FALSE, filter_generation); + continue; + } + + (*iit)->filter( filter ); + + if ((*iit)->getFiltered(filter.getMinRequiredGeneration())) + { + mMostFilteredDescendantGeneration = filter_generation; + } + } + + // if we didn't use all filter iterations + // that means we filtered all of our descendants + // instead of exhausting the filter count for this frame + if (filter.getFilterCount() > 0) + { + // flag this folder as having completed filter pass for all descendants + setCompletedFilterGeneration(filter_generation, FALSE/*dont recurse up to root*/); + } +} + +void LLFolderViewFolder::setFiltered(BOOL filtered, S32 filter_generation) +{ + // if this folder is now filtered, but wasn't before + // (it just passed) + if (filtered && !mFiltered) + { + // reset current height, because last time we drew it + // it might have had more visible items than now + mCurHeight = 0.f; + } + + LLFolderViewItem::setFiltered(filtered, filter_generation); +} + +void LLFolderViewFolder::dirtyFilter() +{ + // we're a folder, so invalidate our completed generation + setCompletedFilterGeneration(-1, FALSE); + LLFolderViewItem::dirtyFilter(); +} + +BOOL LLFolderViewFolder::hasFilteredDescendants() +{ + return mMostFilteredDescendantGeneration >= getRoot()->getFilter()->getCurrentGeneration(); +} + +// Passes selection information on to children and record selection +// information if necessary. +BOOL LLFolderViewFolder::setSelection(LLFolderViewItem* selection, BOOL openitem, + BOOL take_keyboard_focus) +{ + BOOL rv = FALSE; + if( selection == this ) + { + mIsSelected = TRUE; + if(mListener) + { + mListener->selectItem(); + } + rv = TRUE; + } + else + { + mIsSelected = FALSE; + rv = FALSE; + } + BOOL child_selected = FALSE; + + for (folders_t::iterator iter = mFolders.begin(); + iter != mFolders.end();) + { + folders_t::iterator fit = iter++; + if((*fit)->setSelection(selection, openitem, take_keyboard_focus)) + { + rv = TRUE; + child_selected = TRUE; + mNumDescendantsSelected++; + } + } + for (items_t::iterator iter = mItems.begin(); + iter != mItems.end();) + { + items_t::iterator iit = iter++; + if((*iit)->setSelection(selection, openitem, take_keyboard_focus)) + { + rv = TRUE; + child_selected = TRUE; + mNumDescendantsSelected++; + } + } + if(openitem && child_selected) + { + setOpenArrangeRecursively(TRUE); + } + return rv; +} + +// This method is used to change the selection of an item. If +// selection is 'this', then note selection as true. Returns TRUE +// if this or a child is now selected. +BOOL LLFolderViewFolder::changeSelection(LLFolderViewItem* selection, + BOOL selected) +{ + BOOL rv = FALSE; + if(selection == this) + { + mIsSelected = selected; + if(mListener && selected) + { + mListener->selectItem(); + } + rv = TRUE; + } + + for (folders_t::iterator iter = mFolders.begin(); + iter != mFolders.end();) + { + folders_t::iterator fit = iter++; + if((*fit)->changeSelection(selection, selected)) + { + if (selected) + { + mNumDescendantsSelected++; + } + else + { + mNumDescendantsSelected--; + } + rv = TRUE; + } + } + for (items_t::iterator iter = mItems.begin(); + iter != mItems.end();) + { + items_t::iterator iit = iter++; + if((*iit)->changeSelection(selection, selected)) + { + if (selected) + { + mNumDescendantsSelected++; + } + else + { + mNumDescendantsSelected--; + } + rv = TRUE; + } + } + return rv; +} + +S32 LLFolderViewFolder::extendSelection(LLFolderViewItem* selection, LLFolderViewItem* last_selected, LLDynamicArray<LLFolderViewItem*>& selected_items) +{ + S32 num_selected = 0; + + // pass on to child folders first + for (folders_t::iterator iter = mFolders.begin(); + iter != mFolders.end();) + { + folders_t::iterator fit = iter++; + num_selected += (*fit)->extendSelection(selection, last_selected, selected_items); + mNumDescendantsSelected += num_selected; + } + + // handle selection of our immediate children... + BOOL reverse_select = FALSE; + BOOL found_last_selected = FALSE; + BOOL found_selection = FALSE; + LLDynamicArray<LLFolderViewItem*> items_to_select; + LLFolderViewItem* item; + + //...folders first... + for (folders_t::iterator iter = mFolders.begin(); + iter != mFolders.end();) + { + folders_t::iterator fit = iter++; + item = (*fit); + if(item == selection) + { + found_selection = TRUE; + } + else if (item == last_selected) + { + found_last_selected = TRUE; + if (found_selection) + { + reverse_select = TRUE; + } + } + + if (found_selection || found_last_selected) + { + // deselect currently selected items so they can be pushed back on queue + if (item->isSelected()) + { + item->changeSelection(item, FALSE); + } + items_to_select.put(item); + } + + if (found_selection && found_last_selected) + { + break; + } + } + + if (!(found_selection && found_last_selected)) + { + //,,,then items + for (items_t::iterator iter = mItems.begin(); + iter != mItems.end();) + { + items_t::iterator iit = iter++; + item = (*iit); + if(item == selection) + { + found_selection = TRUE; + } + else if (item == last_selected) + { + found_last_selected = TRUE; + if (found_selection) + { + reverse_select = TRUE; + } + } + + if (found_selection || found_last_selected) + { + // deselect currently selected items so they can be pushed back on queue + if (item->isSelected()) + { + item->changeSelection(item, FALSE); + } + items_to_select.put(item); + } + + if (found_selection && found_last_selected) + { + break; + } + } + } + + if (found_last_selected && found_selection) + { + // we have a complete selection inside this folder + for (S32 index = reverse_select ? items_to_select.getLength() - 1 : 0; + reverse_select ? index >= 0 : index < items_to_select.getLength(); reverse_select ? index-- : index++) + { + LLFolderViewItem* item = items_to_select[index]; + if (item->changeSelection(item, TRUE)) + { + selected_items.put(item); + mNumDescendantsSelected++; + num_selected++; + } + } + } + else if (found_selection) + { + // last selection was not in this folder....go ahead and select just the new item + if (selection->changeSelection(selection, TRUE)) + { + selected_items.put(selection); + mNumDescendantsSelected++; + num_selected++; + } + } + + return num_selected; +} + +void LLFolderViewFolder::recursiveDeselect(BOOL deselect_self) +{ + // make sure we don't have negative values + llassert(mNumDescendantsSelected >= 0); + + if (mIsSelected && deselect_self) + { + mIsSelected = FALSE; + + // update ancestors' count of selected descendents + LLFolderViewFolder* parent_folder = getParentFolder(); + while(parent_folder) + { + parent_folder->mNumDescendantsSelected--; + parent_folder = parent_folder->getParentFolder(); + } + } + + if (0 == mNumDescendantsSelected) + { + return; + } + + for (items_t::iterator iter = mItems.begin(); + iter != mItems.end();) + { + items_t::iterator iit = iter++; + LLFolderViewItem* item = (*iit); + item->recursiveDeselect(TRUE); + } + + for (folders_t::iterator iter = mFolders.begin(); + iter != mFolders.end();) + { + folders_t::iterator fit = iter++; + LLFolderViewFolder* folder = (*fit); + folder->recursiveDeselect(TRUE); + } + +} + +void LLFolderViewFolder::destroyView() +{ + for (items_t::iterator iter = mItems.begin(); + iter != mItems.end();) + { + items_t::iterator iit = iter++; + LLFolderViewItem* item = (*iit); + getRoot()->removeItemID(item->getListener()->getUUID()); + } + + std::for_each(mItems.begin(), mItems.end(), DeletePointer()); + mItems.clear(); + + while (!mFolders.empty()) + { + LLFolderViewFolder *folderp = mFolders.back(); + folderp->destroyView(); // removes entry from mFolders + } + + deleteAllChildren(); + + if (mParentFolder) + { + mParentFolder->removeView(this); + } +} + +// remove the specified item (and any children) if possible. Return +// TRUE if the item was deleted. +BOOL LLFolderViewFolder::removeItem(LLFolderViewItem* item) +{ + if(item->remove()) + { + //RN: this seem unneccessary as remove() moves to trash + //removeView(item); + return TRUE; + } + return FALSE; +} + +// simply remove the view (and any children) Don't bother telling the +// listeners. +void LLFolderViewFolder::removeView(LLFolderViewItem* item) +{ + if (!item || item->getParentFolder() != this) + { + return; + } + // deselect without traversing hierarchy + item->recursiveDeselect(TRUE); + getRoot()->removeFromSelectionList(item); + extractItem(item); + delete item; +} + +// extractItem() removes the specified item from the folder, but +// doesn't delete it. +void LLFolderViewFolder::extractItem( LLFolderViewItem* item ) +{ + items_t::iterator it = std::find(mItems.begin(), mItems.end(), item); + if(it == mItems.end()) + { + // This is an evil downcast. However, it's only doing + // pointer comparison to find if (which it should be ) the + // item is in the container, so it's pretty safe. + LLFolderViewFolder* f = reinterpret_cast<LLFolderViewFolder*>(item); + folders_t::iterator ft; + ft = std::find(mFolders.begin(), mFolders.end(), f); + if(ft != mFolders.end()) + { + mFolders.erase(ft); + } + } + else + { + mItems.erase(it); + } + //item has been removed, need to update filter + dirtyFilter(); + //because an item is going away regardless of filter status, force rearrange + requestArrange(); + getRoot()->removeItemID(item->getListener()->getUUID()); + removeChild(item); +} + +bool LLFolderViewFolder::isTrash() const +{ + if (mAmTrash == LLFolderViewFolder::UNKNOWN) + { + mAmTrash = mListener->getUUID() == gInventory.findCategoryUUIDForType(LLAssetType::AT_TRASH, false) ? LLFolderViewFolder::TRASH : LLFolderViewFolder::NOT_TRASH; + } + return mAmTrash == LLFolderViewFolder::TRASH; +} + +void LLFolderViewFolder::sortBy(U32 order) +{ + if (!mSortFunction.updateSort(order)) + { + // No changes. + return; + } + + // Propegate this change to sub folders + for (folders_t::iterator iter = mFolders.begin(); + iter != mFolders.end();) + { + folders_t::iterator fit = iter++; + (*fit)->sortBy(order); + } + + mFolders.sort(mSortFunction); + mItems.sort(mSortFunction); + + if (order & LLInventoryFilter::SO_DATE) + { + time_t latest = 0; + + if (!mItems.empty()) + { + LLFolderViewItem* item = *(mItems.begin()); + latest = item->getCreationDate(); + } + + if (!mFolders.empty()) + { + LLFolderViewFolder* folder = *(mFolders.begin()); + if (folder->getCreationDate() > latest) + { + latest = folder->getCreationDate(); + } + } + mSubtreeCreationDate = latest; + } +} + +void LLFolderViewFolder::setItemSortOrder(U32 ordering) +{ + if (mSortFunction.updateSort(ordering)) + { + for (folders_t::iterator iter = mFolders.begin(); + iter != mFolders.end();) + { + folders_t::iterator fit = iter++; + (*fit)->setItemSortOrder(ordering); + } + + mFolders.sort(mSortFunction); + mItems.sort(mSortFunction); + } +} + +EInventorySortGroup LLFolderViewFolder::getSortGroup() const +{ + if (isTrash()) + { + return SG_TRASH_FOLDER; + } + + // Folders that can't be moved are 'system' folders. + if( mListener ) + { + if( !(mListener->isItemMovable()) ) + { + return SG_SYSTEM_FOLDER; + } + } + + return SG_NORMAL_FOLDER; +} + +BOOL LLFolderViewFolder::isMovable() +{ + if( mListener ) + { + if( !(mListener->isItemMovable()) ) + { + return FALSE; + } + + for (items_t::iterator iter = mItems.begin(); + iter != mItems.end();) + { + items_t::iterator iit = iter++; + if(!(*iit)->isMovable()) + { + return FALSE; + } + } + + for (folders_t::iterator iter = mFolders.begin(); + iter != mFolders.end();) + { + folders_t::iterator fit = iter++; + if(!(*fit)->isMovable()) + { + return FALSE; + } + } + } + return TRUE; +} + + +BOOL LLFolderViewFolder::isRemovable() +{ + if( mListener ) + { + if( !(mListener->isItemRemovable()) ) + { + return FALSE; + } + + for (items_t::iterator iter = mItems.begin(); + iter != mItems.end();) + { + items_t::iterator iit = iter++; + if(!(*iit)->isRemovable()) + { + return FALSE; + } + } + + for (folders_t::iterator iter = mFolders.begin(); + iter != mFolders.end();) + { + folders_t::iterator fit = iter++; + if(!(*fit)->isRemovable()) + { + return FALSE; + } + } + } + return TRUE; +} + +// this is an internal method used for adding items to folders. +BOOL LLFolderViewFolder::addItem(LLFolderViewItem* item) +{ + mItems.push_back(item); + item->setRect(LLRect(0, 0, getRect().getWidth(), 0)); + item->setVisible(FALSE); + addChild( item ); + item->dirtyFilter(); + requestArrange(); + requestSort(); + return TRUE; +} + +// this is an internal method used for adding items to folders. +BOOL LLFolderViewFolder::addFolder(LLFolderViewFolder* folder) +{ + mFolders.push_back(folder); + folder->setOrigin(0, 0); + folder->reshape(getRect().getWidth(), 0); + folder->setVisible(FALSE); + addChild( folder ); + folder->dirtyFilter(); + // rearrange all descendants too, as our indentation level might have changed + folder->requestArrange(TRUE); + requestSort(); + return TRUE; +} + +void LLFolderViewFolder::requestArrange(BOOL include_descendants) +{ + mLastArrangeGeneration = -1; + // flag all items up to root + if (mParentFolder) + { + mParentFolder->requestArrange(); + } + + if (include_descendants) + { + for (folders_t::iterator iter = mFolders.begin(); + iter != mFolders.end(); + ++iter) + { + (*iter)->requestArrange(TRUE); + } + } +} + +void LLFolderViewFolder::toggleOpen() +{ + setOpen(!mIsOpen); +} + +// Force a folder open or closed +void LLFolderViewFolder::setOpen(BOOL openitem) +{ + setOpenArrangeRecursively(openitem); +} + +void LLFolderViewFolder::setOpenArrangeRecursively(BOOL openitem, ERecurseType recurse) +{ + BOOL was_open = mIsOpen; + mIsOpen = openitem; + if(!was_open && openitem) + { + if(mListener) + { + mListener->openItem(); + } + } + + if (recurse == RECURSE_DOWN || recurse == RECURSE_UP_DOWN) + { + for (folders_t::iterator iter = mFolders.begin(); + iter != mFolders.end();) + { + folders_t::iterator fit = iter++; + (*fit)->setOpenArrangeRecursively(openitem, RECURSE_DOWN); /* Flawfinder: ignore */ + } + } + if (mParentFolder && (recurse == RECURSE_UP || recurse == RECURSE_UP_DOWN)) + { + mParentFolder->setOpenArrangeRecursively(openitem, RECURSE_UP); + } + + if (was_open != mIsOpen) + { + requestArrange(); + } +} + +BOOL LLFolderViewFolder::handleDragAndDropFromChild(MASK mask, + BOOL drop, + EDragAndDropType c_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg) +{ + BOOL accepted = mListener && mListener->dragOrDrop(mask,drop,c_type,cargo_data); + if (accepted) + { + mDragAndDropTarget = TRUE; + *accept = ACCEPT_YES_MULTI; + } + else + { + *accept = ACCEPT_NO; + } + + // drag and drop to child item, so clear pending auto-opens + getRoot()->autoOpenTest(NULL); + + return TRUE; +} + +void LLFolderViewFolder::openItem( void ) +{ + toggleOpen(); +} + +void LLFolderViewFolder::applyFunctorRecursively(LLFolderViewFunctor& functor) +{ + functor.doFolder(this); + + for (folders_t::iterator iter = mFolders.begin(); + iter != mFolders.end();) + { + folders_t::iterator fit = iter++; + (*fit)->applyFunctorRecursively(functor); + } + for (items_t::iterator iter = mItems.begin(); + iter != mItems.end();) + { + items_t::iterator iit = iter++; + functor.doItem((*iit)); + } +} + +void LLFolderViewFolder::applyListenerFunctorRecursively(LLFolderViewListenerFunctor& functor) +{ + functor(mListener); + for (folders_t::iterator iter = mFolders.begin(); + iter != mFolders.end();) + { + folders_t::iterator fit = iter++; + (*fit)->applyListenerFunctorRecursively(functor); + } + for (items_t::iterator iter = mItems.begin(); + iter != mItems.end();) + { + items_t::iterator iit = iter++; + (*iit)->applyListenerFunctorRecursively(functor); + } +} + +// LLView functionality +BOOL LLFolderViewFolder::handleDragAndDrop(S32 x, S32 y, MASK mask, + BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg) +{ + LLFolderView* root_view = getRoot(); + + BOOL handled = FALSE; + if(mIsOpen) + { + handled = childrenHandleDragAndDrop(x, y, mask, drop, cargo_type, + cargo_data, accept, tooltip_msg) != NULL; + } + + if (!handled) + { + BOOL accepted = mListener && mListener->dragOrDrop(mask, drop,cargo_type,cargo_data); + + if (accepted) + { + mDragAndDropTarget = TRUE; + *accept = ACCEPT_YES_MULTI; + } + else + { + *accept = ACCEPT_NO; + } + + if (!drop && accepted) + { + root_view->autoOpenTest(this); + } + + lldebugst(LLERR_USER_INPUT) << "dragAndDrop handled by LLFolderViewFolder" << llendl; + } + + return TRUE; +} + + +BOOL LLFolderViewFolder::handleRightMouseDown( S32 x, S32 y, MASK mask ) +{ + BOOL handled = FALSE; + // fetch contents of this folder, as context menu can depend on contents + // still, user would have to open context menu again to see the changes + gInventory.fetchDescendentsOf(mListener->getUUID()); + + if( mIsOpen ) + { + handled = childrenHandleRightMouseDown( x, y, mask ) != NULL; + } + if (!handled) + { + handled = LLFolderViewItem::handleRightMouseDown( x, y, mask ); + } + return handled; +} + + +BOOL LLFolderViewFolder::handleHover(S32 x, S32 y, MASK mask) +{ + BOOL handled = LLView::handleHover(x, y, mask); + + if (!handled) + { + // this doesn't do child processing + handled = LLFolderViewItem::handleHover(x, y, mask); + } + + //if(x < LEFT_INDENTATION + mIndentation && x > mIndentation - LEFT_PAD && y > getRect().getHeight() - ) + //{ + // gViewerWindow->setCursor(UI_CURSOR_ARROW); + // mExpanderHighlighted = TRUE; + // handled = TRUE; + //} + return handled; +} + +BOOL LLFolderViewFolder::handleMouseDown( S32 x, S32 y, MASK mask ) +{ + BOOL handled = FALSE; + if( mIsOpen ) + { + handled = childrenHandleMouseDown(x,y,mask) != NULL; + } + if( !handled ) + { + if(x < LEFT_INDENTATION + mIndentation && x > mIndentation - LEFT_PAD) + { + toggleOpen(); + handled = TRUE; + } + else + { + // do normal selection logic + handled = LLFolderViewItem::handleMouseDown(x, y, mask); + } + } + + return handled; +} + +BOOL LLFolderViewFolder::handleDoubleClick( S32 x, S32 y, MASK mask ) +{ + BOOL handled = FALSE; + if( mIsOpen ) + { + handled = childrenHandleDoubleClick( x, y, mask ) != NULL; + } + if( !handled ) + { + if(x < LEFT_INDENTATION + mIndentation && x > mIndentation - LEFT_PAD) + { + // don't select when user double-clicks plus sign + // so as not to contradict single-click behavior + toggleOpen(); + } + else + { + setSelectionFromRoot(this, FALSE); + toggleOpen(); + } + handled = TRUE; + } + return handled; +} + +void LLFolderViewFolder::draw() +{ + if (mAutoOpenCountdown != 0.f) + { + mControlLabelRotation = mAutoOpenCountdown * -90.f; + } + else if (mIsOpen) + { + mControlLabelRotation = lerp(mControlLabelRotation, -90.f, LLCriticalDamp::getInterpolant(0.04f)); + } + else + { + mControlLabelRotation = lerp(mControlLabelRotation, 0.f, LLCriticalDamp::getInterpolant(0.025f)); + } + + bool possibly_has_children = false; + bool up_to_date = mListener && mListener->isUpToDate(); + if(!up_to_date && mListener && mListener->hasChildren()) // we know we have children but haven't fetched them (doesn't obey filter) + { + possibly_has_children = true; + } + + + BOOL loading = ( mIsOpen && possibly_has_children && !up_to_date ); + + if ( loading && !mIsLoading ) + { + // Measure how long we've been in the loading state + mTimeSinceRequestStart.reset(); + } + + mIsLoading = loading; + + LLFolderViewItem::draw(); + + // draw children if root folder, or any other folder that is open or animating to closed state + if( getRoot() == this || (mIsOpen || mCurHeight != mTargetHeight )) + { + LLView::draw(); + } + + mExpanderHighlighted = FALSE; +} + +time_t LLFolderViewFolder::getCreationDate() const +{ + return llmax<time_t>(mCreationDate, mSubtreeCreationDate); +} + + +BOOL LLFolderViewFolder::potentiallyVisible() +{ + // folder should be visible by it's own filter status + return LLFolderViewItem::potentiallyVisible() + // or one or more of its descendants have passed the minimum filter requirement + || hasFilteredDescendants(getRoot()->getFilter()->getMinRequiredGeneration()) + // or not all of its descendants have been checked against minimum filter requirement + || getCompletedFilterGeneration() < getRoot()->getFilter()->getMinRequiredGeneration(); +} + +// this does prefix traversal, as folders are listed above their contents +LLFolderViewItem* LLFolderViewFolder::getNextFromChild( LLFolderViewItem* item, BOOL include_children ) +{ + BOOL found_item = FALSE; + + LLFolderViewItem* result = NULL; + // when not starting from a given item, start at beginning + if(item == NULL) + { + found_item = TRUE; + } + + // find current item among children + folders_t::iterator fit = mFolders.begin(); + folders_t::iterator fend = mFolders.end(); + + items_t::iterator iit = mItems.begin(); + items_t::iterator iend = mItems.end(); + + // if not trivially starting at the beginning, we have to find the current item + if (!found_item) + { + // first, look among folders, since they are always above items + for(; fit != fend; ++fit) + { + if(item == (*fit)) + { + found_item = TRUE; + // if we are on downwards traversal + if (include_children && (*fit)->isOpen()) + { + // look for first descendant + return (*fit)->getNextFromChild(NULL, TRUE); + } + // otherwise advance to next folder + ++fit; + include_children = TRUE; + break; + } + } + + // didn't find in folders? Check items... + if (!found_item) + { + for(; iit != iend; ++iit) + { + if(item == (*iit)) + { + found_item = TRUE; + // point to next item + ++iit; + break; + } + } + } + } + + if (!found_item) + { + // you should never call this method with an item that isn't a child + // so we should always find something + llassert(FALSE); + return NULL; + } + + // at this point, either iit or fit point to a candidate "next" item + // if both are out of range, we need to punt up to our parent + + // now, starting from found folder, continue through folders + // searching for next visible folder + while(fit != fend && !(*fit)->getVisible()) + { + // turn on downwards traversal for next folder + ++fit; + } + + if (fit != fend) + { + result = (*fit); + } + else + { + // otherwise, scan for next visible item + while(iit != iend && !(*iit)->getVisible()) + { + ++iit; + } + + // check to see if we have a valid item + if (iit != iend) + { + result = (*iit); + } + } + + if( !result && mParentFolder ) + { + // If there are no siblings or children to go to, recurse up one level in the tree + // and skip children for this folder, as we've already discounted them + result = mParentFolder->getNextFromChild(this, FALSE); + } + + return result; +} + +// this does postfix traversal, as folders are listed above their contents +LLFolderViewItem* LLFolderViewFolder::getPreviousFromChild( LLFolderViewItem* item, BOOL include_children ) +{ + BOOL found_item = FALSE; + + LLFolderViewItem* result = NULL; + // when not starting from a given item, start at end + if(item == NULL) + { + found_item = TRUE; + } + + // find current item among children + folders_t::reverse_iterator fit = mFolders.rbegin(); + folders_t::reverse_iterator fend = mFolders.rend(); + + items_t::reverse_iterator iit = mItems.rbegin(); + items_t::reverse_iterator iend = mItems.rend(); + + // if not trivially starting at the end, we have to find the current item + if (!found_item) + { + // first, look among items, since they are always below the folders + for(; iit != iend; ++iit) + { + if(item == (*iit)) + { + found_item = TRUE; + // point to next item + ++iit; + break; + } + } + + // didn't find in items? Check folders... + if (!found_item) + { + for(; fit != fend; ++fit) + { + if(item == (*fit)) + { + found_item = TRUE; + // point to next folder + ++fit; + break; + } + } + } + } + + if (!found_item) + { + // you should never call this method with an item that isn't a child + // so we should always find something + llassert(FALSE); + return NULL; + } + + // at this point, either iit or fit point to a candidate "next" item + // if both are out of range, we need to punt up to our parent + + // now, starting from found item, continue through items + // searching for next visible item + while(iit != iend && !(*iit)->getVisible()) + { + ++iit; + } + + if (iit != iend) + { + // we found an appropriate item + result = (*iit); + } + else + { + // otherwise, scan for next visible folder + while(fit != fend && !(*fit)->getVisible()) + { + ++fit; + } + + // check to see if we have a valid folder + if (fit != fend) + { + // try selecting child element of this folder + if ((*fit)->isOpen()) + { + result = (*fit)->getPreviousFromChild(NULL); + } + else + { + result = (*fit); + } + } + } + + if( !result ) + { + // If there are no siblings or children to go to, recurse up one level in the tree + // which gets back to this folder, which will only be visited if it is a valid, visible item + result = this; + } + + return result; +} + + +bool LLInventorySort::updateSort(U32 order) +{ + if (order != mSortOrder) + { + mSortOrder = order; + mByDate = (order & LLInventoryFilter::SO_DATE); + mSystemToTop = (order & LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP); + mFoldersByName = (order & LLInventoryFilter::SO_FOLDERS_BY_NAME); + return true; + } + return false; +} + +bool LLInventorySort::operator()(const LLFolderViewItem* const& a, const LLFolderViewItem* const& b) +{ + // We sort by name if we aren't sorting by date + // OR if these are folders and we are sorting folders by name. + bool by_name = (!mByDate + || (mFoldersByName + && (a->getSortGroup() != SG_ITEM))); + + if (a->getSortGroup() != b->getSortGroup()) + { + if (mSystemToTop) + { + // Group order is System Folders, Trash, Normal Folders, Items + return (a->getSortGroup() < b->getSortGroup()); + } + else if (mByDate) + { + // Trash needs to go to the bottom if we are sorting by date + if ( (a->getSortGroup() == SG_TRASH_FOLDER) + || (b->getSortGroup() == SG_TRASH_FOLDER)) + { + return (b->getSortGroup() == SG_TRASH_FOLDER); + } + } + } + + if (by_name) + { + S32 compare = LLStringUtil::compareDict(a->getLabel(), b->getLabel()); + if (0 == compare) + { + return (a->getCreationDate() > b->getCreationDate()); + } + else + { + return (compare < 0); + } + } + else + { + // BUG: This is very very slow. The getCreationDate() is log n in number + // of inventory items. + time_t first_create = a->getCreationDate(); + time_t second_create = b->getCreationDate(); + if (first_create == second_create) + { + return (LLStringUtil::compareDict(a->getLabel(), b->getLabel()) < 0); + } + else + { + return (first_create > second_create); + } + } +} diff --git a/indra/newview/llfolderviewitem.h b/indra/newview/llfolderviewitem.h new file mode 100644 index 0000000000000000000000000000000000000000..57807005c2a702a1d23814c21b6a073174d730e3 --- /dev/null +++ b/indra/newview/llfolderviewitem.h @@ -0,0 +1,528 @@ +/** +* @file llfolderviewitem.h +* @brief Items and folders that can appear in a hierarchical folder view +* +* $LicenseInfo:firstyear=2001&license=viewergpl$ +* +* Copyright (c) 2001-2009, Linden Research, Inc. +* +* Second Life Viewer Source Code +* The source code in this file ("Source Code") is provided by Linden Lab +* to you under the terms of the GNU General Public License, version 2.0 +* ("GPL"), unless you have obtained a separate licensing agreement +* ("Other License"), formally executed by you and Linden Lab. Terms of +* the GPL can be found in doc/GPL-license.txt in this distribution, or +* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 +* +* There are special exceptions to the terms and conditions of the GPL as +* it is applied to this Source Code. View the full text of the exception +* in the file doc/FLOSS-exception.txt in this software distribution, or +* online at +* http://secondlifegrid.net/programs/open_source/licensing/flossexception +* +* By copying, modifying or distributing this software, you acknowledge +* that you have read and understood your obligations described above, +* and agree to abide by those obligations. +* +* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO +* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, +* COMPLETENESS OR PERFORMANCE. +* $/LicenseInfo$ +*/ +#ifndef LLFOLDERVIEWITEM_H +#define LLFOLDERVIEWITEM_H + +#include "llview.h" + +class LLFontGL; +class LLFolderView; +class LLFolderViewEventListener; +class LLFolderViewFolder; +class LLFolderViewFunctor; +class LLFolderViewItem; +class LLFolderViewListenerFunctor; +class LLInventoryFilter; +class LLMenuGL; +class LLUIImage; + +// These are grouping of inventory types. +// Order matters when sorting system folders to the top. +enum EInventorySortGroup +{ + SG_SYSTEM_FOLDER, + SG_TRASH_FOLDER, + SG_NORMAL_FOLDER, + SG_ITEM +}; + +// JAMESDEBUG *TODO: do we really need one sort object per folder? +// can we just have one of these per LLFolderView ? +class LLInventorySort +{ +public: + LLInventorySort() + : mSortOrder(0), + mByDate(false), + mSystemToTop(false), + mFoldersByName(false) { } + + // Returns true if order has changed + bool updateSort(U32 order); + U32 getSort() { return mSortOrder; } + + bool operator()(const LLFolderViewItem* const& a, const LLFolderViewItem* const& b); +private: + U32 mSortOrder; + bool mByDate; + bool mSystemToTop; + bool mFoldersByName; +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Class LLFolderViewItem +// +// An instance of this class represents a single item in a folder view +// such as an inventory item or a file. +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class LLFolderViewItem : public LLView +{ +public: + static void initClass(); + static void cleanupClass(); + + // jamesdebug was LLUICtrl::Params + struct Params : public LLInitParam::Block<Params, LLView::Params> + { + Optional<LLUIImage*> icon; + Optional<LLFolderView*> root; + Optional<LLFolderViewEventListener*> listener; + + Optional<LLUIImage*> folder_arrow_image; + Optional<LLUIImage*> selection_image; + + Optional<S32> creation_date; //UTC seconds + + Params(); + }; + + // layout constants + static const S32 LEFT_PAD = 5; + static const S32 LEFT_INDENTATION = 13; + static const S32 ICON_PAD = 2; + static const S32 ICON_WIDTH = 16; + static const S32 TEXT_PAD = 1; + static const S32 ARROW_SIZE = 12; + static const S32 MAX_FOLDER_ITEM_OVERLAP = 2; + // animation parameters + static const F32 FOLDER_CLOSE_TIME_CONSTANT; + static const F32 FOLDER_OPEN_TIME_CONSTANT; + +protected: + friend class LLUICtrlFactory; + friend class LLFolderViewEventListener; + + LLFolderViewItem(Params p = LLFolderViewItem::Params()); + + static const LLFontGL* sFont; + static const LLFontGL* sSmallFont; + static LLUIImagePtr sArrowImage; + static LLUIImagePtr sBoxImage; + + std::string mLabel; + std::string mSearchableLabel; + S32 mLabelWidth; + bool mLabelWidthDirty; + time_t mCreationDate; + LLFolderViewFolder* mParentFolder; + LLFolderViewEventListener* mListener; + BOOL mIsSelected; + BOOL mIsCurSelection; + BOOL mSelectPending; + LLFontGL::StyleFlags mLabelStyle; + std::string mLabelSuffix; + LLUIImagePtr mIcon; + std::string mStatusText; + BOOL mHasVisibleChildren; + S32 mIndentation; + S32 mNumDescendantsSelected; + BOOL mFiltered; + S32 mLastFilterGeneration; + std::string::size_type mStringMatchOffset; + F32 mControlLabelRotation; + LLFolderView* mRoot; + BOOL mDragAndDropTarget; + LLUIImagePtr mArrowImage; + LLUIImagePtr mBoxImage; + BOOL mIsLoading; + LLTimer mTimeSinceRequestStart; + + // This function clears the currently selected item, and records + // the specified selected item appropriately for display and use + // in the UI. If open is TRUE, then folders are opened up along + // the way to the selection. + void setSelectionFromRoot(LLFolderViewItem* selection, BOOL openitem, + BOOL take_keyboard_focus = TRUE); + + // helper function to change the selection from the root. + void changeSelectionFromRoot(LLFolderViewItem* selection, BOOL selected); + + // helper function to change the selection from the root. + void extendSelectionFromRoot(LLFolderViewItem* selection); + + // this is an internal method used for adding items to folders. A + // no-op at this leve, but reimplemented in derived classes. + virtual BOOL addItem(LLFolderViewItem*) { return FALSE; } + virtual BOOL addFolder(LLFolderViewFolder*) { return FALSE; } + +public: + // This function is called when the folder view is dirty. It's + // implemented here but called by derived classes when folding the + // views. + void arrangeFromRoot(); + void filterFromRoot( void ); + + void arrangeAndSet(BOOL set_selection, BOOL take_keyboard_focus); + + virtual ~LLFolderViewItem( void ); + + // addToFolder() returns TRUE if it succeeds. FALSE otherwise + enum { ARRANGE = TRUE, DO_NOT_ARRANGE = FALSE }; + virtual BOOL addToFolder(LLFolderViewFolder* folder, LLFolderView* root); + + virtual EInventorySortGroup getSortGroup() const; + + // Finds width and height of this object and it's children. Also + // makes sure that this view and it's children are the right size. + virtual S32 arrange( S32* width, S32* height, S32 filter_generation ); + virtual S32 getItemHeight(); + + // applies filters to control visibility of inventory items + virtual void filter( LLInventoryFilter& filter); + + // updates filter serial number and optionally propagated value up to root + S32 getLastFilterGeneration() { return mLastFilterGeneration; } + + virtual void dirtyFilter(); + + // If the selection is 'this' then note that otherwise + // ignore. Returns TRUE if this object was affected. If open is + // TRUE, then folders are opened up along the way to the + // selection. + virtual BOOL setSelection(LLFolderViewItem* selection, BOOL openitem, + BOOL take_keyboard_focus); + + // This method is used to toggle the selection of an item. If + // selection is 'this', then note selection, and return TRUE. + virtual BOOL changeSelection(LLFolderViewItem* selection, BOOL selected); + + // this method is used to group select items + virtual S32 extendSelection(LLFolderViewItem* selection, LLFolderViewItem* last_selected, LLDynamicArray<LLFolderViewItem*>& items){ return FALSE; } + + // this method is used to group select items + virtual void recursiveDeselect(BOOL deselect_self); + + // gets multiple-element selection + virtual BOOL getSelectionList(std::set<LLUUID> &selection){return TRUE;} + + // Returns true is this object and all of its children can be removed (deleted by user) + virtual BOOL isRemovable(); + + // Returns true is this object and all of its children can be moved + virtual BOOL isMovable(); + + // destroys this item recursively + virtual void destroyView(); + + S32 getNumSelectedDescendants() { return mNumDescendantsSelected; } + + BOOL isSelected() { return mIsSelected; } + + void setIsCurSelection(BOOL select) { mIsCurSelection = select; } + + BOOL getIsCurSelection() { return mIsCurSelection; } + + BOOL hasVisibleChildren() { return mHasVisibleChildren; } + + // Call through to the viewed object and return true if it can be + // removed. Returns true if it's removed. + //virtual BOOL removeRecursively(BOOL single_item); + BOOL remove(); + + // Build an appropriate context menu for the item. Flags unused. + void buildContextMenu(LLMenuGL& menu, U32 flags); + + // This method returns the actual name of the thing being + // viewed. This method will ask the viewed object itself. + const std::string& getName( void ) const; + + const std::string& getSearchableLabel( void ) const; + + // This method returns the label displayed on the view. This + // method was primarily added to allow sorting on the folder + // contents possible before the entire view has been constructed. + const std::string& getLabel() const { return mLabel; } + + // Used for sorting, like getLabel() above. + virtual time_t getCreationDate() const { return mCreationDate; } + + LLFolderViewFolder* getParentFolder( void ) { return mParentFolder; } + const LLFolderViewFolder* getParentFolder( void ) const { return mParentFolder; } + + LLFolderViewItem* getNextOpenNode( BOOL include_children = TRUE ); + LLFolderViewItem* getPreviousOpenNode( BOOL include_children = TRUE ); + + const LLFolderViewEventListener* getListener( void ) const { return mListener; } + LLFolderViewEventListener* getListener( void ) { return mListener; } + + // just rename the object. + void rename(const std::string& new_name); + + // open + virtual void openItem( void ); + virtual void preview(void); + + // Show children (unfortunate that this is called "open") + virtual void setOpen(BOOL open = TRUE) {}; + + virtual BOOL isOpen() { return FALSE; } + + virtual LLFolderView* getRoot(); + BOOL isDescendantOf( const LLFolderViewFolder* potential_ancestor ); + S32 getIndentation() { return mIndentation; } + + virtual BOOL potentiallyVisible(); // do we know for a fact that this item has been filtered out? + + virtual BOOL getFiltered(); + virtual BOOL getFiltered(S32 filter_generation); + virtual void setFiltered(BOOL filtered, S32 filter_generation); + + // change the icon + void setIcon(LLUIImagePtr icon); + + // refresh information from the object being viewed. + void refreshFromListener(); + virtual void refresh(); + + virtual void applyListenerFunctorRecursively(LLFolderViewListenerFunctor& functor); + + // LLView functionality + virtual BOOL handleRightMouseDown( S32 x, S32 y, MASK mask ); + virtual BOOL handleMouseDown( S32 x, S32 y, MASK mask ); + virtual BOOL handleHover( S32 x, S32 y, MASK mask ); + virtual BOOL handleMouseUp( S32 x, S32 y, MASK mask ); + virtual BOOL handleDoubleClick( S32 x, S32 y, MASK mask ); + virtual BOOL handleScrollWheel(S32 x, S32 y, S32 clicks); + + // virtual void handleDropped(); + virtual void draw(); + virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg); +}; + + +// function used for sorting. +typedef bool (*sort_order_f)(LLFolderViewItem* a, LLFolderViewItem* b); + + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Class LLFolderViewFolder +// +// An instance of an LLFolderViewFolder represents a collection of +// more folders and items. This is used to build the hierarchy of +// items found in the folder view. :) +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class LLFolderViewFolder : public LLFolderViewItem +{ +protected: + LLFolderViewFolder( const LLFolderViewItem::Params& ); + friend class LLUICtrlFactory; + +public: + typedef enum e_trash + { + UNKNOWN, TRASH, NOT_TRASH + } ETrash; + +protected: + typedef std::list<LLFolderViewItem*> items_t; + typedef std::list<LLFolderViewFolder*> folders_t; + items_t mItems; + folders_t mFolders; + LLInventorySort mSortFunction; + + BOOL mIsOpen; + BOOL mExpanderHighlighted; + F32 mCurHeight; + F32 mTargetHeight; + F32 mAutoOpenCountdown; + time_t mSubtreeCreationDate; + mutable ETrash mAmTrash; + S32 mLastArrangeGeneration; + S32 mLastCalculatedWidth; + S32 mCompletedFilterGeneration; + S32 mMostFilteredDescendantGeneration; + bool mNeedsSort; +public: + typedef enum e_recurse_type + { + RECURSE_NO, + RECURSE_UP, + RECURSE_DOWN, + RECURSE_UP_DOWN + } ERecurseType; + + + virtual ~LLFolderViewFolder( void ); + + virtual BOOL potentiallyVisible(); + + LLFolderViewItem* getNextFromChild( LLFolderViewItem*, BOOL include_children = TRUE ); + LLFolderViewItem* getPreviousFromChild( LLFolderViewItem*, BOOL include_children = TRUE ); + + // addToFolder() returns TRUE if it succeeds. FALSE otherwise + virtual BOOL addToFolder(LLFolderViewFolder* folder, LLFolderView* root); + + // Finds width and height of this object and it's children. Also + // makes sure that this view and it's children are the right size. + virtual S32 arrange( S32* width, S32* height, S32 filter_generation ); + + BOOL needsArrange(); + void requestSort(); + + // Returns the sort group (system, trash, folder) for this folder. + virtual EInventorySortGroup getSortGroup() const; + + virtual void setCompletedFilterGeneration(S32 generation, BOOL recurse_up); + virtual S32 getCompletedFilterGeneration() { return mCompletedFilterGeneration; } + + BOOL hasFilteredDescendants(S32 filter_generation) { return mMostFilteredDescendantGeneration >= filter_generation; } + BOOL hasFilteredDescendants(); + + // applies filters to control visibility of inventory items + virtual void filter( LLInventoryFilter& filter); + virtual void setFiltered(BOOL filtered, S32 filter_generation); + virtual void dirtyFilter(); + + // Passes selection information on to children and record + // selection information if necessary. Returns TRUE if this object + // (or a child) was affected. + virtual BOOL setSelection(LLFolderViewItem* selection, BOOL openitem, + BOOL take_keyboard_focus); + + // This method is used to change the selection of an item. If + // selection is 'this', then note selection as true. Returns TRUE + // if this or a child is now selected. + virtual BOOL changeSelection(LLFolderViewItem* selection, BOOL selected); + + // this method is used to group select items + virtual S32 extendSelection(LLFolderViewItem* selection, LLFolderViewItem* last_selected, LLDynamicArray<LLFolderViewItem*>& items); + + virtual void recursiveDeselect(BOOL deselect_self); + + // Returns true is this object and all of its children can be removed. + virtual BOOL isRemovable(); + + // Returns true is this object and all of its children can be moved + virtual BOOL isMovable(); + + // destroys this folder, and all children + virtual void destroyView(); + + // If this folder can be removed, remove all children that can be + // removed, return TRUE if this is empty after the operation and + // it's viewed folder object can be removed. + //virtual BOOL removeRecursively(BOOL single_item); + //virtual BOOL remove(); + + // remove the specified item (and any children) if + // possible. Return TRUE if the item was deleted. + BOOL removeItem(LLFolderViewItem* item); + + // simply remove the view (and any children) Don't bother telling + // the listeners. + void removeView(LLFolderViewItem* item); + + // extractItem() removes the specified item from the folder, but + // doesn't delete it. + void extractItem( LLFolderViewItem* item ); + + // This function is called by a child that needs to be resorted. + void resort(LLFolderViewItem* item); + + void setItemSortOrder(U32 ordering); + void sortBy(U32); + //BOOL (*func)(LLFolderViewItem* a, LLFolderViewItem* b)); + + void setAutoOpenCountdown(F32 countdown) { mAutoOpenCountdown = countdown; } + + // folders can be opened. This will usually be called by internal + // methods. + virtual void toggleOpen(); + + // Force a folder open or closed + virtual void setOpen(BOOL openitem = TRUE); + + // Called when a child is refreshed. + // don't rearrange child folder contents unless explicitly requested + virtual void requestArrange(BOOL include_descendants = FALSE); + + // internal method which doesn't update the entire view. This + // method was written because the list iterators destroy the state + // of other iterations, thus, we can't arrange while iterating + // through the children (such as when setting which is selected. + virtual void setOpenArrangeRecursively(BOOL openitem, ERecurseType recurse = RECURSE_NO); + + // Get the current state of the folder. + virtual BOOL isOpen() { return mIsOpen; } + + // special case if an object is dropped on the child. + BOOL handleDragAndDropFromChild(MASK mask, + BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg); + + void applyFunctorRecursively(LLFolderViewFunctor& functor); + virtual void applyListenerFunctorRecursively(LLFolderViewListenerFunctor& functor); + + virtual void openItem( void ); + virtual BOOL addItem(LLFolderViewItem* item); + virtual BOOL addFolder( LLFolderViewFolder* folder); + + // LLView functionality + virtual BOOL handleHover(S32 x, S32 y, MASK mask); + virtual BOOL handleRightMouseDown( S32 x, S32 y, MASK mask ); + virtual BOOL handleMouseDown( S32 x, S32 y, MASK mask ); + virtual BOOL handleDoubleClick( S32 x, S32 y, MASK mask ); + virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg); + virtual void draw(); + + time_t getCreationDate() const; + bool isTrash() const; +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Class LLFolderViewListenerFunctor +// +// This simple abstract base class can be used to applied to all +// listeners in a hierarchy. +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class LLFolderViewListenerFunctor +{ +public: + virtual ~LLFolderViewListenerFunctor() {} + virtual void operator()(LLFolderViewEventListener* listener) = 0; +}; + +#endif // LLFOLDERVIEWITEM_H diff --git a/indra/newview/llgrouplist.cpp b/indra/newview/llgrouplist.cpp index 6473c85775dc5bc92ce946d54c2895b22bca7113..85da2eb2e33f4da7f169b54a40f531fd674da91e 100644 --- a/indra/newview/llgrouplist.cpp +++ b/indra/newview/llgrouplist.cpp @@ -40,7 +40,7 @@ // newview #include "llagent.h" -static LLDefaultWidgetRegistry::Register<LLGroupList> r("group_list"); +static LLDefaultChildRegistry::Register<LLGroupList> r("group_list"); LLGroupList::LLGroupList(const Params& p) : LLAvatarList(p) diff --git a/indra/newview/llimpanel.cpp b/indra/newview/llimpanel.cpp index fbf990e1af654267374cff0222a59b9cd96021a8..e5b05d9f5155e9ab729bf1ffd9acc85bb0549bdb 100644 --- a/indra/newview/llimpanel.cpp +++ b/indra/newview/llimpanel.cpp @@ -55,8 +55,7 @@ #include "llimview.h" #include "llinventory.h" #include "llinventorymodel.h" -#include "llinventoryview.h" -#include "llfloateractivespeakers.h" +#include "llfloaterinventory.h" #include "llfloaterchat.h" #include "llkeyboard.h" #include "lllineeditor.h" @@ -101,190 +100,7 @@ LLVoiceChannel* LLVoiceChannel::sSuspendedVoiceChannel = NULL; BOOL LLVoiceChannel::sSuspended = FALSE; -void session_starter_helper( - const LLUUID& temp_session_id, - const LLUUID& other_participant_id, - EInstantMessage im_type) -{ - LLMessageSystem *msg = gMessageSystem; - - msg->newMessageFast(_PREHASH_ImprovedInstantMessage); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - - msg->nextBlockFast(_PREHASH_MessageBlock); - msg->addBOOLFast(_PREHASH_FromGroup, FALSE); - msg->addUUIDFast(_PREHASH_ToAgentID, other_participant_id); - msg->addU8Fast(_PREHASH_Offline, IM_ONLINE); - msg->addU8Fast(_PREHASH_Dialog, im_type); - msg->addUUIDFast(_PREHASH_ID, temp_session_id); - msg->addU32Fast(_PREHASH_Timestamp, NO_TIMESTAMP); // no timestamp necessary - - std::string name; - gAgent.buildFullname(name); - - msg->addStringFast(_PREHASH_FromAgentName, name); - msg->addStringFast(_PREHASH_Message, LLStringUtil::null); - msg->addU32Fast(_PREHASH_ParentEstateID, 0); - msg->addUUIDFast(_PREHASH_RegionID, LLUUID::null); - msg->addVector3Fast(_PREHASH_Position, gAgent.getPositionAgent()); -} - -void start_deprecated_conference_chat( - const LLUUID& temp_session_id, - const LLUUID& creator_id, - const LLUUID& other_participant_id, - const LLSD& agents_to_invite) -{ - U8* bucket; - U8* pos; - S32 count; - S32 bucket_size; - - // *FIX: this could suffer from endian issues - count = agents_to_invite.size(); - bucket_size = UUID_BYTES * count; - bucket = new U8[bucket_size]; - pos = bucket; - - for(S32 i = 0; i < count; ++i) - { - LLUUID agent_id = agents_to_invite[i].asUUID(); - - memcpy(pos, &agent_id, UUID_BYTES); - pos += UUID_BYTES; - } - - session_starter_helper( - temp_session_id, - other_participant_id, - IM_SESSION_CONFERENCE_START); - - gMessageSystem->addBinaryDataFast( - _PREHASH_BinaryBucket, - bucket, - bucket_size); - - gAgent.sendReliableMessage(); - - delete[] bucket; -} - -class LLStartConferenceChatResponder : public LLHTTPClient::Responder -{ -public: - LLStartConferenceChatResponder( - const LLUUID& temp_session_id, - const LLUUID& creator_id, - const LLUUID& other_participant_id, - const LLSD& agents_to_invite) - { - mTempSessionID = temp_session_id; - mCreatorID = creator_id; - mOtherParticipantID = other_participant_id; - mAgents = agents_to_invite; - } - - virtual void error(U32 statusNum, const std::string& reason) - { - //try an "old school" way. - if ( statusNum == 400 ) - { - start_deprecated_conference_chat( - mTempSessionID, - mCreatorID, - mOtherParticipantID, - mAgents); - } - - //else throw an error back to the client? - //in theory we should have just have these error strings - //etc. set up in this file as opposed to the IMMgr, - //but the error string were unneeded here previously - //and it is not worth the effort switching over all - //the possible different language translations - } - -private: - LLUUID mTempSessionID; - LLUUID mCreatorID; - LLUUID mOtherParticipantID; - - LLSD mAgents; -}; - -// Returns true if any messages were sent, false otherwise. -// Is sort of equivalent to "does the server need to do anything?" -bool send_start_session_messages( - const LLUUID& temp_session_id, - const LLUUID& other_participant_id, - const std::vector<LLUUID>& ids, - EInstantMessage dialog) -{ - if ( dialog == IM_SESSION_GROUP_START ) - { - session_starter_helper( - temp_session_id, - other_participant_id, - dialog); - - switch(dialog) - { - case IM_SESSION_GROUP_START: - gMessageSystem->addBinaryDataFast( - _PREHASH_BinaryBucket, - EMPTY_BINARY_BUCKET, - EMPTY_BINARY_BUCKET_SIZE); - break; - default: - break; - } - gAgent.sendReliableMessage(); - return true; - } - else if ( dialog == IM_SESSION_CONFERENCE_START ) - { - LLSD agents; - for (int i = 0; i < (S32) ids.size(); i++) - { - agents.append(ids[i]); - } - - //we have a new way of starting conference calls now - LLViewerRegion* region = gAgent.getRegion(); - if (region) - { - std::string url = region->getCapability( - "ChatSessionRequest"); - LLSD data; - data["method"] = "start conference"; - data["session-id"] = temp_session_id; - - data["params"] = agents; - - LLHTTPClient::post( - url, - data, - new LLStartConferenceChatResponder( - temp_session_id, - gAgent.getID(), - other_participant_id, - data["params"])); - } - else - { - start_deprecated_conference_chat( - temp_session_id, - gAgent.getID(), - other_participant_id, - agents); - } - } - - return false; -} class LLVoiceCallCapResponder : public LLHTTPClient::Responder { @@ -1200,7 +1016,7 @@ LLFloaterIMPanel::LLFloaterIMPanel(const std::string& session_label, if ( !mSessionInitialized ) { - if ( !send_start_session_messages( + if ( !LLIMModel::instance().sendStartSession( mSessionUUID, mOtherParticipantUUID, mSessionInitialTargetIDs, @@ -1542,19 +1358,21 @@ void LLFloaterIMPanel::addHistoryLine(const std::string &utf8msg, const LLColor4 prepend_newline = false; } + std::string separator_string(": "); + // 'name' is a sender name that we want to hotlink so that clicking on it opens a profile. if (!name.empty()) // If name exists, then add it to the front of the message. { // Don't hotlink any messages from the system (e.g. "Second Life:"), so just add those in plain text. if (name == SYSTEM_FROM) { - mHistoryEditor->appendColoredText(name,false,prepend_newline,color); + mHistoryEditor->appendColoredText(name + separator_string, false, prepend_newline, color); } else { // Convert the name to a hotlink and add to message. const LLStyleSP &source_style = LLStyleMap::instance().lookupAgent(source); - mHistoryEditor->appendStyledText(name,false,prepend_newline,source_style); + mHistoryEditor->appendStyledText(name + separator_string, false, prepend_newline, source_style); } prepend_newline = false; } @@ -1565,9 +1383,9 @@ void LLFloaterIMPanel::addHistoryLine(const std::string &utf8msg, const LLColor4 { std::string histstr; if (gSavedPerAccountSettings.getBOOL("IMLogTimestamp")) - histstr = LLLogChat::timestamp(gSavedPerAccountSettings.getBOOL("LogTimestampDate")) + name + utf8msg; + histstr = LLLogChat::timestamp(gSavedPerAccountSettings.getBOOL("LogTimestampDate")) + name + separator_string + utf8msg; else - histstr = name + utf8msg; + histstr = name + separator_string + utf8msg; LLLogChat::saveHistory(getTitle(),histstr); } @@ -1620,7 +1438,6 @@ void LLFloaterIMPanel::selectNone() mInputEditor->deselect(); } - BOOL LLFloaterIMPanel::handleKeyHere( KEY key, MASK mask ) { BOOL handled = FALSE; @@ -1847,23 +1664,8 @@ void LLFloaterIMPanel::onClose(bool app_quitting) { setTyping(FALSE); - if(mSessionUUID.notNull()) - { - std::string name; - gAgent.buildFullname(name); - pack_instant_message( - gMessageSystem, - gAgent.getID(), - FALSE, - gAgent.getSessionID(), - mOtherParticipantUUID, - name, - LLStringUtil::null, - IM_ONLINE, - IM_SESSION_LEAVE, - mSessionUUID); - gAgent.sendReliableMessage(); - } + LLIMModel::instance().sendLeaveSession(mSessionUUID, mOtherParticipantUUID); + gIMMgr->removeSession(mSessionUUID); // *HACK hide the voice floater @@ -1884,79 +1686,6 @@ void LLFloaterIMPanel::onVisibilityChange(BOOL new_visibility) mSessionUUID); } -void deliver_message(const std::string& utf8_text, - const LLUUID& im_session_id, - const LLUUID& other_participant_id, - EInstantMessage dialog) -{ - std::string name; - bool sent = false; - gAgent.buildFullname(name); - - const LLRelationship* info = NULL; - info = LLAvatarTracker::instance().getBuddyInfo(other_participant_id); - - U8 offline = (!info || info->isOnline()) ? IM_ONLINE : IM_OFFLINE; - - if((offline == IM_OFFLINE) && (LLVoiceClient::getInstance()->isOnlineSIP(other_participant_id))) - { - // User is online through the OOW connector, but not with a regular viewer. Try to send the message via SLVoice. - sent = gVoiceClient->sendTextMessage(other_participant_id, utf8_text); - } - - if(!sent) - { - // Send message normally. - - // default to IM_SESSION_SEND unless it's nothing special - in - // which case it's probably an IM to everyone. - U8 new_dialog = dialog; - - if ( dialog != IM_NOTHING_SPECIAL ) - { - new_dialog = IM_SESSION_SEND; - } - pack_instant_message( - gMessageSystem, - gAgent.getID(), - FALSE, - gAgent.getSessionID(), - other_participant_id, - name.c_str(), - utf8_text.c_str(), - offline, - (EInstantMessage)new_dialog, - im_session_id); - gAgent.sendReliableMessage(); - } - - // If there is a mute list and this is not a group chat... - if ( LLMuteList::getInstance() ) - { - // ... the target should not be in our mute list for some message types. - // Auto-remove them if present. - switch( dialog ) - { - case IM_NOTHING_SPECIAL: - case IM_GROUP_INVITATION: - case IM_INVENTORY_OFFERED: - case IM_SESSION_INVITE: - case IM_SESSION_P2P_INVITE: - case IM_SESSION_CONFERENCE_START: - case IM_SESSION_SEND: // This one is marginal - erring on the side of hearing. - case IM_LURE_USER: - case IM_GODLIKE_LURE_USER: - case IM_FRIENDSHIP_OFFERED: - LLMuteList::getInstance()->autoRemove(other_participant_id, LLMuteList::AR_IM); - break; - default: ; // do nothing - } - } - - // Add the recipient to the recent people list. - LLRecentPeople::instance().add(other_participant_id); -} - void LLFloaterIMPanel::sendMsg() { if (!gAgent.isGodlike() @@ -1978,7 +1707,7 @@ void LLFloaterIMPanel::sendMsg() if ( mSessionInitialized ) { - deliver_message(utf8_text, + LLIMModel::sendMessage(utf8_text, mSessionUUID, mOtherParticipantUUID, mDialog); @@ -2084,7 +1813,7 @@ void LLFloaterIMPanel::sessionInitReplyReceived(const LLUUID& session_id) iter != mQueuedMsgsForInit.endArray(); ++iter) { - deliver_message( + LLIMModel::sendMessage( iter->asString(), mSessionUUID, mOtherParticipantUUID, @@ -2135,23 +1864,10 @@ void LLFloaterIMPanel::sendTypingState(BOOL typing) // much network traffic. Only send in person-to-person IMs. if (mDialog != IM_NOTHING_SPECIAL) return; - std::string name; - gAgent.buildFullname(name); - - pack_instant_message( - gMessageSystem, - gAgent.getID(), - FALSE, - gAgent.getSessionID(), - mOtherParticipantUUID, - name, - std::string("typing"), - IM_ONLINE, - (typing ? IM_TYPING_START : IM_TYPING_STOP), - mSessionUUID); - gAgent.sendReliableMessage(); + LLIMModel::instance().sendTypingState(mSessionUUID, mOtherParticipantUUID, typing); } + void LLFloaterIMPanel::processIMTyping(const LLIMInfo* im_info, BOOL typing) { if (typing) @@ -2320,3 +2036,80 @@ bool LLFloaterIMPanel::onConfirmForceCloseError(const LLSD& notification, const } +std::map<LLUUID, LLIMFloater*> LLIMFloater::sIMFloaterMap; + +LLIMFloater::LLIMFloater(const LLUUID& session_id, + const std::string title, + EInstantMessage dialog) +: mSessionID(session_id), + mIndex(0) +{ + LLUICtrlFactory::getInstance()->buildFloater(this, "floater_im_session.xml"); + sIMFloaterMap[mSessionID] = this; + + setTitle(title); +} + +LLIMFloater::~LLIMFloater() +{ + sIMFloaterMap.erase(mSessionID); +} + + +void LLIMFloater::show(const LLUUID& session_id, S32 center_x) +{ + + LLIMFloater* floater = get_if_there(sIMFloaterMap, session_id, (LLIMFloater*)NULL); + + if (floater == NULL) + { + floater = new LLIMFloater(session_id, LLIMModel::instance().getName(session_id), IM_NOTHING_SPECIAL); + } + + //hide all + for (std::map<LLUUID, LLIMFloater*>::iterator iter = sIMFloaterMap.begin(); + iter != sIMFloaterMap.end(); ++iter) + { + LLIMFloater* floater = (*iter).second; + floater->setVisible(false); + } + + floater->setVisibleAndFrontmost(true); + + floater->updateMessages(session_id); + + floater->translate(center_x - floater->getRect().getCenterX(), gFloaterView->getRect().mBottom - floater->getRect().mBottom); + +} + +void LLIMFloater::updateMessages(const LLUUID& session_id) +{ + + LLTextEditor* text_editor = getChild<LLTextEditor>("im_text", true, false); + + if (!text_editor) + { + llwarns << "Text editor not found! " << llendl; + return; + } + + std::list<LLSD> messages = LLIMModel::instance().getMessages(mSessionID, mIndex); + + if (messages.size()) + { + std::ostringstream message; + std::list<LLSD>::const_reverse_iterator iter = messages.rbegin(); + std::list<LLSD>::const_reverse_iterator iter_end = messages.rend(); + for (; iter != iter_end; ++iter) + { + LLSD msg = *iter; + + message << msg["from"].asString() << " : " << msg["time"].asString() << "\n " << msg["message"].asString() << "\n"; + + mIndex = msg["index"].asInteger(); + } + + text_editor->setText(message.str()); + } + +} diff --git a/indra/newview/llimpanel.h b/indra/newview/llimpanel.h index 7cd19d487247dc9406b3ffe1b9f2be63a5585fea..88f21864b551cd16c66daad0a09155ee643669d0 100644 --- a/indra/newview/llimpanel.h +++ b/indra/newview/llimpanel.h @@ -356,10 +356,28 @@ private: LLFrameTimer mLastKeystrokeTimer; void disableWhileSessionStarting(); +}; + + +class LLIMFloater : public LLFloater +{ +public: + LLIMFloater(const LLUUID& session_id, + const std::string title, + EInstantMessage dialog); - typedef std::map<LLUUID, LLStyleSP> styleMap; - static styleMap mStyleMap; + virtual ~LLIMFloater(); + + static void show(const LLUUID& session_id, S32 center_x); + void updateMessages(const LLUUID& session_id); + + static std::map<LLUUID, LLIMFloater*> sIMFloaterMap; + + LLUUID mSessionID; + U32 mIndex; }; + + #endif // LL_IMPANEL_H diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index bc98b609ec7cd040883e23758799a1bb9781b5cf..a31d7daff737631aa5cf1266c091eab65b92ce87 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -91,16 +91,494 @@ std::map<std::string,std::string> LLFloaterIM::sEventStringsMap; std::map<std::string,std::string> LLFloaterIM::sErrorStringsMap; std::map<std::string,std::string> LLFloaterIM::sForceCloseSessionMap; +std::map<LLUUID, LLIMModel::LLIMSession*> LLIMModel::sSessionsMap; + + + +void toast_callback(const LLSD& msg){ + + //we send notifications to reset counter also + if (msg["num_unread"].asInteger()) + { + LLSD args; + args["MESSAGE"] = msg["message"]; + args["TIME"] = msg["time"]; + args["FROM"] = msg["from"]; + + LLNotifications::instance().add("IMToast", args, LLSD(), boost::bind(&LLFloaterChatterBox::onOpen, LLFloaterChatterBox::getInstance(), msg["session_id"].asUUID())); + } +} + +LLIMModel::LLIMModel() +{ + addChangedCallback(toast_callback); +} + + +void LLIMModel::testMessages() +{ + static LLUUID bot1_id, bot1_session_id; + if (bot1_id.isNull()) bot1_id.generate(); + std::string from = "Bot1 TestLinden"; + bot1_session_id = LLIMMgr::computeSessionID(IM_NOTHING_SPECIAL, bot1_id); + newSession(bot1_session_id, from, IM_NOTHING_SPECIAL, bot1_id); + addMessage(bot1_session_id, from, "Test Message: Hi from testerbot land!"); + + LLUUID bot2_id; + std::string firstname[] = {"Roflcopter", "Joe"}; + std::string lastname[] = {"Linden", "Tester", "Resident", "Schmoe"}; + + S32 rand1 = ll_rand(sizeof firstname)/(sizeof firstname[0]); + S32 rand2 = ll_rand(sizeof lastname)/(sizeof lastname[0]); + + from = firstname[rand1] + " " + lastname[rand2]; + bot2_id.generate(from); + LLUUID bot2_session_id = LLIMMgr::computeSessionID(IM_NOTHING_SPECIAL, bot2_id); + newSession(bot2_session_id, from, IM_NOTHING_SPECIAL, bot2_id); + addMessage(bot2_session_id, from, "Test Message: Can I haz bear? "); + addMessage(bot2_session_id, from, "Test Message: OMGWTFBBQ."); +} + + +bool LLIMModel::newSession(LLUUID session_id, std::string name, EInstantMessage type, LLUUID other_participant_id) +{ + if (is_in_map(sSessionsMap, session_id)) + { + llwarns << "IM Session " << session_id << " already exists" << llendl; + return false; + } + + LLIMSession* session = new LLIMSession(name, type, other_participant_id); + sSessionsMap[session_id] = session; + + LLIMMgr::getInstance()->notifyObserverSessionAdded(session_id, name, other_participant_id); + + return true; + +} + +std::list<LLSD> LLIMModel::getMessages(LLUUID session_id, int index) +{ + std::list<LLSD> return_list; + + LLIMSession* session = get_if_there(sSessionsMap, session_id, (LLIMSession*)NULL); + + if (!session) + { + llwarns << "session " << session_id << "does not exist " << llendl; + return return_list; + } + + int i = session->mMsgs.size() - index; + + for (std::list<LLSD>::iterator iter = session->mMsgs.begin(); + iter != session->mMsgs.end() && i > 0; + iter++) + { + LLSD msg; + msg = *iter; + return_list.push_back(*iter); + i--; + } + + session->mNumUnread = 0; + + LLSD arg; + arg["session_id"] = session_id; + arg["num_unread"] = 0; + mChangedSignal(arg); + + // TODO: in the future is there a more efficient way to return these + return return_list; + +} + +bool LLIMModel::addToHistory(LLUUID session_id, std::string from, std::string utf8_text) { + + LLIMSession* session = get_if_there(sSessionsMap, session_id, (LLIMSession*)NULL); + + if (!session) + { + llwarns << "session " << session_id << "does not exist " << llendl; + return false; + } + + LLSD message; + message["from"] = from; + message["message"] = utf8_text; + message["time"] = LLLogChat::timestamp(false); //might want to add date separately + message["index"] = (LLSD::Integer)session->mMsgs.size(); + + session->mMsgs.push_front(message); + + return true; + +} + + +bool LLIMModel::addMessage(LLUUID session_id, std::string from, std::string utf8_text) { + + LLIMSession* session = get_if_there(sSessionsMap, session_id, (LLIMSession*)NULL); + + if (!session) + { + llwarns << "session " << session_id << "does not exist " << llendl; + return false; + } + + addToHistory(session_id, from, utf8_text); + + std::string agent_name; + gAgent.buildFullname(agent_name); + + session->mNumUnread++; + + // notify listeners + LLSD arg; + arg["session_id"] = session_id; + arg["num_unread"] = session->mNumUnread; + arg["message"] = utf8_text; + mChangedSignal(arg); + + return true; +} + + +const std::string& LLIMModel::getName(LLUUID session_id) +{ + LLIMSession* session = get_if_there(sSessionsMap, session_id, (LLIMSession*)NULL); + + if (!session) + { + llwarns << "session " << session_id << "does not exist " << llendl; + return LLStringUtil::null; + } + + return session->mName; +} + + +// TODO get rid of other participant ID +void LLIMModel::sendTypingState(LLUUID session_id, LLUUID other_participant_id, BOOL typing) +{ + std::string name; + gAgent.buildFullname(name); + + pack_instant_message( + gMessageSystem, + gAgent.getID(), + FALSE, + gAgent.getSessionID(), + other_participant_id, + name, + std::string("typing"), + IM_ONLINE, + (typing ? IM_TYPING_START : IM_TYPING_STOP), + session_id); + gAgent.sendReliableMessage(); +} + +void LLIMModel::sendLeaveSession(LLUUID session_id, LLUUID other_participant_id) +{ + if(session_id.notNull()) + { + std::string name; + gAgent.buildFullname(name); + pack_instant_message( + gMessageSystem, + gAgent.getID(), + FALSE, + gAgent.getSessionID(), + other_participant_id, + name, + LLStringUtil::null, + IM_ONLINE, + IM_SESSION_LEAVE, + session_id); + gAgent.sendReliableMessage(); + } +} + + + +void LLIMModel::sendMessage(const std::string& utf8_text, + const LLUUID& im_session_id, + const LLUUID& other_participant_id, + EInstantMessage dialog) +{ + std::string name; + bool sent = false; + gAgent.buildFullname(name); + + const LLRelationship* info = NULL; + info = LLAvatarTracker::instance().getBuddyInfo(other_participant_id); + + U8 offline = (!info || info->isOnline()) ? IM_ONLINE : IM_OFFLINE; + + if((offline == IM_OFFLINE) && (LLVoiceClient::getInstance()->isOnlineSIP(other_participant_id))) + { + // User is online through the OOW connector, but not with a regular viewer. Try to send the message via SLVoice. + sent = gVoiceClient->sendTextMessage(other_participant_id, utf8_text); + } + + if(!sent) + { + // Send message normally. + + // default to IM_SESSION_SEND unless it's nothing special - in + // which case it's probably an IM to everyone. + U8 new_dialog = dialog; + + if ( dialog != IM_NOTHING_SPECIAL ) + { + new_dialog = IM_SESSION_SEND; + } + pack_instant_message( + gMessageSystem, + gAgent.getID(), + FALSE, + gAgent.getSessionID(), + other_participant_id, + name.c_str(), + utf8_text.c_str(), + offline, + (EInstantMessage)new_dialog, + im_session_id); + gAgent.sendReliableMessage(); + } + + // If there is a mute list and this is not a group chat... + if ( LLMuteList::getInstance() ) + { + // ... the target should not be in our mute list for some message types. + // Auto-remove them if present. + switch( dialog ) + { + case IM_NOTHING_SPECIAL: + case IM_GROUP_INVITATION: + case IM_INVENTORY_OFFERED: + case IM_SESSION_INVITE: + case IM_SESSION_P2P_INVITE: + case IM_SESSION_CONFERENCE_START: + case IM_SESSION_SEND: // This one is marginal - erring on the side of hearing. + case IM_LURE_USER: + case IM_GODLIKE_LURE_USER: + case IM_FRIENDSHIP_OFFERED: + LLMuteList::getInstance()->autoRemove(other_participant_id, LLMuteList::AR_IM); + break; + default: ; // do nothing + } + } + + if((dialog == IM_NOTHING_SPECIAL) && + (other_participant_id.notNull())) + { + // Do we have to replace the /me's here? + std::string from; + gAgent.buildFullname(from); + LLIMModel::instance().addToHistory(im_session_id, from, utf8_text); + } + + // Add the recipient to the recent people list. + LLRecentPeople::instance().add(other_participant_id); +} + +boost::signals2::connection LLIMModel::addChangedCallback( boost::function<void (const LLSD& data)> cb ) +{ + return mChangedSignal.connect(cb); +} + +void session_starter_helper( + const LLUUID& temp_session_id, + const LLUUID& other_participant_id, + EInstantMessage im_type) +{ + LLMessageSystem *msg = gMessageSystem; + + msg->newMessageFast(_PREHASH_ImprovedInstantMessage); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + + msg->nextBlockFast(_PREHASH_MessageBlock); + msg->addBOOLFast(_PREHASH_FromGroup, FALSE); + msg->addUUIDFast(_PREHASH_ToAgentID, other_participant_id); + msg->addU8Fast(_PREHASH_Offline, IM_ONLINE); + msg->addU8Fast(_PREHASH_Dialog, im_type); + msg->addUUIDFast(_PREHASH_ID, temp_session_id); + msg->addU32Fast(_PREHASH_Timestamp, NO_TIMESTAMP); // no timestamp necessary + + std::string name; + gAgent.buildFullname(name); + + msg->addStringFast(_PREHASH_FromAgentName, name); + msg->addStringFast(_PREHASH_Message, LLStringUtil::null); + msg->addU32Fast(_PREHASH_ParentEstateID, 0); + msg->addUUIDFast(_PREHASH_RegionID, LLUUID::null); + msg->addVector3Fast(_PREHASH_Position, gAgent.getPositionAgent()); +} + +void start_deprecated_conference_chat( + const LLUUID& temp_session_id, + const LLUUID& creator_id, + const LLUUID& other_participant_id, + const LLSD& agents_to_invite) +{ + U8* bucket; + U8* pos; + S32 count; + S32 bucket_size; + + // *FIX: this could suffer from endian issues + count = agents_to_invite.size(); + bucket_size = UUID_BYTES * count; + bucket = new U8[bucket_size]; + pos = bucket; + + for(S32 i = 0; i < count; ++i) + { + LLUUID agent_id = agents_to_invite[i].asUUID(); + + memcpy(pos, &agent_id, UUID_BYTES); + pos += UUID_BYTES; + } + + session_starter_helper( + temp_session_id, + other_participant_id, + IM_SESSION_CONFERENCE_START); + + gMessageSystem->addBinaryDataFast( + _PREHASH_BinaryBucket, + bucket, + bucket_size); + + gAgent.sendReliableMessage(); + + delete[] bucket; +} + +class LLStartConferenceChatResponder : public LLHTTPClient::Responder +{ +public: + LLStartConferenceChatResponder( + const LLUUID& temp_session_id, + const LLUUID& creator_id, + const LLUUID& other_participant_id, + const LLSD& agents_to_invite) + { + mTempSessionID = temp_session_id; + mCreatorID = creator_id; + mOtherParticipantID = other_participant_id; + mAgents = agents_to_invite; + } + + virtual void error(U32 statusNum, const std::string& reason) + { + //try an "old school" way. + if ( statusNum == 400 ) + { + start_deprecated_conference_chat( + mTempSessionID, + mCreatorID, + mOtherParticipantID, + mAgents); + } + + //else throw an error back to the client? + //in theory we should have just have these error strings + //etc. set up in this file as opposed to the IMMgr, + //but the error string were unneeded here previously + //and it is not worth the effort switching over all + //the possible different language translations + } + +private: + LLUUID mTempSessionID; + LLUUID mCreatorID; + LLUUID mOtherParticipantID; + + LLSD mAgents; +}; + +// Returns true if any messages were sent, false otherwise. +// Is sort of equivalent to "does the server need to do anything?" +bool LLIMModel::sendStartSession( + const LLUUID& temp_session_id, + const LLUUID& other_participant_id, + const std::vector<LLUUID>& ids, + EInstantMessage dialog) +{ + if ( dialog == IM_SESSION_GROUP_START ) + { + session_starter_helper( + temp_session_id, + other_participant_id, + dialog); + + switch(dialog) + { + case IM_SESSION_GROUP_START: + gMessageSystem->addBinaryDataFast( + _PREHASH_BinaryBucket, + EMPTY_BINARY_BUCKET, + EMPTY_BINARY_BUCKET_SIZE); + break; + default: + break; + } + gAgent.sendReliableMessage(); + + return true; + } + else if ( dialog == IM_SESSION_CONFERENCE_START ) + { + LLSD agents; + for (int i = 0; i < (S32) ids.size(); i++) + { + agents.append(ids[i]); + } + + //we have a new way of starting conference calls now + LLViewerRegion* region = gAgent.getRegion(); + if (region) + { + std::string url = region->getCapability( + "ChatSessionRequest"); + LLSD data; + data["method"] = "start conference"; + data["session-id"] = temp_session_id; + + data["params"] = agents; + + LLHTTPClient::post( + url, + data, + new LLStartConferenceChatResponder( + temp_session_id, + gAgent.getID(), + other_participant_id, + data["params"])); + } + else + { + start_deprecated_conference_chat( + temp_session_id, + gAgent.getID(), + other_participant_id, + agents); + } + } + + return false; +} + + + // // Helper Functions // -// returns true if a should appear before b -//static BOOL group_dictionary_sort( LLGroupData* a, LLGroupData* b ) -//{ -// return (LLStringUtil::compareDict( a->mName, b->mName ) < 0); -//} - class LLViewerChatterBoxInvitationAcceptResponder : public LLHTTPClient::Responder { @@ -613,26 +1091,6 @@ bool inviteUserResponse(const LLSD& notification, const LLSD& response) return false; } -// -// Public Static Member Functions -// - -// This is a helper function to determine what kind of im session -// should be used for the given agent. -// static -EInstantMessage LLIMMgr::defaultIMTypeForAgent(const LLUUID& agent_id) -{ - EInstantMessage type = IM_NOTHING_SPECIAL; - if(is_agent_friend(agent_id)) - { - if(LLAvatarTracker::instance().isBuddyOnline(agent_id)) - { - type = IM_SESSION_CONFERENCE_START; - } - } - return type; -} - // // Member Functions // @@ -725,7 +1183,9 @@ void LLIMMgr::addMessage( dialog, FALSE); - notifyObserverSessionAdded(floater->getSessionID(), name, other_participant_id); + + LLIMModel::instance().newSession(new_session_id, name, dialog, other_participant_id); + // When we get a new IM, and if you are a god, display a bit // of information about the source. This is to help liaisons @@ -746,6 +1206,7 @@ void LLIMMgr::addMessage( //<< "*** position: " << position << std::endl; floater->addHistoryLine(bonus_info.str(), LLUIColorTable::instance().getColor("SystemChatColor")); + LLIMModel::instance().addMessage(new_session_id, from, bonus_info.str()); } make_ui_sound("UISndNewIncomingIMSession"); @@ -765,6 +1226,8 @@ void LLIMMgr::addMessage( floater->addHistoryLine(msg, color, true, other_participant_id, from); // Insert linked name to front of message } + LLIMModel::instance().addMessage(new_session_id, from, msg); + if( !LLFloaterReg::instanceVisible("communicate") && !floater->getVisible()) { LLFloaterChatterBox* chat_floater = LLFloaterChatterBox::getInstance(); @@ -1652,7 +2115,7 @@ public: { saved = llformat("(Saved %s) ", formatted_time(timestamp).c_str()); } - std::string buffer = separator_string + saved + message.substr(message_offset); + std::string buffer = saved + message.substr(message_offset); BOOL is_this_agent = FALSE; if(from_id == gAgentID) diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h index 37dcd1593fe475e0504024ab798ab92c8ab13464..6a354dfe926622cf46b0d246397428654eb5690c 100644 --- a/indra/newview/llimview.h +++ b/indra/newview/llimview.h @@ -38,6 +38,7 @@ #include "llinstantmessage.h" #include "lluuid.h" #include "llmultifloater.h" +#include "llrecentpeople.h" class LLFloaterChatterBox; class LLUUID; @@ -45,6 +46,47 @@ class LLFloaterIMPanel; class LLFriendObserver; class LLFloaterIM; +class LLIMModel : public LLSingleton<LLIMModel> +{ +public: + + struct LLIMSession + { + LLIMSession(std::string name, EInstantMessage type, LLUUID other_participant_id) + :mName(name), mType(type), mNumUnread(0), mOtherPraticipantID(other_participant_id) {} + + std::string mName; + EInstantMessage mType; + LLUUID mOtherPraticipantID; + S32 mNumUnread; + std::list<LLSD> mMsgs; + }; + + + LLIMModel(); + + static std::map<LLUUID, LLIMSession*> sSessionsMap; //mapping session_id to session + boost::signals2::signal<void(const LLSD&)> mChangedSignal; + boost::signals2::connection addChangedCallback( boost::function<void (const LLSD& data)> cb ); + + bool newSession(LLUUID session_id, std::string name, EInstantMessage type, LLUUID other_participant_id); + std::list<LLSD> getMessages(LLUUID session_id, int index = 0); + bool addMessage(LLUUID session_id, std::string from, std::string utf8_text); + bool addToHistory(LLUUID session_id, std::string from, std::string utf8_text); + //used to get the name of the session, for use as the title + //currently just the other avatar name + const std::string& getName(LLUUID session_id); + + static void sendLeaveSession(LLUUID session_id, LLUUID other_participant_id); + static bool sendStartSession(const LLUUID& temp_session_id, const LLUUID& other_participant_id, + const std::vector<LLUUID>& ids, EInstantMessage dialog); + static void sendTypingState(LLUUID session_id, LLUUID other_participant_id, BOOL typing); + static void sendMessage(const std::string& utf8_text, const LLUUID& im_session_id, + const LLUUID& other_participant_id, EInstantMessage dialog); + + void testMessages(); +}; + class LLIMSessionObserver { public: @@ -53,8 +95,11 @@ public: virtual void sessionRemoved(const LLUUID& session_id) = 0; }; + class LLIMMgr : public LLSingleton<LLIMMgr> { + friend class LLIMModel; + public: enum EInvitationType { diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index af653238d35c7959df72ab6186e46ce2892cb0be..9d1b24ae11bab4a5ab2e385d79cbc4e60885c5c1 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -34,7 +34,7 @@ #include <utility> // for std::pair<> -#include "llinventoryview.h" +#include "llfloaterinventory.h" #include "llinventorybridge.h" #include "message.h" @@ -184,6 +184,13 @@ PermissionMask LLInvFVBridge::getPermissionMask() const return PERM_ALL; } +// virtual +LLAssetType::EType LLInvFVBridge::getPreferredType() const +{ + return LLAssetType::AT_NONE; +} + + // Folders don't have creation dates. time_t LLInvFVBridge::getCreationDate() const { @@ -195,7 +202,7 @@ BOOL LLInvFVBridge::isItemRemovable() { LLInventoryModel* model = getInventoryModel(); if(!model) return FALSE; - if(model->isObjectDescendentOf(mUUID, gAgent.getInventoryRootID())) + if(model->isObjectDescendentOf(mUUID, gInventory.getRootFolderID())) { return TRUE; } @@ -660,8 +667,8 @@ BOOL LLInvFVBridge::isAgentInventory() const { LLInventoryModel* model = getInventoryModel(); if(!model) return FALSE; - if(gAgent.getInventoryRootID() == mUUID) return TRUE; - return model->isObjectDescendentOf(mUUID, gAgent.getInventoryRootID()); + if(gInventory.getRootFolderID() == mUUID) return TRUE; + return model->isObjectDescendentOf(mUUID, gInventory.getRootFolderID()); } BOOL LLInvFVBridge::isItemPermissive() const @@ -1020,7 +1027,7 @@ PermissionMask LLItemBridge::getPermissionMask() const } return perm_mask; } - + const std::string& LLItemBridge::getDisplayName() const { if(mDisplayName.empty()) @@ -1062,10 +1069,11 @@ LLFontGL::StyleFlags LLItemBridge::getLabelStyle() const std::string LLItemBridge::getLabelSuffix() const { - // assume that this won't be called before string table is loaded - static const char* NO_COPY =LLTrans::getString("NO_COPY").c_str(); - static const char* NO_MOD = LLTrans::getString("NO_MOD").c_str(); - static const char* NO_XFER = LLTrans::getString("NO_XFER").c_str(); + // String table is loaded before login screen and inventory items are + // loaded after login, so LLTrans should be ready. + static std::string NO_COPY =LLTrans::getString("no_copy"); + static std::string NO_MOD = LLTrans::getString("no_modify"); + static std::string NO_XFER = LLTrans::getString("no_transfer"); std::string suffix; LLInventoryItem* item = getItem(); @@ -1075,26 +1083,26 @@ std::string LLItemBridge::getLabelSuffix() const if(LLAssetType::AT_CALLINGCARD != item->getType() && item->getPermissions().getOwner() == gAgent.getID()) { - BOOL copy = item->getPermissions().allowCopyBy(gAgent.getID()); - BOOL mod = item->getPermissions().allowModifyBy(gAgent.getID()); - BOOL xfer = item->getPermissions().allowOperationBy(PERM_TRANSFER, - gAgent.getID()); BOOL link = (item->getActualType() == LLAssetType::AT_LINK); - - const char* EMPTY = ""; const char* LINK = " (link)"; // *TODO: Seraph translate if (link) return LINK; - const char* scopy; - if(copy) scopy = EMPTY; - else scopy = NO_COPY; - const char* smod; - if(mod) smod = EMPTY; - else smod = NO_MOD; - const char* sxfer; - if(xfer) sxfer = EMPTY; - else sxfer = NO_XFER; - suffix = llformat("%s%s%s",scopy,smod,sxfer); + BOOL copy = item->getPermissions().allowCopyBy(gAgent.getID()); + if (!copy) + { + suffix += NO_COPY; + } + BOOL mod = item->getPermissions().allowModifyBy(gAgent.getID()); + if (!mod) + { + suffix += NO_MOD; + } + BOOL xfer = item->getPermissions().allowOperationBy(PERM_TRANSFER, + gAgent.getID()); + if (!xfer) + { + suffix += NO_XFER; + } } } return suffix; @@ -1269,7 +1277,7 @@ BOOL LLFolderBridge::isItemRemovable() return FALSE; } - if(!model->isObjectDescendentOf(mUUID, gAgent.getInventoryRootID())) + if(!model->isObjectDescendentOf(mUUID, gInventory.getRootFolderID())) { return FALSE; } @@ -2525,9 +2533,9 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, // everything in the active window so that we don't follow // the selection to its new location (which is very // annoying). - if (LLInventoryView::getActiveInventory()) + if (LLFloaterInventory::getActiveInventory()) { - LLInventoryPanel* active_panel = LLInventoryView::getActiveInventory()->getPanel(); + LLInventoryPanel* active_panel = LLFloaterInventory::getActiveInventory()->getPanel(); LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get()); if (active_panel && (panel != active_panel)) { @@ -3348,7 +3356,7 @@ void LLObjectBridge::performAction(LLFolderView* folder, LLInventoryModel* model LLUUID object_id = mUUID; LLViewerInventoryItem* item; item = (LLViewerInventoryItem*)gInventory.getItem(object_id); - if(item && gInventory.isObjectDescendentOf(object_id, gAgent.getInventoryRootID())) + if(item && gInventory.isObjectDescendentOf(object_id, gInventory.getRootFolderID())) { rez_attachment(item, NULL); } @@ -3815,7 +3823,7 @@ void LLOutfitObserver::done() } if(pid.isNull()) { - pid = gAgent.getInventoryRootID(); + pid = gInventory.getRootFolderID(); } LLUUID cat_id = gInventory.createNewCategory( @@ -3922,7 +3930,7 @@ void wear_outfit_by_name(const std::string& name) LLInventoryModel::cat_array_t cat_array; LLInventoryModel::item_array_t item_array; LLNameCategoryCollector has_name(name); - gInventory.collectDescendentsIf(gAgent.getInventoryRootID(), + gInventory.collectDescendentsIf(gInventory.getRootFolderID(), cat_array, item_array, LLInventoryModel::EXCLUDE_TRASH, @@ -4960,8 +4968,8 @@ BOOL LLWearableBridgeAction::isInTrash() const BOOL LLWearableBridgeAction::isAgentInventory() const { if(!mModel) return FALSE; - if(gAgent.getInventoryRootID() == mUUID) return TRUE; - return mModel->isObjectDescendentOf(mUUID, gAgent.getInventoryRootID()); + if(gInventory.getRootFolderID() == mUUID) return TRUE; + return mModel->isObjectDescendentOf(mUUID, gInventory.getRootFolderID()); } void LLWearableBridgeAction::wearOnAvatar() diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h index 016eb701d673aa2b379618ac1a9213608b04f328..a37b7969edfee7622a28956bab989efe6ba868ee 100644 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -38,7 +38,8 @@ #include "llviewercontrol.h" #include "llcallingcard.h" #include "llinventorymodel.h" -#include "llinventoryview.h" +#include "llfloaterinventory.h" +#include "llfoldervieweventlistener.h" enum EInventoryIcon { @@ -147,6 +148,7 @@ public: virtual const std::string& getName() const; virtual const std::string& getDisplayName() const; virtual PermissionMask getPermissionMask() const; + virtual LLAssetType::EType getPreferredType() const; virtual time_t getCreationDate() const; virtual LLFontGL::StyleFlags getLabelStyle() const { diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9cbe11f5c934edcabb63900ec418e73102fb5919 --- /dev/null +++ b/indra/newview/llinventoryfilter.cpp @@ -0,0 +1,631 @@ +/** +* @file llinventoryfilter.cpp +* @brief Support for filtering your inventory to only display a subset of the +* available items. +* +* $LicenseInfo:firstyear=2005&license=viewergpl$ +* +* Copyright (c) 2005-2009, Linden Research, Inc. +* +* Second Life Viewer Source Code +* The source code in this file ("Source Code") is provided by Linden Lab +* to you under the terms of the GNU General Public License, version 2.0 +* ("GPL"), unless you have obtained a separate licensing agreement +* ("Other License"), formally executed by you and Linden Lab. Terms of +* the GPL can be found in doc/GPL-license.txt in this distribution, or +* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 +* +* There are special exceptions to the terms and conditions of the GPL as +* it is applied to this Source Code. View the full text of the exception +* in the file doc/FLOSS-exception.txt in this software distribution, or +* online at +* http://secondlifegrid.net/programs/open_source/licensing/flossexception +* +* By copying, modifying or distributing this software, you acknowledge +* that you have read and understood your obligations described above, +* and agree to abide by those obligations. +* +* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO +* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, +* COMPLETENESS OR PERFORMANCE. +* $/LicenseInfo$ +*/ +#include "llviewerprecompiledheaders.h" + +#include "llinventoryfilter.h" + +// viewer includes +#include "llfoldervieweventlistener.h" +#include "llfolderviewitem.h" +#include "llinventorymodel.h" // gInventory.backgroundFetchActive() +#include "llviewercontrol.h" + +// linden library includes +#include "lltrans.h" + +///---------------------------------------------------------------------------- +/// Class LLInventoryFilter +///---------------------------------------------------------------------------- +LLInventoryFilter::LLInventoryFilter(const std::string& name) +: mName(name), + mModified(FALSE), + mNeedTextRebuild(TRUE) +{ + mFilterOps.mFilterTypes = 0xffffffff; + mFilterOps.mMinDate = time_min(); + mFilterOps.mMaxDate = time_max(); + mFilterOps.mHoursAgo = 0; + mFilterOps.mShowFolderState = SHOW_NON_EMPTY_FOLDERS; + mFilterOps.mPermissions = PERM_NONE; + + mOrder = SO_FOLDERS_BY_NAME; // This gets overridden by a pref immediately + + mSubStringMatchOffset = 0; + mFilterSubString.clear(); + mFilterGeneration = 0; + mMustPassGeneration = S32_MAX; + mMinRequiredGeneration = 0; + mFilterCount = 0; + mNextFilterGeneration = mFilterGeneration + 1; + + mLastLogoff = gSavedPerAccountSettings.getU32("LastLogoff"); + mFilterBehavior = FILTER_NONE; + + // copy mFilterOps into mDefaultFilterOps + markDefault(); +} + +LLInventoryFilter::~LLInventoryFilter() +{ +} + +BOOL LLInventoryFilter::check(LLFolderViewItem* item) +{ + time_t earliest; + + earliest = time_corrected() - mFilterOps.mHoursAgo * 3600; + if (mFilterOps.mMinDate > time_min() && mFilterOps.mMinDate < earliest) + { + earliest = mFilterOps.mMinDate; + } + else if (!mFilterOps.mHoursAgo) + { + earliest = 0; + } + LLFolderViewEventListener* listener = item->getListener(); + mSubStringMatchOffset = mFilterSubString.size() ? item->getSearchableLabel().find(mFilterSubString) : std::string::npos; + BOOL passed = (0x1 << listener->getInventoryType() & mFilterOps.mFilterTypes || listener->getInventoryType() == LLInventoryType::IT_NONE) + && (mFilterSubString.size() == 0 || mSubStringMatchOffset != std::string::npos) + && ((listener->getPermissionMask() & mFilterOps.mPermissions) == mFilterOps.mPermissions) + && (listener->getCreationDate() >= earliest && listener->getCreationDate() <= mFilterOps.mMaxDate); + return passed; +} + +const std::string LLInventoryFilter::getFilterSubString(BOOL trim) +{ + return mFilterSubString; +} + +std::string::size_type LLInventoryFilter::getStringMatchOffset() const +{ + return mSubStringMatchOffset; +} + +// has user modified default filter params? +BOOL LLInventoryFilter::isNotDefault() +{ + return mFilterOps.mFilterTypes != mDefaultFilterOps.mFilterTypes + || mFilterSubString.size() + || mFilterOps.mPermissions != mDefaultFilterOps.mPermissions + || mFilterOps.mMinDate != mDefaultFilterOps.mMinDate + || mFilterOps.mMaxDate != mDefaultFilterOps.mMaxDate + || mFilterOps.mHoursAgo != mDefaultFilterOps.mHoursAgo; +} + +BOOL LLInventoryFilter::isActive() +{ + return mFilterOps.mFilterTypes != 0xffffffff + || mFilterSubString.size() + || mFilterOps.mPermissions != PERM_NONE + || mFilterOps.mMinDate != time_min() + || mFilterOps.mMaxDate != time_max() + || mFilterOps.mHoursAgo != 0; +} + +BOOL LLInventoryFilter::isModified() +{ + return mModified; +} + +BOOL LLInventoryFilter::isModifiedAndClear() +{ + BOOL ret = mModified; + mModified = FALSE; + return ret; +} + +void LLInventoryFilter::setFilterTypes(U32 types) +{ + if (mFilterOps.mFilterTypes != types) + { + // keep current items only if no type bits getting turned off + BOOL fewer_bits_set = (mFilterOps.mFilterTypes & ~types); + BOOL more_bits_set = (~mFilterOps.mFilterTypes & types); + + mFilterOps.mFilterTypes = types; + if (more_bits_set && fewer_bits_set) + { + // neither less or more restrive, both simultaneously + // so we need to filter from scratch + setModified(FILTER_RESTART); + } + else if (more_bits_set) + { + // target is only one of all requested types so more type bits == less restrictive + setModified(FILTER_LESS_RESTRICTIVE); + } + else if (fewer_bits_set) + { + setModified(FILTER_MORE_RESTRICTIVE); + } + + } +} + +void LLInventoryFilter::setFilterSubString(const std::string& string) +{ + if (mFilterSubString != string) + { + // hitting BACKSPACE, for example + BOOL less_restrictive = mFilterSubString.size() >= string.size() && !mFilterSubString.substr(0, string.size()).compare(string); + // appending new characters + BOOL more_restrictive = mFilterSubString.size() < string.size() && !string.substr(0, mFilterSubString.size()).compare(mFilterSubString); + mFilterSubString = string; + LLStringUtil::toUpper(mFilterSubString); + LLStringUtil::trimHead(mFilterSubString); + + if (less_restrictive) + { + setModified(FILTER_LESS_RESTRICTIVE); + } + else if (more_restrictive) + { + setModified(FILTER_MORE_RESTRICTIVE); + } + else + { + setModified(FILTER_RESTART); + } + } +} + +void LLInventoryFilter::setFilterPermissions(PermissionMask perms) +{ + if (mFilterOps.mPermissions != perms) + { + // keep current items only if no perm bits getting turned off + BOOL fewer_bits_set = (mFilterOps.mPermissions & ~perms); + BOOL more_bits_set = (~mFilterOps.mPermissions & perms); + mFilterOps.mPermissions = perms; + + if (more_bits_set && fewer_bits_set) + { + setModified(FILTER_RESTART); + } + else if (more_bits_set) + { + // target must have all requested permission bits, so more bits == more restrictive + setModified(FILTER_MORE_RESTRICTIVE); + } + else if (fewer_bits_set) + { + setModified(FILTER_LESS_RESTRICTIVE); + } + } +} + +void LLInventoryFilter::setDateRange(time_t min_date, time_t max_date) +{ + mFilterOps.mHoursAgo = 0; + if (mFilterOps.mMinDate != min_date) + { + mFilterOps.mMinDate = min_date; + setModified(); + } + if (mFilterOps.mMaxDate != llmax(mFilterOps.mMinDate, max_date)) + { + mFilterOps.mMaxDate = llmax(mFilterOps.mMinDate, max_date); + setModified(); + } +} + +void LLInventoryFilter::setDateRangeLastLogoff(BOOL sl) +{ + if (sl && !isSinceLogoff()) + { + setDateRange(mLastLogoff, time_max()); + setModified(); + } + if (!sl && isSinceLogoff()) + { + setDateRange(0, time_max()); + setModified(); + } +} + +BOOL LLInventoryFilter::isSinceLogoff() +{ + return (mFilterOps.mMinDate == (time_t)mLastLogoff) && + (mFilterOps.mMaxDate == time_max()); +} + +void LLInventoryFilter::setHoursAgo(U32 hours) +{ + if (mFilterOps.mHoursAgo != hours) + { + // *NOTE: need to cache last filter time, in case filter goes stale + BOOL less_restrictive = (mFilterOps.mMinDate == time_min() && mFilterOps.mMaxDate == time_max() && hours > mFilterOps.mHoursAgo); + BOOL more_restrictive = (mFilterOps.mMinDate == time_min() && mFilterOps.mMaxDate == time_max() && hours <= mFilterOps.mHoursAgo); + mFilterOps.mHoursAgo = hours; + mFilterOps.mMinDate = time_min(); + mFilterOps.mMaxDate = time_max(); + if (less_restrictive) + { + setModified(FILTER_LESS_RESTRICTIVE); + } + else if (more_restrictive) + { + setModified(FILTER_MORE_RESTRICTIVE); + } + else + { + setModified(FILTER_RESTART); + } + } +} +void LLInventoryFilter::setShowFolderState(EFolderShow state) +{ + if (mFilterOps.mShowFolderState != state) + { + mFilterOps.mShowFolderState = state; + if (state == SHOW_NON_EMPTY_FOLDERS) + { + // showing fewer folders than before + setModified(FILTER_MORE_RESTRICTIVE); + } + else if (state == SHOW_ALL_FOLDERS) + { + // showing same folders as before and then some + setModified(FILTER_LESS_RESTRICTIVE); + } + else + { + setModified(); + } + } +} + +void LLInventoryFilter::setSortOrder(U32 order) +{ + if (mOrder != order) + { + mOrder = order; + setModified(); + } +} + +void LLInventoryFilter::markDefault() +{ + mDefaultFilterOps = mFilterOps; +} + +void LLInventoryFilter::resetDefault() +{ + mFilterOps = mDefaultFilterOps; + setModified(); +} + +void LLInventoryFilter::setModified(EFilterBehavior behavior) +{ + mModified = TRUE; + mNeedTextRebuild = TRUE; + mFilterGeneration = mNextFilterGeneration++; + + if (mFilterBehavior == FILTER_NONE) + { + mFilterBehavior = behavior; + } + else if (mFilterBehavior != behavior) + { + // trying to do both less restrictive and more restrictive filter + // basically means restart from scratch + mFilterBehavior = FILTER_RESTART; + } + + if (isNotDefault()) + { + // if not keeping current filter results, update last valid as well + switch(mFilterBehavior) + { + case FILTER_RESTART: + mMustPassGeneration = mFilterGeneration; + mMinRequiredGeneration = mFilterGeneration; + break; + case FILTER_LESS_RESTRICTIVE: + mMustPassGeneration = mFilterGeneration; + break; + case FILTER_MORE_RESTRICTIVE: + mMinRequiredGeneration = mFilterGeneration; + // must have passed either current filter generation (meaningless, as it hasn't been run yet) + // or some older generation, so keep the value + mMustPassGeneration = llmin(mMustPassGeneration, mFilterGeneration); + break; + default: + llerrs << "Bad filter behavior specified" << llendl; + } + } + else + { + // shortcut disabled filters to show everything immediately + mMinRequiredGeneration = 0; + mMustPassGeneration = S32_MAX; + } +} + +BOOL LLInventoryFilter::isFilterWith(LLInventoryType::EType t) +{ + return mFilterOps.mFilterTypes & (0x01 << t); +} + +std::string LLInventoryFilter::getFilterText() +{ + if (!mNeedTextRebuild) + { + return mFilterText; + } + + mNeedTextRebuild = FALSE; + std::string filtered_types; + std::string not_filtered_types; + BOOL filtered_by_type = FALSE; + BOOL filtered_by_all_types = TRUE; + S32 num_filter_types = 0; + mFilterText.clear(); + + if (isFilterWith(LLInventoryType::IT_ANIMATION)) + { + //filtered_types += " Animations,"; + filtered_types += LLTrans::getString("Animations"); + filtered_by_type = TRUE; + num_filter_types++; + } + else + { + //not_filtered_types += " Animations,"; + not_filtered_types += LLTrans::getString("Animations"); + + filtered_by_all_types = FALSE; + } + + if (isFilterWith(LLInventoryType::IT_CALLINGCARD)) + { + //filtered_types += " Calling Cards,"; + filtered_types += LLTrans::getString("Calling Cards"); + filtered_by_type = TRUE; + num_filter_types++; + } + else + { + //not_filtered_types += " Calling Cards,"; + not_filtered_types += LLTrans::getString("Calling Cards"); + filtered_by_all_types = FALSE; + } + + if (isFilterWith(LLInventoryType::IT_WEARABLE)) + { + //filtered_types += " Clothing,"; + filtered_types += LLTrans::getString("Clothing"); + filtered_by_type = TRUE; + num_filter_types++; + } + else + { + //not_filtered_types += " Clothing,"; + not_filtered_types += LLTrans::getString("Clothing"); + filtered_by_all_types = FALSE; + } + + if (isFilterWith(LLInventoryType::IT_GESTURE)) + { + //filtered_types += " Gestures,"; + filtered_types += LLTrans::getString("Gestures"); + filtered_by_type = TRUE; + num_filter_types++; + } + else + { + //not_filtered_types += " Gestures,"; + not_filtered_types += LLTrans::getString("Gestures"); + filtered_by_all_types = FALSE; + } + + if (isFilterWith(LLInventoryType::IT_LANDMARK)) + { + //filtered_types += " Landmarks,"; + filtered_types += LLTrans::getString("Landmarks"); + filtered_by_type = TRUE; + num_filter_types++; + } + else + { + //not_filtered_types += " Landmarks,"; + not_filtered_types += LLTrans::getString("Landmarks"); + filtered_by_all_types = FALSE; + } + + if (isFilterWith(LLInventoryType::IT_NOTECARD)) + { + //filtered_types += " Notecards,"; + filtered_types += LLTrans::getString("Notecards"); + filtered_by_type = TRUE; + num_filter_types++; + } + else + { + //not_filtered_types += " Notecards,"; + not_filtered_types += LLTrans::getString("Notecards"); + filtered_by_all_types = FALSE; + } + + if (isFilterWith(LLInventoryType::IT_OBJECT) && isFilterWith(LLInventoryType::IT_ATTACHMENT)) + { + //filtered_types += " Objects,"; + filtered_types += LLTrans::getString("Objects"); + filtered_by_type = TRUE; + num_filter_types++; + } + else + { + //not_filtered_types += " Objects,"; + not_filtered_types += LLTrans::getString("Objects"); + filtered_by_all_types = FALSE; + } + + if (isFilterWith(LLInventoryType::IT_LSL)) + { + //filtered_types += " Scripts,"; + filtered_types += LLTrans::getString("Scripts"); + filtered_by_type = TRUE; + num_filter_types++; + } + else + { + //not_filtered_types += " Scripts,"; + not_filtered_types += LLTrans::getString("Scripts"); + filtered_by_all_types = FALSE; + } + + if (isFilterWith(LLInventoryType::IT_SOUND)) + { + //filtered_types += " Sounds,"; + filtered_types += LLTrans::getString("Sounds"); + filtered_by_type = TRUE; + num_filter_types++; + } + else + { + //not_filtered_types += " Sounds,"; + not_filtered_types += LLTrans::getString("Sounds"); + filtered_by_all_types = FALSE; + } + + if (isFilterWith(LLInventoryType::IT_TEXTURE)) + { + //filtered_types += " Textures,"; + filtered_types += LLTrans::getString("Textures"); + filtered_by_type = TRUE; + num_filter_types++; + } + else + { + //not_filtered_types += " Textures,"; + not_filtered_types += LLTrans::getString("Textures"); + filtered_by_all_types = FALSE; + } + + if (isFilterWith(LLInventoryType::IT_SNAPSHOT)) + { + //filtered_types += " Snapshots,"; + filtered_types += LLTrans::getString("Snapshots"); + filtered_by_type = TRUE; + num_filter_types++; + } + else + { + //not_filtered_types += " Snapshots,"; + not_filtered_types += LLTrans::getString("Snapshots"); + filtered_by_all_types = FALSE; + } + + if (!gInventory.backgroundFetchActive() + && filtered_by_type + && !filtered_by_all_types) + { + mFilterText += " - "; + if (num_filter_types < 5) + { + mFilterText += filtered_types; + } + else + { + //mFilterText += "No "; + mFilterText += LLTrans::getString("No Filters"); + mFilterText += not_filtered_types; + } + // remove the ',' at the end + mFilterText.erase(mFilterText.size() - 1, 1); + } + + if (isSinceLogoff()) + { + //mFilterText += " - Since Logoff"; + mFilterText += LLTrans::getString("Since Logoff"); + } + return mFilterText; +} + +void LLInventoryFilter::toLLSD(LLSD& data) +{ + data["filter_types"] = (LLSD::Integer)getFilterTypes(); + data["min_date"] = (LLSD::Integer)getMinDate(); + data["max_date"] = (LLSD::Integer)getMaxDate(); + data["hours_ago"] = (LLSD::Integer)getHoursAgo(); + data["show_folder_state"] = (LLSD::Integer)getShowFolderState(); + data["permissions"] = (LLSD::Integer)getFilterPermissions(); + data["substring"] = (LLSD::String)getFilterSubString(); + data["sort_order"] = (LLSD::Integer)getSortOrder(); + data["since_logoff"] = (LLSD::Boolean)isSinceLogoff(); +} + +void LLInventoryFilter::fromLLSD(LLSD& data) +{ + if(data.has("filter_types")) + { + setFilterTypes((U32)data["filter_types"].asInteger()); + } + + if(data.has("min_date") && data.has("max_date")) + { + setDateRange(data["min_date"].asInteger(), data["max_date"].asInteger()); + } + + if(data.has("hours_ago")) + { + setHoursAgo((U32)data["hours_ago"].asInteger()); + } + + if(data.has("show_folder_state")) + { + setShowFolderState((EFolderShow)data["show_folder_state"].asInteger()); + } + + if(data.has("permissions")) + { + setFilterPermissions((PermissionMask)data["permissions"].asInteger()); + } + + if(data.has("substring")) + { + setFilterSubString(std::string(data["substring"].asString())); + } + + if(data.has("sort_order")) + { + setSortOrder((U32)data["sort_order"].asInteger()); + } + + if(data.has("since_logoff")) + { + setDateRangeLastLogoff((bool)data["since_logoff"].asBoolean()); + } +} diff --git a/indra/newview/llinventoryfilter.h b/indra/newview/llinventoryfilter.h new file mode 100644 index 0000000000000000000000000000000000000000..7c5f6681cfb497fbc5674828f5ac39935f9de853 --- /dev/null +++ b/indra/newview/llinventoryfilter.h @@ -0,0 +1,150 @@ +/** +* @file llinventoryfilter.h +* @brief Support for filtering your inventory to only display a subset of the +* available items. +* +* $LicenseInfo:firstyear=2005&license=viewergpl$ +* +* Copyright (c) 2005-2009, Linden Research, Inc. +* +* Second Life Viewer Source Code +* The source code in this file ("Source Code") is provided by Linden Lab +* to you under the terms of the GNU General Public License, version 2.0 +* ("GPL"), unless you have obtained a separate licensing agreement +* ("Other License"), formally executed by you and Linden Lab. Terms of +* the GPL can be found in doc/GPL-license.txt in this distribution, or +* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 +* +* There are special exceptions to the terms and conditions of the GPL as +* it is applied to this Source Code. View the full text of the exception +* in the file doc/FLOSS-exception.txt in this software distribution, or +* online at +* http://secondlifegrid.net/programs/open_source/licensing/flossexception +* +* By copying, modifying or distributing this software, you acknowledge +* that you have read and understood your obligations described above, +* and agree to abide by those obligations. +* +* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO +* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, +* COMPLETENESS OR PERFORMANCE. +* $/LicenseInfo$ +*/ +#ifndef LLINVENTORYFILTER_H +#define LLINVENTORYFILTER_H + +// lots of includes here +#include "llinventorytype.h" +#include "llpermissionsflags.h" // PermissionsMask + +class LLFolderViewItem; + +class LLInventoryFilter +{ +public: + typedef enum e_folder_show + { + SHOW_ALL_FOLDERS, + SHOW_NON_EMPTY_FOLDERS, + SHOW_NO_FOLDERS + } EFolderShow; + + typedef enum e_filter_behavior + { + FILTER_NONE, // nothing to do, already filtered + FILTER_RESTART, // restart filtering from scratch + FILTER_LESS_RESTRICTIVE, // existing filtered items will certainly pass this filter + FILTER_MORE_RESTRICTIVE // if you didn't pass the previous filter, you definitely won't pass this one + } EFilterBehavior; + + static const U32 SO_DATE = 1; + static const U32 SO_FOLDERS_BY_NAME = 2; + static const U32 SO_SYSTEM_FOLDERS_TO_TOP = 4; + + LLInventoryFilter(const std::string& name); + virtual ~LLInventoryFilter(); + + void setFilterTypes(U32 types); + U32 getFilterTypes() const { return mFilterOps.mFilterTypes; } + + void setFilterSubString(const std::string& string); + const std::string getFilterSubString(BOOL trim = FALSE); + + void setFilterPermissions(PermissionMask perms); + PermissionMask getFilterPermissions() const { return mFilterOps.mPermissions; } + + void setDateRange(time_t min_date, time_t max_date); + void setDateRangeLastLogoff(BOOL sl); + time_t getMinDate() const { return mFilterOps.mMinDate; } + time_t getMaxDate() const { return mFilterOps.mMaxDate; } + + void setHoursAgo(U32 hours); + U32 getHoursAgo() const { return mFilterOps.mHoursAgo; } + + void setShowFolderState( EFolderShow state); + EFolderShow getShowFolderState() { return mFilterOps.mShowFolderState; } + + void setSortOrder(U32 order); + U32 getSortOrder() { return mOrder; } + + BOOL check(LLFolderViewItem* item); + std::string::size_type getStringMatchOffset() const; + BOOL isActive(); + BOOL isNotDefault(); + BOOL isModified(); + BOOL isModifiedAndClear(); + BOOL isSinceLogoff(); + void clearModified() { mModified = FALSE; mFilterBehavior = FILTER_NONE; } + const std::string getName() const { return mName; } + std::string getFilterText(); + + void setFilterCount(S32 count) { mFilterCount = count; } + S32 getFilterCount() { return mFilterCount; } + void decrementFilterCount() { mFilterCount--; } + + void markDefault(); + void resetDefault(); + + BOOL isFilterWith(LLInventoryType::EType t); + + S32 getCurrentGeneration() const { return mFilterGeneration; } + S32 getMinRequiredGeneration() const { return mMinRequiredGeneration; } + S32 getMustPassGeneration() const { return mMustPassGeneration; } + + //RN: this is public to allow system to externally force a global refilter + void setModified(EFilterBehavior behavior = FILTER_RESTART); + + void toLLSD(LLSD& data); + void fromLLSD(LLSD& data); + +protected: + struct filter_ops + { + U32 mFilterTypes; + time_t mMinDate; + time_t mMaxDate; + U32 mHoursAgo; + EFolderShow mShowFolderState; + PermissionMask mPermissions; + }; + filter_ops mFilterOps; + filter_ops mDefaultFilterOps; + std::string::size_type mSubStringMatchOffset; + std::string mFilterSubString; + U32 mOrder; + const std::string mName; + S32 mFilterGeneration; + S32 mMustPassGeneration; + S32 mMinRequiredGeneration; + S32 mFilterCount; + S32 mNextFilterGeneration; + EFilterBehavior mFilterBehavior; + +private: + U32 mLastLogoff; + BOOL mModified; + BOOL mNeedTextRebuild; + std::string mFilterText; +}; + +#endif diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 5a14bdd55e3618d6a968fe9720acd80f68b3694b..2c281a46157db183038ba5a14688c6532ab4aba1 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -46,7 +46,7 @@ #include "llfloater.h" #include "llfocusmgr.h" #include "llinventorybridge.h" -#include "llinventoryview.h" +#include "llfloaterinventory.h" #include "llviewerinventory.h" #include "llviewermessage.h" #include "llviewerwindow.h" @@ -155,9 +155,20 @@ bool LLCanCache::operator()(LLInventoryCategory* cat, LLInventoryItem* item) LLInventoryModel gInventory; // Default constructor -LLInventoryModel::LLInventoryModel() : - mModifyMask(LLInventoryObserver::ALL), +LLInventoryModel::LLInventoryModel() +: mModifyMask(LLInventoryObserver::ALL), + mChangedItemIDs(), + mCategoryMap(), + mItemMap(), + mCategoryLock(), + mItemLock(), mLastItem(NULL), + mParentChildCategoryTree(), + mParentChildItemTree(), + mObservers(), + mRootFolderID(), + mLibraryRootFolderID(), + mLibraryOwnerID(), mIsAgentInvUsable(false) { } @@ -299,7 +310,7 @@ LLUUID LLInventoryModel::findCategoryUUIDForType(LLAssetType::EType t, bool crea LLUUID rv = findCatUUID(t); if(rv.isNull() && isInventoryUsable() && create_folder) { - LLUUID root_id = gAgent.getInventoryRootID(); + LLUUID root_id = gInventory.getRootFolderID(); if(root_id.notNull()) { rv = createNewCategory(root_id, t, LLStringUtil::null); @@ -312,7 +323,7 @@ LLUUID LLInventoryModel::findCategoryUUIDForType(LLAssetType::EType t, bool crea // preferred type. Returns LLUUID::null if not found. LLUUID LLInventoryModel::findCatUUID(LLAssetType::EType preferred_type) { - LLUUID root_id = gAgent.getInventoryRootID(); + LLUUID root_id = gInventory.getRootFolderID(); if(LLAssetType::AT_CATEGORY == preferred_type) { return root_id; @@ -469,7 +480,7 @@ void LLInventoryModel::collectLinkedItems(const LLUUID& id, { LLInventoryModel::cat_array_t cat_array; LLLinkedItemIDMatches is_linked_item_match(id); - collectDescendentsIf(gAgent.getInventoryRootID(), + collectDescendentsIf(gInventory.getRootFolderID(), cat_array, items, LLInventoryModel::INCLUDE_TRASH, @@ -500,7 +511,7 @@ void LLInventoryModel::appendPath(const LLUUID& id, std::string& path) bool LLInventoryModel::isInventoryUsable() { bool result = false; - if(gAgent.getInventoryRootID().notNull() && mIsAgentInvUsable) + if(gInventory.getRootFolderID().notNull() && mIsAgentInvUsable) { result = true; } @@ -1478,8 +1489,8 @@ void LLInventoryModel::startBackgroundFetch(const LLUUID& cat_id) if (!sFullFetchStarted) { sFullFetchStarted = TRUE; - sFetchQueue.push_back(gInventoryLibraryRoot); - sFetchQueue.push_back(gAgent.getInventoryRootID()); + sFetchQueue.push_back(gInventory.getLibraryRootFolderID()); + sFetchQueue.push_back(gInventory.getRootFolderID()); gIdleCallbacks.addFunction(&LLInventoryModel::backgroundFetch, NULL); } } @@ -2271,7 +2282,7 @@ void LLInventoryModel::buildParentChildMap() else { // it's a protected folder. - cat->setParent(gAgent.getInventoryRootID()); + cat->setParent(gInventory.getRootFolderID()); } cat->updateServer(TRUE); catsp = getUnlockedCatArray(cat->getParentUUID()); @@ -2371,7 +2382,7 @@ void LLInventoryModel::buildParentChildMap() } } - const LLUUID& agent_inv_root_id = gAgent.getInventoryRootID(); + LLUUID agent_inv_root_id = gInventory.getRootFolderID(); if (agent_inv_root_id.notNull()) { cat_array_t* catsp = get_ptr_in_map(mParentChildCategoryTree, agent_inv_root_id); @@ -2821,7 +2832,7 @@ void LLInventoryModel::processUpdateInventoryFolder(LLMessageSystem* msg, gInventory.notifyObservers(); // *HACK: Do the 'show' logic for a new item in the inventory. - LLInventoryView* view = LLInventoryView::getActiveInventory(); + LLFloaterInventory* view = LLFloaterInventory::getActiveInventory(); if(view) { view->getPanel()->setSelection(lastfolder->getUUID(), TAKE_FOCUS_NO); @@ -3030,13 +3041,13 @@ void LLInventoryModel::processBulkUpdateInventory(LLMessageSystem* msg, void**) // The incoming inventory could span more than one BulkInventoryUpdate packet, // so record the transaction ID for this purchase, then wear all clothing // that comes in as part of that transaction ID. JC - if (LLInventoryView::sWearNewClothing) + if (LLFloaterInventory::sWearNewClothing) { - LLInventoryView::sWearNewClothingTransactionID = tid; - LLInventoryView::sWearNewClothing = FALSE; + LLFloaterInventory::sWearNewClothingTransactionID = tid; + LLFloaterInventory::sWearNewClothing = FALSE; } - if (tid == LLInventoryView::sWearNewClothingTransactionID) + if (tid == LLFloaterInventory::sWearNewClothingTransactionID) { count = wearable_ids.size(); for (i = 0; i < count; ++i) @@ -3054,7 +3065,7 @@ void LLInventoryModel::processBulkUpdateInventory(LLMessageSystem* msg, void**) gInventoryCallbacks.fire(cbinfo.mCallback, cbinfo.mInvID); } // Don't show the inventory. We used to call showAgentInventory here. - //LLInventoryView* view = LLInventoryView::getActiveInventory(); + //LLFloaterInventory* view = LLFloaterInventory::getActiveInventory(); //if(view) //{ // const BOOL take_keyboard_focus = FALSE; @@ -3064,10 +3075,10 @@ void LLInventoryModel::processBulkUpdateInventory(LLMessageSystem* msg, void**) // // HACK to open inventory offers that are accepted. This information // // really needs to flow through the instant messages and inventory // // transfer/update messages. - // if (LLInventoryView::sOpenNextNewItem) + // if (LLFloaterInventory::sOpenNextNewItem) // { // view->openSelected(); - // LLInventoryView::sOpenNextNewItem = FALSE; + // LLFloaterInventory::sOpenNextNewItem = FALSE; // } // // // restore keyboard focus @@ -3232,6 +3243,36 @@ void LLInventoryModel::removeItem(const LLUUID& item_id) } } +LLUUID LLInventoryModel::getRootFolderID() const +{ + return mRootFolderID; +} + +void LLInventoryModel::setRootFolderID(const LLUUID& val) +{ + mRootFolderID = val; +} + +LLUUID LLInventoryModel::getLibraryRootFolderID() const +{ + return mLibraryRootFolderID; +} + +void LLInventoryModel::setLibraryRootFolderID(const LLUUID& val) +{ + mLibraryRootFolderID = val; +} + +LLUUID LLInventoryModel::getLibraryOwnerID() const +{ + return mLibraryOwnerID; +} + +void LLInventoryModel::setLibraryOwnerID(const LLUUID& val) +{ + mLibraryOwnerID = val; +} + //---------------------------------------------------------------------------- // *NOTE: DEBUG functionality diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h index 46288700d26bc3863756c5a28f8bfbf966253be2..950e8866bbcc6bcf94f45f1e9c0dea4a087fe8c1 100644 --- a/indra/newview/llinventorymodel.h +++ b/indra/newview/llinventorymodel.h @@ -204,7 +204,7 @@ public: // Calling this method with an inventory item will either change // an existing item with a matching item_id, or will add the item // to the current inventory. Returns the change mask generated by - // the update. No notifcation will be sent to observers. This + // the update. No notification will be sent to observers. This // method will only generate network traffic if the item had to be // reparented. // *NOTE: In usage, you will want to perform cache accounting @@ -231,7 +231,7 @@ public: // delete a particular inventory object by ID. This will purge one // object from the internal data structures maintaining a - // cosistent internal state. No cache accounting, observer + // consistent internal state. No cache accounting, observer // notification, or server update is performed. Purges linked items. void deleteObject(const LLUUID& id); @@ -240,12 +240,12 @@ public: void purgeObject(const LLUUID& id); void purgeLinkedObjects(const LLUUID& id); - // This is a method which collects the descendents of the id + // This is a method which collects the descendants of the id // provided. If the category is not found, no action is // taken. This method goes through the long winded process of // removing server representation of folders and items while doing // cache accounting in a fairly efficient manner. This method does - // not notify observers (though maybe it shouldd...) + // not notify observers (though maybe it should...) void purgeDescendentsOf(const LLUUID& id); // This method optimally removes the referenced categories and @@ -394,6 +394,22 @@ public: static bool isEverythingFetched(); static void backgroundFetch(void*); // background fetch idle function static void incrBulkFetch(S16 fetching) { sBulkFetchCount+=fetching; if (sBulkFetchCount<0) sBulkFetchCount=0; } + + + // Data about the agent's root folder and root library folder + // are stored here, rather than in LLAgent where it used to be, because + // gInventory is a singleton and represents the agent's inventory. + // The "library" is actually the inventory of a special agent, + // usually Alexandria Linden. + LLUUID getRootFolderID() const; + LLUUID getLibraryOwnerID() const; + LLUUID getLibraryRootFolderID() const; + + // These are set during login with data from the server + void setRootFolderID(const LLUUID& id); + void setLibraryOwnerID(const LLUUID& id); + void setLibraryRootFolderID(const LLUUID& id); + protected: // Internal methods which add inventory and make sure that all of @@ -446,7 +462,7 @@ protected: item_array_t* getUnlockedItemArray(const LLUUID& id); protected: - // Varaibles used to track what has changed since the last notify. + // Variables used to track what has changed since the last notify. U32 mModifyMask; typedef std::set<LLUUID> changed_items_t; changed_items_t mChangedItemIDs; @@ -477,6 +493,11 @@ protected: typedef std::set<LLInventoryObserver*> observer_list_t; observer_list_t mObservers; + // Agent inventory folder information. + LLUUID mRootFolderID; + LLUUID mLibraryRootFolderID; + LLUUID mLibraryOwnerID; + // completing the fetch once per session should be sufficient static BOOL sBackgroundFetchActive; static BOOL sTimelyFetchPending; diff --git a/indra/newview/lljoystickbutton.cpp b/indra/newview/lljoystickbutton.cpp index 8e6889a37942e23c2698949fbcaa9b6cddb1b221..d63eebfcacde06d921e0ce5fc65b27af62394369 100644 --- a/indra/newview/lljoystickbutton.cpp +++ b/indra/newview/lljoystickbutton.cpp @@ -49,11 +49,11 @@ #include "llglheaders.h" -static LLDefaultWidgetRegistry::Register<LLJoystickAgentSlide> r1("joystick_slide"); -static LLDefaultWidgetRegistry::Register<LLJoystickAgentTurn> r2("joystick_turn"); -static LLDefaultWidgetRegistry::Register<LLJoystickCameraRotate> r3("joystick_rotate"); -static LLDefaultWidgetRegistry::Register<LLJoystickCameraZoom> r4("joystick_zoom"); -static LLDefaultWidgetRegistry::Register<LLJoystickCameraTrack> r5("joystick_track"); +static LLDefaultChildRegistry::Register<LLJoystickAgentSlide> r1("joystick_slide"); +static LLDefaultChildRegistry::Register<LLJoystickAgentTurn> r2("joystick_turn"); +static LLDefaultChildRegistry::Register<LLJoystickCameraRotate> r3("joystick_rotate"); +static LLDefaultChildRegistry::Register<LLJoystickCameraZoom> r4("joystick_zoom"); +static LLDefaultChildRegistry::Register<LLJoystickCameraTrack> r5("joystick_track"); diff --git a/indra/newview/lljoystickbutton.h b/indra/newview/lljoystickbutton.h index 954a8c481d027eb8377d0825f72ae6aab5e09369..d0f63803ea623d5ce394da52cc1c2678640e927e 100644 --- a/indra/newview/lljoystickbutton.h +++ b/indra/newview/lljoystickbutton.h @@ -63,7 +63,7 @@ public: Params() : quadrant("quadrant", JQ_ORIGIN) { - label(""); + label = ""; } }; LLJoystick(const Params&); diff --git a/indra/newview/lllistbrowser.cpp b/indra/newview/lllistbrowser.cpp new file mode 100644 index 0000000000000000000000000000000000000000..edd8e9818f8e7ecc5625b31e140e26933d0d689d --- /dev/null +++ b/indra/newview/lllistbrowser.cpp @@ -0,0 +1,37 @@ +/** + * @file lllistbrowser.cpp + * @brief UI widget showing a search filter, list view, icon action buttons, + * and verb action buttons, as usually embedded in the side tray. + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ +#include "llviewerprecompiledheaders.h" + +#include "lllistbrowser.h" + +// TODO diff --git a/indra/newview/lllistbrowser.h b/indra/newview/lllistbrowser.h new file mode 100644 index 0000000000000000000000000000000000000000..bc9498c514f8047cd373979666fec86be60cea27 --- /dev/null +++ b/indra/newview/lllistbrowser.h @@ -0,0 +1,36 @@ +/** + * @file lllistbrowser.h + * @brief UI widget showing a search filter, list view, icon action buttons, + * and verb action buttons, as usually embedded in the side tray. + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ +#ifndef LLLISTBROWSER_H +#define LLLISTBROWSER_H + +#endif // LLLISTBROWSER_H diff --git a/indra/newview/lllistview.cpp b/indra/newview/lllistview.cpp new file mode 100644 index 0000000000000000000000000000000000000000..568655b500772fcea51a8da3af5251507beb60ed --- /dev/null +++ b/indra/newview/lllistview.cpp @@ -0,0 +1,73 @@ +/** + * @file lllistview.cpp + * @brief UI widget containing a scrollable, possibly hierarchical list of + * folders (LLListViewFolder) and items (LLListViewItem). + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ +#include "llviewerprecompiledheaders.h" + +#include "lllistview.h" + +#include "lltextbox.h" +#include "lluictrlfactory.h" // LLDefaultWidgetRegistry + +// linker optimizes this out on Windows until there is a real reference +// to this file +static LLDefaultChildRegistry::Register<LLListView> r("list_view"); + +LLListView::Params::Params() +: bg_color("bg_color"), + fg_selected_color("fg_selected_color"), + bg_selected_color("bg_selected_color") +{} + +LLListView::LLListView(const Params& p) +: LLUICtrl(p), + mLabel(NULL), + mBgColor(p.bg_color()), + mFgSelectedColor(p.fg_selected_color()), + mBgSelectedColor(p.bg_selected_color()) +{ + LLRect label_rect(0, 20, 300, 0); + LLTextBox::Params text_box_params; + text_box_params.rect(label_rect); + text_box_params.text("This is a list-view"); + mLabel = LLUICtrlFactory::create<LLTextBox>(text_box_params); + addChild(mLabel); +} + +LLListView::~LLListView() +{} + + +// placeholder for setting a property +void LLListView::setString(const std::string& s) +{ + mLabel->setValue( LLSD(s) ); +} diff --git a/indra/newview/lllistview.h b/indra/newview/lllistview.h new file mode 100644 index 0000000000000000000000000000000000000000..501c0c9e1fd8abe136b20e8ee820e3ca52f54077 --- /dev/null +++ b/indra/newview/lllistview.h @@ -0,0 +1,66 @@ +/** + * @file lllistview.h + * @brief UI widget containing a scrollable, possibly hierarchical list of + * folders (LLListViewFolder) and items (LLListViewItem). + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ +#ifndef LLLISTVIEW_H +#define LLLISTVIEW_H + +#include "llui.h" // for LLUIColor, *TODO: use more specific header +#include "lluictrl.h" + +class LLTextBox; + +class LLListView +: public LLUICtrl +{ +public: + struct Params : public LLInitParam::Block<Params, LLUICtrl::Params> + { + Optional<LLUIColor> bg_color, + fg_selected_color, + bg_selected_color; + Params(); + }; + LLListView(const Params& p); + virtual ~LLListView(); + + // placeholder for setting a property + void setString(const std::string& s); + +private: + // TODO: scroll container? + LLTextBox* mLabel; // just for testing + LLUIColor mBgColor; + LLUIColor mFgSelectedColor; + LLUIColor mBgSelectedColor; +}; + +#endif // LLLISTVIEW_H diff --git a/indra/newview/lllocationinputctrl.cpp b/indra/newview/lllocationinputctrl.cpp index 2cee9de1eba59cd1540198a497c18a4767d41109..c7ef6e16f789e176aec83d6d4d46d51225649102 100644 --- a/indra/newview/lllocationinputctrl.cpp +++ b/indra/newview/lllocationinputctrl.cpp @@ -167,7 +167,7 @@ private: //============================================================================ -static LLDefaultWidgetRegistry::Register<LLLocationInputCtrl> r("location_input"); +static LLDefaultChildRegistry::Register<LLLocationInputCtrl> r("location_input"); LLLocationInputCtrl::Params::Params() : add_landmark_image_enabled("add_landmark_image_enabled"), @@ -459,7 +459,7 @@ void LLLocationInputCtrl::updateAddLandmarkButton() LLInventoryModel::cat_array_t cats; LLInventoryModel::item_array_t items; LLIsAgentParcelLandmark is_current_parcel_landmark; - gInventory.collectDescendentsIf(gAgent.getInventoryRootID(), + gInventory.collectDescendentsIf(gInventory.getRootFolderID(), cats, items, LLInventoryModel::EXCLUDE_TRASH, diff --git a/indra/newview/llmenucommands.cpp b/indra/newview/llmenucommands.cpp index f0bfbef5658070774e4ec194a83e686d3fb30e26..c0225ebfcade63c59637e3b4ae3d0ba7606e34ee 100644 --- a/indra/newview/llmenucommands.cpp +++ b/indra/newview/llmenucommands.cpp @@ -51,7 +51,7 @@ #include "llfloaterdirectory.h" #include "llfloaterworldmap.h" #include "llgivemoney.h" -#include "llinventoryview.h" +#include "llfloaterinventory.h" #include "llnotify.h" #include "llstatusbar.h" #include "llimview.h" diff --git a/indra/newview/llmoveview.cpp b/indra/newview/llmoveview.cpp index 36ec2c779a182a03a7045d73ad2102a7d690f019..1ba8bdc37ffbe1cc933c6c39f8874351ea094418 100644 --- a/indra/newview/llmoveview.cpp +++ b/indra/newview/llmoveview.cpp @@ -38,12 +38,14 @@ #include "indra_constants.h" // Viewer includes + #include "llagent.h" -#include "llviewercontrol.h" #include "llbutton.h" -#include "llviewerwindow.h" +#include "llfloaterreg.h" #include "lljoystickbutton.h" #include "lluictrlfactory.h" +#include "llviewerwindow.h" +#include "llviewercontrol.h" // // Constants @@ -59,12 +61,10 @@ const F32 NUDGE_TIME = 0.25f; // in seconds // protected LLFloaterMove::LLFloaterMove(const LLSD& key) -: LLFloater() +: LLFloater(key) { - setIsChrome(TRUE); - const BOOL DONT_OPEN = FALSE; - LLUICtrlFactory::getInstance()->buildFloater(this,"floater_moveview.xml", DONT_OPEN); +// LLUICtrlFactory::getInstance()->buildFloater(this,"floater_moveview.xml", DONT_OPEN); } @@ -81,6 +81,9 @@ void LLFloaterMove::onClose(bool app_quitting) // virtual BOOL LLFloaterMove::postBuild() { + setIsChrome(TRUE); + + mForwardButton = getChild<LLJoystickAgentTurn>("forward btn"); mForwardButton->setHeldDownDelay(MOVE_BUTTON_DELAY); @@ -138,14 +141,20 @@ F32 LLFloaterMove::getYawRate( F32 time ) // protected static void LLFloaterMove::turnLeft(void *) { - F32 time = getInstance()->mTurnLeftButton->getHeldDownTime(); + LLFloaterMove* instance = LLFloaterReg::getTypedInstance<LLFloaterMove>("moveview"); + if(!instance) return; + + F32 time = instance->mTurnLeftButton->getHeldDownTime(); gAgent.moveYaw( getYawRate( time ) ); } // protected static void LLFloaterMove::turnRight(void *) { - F32 time = getInstance()->mTurnRightButton->getHeldDownTime(); + LLFloaterMove* instance = LLFloaterReg::getTypedInstance<LLFloaterMove>("moveview"); + if(!instance) return; + + F32 time = instance->mTurnRightButton->getHeldDownTime(); gAgent.moveYaw( -getYawRate( time ) ); } diff --git a/indra/newview/llmoveview.h b/indra/newview/llmoveview.h index 8d7cdc881d765a639d2063313a008cfa6a825fa0..de5d1ac43233d80affdd270f3d26ffc093f34d09 100644 --- a/indra/newview/llmoveview.h +++ b/indra/newview/llmoveview.h @@ -44,16 +44,15 @@ class LLJoystickAgentSlide; // Classes // class LLFloaterMove -: public LLFloater, - public LLFloaterSingleton<LLFloaterMove> +: public LLFloater { - friend class LLUISingleton<LLFloaterMove, VisibilityPolicy<LLFloater> >; - -protected: + friend class LLFloaterReg; + +private: LLFloaterMove(const LLSD& key); ~LLFloaterMove() {} - public: + /*virtual*/ void onOpen(const LLSD& key); /*virtual*/ void onClose(bool app_quitting); /*virtual*/ BOOL postBuild(); diff --git a/indra/newview/llnamebox.cpp b/indra/newview/llnamebox.cpp index b85c1c759dab01a7e979f095e84a97a9128eaa60..56648d3218c51fd321eddb2cecf9cb21472e2ce1 100644 --- a/indra/newview/llnamebox.cpp +++ b/indra/newview/llnamebox.cpp @@ -46,7 +46,7 @@ // statics std::set<LLNameBox*> LLNameBox::sInstances; -static LLDefaultWidgetRegistry::Register<LLNameBox> r("name_box"); +static LLDefaultChildRegistry::Register<LLNameBox> r("name_box"); LLNameBox::LLNameBox(const Params& p) diff --git a/indra/newview/llnameeditor.cpp b/indra/newview/llnameeditor.cpp index 7f9ba8ba5a954037d9e5e1143f2637fb092fbafd..ccb33c770a26894624c9fdb46ca04b8ad6bc9afb 100644 --- a/indra/newview/llnameeditor.cpp +++ b/indra/newview/llnameeditor.cpp @@ -43,7 +43,7 @@ #include "llstring.h" #include "llui.h" -static LLDefaultWidgetRegistry::Register<LLNameEditor> r("name_editor"); +static LLDefaultChildRegistry::Register<LLNameEditor> r("name_editor"); // statics std::set<LLNameEditor*> LLNameEditor::sInstances; diff --git a/indra/newview/llnamelistctrl.cpp b/indra/newview/llnamelistctrl.cpp index 722113928bcea1b4f5d7c07d4b5a994bd042423c..d7066cb1401680865022bb2f631fc901a5c95089 100644 --- a/indra/newview/llnamelistctrl.cpp +++ b/indra/newview/llnamelistctrl.cpp @@ -44,7 +44,7 @@ #include "llscrolllistcolumn.h" #include "llsdparam.h" -static LLDefaultWidgetRegistry::Register<LLNameListCtrl> r("name_list"); +static LLDefaultChildRegistry::Register<LLNameListCtrl> r("name_list"); void LLNameListCtrl::NameTypeNames::declareValues() { diff --git a/indra/newview/llnavigationbar.cpp b/indra/newview/llnavigationbar.cpp index cf1d9a5d86755fd52e579d706df0c9f82389b188..b4a6e63de81259c6e6a47da86d4176f3ad3b2675 100644 --- a/indra/newview/llnavigationbar.cpp +++ b/indra/newview/llnavigationbar.cpp @@ -231,7 +231,7 @@ BOOL LLNavigationBar::postBuild() search_btn->setClickedCallback(boost::bind(&LLNavigationBar::onSearchCommit, this)); // Load the location field context menu - mLocationContextMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_navbar.xml", gMenuHolder); + mLocationContextMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_navbar.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); if (!mLocationContextMenu) { llwarns << "Error loading navigation bar context menu" << llendl; diff --git a/indra/newview/llnetmap.cpp b/indra/newview/llnetmap.cpp index 1f623af434299c6cd000bf0e306b2035c2194d26..510933a331c29bc2fcfebeda14b221c08dd63cef 100644 --- a/indra/newview/llnetmap.cpp +++ b/indra/newview/llnetmap.cpp @@ -56,7 +56,7 @@ #include "llworld.h" #include "llworldmapview.h" // shared draw code -static LLDefaultWidgetRegistry::Register<LLNetMap> r1("net_map"); +static LLDefaultChildRegistry::Register<LLNetMap> r1("net_map"); const F32 MAP_SCALE_MIN = 64; const F32 MAP_SCALE_MID = 172; diff --git a/indra/newview/lloutputmonitorctrl.cpp b/indra/newview/lloutputmonitorctrl.cpp index 196a86b29c94d3fca90408775775fcd3a59281c0..60a86ed25390c16c5c689719d3e5f684374a380f 100644 --- a/indra/newview/lloutputmonitorctrl.cpp +++ b/indra/newview/lloutputmonitorctrl.cpp @@ -39,7 +39,7 @@ // viewer includes #include "llvoiceclient.h" -static LLDefaultWidgetRegistry::Register<LLOutputMonitorCtrl> r("output_monitor"); +static LLDefaultChildRegistry::Register<LLOutputMonitorCtrl> r("output_monitor"); // The defaults will be initialized in the constructor. LLColor4 LLOutputMonitorCtrl::sColorMuted; diff --git a/indra/newview/llpanelavatar.cpp b/indra/newview/llpanelavatar.cpp index ee592ac22c07e0942f0ffe3d4cec4d6139d78270..5c572b8fcdd056a9fdee37a57e74ecdefa27c9a4 100644 --- a/indra/newview/llpanelavatar.cpp +++ b/indra/newview/llpanelavatar.cpp @@ -115,7 +115,7 @@ BOOL LLDropTarget::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, return FALSE; } -static LLDefaultWidgetRegistry::Register<LLDropTarget> r("drop_target"); +static LLDefaultChildRegistry::Register<LLDropTarget> r("drop_target"); ////////////////////////////////////////////////////////////////////////// //----------------------------------------------------------------------------- diff --git a/indra/newview/llpanelclassified.cpp b/indra/newview/llpanelclassified.cpp index c328bcb7f99f04d8900574e13fdc6e4002110662..bd4625ab116d0337398c76b64c49342d470c1848 100644 --- a/indra/newview/llpanelclassified.cpp +++ b/indra/newview/llpanelclassified.cpp @@ -931,12 +931,12 @@ bool LLPanelClassified::confirmPublish(const LLSD& notification, const LLSD& res void LLPanelClassified::onClickTeleport(void* data) { LLPanelClassified* self = (LLPanelClassified*)data; - - if (!self->mPosGlobal.isExactlyZero()) + LLFloaterWorldMap* worldmap_instance = LLFloaterWorldMap::getInstance(); + + if (!self->mPosGlobal.isExactlyZero()&&worldmap_instance) { - gAgent.teleportViaLocation(self->mPosGlobal); - LLFloaterWorldMap::getInstance()->trackLocation(self->mPosGlobal); - + gAgent.teleportViaLocation(self->mPosGlobal); + worldmap_instance->trackLocation(self->mPosGlobal); self->sendClassifiedClickMessage("teleport"); } } @@ -946,9 +946,12 @@ void LLPanelClassified::onClickTeleport(void* data) void LLPanelClassified::onClickMap(void* data) { LLPanelClassified* self = (LLPanelClassified*)data; - LLFloaterWorldMap::getInstance()->trackLocation(self->mPosGlobal); - LLFloaterReg::showInstance("world_map", "center"); - + LLFloaterWorldMap* worldmap_instance = LLFloaterWorldMap::getInstance(); + if(worldmap_instance) + { + worldmap_instance->trackLocation(self->mPosGlobal); + LLFloaterReg::showInstance("world_map", "center"); + } self->sendClassifiedClickMessage("map"); } diff --git a/indra/newview/llpanelcontents.cpp b/indra/newview/llpanelcontents.cpp index b7ec485872f3a51007b35786c89e0c95cf710e6f..5da646497b3cc5835b87b50bf0a595ea6618f403 100644 --- a/indra/newview/llpanelcontents.cpp +++ b/indra/newview/llpanelcontents.cpp @@ -193,5 +193,5 @@ void LLPanelContents::onClickNewScript(void *userdata) void LLPanelContents::onClickPermissions(void *userdata) { LLPanelContents* self = (LLPanelContents*)userdata; - gFloaterView->getParentFloater(self)->addDependentFloater(LLFloaterBulkPermission::showInstance()); + gFloaterView->getParentFloater(self)->addDependentFloater(LLFloaterReg::showInstance("bulk_perms")); } diff --git a/indra/newview/llpanelgrouplandmoney.cpp b/indra/newview/llpanelgrouplandmoney.cpp index ea092645e7d3b08a383f58aa4576e40756ff83a3..39a9f231b24abd76323c590b3b8387e4923491bc 100644 --- a/indra/newview/llpanelgrouplandmoney.cpp +++ b/indra/newview/llpanelgrouplandmoney.cpp @@ -247,9 +247,12 @@ void LLPanelGroupLandMoney::impl::onMapButton() F64 global_z = gAgent.getPositionGlobal().mdV[VZ]; LLVector3d pos_global(global_x, global_y, global_z); - LLFloaterWorldMap::getInstance()->trackLocation(pos_global); - - LLFloaterReg::showInstance("world_map", "center"); + LLFloaterWorldMap* worldmap_instance = LLFloaterWorldMap::getInstance(); + if(worldmap_instance) + { + worldmap_instance->trackLocation(pos_global); + LLFloaterReg::showInstance("world_map", "center"); + } } bool LLPanelGroupLandMoney::impl::applyContribution() diff --git a/indra/newview/llpanelgroupnotices.cpp b/indra/newview/llpanelgroupnotices.cpp index 201cf5a0237d8696f9b2e41ca2c021b10327be54..0e75681afab083325942fc974ac26a0b51f4fc0f 100644 --- a/indra/newview/llpanelgroupnotices.cpp +++ b/indra/newview/llpanelgroupnotices.cpp @@ -39,7 +39,7 @@ #include "llinventory.h" #include "llviewerinventory.h" #include "llinventorymodel.h" -#include "llinventoryview.h" +#include "llfloaterinventory.h" #include "llagent.h" #include "lltooldraganddrop.h" @@ -105,7 +105,7 @@ protected: LLUUID mGroupID; }; -static LLDefaultWidgetRegistry::Register<LLGroupDropTarget> r("group_drop_target"); +static LLDefaultChildRegistry::Register<LLGroupDropTarget> r("group_drop_target"); LLGroupDropTarget::LLGroupDropTarget(const LLGroupDropTarget::Params& p) : LLView(p), diff --git a/indra/newview/llpanelland.cpp b/indra/newview/llpanelland.cpp index 92fe082ef2ff60e9cd7e41695a5ef870c2d0d513..bce5525a4066618bedb854b092a5650e2515f5dc 100644 --- a/indra/newview/llpanelland.cpp +++ b/indra/newview/llpanelland.cpp @@ -40,6 +40,7 @@ #include "llbutton.h" #include "llcheckboxctrl.h" #include "llfloaterland.h" +#include "llfloaterreg.h" #include "lltextbox.h" #include "llviewercontrol.h" #include "llviewerparcelmgr.h" @@ -262,7 +263,7 @@ void LLPanelLandInfo::onClickAbout(void*) LLViewerParcelMgr::getInstance()->selectParcelInRectangle(); } - LLFloaterLand::showInstance(); + LLFloaterReg::showInstance("about_land"); } void LLPanelLandInfo::onShowOwnersHelp(void* user_data) diff --git a/indra/newview/llpanellandmarks.cpp b/indra/newview/llpanellandmarks.cpp index 8c7e3e960a63cfe631807236a1d076fb1652d3c4..d1164dafb8d66af0e6b88bf9bac99046144d6c80 100644 --- a/indra/newview/llpanellandmarks.cpp +++ b/indra/newview/llpanellandmarks.cpp @@ -31,12 +31,14 @@ #include "llviewerprecompiledheaders.h" +#include "llpanellandmarks.h" + #include "llfloaterreg.h" #include "lllandmark.h" #include "llfloaterworldmap.h" +#include "llfoldervieweventlistener.h" #include "lllandmarklist.h" -#include "llpanellandmarks.h" #include "llsidetray.h" #include "lltabcontainer.h" #include "llworldmap.h" @@ -138,9 +140,10 @@ void LLLandmarksPanel::onShowOnMap() if (!landmark->getGlobalPos(landmark_global_pos)) return; - if (!landmark_global_pos.isExactlyZero()) + LLFloaterWorldMap* worldmap_instance = LLFloaterWorldMap::getInstance(); + if (!landmark_global_pos.isExactlyZero() && worldmap_instance) { - LLFloaterWorldMap::getInstance()->trackLocation(landmark_global_pos); + worldmap_instance->trackLocation(landmark_global_pos); LLFloaterReg::showInstance("world_map", "center"); } } diff --git a/indra/newview/llpanellandmarks.h b/indra/newview/llpanellandmarks.h index 76333e4d85d276188174605bb43446ec4187d17c..8889a99925b3178e57dfe0073f6bdf56823c7eb8 100644 --- a/indra/newview/llpanellandmarks.h +++ b/indra/newview/llpanellandmarks.h @@ -33,7 +33,7 @@ #ifndef LL_LLPANELLANDMARKS_H #define LL_LLPANELLANDMARKS_H -#include "llinventoryview.h" +#include "llfloaterinventory.h" #include "llinventorymodel.h" #include "llpanelplacestab.h" diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp index 3f9f44bbf599f39da43ec91ff2ab1d619022a7b4..b6141384f7666c9927ae84087d8dc331513fdb53 100644 --- a/indra/newview/llpanelpeople.cpp +++ b/indra/newview/llpanelpeople.cpp @@ -375,10 +375,10 @@ BOOL LLPanelPeople::postBuild() // Create menus. LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; registrar.add("People.Group.Plus.Action", boost::bind(&LLPanelPeople::onGroupPlusMenuItemClicked, this, _2)); - LLMenuGL* plus_menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_group_plus.xml", gMenuHolder); + LLMenuGL* plus_menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_group_plus.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); mGroupPlusMenuHandle = plus_menu->getHandle(); registrar.add("People.Group.Minus.Action", boost::bind(&LLPanelPeople::onGroupMinusMenuItemClicked, this, _2)); - LLMenuGL* minus_menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_group_minus.xml", gMenuHolder); + LLMenuGL* minus_menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_group_minus.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); mGroupMinusMenuHandle = minus_menu->getHandle(); // Perform initial update. diff --git a/indra/newview/llpanelpicks.cpp b/indra/newview/llpanelpicks.cpp index c32af2442321e27fc0f72e4a4a9883fafc32744a..f3adaded346aac03a9bc87a9ed810b3aab7ef6af 100644 --- a/indra/newview/llpanelpicks.cpp +++ b/indra/newview/llpanelpicks.cpp @@ -239,7 +239,7 @@ BOOL LLPanelPicks::postBuild(void) mCommitCallbackRegistrar.add("Pick.Map", boost::bind(onClickMap, this)); mCommitCallbackRegistrar.add("Pick.Delete", boost::bind(onClickDelete, this)); - mPopupMenu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>("menu_picks.xml", gMenuHolder); + mPopupMenu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>("menu_picks.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); return TRUE; } diff --git a/indra/newview/llpanelplace.cpp b/indra/newview/llpanelplace.cpp index d4c2f4b6b244352c0e450d449d99875d84f2fb8c..2cb7fd8c14e6d020769872376cd214087641fd95 100644 --- a/indra/newview/llpanelplace.cpp +++ b/indra/newview/llpanelplace.cpp @@ -355,16 +355,17 @@ void LLPanelPlace::onClickTeleport(void* data) } // LLFloater* parent_floaterp = (LLFloater*)self->getParent(); parent_viewp->setVisible(false); - if(self->mLandmarkAssetID.notNull()) + LLFloaterWorldMap* worldmap_instance = LLFloaterWorldMap::getInstance(); + if(self->mLandmarkAssetID.notNull() && worldmap_instance) { gAgent.teleportViaLandmark(self->mLandmarkAssetID); - LLFloaterWorldMap::getInstance()->trackLandmark(self->mLandmarkAssetID); + worldmap_instance->trackLandmark(self->mLandmarkAssetID); } - else if (!self->mPosGlobal.isExactlyZero()) + else if (!self->mPosGlobal.isExactlyZero() && worldmap_instance) { gAgent.teleportViaLocation(self->mPosGlobal); - LLFloaterWorldMap::getInstance()->trackLocation(self->mPosGlobal); + worldmap_instance->trackLocation(self->mPosGlobal); } } @@ -372,9 +373,11 @@ void LLPanelPlace::onClickTeleport(void* data) void LLPanelPlace::onClickMap(void* data) { LLPanelPlace* self = (LLPanelPlace*)data; - if (!self->mPosGlobal.isExactlyZero()) + LLFloaterWorldMap* worldmap_instance = LLFloaterWorldMap::getInstance(); + + if (!self->mPosGlobal.isExactlyZero() && worldmap_instance) { - LLFloaterWorldMap::getInstance()->trackLocation(self->mPosGlobal); + worldmap_instance->trackLocation(self->mPosGlobal); LLFloaterReg::showInstance("world_map", "center"); } } diff --git a/indra/newview/llpanelplaces.cpp b/indra/newview/llpanelplaces.cpp index 42b09a45c3e54013c3c9f2cd303f8d6a55eeaef0..f23d839708377f6b7a47277ab0c93dad94c0c7e6 100644 --- a/indra/newview/llpanelplaces.cpp +++ b/indra/newview/llpanelplaces.cpp @@ -216,8 +216,13 @@ void LLPanelPlaces::onShowOnMapButtonClicked() LLVector3d global_pos = gAgent.getPositionGlobal(); if (!global_pos.isExactlyZero()) { - LLFloaterWorldMap::getInstance()->trackLocation(global_pos); - LLFloaterReg::showInstance("world_map", "center"); + LLFloaterWorldMap* instance = LLFloaterWorldMap::getInstance(); + if(instance) + { + instance->trackLocation(global_pos); + LLFloaterReg::showInstance("world_map", "center"); + + } } } else diff --git a/indra/newview/llpreview.cpp b/indra/newview/llpreview.cpp index 676943ff87400cbee8fd4aff6ed8d0ecd21bdc61..9a987c8d7c52afa7c7d0cf0d478357c4a88b358b 100644 --- a/indra/newview/llpreview.cpp +++ b/indra/newview/llpreview.cpp @@ -51,7 +51,7 @@ #include "llagent.h" #include "llvoavatarself.h" #include "llselectmgr.h" -#include "llinventoryview.h" +#include "llfloaterinventory.h" #include "llviewerinventory.h" #include "llviewerwindow.h" #include "lltrans.h" diff --git a/indra/newview/llpreviewanim.cpp b/indra/newview/llpreviewanim.cpp index 6857d14fff80cc25e300f9fef7bae3bf7019b191..c4037c94fe1b0edf8af907e669f081158276074c 100644 --- a/indra/newview/llpreviewanim.cpp +++ b/indra/newview/llpreviewanim.cpp @@ -36,7 +36,7 @@ #include "llbutton.h" #include "llresmgr.h" #include "llinventory.h" -#include "llinventoryview.h" +#include "llfloaterinventory.h" #include "llvoavatarself.h" #include "llagent.h" // gAgent #include "llkeyframemotion.h" diff --git a/indra/newview/llpreviewgesture.cpp b/indra/newview/llpreviewgesture.cpp index dc6ee44936f4b804e4d36a3e8faa8514539d0009..ac08fd23a456964e920ebfd5a8f573a92c70619e 100644 --- a/indra/newview/llpreviewgesture.cpp +++ b/indra/newview/llpreviewgesture.cpp @@ -559,7 +559,7 @@ void LLPreviewGesture::addAnimations() PERM_ITEM_UNRESTRICTED, gAgent.getID(), gAgent.getGroupID()); - gInventory.collectDescendentsIf(gAgent.getInventoryRootID(), + gInventory.collectDescendentsIf(gInventory.getRootFolderID(), cats, items, LLInventoryModel::EXCLUDE_TRASH, @@ -604,7 +604,7 @@ void LLPreviewGesture::addSounds() PERM_ITEM_UNRESTRICTED, gAgent.getID(), gAgent.getGroupID()); - gInventory.collectDescendentsIf(gAgent.getInventoryRootID(), + gInventory.collectDescendentsIf(gInventory.getRootFolderID(), cats, items, LLInventoryModel::EXCLUDE_TRASH, diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp index 7c50bc59771dcc8d93211362938bf4fa55545eaf..7883b1ab064a91cbc2b8252adcc48a2d95c062e3 100644 --- a/indra/newview/llpreviewscript.cpp +++ b/indra/newview/llpreviewscript.cpp @@ -973,7 +973,7 @@ void LLPreviewLSL::loadAsset() const LLInventoryItem* item = gInventory.getItem(mItemUUID); BOOL is_library = item && !gInventory.isObjectDescendentOf(mItemUUID, - gAgent.getInventoryRootID()); + gInventory.getRootFolderID()); if(!item) { // do the more generic search. diff --git a/indra/newview/llpreviewsound.cpp b/indra/newview/llpreviewsound.cpp index 7e7be5b2c68cbb9ce7f641c6ce4d9ff0138d90d2..84f7562297cc55498a37e40d4f7235293060ed89 100644 --- a/indra/newview/llpreviewsound.cpp +++ b/indra/newview/llpreviewsound.cpp @@ -36,7 +36,7 @@ #include "llagent.h" // gAgent #include "llbutton.h" #include "llinventory.h" -#include "llinventoryview.h" +#include "llfloaterinventory.h" #include "lllineeditor.h" #include "llpreviewsound.h" #include "llresmgr.h" diff --git a/indra/newview/llpreviewtexture.cpp b/indra/newview/llpreviewtexture.cpp index 3204006e43bf52a1a738cbb99b626ba35899c9b2..d6ecb422550df230d4f764e241ef6db9744bbf1e 100644 --- a/indra/newview/llpreviewtexture.cpp +++ b/indra/newview/llpreviewtexture.cpp @@ -39,7 +39,7 @@ #include "llfilepicker.h" #include "llfloaterreg.h" #include "llimagetga.h" -#include "llinventoryview.h" +#include "llfloaterinventory.h" #include "llinventory.h" #include "llresmgr.h" #include "lltrans.h" diff --git a/indra/newview/llrootview.h b/indra/newview/llrootview.h index af9517f922c7448a04a5e72d470ec60170369bf1..f704fecdddd7f098983b94117a594711c32ca029 100644 --- a/indra/newview/llrootview.h +++ b/indra/newview/llrootview.h @@ -36,20 +36,16 @@ #include "llview.h" #include "lluictrlfactory.h" -class LLRootViewRegistry : public LLWidgetRegistry<LLRootViewRegistry> +class LLRootViewRegistry : public LLChildRegistry<LLRootViewRegistry> {}; class LLRootView : public LLView { public: + typedef LLRootViewRegistry child_registry_t; + LLRootView(const Params& p) : LLView(p) {} - - const widget_registry_t& getChildRegistry() const - { - // use default widget registry - return LLRootViewRegistry::instance(); - } }; #endif //LL_LLROOTVIEW_H diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index baa5f348494411d064d4935cf494af79ddc43f4a..b3b850441c7e81a014ed77e72b474ed61c06a628 100644 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -57,6 +57,7 @@ #include "llfloaterinspect.h" #include "llfloaterproperties.h" #include "llfloaterreporter.h" +#include "llfloaterreg.h" #include "llfloatertools.h" #include "llframetimer.h" #include "llhudeffecttrail.h" @@ -4842,8 +4843,12 @@ void LLSelectMgr::renderSilhouettes(BOOL for_hud) } if (mSelectedObjects->getNumNodes()) { - LLUUID inspect_item_id = LLFloaterInspect::getSelectedUUID(); - + LLFloaterInspect* inspect_instance = LLFloaterReg::getTypedInstance<LLFloaterInspect>("inspect"); + LLUUID inspect_item_id= LLUUID::null; + if(inspect_instance) + { + inspect_item_id = inspect_instance->getSelectedUUID(); + } for (S32 pass = 0; pass < 2; pass++) { for (LLObjectSelection::iterator iter = mSelectedObjects->begin(); @@ -5400,7 +5405,11 @@ void dialog_refresh_all() } LLFloaterProperties::dirtyAll(); - LLFloaterInspect::dirty(); + LLFloaterInspect* inspect_instance = LLFloaterReg::getTypedInstance<LLFloaterInspect>("inspect"); + if(inspect_instance) + { + inspect_instance->dirty(); + } } S32 get_family_count(LLViewerObject *parent) diff --git a/indra/newview/llsidetray.cpp b/indra/newview/llsidetray.cpp index 2871b16f5c3b3425679aa79fa909f6e97afcf8b2..b7c4c748912ba3aa33f55c5ae7bd0f543ef571be 100644 --- a/indra/newview/llsidetray.cpp +++ b/indra/newview/llsidetray.cpp @@ -52,7 +52,7 @@ using namespace std; static LLRootViewRegistry::Register<LLSideTray> t1("side_tray"); -static LLDefaultWidgetRegistry::Register<LLSideTrayTab> t2("sidetray_tab"); +static LLDefaultChildRegistry::Register<LLSideTrayTab> t2("sidetray_tab"); static const std::string COLLAPSED_NAME = "<<"; static const std::string EXPANDED_NAME = ">>"; @@ -103,7 +103,7 @@ LLSideTray* LLSideTray::getInstance() { if (!sInstance) { - sInstance = LLUICtrlFactory::createFromFile<LLSideTray>("panel_side_tray.xml",gViewerWindow->getRootView()); + sInstance = LLUICtrlFactory::createFromFile<LLSideTray>("panel_side_tray.xml",gViewerWindow->getRootView(), LLRootView::child_registry_t::instance()); } return sInstance; @@ -156,7 +156,7 @@ bool LLSideTrayTab::addChild(LLView* view, S32 tab_group) //virtual BOOL LLSideTrayTab::postBuild() { - LLPanel* title_panel = LLUICtrlFactory::getInstance()->createFromFile<LLPanel>("panel_side_tray_tab_caption.xml",this); + LLPanel* title_panel = LLUICtrlFactory::getInstance()->createFromFile<LLPanel>("panel_side_tray_tab_caption.xml",this, child_registry_t::instance()); string name = title_panel->getName(); LLPanel::addChild(title_panel); @@ -374,7 +374,7 @@ bool LLSideTray::selectTabByName (const std::string& name) LLButton* LLSideTray::createButton (const std::string& name,const std::string& image,LLUICtrl::commit_callback_t callback) { - static LLSideTray::Params sidetray_params(LLUICtrlFactory::getDefaultParams<LLSideTray::Params>()); + static LLSideTray::Params sidetray_params(LLUICtrlFactory::getDefaultParams<LLSideTray>()); LLButton::Params bparams; @@ -475,7 +475,7 @@ void LLSideTray::reflectCollapseChange() void LLSideTray::arrange () { - static LLSideTray::Params sidetray_params(LLUICtrlFactory::getDefaultParams<LLSideTray::Params>()); + static LLSideTray::Params sidetray_params(LLUICtrlFactory::getDefaultParams<LLSideTray>()); calcMaxSideBarWidth(); @@ -600,7 +600,7 @@ void LLSideTray::reshape (S32 width, S32 height, BOOL called_from_parent) if(!mActiveTab) return; - static LLSideTray::Params sidetray_params(LLUICtrlFactory::getDefaultParams<LLSideTray::Params>()); + static LLSideTray::Params sidetray_params(LLUICtrlFactory::getDefaultParams<LLSideTray>()); setPanelRect(); @@ -724,7 +724,7 @@ static const S32 fake_top_offset = 78; void LLSideTray::setPanelRect () { - static LLSideTray::Params sidetray_params(LLUICtrlFactory::getDefaultParams<LLSideTray::Params>()); + static LLSideTray::Params sidetray_params(LLUICtrlFactory::getDefaultParams<LLSideTray>()); const LLRect& parent_rect = gViewerWindow->getRootView()->getRect(); @@ -743,6 +743,6 @@ void LLSideTray::setPanelRect () S32 LLSideTray::getTrayWidth() { - static LLSideTray::Params sidetray_params(LLUICtrlFactory::getDefaultParams<LLSideTray::Params>()); + static LLSideTray::Params sidetray_params(LLUICtrlFactory::getDefaultParams<LLSideTray>()); return getRect().getWidth() - (sidetray_params.default_button_width + sidetray_params.default_button_margin); } diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 790669c07f2e159c7a74dbe2c628bd24375c7f8b..8b6124870df5941a650e46ff523426b300f2e84c 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -94,9 +94,6 @@ #include "llface.h" #include "llfeaturemanager.h" #include "llfirstuse.h" -#include "llfloateractivespeakers.h" -#include "llfloaterbeacons.h" -#include "llfloatercamera.h" #include "llfloaterchat.h" #include "llfloatergesture.h" #include "llfloaterhud.h" @@ -113,7 +110,7 @@ #include "llimagebmp.h" #include "llinventorybridge.h" #include "llinventorymodel.h" -#include "llinventoryview.h" +#include "llfloaterinventory.h" #include "llkeyboard.h" #include "llloginhandler.h" // gLoginHandler, SLURL support #include "llpanellogin.h" @@ -750,8 +747,10 @@ bool idle_startup() std::string msg = LLTrans::getString("LoginInitializingBrowser"); set_startup_status(0.03f, msg.c_str(), gAgent.mMOTD.c_str()); display_startup(); +#if !defined(LL_WINDOWS) || !defined(LL_DEBUG) + // This generates an error in debug mode on Windows LLViewerMedia::initBrowser(); - +#endif LLStartUp::setStartupState( STATE_LOGIN_SHOW ); return FALSE; } @@ -1466,8 +1465,7 @@ bool idle_startup() it = options[0].find("folder_id"); if(it != options[0].end()) { - gAgent.getInventoryRootID().set((*it).second); - //gInventory.mock(gAgent.getInventoryRootID()); + gInventory.setRootFolderID( LLUUID( (*it).second ) ); } } @@ -1555,7 +1553,7 @@ bool idle_startup() && gAgentSessionID.notNull() && gMessageSystem->mOurCircuitCode && first_sim.isOk() - && gAgent.getInventoryRootID().notNull()) + && gInventory.getRootFolderID().notNull()) { LLStartUp::setStartupState( STATE_WORLD_INIT ); } @@ -1724,21 +1722,21 @@ bool idle_startup() if (gSavedSettings.getBOOL("ShowCameraControls")) { - LLFloaterCamera::showInstance(); + LLFloaterReg::showInstance("camera"); } if (gSavedSettings.getBOOL("ShowMovementControls")) { - LLFloaterMove::showInstance(); + LLFloaterReg::showInstance("moveview"); } if (gSavedSettings.getBOOL("ShowActiveSpeakers")) { - LLFloaterActiveSpeakers::showInstance(); + LLFloaterReg::showInstance("active_speakers"); } if (gSavedSettings.getBOOL("BeaconAlwaysOn")) { - LLFloaterBeacons::showInstance(); + LLFloaterReg::showInstance("beacons"); } if (!gNoRender) @@ -1994,7 +1992,7 @@ bool idle_startup() it = options[0].find("folder_id"); if(it != options[0].end()) { - gInventoryLibraryRoot.set((*it).second); + gInventory.setLibraryRootFolderID( LLUUID( (*it).second ) ); } } options.clear(); @@ -2006,14 +2004,14 @@ bool idle_startup() it = options[0].find("agent_id"); if(it != options[0].end()) { - gInventoryLibraryOwner.set((*it).second); + gInventory.setLibraryOwnerID( LLUUID( (*it).second ) ); } } options.clear(); if(LLUserAuth::getInstance()->getOptions("inventory-skel-lib", options) - && gInventoryLibraryOwner.notNull()) + && gInventory.getLibraryOwnerID().notNull()) { - if(!gInventory.loadSkeleton(options, gInventoryLibraryOwner)) + if(!gInventory.loadSkeleton(options, gInventory.getLibraryOwnerID())) { LL_WARNS("AppInit") << "Problem loading inventory-skel-lib" << LL_ENDL; } @@ -2087,10 +2085,9 @@ bool idle_startup() // Either we want to show tutorial because this is the first login // to a Linden Help Island or the user quit with the tutorial // visible. JC - if (show_hud - || gSavedSettings.getBOOL("ShowTutorial")) + if (show_hud || gSavedSettings.getBOOL("ShowTutorial")) { - LLFloaterHUD::showHUD(); + LLFloaterReg::showInstance("hud", LLSD(), FALSE); } options.clear(); @@ -2465,9 +2462,11 @@ bool idle_startup() // Let the map know about the inventory. LLFloaterWorldMap* floater_world_map = LLFloaterWorldMap::getInstance(); - floater_world_map->observeInventory(&gInventory); - floater_world_map->observeFriends(); - + if(floater_world_map) + { + floater_world_map->observeInventory(&gInventory); + floater_world_map->observeFriends(); + } gViewerWindow->showCursor(); gViewerWindow->getWindow()->resetBusyCount(); gViewerWindow->getWindow()->setCursor(UI_CURSOR_ARROW); diff --git a/indra/newview/llstatusbar.cpp b/indra/newview/llstatusbar.cpp index 58af603569636133515bb7950ff24c6bb04a55de..bc90fe7adcf8c4660ef8508a118b45f49fc60791 100644 --- a/indra/newview/llstatusbar.cpp +++ b/indra/newview/llstatusbar.cpp @@ -47,7 +47,7 @@ #include "llfloaterregioninfo.h" #include "llfloaterscriptdebug.h" #include "llhudicon.h" -#include "llinventoryview.h" +#include "llfloaterinventory.h" #include "llkeyboard.h" #include "lllineeditor.h" #include "llmenugl.h" diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp index 3c9290aceab3f80fec26107045603f228f0a2201..243ac7803e6194b221b6cd77ca8e7fba70ce9ebd 100644 --- a/indra/newview/lltexturectrl.cpp +++ b/indra/newview/lltexturectrl.cpp @@ -45,9 +45,10 @@ #include "llfocusmgr.h" #include "llviewerimage.h" #include "llfolderview.h" +#include "llfoldervieweventlistener.h" #include "llinventory.h" #include "llinventorymodel.h" -#include "llinventoryview.h" +#include "llfloaterinventory.h" #include "lllineeditor.h" #include "llui.h" #include "llviewerinventory.h" @@ -342,7 +343,7 @@ BOOL LLFloaterTexturePicker::handleKeyHere(KEY key, MASK mask) { if (!root_folder->getCurSelectedItem()) { - LLFolderViewItem* itemp = root_folder->getItemByID(gAgent.getInventoryRootID()); + LLFolderViewItem* itemp = root_folder->getItemByID(gInventory.getRootFolderID()); if (itemp) { root_folder->setSelection(itemp, FALSE, FALSE); @@ -858,7 +859,7 @@ void LLFloaterTexturePicker::onTextureSelect( const LLTextureEntry& te ) /////////////////////////////////////////////////////////////////////// // LLTextureCtrl -static LLDefaultWidgetRegistry::Register<LLTextureCtrl> r("texture_picker"); +static LLDefaultChildRegistry::Register<LLTextureCtrl> r("texture_picker"); LLTextureCtrl::LLTextureCtrl(const LLTextureCtrl::Params& p) : LLUICtrl(p), diff --git a/indra/newview/lltoolbar.cpp b/indra/newview/lltoolbar.cpp index d27958c2ac03510eab68e8adb961b804393588cb..477e452907c3638d01d0695930f65b27880a37d6 100644 --- a/indra/newview/lltoolbar.cpp +++ b/indra/newview/lltoolbar.cpp @@ -52,7 +52,7 @@ #include "lluiconstants.h" #include "llvoavatarself.h" #include "lltooldraganddrop.h" -#include "llinventoryview.h" +#include "llfloaterinventory.h" #include "llfloaterchatterbox.h" #include "llfloaterfriends.h" #include "llfloatersnapshot.h" @@ -157,7 +157,7 @@ BOOL LLToolBar::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, LLButton* inventory_btn = getChild<LLButton>("inventory_btn"); if (!inventory_btn) return FALSE; - LLInventoryView* active_inventory = LLInventoryView::getActiveInventory(); + LLFloaterInventory* active_inventory = LLFloaterInventory::getActiveInventory(); LLRect button_screen_rect; inventory_btn->localRectToScreen(inventory_btn->getRect(),&button_screen_rect); @@ -173,7 +173,7 @@ BOOL LLToolBar::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, if (!(active_inventory && active_inventory->getVisible()) && mInventoryAutoOpenTimer.getElapsedTimeF32() > sInventoryAutoOpenTime) { - LLInventoryView::showAgentInventory(); + LLFloaterInventory::showAgentInventory(); } } else @@ -332,8 +332,11 @@ void LLToolBar::updateCommunicateList() communicate_button->addSeparator(ADD_TOP); communicate_button->add(getString("Redock Windows"), LLSD("redock"), ADD_TOP); communicate_button->addSeparator(ADD_TOP); - communicate_button->add(LLFloaterReg::getTypedInstance<LLFloaterMute>("mute")->getShortTitle(), LLSD("mute list"), ADD_TOP); - + LLFloaterMute* mute_instance = LLFloaterReg::getTypedInstance<LLFloaterMute>("mute"); + if(mute_instance) + { + communicate_button->add(mute_instance->getShortTitle(), LLSD("mute list"), ADD_TOP); + } std::set<LLHandle<LLFloater> >::const_iterator floater_handle_it; if (gIMMgr->getIMFloaterHandles().size() > 0) @@ -385,25 +388,29 @@ void LLToolBar::onClickCommunicate(LLUICtrl* ctrl, const LLSD& user_data) } else if (selected_option.asString() == "redock") { - LLFloaterChatterBox::getInstance()->addFloater(LLFloaterMyFriends::getInstance(), FALSE); - LLFloaterChatterBox::getInstance()->addFloater(LLFloaterChat::getInstance(), FALSE); - LLUUID session_to_show; - - std::set<LLHandle<LLFloater> >::const_iterator floater_handle_it; - for(floater_handle_it = gIMMgr->getIMFloaterHandles().begin(); floater_handle_it != gIMMgr->getIMFloaterHandles().end(); ++floater_handle_it) + LLFloaterChatterBox* chatterbox_instance = LLFloaterChatterBox::getInstance(); + if(chatterbox_instance) { - LLFloater* im_floaterp = floater_handle_it->get(); - if (im_floaterp) + chatterbox_instance->addFloater(LLFloaterMyFriends::getInstance(), FALSE); + chatterbox_instance->addFloater(LLFloaterChat::getInstance(), FALSE); + + LLUUID session_to_show; + + std::set<LLHandle<LLFloater> >::const_iterator floater_handle_it; + for(floater_handle_it = gIMMgr->getIMFloaterHandles().begin(); floater_handle_it != gIMMgr->getIMFloaterHandles().end(); ++floater_handle_it) { - if (im_floaterp->isFrontmost()) + LLFloater* im_floaterp = floater_handle_it->get(); + if (im_floaterp) { - session_to_show = ((LLFloaterIMPanel*)im_floaterp)->getSessionID(); + if (im_floaterp->isFrontmost()) + { + session_to_show = ((LLFloaterIMPanel*)im_floaterp)->getSessionID(); + } + chatterbox_instance->addFloater(im_floaterp, FALSE); } - LLFloaterChatterBox::getInstance()->addFloater(im_floaterp, FALSE); } + LLFloaterReg::showInstance("communicate", session_to_show); } - - LLFloaterReg::showInstance("communicate", session_to_show); } else if (selected_option.asString() == "mute list") { diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp index 0c0253a76a273ee9fe6b08f6e0b2367c5719ae50..72ed8f810823932862b504be29ee3b95727559a5 100644 --- a/indra/newview/lltooldraganddrop.cpp +++ b/indra/newview/lltooldraganddrop.cpp @@ -51,7 +51,7 @@ #include "llhudmanager.h" #include "llinventorybridge.h" #include "llinventorymodel.h" -#include "llinventoryview.h" +#include "llfloaterinventory.h" #include "llmutelist.h" #include "llnotify.h" #include "llpreviewnotecard.h" diff --git a/indra/newview/lltoolpie.cpp b/indra/newview/lltoolpie.cpp index a89e79c8b80422beac49f323c8fe3dbbb065a104..c71ed5ae47f4f1a91ebe8d7ff8e0d553cd124c22 100644 --- a/indra/newview/lltoolpie.cpp +++ b/indra/newview/lltoolpie.cpp @@ -44,6 +44,7 @@ #include "llfirstuse.h" #include "llfloateravatarinfo.h" #include "llfloaterland.h" +#include "llfloaterreg.h" #include "llfloaterscriptdebug.h" #include "llhoverview.h" #include "llhudeffecttrail.h" @@ -142,7 +143,7 @@ BOOL LLToolPie::pickLeftMouseDownCallback() else { // not selling passes, get info - LLFloaterLand::showInstance(); + LLFloaterReg::showInstance("about_land"); } } @@ -425,7 +426,7 @@ void LLToolPie::selectionPropertiesReceived() handle_give_money_dialog(); break; case CLICK_ACTION_OPEN: - handle_object_open(); + LLFloaterReg::showInstance("openobject"); break; default: break; diff --git a/indra/newview/llurldispatcher.cpp b/indra/newview/llurldispatcher.cpp index 6c8e7e1f69aeb5c0a70e99290accf239e9f59256..acb7f927b6efa109e2556a24c0e441dc5bf5c8e0 100644 --- a/indra/newview/llurldispatcher.cpp +++ b/indra/newview/llurldispatcher.cpp @@ -36,11 +36,12 @@ // viewer includes #include "llagent.h" // teleportViaLocation() #include "llcommandhandler.h" -#include "llfloaterurldisplay.h" #include "llfloaterdirectory.h" #include "llfloaterhtml.h" -#include "llfloaterworldmap.h" #include "llfloaterhtmlhelp.h" +#include "llfloaterreg.h" +#include "llfloaterurldisplay.h" +#include "llfloaterworldmap.h" #include "llpanellogin.h" #include "llslurl.h" #include "llstartup.h" // gStartupState @@ -201,8 +202,8 @@ bool LLURLDispatcherImpl::dispatchRegion(const std::string& url, bool right_mous S32 z = 0; LLURLSimString::parse(sim_string, ®ion_name, &x, &y, &z); - LLFloaterURLDisplay* url_displayp = LLFloaterURLDisplay::getInstance(LLSD()); - url_displayp->setName(region_name); + LLFloaterURLDisplay* url_displayp = LLFloaterReg::getTypedInstance<LLFloaterURLDisplay>("preview_url",LLSD()); + if(url_displayp) url_displayp->setName(region_name); // Request a region handle by name LLWorldMap::getInstance()->sendNamedRegionRequest(region_name, @@ -280,21 +281,26 @@ void LLURLDispatcherImpl::regionHandleCallback(U64 region_handle, const std::str LLVector3d global_pos = from_region_handle(region_handle); global_pos += LLVector3d(local_pos); gAgent.teleportViaLocation(global_pos); - LLFloaterWorldMap::getInstance()->trackLocation(global_pos); + LLFloaterWorldMap* instance = LLFloaterWorldMap::getInstance(); + if(instance) + { + instance->trackLocation(global_pos); + } } else { // display informational floater, allow user to click teleport btn - LLFloaterURLDisplay* url_displayp = LLFloaterURLDisplay::getInstance(LLSD()); - - - url_displayp->displayParcelInfo(region_handle, local_pos); - if(snapshot_id.notNull()) + LLFloaterURLDisplay* url_displayp = LLFloaterReg::getTypedInstance<LLFloaterURLDisplay>("preview_url",LLSD()); + if(url_displayp) { - url_displayp->setSnapshotDisplay(snapshot_id); + url_displayp->displayParcelInfo(region_handle, local_pos); + if(snapshot_id.notNull()) + { + url_displayp->setSnapshotDisplay(snapshot_id); + } + std::string locationString = llformat("%s %d, %d, %d", region_name.c_str(), x, y, z); + url_displayp->setLocationString(locationString); } - std::string locationString = llformat("%s %d, %d, %d", region_name.c_str(), x, y, z); - url_displayp->setLocationString(locationString); } } diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index 03c4915e66f3ea6a036735939f6ec64831042485..914f74ca788170db33af76b8f0274aa07948c486 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -39,28 +39,48 @@ #include "llcompilequeue.h" #include "llfloaterabout.h" +#include "llfloateractivespeakers.h" #include "llfloaterauction.h" #include "llfloateraddlandmark.h" #include "llfloateravatarinfo.h" +#include "llfloaterbeacons.h" +#include "llfloaterbulkpermission.h" #include "llfloaterbuildoptions.h" #include "llfloaterbump.h" +#include "llfloatercamera.h" #include "llfloaterchat.h" #include "llfloaterchatterbox.h" #include "llfloaterdirectory.h" +#include "llfloaterfonttest.h" +#include "llfloatergodtools.h" +#include "llfloaterhtmlcurrency.h" +#include "llfloaterhtmlhelp.h" +#include "llfloaterhud.h" +#include "llfloaterinspect.h" #include "llfloaterjoystick.h" #include "llfloaternotificationsconsole.h" #include "llfloaterlagmeter.h" +#include "llfloaterland.h" #include "llfloatermap.h" #include "llfloatermemleak.h" #include "llfloatermute.h" +#include "llfloaterobjectiminfo.h" +#include "llfloateropenobject.h" +#include "llfloaterperms.h" #include "llfloaterpreference.h" +#include "llfloaterregioninfo.h" #include "llfloatersnapshot.h" #include "llfloatersettingsdebug.h" +#include "llfloatertestlistview.h" +#include "llfloatertopobjects.h" #include "llfloatertools.h" #include "llfloateruipreview.h" +#include "llfloaterurldisplay.h" #include "llfloatervoicedevicesettings.h" #include "llfloaterworldmap.h" -#include "llinventoryview.h" +#include "llfloaterinventory.h" +#include "llmediaremotectrl.h" +#include "llmoveview.h" #include "llnearbychathistory.h" #include "llpreviewanim.h" @@ -72,6 +92,8 @@ #include "llpreviewtexture.h" #include "llfloaterminiinspector.h" +//class LLLLFloaterObjectIMInfo; + void LLViewerFloaterReg::registerFloaters() { LLFloaterReg::add("mini_inspector", "panel_mini_inspector.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMiniInspector>); @@ -82,9 +104,15 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("build", "floater_tools.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterTools>); LLFloaterReg::add("world_map", "floater_world_map.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterWorldMap>); LLFloaterReg::add("mini_map", "floater_map.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMap>); - LLFloaterReg::add("inventory", "floater_inventory.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLInventoryView>); + LLFloaterReg::add("inventory", "floater_inventory.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterInventory>); LLFloaterReg::add("add_landmark", "floater_add_landmark.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterAddLandmark>); LLFloaterReg::add("mute", "floater_mute.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMute>); + LLFloaterReg::add("about_land", "floater_about_land.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterLand>); + LLFloaterReg::add("perm_prefs", "floater_perm_prefs.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPerms>); + LLFloaterReg::add("region_info", "floater_region_info.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterRegionInfo>); + LLFloaterReg::add("preview_url", "floater_preview_url.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterURLDisplay>); + LLFloaterReg::add("font_test", "floater_font_test.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterFontTest>); + LLFloaterReg::add("mem_leaking", "floater_mem_leaking.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMemLeak>); LLFloaterReg::add("auction", "floater_auction.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterAuction>); LLFloaterReg::add("build_options", "floater_build_options.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterBuildOptions>); @@ -92,9 +120,25 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("notifications_console", "floater_notifications_console.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterNotificationConsole>); LLFloaterReg::add("settings_debug", "floater_settings_debug.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSettingsDebug>); LLFloaterReg::add("lagmeter", "floater_lagmeter.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterLagMeter>); + LLFloaterReg::add("moveview", "floater_moveview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMove>); + LLFloaterReg::add("active_speakers", "floater_active_speakers.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterActiveSpeakers>); + LLFloaterReg::add("beacons", "floater_beacons.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterBeacons>); + LLFloaterReg::add("bulk_perms", "floater_bulk_perms.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterBulkPermission>); + LLFloaterReg::add("camera", "floater_camera.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterCamera>); + LLFloaterReg::add("god_tools", "floater_god_tools.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterGodTools>); + LLFloaterReg::add("media_browser", "floater_media_browser.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMediaBrowser>); + LLFloaterReg::add("html_currency", "floater_html_simple.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterHtmlCurrency>); + LLFloaterReg::add("top_objects", "floater_top_objects.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterTopObjects>); + LLFloaterReg::add("inspect", "floater_inspect.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterInspect>); + LLFloaterReg::add("hud", "floater_hud.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterHUD>); + LLFloaterReg::add("openobject", "floater_openobject.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterOpenObject>); - LLFloaterReg::add("ui_preview", "floater_ui_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterUIPreview>); - LLFloaterReg::add("test_widgets", "floater_test_widgets.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloater>); + LLFloaterReg::add("ui_preview", "floater_ui_preview.xml", + &LLFloaterReg::build<LLFloaterUIPreview>); + LLFloaterReg::add("test_list_view", "floater_test_list_view.xml", + &LLFloaterReg::build<LLFloaterTestListView>); + LLFloaterReg::add("test_widgets", "floater_test_widgets.xml", + &LLFloaterReg::build<LLFloater>); LLFloaterReg::add("pref_joystick", "floater_joystick.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterJoystick>); LLFloaterReg::add("pref_voicedevicesettings", "floater_device_settings.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterVoiceDeviceSettings>); @@ -122,4 +166,10 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("preview_texture", "floater_preview_texture.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLPreviewTexture>, "preview"); LLFloaterReg::add("stats", "floater_stats.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloater>); + + LLObjectIMInfo::register_floater(); + // debug use only + LLFloaterReg::add("media_remote_ctrl", "floater_media_remote.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMediaRemoteCtrl>); + + // *NOTE: Please keep these alphabetized for easier merges } diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index 2c79e67ebcd5f9923074bb2a0869f8269e927bc5..54b0a4f5683af170f8c56b2e3eb42ddc71e71e21 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -45,7 +45,7 @@ #include "llgesturemgr.h" #include "llinventorybridge.h" -#include "llinventoryview.h" +#include "llfloaterinventory.h" #include "llviewerregion.h" #include "llviewerobjectlist.h" @@ -870,7 +870,7 @@ void menu_create_inventory_item(LLFolderView* folder, LLFolderBridge *bridge, co } else { - category = gInventory.createNewCategory(gAgent.getInventoryRootID(), LLAssetType::AT_NONE, LLStringUtil::null); + category = gInventory.createNewCategory(gInventory.getRootFolderID(), LLAssetType::AT_NONE, LLStringUtil::null); } gInventory.notifyObservers(); folder->setSelectionByID(category, TRUE); diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index ae7099d3829b5a842685322ea52d04d45d303b2a..70a6e24c8f310fd94db78c0fcd3a2b6435d7fdeb 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -87,14 +87,12 @@ #include "llfloateractivespeakers.h" #include "llfloateranimpreview.h" #include "llfloateravatartextures.h" -#include "llfloaterbeacons.h" #include "llfloaterbuildoptions.h" #include "llfloaterbump.h" #include "llfloaterbuy.h" #include "llfloaterbuycontents.h" #include "llfloaterbuycurrency.h" #include "llfloaterbuyland.h" -#include "llfloatercamera.h" #include "llfloaterchat.h" #include "llfloatercustomize.h" #include "llfloaterdaycycle.h" @@ -146,7 +144,7 @@ #include "llimagetga.h" #include "llinventorybridge.h" #include "llinventorymodel.h" -#include "llinventoryview.h" +#include "llfloaterinventory.h" #include "llkeyboard.h" #include "llpanellogin.h" #include "llmenucommands.h" @@ -500,23 +498,23 @@ void init_menus() /// /// Pie menus /// - gPieSelf = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>("menu_pie_self.xml", gMenuHolder); + gPieSelf = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>("menu_pie_self.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); // TomY TODO: what shall we do about these? gDetachScreenPieMenu = gMenuHolder->getChild<LLContextMenu>("Object Detach HUD", true); gDetachPieMenu = gMenuHolder->getChild<LLContextMenu>("Object Detach", true); - gPieAvatar = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>("menu_pie_avatar.xml", gMenuHolder); + gPieAvatar = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>("menu_pie_avatar.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); - gPieObject = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>("menu_pie_object.xml", gMenuHolder); + gPieObject = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>("menu_pie_object.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); gAttachScreenPieMenu = gMenuHolder->getChild<LLContextMenu>("Object Attach HUD"); gAttachPieMenu = gMenuHolder->getChild<LLContextMenu>("Object Attach"); gPieRate = gMenuHolder->getChild<LLContextMenu>("Rate Menu"); - gPieAttachment = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>("menu_pie_attachment.xml", gMenuHolder); + gPieAttachment = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>("menu_pie_attachment.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); - gPieLand = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>("menu_pie_land.xml", gMenuHolder); + gPieLand = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>("menu_pie_land.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); /// /// set up the colors @@ -544,7 +542,7 @@ void init_menus() { color = LLUIColorTable::instance().getColor( "MenuNonProductionBgColor" ); } - gMenuBarView = LLUICtrlFactory::getInstance()->createFromFile<LLMenuBarGL>("menu_viewer.xml", gMenuHolder); + gMenuBarView = LLUICtrlFactory::getInstance()->createFromFile<LLMenuBarGL>("menu_viewer.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); gMenuBarView->setRect(LLRect(0, top, 0, top - MENU_BAR_HEIGHT)); gMenuBarView->setBackgroundColor( color ); @@ -575,7 +573,7 @@ void init_menus() // Let land based option enable when parcel changes gMenuParcelObserver = new LLMenuParcelObserver(); - gLoginMenuBarView = LLUICtrlFactory::getInstance()->createFromFile<LLMenuBarGL>("menu_login.xml", gMenuHolder); + gLoginMenuBarView = LLUICtrlFactory::getInstance()->createFromFile<LLMenuBarGL>("menu_login.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); gLoginMenuBarView->arrangeAndClear(); LLRect menuBarRect = gLoginMenuBarView->getRect(); gLoginMenuBarView->setRect(LLRect(menuBarRect.mLeft, menuBarRect.mTop, gViewerWindow->getRootView()->getRect().getWidth() - menuBarRect.mLeft, menuBarRect.mBottom)); @@ -612,11 +610,6 @@ class LLAdvancedToggleConsole : public view_listener_t toggle_visibility( (void*)gDebugView->mMemoryView ); } #endif - else if ("notifications" == console_type) - { - //LLFloaterNotificationConsole::showInstance(); - LLFloaterReg::showInstance("notifications_console"); - } return true; } }; @@ -1117,30 +1110,6 @@ class LLAdvancedCheckFrameTest : public view_listener_t }; - // -///////////////////////////// -//// HIDE SELECTED OBJECTS // -///////////////////////////// -// -// -//class LLAdvancedToggleHideSelectedObjects : public view_listener_t -//{ -// bool handleEvent(const LLSD& userdata) -// { -// LLSelectMgr::sHideSelectedObjects = !(LLSelectMgr::sHideSelectedObjects); -// return true; -// } -//}; - // -//class LLAdvancedCheckHideSelectedObjects : public view_listener_t -//{ -// bool handleEvent(const LLSD& userdata) -// { -// bool new_value = gHideSelectedObjects; -// return new_value; -// } -//}; - /////////////////////////// // SELECTED TEXTURE INFO // /////////////////////////// @@ -1506,16 +1475,6 @@ class LLAdvancedCheckDebugWindowProc : public view_listener_t // ------------------------------XUI MENU --------------------------- - -class LLAdvancedShowFontTest : public view_listener_t -{ - bool handleEvent(const LLSD& userdata) - { - LLFloaterFontTest::show(NULL); - return true; - } -}; - ////////////////////// // LOAD UI FROM XML // ////////////////////// @@ -1547,6 +1506,15 @@ class LLAdvancedSaveUIToXML : public view_listener_t }; +class LLAdvancedSendTestIms : public view_listener_t +{ + bool handleEvent(const LLSD& userdata) + { + LLIMModel::instance().testMessages(); + return true; +} +}; + /////////////// // XUI NAMES // @@ -1987,18 +1955,6 @@ class LLAdvancedDumpAvatarLocalTextures : public view_listener_t } }; -//////////////////////////////// -// Memory Leaking Simulation // -//////////////////////////////// -class LLAdvancedMemoryLeakingSimulation : public view_listener_t -{ - bool handleEvent(const LLSD& userdata) - { - LLFloaterMemLeak::show(NULL); - return true; - } -}; - #endif ///////////////// @@ -2147,7 +2103,6 @@ class LLAdvancedShowDebugSettings : public view_listener_t { bool handleEvent(const LLSD& userdata) { - // LLFloaterSettingsDebug::showInstance(userdata); LLFloaterReg::showInstance("settings_debug",userdata); return true; } @@ -2414,14 +2369,6 @@ class LLAdminHandleRegionDumpTempAssetData: public view_listener_t } }; //Admin (Top Level) -class LLAdminShowGodTools: public view_listener_t -{ - bool handleEvent(const LLSD& userdata) - { - LLFloaterGodTools::showInstance(LLSD()); - return true; - } -}; class LLAdminOnSaveState: public view_listener_t { @@ -2581,7 +2528,7 @@ class LLObjectEnableTouch : public view_listener_t // label.assign("Touch"); // } //} - +/* bool handle_object_open() { LLViewerObject* obj = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); @@ -2598,7 +2545,7 @@ class LLObjectOpen : public view_listener_t return handle_object_open(); } }; - +*/ class LLObjectEnableOpen : public view_listener_t { bool handleEvent(const LLSD& userdata) @@ -2715,16 +2662,6 @@ class LLObjectEdit : public view_listener_t } }; -class LLObjectInspect : public view_listener_t -{ - bool handleEvent(const LLSD& userdata) - { - LLFloaterInspect::show(); - return true; - } -}; - - //--------------------------------------------------------------------------- // Land pie menu //--------------------------------------------------------------------------- @@ -4382,7 +4319,7 @@ void handle_take() } // check library - if(gInventory.isObjectDescendentOf(category_id, gInventoryLibraryRoot)) + if(gInventory.isObjectDescendentOf(category_id, gInventory.getLibraryRootFolderID())) { category_id.setNull(); } @@ -5612,35 +5549,10 @@ class LLShowFloater : public view_listener_t { LLToolBar::toggle(NULL); } - else if (floater_name == "mute list") - { - LLFloaterReg::toggleInstance("mute"); - } - else if (floater_name == "camera controls") - { - LLFloaterCamera::toggleInstance(); - } - else if (floater_name == "movement controls") - { - LLFloaterMove::toggleInstance(); - } else if (floater_name == "my land") { LLFloaterLandHoldings::show(NULL); } - else if (floater_name == "about land") - { - if (LLViewerParcelMgr::getInstance()->selectionEmpty()) - { - LLViewerParcelMgr::getInstance()->selectParcelAt(gAgent.getPositionGlobal()); - } - - LLFloaterLand::showInstance(); - } - else if (floater_name == "about region") - { - LLFloaterRegionInfo::showInstance(); - } else if (floater_name == "buy land") { if (LLViewerParcelMgr::getInstance()->selectionEmpty()) @@ -5650,10 +5562,6 @@ class LLShowFloater : public view_listener_t LLViewerParcelMgr::getInstance()->startBuyLand(); } - else if (floater_name == "grid options") - { - LLFloaterReg::showInstance("build_options"); - } else if (floater_name == "script errors") { LLFloaterScriptDebug::show(LLUUID::null); @@ -5662,48 +5570,16 @@ class LLShowFloater : public view_listener_t { gViewerHtmlHelp.show(); } - else if (floater_name == "help tutorial") - { - LLFloaterHUD::showHUD(); - } else if (floater_name == "complaint reporter") { // Prevent menu from appearing in screen shot. gMenuHolder->hideMenus(); LLFloaterReporter::showFromMenu(COMPLAINT_REPORT); } - else if (floater_name == "mean events") - { - if (!gNoRender) - { - //LLFloaterBump::showInstance(); - LLFloaterReg::showInstance("bumps"); - } - } - else if (floater_name == "lag meter") - { - LLFloaterReg::showInstance("lagmeter"); - } else if (floater_name == "buy currency") { LLFloaterBuyCurrency::buyCurrency(); } - else if (floater_name == "about") - { - LLFloaterReg::showInstance("sl_about"); - } - else if (floater_name == "active speakers") - { - LLFloaterActiveSpeakers::toggleInstance(LLSD()); - } - else if (floater_name == "beacons") - { - LLFloaterBeacons::toggleInstance(LLSD()); - } - else if (floater_name == "perm prefs") - { - LLFloaterPerms::toggleInstance(LLSD()); - } else { LLFloaterReg::toggleInstance(floater_name); @@ -5722,30 +5598,6 @@ class LLFloaterVisible : public view_listener_t { new_value = LLToolBar::visible(NULL); } - else if (floater_name == "mute list") - { - new_value = LLFloaterReg::instanceVisible("mute"); - } - else if (floater_name == "camera controls") - { - new_value = LLFloaterCamera::instanceVisible(); - } - else if (floater_name == "movement controls") - { - new_value = LLFloaterMove::instanceVisible(); - } - else if (floater_name == "stat bar") - { - new_value = gSavedSettings.getBOOL("ShowDebugStats"); - } - else if (floater_name == "active speakers") - { - new_value = LLFloaterActiveSpeakers::instanceVisible(LLSD()); - } - else if (floater_name == "beacons") - { - new_value = LLFloaterBeacons::instanceVisible(LLSD()); - } else { new_value = LLFloaterReg::instanceVisible(floater_name); @@ -6440,8 +6292,8 @@ class LLToolsSelectedScriptAction : public view_listener_t msg = "RunningNot"; } LLUUID id; id.generate(); - LLFloater* floater = LLFloaterReg::getInstance(name, LLSD(id)); - LLFloaterScriptQueue* queue = dynamic_cast<LLFloaterScriptQueue*>(floater); + + LLFloaterScriptQueue* queue =LLFloaterReg::getTypedInstance<LLFloaterScriptQueue>(name, LLSD(id)); if (queue) { queue->setMono(mono); @@ -6450,7 +6302,7 @@ class LLToolsSelectedScriptAction : public view_listener_t else { llwarns << "Failed to generate LLFloaterScriptQueue with action: " << action << llendl; - delete floater; + delete queue; } return true; } @@ -7016,7 +6868,7 @@ void handle_grab_texture(void* data) gInventory.updateItem(item); gInventory.notifyObservers(); - LLInventoryView* view = LLInventoryView::getActiveInventory(); + LLFloaterInventory* view = LLFloaterInventory::getActiveInventory(); // Show the preview panel for textures to let // user know that the image is now in inventory. @@ -7026,7 +6878,7 @@ void handle_grab_texture(void* data) view->getPanel()->setSelection(item_id, TAKE_FOCUS_NO); view->getPanel()->openSelected(); - //LLInventoryView::dumpSelectionInformation((void*)view); + //LLFloaterInventory::dumpSelectionInformation((void*)view); // restore keyboard focus gFocusMgr.setKeyboardFocus(focus_ctrl); } @@ -7261,10 +7113,14 @@ void handle_buy_currency_test(void*) llinfos << "buy currency url " << url << llendl; - LLFloaterHtmlCurrency* floater = LLFloaterHtmlCurrency::showInstance(url); - // Needed so we can use secondlife:///app/floater/self/close SLURLs - floater->setTrusted(true); - floater->center(); + LLFloaterHtmlCurrency* floater =LLFloaterReg::getTypedInstance<LLFloaterHtmlCurrency>("html_currency", LLSD(url)); + if(floater) + { + LLFloaterReg::showInstance("html_currency", LLSD(url)); + // Needed so we can use secondlife:///app/floater/self/close SLURLs + floater->setTrusted(true); + floater->center(); + } } void handle_rebake_textures(void*) @@ -7984,11 +7840,11 @@ void initialize_menus() // Advanced > XUI commit.add("Advanced.ReloadColorSettings", boost::bind(&LLUIColorTable::loadFromSettings, LLUIColorTable::getInstance())); - view_listener_t::addMenu(new LLAdvancedShowFontTest(), "Advanced.ShowFontTest"); view_listener_t::addMenu(new LLAdvancedLoadUIFromXML(), "Advanced.LoadUIFromXML"); view_listener_t::addMenu(new LLAdvancedSaveUIToXML(), "Advanced.SaveUIToXML"); view_listener_t::addMenu(new LLAdvancedToggleXUINames(), "Advanced.ToggleXUINames"); view_listener_t::addMenu(new LLAdvancedCheckXUINames(), "Advanced.CheckXUINames"); + view_listener_t::addMenu(new LLAdvancedSendTestIms(), "Advanced.SendTestIMs"); // Advanced > Character > Grab Baked Texture view_listener_t::addMenu(new LLAdvancedGrabBakedTexture(), "Advanced.GrabBakedTexture"); @@ -8024,7 +7880,6 @@ void initialize_menus() #ifndef LL_RELEASE_FOR_DOWNLOAD view_listener_t::addMenu(new LLAdvancedDebugAvatarTextures(), "Advanced.DebugAvatarTextures"); view_listener_t::addMenu(new LLAdvancedDumpAvatarLocalTextures(), "Advanced.DumpAvatarLocalTextures"); - view_listener_t::addMenu(new LLAdvancedMemoryLeakingSimulation(), "Advanced.MemoryLeakingSimulation"); #endif // Advanced > Network view_listener_t::addMenu(new LLAdvancedEnableMessageLog(), "Advanced.EnableMessageLog"); @@ -8072,7 +7927,6 @@ void initialize_menus() // Admin >Region view_listener_t::addMenu(new LLAdminHandleRegionDumpTempAssetData(), "Admin.HandleRegionDumpTempAssetData"); // Admin top level - view_listener_t::addMenu(new LLAdminShowGodTools(), "Admin.ShowGodTools"); view_listener_t::addMenu(new LLAdminOnSaveState(), "Admin.OnSaveState"); // Self pie menu @@ -8100,7 +7954,6 @@ void initialize_menus() view_listener_t::addMenu(new LLAvatarEnableFreezeEject(), "Avatar.EnableFreezeEject"); // Object pie menu - view_listener_t::addMenu(new LLObjectOpen(), "Object.Open"); view_listener_t::addMenu(new LLObjectBuild(), "Object.Build"); view_listener_t::addMenu(new LLObjectTouch(), "Object.Touch"); view_listener_t::addMenu(new LLObjectSitOrStand(), "Object.SitOrStand"); @@ -8111,7 +7964,6 @@ void initialize_menus() view_listener_t::addMenu(new LLObjectMute(), "Object.Mute"); view_listener_t::addMenu(new LLObjectBuy(), "Object.Buy"); view_listener_t::addMenu(new LLObjectEdit(), "Object.Edit"); - view_listener_t::addMenu(new LLObjectInspect(), "Object.Inspect"); view_listener_t::addMenu(new LLObjectEnableOpen(), "Object.EnableOpen"); view_listener_t::addMenu(new LLObjectEnableTouch(), "Object.EnableTouch"); diff --git a/indra/newview/llviewermenu.h b/indra/newview/llviewermenu.h index 99994bdf5bbf9624f3baf1d2b1eb4dc3995f7f73..13a16399170d1f7f462454bf6ff1cfbf1828d63e 100644 --- a/indra/newview/llviewermenu.h +++ b/indra/newview/llviewermenu.h @@ -101,7 +101,6 @@ void handle_toggle_flycam(); bool handle_sit_or_stand(); bool handle_give_money_dialog(); -bool handle_object_open(); bool handle_go_to(); // Export to XML or Collada diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index a05bd3060046cb1a241190009a5363078dfe9218..e46748edf0cc6a73a2812c274abb563551291893 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -94,7 +94,7 @@ #include "llhudmanager.h" #include "llimpanel.h" #include "llinventorymodel.h" -#include "llinventoryview.h" +#include "llfloaterinventory.h" #include "llmenugl.h" #include "llmutelist.h" #include "llnotifications.h" @@ -912,17 +912,17 @@ void open_offer(const std::vector<LLUUID>& items, const std::string& from_name) //highlight item, if it's not in the trash or lost+found // Don't auto-open the inventory floater - LLInventoryView* view = NULL; + LLFloaterInventory* view = NULL; if(gSavedSettings.getBOOL("ShowInInventory") && asset_type != LLAssetType::AT_CALLINGCARD && item->getInventoryType() != LLInventoryType::IT_ATTACHMENT && !from_name.empty()) { - view = LLInventoryView::showAgentInventory(); + view = LLFloaterInventory::showAgentInventory(); } else { - view = LLInventoryView::getActiveInventory(); + view = LLFloaterInventory::getActiveInventory(); } if(!view) { @@ -986,7 +986,8 @@ void inventory_offer_mute_callback(const LLUUID& blocked_id, if (LLMuteList::getInstance()->add(mute)) { LLFloaterReg::showInstance("mute"); - LLFloaterReg::getTypedInstance<LLFloaterMute>("mute")->selectMute(blocked_id); + LLFloaterMute* mute_instance = LLFloaterReg::getTypedInstance<LLFloaterMute>("mute"); + if(mute_instance) mute_instance->selectMute(blocked_id); } // purge the message queue of any previously queued inventory offers from the same source. @@ -1527,7 +1528,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) // now store incoming IM in chat history - buffer = separator_string + message.substr(message_offset); + buffer = message.substr(message_offset); LL_INFOS("Messaging") << "process_improved_im: session_id( " << session_id << " ), from_id( " << from_id << " )" << LL_ENDL; @@ -1577,7 +1578,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) { saved = llformat("(Saved %s) ", formatted_time(timestamp).c_str()); } - buffer = separator_string + saved + message.substr(message_offset); + buffer = saved + message.substr(message_offset); LL_INFOS("Messaging") << "process_improved_im: session_id( " << session_id << " ), from_id( " << from_id << " )" << LL_ENDL; @@ -1876,7 +1877,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) { saved = llformat("(Saved %s) ", formatted_time(timestamp).c_str()); } - buffer = separator_string + saved + message.substr(message_offset); + buffer = saved + message.substr(message_offset); BOOL is_this_agent = FALSE; if(from_id == gAgentID) { @@ -4793,13 +4794,13 @@ void container_inventory_arrived(LLViewerObject* object, gAgent.changeCameraToDefault(); } - LLInventoryView* view = LLInventoryView::getActiveInventory(); + LLFloaterInventory* view = LLFloaterInventory::getActiveInventory(); if (inventory->size() > 2) { // create a new inventory category to put this in LLUUID cat_id; - cat_id = gInventory.createNewCategory(gAgent.getInventoryRootID(), + cat_id = gInventory.createNewCategory(gInventory.getRootFolderID(), LLAssetType::AT_NONE, LLTrans::getString("AcquiredItems")); @@ -5494,10 +5495,14 @@ void process_script_teleport_request(LLMessageSystem* msg, void**) msg->getVector3("Data", "SimPosition", pos); msg->getVector3("Data", "LookAt", look_at); - LLFloaterWorldMap::getInstance()->trackURL( - sim_name, (S32)pos.mV[VX], (S32)pos.mV[VY], (S32)pos.mV[VZ]); - LLFloaterReg::showInstance("world_map", "center"); - + LLFloaterWorldMap* instance = LLFloaterWorldMap::getInstance(); + if(instance) + { + instance->trackURL( + sim_name, (S32)pos.mV[VX], (S32)pos.mV[VY], (S32)pos.mV[VZ]); + LLFloaterReg::showInstance("world_map", "center"); + } + // remove above two lines and replace with below line // to re-enable parcel browser for llMapDestination() // LLURLDispatcher::dispatch(LLSLURL::buildSLURL(sim_name, (S32)pos.mV[VX], (S32)pos.mV[VY], (S32)pos.mV[VZ]), FALSE); diff --git a/indra/newview/llviewertexteditor.cpp b/indra/newview/llviewertexteditor.cpp index f4989ec4fef6fc4fd56e472ccaf812029a9bec25..399b7c6bc1115cbbde9bd03e197fb53b92802beb 100644 --- a/indra/newview/llviewertexteditor.cpp +++ b/indra/newview/llviewertexteditor.cpp @@ -39,7 +39,7 @@ #include "llinventory.h" #include "llinventorybridge.h" #include "llinventorymodel.h" -#include "llinventoryview.h" +#include "llfloaterinventory.h" #include "llviewertexteditor.h" @@ -64,7 +64,7 @@ #include "llappviewer.h" // for gPacificDaylightTime -static LLDefaultWidgetRegistry::Register<LLViewerTextEditor> r("text_editor"); +static LLDefaultChildRegistry::Register<LLViewerTextEditor> r("text_editor"); ///---------------------------------------------------------------------------- /// Class LLEmbeddedNotecardOpener diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 569eba2f20407d312314e418c808edef7686af74..e4aaf2bf29f2b861d9501f1eb2a9b952290e0c3f 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -93,7 +93,6 @@ #include "llfeaturemanager.h" #include "llfilepicker.h" #include "llfloater.h" -#include "llfloateractivespeakers.h" #include "llfloaterbuildoptions.h" #include "llfloaterbuyland.h" #include "llfloatercamera.h" @@ -116,7 +115,7 @@ #include "llhudview.h" #include "llimagebmp.h" #include "llimagej2c.h" -#include "llinventoryview.h" +#include "llfloaterinventory.h" #include "llkeyboard.h" #include "lllineeditor.h" #include "llmenugl.h" diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index b38e71236d354738ba9a2ffdd31b7eadece1b44b..e351c904e6aa4ad8591d271474de99374dcc38f7 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -52,7 +52,7 @@ #include "llheadrotmotion.h" #include "llhudeffecttrail.h" #include "llhudmanager.h" -#include "llinventoryview.h" +#include "llfloaterinventory.h" #include "llkeyframefallmotion.h" #include "llkeyframestandmotion.h" #include "llkeyframewalkmotion.h" diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index e7d7d74f62b4b0fcd2aa6ce4c3533ac5fdd9cdca..ef02b509bacf6e399ee64c49690e61e3d14b2827 100644 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -54,7 +54,7 @@ #include "llheadrotmotion.h" #include "llhudeffecttrail.h" #include "llhudmanager.h" -#include "llinventoryview.h" +#include "llfloaterinventory.h" #include "llkeyframefallmotion.h" #include "llkeyframestandmotion.h" #include "llkeyframewalkmotion.h" diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp index 082dcb50a2f3bf7003e429963ab1b745f9d02996..fc639fbb217b2b120dffafafe18c9da5b14aca1a 100644 --- a/indra/newview/llvoiceclient.cpp +++ b/indra/newview/llvoiceclient.cpp @@ -4551,7 +4551,7 @@ void LLVoiceClient::messageEvent( if(messageHeader.find("text/html") != std::string::npos) { - std::string rawMessage; + std::string message; { const std::string startMarker = "<body"; @@ -4563,7 +4563,7 @@ void LLVoiceClient::messageEvent( std::string::size_type end; // Default to displaying the raw string, so the message gets through. - rawMessage = messageBody; + message = messageBody; // Find the actual message text within the XML fragment start = messageBody.find(startMarker); @@ -4577,7 +4577,7 @@ void LLVoiceClient::messageEvent( if(end != std::string::npos) end -= start; - rawMessage.assign(messageBody, start, end); + message.assign(messageBody, start, end); } else { @@ -4593,24 +4593,24 @@ void LLVoiceClient::messageEvent( if(end != std::string::npos) end -= start; - rawMessage.assign(messageBody, start, end); + message.assign(messageBody, start, end); } } } -// LL_DEBUGS("Voice") << " raw message = \n" << rawMessage << LL_ENDL; +// LL_DEBUGS("Voice") << " raw message = \n" << message << LL_ENDL; // strip formatting tags { std::string::size_type start; std::string::size_type end; - while((start = rawMessage.find('<')) != std::string::npos) + while((start = message.find('<')) != std::string::npos) { - if((end = rawMessage.find('>', start + 1)) != std::string::npos) + if((end = message.find('>', start + 1)) != std::string::npos) { // Strip out the tag - rawMessage.erase(start, (end + 1) - start); + message.erase(start, (end + 1) - start); } else { @@ -4626,31 +4626,31 @@ void LLVoiceClient::messageEvent( // The text may contain text encoded with <, >, and & mark = 0; - while((mark = rawMessage.find("<", mark)) != std::string::npos) + while((mark = message.find("<", mark)) != std::string::npos) { - rawMessage.replace(mark, 4, "<"); + message.replace(mark, 4, "<"); mark += 1; } mark = 0; - while((mark = rawMessage.find(">", mark)) != std::string::npos) + while((mark = message.find(">", mark)) != std::string::npos) { - rawMessage.replace(mark, 4, ">"); + message.replace(mark, 4, ">"); mark += 1; } mark = 0; - while((mark = rawMessage.find("&", mark)) != std::string::npos) + while((mark = message.find("&", mark)) != std::string::npos) { - rawMessage.replace(mark, 5, "&"); + message.replace(mark, 5, "&"); mark += 1; } } // strip leading/trailing whitespace (since we always seem to get a couple newlines) - LLStringUtil::trim(rawMessage); + LLStringUtil::trim(message); -// LL_DEBUGS("Voice") << " stripped message = \n" << rawMessage << LL_ENDL; +// LL_DEBUGS("Voice") << " stripped message = \n" << message << LL_ENDL; sessionState *session = findSession(sessionHandle); if(session) @@ -4674,14 +4674,12 @@ void LLVoiceClient::messageEvent( quiet_chat = true; // TODO: Question: Return busy mode response here? Or maybe when session is started instead? } - - std::string fullMessage = std::string(": ") + rawMessage; - + LL_DEBUGS("Voice") << "adding message, name " << session->mName << " session " << session->mIMSessionID << ", target " << session->mCallerID << LL_ENDL; gIMMgr->addMessage(session->mIMSessionID, session->mCallerID, session->mName.c_str(), - fullMessage.c_str(), + message.c_str(), LLStringUtil::null, // default arg IM_NOTHING_SPECIAL, // default arg 0, // default arg @@ -4689,7 +4687,7 @@ void LLVoiceClient::messageEvent( LLVector3::zero, // default arg true); // prepend name and make it a link to the user's profile - chat.mText = std::string("IM: ") + session->mName + std::string(": ") + rawMessage; + chat.mText = std::string("IM: ") + session->mName + std::string(": ") + message; // If the chat should come in quietly (i.e. we're in busy mode), pretend it's from a local agent. LLFloaterChat::addChat( chat, TRUE, quiet_chat ); } diff --git a/indra/newview/llweb.cpp b/indra/newview/llweb.cpp index 781f8298f7467e6737cfe9d67b24d2cfa3f1d833..57f57f75d77f5593f1e45d7f35aaa0bfb385ae9f 100644 --- a/indra/newview/llweb.cpp +++ b/indra/newview/llweb.cpp @@ -41,6 +41,7 @@ #include "llviewerwindow.h" #include "llviewercontrol.h" #include "llfloaterhtmlhelp.h" +#include "llfloaterreg.h" #include "llalertdialog.h" class URLLoader : public LLAlertDialog::URLLoader @@ -75,7 +76,7 @@ void LLWeb::loadURL(const std::string& url) } else { - LLFloaterMediaBrowser::showInstance(url); + LLFloaterReg::showInstance("media_browser",url); } } diff --git a/indra/newview/skins/default/xui/en/floater_auction.xml b/indra/newview/skins/default/xui/en/floater_auction.xml index 076332e062d5a0d45fc5fccacdff5ac9d02a6c99..32d3f4fd7e6ee44cc5ce95ca9d942ee17d305cdb 100644 --- a/indra/newview/skins/default/xui/en/floater_auction.xml +++ b/indra/newview/skins/default/xui/en/floater_auction.xml @@ -48,7 +48,7 @@ left_delta="0" name="snapshot_btn" top_pad="4" - width="96" > + width="96"> <button.commit_callback function="ClickSnapshot" /> </button> diff --git a/indra/newview/skins/default/xui/en/floater_beacons.xml b/indra/newview/skins/default/xui/en/floater_beacons.xml index 41ddec639578e7f31379cf3bd4792d3a93056790..049ea9ab145948d2c8b3edf789e5802ab5e9ad70 100644 --- a/indra/newview/skins/default/xui/en/floater_beacons.xml +++ b/indra/newview/skins/default/xui/en/floater_beacons.xml @@ -20,43 +20,64 @@ control_name="scripttouchbeacon" label="Scripted Objects with Touch Only" layout="topleft" - name="touch_only" /> + name="touch_only" > + <check_box.commit_callback + function="Beacons.UICheck" /> + </check_box> <check_box bottom_delta="20" control_name="scriptsbeacon" label="Scripted Objects" layout="topleft" - name="scripted" /> + name="scripted"> + <check_box.commit_callback + function="Beacons.UICheck" /> + </check_box> <check_box bottom_delta="20" control_name="physicalbeacon" label="Physical Objects" layout="topleft" - name="physical" /> + name="physical" > + <check_box.commit_callback + function="Beacons.UICheck" /> + </check_box> <check_box bottom_delta="20" control_name="soundsbeacon" label="Sound Sources" layout="topleft" - name="sounds" /> + name="sounds" > + <check_box.commit_callback + function="Beacons.UICheck" /> + </check_box> <check_box bottom_delta="20" control_name="particlesbeacon" label="Particle Sources" layout="topleft" - name="particles" /> + name="particles" > + <check_box.commit_callback + function="Beacons.UICheck" /> + </check_box> <check_box bottom_delta="20" control_name="renderhighlights" label="Render Highlights" layout="topleft" - name="highlights" /> + name="highlights" > + <check_box.commit_callback + function="Beacons.UICheck" /> + </check_box> <check_box bottom_delta="20" control_name="renderbeacons" label="Render Beacons" layout="topleft" - name="beacons" /> + name="beacons" > + <check_box.commit_callback + function="Beacons.UICheck" /> + </check_box> <text type="string" length="1" diff --git a/indra/newview/skins/default/xui/en/floater_bulk_perms.xml b/indra/newview/skins/default/xui/en/floater_bulk_perms.xml index 6d7e3a9c4502442f929f0b0963edbce4dda092d5..843a8848bf45c0953a1272772b8221217209ccca 100644 --- a/indra/newview/skins/default/xui/en/floater_bulk_perms.xml +++ b/indra/newview/skins/default/xui/en/floater_bulk_perms.xml @@ -224,7 +224,10 @@ left="8" name="check_all" top="257" - width="100" /> + width="100"> + <button.commit_callback + function="BulkPermission.CheckAll" /> + </button> <button follows="left|top" height="20" @@ -234,7 +237,10 @@ left_delta="0" name="check_none" top_pad="4" - width="100" /> + width="100" > + <button.commit_callback + function="BulkPermission.UncheckAll"/> + </button> <text type="string" length="1" @@ -295,10 +301,13 @@ left_delta="78" name="next_owner_copy" top_delta="0" - width="88" /> - <check_box + width="88"> + <check_box.commit_callback + function="BulkPermission.CommitCopy"/> + </check_box> + <check_box control_name="BulkChangeNextOwnerTransfer" - enabled="false" + enabled_control="BulkChangeNextOwnerCopy" height="16" initial_value="true" label="Resell/Give away" @@ -324,7 +333,10 @@ left="65" name="apply" top_pad="10" - width="100" /> + width="100"> + <button.commit_callback + function="BulkPermission.Apply"/> + </button> <button follows="left|top" height="20" @@ -333,5 +345,8 @@ left_pad="5" name="close" top_delta="0" - width="100" /> + width="100" > + <button.commit_callback + function="BulkPermission.Close"/> + </button> </floater> diff --git a/indra/newview/skins/default/xui/en/floater_god_tools.xml b/indra/newview/skins/default/xui/en/floater_god_tools.xml index e35ab3ea49b37e025b33d1bdd0e09837cbcb4272..f3abad8cb26a4ddb616605f534a2f4590a44445b 100644 --- a/indra/newview/skins/default/xui/en/floater_god_tools.xml +++ b/indra/newview/skins/default/xui/en/floater_god_tools.xml @@ -34,7 +34,10 @@ left="10" name="Kick all users" top="8" - width="100" /> + width="100"> + <button.commit_callback + function="GridTools.KickAll" /> + </button> <button follows="left|top" height="20" @@ -44,7 +47,10 @@ left_delta="0" name="Flush This Region's Map Visibility Caches" top_pad="8" - width="250" /> + width="250"> + <button.commit_callback + function="GridTools.FlushMapVisibilityCaches" /> + </button> </panel> <panel border="true" @@ -79,7 +85,10 @@ max_length="63" name="region name" top_delta="0" - width="208" /> + width="208"> + <line_editor.commit_callback + function="RegionTools.ChangeAnything" /> + </line_editor> <check_box height="16" label="Prelude" @@ -88,7 +97,10 @@ name="check prelude" tool_tip="Set this to make the region a prelude." top="30" - width="180" /> + width="180"> + <check_box.commit_callback + function="RegionTools.ChangePrelude" /> + </check_box> <check_box height="16" label="Fixed Sun" @@ -97,7 +109,10 @@ name="check fixed sun" tool_tip="Fix the sun position (like in Region/Estate > Terrain." top_pad="4" - width="180" /> + width="180"> + <check_box.commit_callback + function="RegionTools.ChangeAnything" /> + </check_box> <check_box height="16" label="Reset Home On Teleport" @@ -106,7 +121,10 @@ name="check reset home" tool_tip="When resident teleports out, reset their home to the destination position." top_pad="4" - width="180" /> + width="180"> + <check_box.commit_callback + function="RegionTools.ChangeAnything" /> + </check_box> <check_box height="16" label="Visible" @@ -115,7 +133,10 @@ name="check visible" tool_tip="Set this to make the region visible to non-gods." top_pad="4" - width="180" /> + width="180"> + <check_box.commit_callback + function="RegionTools.ChangeAnything" /> + </check_box> <check_box height="16" label="Damage" @@ -124,7 +145,10 @@ name="check damage" tool_tip="Set this to enable damage in this region." top_pad="4" - width="180" /> + width="180"> + <check_box.commit_callback + function="RegionTools.ChangeAnything" /> + </check_box> <check_box height="16" label="Block Traffic Tracking" @@ -133,7 +157,10 @@ name="block dwell" tool_tip="Set this to make the region not compute traffic." top_pad="4" - width="180" /> + width="180"> + <check_box.commit_callback + function="RegionTools.ChangeAnything" /> + </check_box> <check_box height="16" label="Block Terraform" @@ -142,7 +169,10 @@ name="block terraform" tool_tip="Set this to disallow people terraforming their land" top_pad="4" - width="180" /> + width="180"> + <check_box.commit_callback + function="RegionTools.ChangeAnything" /> + </check_box> <check_box height="16" label="Sandbox" @@ -151,7 +181,10 @@ name="is sandbox" tool_tip="Toggle whether this is a sandbox region." top_pad="4" - width="180" /> + width="180"> + <check_box.commit_callback + function="RegionTools.ChangeAnything" /> + </check_box> <button follows="top|right" font="SansSerifSmall" @@ -163,7 +196,10 @@ name="Bake Terrain" tool_tip="Save the current terrain as default." top_pad="32" - width="110" /> + width="110"> + <button.commit_callback + function="RegionTools.BakeTerrain" /> + </button> <button follows="top|right" font="SansSerifSmall" @@ -175,7 +211,10 @@ name="Revert Terrain" tool_tip="Replace the current terrain with default." top_pad="4" - width="110" /> + width="110"> + <button.commit_callback + function="RegionTools.RevertTerrain" /> + </button> <button follows="top|right" font="SansSerifSmall" @@ -187,7 +226,10 @@ name="Swap Terrain" tool_tip="Swap current terrain with default." top_pad="4" - width="110" /> + width="110"> + <button.commit_callback + function="RegionTools.SwapTerrain" /> + </button> <text type="string" length="1" @@ -236,7 +278,10 @@ name="parentestate" tool_tip="This is the parent estate for this region" top_delta="0" - width="50" /> + width="50"> + <line_editor.commit_callback + function="RegionTools.ChangeAnything" /> + </line_editor> <text type="string" length="1" @@ -260,7 +305,10 @@ name="gridposx" tool_tip="This is the grid x position for this region" top_delta="0" - width="50" /> + width="50"> + <line_editor.commit_callback + function="RegionTools.ChangeAnything" /> + </line_editor> <line_editor border_style="line" border_thickness="1" @@ -272,7 +320,10 @@ name="gridposy" tool_tip="This is the grid y position for this region" top_delta="0" - width="40" /> + width="40"> + <line_editor.commit_callback + function="RegionTools.ChangeAnything" /> + </line_editor> <text type="string" length="1" @@ -295,7 +346,10 @@ max_length="10" name="redirectx" top_delta="0" - width="50" /> + width="50"> + <line_editor.commit_callback + function="RegionTools.ChangeAnything" /> + </line_editor> <line_editor border_style="line" border_thickness="1" @@ -306,7 +360,10 @@ max_length="10" name="redirecty" top_delta="0" - width="40" /> + width="40"> + <line_editor.commit_callback + function="RegionTools.ChangeAnything" /> + </line_editor> <spinner follows="top|right" height="16" @@ -316,7 +373,10 @@ max_val="4" name="billable factor" top="110" - width="80" /> + width="80"> + <spinner.commit_callback + function="RegionTools.ChangeAnything" /> + </spinner> <text type="string" length="1" @@ -340,7 +400,10 @@ max_val="100" name="land cost" top="130" - width="80" /> + width="80"> + <spinner.commit_callback + function="RegionTools.ChangeAnything" /> + </spinner> <text type="string" length="1" @@ -365,7 +428,10 @@ name="Refresh" tool_tip="Click here to refresh the above information." top="150" - width="110" /> + width="110"> + <button.commit_callback + function="RegionTools.Refresh" /> + </button> <button follows="top|right" font="SansSerifSmall" @@ -377,7 +443,10 @@ name="Apply" tool_tip="Click here to apply any changes from above." top_pad="36" - width="110" /> + width="110"> + <button.commit_callback + function="RegionTools.ApplyChanges" /> + </button> <button follows="top|right" font="SansSerifSmall" @@ -389,7 +458,10 @@ name="Select Region" tool_tip="Select the whole region with the land tool." top="238" - width="110" /> + width="110"> + <button.commit_callback + function="RegionTools.SelectRegion" /> + </button> <button follows="top|right" font="SansSerifSmall" @@ -401,7 +473,10 @@ name="Autosave now" tool_tip="Save gzipped state to autosave directory." top_pad="4" - width="110" /> + width="110"> + <button.commit_callback + function="RegionTools.SaveState" /> + </button> </panel> <panel border="true" @@ -450,7 +525,10 @@ name="disable scripts" tool_tip="Set this to disable all scripts in this region" top="30" - width="110" /> + width="110"> + <check_box.commit_callback + function="ObjectTools.ChangeAnything" /> + </check_box> <check_box height="16" label="Disable Collisions" @@ -459,7 +537,10 @@ name="disable collisions" tool_tip="Set this to disable non-agent collisions in this region" top_delta="0" - width="121" /> + width="121"> + <check_box.commit_callback + function="ObjectTools.ChangeAnything" /> + </check_box> <check_box height="16" label="Disable Physics" @@ -468,7 +549,10 @@ name="disable physics" tool_tip="Set this to disable all physics in this region" top_delta="0" - width="130" /> + width="130"> + <check_box.commit_callback + function="ObjectTools.ChangeAnything" /> + </check_box> <button follows="top|right" font="SansSerifSmall" @@ -480,8 +564,11 @@ name="Apply" tool_tip="Click here to apply any changes from above." top="54" - width="110" /> - <button + width="110"> + <button.commit_callback + function="ObjectTools.ApplyChanges" /> + </button> + <button follows="top|right" font="SansSerifSmall" height="20" @@ -492,7 +579,10 @@ name="Set Target" tool_tip="Set the target avatar for object deletion." top="78" - width="110" /> + width="110"> + <button.commit_callback + function="ObjectTools.Set" /> + </button> <text type="string" length="1" @@ -516,7 +606,10 @@ name="Delete Target's Scripted Objects On Others Land" tool_tip="Delete all scripted objects owned by the target on land not owned by the target. (no copy) objects will be returned." top="126" - width="380" /> + width="380"> + <button.commit_callback + function="ObjectTools.DeletePublicOwnedBy" /> + </button> <button follows="top|right" font="SansSerifSmall" @@ -528,7 +621,10 @@ name="Delete Target's Scripted Objects On *Any* Land" tool_tip="Delete all scripted objects owned by the target in this region. (no copy) objects will be returned." top_pad="28" - width="380" /> + width="380"> + <button.commit_callback + function="ObjectTools.DeleteAllScriptedOwnedBy" /> + </button> <button follows="top|right" font="SansSerifSmall" @@ -540,8 +636,11 @@ name="Delete *ALL* Of Target's Objects" tool_tip="Delete all objects owned by the target in this region. (no copy) objects will be returned." top_pad="28" - width="380" /> - <button + width="380"> + <button.commit_callback + function="ObjectTools.DeleteAllOwnedBy" /> + </button> + <button follows="top|right" font="SansSerifSmall" height="20" @@ -552,7 +651,10 @@ name="Get Top Colliders" tool_tip="Gets list of objects experiencing the most narrowphase callbacks." top_pad="28" - width="110" /> + width="110"> + <button.commit_callback + function="ObjectTools.GetTopColliders" /> + </button> <button follows="top|right" font="SansSerifSmall" @@ -564,7 +666,10 @@ name="Get Top Scripts" tool_tip="Gets list of objects spending the most time running scripts." top_pad="4" - width="110" /> + width="110"> + <button.commit_callback + function="ObjectTools.GetTopScripts" /> + </button> <button follows="top|right" font="SansSerifSmall" @@ -576,7 +681,10 @@ name="Scripts digest" tool_tip="Gets a list of all scripts and number of occurences of each." top_pad="4" - width="110" /> + width="110" > + <button.commit_callback + function="ObjectTools.GetScriptDigest" /> + </button> </panel> <panel border="true" @@ -679,7 +787,10 @@ left="10" name="Make Request" top="96" - width="100" /> + width="100"> + <button.commit_callback + function="GodTools.Request" /> + </button> </panel> </tab_container> </floater> diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml new file mode 100644 index 0000000000000000000000000000000000000000..7c95fcd96a31294de6c3bb2c6c3ada540fad939d --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_im_session.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<floater + background_visible="true" + follows="left|top|right|bottom" + height="200" + layout="topleft" + left="0" + name="panel_im" + top="0" + width="300"> + <text_editor + enabled="false" + type="string" + length="1" + top="20" + follows="left|top|right" + font="SansSerif" + height="175" + layout="topleft" + left="5" + name="im_text" + width="290" + word_wrap="true"> + </text_editor> +</floater> diff --git a/indra/newview/skins/default/xui/en/floater_inspect.xml b/indra/newview/skins/default/xui/en/floater_inspect.xml index ed3b4f00f22808dc3f1deb9e12e723dad49e5ac8..b11b3e4df568bfd458c23315c68f3cdafb09be22 100644 --- a/indra/newview/skins/default/xui/en/floater_inspect.xml +++ b/indra/newview/skins/default/xui/en/floater_inspect.xml @@ -40,6 +40,8 @@ label="Creation Date" name="creation_date" width="150" /> + <scroll_list.commit_callback + function="Inspect.SelectObject" /> </scroll_list> <button follows="left|bottom" @@ -50,7 +52,10 @@ name="button owner" tool_tip="See profile of the highlighted object's owner" top_pad="5" - width="150" /> + width="150"> + <button.commit_callback + function="Inspect.OwnerProfilet" /> + </button> <button follows="left|bottom" height="20" @@ -60,5 +65,8 @@ name="button creator" tool_tip="See profile of the highlighted object's original creator" top_delta="0" - width="150" /> + width="150"> + <button.commit_callback + function="Inspect.CreatorProfile" /> + </button> </floater> diff --git a/indra/newview/skins/default/xui/en/floater_lagmeter.xml b/indra/newview/skins/default/xui/en/floater_lagmeter.xml index 8af4f74aa3d59e3e429ecd5397f3611191964e2a..a326cd006fee2f276dc92a3525c110f1a4339bc2 100644 --- a/indra/newview/skins/default/xui/en/floater_lagmeter.xml +++ b/indra/newview/skins/default/xui/en/floater_lagmeter.xml @@ -201,7 +201,7 @@ Client: </text> <text - make_visible_control="LagMeterShrunk" + visiblity_control="LagMeterShrunk" type="string" length="1" bottom="40" @@ -215,7 +215,7 @@ Normal </text> <text - make_visible_control="LagMeterShrunk" + visiblity_control="LagMeterShrunk" bottom="56" follows="left|top" height="16" @@ -250,7 +250,7 @@ Network: </text> <text - make_visible_control="LagMeterShrunk" + visiblity_control="LagMeterShrunk" type="string" length="1" bottom="80" @@ -264,7 +264,7 @@ Normal </text> <text - make_visible_control="LagMeterShrunk" + visiblity_control="LagMeterShrunk" bottom="96" follows="left|top" height="16" diff --git a/indra/newview/skins/default/xui/en/floater_media_browser.xml b/indra/newview/skins/default/xui/en/floater_media_browser.xml index a073c3443aa4e3795c62d4f543ee9878ba754b70..15ec2e220fd31cf7a45a97901910df2c0b28d699 100644 --- a/indra/newview/skins/default/xui/en/floater_media_browser.xml +++ b/indra/newview/skins/default/xui/en/floater_media_browser.xml @@ -34,7 +34,10 @@ left="0" name="back" top="0" - width="55" /> + width="55"> + <button.commit_callback + function="MediaBrowser.Back" /> + </button> <button follows="left|top" height="20" @@ -43,7 +46,10 @@ left_pad="3" name="forward" top_delta="0" - width="68" /> + width="68"> + <button.commit_callback + function="MediaBrowser.Forward" /> + </button> <button enabled="false" follows="left|top" @@ -53,7 +59,10 @@ left_pad="2" name="reload" top_delta="0" - width="70" /> + width="70"> + <button.commit_callback + function="MediaBrowser.Refresh" /> + </button> <combo_box allow_text_entry="true" follows="left|top|right" @@ -63,7 +72,10 @@ max_chars="255" name="address" top_delta="0" - width="540" /> + width="540"> + <combo_box.commit_callback + function="MediaBrowser.EnterAddress" /> + </combo_box> <button enabled="false" follows="right|top" @@ -73,7 +85,10 @@ left_pad="5" name="go" top_delta="0" - width="55" /> + width="55"> + <button.commit_callback + function="MediaBrowser.Go" /> + </button> </layout_panel> <layout_panel auto_resize="false" @@ -93,7 +108,10 @@ left="0" name="assign" top="0" - width="200" /> + width="200"> + <button.commit_callback + function="MediaBrowser.Assign" /> + </button> </layout_panel> <layout_panel height="20" @@ -119,7 +137,10 @@ left_delta="0" name="open_browser" top_pad="5" - width="185" /> + width="185"> + <button.commit_callback + function="MediaBrowser.OpenWebBrowser" /> + </button> <check_box control_name="UseExternalBrowser" follows="bottom|left" @@ -138,7 +159,10 @@ left_pad="80" name="close" top_delta="0" - width="70" /> + width="70"> + <button.commit_callback + function="MediaBrowser.Close" /> + </button> </layout_panel> </layout_stack> </floater> diff --git a/indra/newview/skins/default/xui/en/floater_mem_leaking.xml b/indra/newview/skins/default/xui/en/floater_mem_leaking.xml index e2a99e66141dbe61edca9091233928e3e0099f78..da698f276b4f271403fc514a4827678f02ccd5b1 100644 --- a/indra/newview/skins/default/xui/en/floater_mem_leaking.xml +++ b/indra/newview/skins/default/xui/en/floater_mem_leaking.xml @@ -20,7 +20,10 @@ max_val="4.29497e+009" name="leak_speed" top="30" - width="330" /> + width="330"> + <spinner.commit_callback + function="MemLeak.ChangeLeakingSpeed" /> + </spinner> <spinner decimal_digits="0" follows="left|top" @@ -34,7 +37,10 @@ max_val="4096" name="max_leak" top_pad="5" - width="330" /> + width="330"> + <spinner.commit_callback + function="MemLeak.ChangeMaxMemLeaking" /> + </spinner> <text type="string" length="1" @@ -79,7 +85,10 @@ left_delta="0" name="start_btn" top_delta="20" - width="70" /> + width="70"> + <button.commit_callback + function="MemLeak.Start" /> + </button> <button follows="left|top" height="20" @@ -88,7 +97,10 @@ left_pad="7" name="stop_btn" top_delta="0" - width="70" /> + width="70"> + <button.commit_callback + function="MemLeak.Stop" /> + </button> <button follows="left|top" height="20" @@ -97,7 +109,10 @@ left_pad="7" name="release_btn" top_delta="0" - width="70" /> + width="70"> + <button.commit_callback + function="MemLeak.Release" /> + </button> <button follows="left|top" height="20" @@ -106,5 +121,8 @@ left_pad="36" name="close_btn" top_delta="0" - width="70" /> + width="70"> + <button.commit_callback + function="MemLeak.Close" /> + </button> </floater> diff --git a/indra/newview/skins/default/xui/en/floater_openobject.xml b/indra/newview/skins/default/xui/en/floater_openobject.xml index 742934b57b0ce7d8759dcc212f31ef320d92ff27..e0ac2c1d5161dbce8ebfec9c0daf5d703ae65e05 100644 --- a/indra/newview/skins/default/xui/en/floater_openobject.xml +++ b/indra/newview/skins/default/xui/en/floater_openobject.xml @@ -42,7 +42,10 @@ name="copy_to_inventory_button" tab_group="1" top_pad="285" - width="120" /> + width="120"> + <button.commit_callback + function="OpenObject.MoveToInventory" /> + </button> <button follows="bottom|left" font="SansSerifSmall" @@ -53,5 +56,8 @@ left_pad="10" name="copy_and_wear_button" top_delta="0" - width="120" /> + width="120"> + <button.commit_callback + function="OpenObject.MoveAndWear" /> + </button> </floater> diff --git a/indra/newview/skins/default/xui/en/floater_perm_prefs.xml b/indra/newview/skins/default/xui/en/floater_perm_prefs.xml index 430cb940e5b5fcf3e1d3a087dc238d83079673c1..e4cb97035c0d7e1455b678531d8338dc77c5d101 100644 --- a/indra/newview/skins/default/xui/en/floater_perm_prefs.xml +++ b/indra/newview/skins/default/xui/en/floater_perm_prefs.xml @@ -24,7 +24,11 @@ left="260" name="help" top="7" - width="22" /> + width="22"> + <button.commit_callback + function="Notification.Show" + parameter="ClickUploadHelpPermissions" /> + </button> <check_box control_name="ShareWithGroup" height="16" @@ -72,8 +76,12 @@ left_delta="78" name="next_owner_copy" top_delta="0" - width="88" /> + width="88" > + <check_box.commit_callback + function="Perms.Copy" /> + </check_box> <check_box + enabled_control="NextOwnerCopy" control_name="NextOwnerTransfer" enabled="false" height="16" @@ -93,7 +101,10 @@ left="90" name="ok" top="150" - width="100" /> + width="100"> + <button.commit_callback + function="Perms.OK" /> + </button> <button height="20" label="Cancel" @@ -102,5 +113,8 @@ left_pad="5" name="cancel" top_delta="0" - width="100" /> + width="100"> + <button.commit_callback + function="Perms.Cancel" /> + </button> </floater> diff --git a/indra/newview/skins/default/xui/en/floater_test_list_view.xml b/indra/newview/skins/default/xui/en/floater_test_list_view.xml new file mode 100644 index 0000000000000000000000000000000000000000..3991a4a82b75ada731cc42ddfe320741738487ef --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_test_list_view.xml @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<floater + can_resize="true" + height="400" + layout="topleft" + name="floater_test_list_view" + width="400"> + <list_view + height="300" + left="10" + name="test_list_view" + top="28" + width="300" /> + <button + name="test_1_btn" + label="Test 1" + top="350" + left="10" + height="20" + width="80" + commit_callback.function="TestListView.Test1" /> + <button + name="test_2_btn" + label="Test 2" + top_delta="0" + left_pad="10" + height="20" + width="80" + commit_callback.function="TestListView.Test2" /> + +</floater> diff --git a/indra/newview/skins/default/xui/en/floater_top_objects.xml b/indra/newview/skins/default/xui/en/floater_top_objects.xml index 20e39beb6fa6681e5d7bf5287abb4254b354db96..ecd64d08e69254a6341e734c88a7517d1f1fc24c 100644 --- a/indra/newview/skins/default/xui/en/floater_top_objects.xml +++ b/indra/newview/skins/default/xui/en/floater_top_objects.xml @@ -87,6 +87,8 @@ label="Mono Time" name="mono_time" width="55" /> + <scroll_list.commit_callback + function="TopObjects.CommitObjectsList" /> </scroll_list> <text type="string" @@ -117,7 +119,10 @@ left_pad="10" name="show_beacon_btn" top_delta="0" - width="100" /> + width="100"> + <button.commit_callback + function="TopObjects.ShowBeacon" /> + </button> <text type="string" length="1" @@ -146,7 +151,10 @@ left_pad="10" name="filter_object_btn" top_delta="0" - width="100" /> + width="100"> + <button.commit_callback + function="TopObjects.GetByObjectName" /> + </button> <text type="string" length="1" @@ -175,7 +183,10 @@ left_pad="10" name="filter_owner_btn" top_delta="0" - width="100" /> + width="100"> + <button.commit_callback + function="TopObjects.GetByOwnerName" /> + </button> <button follows="bottom|left" height="20" @@ -184,7 +195,10 @@ left="10" name="return_selected_btn" top="295" - width="130" /> + width="130"> + <button.commit_callback + function="TopObjects.ReturnSelected" /> + </button> <button follows="bottom|left" height="20" @@ -193,7 +207,10 @@ left_pad="10" name="return_all_btn" top_delta="0" - width="130" /> + width="130"> + <button.commit_callback + function="TopObjects.ReturnAll" /> + </button> <button follows="bottom|left" height="20" @@ -202,7 +219,10 @@ left="10" name="disable_selected_btn" top="320" - width="130" /> + width="130"> + <button.commit_callback + function="TopObjects.DisableSelected" /> + </button> <button follows="bottom|left" height="20" @@ -211,7 +231,10 @@ left_pad="10" name="disable_all_btn" top_delta="0" - width="130" /> + width="130"> + <button.commit_callback + function="TopObjects.DisableAll" /> + </button> <button bottom="315" follows="bottom|right" @@ -220,5 +243,8 @@ layout="topleft" name="refresh_btn" right="-10" - width="100" /> + width="100"> + <button.commit_callback + function="TopObjects.Refresh" /> + </button> </floater> diff --git a/indra/newview/skins/default/xui/en/floater_world_map.xml b/indra/newview/skins/default/xui/en/floater_world_map.xml index 43f209546adb813db1477bb1958255a38ec40e7e..b1791908191564018bfa217ae7db7c231f966e7a 100644 --- a/indra/newview/skins/default/xui/en/floater_world_map.xml +++ b/indra/newview/skins/default/xui/en/floater_world_map.xml @@ -144,7 +144,10 @@ name="Go Home" tool_tip="Teleport to your home" top="34" - width="88" /> + width="88" > + <button.commit_callback + function="WMap.GoHome" /> + </button> <icon color="0 1 0 1" follows="top|right" @@ -325,6 +328,8 @@ <combo_box.item label="Online Friends" value="None" /> + <combo_box.commit_callback + function="WMap.AvatarCombo"/> </combo_box> <icon color="0.5 0 0 1" @@ -352,6 +357,8 @@ <combo_box.item label="Landmarks" value="None" /> + <combo_box.commit_callback + function="WMap.Landmark" /> </combo_box> <icon color="0.5 0 0 1" @@ -384,7 +391,10 @@ name="DoSearch" tool_tip="Search for region" top_delta="0" - width="60" /> + width="60"> + <button.commit_callback + function="WMap.Location" /> + </button> <text type="string" length="1" @@ -415,6 +425,8 @@ label="" name="sim_name" width="206" /> + <scroll_list.commit_callback + function="WMap.SearchResult" /> </scroll_list> <text type="string" @@ -441,7 +453,10 @@ name="spin x" tool_tip="X coordinate of location to show on map" top_delta="0" - width="48" /> + width="48"> + <spinner.commit_callback + function="WMap.CommitLocation" /> + </spinner> <spinner decimal_digits="0" follows="bottom|right" @@ -454,7 +469,10 @@ name="spin y" tool_tip="Y coordinate of location to show on map" top_delta="0" - width="48" /> + width="48" > + <spinner.commit_callback + function="WMap.CommitLocation" /> + </spinner> <spinner decimal_digits="0" follows="bottom|right" @@ -467,7 +485,10 @@ name="spin z" tool_tip="Z coordinate of location to show on map" top_delta="0" - width="48" /> + width="48"> + <spinner.commit_callback + function="WMap.CommitLocation" /> + </spinner> <button follows="right|bottom" height="20" @@ -478,7 +499,10 @@ name="Teleport" tool_tip="Teleport to selected location" top="494" - width="90" /> + width="90"> + <button.commit_callback + function="WMap.Teleport" /> + </button> <button follows="right|bottom" height="20" @@ -489,7 +513,10 @@ name="Show Destination" tool_tip="Center map on selected location" top_delta="0" - width="125" /> + width="125"> + <button.commit_callback + function="WMap.ShowTarget" /> + </button> <button follows="right|bottom" height="20" @@ -500,7 +527,10 @@ name="Clear" tool_tip="Stop tracking" top="518" - width="90" /> + width="90"> + <button.commit_callback + function="WMap.Clear" /> + </button> <button follows="right|bottom" height="20" @@ -511,7 +541,10 @@ name="Show My Location" tool_tip="Center map on your avatar's location" top_delta="0" - width="125" /> + width="125" > + <button.commit_callback + function="WMap.ShowAgent" /> + </button> <button enabled="false" follows="bottom|right" @@ -522,7 +555,10 @@ name="copy_slurl" tool_tip="Copies current location as SLURL to be used on the web." top="542" - width="222" /> + width="222"> + <button.commit_callback + function="WMap.CopySLURL" /> + </button> <slider follows="right|bottom" height="16" diff --git a/indra/newview/skins/default/xui/en/menu_login.xml b/indra/newview/skins/default/xui/en/menu_login.xml index eb3dcc225e5b8e9e1ea711d9d88336f71849243c..14c38f6f26d61c77c6e63b28a933658c6eb4e2e0 100644 --- a/indra/newview/skins/default/xui/en/menu_login.xml +++ b/indra/newview/skins/default/xui/en/menu_login.xml @@ -101,5 +101,13 @@ function="ShowFloater" parameter="test_widgets" /> </menu_item_call> + <menu_item_call + label="List View Test" + name="List View Test" + shortcut="control|shift|L"> + <menu_item_call.on_click + function="ShowFloater" + parameter="test_list_view" /> + </menu_item_call> </menu> </menu_bar> diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index 1d1a1c063ec5e7dc5ee13d9b248b3c9075fe7eff..4ce3c18dcc85da83ac1b0fad443e30552f14200f 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -15,8 +15,17 @@ name="Preferences" shortcut="control|P"> <menu_item_call.on_click - function="ShowFloater" + function="Floater.Show" parameter="preferences" /> + </menu_item_call> + <menu_item_call + label="Media Remote Ctrl" + layout="topleft" + name="Preferences" + shortcut="control|A"> + <menu_item_call.on_click + function="Floater.Toggle" + parameter="media_remote_ctrl" /> </menu_item_call> <menu_item_separator layout="topleft" /> @@ -221,22 +230,22 @@ layout="topleft" name="Active Speakers"> <menu_item_check.on_check - function="FloaterVisible" - parameter="active speakers" /> + function="Floater.Visible" + parameter="active_speakers" /> <menu_item_check.on_click - function="ShowFloater" - parameter="active speakers" /> + function="Floater.Toggle" + parameter="active_speakers" /> </menu_item_check> <menu_item_check label="Block List" layout="topleft" name="Mute List"> <menu_item_check.on_check - function="FloaterVisible" - parameter="mute list" /> + function="Floater.Visible" + parameter="mute" /> <menu_item_check.on_click - function="ShowFloater" - parameter="mute list" /> + function="Floater.Toggle" + parameter="mute" /> </menu_item_check> </menu> <menu @@ -249,22 +258,22 @@ layout="topleft" name="Camera Controls"> <menu_item_check.on_check - function="FloaterVisible" - parameter="camera controls" /> + function="Floater.Visible" + parameter="camera" /> <menu_item_check.on_click - function="ShowFloater" - parameter="camera controls" /> + function="Floater.Toggle" + parameter="camera" /> </menu_item_check> <menu_item_check label="Movement Controls" layout="topleft" name="Movement Controls"> <menu_item_check.on_check - function="FloaterVisible" - parameter="movement controls" /> + function="Floater.Visible" + parameter="moveview" /> <menu_item_check.on_click - function="ShowFloater" - parameter="movement controls" /> + function="Floater.Toggle" + parameter="moveview" /> </menu_item_check> <menu_item_separator layout="topleft" /> @@ -273,16 +282,16 @@ layout="topleft" name="About Land"> <menu_item_call.on_click - function="ShowFloater" - parameter="about land" /> + function="Floater.Show" + parameter="about_land" /> </menu_item_call> <menu_item_call label="Region/Estate" layout="topleft" name="Region/Estate"> <menu_item_call.on_click - function="ShowFloater" - parameter="about region" /> + function="Floater.Show" + parameter="region_info" /> </menu_item_call> <menu_item_separator layout="topleft" /> @@ -350,9 +359,10 @@ name="Mini-Map" shortcut="control|shift|M"> <menu_item_check.on_check - function="FloaterVisible" /> + function="Floater.Visible" + parameter="mini_map" /> <menu_item_check.on_click - function="ShowFloater" + function="Floater.Show" parameter="mini_map" /> </menu_item_check> <menu_item_separator @@ -400,8 +410,8 @@ layout="topleft" name="Tutorial"> <menu_item_call.on_click - function="ShowFloater" - parameter="help tutorial" /> + function="Floater.Show" + parameter="hud" /> </menu_item_call> <menu label="Report" @@ -429,16 +439,16 @@ layout="topleft" name="Bumps, Pushes &amp; Hits"> <menu_item_call.on_click - function="ShowFloater" - parameter="mean events" /> + function="Floater.Show" + parameter="bumps" /> </menu_item_call> <menu_item_call label="About Second Life" layout="topleft" name="About Second Life"> <menu_item_call.on_click - function="ShowFloater" - parameter="about" /> + function="Floater.Show" + parameter="sl_about" /> </menu_item_call> </menu> </menu> @@ -573,8 +583,8 @@ layout="topleft" name="perm prefs"> <menu_item_call.on_click - function="ShowFloater" - parameter="perm prefs" /> + function="Floater.Toggle" + parameter="perm_prefs" /> </menu_item_call> <menu_item_call label="Show Script Warning/Error Window" @@ -702,8 +712,8 @@ name="Grid Options" shortcut="control|shift|B"> <menu_item_call.on_click - function="ShowFloater" - parameter="grid options" /> + function="Floater.Show" + parameter="build_options" /> <menu_item_call.on_enable function="Tools.EnableToolNotPie" /> </menu_item_call> @@ -720,10 +730,10 @@ name="beacons" shortcut="control|alt|shift|N"> <menu_item_check.on_check - function="FloaterVisible" + function="Floater.Visible" parameter="beacons" /> <menu_item_check.on_click - function="ShowFloater" + function="Floater.Toggle" parameter="beacons" /> </menu_item_check> <menu_item_check @@ -1312,8 +1322,8 @@ layout="topleft" name="Lag Meter"> <menu_item_call.on_click - function="ShowFloater" - parameter="lag meter" /> + function="Floater.Show" + parameter="lagmeter" /> </menu_item_call> <menu_item_check label="Statistics Bar" @@ -1894,8 +1904,8 @@ function="Advanced.CheckConsole" parameter="notifications" /> <menu_item_check.on_click - function="Advanced.ToggleConsole" - parameter="notifications" /> + function="Floater.Show" + parameter="notifications_console" /> </menu_item_check> <menu_item_separator layout="topleft" /> @@ -1999,8 +2009,8 @@ layout="topleft" name="Memory Leaking Simulation"> <menu_item_call.on_click - function="Advanced.MemoryLeakingSimulation" - parameter="" /> + function="Floater.Show" + parameter="mem_leaking" /> </menu_item_call> <menu_item_separator layout="topleft" /> @@ -2843,7 +2853,8 @@ layout="topleft" name="Show Font Test"> <menu_item_call.on_click - function="Advanced.ShowFontTest" /> + function="Floater.Show" + parameter="font_test" /> </menu_item_call> <menu_item_call label="Load from XML..." @@ -2869,6 +2880,13 @@ <menu_item_check.on_click function="Advanced.ToggleXUINames" /> </menu_item_check> + <menu_item_call + label="Send Test IMs" + layout="topleft" + name="Send Test IMs"> + <menu_item_call.on_click + function="Advanced.SendTestIMs" /> + </menu_item_call> </menu> <menu create_jump_keys="true" @@ -3304,7 +3322,8 @@ layout="topleft" name="God Tools"> <menu_item_call.on_click - function="Admin.ShowGodTools" /> + function="Floater.Show" + parameter="god_tools" /> <menu_item_call.on_enable function="EnableGodCustomerService" /> </menu_item_call> diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 0a63da1463687dab402434d5a00ef726ab9becea..d2c0ffd13dc3c8f5ec0af627dafe7c353aa559d4 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -13,7 +13,7 @@ <global name="implicitclosebutton"> Close </global> - + <template name="okbutton"> <form> <button @@ -4980,347 +4980,347 @@ The string [STRING_NAME] is missing from strings.xml icon="notifytip.tga" name="SystemMessageTip" type="notifytip"> -[MESSAGE] + [MESSAGE] </notification> <notification icon="notifytip.tga" name="Cancelled" type="notifytip"> -Cancelled + Cancelled </notification> <notification icon="notifytip.tga" name="CancelledSit" type="notifytip"> -Cancelled Sit + Cancelled Sit </notification> <notification icon="notifytip.tga" name="CancelledAttach" type="notifytip"> -Cancelled Attach + Cancelled Attach </notification> <notification icon="notifytip.tga" name="ReplacedMissingWearable" type="notifytip"> -Replaced missing clothing/body part with default. + Replaced missing clothing/body part with default. </notification> <notification icon="groupnotify" name="GroupNotice" type="groupnotify"> -Topic: [SUBJECT], Message: [MESSAGE] + Topic: [SUBJECT], Message: [MESSAGE] </notification> <notification icon="notifytip.tga" name="FriendOnline" type="notifytip"> -[FIRST] [LAST] is Online + [FIRST] [LAST] is Online </notification> <notification icon="notifytip.tga" name="FriendOffline" type="notifytip"> -[FIRST] [LAST] is Offline + [FIRST] [LAST] is Offline </notification> <notification icon="notifytip.tga" name="AddSelfFriend" type="notifytip"> -You cannot add yourself as a friend. + You cannot add yourself as a friend. </notification> <notification icon="notifytip.tga" name="UploadingAuctionSnapshot" type="notifytip"> -Uploading in-world and web site snapshots... -(Takes about 5 minutes.) + Uploading in-world and web site snapshots... + (Takes about 5 minutes.) </notification> <notification icon="notify.tga" name="UploadPayment" type="notify"> -You paid L$[AMOUNT] to upload. + You paid L$[AMOUNT] to upload. </notification> <notification icon="notifytip.tga" name="UploadWebSnapshotDone" type="notifytip"> -Web site snapshot upload done. + Web site snapshot upload done. </notification> <notification icon="notifytip.tga" name="UploadSnapshotDone" type="notifytip"> -In-world snapshot upload done + In-world snapshot upload done </notification> <notification icon="notifytip.tga" name="TerrainDownloaded" type="notifytip"> -Terrain.raw downloaded + Terrain.raw downloaded </notification> <notification icon="notifytip.tga" name="GestureMissing" type="notifytip"> -Gesture [NAME] is missing from database. + Gesture [NAME] is missing from database. </notification> <notification icon="notifytip.tga" name="UnableToLoadGesture" type="notifytip"> -Unable to load gesture [NAME]. -Please try again. + Unable to load gesture [NAME]. + Please try again. </notification> <notification icon="notifytip.tga" name="LandmarkMissing" type="notifytip"> -Landmark is missing from database. + Landmark is missing from database. </notification> <notification icon="notifytip.tga" name="UnableToLoadLandmark" type="notifytip"> -Unable to load landmark. Please try again. + Unable to load landmark. Please try again. </notification> <notification icon="notifytip.tga" name="CapsKeyOn" type="notifytip"> -Your Caps Lock key is on. -As this will affect the password you type in, you will probably want to turn it off. + Your Caps Lock key is on. + As this will affect the password you type in, you will probably want to turn it off. </notification> <notification icon="notifytip.tga" name="NotecardMissing" type="notifytip"> -Notecard is missing from database. + Notecard is missing from database. </notification> <notification icon="notifytip.tga" name="NotecardNoPermissions" type="notifytip"> -Insufficient permissions to view notecard. + Insufficient permissions to view notecard. </notification> <notification icon="notifytip.tga" name="RezItemNoPermissions" type="notifytip"> -Insufficient permissions to rez object. + Insufficient permissions to rez object. </notification> <notification icon="notifytip.tga" name="UnableToLoadNotecard" type="notifytip"> -Unable to load notecard. -Please try again. + Unable to load notecard. + Please try again. </notification> <notification icon="notifytip.tga" name="ScriptMissing" type="notifytip"> -Script is missing from database. + Script is missing from database. </notification> <notification icon="notifytip.tga" name="ScriptNoPermissions" type="notifytip"> -Insufficient permissions to view script. + Insufficient permissions to view script. </notification> <notification icon="notifytip.tga" name="UnableToLoadScript" type="notifytip"> -Unable to load script. Please try again. + Unable to load script. Please try again. </notification> <notification icon="notifytip.tga" name="IncompleteInventory" type="notifytip"> -The complete contents you are offering are not yet locally available. Please try offering those items again in a minute. + The complete contents you are offering are not yet locally available. Please try offering those items again in a minute. </notification> <notification icon="notifytip.tga" name="CannotModifyProtectedCategories" type="notifytip"> -You cannot modify protected categories. + You cannot modify protected categories. </notification> <notification icon="notifytip.tga" name="CannotRemoveProtectedCategories" type="notifytip"> -You cannot remove protected categories. + You cannot remove protected categories. </notification> <notification icon="notifytip.tga" name="OfferedCard" type="notifytip"> -You have offered a calling card to [FIRST] [LAST] + You have offered a calling card to [FIRST] [LAST] </notification> <notification icon="notifytip.tga" name="UnableToBuyWhileDownloading" type="notifytip"> -Unable to buy while downloading object data. -Please try again. + Unable to buy while downloading object data. + Please try again. </notification> <notification icon="notifytip.tga" name="UnableToLinkWhileDownloading" type="notifytip"> -Unable to link while downloading object data. -Please try again. + Unable to link while downloading object data. + Please try again. </notification> <notification icon="notifytip.tga" name="CannotBuyObjectsFromDifferentOwners" type="notifytip"> -Cannot buy objects from different owners at the same time. -Please select a single object. + Cannot buy objects from different owners at the same time. + Please select a single object. </notification> <notification icon="notifytip.tga" name="ObjectNotForSale" type="notifytip"> -Object does not appear to be for sale. + Object does not appear to be for sale. </notification> <notification icon="notifytip.tga" name="EnteringGodMode" type="notifytip"> -Entering god mode, level [LEVEL] + Entering god mode, level [LEVEL] </notification> <notification icon="notifytip.tga" name="LeavingGodMode" type="notifytip"> -Leaving god mode, level [LEVEL] + Leaving god mode, level [LEVEL] </notification> <notification icon="notifytip.tga" name="CopyFailed" type="notifytip"> -Copy failed because you lack copy permission + Copy failed because you lack copy permission </notification> <notification icon="notifytip.tga" name="InventoryAccepted" type="notifytip"> -[NAME] accepted your inventory offer. + [NAME] accepted your inventory offer. </notification> <notification icon="notifytip.tga" name="InventoryDeclined" type="notifytip"> -[NAME] declined your inventory offer. + [NAME] declined your inventory offer. </notification> <notification icon="notifytip.tga" name="ObjectMessage" type="notifytip"> -[NAME]: [MESSAGE] + [NAME]: [MESSAGE] </notification> <notification icon="notifytip.tga" name="CallingCardAccepted" type="notifytip"> -Your calling card was accepted. + Your calling card was accepted. </notification> <notification icon="notifytip.tga" name="CallingCardDeclined" type="notifytip"> -Your calling card was declined. + Your calling card was declined. </notification> <notification icon="notifytip.tga" name="TeleportToLandmark" type="notifytip"> -Now that you have reached the mainland, you can teleport to locations like '[NAME]' by clicking on the Inventory button on the bottom right of your screen, and then select the Landmarks folder. -Double click on the landmark and click on Teleport to travel there. + Now that you have reached the mainland, you can teleport to locations like '[NAME]' by clicking on the Inventory button on the bottom right of your screen, and then select the Landmarks folder. + Double click on the landmark and click on Teleport to travel there. </notification> <notification icon="notifytip.tga" name="TeleportToPerson" type="notifytip"> -Now that you have reached the mainland, you can contact residents like '[NAME]' by clicking on the Inventory button on the bottom right of your screen, and then select the Calling Cards folder. -Double click on the card, click on Instant Message, and type a message. + Now that you have reached the mainland, you can contact residents like '[NAME]' by clicking on the Inventory button on the bottom right of your screen, and then select the Calling Cards folder. + Double click on the card, click on Instant Message, and type a message. </notification> <notification icon="notifytip.tga" name="CantSelectLandFromMultipleRegions" type="notifytip"> -Can't select land across server boundaries. -Try selecting a smaller piece of land. + Can't select land across server boundaries. + Try selecting a smaller piece of land. </notification> <notification icon="notifytip.tga" name="SearchWordBanned" type="notifytip"> -Some terms in your search query were excluded due to content restrictions as clarified in the Community Standards. + Some terms in your search query were excluded due to content restrictions as clarified in the Community Standards. </notification> <notification icon="notifytip.tga" name="NoContentToSearch" type="notifytip"> -Please select at least one type of content to search (PG, Mature, or Adult). + Please select at least one type of content to search (PG, Mature, or Adult). </notification> <notification icon="notify.tga" name="GroupVote" type="notify"> -[NAME] has proposed to vote on: -[MESSAGE] + [NAME] has proposed to vote on: + [MESSAGE] <form name="form"> <button index="0" @@ -5337,17 +5337,17 @@ Please select at least one type of content to search (PG, Mature, or Adult). icon="notify.tga" name="SystemMessage" type="notify"> -[MESSAGE] + [MESSAGE] </notification> <notification icon="notify.tga" name="EventNotification" type="notify"> -Event Notification: + Event Notification: -[NAME] -[DATE] + [NAME] + [DATE] <form name="form"> <button index="0" @@ -5368,9 +5368,9 @@ Event Notification: icon="notify.tga" name="TransferObjectsHighlighted" type="notify"> -All objects on this parcel that will transfer to the purchaser of this parcel are now highlighted. + All objects on this parcel that will transfer to the purchaser of this parcel are now highlighted. -* Trees and grasses that will transfer are not highlighted. + * Trees and grasses that will transfer are not highlighted. <form name="form"> <button index="0" @@ -5383,61 +5383,61 @@ All objects on this parcel that will transfer to the purchaser of this parcel ar icon="notify.tga" name="DeactivatedGesturesTrigger" type="notify"> -Deactivated gestures with same trigger: -[NAMES] + Deactivated gestures with same trigger: + [NAMES] </notification> <notification icon="notify.tga" name="NoQuickTime" type="notify"> -Apple's QuickTime software does not appear to be installed on your system. -If you want to view streaming media on parcels that support it you should go to the QuickTime site (http://www.apple.com/quicktime) and install the QuickTime Player. + Apple's QuickTime software does not appear to be installed on your system. + If you want to view streaming media on parcels that support it you should go to the QuickTime site (http://www.apple.com/quicktime) and install the QuickTime Player. </notification> <notification icon="notify.tga" name="OwnedObjectsReturned" type="notify"> -The objects you own on the selected parcel of land have been returned back to your inventory. + The objects you own on the selected parcel of land have been returned back to your inventory. </notification> <notification icon="notify.tga" name="OtherObjectsReturned" type="notify"> -The objects on the selected parcel of land that is owned by [FIRST] [LAST] have been returned to his or her inventory. + The objects on the selected parcel of land that is owned by [FIRST] [LAST] have been returned to his or her inventory. </notification> <notification icon="notify.tga" name="OtherObjectsReturned2" type="notify"> -The objects on the selected parcel of land owned by the resident '[NAME]' have been returned to their owner. + The objects on the selected parcel of land owned by the resident '[NAME]' have been returned to their owner. </notification> <notification icon="notify.tga" name="GroupObjectsReturned" type="notify"> -The objects on the selected parcel of land shared with the group [GROUPNAME] have been returned back to their owner's inventory. -Transferable deeded objects have been returned to their previous owners. -Non-transferable objects that are deeded to the group have been deleted. + The objects on the selected parcel of land shared with the group [GROUPNAME] have been returned back to their owner's inventory. + Transferable deeded objects have been returned to their previous owners. + Non-transferable objects that are deeded to the group have been deleted. </notification> <notification icon="notify.tga" name="UnOwnedObjectsReturned" type="notify"> -The objects on the selected parcel that are NOT owned by you have been returned to their owners. + The objects on the selected parcel that are NOT owned by you have been returned to their owners. </notification> <notification icon="notify.tga" name="NotSafe" type="notify"> -This land has damage enabled ('not safe'). -You can be hurt here. If you die, you will be teleported to your home location. + This land has damage enabled ('not safe'). + You can be hurt here. If you die, you will be teleported to your home location. <unique/> </notification> @@ -5445,8 +5445,8 @@ You can be hurt here. If you die, you will be teleported to your home location. icon="notify.tga" name="NoFly" type="notify"> -This land has flying disabled ('no fly'). -You cannot fly here. + This land has flying disabled ('no fly'). + You cannot fly here. <unique/> </notification> @@ -5454,8 +5454,8 @@ You cannot fly here. icon="notify.tga" name="PushRestricted" type="notify"> -This land is 'No Pushing'. -You cannot push others here unless you own the land. + This land is 'No Pushing'. + You cannot push others here unless you own the land. <unique/> </notification> @@ -5463,7 +5463,7 @@ You cannot push others here unless you own the land. icon="notify.tga" name="NoVoice" type="notify"> -This land has voice disabled. + This land has voice disabled. <unique/> </notification> @@ -5471,8 +5471,8 @@ This land has voice disabled. icon="notify.tga" name="NoBuild" type="notify"> -This land has building disabled ('no build'). -You cannot create objects here. + This land has building disabled ('no build'). + You cannot create objects here. <unique/> </notification> @@ -5480,222 +5480,222 @@ You cannot create objects here. icon="notify.tga" name="ScriptsStopped" type="notify"> -An administrator has temporarily stopped scripts in this region. + An administrator has temporarily stopped scripts in this region. </notification> <notification icon="notify.tga" name="ScriptsNotRunning" type="notify"> -This region is not running any scripts. + This region is not running any scripts. </notification> <notification icon="notify.tga" name="NoOutsideScripts" type="notify"> -This land has outside scripts disabled ('no outside scripts'). -No scripts will run except those belonging to the land owner. + This land has outside scripts disabled ('no outside scripts'). + No scripts will run except those belonging to the land owner. </notification> <notification icon="notify.tga" name="ClaimPublicLand" type="notify"> -Can only claim public land in region you're in. + Can only claim public land in region you're in. </notification> <notification icon="notify.tga" name="RegionTPAccessBlocked" type="notify"> -You aren't allowed in that Region due to your maturity Rating. You may need to validate your age and/or install the latest Viewer. + You aren't allowed in that Region due to your maturity Rating. You may need to validate your age and/or install the latest Viewer. -Please go to the Knowledge Base for details on accessing areas with this maturity Rating. + Please go to the Knowledge Base for details on accessing areas with this maturity Rating. </notification> <notification icon="notify.tga" name="URBannedFromRegion" type="notify"> -You are banned from the region. + You are banned from the region. </notification> <notification icon="notify.tga" name="NoTeenGridAccess" type="notify"> -Your account cannot connect to this teen grid region. + Your account cannot connect to this teen grid region. </notification> <notification icon="notify.tga" name="NoHelpIslandTP" type="notify"> -You cannot teleport back to Help Island. -Go to 'Help Island Public' to repeat the tutorial. + You cannot teleport back to Help Island. + Go to 'Help Island Public' to repeat the tutorial. </notification> <notification icon="notify.tga" name="ImproperPaymentStatus" type="notify"> -You do not have proper payment status to enter this region. + You do not have proper payment status to enter this region. </notification> <notification icon="notify.tga" name="MustGetAgeRgion" type="notify"> -You must be age-verified to enter this region. + You must be age-verified to enter this region. </notification> <notification icon="notify.tga" name="MustGetAgeParcel" type="notify"> -You must be age-verified to enter this parcel. + You must be age-verified to enter this parcel. </notification> <notification icon="notify.tga" name="NoDestRegion" type="notify"> -No destination region found. + No destination region found. </notification> <notification icon="notify.tga" name="NotAllowedInDest" type="notify"> -You are not allowed into the destination. + You are not allowed into the destination. </notification> <notification icon="notify.tga" name="RegionParcelBan" type="notify"> -Cannot region cross into banned parcel. Try another way. + Cannot region cross into banned parcel. Try another way. </notification> <notification icon="notify.tga" name="TelehubRedirect" type="notify"> -You have been redirected to a telehub. + You have been redirected to a telehub. </notification> <notification icon="notify.tga" name="CouldntTPCloser" type="notify"> -Could not teleport closer to destination. + Could not teleport closer to destination. </notification> <notification icon="notify.tga" name="TPCancelled" type="notify"> - Teleport cancelled. + Teleport cancelled. </notification> <notification icon="notify.tga" name="FullRegionTryAgain" type="notify"> -The region you are attempting to enter is currently full. -Please try again in a few moments. + The region you are attempting to enter is currently full. + Please try again in a few moments. </notification> <notification icon="notify.tga" name="GeneralFailure" type="notify"> -General failure. + General failure. </notification> <notification icon="notify.tga" name="RoutedWrongRegion" type="notify"> -Routed to wrong region. Please try again. + Routed to wrong region. Please try again. </notification> <notification icon="notify.tga" name="NoValidAgentID" type="notify"> -No valid agent id. + No valid agent id. </notification> <notification icon="notify.tga" name="NoValidSession" type="notify"> -No valid session id. + No valid session id. </notification> <notification icon="notify.tga" name="NoValidCircuit" type="notify"> -No valid circuit code. + No valid circuit code. </notification> <notification icon="notify.tga" name="NoValidTimestamp" type="notify"> -No valid timestamp. + No valid timestamp. </notification> <notification icon="notify.tga" name="NoPendingConnection" type="notify"> -Unable to create pending connection. + Unable to create pending connection. </notification> <notification icon="notify.tga" name="InternalUsherError" type="notify"> -Internal error attempting to connect agent usher. + Internal error attempting to connect agent usher. </notification> <notification icon="notify.tga" name="NoGoodTPDestination" type="notify"> -Unable to find a good teleport destination in this region. + Unable to find a good teleport destination in this region. </notification> <notification icon="notify.tga" name="InternalErrorRegionResolver" type="notify"> -Internal error attempting to activate region resolver. + Internal error attempting to activate region resolver. </notification> <notification icon="notify.tga" name="NoValidLanding" type="notify"> -A valid landing point could not be found. + A valid landing point could not be found. </notification> <notification icon="notify.tga" name="NoValidParcel" type="notify"> -No valid parcel could be found. + No valid parcel could be found. </notification> <notification icon="notify.tga" name="ObjectGiveItem" type="notify"> -An object named [OBJECTFROMNAME] owned by [FIRST] [LAST] has given you a [OBJECTTYPE] named [OBJECTNAME]. + An object named [OBJECTFROMNAME] owned by [FIRST] [LAST] has given you a [OBJECTTYPE] named [OBJECTNAME]. <form name="form"> <button index="0" @@ -5716,7 +5716,7 @@ An object named [OBJECTFROMNAME] owned by [FIRST] [LAST] has given you a [OBJECT icon="notify.tga" name="ObjectGiveItemUnknownUser" type="notify"> -An object named [OBJECTFROMNAME] owned by (an unknown user) has given you a [OBJECTTYPE] named [OBJECTNAME]. + An object named [OBJECTFROMNAME] owned by (an unknown user) has given you a [OBJECTTYPE] named [OBJECTNAME]. <form name="form"> <button index="0" @@ -5737,7 +5737,7 @@ An object named [OBJECTFROMNAME] owned by (an unknown user) has given you a [OBJ icon="notify.tga" name="UserGiveItem" type="notify"> -[NAME] has given you a [OBJECTTYPE] named '[OBJECTNAME]'. + [NAME] has given you a [OBJECTTYPE] named '[OBJECTNAME]'. <form name="form"> <button index="0" @@ -5758,15 +5758,15 @@ An object named [OBJECTFROMNAME] owned by (an unknown user) has given you a [OBJ icon="notify.tga" name="GodMessage" type="notify"> -[NAME] -[MESSAGE] + [NAME] + [MESSAGE] </notification> <notification icon="notify.tga" name="JoinGroup" type="notify"> -[MESSAGE] + [MESSAGE] <form name="form"> <button index="0" @@ -5787,9 +5787,9 @@ An object named [OBJECTFROMNAME] owned by (an unknown user) has given you a [OBJ icon="notify.tga" name="TeleportOffered" type="notify"> -[NAME] has offered to teleport you to his or her location: + [NAME] has offered to teleport you to his or her location: -[MESSAGE] + [MESSAGE] <form name="form"> <button index="0" @@ -5806,8 +5806,8 @@ An object named [OBJECTFROMNAME] owned by (an unknown user) has given you a [OBJ icon="notify.tga" name="GotoURL" type="notify"> -[MESSAGE] -[URL] + [MESSAGE] + [URL] <form name="form"> <button index="0" @@ -5824,11 +5824,11 @@ An object named [OBJECTFROMNAME] owned by (an unknown user) has given you a [OBJ icon="notify.tga" name="OfferFriendship" type="notify"> -[NAME] is offering friendship. + [NAME] is offering friendship. -[MESSAGE] + [MESSAGE] -(By default, you will be able to see each other's online status.) + (By default, you will be able to see each other's online status.) <form name="form"> <button index="0" @@ -5845,9 +5845,9 @@ An object named [OBJECTFROMNAME] owned by (an unknown user) has given you a [OBJ icon="notify.tga" name="OfferFriendshipNoMessage" type="notify"> -[NAME] is offering friendship. + [NAME] is offering friendship. -(By default, you will be able to see each other's online status.) + (By default, you will be able to see each other's online status.) <form name="form"> <button index="0" @@ -5864,22 +5864,22 @@ An object named [OBJECTFROMNAME] owned by (an unknown user) has given you a [OBJ icon="notify.tga" name="FriendshipAccepted" type="notify"> -[NAME] accepted your friendship offer. + [NAME] accepted your friendship offer. </notification> <notification icon="notify.tga" name="FriendshipDeclined" type="notify"> -[NAME] declined your friendship offer. + [NAME] declined your friendship offer. </notification> <notification icon="notify.tga" name="OfferCallingCard" type="notify"> -[FIRST] [LAST] is offering their calling card. -This will add a bookmark in your inventory so you can quickly IM this resident. + [FIRST] [LAST] is offering their calling card. + This will add a bookmark in your inventory so you can quickly IM this resident. <form name="form"> <button index="0" @@ -5898,8 +5898,8 @@ This will add a bookmark in your inventory so you can quickly IM this resident. priority="high" sound="UISndAlert" type="notify"> -Region is restarting in [MINUTES] minutes. -If you remain in this region you will be logged out. + Region is restarting in [MINUTES] minutes. + If you remain in this region you will be logged out. </notification> <notification @@ -5908,19 +5908,19 @@ If you remain in this region you will be logged out. priority="high" sound="UISndAlert" type="notify"> -Region is restarting in [SECONDS] seconds. -If you remain in this region you will be logged out. + Region is restarting in [SECONDS] seconds. + If you remain in this region you will be logged out. </notification> <notification icon="notify.tga" name="LoadWebPage" type="notify"> -Load web page [URL]? + Load web page [URL]? -[MESSAGE] + [MESSAGE] -From object: [OBJECTNAME], owner: [NAME]? + From object: [OBJECTNAME], owner: [NAME]? <form name="form"> <button index="0" @@ -5937,14 +5937,14 @@ From object: [OBJECTNAME], owner: [NAME]? icon="notify.tga" name="FailedToFindWearableUnnamed" type="notify"> -Failed to find [TYPE] in database. + Failed to find [TYPE] in database. </notification> <notification icon="notify.tga" name="FailedToFindWearable" type="notify"> -Failed to find [TYPE] named [DESC] in database. + Failed to find [TYPE] named [DESC] in database. </notification> <notification @@ -5958,10 +5958,10 @@ Failed to find [TYPE] named [DESC] in database. icon="notify.tga" name="ScriptQuestion" type="notify"> -'[OBJECTNAME]', an object owned by '[NAME]', would like to: + '[OBJECTNAME]', an object owned by '[NAME]', would like to: -[QUESTIONS] -Is this OK? + [QUESTIONS] + Is this OK? <form name="form"> <button index="0" @@ -5983,12 +5983,12 @@ Is this OK? name="ScriptQuestionCaution" priority="high" type="notify"> -'[OBJECTNAME]', an object owned by '[NAME]', would like to: + '[OBJECTNAME]', an object owned by '[NAME]', would like to: -[QUESTIONS] -If you do not trust this object and its creator, you should deny the request. For additional information, click the Details button. + [QUESTIONS] + If you do not trust this object and its creator, you should deny the request. For additional information, click the Details button. -Grant this request? + Grant this request? <form name="form"> <button index="0" @@ -6010,8 +6010,8 @@ Grant this request? icon="notify.tga" name="ScriptDialog" type="notify"> -[FIRST] [LAST]'s '[TITLE]' -[MESSAGE] + [FIRST] [LAST]'s '[TITLE]' + [MESSAGE] <form name="form"> <button index="-1" @@ -6024,8 +6024,8 @@ Grant this request? icon="notify.tga" name="ScriptDialogGroup" type="notify"> -[GROUPNAME]'s '[TITLE]' -[MESSAGE] + [GROUPNAME]'s '[TITLE]' + [MESSAGE] <form name="form"> <button index="-1" @@ -6038,142 +6038,142 @@ Grant this request? icon="notify.tga" name="FirstBalanceIncrease" type="notify"> -You just received L$[AMOUNT]. -Objects and other users may give you L$. -Your balance is shown in the upper-right corner of the screen. + You just received L$[AMOUNT]. + Objects and other users may give you L$. + Your balance is shown in the upper-right corner of the screen. </notification> <notification icon="notify.tga" name="FirstBalanceDecrease" type="notify"> -You just paid L$[AMOUNT]. -Your balance is shown in the upper-right corner of the screen. + You just paid L$[AMOUNT]. + Your balance is shown in the upper-right corner of the screen. </notification> <notification icon="notify.tga" name="FirstSit" type="notify"> -You are sitting. -Use the arrow keys (or AWSD) to change the view. -Click the 'Stand Up' button to get up. + You are sitting. + Use the arrow keys (or AWSD) to change the view. + Click the 'Stand Up' button to get up. </notification> <notification icon="notify.tga" name="FirstMap" type="notify"> -Click and drag to scroll the map. -Double-click to teleport. -Use the controls on the right to find things and display different backgrounds. + Click and drag to scroll the map. + Double-click to teleport. + Use the controls on the right to find things and display different backgrounds. </notification> <notification icon="notify.tga" name="FirstBuild" type="notify"> -You can build new objects in some areas of [SECOND_LIFE]. -Use the tools in the upper left to build, and try holding down Ctrl or Alt to rapidly switch tools. -Press Esc to stop building. + You can build new objects in some areas of [SECOND_LIFE]. + Use the tools in the upper left to build, and try holding down Ctrl or Alt to rapidly switch tools. + Press Esc to stop building. </notification> <notification icon="notify.tga" name="FirstLeftClickNoHit" type="notify"> -Left-clicking interacts with special objects. -If the mouse pointer changes to a hand, you can interact with the object. -Right-click always shows a menu of things you can do. + Left-clicking interacts with special objects. + If the mouse pointer changes to a hand, you can interact with the object. + Right-click always shows a menu of things you can do. </notification> <notification icon="notify.tga" name="FirstTeleport" type="notify"> -This region doesn't allow point-to-point teleports, so you've been transported to the nearest telehub. -Your destination is marked with a tall beacon. -Follow the red arrow to the beacon, or click the arrow to dismiss the beacon. + This region doesn't allow point-to-point teleports, so you've been transported to the nearest telehub. + Your destination is marked with a tall beacon. + Follow the red arrow to the beacon, or click the arrow to dismiss the beacon. </notification> <notification icon="notify.tga" name="FirstOverrideKeys" type="notify"> -Your movement keys are now being handled by an object. -Try the arrow keys or AWSD to see what they do. -Some objects (like guns) require you to go into mouselook to use them. -Press 'M' to do this. + Your movement keys are now being handled by an object. + Try the arrow keys or AWSD to see what they do. + Some objects (like guns) require you to go into mouselook to use them. + Press 'M' to do this. </notification> <notification icon="notify.tga" name="FirstAppearance" type="notify"> -You are editing your appearance. -To rotate and zoom view, use the arrow keys. -When you are finished, press 'Save All' to save your look and exit. -You can edit your appearance as often as you like. + You are editing your appearance. + To rotate and zoom view, use the arrow keys. + When you are finished, press 'Save All' to save your look and exit. + You can edit your appearance as often as you like. </notification> <notification icon="notify.tga" name="FirstInventory" type="notify"> -This is your inventory, which contains objects, notecards, clothing, and other things you own. -* To wear an object or outfit folder, drag it onto yourself. -* To bring an object into the world, drag it onto the ground. -* To read a notecard, double-click it. + This is your inventory, which contains objects, notecards, clothing, and other things you own. + * To wear an object or outfit folder, drag it onto yourself. + * To bring an object into the world, drag it onto the ground. + * To read a notecard, double-click it. </notification> <notification icon="notify.tga" name="FirstSandbox" type="notify"> -This is a sandbox region. -Objects you build here may be deleted after you leave the area, Sandboxes clean on a regular basis, please refer to the information at the top of the screen next to the region name. + This is a sandbox region. + Objects you build here may be deleted after you leave the area, Sandboxes clean on a regular basis, please refer to the information at the top of the screen next to the region name. -Sandbox regions are uncommon, and are marked with signs. + Sandbox regions are uncommon, and are marked with signs. </notification> <notification icon="notify.tga" name="FirstFlexible" type="notify"> -This object is flexible. -Flexible objects may not be physical and must be phantom until the flexible checkbox is unchecked. + This object is flexible. + Flexible objects may not be physical and must be phantom until the flexible checkbox is unchecked. </notification> <notification icon="notify.tga" name="FirstDebugMenus" type="notify"> -You have enabled the Advanced menu. -This menu contains features useful for developers debugging Second Life. -To toggle this menu on Windows press Ctrl-Alt-D. On Mac press Cmd-Opt-Shift-D. + You have enabled the Advanced menu. + This menu contains features useful for developers debugging Second Life. + To toggle this menu on Windows press Ctrl-Alt-D. On Mac press Cmd-Opt-Shift-D. </notification> <notification icon="notify.tga" name="FirstSculptedPrim" type="notify"> -You are editing a sculpted prim. -Sculpted prims require a special texture to specify their shape. -You can find example sculpted textures in the inventory library. + You are editing a sculpted prim. + Sculpted prims require a special texture to specify their shape. + You can find example sculpted textures in the inventory library. </notification> <notification icon="notify.tga" name="FirstMedia" type="notify"> -You have begun playing media. Media can set to play automatically in the preferences window under Audio / Video. Note that this can be a security risk for media sites you do not trust. + You have begun playing media. Media can set to play automatically in the preferences window under Audio / Video. Note that this can be a security risk for media sites you do not trust. </notification> <notification icon="notifytip.tga" name="MaxListSelectMessage" type="notifytip"> -You may only select up to [MAX_SELECT] items from this list. + You may only select up to [MAX_SELECT] items from this list. </notification> <notification @@ -6302,7 +6302,7 @@ Click Accept to join the chat or Decline to decline the invitation. Click Block icon="notifytip.tga" name="VoiceChannelFull" type="notifytip"> -The voice call you are trying to join, [VOICE_CHANNEL_NAME], has reached maximum capacity. Please try again later. + The voice call you are trying to join, [VOICE_CHANNEL_NAME], has reached maximum capacity. Please try again later. <unique> <context key="VOICE_CHANNEL_NAME"/> </unique> @@ -6312,7 +6312,7 @@ The voice call you are trying to join, [VOICE_CHANNEL_NAME], has reached maximum icon="notifytip.tga" name="ProximalVoiceChannelFull" type="notifytip"> -We're sorry. This area has reached maximum capacity for voice conversations. Please try to use voice in another area. + We're sorry. This area has reached maximum capacity for voice conversations. Please try to use voice in another area. <unique/> </notification> @@ -6320,7 +6320,7 @@ We're sorry. This area has reached maximum capacity for voice conversation icon="notifytip.tga" name="VoiceChannelDisconnected" type="notifytip"> -You have been disconnected from [VOICE_CHANNEL_NAME]. You will now be reconnected to spatial voice chat. + You have been disconnected from [VOICE_CHANNEL_NAME]. You will now be reconnected to spatial voice chat. <unique> <context key="VOICE_CHANNEL_NAME"/> </unique> @@ -6330,7 +6330,7 @@ You have been disconnected from [VOICE_CHANNEL_NAME]. You will now be reconnect icon="notifytip.tga" name="VoiceChannelDisconnectedP2P" type="notifytip"> -[VOICE_CHANNEL_NAME] has ended the call. You will now be reconnected to spatial voice chat. + [VOICE_CHANNEL_NAME] has ended the call. You will now be reconnected to spatial voice chat. <unique> <context key="VOICE_CHANNEL_NAME"/> </unique> @@ -6340,7 +6340,7 @@ You have been disconnected from [VOICE_CHANNEL_NAME]. You will now be reconnect icon="notifytip.tga" name="P2PCallDeclined" type="notifytip"> -[VOICE_CHANNEL_NAME] has declined your call. You will now be reconnected to spatial voice chat. + [VOICE_CHANNEL_NAME] has declined your call. You will now be reconnected to spatial voice chat. <unique> <context key="VOICE_CHANNEL_NAME"/> </unique> @@ -6350,7 +6350,7 @@ You have been disconnected from [VOICE_CHANNEL_NAME]. You will now be reconnect icon="notifytip.tga" name="P2PCallNoAnswer" type="notifytip"> -[VOICE_CHANNEL_NAME] is not available to take your call. You will now be reconnected to spatial voice chat. + [VOICE_CHANNEL_NAME] is not available to take your call. You will now be reconnected to spatial voice chat. <unique> <context key="VOICE_CHANNEL_NAME"/> </unique> @@ -6360,7 +6360,7 @@ You have been disconnected from [VOICE_CHANNEL_NAME]. You will now be reconnect icon="notifytip.tga" name="VoiceChannelJoinFailed" type="notifytip"> -Failed to connect to [VOICE_CHANNEL_NAME], please try again later. You will now be reconnected to spatial voice chat. + Failed to connect to [VOICE_CHANNEL_NAME], please try again later. You will now be reconnected to spatial voice chat. <unique> <context key="VOICE_CHANNEL_NAME"/> </unique> @@ -6371,7 +6371,7 @@ Failed to connect to [VOICE_CHANNEL_NAME], please try again later. You will now icon="notifytip.tga" name="VoiceLoginRetry" type="notifytip"> -We are creating a voice channel for you. This may take up to one minute. + We are creating a voice channel for you. This may take up to one minute. <unique/> </notification> @@ -6379,28 +6379,28 @@ We are creating a voice channel for you. This may take up to one minute. icon="notifytip.tga" name="Cannot enter parcel: not a group member" type="notifytip"> -Cannot enter parcel, you are not a member of the appropriate group. + Cannot enter parcel, you are not a member of the appropriate group. </notification> <notification icon="notifytip.tga" name="Cannot enter parcel: banned" type="notifytip"> -Cannot enter parcel, you have been banned. + Cannot enter parcel, you have been banned. </notification> <notification icon="notifytip.tga" name="Cannot enter parcel: not on access list" type="notifytip"> -Cannot enter parcel, you are not on the access list. + Cannot enter parcel, you are not on the access list. </notification> <notification icon="notifytip.tga" name="VoiceNotAllowed" type="notifytip"> -You do not have permission to connect to voice chat for [VOICE_CHANNEL_NAME]. + You do not have permission to connect to voice chat for [VOICE_CHANNEL_NAME]. <unique> <context key="VOICE_CHANNEL_NAME"/> </unique> @@ -6410,7 +6410,7 @@ You do not have permission to connect to voice chat for [VOICE_CHANNEL_NAME]. icon="notifytip.tga" name="VoiceCallGenericError" type="notifytip"> -An error has occurred while trying to connect to voice chat for [VOICE_CHANNEL_NAME]. Please try again later. + An error has occurred while trying to connect to voice chat for [VOICE_CHANNEL_NAME]. Please try again later. <unique> <context key="VOICE_CHANNEL_NAME"/> </unique> @@ -6422,7 +6422,7 @@ An error has occurred while trying to connect to voice chat for [VOICE_CHANNEL_N name="ServerVersionChanged" priority="high" type="notifytip"> -The region you have entered is running a different simulator version. Click this message for details. + The region you have entered is running a different simulator version. Click this message for details. </notification> <notification @@ -6430,7 +6430,14 @@ The region you have entered is running a different simulator version. Click this name="UnableToOpenCommandURL" priority="high" type="notifytip"> -The URL you clicked cannot be opened from this web browser. + The URL you clicked cannot be opened from this web browser. + </notification> + + <notification name="IMToast" type="notify"> + [MESSAGE] + <form name="form"> + <button index="0" name="respondbutton" text="Respond"/> + </form> </notification> <global name="UnsupportedCPU"> diff --git a/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml b/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml index 7b802fb5b3e54aa74f97d287c6b7a6b163c59933..61ba76aa2801071ed85bbb7e0e7759e8e87ac3ec 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml @@ -40,7 +40,7 @@ width="100"> </check_box> <combo_box - make_visible_control="WindowFullScreen" + visiblity_control="WindowFullScreen" allow_text_entry="true" height="16" layout="topleft" @@ -208,7 +208,7 @@ Ultra </text> <panel - make_visible_control="ShowAdvancedGraphicsSettings" + visiblity_control="ShowAdvancedGraphicsSettings" border="false" follows="top|left" height="260" diff --git a/indra/newview/skins/default/xui/en/panel_region_general.xml b/indra/newview/skins/default/xui/en/panel_region_general.xml index 90cc209a687f96ff16366e5ca2660b5dd5ddcbc0..8ea1a05e97153b6cabf84553e395dcfbba473aec 100644 --- a/indra/newview/skins/default/xui/en/panel_region_general.xml +++ b/indra/newview/skins/default/xui/en/panel_region_general.xml @@ -310,7 +310,10 @@ left="108" name="apply_btn" top="320" - width="100" /> + width="100"> + <button.commit_callback + function="RegionInfo.Cancel" /> + </button> <button follows="left|top" height="20" diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index c21c691680db488e2fff17cdc2beef52d11ada70..e8027b1b4b25e126c9f729ae080c836e283675f9 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -341,36 +341,39 @@ You do not have a copy of this texture in your inventory </string> - <string name="no_transfer"> (no transfer)</string> - <string name="no_modify"> (no modify)</string> - <string name="no_copy"> (no copy)</string> - <string name="worn"> (worn)</string> + <!-- use value="" because they have preceding spaces --> + <string name="no_transfer" value=" (no transfer)" /> + <string name="no_modify" value=" (no modify)" /> + <string name="no_copy" value=" (no copy)" /> + <string name="worn" value=" (worn)" /> <string name="LoadingContents">Loading contents...</string> <string name="NoContents">No contents</string> <!-- Gestures labels --> - <string name="Chat"> Chat : </string> - <string name="Sound"> Sound : </string> - <string name="Wait"> --- Wait : </string> - <string name="AnimFlagStop"> Stop Animation : </string> - <string name="AnimFlagStart"> Start Animation : </string> - <string name="Wave"> Wave </string> - <string name="HelloAvatar"> Hello, avatar! </string> + <!-- use value="" because they have preceding spaces --> + <string name="Chat" value=" Chat : " /> + <string name="Sound" value=" Sound : " /> + <string name="Wait" value=" --- Wait : " /> + <string name="AnimFlagStop" value=" Stop Animation : " /> + <string name="AnimFlagStart" value=" Start Animation : " /> + <string name="Wave" value=" Wave " /> + <string name="HelloAvatar" value=" Hello, avatar! " /> <!-- inventory filter --> - <string name="Animations"> Animations,</string> - <string name="Calling Cards"> Calling Cards,</string> - <string name="Clothing"> Clothing,</string> - <string name="Gestures"> Gestures,</string> - <string name="Landmarks"> Landmarks,</string> - <string name="Notecards"> Notecards,</string> - <string name="Objects"> Objects,</string> - <string name="Scripts"> Scripts,</string> - <string name="Sounds"> Sounds,</string> - <string name="Textures"> Textures,</string> - <string name="Snapshots"> Snapshots,</string> - <string name="No Filters"> No </string> - <string name="Since Logoff"> - Since Logoff</string> + <!-- use value="" because they have preceding spaces --> + <string name="Animations" value=" Animations," /> + <string name="Calling Cards" value=" Calling Cards," /> + <string name="Clothing" value=" Clothing," /> + <string name="Gestures" value=" Gestures," /> + <string name="Landmarks" value=" Landmarks," /> + <string name="Notecards" value=" Notecards," /> + <string name="Objects" value=" Objects," /> + <string name="Scripts" value=" Scripts," /> + <string name="Sounds" value=" Sounds," /> + <string name="Textures" value=" Textures," /> + <string name="Snapshots" value=" Snapshots," /> + <string name="No Filters" value="No " /> + <string name="Since Logoff" value=" - Since Logoff" /> <!-- inventory folder --> <string name="InvFolder My Inventory">My Inventory</string> @@ -397,10 +400,6 @@ this texture in your inventory <string name="InvFolder favorite">Favorites</string> <!-- inventory FVBridge --> - <string name="NO_COPY"> (no copy)</string> - <string name="NO_MOD"> (no modify)</string> - <string name="NO_XFER"> (no transfer)</string> - <string name="Buy">Buy</string> <string name="BuyforL$">Buy for L$</string> @@ -486,13 +485,11 @@ this texture in your inventory <!-- groups --> <string name="GroupsNone">none</string> - <string name="Group"> (group)</string> + <string name="Group" value=" (group)" /> <string name="Unknown">(Unknown)</string> - <string name="SummaryForTheWeek">Summary for this week, beginning on </string> - <string name="NextStipendDay">The next stipend day is </string> - <string name="GroupIndividualShare"> Group Individual Share - - </string> + <string name="SummaryForTheWeek" value="Summary for this week, beginning on " /> + <string name="NextStipendDay" value="The next stipend day is " /> + <string name="GroupIndividualShare" value=" Group Individual Share" /> <string name="Balance">Balance</string> <string name="Credits">Credits</string> <string name="Debits">Debits</string> @@ -544,8 +541,8 @@ you managed for [OWNER] <string name="RegionNoCovenant">There is no Covenant provided for this Estate.</string> <string name="RegionNoCovenantOtherOwner">There is no Covenant provided for this Estate. The land on this estate is being sold by the Estate owner, not Linden Lab. Please contact the Estate Owner for sales details.</string> <string name="covenant_last_modified">Last Modified:</string> - <string name="none_text"> (none) </string> - <string name="never_text"> (never) </string> + <string name="none_text" value=" (none) " /> + <string name="never_text" value=" (never) " /> <!--Region Details--> <string name="GroupOwned">Group Owned</string> diff --git a/indra/newview/skins/default/xui/en/widgets/list_view.xml b/indra/newview/skins/default/xui/en/widgets/list_view.xml new file mode 100644 index 0000000000000000000000000000000000000000..c66aeb57a0da8b7464ea83839d60e3967eac8667 --- /dev/null +++ b/indra/newview/skins/default/xui/en/widgets/list_view.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<list_view + fg_selected_color="ListViewSelectedFgColor" + bg_selected_color="ListViewSelectedBgColor" + bg_color="ListViewBgColor" + />