diff options
Diffstat (limited to 'indra/newview/llfloateruipreview.cpp')
-rw-r--r-- | indra/newview/llfloateruipreview.cpp | 2664 |
1 files changed, 1332 insertions, 1332 deletions
diff --git a/indra/newview/llfloateruipreview.cpp b/indra/newview/llfloateruipreview.cpp index 553d09bec2..4db76c7971 100644 --- a/indra/newview/llfloateruipreview.cpp +++ b/indra/newview/llfloateruipreview.cpp @@ -5,21 +5,21 @@ * $LicenseInfo:firstyear=2008&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -30,9 +30,9 @@ // *TODO: Translate error messgaes using notifications/alerts.xml -#include "llviewerprecompiledheaders.h" // Precompiled headers +#include "llviewerprecompiledheaders.h" // Precompiled headers -#include "llfloateruipreview.h" // Own header +#include "llfloateruipreview.h" // Own header // Internal utility #include "lldiriterator.h" @@ -56,10 +56,10 @@ #include "lltooltip.h" #include "llviewermenu.h" #include "llrngwriter.h" -#include "llfloater.h" // superclass +#include "llfloater.h" // superclass #include "llfloaterreg.h" -#include "llscrollcontainer.h" // scroll container for overlapping elements -#include "lllivefile.h" // live file poll/stat/reload +#include "llscrollcontainer.h" // scroll container for overlapping elements +#include "lllivefile.h" // live file poll/stat/reload #include "llviewermenufile.h" // LLFilePickerReplyThread // Boost (for linux/unix command-line execv) @@ -84,8 +84,8 @@ static LLDefaultChildRegistry::Register<LLOverlapPanel> register_overlap_panel(" static std::string get_xui_dir() { - std::string delim = gDirUtilp->getDirDelimiter(); - return gDirUtilp->getSkinBaseDir() + delim + "default" + delim + "xui" + delim; + std::string delim = gDirUtilp->getDirDelimiter(); + return gDirUtilp->getSkinBaseDir() + delim + "default" + delim + "xui" + delim; } // Forward declarations to avoid header dependencies @@ -107,115 +107,115 @@ class LLPreviewedFloater; class LLOverlapPanel : public LLPanel { public: - struct Params : public LLInitParam::Block<Params, LLPanel::Params> - { - Params() {} - }; - LLOverlapPanel(Params p = Params()) : LLPanel(p), - mSpacing(10), - // mClickedElement(NULL), - mLastClickedElement(NULL) - { - mOriginalWidth = getRect().getWidth(); - mOriginalHeight = getRect().getHeight(); - } - virtual void draw(); - - typedef std::map<LLView*, std::list<LLView*> > OverlapMap; - OverlapMap mOverlapMap; // map, of XUI element to a list of XUI elements it overlaps - - // LLView *mClickedElement; - LLView *mLastClickedElement; - int mOriginalWidth, mOriginalHeight, mSpacing; + struct Params : public LLInitParam::Block<Params, LLPanel::Params> + { + Params() {} + }; + LLOverlapPanel(Params p = Params()) : LLPanel(p), + mSpacing(10), + // mClickedElement(NULL), + mLastClickedElement(NULL) + { + mOriginalWidth = getRect().getWidth(); + mOriginalHeight = getRect().getHeight(); + } + virtual void draw(); + + typedef std::map<LLView*, std::list<LLView*> > OverlapMap; + OverlapMap mOverlapMap; // map, of XUI element to a list of XUI elements it overlaps + + // LLView *mClickedElement; + LLView *mLastClickedElement; + int mOriginalWidth, mOriginalHeight, mSpacing; }; class LLFloaterUIPreview : public LLFloater { public: - // Setup - LLFloaterUIPreview(const LLSD& key); - virtual ~LLFloaterUIPreview(); - - std::string getLocStr(S32 ID); // fetches the localization string based on what is selected in the drop-down menu - void displayFloater(BOOL click, S32 ID); // needs to be public so live file can call it when it finds an update - - /*virtual*/ BOOL postBuild(); - /*virtual*/ void onClose(bool app_quitting); - - void refreshList(); // refresh list (empty it out and fill it up from scratch) - void addFloaterEntry(const std::string& path); // add a single file's entry to the list of floaters - - static BOOL containerType(LLView* viewp); // check if the element is a container type and tree traverses need to look at its children - -public: - LLPreviewedFloater* mDisplayedFloater; // the floater which is currently being displayed - LLPreviewedFloater* mDisplayedFloater_2; // the floater which is currently being displayed - LLGUIPreviewLiveFile* mLiveFile; // live file for checking for updates to the currently-displayed XML file - LLOverlapPanel* mOverlapPanel; // custom overlapping elements panel - // BOOL mHighlightingDiffs; // bool for whether localization diffs are being highlighted or not - BOOL mHighlightingOverlaps; // bool for whether overlapping elements are being highlighted - - // typedef std::map<std::string,std::pair<std::list<std::string>,std::list<std::string> > > DiffMap; // this version copies the lists etc., and thus is bad memory-wise - typedef std::list<std::string> StringList; - typedef std::shared_ptr<StringList> StringListPtr; - typedef std::map<std::string, std::pair<StringListPtr,StringListPtr> > DiffMap; - DiffMap mDiffsMap; // map, of filename to pair of list of changed element paths and list of errors + // Setup + LLFloaterUIPreview(const LLSD& key); + virtual ~LLFloaterUIPreview(); + + std::string getLocStr(S32 ID); // fetches the localization string based on what is selected in the drop-down menu + void displayFloater(BOOL click, S32 ID); // needs to be public so live file can call it when it finds an update + + /*virtual*/ BOOL postBuild(); + /*virtual*/ void onClose(bool app_quitting); + + void refreshList(); // refresh list (empty it out and fill it up from scratch) + void addFloaterEntry(const std::string& path); // add a single file's entry to the list of floaters + + static BOOL containerType(LLView* viewp); // check if the element is a container type and tree traverses need to look at its children + +public: + LLPreviewedFloater* mDisplayedFloater; // the floater which is currently being displayed + LLPreviewedFloater* mDisplayedFloater_2; // the floater which is currently being displayed + LLGUIPreviewLiveFile* mLiveFile; // live file for checking for updates to the currently-displayed XML file + LLOverlapPanel* mOverlapPanel; // custom overlapping elements panel + // BOOL mHighlightingDiffs; // bool for whether localization diffs are being highlighted or not + BOOL mHighlightingOverlaps; // bool for whether overlapping elements are being highlighted + + // typedef std::map<std::string,std::pair<std::list<std::string>,std::list<std::string> > > DiffMap; // this version copies the lists etc., and thus is bad memory-wise + typedef std::list<std::string> StringList; + typedef std::shared_ptr<StringList> StringListPtr; + typedef std::map<std::string, std::pair<StringListPtr,StringListPtr> > DiffMap; + DiffMap mDiffsMap; // map, of filename to pair of list of changed element paths and list of errors private: - LLExternalEditor mExternalEditor; - - // XUI elements for this floater - LLScrollListCtrl* mFileList; // scroll list control for file list - LLLineEditor* mEditorPathTextBox; // text field for path to editor executable - LLLineEditor* mEditorArgsTextBox; // text field for arguments to editor executable - LLLineEditor* mDiffPathTextBox; // text field for path to diff file - LLButton* mDisplayFloaterBtn; // button to display primary floater - LLButton* mDisplayFloaterBtn_2; // button to display secondary floater - LLButton* mEditFloaterBtn; // button to edit floater - LLButton* mExecutableBrowseButton; // button to browse for executable - LLButton* mCloseOtherButton; // button to close primary displayed floater - LLButton* mCloseOtherButton_2; // button to close secondary displayed floater - LLButton* mDiffBrowseButton; // button to browse for diff file - LLButton* mToggleHighlightButton; // button to toggle highlight of files/elements with diffs - LLButton* mToggleOverlapButton; // button to togle overlap panel/highlighting - LLComboBox* mLanguageSelection; // combo box for primary language selection - LLComboBox* mLanguageSelection_2; // combo box for secondary language selection - S32 mLastDisplayedX, mLastDisplayedY; // stored position of last floater so the new one opens up in the same place - std::string mDelim; // the OS-specific delimiter character (/ or \) (*TODO: this shouldn't be needed, right?) - - std::string mSavedEditorPath; // stored editor path so closing this floater doesn't reset it - std::string mSavedEditorArgs; // stored editor args so closing this floater doesn't reset it - std::string mSavedDiffPath; // stored diff file path so closing this floater doesn't reset it - - // Internal functionality - static void popupAndPrintWarning(const std::string& warning); // pop up a warning - std::string getLocalizedDirectory(); // build and return the path to the XUI directory for the currently-selected localization - void scanDiffFile(LLXmlTreeNode* file_node); // scan a given XML node for diff entries and highlight them in its associated file - void highlightChangedElements(); // look up the list of elements to highlight and highlight them in the current floater - void highlightChangedFiles(); // look up the list of changed files to highlight and highlight them in the scroll list - void findOverlapsInChildren(LLView* parent); // fill the map below with element overlap information - static BOOL overlapIgnorable(LLView* viewp); // check it the element can be ignored for overlap/localization purposes - - // check if two elements overlap using their rectangles - // used instead of llrect functions because by adding a few pixels of leeway I can cut down drastically on the number of overlaps - BOOL elementOverlap(LLView* view1, LLView* view2); - - // Button/drop-down action listeners (self explanatory) - void onClickDisplayFloater(S32 id); - void onClickSaveFloater(S32 id); - void onClickSaveAll(S32 id); - void onClickEditFloater(); - void onClickBrowseForEditor(); - void getExecutablePath(const std::vector<std::string>& filenames); - void onClickBrowseForDiffs(); - void getDiffsFilePath(const std::vector<std::string>& filenames); - void onClickToggleDiffHighlighting(); - void onClickToggleOverlapping(); - void onClickCloseDisplayedFloater(S32 id); - void onLanguageComboSelect(LLUICtrl* ctrl); - void onClickExportSchema(); - void onClickShowRectangles(const LLSD& data); + LLExternalEditor mExternalEditor; + + // XUI elements for this floater + LLScrollListCtrl* mFileList; // scroll list control for file list + LLLineEditor* mEditorPathTextBox; // text field for path to editor executable + LLLineEditor* mEditorArgsTextBox; // text field for arguments to editor executable + LLLineEditor* mDiffPathTextBox; // text field for path to diff file + LLButton* mDisplayFloaterBtn; // button to display primary floater + LLButton* mDisplayFloaterBtn_2; // button to display secondary floater + LLButton* mEditFloaterBtn; // button to edit floater + LLButton* mExecutableBrowseButton; // button to browse for executable + LLButton* mCloseOtherButton; // button to close primary displayed floater + LLButton* mCloseOtherButton_2; // button to close secondary displayed floater + LLButton* mDiffBrowseButton; // button to browse for diff file + LLButton* mToggleHighlightButton; // button to toggle highlight of files/elements with diffs + LLButton* mToggleOverlapButton; // button to togle overlap panel/highlighting + LLComboBox* mLanguageSelection; // combo box for primary language selection + LLComboBox* mLanguageSelection_2; // combo box for secondary language selection + S32 mLastDisplayedX, mLastDisplayedY; // stored position of last floater so the new one opens up in the same place + std::string mDelim; // the OS-specific delimiter character (/ or \) (*TODO: this shouldn't be needed, right?) + + std::string mSavedEditorPath; // stored editor path so closing this floater doesn't reset it + std::string mSavedEditorArgs; // stored editor args so closing this floater doesn't reset it + std::string mSavedDiffPath; // stored diff file path so closing this floater doesn't reset it + + // Internal functionality + static void popupAndPrintWarning(const std::string& warning); // pop up a warning + std::string getLocalizedDirectory(); // build and return the path to the XUI directory for the currently-selected localization + void scanDiffFile(LLXmlTreeNode* file_node); // scan a given XML node for diff entries and highlight them in its associated file + void highlightChangedElements(); // look up the list of elements to highlight and highlight them in the current floater + void highlightChangedFiles(); // look up the list of changed files to highlight and highlight them in the scroll list + void findOverlapsInChildren(LLView* parent); // fill the map below with element overlap information + static BOOL overlapIgnorable(LLView* viewp); // check it the element can be ignored for overlap/localization purposes + + // check if two elements overlap using their rectangles + // used instead of llrect functions because by adding a few pixels of leeway I can cut down drastically on the number of overlaps + BOOL elementOverlap(LLView* view1, LLView* view2); + + // Button/drop-down action listeners (self explanatory) + void onClickDisplayFloater(S32 id); + void onClickSaveFloater(S32 id); + void onClickSaveAll(S32 id); + void onClickEditFloater(); + void onClickBrowseForEditor(); + void getExecutablePath(const std::vector<std::string>& filenames); + void onClickBrowseForDiffs(); + void getDiffsFilePath(const std::vector<std::string>& filenames); + void onClickToggleDiffHighlighting(); + void onClickToggleOverlapping(); + void onClickCloseDisplayedFloater(S32 id); + void onLanguageComboSelect(LLUICtrl* ctrl); + void onClickExportSchema(); + void onClickShowRectangles(const LLSD& data); }; //---------------------------------------------------------------------------- @@ -226,11 +226,11 @@ private: class LLLocalizationResetForcer { public: - LLLocalizationResetForcer(LLFloaterUIPreview* floater, S32 ID); - virtual ~LLLocalizationResetForcer(); + LLLocalizationResetForcer(LLFloaterUIPreview* floater, S32 ID); + virtual ~LLLocalizationResetForcer(); private: - std::string mSavedLocalization; // the localization before we change it + std::string mSavedLocalization; // the localization before we change it }; // Implementation of live file @@ -239,26 +239,26 @@ private: class LLGUIPreviewLiveFile : public LLLiveFile { public: - LLGUIPreviewLiveFile(std::string path, std::string name, LLFloaterUIPreview* parent); - virtual ~LLGUIPreviewLiveFile(); - LLFloaterUIPreview* mParent; - LLFadeEventTimer* mFadeTimer; // timer for fade-to-yellow-and-back effect to warn that file has been reloaded - BOOL mFirstFade; // setting this avoids showing the fade reload warning on first load - std::string mFileName; + LLGUIPreviewLiveFile(std::string path, std::string name, LLFloaterUIPreview* parent); + virtual ~LLGUIPreviewLiveFile(); + LLFloaterUIPreview* mParent; + LLFadeEventTimer* mFadeTimer; // timer for fade-to-yellow-and-back effect to warn that file has been reloaded + BOOL mFirstFade; // setting this avoids showing the fade reload warning on first load + std::string mFileName; protected: - bool loadFile(); + bool loadFile(); }; // Implementation of graphical fade in/out (on timer) for when XUI files are updated class LLFadeEventTimer : public LLEventTimer { public: - LLFadeEventTimer(F32 refresh, LLGUIPreviewLiveFile* parent); - BOOL tick(); - LLGUIPreviewLiveFile* mParent; + LLFadeEventTimer(F32 refresh, LLGUIPreviewLiveFile* parent); + BOOL tick(); + LLGUIPreviewLiveFile* mParent; private: - BOOL mFadingOut; // fades in then out; this is toggled in between - LLColor4 mOriginalColor; // original color; color is reset to this after fade is coimplete + BOOL mFadingOut; // fades in then out; this is toggled in between + LLColor4 mOriginalColor; // original color; color is reset to this after fade is coimplete }; // Implementation of previewed floater @@ -266,21 +266,21 @@ private: class LLPreviewedFloater : public LLFloater { public: - LLPreviewedFloater(LLFloaterUIPreview* floater, const Params& params) - : LLFloater(LLSD(), params), - mFloaterUIPreview(floater) - { - } + LLPreviewedFloater(LLFloaterUIPreview* floater, const Params& params) + : LLFloater(LLSD(), params), + mFloaterUIPreview(floater) + { + } - virtual void draw(); - BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); - BOOL handleToolTip(S32 x, S32 y, MASK mask); - BOOL selectElement(LLView* parent, int x, int y, int depth); // select element to display its overlappers + virtual void draw(); + BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); + BOOL handleToolTip(S32 x, S32 y, MASK mask); + BOOL selectElement(LLView* parent, int x, int y, int depth); // select element to display its overlappers - LLFloaterUIPreview* mFloaterUIPreview; + LLFloaterUIPreview* mFloaterUIPreview; - // draw widget outlines - static bool sShowRectangles; + // draw widget outlines + static bool sShowRectangles; }; bool LLPreviewedFloater::sShowRectangles = false; @@ -291,507 +291,507 @@ bool LLPreviewedFloater::sShowRectangles = false; // Changes are made here LLLocalizationResetForcer::LLLocalizationResetForcer(LLFloaterUIPreview* floater, S32 ID) { - mSavedLocalization = LLUI::getInstance()->mSettingGroups["config"]->getString("Language"); // save current localization setting - LLUI::getInstance()->mSettingGroups["config"]->setString("Language", floater->getLocStr(ID));// hack language to be the one we want to preview floaters in - // forcibly reset XUI paths with this new language - gDirUtilp->setSkinFolder(gDirUtilp->getSkinFolder(), floater->getLocStr(ID)); + mSavedLocalization = LLUI::getInstance()->mSettingGroups["config"]->getString("Language"); // save current localization setting + LLUI::getInstance()->mSettingGroups["config"]->setString("Language", floater->getLocStr(ID));// hack language to be the one we want to preview floaters in + // forcibly reset XUI paths with this new language + gDirUtilp->setSkinFolder(gDirUtilp->getSkinFolder(), floater->getLocStr(ID)); } // Actually reset in destructor // Changes are reversed here LLLocalizationResetForcer::~LLLocalizationResetForcer() { - LLUI::getInstance()->mSettingGroups["config"]->setString("Language", mSavedLocalization); // reset language to what it was before we changed it - // forcibly reset XUI paths with this new language - gDirUtilp->setSkinFolder(gDirUtilp->getSkinFolder(), mSavedLocalization); + LLUI::getInstance()->mSettingGroups["config"]->setString("Language", mSavedLocalization); // reset language to what it was before we changed it + // forcibly reset XUI paths with this new language + gDirUtilp->setSkinFolder(gDirUtilp->getSkinFolder(), mSavedLocalization); } // Live file constructor // Needs full path for LLLiveFile but needs just file name for this code, hence the reduntant arguments; easier than separating later LLGUIPreviewLiveFile::LLGUIPreviewLiveFile(std::string path, std::string name, LLFloaterUIPreview* parent) : mFileName(name), - mParent(parent), - mFirstFade(TRUE), - mFadeTimer(NULL), - LLLiveFile(path, 1.0) + mParent(parent), + mFirstFade(TRUE), + mFadeTimer(NULL), + LLLiveFile(path, 1.0) {} LLGUIPreviewLiveFile::~LLGUIPreviewLiveFile() { - mParent->mLiveFile = NULL; - if(mFadeTimer) - { - mFadeTimer->mParent = NULL; - // deletes itself; see lltimer.cpp - } + mParent->mLiveFile = NULL; + if(mFadeTimer) + { + mFadeTimer->mParent = NULL; + // deletes itself; see lltimer.cpp + } } // Live file load bool LLGUIPreviewLiveFile::loadFile() { - mParent->displayFloater(FALSE,1); // redisplay the floater - if(mFirstFade) // only fade if it wasn't just clicked on; can't use "clicked" BOOL below because of an oddity with setting LLLiveFile initial state - { - mFirstFade = FALSE; - } - else - { - if(mFadeTimer) - { - mFadeTimer->mParent = NULL; - } - mFadeTimer = new LLFadeEventTimer(0.05f,this); - } - return true; + mParent->displayFloater(FALSE,1); // redisplay the floater + if(mFirstFade) // only fade if it wasn't just clicked on; can't use "clicked" BOOL below because of an oddity with setting LLLiveFile initial state + { + mFirstFade = FALSE; + } + else + { + if(mFadeTimer) + { + mFadeTimer->mParent = NULL; + } + mFadeTimer = new LLFadeEventTimer(0.05f,this); + } + return true; } // Initialize fade event timer LLFadeEventTimer::LLFadeEventTimer(F32 refresh, LLGUIPreviewLiveFile* parent) - : mParent(parent), - mFadingOut(TRUE), - LLEventTimer(refresh) + : mParent(parent), + mFadingOut(TRUE), + LLEventTimer(refresh) { - mOriginalColor = mParent->mParent->mDisplayedFloater->getBackgroundColor(); + mOriginalColor = mParent->mParent->mDisplayedFloater->getBackgroundColor(); } // Single tick of fade event timer: increment the color BOOL LLFadeEventTimer::tick() { - float diff = 0.04f; - if(TRUE == mFadingOut) // set fade for in/out color direction - { - diff = -diff; - } - - if(NULL == mParent) // no more need to tick, so suicide - { - return TRUE; - } - - // Set up colors - LLColor4 bg_color = mParent->mParent->mDisplayedFloater->getBackgroundColor(); - LLSD colors = bg_color.getValue(); - LLSD colors_old = colors; - - // Tick colors - colors[0] = colors[0].asReal() - diff; if(colors[0].asReal() < mOriginalColor.getValue()[0].asReal()) { colors[0] = colors_old[0]; } - colors[1] = colors[1].asReal() - diff; if(colors[1].asReal() < mOriginalColor.getValue()[1].asReal()) { colors[1] = colors_old[1]; } - colors[2] = colors[2].asReal() + diff; if(colors[2].asReal() > mOriginalColor.getValue()[2].asReal()) { colors[2] = colors_old[2]; } - - // Clamp and set colors - bg_color.setValue(colors); - bg_color.clamp(); // make sure we didn't exceed [0,1] - mParent->mParent->mDisplayedFloater->setBackgroundColor(bg_color); - - if(bg_color[2] <= 0.0f) // end of fade out, start fading in - { - mFadingOut = FALSE; - } - - return FALSE; + float diff = 0.04f; + if(TRUE == mFadingOut) // set fade for in/out color direction + { + diff = -diff; + } + + if(NULL == mParent) // no more need to tick, so suicide + { + return TRUE; + } + + // Set up colors + LLColor4 bg_color = mParent->mParent->mDisplayedFloater->getBackgroundColor(); + LLSD colors = bg_color.getValue(); + LLSD colors_old = colors; + + // Tick colors + colors[0] = colors[0].asReal() - diff; if(colors[0].asReal() < mOriginalColor.getValue()[0].asReal()) { colors[0] = colors_old[0]; } + colors[1] = colors[1].asReal() - diff; if(colors[1].asReal() < mOriginalColor.getValue()[1].asReal()) { colors[1] = colors_old[1]; } + colors[2] = colors[2].asReal() + diff; if(colors[2].asReal() > mOriginalColor.getValue()[2].asReal()) { colors[2] = colors_old[2]; } + + // Clamp and set colors + bg_color.setValue(colors); + bg_color.clamp(); // make sure we didn't exceed [0,1] + mParent->mParent->mDisplayedFloater->setBackgroundColor(bg_color); + + if(bg_color[2] <= 0.0f) // end of fade out, start fading in + { + mFadingOut = FALSE; + } + + return FALSE; } // Constructor LLFloaterUIPreview::LLFloaterUIPreview(const LLSD& key) : LLFloater(key), - mDisplayedFloater(NULL), - mDisplayedFloater_2(NULL), - mLiveFile(NULL), - // sHighlightingDiffs(FALSE), - mHighlightingOverlaps(FALSE), - mLastDisplayedX(0), - mLastDisplayedY(0) + mDisplayedFloater(NULL), + mDisplayedFloater_2(NULL), + mLiveFile(NULL), + // sHighlightingDiffs(FALSE), + mHighlightingOverlaps(FALSE), + mLastDisplayedX(0), + mLastDisplayedY(0) { } // Destructor LLFloaterUIPreview::~LLFloaterUIPreview() { - // spawned floaters are deleted automatically, so we don't need to delete them here - - // save contents of textfields so it can be restored later if the floater is created again this session - mSavedEditorPath = mEditorPathTextBox->getText(); - mSavedEditorArgs = mEditorArgsTextBox->getText(); - mSavedDiffPath = mDiffPathTextBox->getText(); - - // delete live file if it exists - if(mLiveFile) - { - delete mLiveFile; - mLiveFile = NULL; - } + // spawned floaters are deleted automatically, so we don't need to delete them here + + // save contents of textfields so it can be restored later if the floater is created again this session + mSavedEditorPath = mEditorPathTextBox->getText(); + mSavedEditorArgs = mEditorArgsTextBox->getText(); + mSavedDiffPath = mDiffPathTextBox->getText(); + + // delete live file if it exists + if(mLiveFile) + { + delete mLiveFile; + mLiveFile = NULL; + } } // Perform post-build setup (defined in superclass) BOOL LLFloaterUIPreview::postBuild() { - LLPanel* main_panel_tmp = getChild<LLPanel>("main_panel"); // get a pointer to the main panel in order to... - mFileList = main_panel_tmp->getChild<LLScrollListCtrl>("name_list"); // save pointer to file list - // Double-click opens the floater, for convenience - mFileList->setDoubleClickCallback(boost::bind(&LLFloaterUIPreview::onClickDisplayFloater, this, PRIMARY_FLOATER)); - - setDefaultBtn("display_floater"); - // get pointers to buttons and link to callbacks - mLanguageSelection = main_panel_tmp->getChild<LLComboBox>("language_select_combo"); - mLanguageSelection->setCommitCallback(boost::bind(&LLFloaterUIPreview::onLanguageComboSelect, this, mLanguageSelection)); - mLanguageSelection_2 = main_panel_tmp->getChild<LLComboBox>("language_select_combo_2"); - mLanguageSelection_2->setCommitCallback(boost::bind(&LLFloaterUIPreview::onLanguageComboSelect, this, mLanguageSelection)); - LLPanel* editor_panel_tmp = main_panel_tmp->getChild<LLPanel>("editor_panel"); - mDisplayFloaterBtn = main_panel_tmp->getChild<LLButton>("display_floater"); - mDisplayFloaterBtn->setClickedCallback(boost::bind(&LLFloaterUIPreview::onClickDisplayFloater, this, PRIMARY_FLOATER)); - mDisplayFloaterBtn_2 = main_panel_tmp->getChild<LLButton>("display_floater_2"); - mDisplayFloaterBtn_2->setClickedCallback(boost::bind(&LLFloaterUIPreview::onClickDisplayFloater, this, SECONDARY_FLOATER)); - mToggleOverlapButton = main_panel_tmp->getChild<LLButton>("toggle_overlap_panel"); - mToggleOverlapButton->setClickedCallback(boost::bind(&LLFloaterUIPreview::onClickToggleOverlapping, this)); - mCloseOtherButton = main_panel_tmp->getChild<LLButton>("close_displayed_floater"); - mCloseOtherButton->setClickedCallback(boost::bind(&LLFloaterUIPreview::onClickCloseDisplayedFloater, this, PRIMARY_FLOATER)); - mCloseOtherButton_2 = main_panel_tmp->getChild<LLButton>("close_displayed_floater_2"); - mCloseOtherButton_2->setClickedCallback(boost::bind(&LLFloaterUIPreview::onClickCloseDisplayedFloater, this, SECONDARY_FLOATER)); - mEditFloaterBtn = main_panel_tmp->getChild<LLButton>("edit_floater"); - mEditFloaterBtn->setClickedCallback(boost::bind(&LLFloaterUIPreview::onClickEditFloater, this)); - mExecutableBrowseButton = editor_panel_tmp->getChild<LLButton>("browse_for_executable"); - LLPanel* vlt_panel_tmp = main_panel_tmp->getChild<LLPanel>("vlt_panel"); - mExecutableBrowseButton->setClickedCallback(boost::bind(&LLFloaterUIPreview::onClickBrowseForEditor, this)); - mDiffBrowseButton = vlt_panel_tmp->getChild<LLButton>("browse_for_vlt_diffs"); - mDiffBrowseButton->setClickedCallback(boost::bind(&LLFloaterUIPreview::onClickBrowseForDiffs, this)); - mToggleHighlightButton = vlt_panel_tmp->getChild<LLButton>("toggle_vlt_diff_highlight"); - mToggleHighlightButton->setClickedCallback(boost::bind(&LLFloaterUIPreview::onClickToggleDiffHighlighting, this)); - main_panel_tmp->getChild<LLButton>("save_floater")->setClickedCallback(boost::bind(&LLFloaterUIPreview::onClickSaveFloater, this, PRIMARY_FLOATER)); - main_panel_tmp->getChild<LLButton>("save_all_floaters")->setClickedCallback(boost::bind(&LLFloaterUIPreview::onClickSaveAll, this, PRIMARY_FLOATER)); - - getChild<LLButton>("export_schema")->setClickedCallback(boost::bind(&LLFloaterUIPreview::onClickExportSchema, this)); - getChild<LLUICtrl>("show_rectangles")->setCommitCallback( - boost::bind(&LLFloaterUIPreview::onClickShowRectangles, this, _2)); - - // get pointers to text fields - mEditorPathTextBox = editor_panel_tmp->getChild<LLLineEditor>("executable_path_field"); - mEditorArgsTextBox = editor_panel_tmp->getChild<LLLineEditor>("executable_args_field"); - mDiffPathTextBox = vlt_panel_tmp->getChild<LLLineEditor>("vlt_diff_path_field"); - - // *HACK: restored saved editor path and args to textfields - mEditorPathTextBox->setText(mSavedEditorPath); - mEditorArgsTextBox->setText(mSavedEditorArgs); - mDiffPathTextBox->setText(mSavedDiffPath); - - // Set up overlap panel - mOverlapPanel = getChild<LLOverlapPanel>("overlap_panel"); - - getChildView("overlap_scroll")->setVisible( mHighlightingOverlaps); - - mDelim = gDirUtilp->getDirDelimiter(); // initialize delimiter to dir sep slash - - // refresh list of available languages (EN will still be default) - BOOL found = TRUE; - BOOL found_en_us = FALSE; - std::string language_directory; - std::string xui_dir = get_xui_dir(); // directory containing localizations -- don't forget trailing delim - mLanguageSelection->removeall(); // clear out anything temporarily in list from XML - - LLDirIterator iter(xui_dir, "*"); - while(found) // for every directory - { - if((found = iter.next(language_directory))) // get next directory - { - std::string full_path = gDirUtilp->add(xui_dir, language_directory); - if(LLFile::isfile(full_path.c_str())) // if it's not a directory, skip it - { - continue; - } - - if(strncmp("template",language_directory.c_str(),8) && -1 == language_directory.find(".")) // if it's not the template directory or a hidden directory - { - if(!strncmp("en",language_directory.c_str(),5)) // remember if we've seen en, so we can make it default - { - found_en_us = TRUE; - } - else - { - mLanguageSelection->add(std::string(language_directory)); // add it to the language selection dropdown menu - mLanguageSelection_2->add(std::string(language_directory)); - } - } - } - } - if(found_en_us) - { - mLanguageSelection->add(std::string("en"),ADD_TOP); // make en first item if we found it - mLanguageSelection_2->add(std::string("en"),ADD_TOP); - } - else - { - std::string warning = std::string("No EN localization found; check your XUI directories!"); - popupAndPrintWarning(warning); - } - mLanguageSelection->selectFirstItem(); // select the first item - mLanguageSelection_2->selectFirstItem(); - - refreshList(); // refresh the list of available floaters - - return TRUE; + LLPanel* main_panel_tmp = getChild<LLPanel>("main_panel"); // get a pointer to the main panel in order to... + mFileList = main_panel_tmp->getChild<LLScrollListCtrl>("name_list"); // save pointer to file list + // Double-click opens the floater, for convenience + mFileList->setDoubleClickCallback(boost::bind(&LLFloaterUIPreview::onClickDisplayFloater, this, PRIMARY_FLOATER)); + + setDefaultBtn("display_floater"); + // get pointers to buttons and link to callbacks + mLanguageSelection = main_panel_tmp->getChild<LLComboBox>("language_select_combo"); + mLanguageSelection->setCommitCallback(boost::bind(&LLFloaterUIPreview::onLanguageComboSelect, this, mLanguageSelection)); + mLanguageSelection_2 = main_panel_tmp->getChild<LLComboBox>("language_select_combo_2"); + mLanguageSelection_2->setCommitCallback(boost::bind(&LLFloaterUIPreview::onLanguageComboSelect, this, mLanguageSelection)); + LLPanel* editor_panel_tmp = main_panel_tmp->getChild<LLPanel>("editor_panel"); + mDisplayFloaterBtn = main_panel_tmp->getChild<LLButton>("display_floater"); + mDisplayFloaterBtn->setClickedCallback(boost::bind(&LLFloaterUIPreview::onClickDisplayFloater, this, PRIMARY_FLOATER)); + mDisplayFloaterBtn_2 = main_panel_tmp->getChild<LLButton>("display_floater_2"); + mDisplayFloaterBtn_2->setClickedCallback(boost::bind(&LLFloaterUIPreview::onClickDisplayFloater, this, SECONDARY_FLOATER)); + mToggleOverlapButton = main_panel_tmp->getChild<LLButton>("toggle_overlap_panel"); + mToggleOverlapButton->setClickedCallback(boost::bind(&LLFloaterUIPreview::onClickToggleOverlapping, this)); + mCloseOtherButton = main_panel_tmp->getChild<LLButton>("close_displayed_floater"); + mCloseOtherButton->setClickedCallback(boost::bind(&LLFloaterUIPreview::onClickCloseDisplayedFloater, this, PRIMARY_FLOATER)); + mCloseOtherButton_2 = main_panel_tmp->getChild<LLButton>("close_displayed_floater_2"); + mCloseOtherButton_2->setClickedCallback(boost::bind(&LLFloaterUIPreview::onClickCloseDisplayedFloater, this, SECONDARY_FLOATER)); + mEditFloaterBtn = main_panel_tmp->getChild<LLButton>("edit_floater"); + mEditFloaterBtn->setClickedCallback(boost::bind(&LLFloaterUIPreview::onClickEditFloater, this)); + mExecutableBrowseButton = editor_panel_tmp->getChild<LLButton>("browse_for_executable"); + LLPanel* vlt_panel_tmp = main_panel_tmp->getChild<LLPanel>("vlt_panel"); + mExecutableBrowseButton->setClickedCallback(boost::bind(&LLFloaterUIPreview::onClickBrowseForEditor, this)); + mDiffBrowseButton = vlt_panel_tmp->getChild<LLButton>("browse_for_vlt_diffs"); + mDiffBrowseButton->setClickedCallback(boost::bind(&LLFloaterUIPreview::onClickBrowseForDiffs, this)); + mToggleHighlightButton = vlt_panel_tmp->getChild<LLButton>("toggle_vlt_diff_highlight"); + mToggleHighlightButton->setClickedCallback(boost::bind(&LLFloaterUIPreview::onClickToggleDiffHighlighting, this)); + main_panel_tmp->getChild<LLButton>("save_floater")->setClickedCallback(boost::bind(&LLFloaterUIPreview::onClickSaveFloater, this, PRIMARY_FLOATER)); + main_panel_tmp->getChild<LLButton>("save_all_floaters")->setClickedCallback(boost::bind(&LLFloaterUIPreview::onClickSaveAll, this, PRIMARY_FLOATER)); + + getChild<LLButton>("export_schema")->setClickedCallback(boost::bind(&LLFloaterUIPreview::onClickExportSchema, this)); + getChild<LLUICtrl>("show_rectangles")->setCommitCallback( + boost::bind(&LLFloaterUIPreview::onClickShowRectangles, this, _2)); + + // get pointers to text fields + mEditorPathTextBox = editor_panel_tmp->getChild<LLLineEditor>("executable_path_field"); + mEditorArgsTextBox = editor_panel_tmp->getChild<LLLineEditor>("executable_args_field"); + mDiffPathTextBox = vlt_panel_tmp->getChild<LLLineEditor>("vlt_diff_path_field"); + + // *HACK: restored saved editor path and args to textfields + mEditorPathTextBox->setText(mSavedEditorPath); + mEditorArgsTextBox->setText(mSavedEditorArgs); + mDiffPathTextBox->setText(mSavedDiffPath); + + // Set up overlap panel + mOverlapPanel = getChild<LLOverlapPanel>("overlap_panel"); + + getChildView("overlap_scroll")->setVisible( mHighlightingOverlaps); + + mDelim = gDirUtilp->getDirDelimiter(); // initialize delimiter to dir sep slash + + // refresh list of available languages (EN will still be default) + BOOL found = TRUE; + BOOL found_en_us = FALSE; + std::string language_directory; + std::string xui_dir = get_xui_dir(); // directory containing localizations -- don't forget trailing delim + mLanguageSelection->removeall(); // clear out anything temporarily in list from XML + + LLDirIterator iter(xui_dir, "*"); + while(found) // for every directory + { + if((found = iter.next(language_directory))) // get next directory + { + std::string full_path = gDirUtilp->add(xui_dir, language_directory); + if(LLFile::isfile(full_path.c_str())) // if it's not a directory, skip it + { + continue; + } + + if(strncmp("template",language_directory.c_str(),8) && -1 == language_directory.find(".")) // if it's not the template directory or a hidden directory + { + if(!strncmp("en",language_directory.c_str(),5)) // remember if we've seen en, so we can make it default + { + found_en_us = TRUE; + } + else + { + mLanguageSelection->add(std::string(language_directory)); // add it to the language selection dropdown menu + mLanguageSelection_2->add(std::string(language_directory)); + } + } + } + } + if(found_en_us) + { + mLanguageSelection->add(std::string("en"),ADD_TOP); // make en first item if we found it + mLanguageSelection_2->add(std::string("en"),ADD_TOP); + } + else + { + std::string warning = std::string("No EN localization found; check your XUI directories!"); + popupAndPrintWarning(warning); + } + mLanguageSelection->selectFirstItem(); // select the first item + mLanguageSelection_2->selectFirstItem(); + + refreshList(); // refresh the list of available floaters + + return TRUE; } // Callback for language combo box selection: refresh current floater when you change languages void LLFloaterUIPreview::onLanguageComboSelect(LLUICtrl* ctrl) { - LLComboBox* caller = dynamic_cast<LLComboBox*>(ctrl); - if (!caller) - return; - if(caller->getName() == std::string("language_select_combo")) - { - if(mDisplayedFloater) - { - onClickCloseDisplayedFloater(PRIMARY_FLOATER); - displayFloater(TRUE,1); - } - } - else - { - if(mDisplayedFloater_2) - { - onClickCloseDisplayedFloater(PRIMARY_FLOATER); - displayFloater(TRUE,2); // *TODO: make take an arg - } - } + LLComboBox* caller = dynamic_cast<LLComboBox*>(ctrl); + if (!caller) + return; + if(caller->getName() == std::string("language_select_combo")) + { + if(mDisplayedFloater) + { + onClickCloseDisplayedFloater(PRIMARY_FLOATER); + displayFloater(TRUE,1); + } + } + else + { + if(mDisplayedFloater_2) + { + onClickCloseDisplayedFloater(PRIMARY_FLOATER); + displayFloater(TRUE,2); // *TODO: make take an arg + } + } } void LLFloaterUIPreview::onClickExportSchema() { - //NOTE: schema generation not complete - //gViewerWindow->setCursor(UI_CURSOR_WAIT); - //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); - // const bool use_type_decorations = false; - // root_nodep->writeToFile(rng_file, std::string(), use_type_decorations); - // } - // fclose(rng_file); - //} - //gViewerWindow->setCursor(UI_CURSOR_ARROW); + //NOTE: schema generation not complete + //gViewerWindow->setCursor(UI_CURSOR_WAIT); + //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); + // const bool use_type_decorations = false; + // root_nodep->writeToFile(rng_file, std::string(), use_type_decorations); + // } + // fclose(rng_file); + //} + //gViewerWindow->setCursor(UI_CURSOR_ARROW); } void LLFloaterUIPreview::onClickShowRectangles(const LLSD& data) { - LLPreviewedFloater::sShowRectangles = data.asBoolean(); + LLPreviewedFloater::sShowRectangles = data.asBoolean(); } // Close click handler -- delete my displayed floater if it exists void LLFloaterUIPreview::onClose(bool app_quitting) { - if(!app_quitting && mDisplayedFloater) - { - onClickCloseDisplayedFloater(PRIMARY_FLOATER); - onClickCloseDisplayedFloater(SECONDARY_FLOATER); - delete mDisplayedFloater; - mDisplayedFloater = NULL; - delete mDisplayedFloater_2; - mDisplayedFloater_2 = NULL; - } + if(!app_quitting && mDisplayedFloater) + { + onClickCloseDisplayedFloater(PRIMARY_FLOATER); + onClickCloseDisplayedFloater(SECONDARY_FLOATER); + delete mDisplayedFloater; + mDisplayedFloater = NULL; + delete mDisplayedFloater_2; + mDisplayedFloater_2 = NULL; + } } // Error handling (to avoid code repetition) // *TODO: this is currently unlocalized. Add to alerts/notifications.xml, someday, maybe. void LLFloaterUIPreview::popupAndPrintWarning(const std::string& warning) { - LL_WARNS() << warning << LL_ENDL; - LLSD args; - args["MESSAGE"] = warning; - LLNotificationsUtil::add("GenericAlert", args); + LL_WARNS() << warning << LL_ENDL; + LLSD args; + args["MESSAGE"] = warning; + LLNotificationsUtil::add("GenericAlert", args); } // Get localization string from drop-down menu std::string LLFloaterUIPreview::getLocStr(S32 ID) { - if(ID == 1) - { - return mLanguageSelection->getSelectedItemLabel(0); - } - else - { - return mLanguageSelection_2->getSelectedItemLabel(0); - } + if(ID == 1) + { + return mLanguageSelection->getSelectedItemLabel(0); + } + else + { + return mLanguageSelection_2->getSelectedItemLabel(0); + } } // Get localized directory (build path from data directory to XUI files, substituting localization string in for language) std::string LLFloaterUIPreview::getLocalizedDirectory() { - return get_xui_dir() + (getLocStr(1)) + mDelim; // e.g. "C:/Code/guipreview/indra/newview/skins/xui/en/"; + return get_xui_dir() + (getLocStr(1)) + mDelim; // e.g. "C:/Code/guipreview/indra/newview/skins/xui/en/"; } // Refresh the list of floaters by doing a directory traverse for XML XUI floater files // Could be used to grab any specific language's list of compatible floaters, but currently it's just used to get all of them void LLFloaterUIPreview::refreshList() { - // Note: the mask doesn't seem to accept regular expressions, so there need to be two directory searches here - mFileList->clearRows(); // empty list - std::string name; - BOOL found = TRUE; - - LLDirIterator floater_iter(getLocalizedDirectory(), "floater_*.xml"); - while(found) // for every floater file that matches the pattern - { - if((found = floater_iter.next(name))) // get next file matching pattern - { - addFloaterEntry(name.c_str()); // and add it to the list (file name only; localization code takes care of rest of path) - } - } - found = TRUE; - - LLDirIterator inspect_iter(getLocalizedDirectory(), "inspect_*.xml"); - while(found) // for every inspector file that matches the pattern - { - if((found = inspect_iter.next(name))) // get next file matching pattern - { - addFloaterEntry(name.c_str()); // and add it to the list (file name only; localization code takes care of rest of path) - } - } - found = TRUE; - - LLDirIterator menu_iter(getLocalizedDirectory(), "menu_*.xml"); - while(found) // for every menu file that matches the pattern - { - if((found = menu_iter.next(name))) // get next file matching pattern - { - addFloaterEntry(name.c_str()); // and add it to the list (file name only; localization code takes care of rest of path) - } - } - found = TRUE; - - LLDirIterator panel_iter(getLocalizedDirectory(), "panel_*.xml"); - while(found) // for every panel file that matches the pattern - { - if((found = panel_iter.next(name))) // get next file matching pattern - { - addFloaterEntry(name.c_str()); // and add it to the list (file name only; localization code takes care of rest of path) - } - } - found = TRUE; - - LLDirIterator sidepanel_iter(getLocalizedDirectory(), "sidepanel_*.xml"); - while(found) // for every sidepanel file that matches the pattern - { - if((found = sidepanel_iter.next(name))) // get next file matching pattern - { - addFloaterEntry(name.c_str()); // and add it to the list (file name only; localization code takes care of rest of path) - } - } - - if(!mFileList->isEmpty()) // if there were any matching files, just select the first one (so we don't have to worry about disabling buttons when no entry is selected) - { - mFileList->selectFirstItem(); - } + // Note: the mask doesn't seem to accept regular expressions, so there need to be two directory searches here + mFileList->clearRows(); // empty list + std::string name; + BOOL found = TRUE; + + LLDirIterator floater_iter(getLocalizedDirectory(), "floater_*.xml"); + while(found) // for every floater file that matches the pattern + { + if((found = floater_iter.next(name))) // get next file matching pattern + { + addFloaterEntry(name.c_str()); // and add it to the list (file name only; localization code takes care of rest of path) + } + } + found = TRUE; + + LLDirIterator inspect_iter(getLocalizedDirectory(), "inspect_*.xml"); + while(found) // for every inspector file that matches the pattern + { + if((found = inspect_iter.next(name))) // get next file matching pattern + { + addFloaterEntry(name.c_str()); // and add it to the list (file name only; localization code takes care of rest of path) + } + } + found = TRUE; + + LLDirIterator menu_iter(getLocalizedDirectory(), "menu_*.xml"); + while(found) // for every menu file that matches the pattern + { + if((found = menu_iter.next(name))) // get next file matching pattern + { + addFloaterEntry(name.c_str()); // and add it to the list (file name only; localization code takes care of rest of path) + } + } + found = TRUE; + + LLDirIterator panel_iter(getLocalizedDirectory(), "panel_*.xml"); + while(found) // for every panel file that matches the pattern + { + if((found = panel_iter.next(name))) // get next file matching pattern + { + addFloaterEntry(name.c_str()); // and add it to the list (file name only; localization code takes care of rest of path) + } + } + found = TRUE; + + LLDirIterator sidepanel_iter(getLocalizedDirectory(), "sidepanel_*.xml"); + while(found) // for every sidepanel file that matches the pattern + { + if((found = sidepanel_iter.next(name))) // get next file matching pattern + { + addFloaterEntry(name.c_str()); // and add it to the list (file name only; localization code takes care of rest of path) + } + } + + if(!mFileList->isEmpty()) // if there were any matching files, just select the first one (so we don't have to worry about disabling buttons when no entry is selected) + { + mFileList->selectFirstItem(); + } } // Add a single entry to the list of available floaters // Note: no deduplification (shouldn't be necessary) void LLFloaterUIPreview::addFloaterEntry(const std::string& path) { - LLUUID* entry_id = new LLUUID(); // create a new UUID - entry_id->generate(path); - const LLUUID& entry_id_ref = *entry_id; // get a reference to the UUID for the LLSD block - - // fill LLSD column entry: initialize row/col structure - LLSD row; - row["id"] = entry_id_ref; - LLSD& columns = row["columns"]; - - // Get name of floater: - LLXmlTree xml_tree; - std::string full_path = getLocalizedDirectory() + path; // get full path - BOOL success = xml_tree.parseFile(full_path.c_str(), TRUE); // parse xml - std::string entry_name; - std::string entry_title; - if(success) - { - // get root (or error handle) - LLXmlTreeNode* root_floater = xml_tree.getRoot(); - if (!root_floater) - { - std::string warning = std::string("No root node found in XUI file: ") + path; - popupAndPrintWarning(warning); - return; - } - - // get name - root_floater->getAttributeString("name",entry_name); - if(std::string("") == entry_name) - { - entry_name = "Error: unable to load " + std::string(path); // set to error state if load fails - } - - // get title - root_floater->getAttributeString("title",entry_title); // some don't have a title, and some have title = "(unknown)", so just leave it blank if it fails - } - else - { - std::string warning = std::string("Unable to parse XUI file: ") + path; // error handling - popupAndPrintWarning(warning); - if(mLiveFile) - { - delete mLiveFile; - mLiveFile = NULL; - } - return; - } - - // Fill floater title column - columns[0]["column"] = "title_column"; - columns[0]["type"] = "text"; - columns[0]["value"] = entry_title; - - // Fill floater path column - columns[1]["column"] = "file_column"; - columns[1]["type"] = "text"; - columns[1]["value"] = std::string(path); - - // Fill floater name column - columns[2]["column"] = "top_level_node_column"; - columns[2]["type"] = "text"; - columns[2]["value"] = entry_name; - - mFileList->addElement(row); // actually add to list + LLUUID* entry_id = new LLUUID(); // create a new UUID + entry_id->generate(path); + const LLUUID& entry_id_ref = *entry_id; // get a reference to the UUID for the LLSD block + + // fill LLSD column entry: initialize row/col structure + LLSD row; + row["id"] = entry_id_ref; + LLSD& columns = row["columns"]; + + // Get name of floater: + LLXmlTree xml_tree; + std::string full_path = getLocalizedDirectory() + path; // get full path + BOOL success = xml_tree.parseFile(full_path.c_str(), TRUE); // parse xml + std::string entry_name; + std::string entry_title; + if(success) + { + // get root (or error handle) + LLXmlTreeNode* root_floater = xml_tree.getRoot(); + if (!root_floater) + { + std::string warning = std::string("No root node found in XUI file: ") + path; + popupAndPrintWarning(warning); + return; + } + + // get name + root_floater->getAttributeString("name",entry_name); + if(std::string("") == entry_name) + { + entry_name = "Error: unable to load " + std::string(path); // set to error state if load fails + } + + // get title + root_floater->getAttributeString("title",entry_title); // some don't have a title, and some have title = "(unknown)", so just leave it blank if it fails + } + else + { + std::string warning = std::string("Unable to parse XUI file: ") + path; // error handling + popupAndPrintWarning(warning); + if(mLiveFile) + { + delete mLiveFile; + mLiveFile = NULL; + } + return; + } + + // Fill floater title column + columns[0]["column"] = "title_column"; + columns[0]["type"] = "text"; + columns[0]["value"] = entry_title; + + // Fill floater path column + columns[1]["column"] = "file_column"; + columns[1]["type"] = "text"; + columns[1]["value"] = std::string(path); + + // Fill floater name column + columns[2]["column"] = "top_level_node_column"; + columns[2]["type"] = "text"; + columns[2]["value"] = entry_name; + + mFileList->addElement(row); // actually add to list } // Respond to button click to display/refresh currently-selected floater void LLFloaterUIPreview::onClickDisplayFloater(S32 caller_id) { - displayFloater(TRUE, caller_id); + displayFloater(TRUE, caller_id); } // Saves the current floater/panel void LLFloaterUIPreview::onClickSaveFloater(S32 caller_id) { - displayFloater(TRUE, caller_id); - popupAndPrintWarning("Save-floater functionality removed, use XML schema to clean up XUI files"); + displayFloater(TRUE, caller_id); + popupAndPrintWarning("Save-floater functionality removed, use XML schema to clean up XUI files"); } // Saves all floater/panels void LLFloaterUIPreview::onClickSaveAll(S32 caller_id) { - int listSize = mFileList->getItemCount(); - - for (int index = 0; index < listSize; index++) - { - mFileList->selectNthItem(index); - displayFloater(TRUE, caller_id); - } - popupAndPrintWarning("Save-floater functionality removed, use XML schema to clean up XUI files"); + int listSize = mFileList->getItemCount(); + + for (int index = 0; index < listSize; index++) + { + mFileList->selectNthItem(index); + displayFloater(TRUE, caller_id); + } + popupAndPrintWarning("Save-floater functionality removed, use XML schema to clean up XUI files"); } // Actually display the floater @@ -799,224 +799,224 @@ void LLFloaterUIPreview::onClickSaveAll(S32 caller_id) // otherwise, we get an infinite loop as the live file keeps recreating itself. That means this function is generally called twice. void LLFloaterUIPreview::displayFloater(BOOL click, S32 ID) { - // Convince UI that we're in a different language (the one selected on the drop-down menu) - LLLocalizationResetForcer reset_forcer(this, ID); // save old language in reset forcer object (to be reset upon destruction when it falls out of scope) - - LLPreviewedFloater** floaterp = (ID == 1 ? &(mDisplayedFloater) : &(mDisplayedFloater_2)); - if(ID == 1) - { - BOOL floater_already_open = mDisplayedFloater != NULL; - if(floater_already_open) // if we are already displaying a floater - { - mLastDisplayedX = mDisplayedFloater->calcScreenRect().mLeft; // save floater's last known position to put the new one there - mLastDisplayedY = mDisplayedFloater->calcScreenRect().mBottom; - delete mDisplayedFloater; // delete it (this closes it too) - mDisplayedFloater = NULL; // and reset the pointer - } - } - else - { - if(mDisplayedFloater_2 != NULL) - { - delete mDisplayedFloater_2; - mDisplayedFloater_2 = NULL; - } - } - - std::string path = mFileList->getSelectedItemLabel(1); // get the path of the currently-selected floater - if(std::string("") == path) // if no item is selected - { - return; // ignore click (this can only happen with empty list; otherwise an item is always selected) - } - - LLFloater::Params p(LLFloater::getDefaultParams()); - p.min_height=p.header_height; - p.min_width=10; - - *floaterp = new LLPreviewedFloater(this, p); - - if(!strncmp(path.c_str(),"floater_",8) - || !strncmp(path.c_str(), "inspect_", 8)) // if it's a floater - { - (*floaterp)->buildFromFile(path); // just build it - (*floaterp)->openFloater((*floaterp)->getKey()); - (*floaterp)->setCanResize((*floaterp)->isResizable()); - } - else if (!strncmp(path.c_str(),"menu_",5)) // if it's a menu - { - // former 'save' processing excised - } - else // if it is a panel... - { - (*floaterp)->setCanResize(true); - - const LLFloater::Params& floater_params = LLFloater::getDefaultParams(); - S32 floater_header_size = floater_params.header_height; - - LLPanel::Params panel_params; - LLPanel* panel = LLUICtrlFactory::create<LLPanel>(panel_params); // create a new panel - - panel->buildFromFile(path); // build it - panel->setOrigin(2,2); // reset its origin point so it's not offset by -left or other XUI attributes - (*floaterp)->setTitle(path); // use the file name as its title, since panels have no guaranteed meaningful name attribute - panel->setUseBoundingRect(TRUE); // enable the use of its outer bounding rect (normally disabled because it's O(n) on the number of sub-elements) - panel->updateBoundingRect(); // update bounding rect - LLRect bounding_rect = panel->getBoundingRect(); // get the bounding rect - LLRect new_rect = panel->getRect(); // get the panel's rect - new_rect.unionWith(bounding_rect); // union them to make sure we get the biggest one possible - LLRect floater_rect = new_rect; - floater_rect.stretch(4, 4); - (*floaterp)->reshape(floater_rect.getWidth(), floater_rect.getHeight() + floater_header_size); // reshape floater to match the union rect's dimensions - panel->reshape(new_rect.getWidth(), new_rect.getHeight()); // reshape panel to match the union rect's dimensions as well (both are needed) - (*floaterp)->addChild(panel); // add panel as child - (*floaterp)->openFloater(); // open floater (needed?) - } - - if(ID == 1) - { - (*floaterp)->setOrigin(mLastDisplayedX, mLastDisplayedY); - } - - // *HACK: Remove ability to close it; if you close it, its destructor gets called, but we don't know it's null and try to delete it again, - // resulting in a double free - (*floaterp)->setCanClose(FALSE); - - if(ID == 1) - { - mCloseOtherButton->setEnabled(TRUE); // enable my floater's close button - } - else - { - mCloseOtherButton_2->setEnabled(TRUE); - } - - // Add localization to title so user knows whether it's localized or defaulted to en - std::string full_path = getLocalizedDirectory() + path; - std::string floater_lang = "EN"; - llstat dummy; - if(!LLFile::stat(full_path.c_str(), &dummy)) // if the file does not exist - { - floater_lang = getLocStr(ID); - } - std::string new_title = (*floaterp)->getTitle() + std::string(" [") + floater_lang + - (ID == 1 ? " - Primary" : " - Secondary") + std::string("]"); - (*floaterp)->setTitle(new_title); - - (*floaterp)->center(); - addDependentFloater(*floaterp); - - if(click && ID == 1) - { - // set up live file to track it - if(mLiveFile) - { - delete mLiveFile; - mLiveFile = NULL; - } - mLiveFile = new LLGUIPreviewLiveFile(std::string(full_path.c_str()),std::string(path.c_str()),this); - mLiveFile->checkAndReload(); - mLiveFile->addToEventTimer(); - } - - if(ID == 1) - { - mToggleOverlapButton->setEnabled(TRUE); - } - - if(LLView::sHighlightingDiffs && click && ID == 1) - { - highlightChangedElements(); - } - - if(ID == 1) - { - mOverlapPanel->mOverlapMap.clear(); - LLView::sPreviewClickedElement = NULL; // stop overlapping elements from drawing - mOverlapPanel->mLastClickedElement = NULL; - findOverlapsInChildren((LLView*)mDisplayedFloater); - - // highlight and enable them - if(mHighlightingOverlaps) - { - for(LLOverlapPanel::OverlapMap::iterator iter = mOverlapPanel->mOverlapMap.begin(); iter != mOverlapPanel->mOverlapMap.end(); ++iter) - { - LLView* viewp = iter->first; - LLView::sPreviewHighlightedElements.insert(viewp); - } - } - else if(LLView::sHighlightingDiffs) - { - highlightChangedElements(); - } - } - - // NOTE: language is reset here automatically when the reset forcer object falls out of scope (see header for details) + // Convince UI that we're in a different language (the one selected on the drop-down menu) + LLLocalizationResetForcer reset_forcer(this, ID); // save old language in reset forcer object (to be reset upon destruction when it falls out of scope) + + LLPreviewedFloater** floaterp = (ID == 1 ? &(mDisplayedFloater) : &(mDisplayedFloater_2)); + if(ID == 1) + { + BOOL floater_already_open = mDisplayedFloater != NULL; + if(floater_already_open) // if we are already displaying a floater + { + mLastDisplayedX = mDisplayedFloater->calcScreenRect().mLeft; // save floater's last known position to put the new one there + mLastDisplayedY = mDisplayedFloater->calcScreenRect().mBottom; + delete mDisplayedFloater; // delete it (this closes it too) + mDisplayedFloater = NULL; // and reset the pointer + } + } + else + { + if(mDisplayedFloater_2 != NULL) + { + delete mDisplayedFloater_2; + mDisplayedFloater_2 = NULL; + } + } + + std::string path = mFileList->getSelectedItemLabel(1); // get the path of the currently-selected floater + if(std::string("") == path) // if no item is selected + { + return; // ignore click (this can only happen with empty list; otherwise an item is always selected) + } + + LLFloater::Params p(LLFloater::getDefaultParams()); + p.min_height=p.header_height; + p.min_width=10; + + *floaterp = new LLPreviewedFloater(this, p); + + if(!strncmp(path.c_str(),"floater_",8) + || !strncmp(path.c_str(), "inspect_", 8)) // if it's a floater + { + (*floaterp)->buildFromFile(path); // just build it + (*floaterp)->openFloater((*floaterp)->getKey()); + (*floaterp)->setCanResize((*floaterp)->isResizable()); + } + else if (!strncmp(path.c_str(),"menu_",5)) // if it's a menu + { + // former 'save' processing excised + } + else // if it is a panel... + { + (*floaterp)->setCanResize(true); + + const LLFloater::Params& floater_params = LLFloater::getDefaultParams(); + S32 floater_header_size = floater_params.header_height; + + LLPanel::Params panel_params; + LLPanel* panel = LLUICtrlFactory::create<LLPanel>(panel_params); // create a new panel + + panel->buildFromFile(path); // build it + panel->setOrigin(2,2); // reset its origin point so it's not offset by -left or other XUI attributes + (*floaterp)->setTitle(path); // use the file name as its title, since panels have no guaranteed meaningful name attribute + panel->setUseBoundingRect(TRUE); // enable the use of its outer bounding rect (normally disabled because it's O(n) on the number of sub-elements) + panel->updateBoundingRect(); // update bounding rect + LLRect bounding_rect = panel->getBoundingRect(); // get the bounding rect + LLRect new_rect = panel->getRect(); // get the panel's rect + new_rect.unionWith(bounding_rect); // union them to make sure we get the biggest one possible + LLRect floater_rect = new_rect; + floater_rect.stretch(4, 4); + (*floaterp)->reshape(floater_rect.getWidth(), floater_rect.getHeight() + floater_header_size); // reshape floater to match the union rect's dimensions + panel->reshape(new_rect.getWidth(), new_rect.getHeight()); // reshape panel to match the union rect's dimensions as well (both are needed) + (*floaterp)->addChild(panel); // add panel as child + (*floaterp)->openFloater(); // open floater (needed?) + } + + if(ID == 1) + { + (*floaterp)->setOrigin(mLastDisplayedX, mLastDisplayedY); + } + + // *HACK: Remove ability to close it; if you close it, its destructor gets called, but we don't know it's null and try to delete it again, + // resulting in a double free + (*floaterp)->setCanClose(FALSE); + + if(ID == 1) + { + mCloseOtherButton->setEnabled(TRUE); // enable my floater's close button + } + else + { + mCloseOtherButton_2->setEnabled(TRUE); + } + + // Add localization to title so user knows whether it's localized or defaulted to en + std::string full_path = getLocalizedDirectory() + path; + std::string floater_lang = "EN"; + llstat dummy; + if(!LLFile::stat(full_path.c_str(), &dummy)) // if the file does not exist + { + floater_lang = getLocStr(ID); + } + std::string new_title = (*floaterp)->getTitle() + std::string(" [") + floater_lang + + (ID == 1 ? " - Primary" : " - Secondary") + std::string("]"); + (*floaterp)->setTitle(new_title); + + (*floaterp)->center(); + addDependentFloater(*floaterp); + + if(click && ID == 1) + { + // set up live file to track it + if(mLiveFile) + { + delete mLiveFile; + mLiveFile = NULL; + } + mLiveFile = new LLGUIPreviewLiveFile(std::string(full_path.c_str()),std::string(path.c_str()),this); + mLiveFile->checkAndReload(); + mLiveFile->addToEventTimer(); + } + + if(ID == 1) + { + mToggleOverlapButton->setEnabled(TRUE); + } + + if(LLView::sHighlightingDiffs && click && ID == 1) + { + highlightChangedElements(); + } + + if(ID == 1) + { + mOverlapPanel->mOverlapMap.clear(); + LLView::sPreviewClickedElement = NULL; // stop overlapping elements from drawing + mOverlapPanel->mLastClickedElement = NULL; + findOverlapsInChildren((LLView*)mDisplayedFloater); + + // highlight and enable them + if(mHighlightingOverlaps) + { + for(LLOverlapPanel::OverlapMap::iterator iter = mOverlapPanel->mOverlapMap.begin(); iter != mOverlapPanel->mOverlapMap.end(); ++iter) + { + LLView* viewp = iter->first; + LLView::sPreviewHighlightedElements.insert(viewp); + } + } + else if(LLView::sHighlightingDiffs) + { + highlightChangedElements(); + } + } + + // NOTE: language is reset here automatically when the reset forcer object falls out of scope (see header for details) } // Respond to button click to edit currently-selected floater void LLFloaterUIPreview::onClickEditFloater() { - // Determine file to edit. - std::string file_path; - { - std::string file_name = mFileList->getSelectedItemLabel(1); // get the file name of the currently-selected floater - if (file_name.empty()) // if no item is selected - { - LL_WARNS() << "No file selected" << LL_ENDL; - return; // ignore click - } - file_path = getLocalizedDirectory() + file_name; - - // stat file to see if it exists (some localized versions may not have it there are no diffs, and then we try to open an nonexistent file) - llstat dummy; - if(LLFile::stat(file_path.c_str(), &dummy)) // if the file does not exist - { - popupAndPrintWarning("No file for this floater exists in the selected localization. Opening the EN version instead."); - file_path = get_xui_dir() + mDelim + "en" + mDelim + file_name; // open the en version instead, by default - } - } - - // Set the editor command. - std::string cmd_override; - { - std::string bin = mEditorPathTextBox->getText(); - if (!bin.empty()) - { - // surround command with double quotes for the case if the path contains spaces - if (bin.find("\"") == std::string::npos) - { - bin = "\"" + bin + "\""; - } - - std::string args = mEditorArgsTextBox->getText(); - cmd_override = bin + " " + args; - } - } - - LLExternalEditor::EErrorCode status = mExternalEditor.setCommand("LL_XUI_EDITOR", cmd_override); - if (status != LLExternalEditor::EC_SUCCESS) - { - std::string warning; - - if (status == LLExternalEditor::EC_NOT_SPECIFIED) // Use custom message for this error. - { - warning = getString("ExternalEditorNotSet"); - } - else - { - warning = LLExternalEditor::getErrorMessage(status); - } - - popupAndPrintWarning(warning); - return; - } - - // Run the editor. - if (mExternalEditor.run(file_path) != LLExternalEditor::EC_SUCCESS) - { - popupAndPrintWarning(LLExternalEditor::getErrorMessage(status)); - return; - } + // Determine file to edit. + std::string file_path; + { + std::string file_name = mFileList->getSelectedItemLabel(1); // get the file name of the currently-selected floater + if (file_name.empty()) // if no item is selected + { + LL_WARNS() << "No file selected" << LL_ENDL; + return; // ignore click + } + file_path = getLocalizedDirectory() + file_name; + + // stat file to see if it exists (some localized versions may not have it there are no diffs, and then we try to open an nonexistent file) + llstat dummy; + if(LLFile::stat(file_path.c_str(), &dummy)) // if the file does not exist + { + popupAndPrintWarning("No file for this floater exists in the selected localization. Opening the EN version instead."); + file_path = get_xui_dir() + mDelim + "en" + mDelim + file_name; // open the en version instead, by default + } + } + + // Set the editor command. + std::string cmd_override; + { + std::string bin = mEditorPathTextBox->getText(); + if (!bin.empty()) + { + // surround command with double quotes for the case if the path contains spaces + if (bin.find("\"") == std::string::npos) + { + bin = "\"" + bin + "\""; + } + + std::string args = mEditorArgsTextBox->getText(); + cmd_override = bin + " " + args; + } + } + + LLExternalEditor::EErrorCode status = mExternalEditor.setCommand("LL_XUI_EDITOR", cmd_override); + if (status != LLExternalEditor::EC_SUCCESS) + { + std::string warning; + + if (status == LLExternalEditor::EC_NOT_SPECIFIED) // Use custom message for this error. + { + warning = getString("ExternalEditorNotSet"); + } + else + { + warning = LLExternalEditor::getErrorMessage(status); + } + + popupAndPrintWarning(warning); + return; + } + + // Run the editor. + if (mExternalEditor.run(file_path) != LLExternalEditor::EC_SUCCESS) + { + popupAndPrintWarning(LLExternalEditor::getErrorMessage(status)); + return; + } } // Respond to button click to browse for an executable with which to edit XML files @@ -1028,398 +1028,398 @@ void LLFloaterUIPreview::onClickBrowseForEditor() void LLFloaterUIPreview::getExecutablePath(const std::vector<std::string>& filenames) { - // put the selected path into text field - const std::string chosen_path = filenames[0]; - std::string executable_path = chosen_path; + // put the selected path into text field + const std::string chosen_path = filenames[0]; + std::string executable_path = chosen_path; #if LL_DARWIN - // on Mac, if it's an application bundle, figure out the actual path from the Info.plist file - CFStringRef path_cfstr = CFStringCreateWithCString(kCFAllocatorDefault, chosen_path.c_str(), kCFStringEncodingMacRoman); // get path as a CFStringRef - CFURLRef path_url = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, path_cfstr, kCFURLPOSIXPathStyle, TRUE); // turn it into a CFURLRef - CFBundleRef chosen_bundle = CFBundleCreate(kCFAllocatorDefault, path_url); // get a handle for the bundle - if(NULL != chosen_bundle) - { - CFDictionaryRef bundleInfoDict = CFBundleGetInfoDictionary(chosen_bundle); // get the bundle's dictionary - if(NULL != bundleInfoDict) - { - CFStringRef executable_cfstr = (CFStringRef)CFDictionaryGetValue(bundleInfoDict, CFSTR("CFBundleExecutable")); // get the name of the actual executable (e.g. TextEdit or firefox-bin) - int max_file_length = 256; // (max file name length is 255 in OSX) - char executable_buf[max_file_length]; - if(CFStringGetCString(executable_cfstr, executable_buf, max_file_length, kCFStringEncodingMacRoman)) // convert CFStringRef to char* - { - executable_path += std::string("/Contents/MacOS/") + std::string(executable_buf); // append path to executable directory and then executable name to exec path - } - else - { - std::string warning = "Unable to get CString from CFString for executable path"; - popupAndPrintWarning(warning); - } - } - else - { - std::string warning = "Unable to get bundle info dictionary from application bundle"; - popupAndPrintWarning(warning); - } - } - else - { - if(-1 != executable_path.find(".app")) // only warn if this path actually had ".app" in it, i.e. it probably just wasn'nt an app bundle and that's okay - { - std::string warning = std::string("Unable to get bundle from path \"") + chosen_path + std::string("\""); - popupAndPrintWarning(warning); - } - } + // on Mac, if it's an application bundle, figure out the actual path from the Info.plist file + CFStringRef path_cfstr = CFStringCreateWithCString(kCFAllocatorDefault, chosen_path.c_str(), kCFStringEncodingMacRoman); // get path as a CFStringRef + CFURLRef path_url = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, path_cfstr, kCFURLPOSIXPathStyle, TRUE); // turn it into a CFURLRef + CFBundleRef chosen_bundle = CFBundleCreate(kCFAllocatorDefault, path_url); // get a handle for the bundle + if(NULL != chosen_bundle) + { + CFDictionaryRef bundleInfoDict = CFBundleGetInfoDictionary(chosen_bundle); // get the bundle's dictionary + if(NULL != bundleInfoDict) + { + CFStringRef executable_cfstr = (CFStringRef)CFDictionaryGetValue(bundleInfoDict, CFSTR("CFBundleExecutable")); // get the name of the actual executable (e.g. TextEdit or firefox-bin) + int max_file_length = 256; // (max file name length is 255 in OSX) + char executable_buf[max_file_length]; + if(CFStringGetCString(executable_cfstr, executable_buf, max_file_length, kCFStringEncodingMacRoman)) // convert CFStringRef to char* + { + executable_path += std::string("/Contents/MacOS/") + std::string(executable_buf); // append path to executable directory and then executable name to exec path + } + else + { + std::string warning = "Unable to get CString from CFString for executable path"; + popupAndPrintWarning(warning); + } + } + else + { + std::string warning = "Unable to get bundle info dictionary from application bundle"; + popupAndPrintWarning(warning); + } + } + else + { + if(-1 != executable_path.find(".app")) // only warn if this path actually had ".app" in it, i.e. it probably just wasn'nt an app bundle and that's okay + { + std::string warning = std::string("Unable to get bundle from path \"") + chosen_path + std::string("\""); + popupAndPrintWarning(warning); + } + } #endif - mEditorPathTextBox->setText(std::string(executable_path)); // copy the path to the executable to the textfield for display and later fetching + mEditorPathTextBox->setText(std::string(executable_path)); // copy the path to the executable to the textfield for display and later fetching } // Respond to button click to browse for a VLT-generated diffs file void LLFloaterUIPreview::onClickBrowseForDiffs() { - // create load dialog box + // create load dialog box LLFilePickerReplyThread::startPicker(boost::bind(&LLFloaterUIPreview::getDiffsFilePath, this, _1), LLFilePicker::FFLOAD_XML, false); } void LLFloaterUIPreview::getDiffsFilePath(const std::vector<std::string>& filenames) { - // put the selected path into text field - const std::string chosen_path = filenames[0]; - mDiffPathTextBox->setText(std::string(chosen_path)); // copy the path to the executable to the textfield for display and later fetching - if(LLView::sHighlightingDiffs) // if we're already highlighting, toggle off and then on so we get the data from the new file - { - onClickToggleDiffHighlighting(); - onClickToggleDiffHighlighting(); - } + // put the selected path into text field + const std::string chosen_path = filenames[0]; + mDiffPathTextBox->setText(std::string(chosen_path)); // copy the path to the executable to the textfield for display and later fetching + if(LLView::sHighlightingDiffs) // if we're already highlighting, toggle off and then on so we get the data from the new file + { + onClickToggleDiffHighlighting(); + onClickToggleDiffHighlighting(); + } } void LLFloaterUIPreview::onClickToggleDiffHighlighting() { - if(mHighlightingOverlaps) - { - onClickToggleOverlapping(); - mToggleOverlapButton->toggleState(); - } - - LLView::sPreviewHighlightedElements.clear(); // clear lists first - mDiffsMap.clear(); - mFileList->clearHighlightedItems(); - - if(LLView::sHighlightingDiffs) // Turning highlighting off - { - LLView::sHighlightingDiffs = !sHighlightingDiffs; - return; - } - else // Turning highlighting on - { - // Get the file and make sure it exists - std::string path_in_textfield = mDiffPathTextBox->getText(); // get file path - BOOL error = FALSE; - - if(std::string("") == path_in_textfield) // check for blank file - { - std::string warning = "Unable to highlight differences because no file was provided; fill in the relevant text field"; - popupAndPrintWarning(warning); - error = TRUE; - } - - llstat dummy; - if(LLFile::stat(path_in_textfield.c_str(), &dummy) && !error) // check if the file exists (empty check is reduntant but useful for the informative error message) - { - std::string warning = std::string("Unable to highlight differences because an invalid path to a difference file was provided:\"") + path_in_textfield + "\""; - popupAndPrintWarning(warning); - error = TRUE; - } - - // Build a list of changed elements as given by the XML - std::list<std::string> changed_element_names; - LLXmlTree xml_tree; - BOOL success = xml_tree.parseFile(path_in_textfield.c_str(), TRUE); - - if(success && !error) - { - LLXmlTreeNode* root_floater = xml_tree.getRoot(); - if(!strncmp("XuiDelta",root_floater->getName().c_str(),9)) - { - for (LLXmlTreeNode* child = root_floater->getFirstChild(); // get the first child first, then below get the next one; otherwise the iterator is invalid (bug or feature in XML code?) - child != NULL; - child = root_floater->getNextChild()) // get child for next iteration - { - if(!strncmp("file",child->getName().c_str(),5)) - { - scanDiffFile(child); - } - else if(!strncmp("error",child->getName().c_str(),6)) - { - std::string error_file, error_message; - child->getAttributeString("filename",error_file); - child->getAttributeString("message",error_message); - if(mDiffsMap.find(error_file) != mDiffsMap.end()) - { - mDiffsMap.insert(std::make_pair(error_file,std::make_pair(StringListPtr(new StringList), StringListPtr(new StringList)))); - } - mDiffsMap[error_file].second->push_back(error_message); - } - else - { - std::string warning = std::string("Child was neither a file or an error, but rather the following:\"") + std::string(child->getName()) + "\""; - popupAndPrintWarning(warning); - error = TRUE; - break; - } - } - } - else - { - std::string warning = std::string("Root node not named XuiDelta:\"") + path_in_textfield + "\""; - popupAndPrintWarning(warning); - error = TRUE; - } - } - else if(!error) - { - std::string warning = std::string("Unable to create tree from XML:\"") + path_in_textfield + "\""; - popupAndPrintWarning(warning); - error = TRUE; - } - - if(error) // if we encountered an error, reset the button to off - { - mToggleHighlightButton->setToggleState(FALSE); - } - else // only toggle if we didn't encounter an error - { - LLView::sHighlightingDiffs = !sHighlightingDiffs; - highlightChangedElements(); // *TODO: this is extraneous, right? - highlightChangedFiles(); // *TODO: this is extraneous, right? - } - } + if(mHighlightingOverlaps) + { + onClickToggleOverlapping(); + mToggleOverlapButton->toggleState(); + } + + LLView::sPreviewHighlightedElements.clear(); // clear lists first + mDiffsMap.clear(); + mFileList->clearHighlightedItems(); + + if(LLView::sHighlightingDiffs) // Turning highlighting off + { + LLView::sHighlightingDiffs = !sHighlightingDiffs; + return; + } + else // Turning highlighting on + { + // Get the file and make sure it exists + std::string path_in_textfield = mDiffPathTextBox->getText(); // get file path + BOOL error = FALSE; + + if(std::string("") == path_in_textfield) // check for blank file + { + std::string warning = "Unable to highlight differences because no file was provided; fill in the relevant text field"; + popupAndPrintWarning(warning); + error = TRUE; + } + + llstat dummy; + if(LLFile::stat(path_in_textfield.c_str(), &dummy) && !error) // check if the file exists (empty check is reduntant but useful for the informative error message) + { + std::string warning = std::string("Unable to highlight differences because an invalid path to a difference file was provided:\"") + path_in_textfield + "\""; + popupAndPrintWarning(warning); + error = TRUE; + } + + // Build a list of changed elements as given by the XML + std::list<std::string> changed_element_names; + LLXmlTree xml_tree; + BOOL success = xml_tree.parseFile(path_in_textfield.c_str(), TRUE); + + if(success && !error) + { + LLXmlTreeNode* root_floater = xml_tree.getRoot(); + if(!strncmp("XuiDelta",root_floater->getName().c_str(),9)) + { + for (LLXmlTreeNode* child = root_floater->getFirstChild(); // get the first child first, then below get the next one; otherwise the iterator is invalid (bug or feature in XML code?) + child != NULL; + child = root_floater->getNextChild()) // get child for next iteration + { + if(!strncmp("file",child->getName().c_str(),5)) + { + scanDiffFile(child); + } + else if(!strncmp("error",child->getName().c_str(),6)) + { + std::string error_file, error_message; + child->getAttributeString("filename",error_file); + child->getAttributeString("message",error_message); + if(mDiffsMap.find(error_file) != mDiffsMap.end()) + { + mDiffsMap.insert(std::make_pair(error_file,std::make_pair(StringListPtr(new StringList), StringListPtr(new StringList)))); + } + mDiffsMap[error_file].second->push_back(error_message); + } + else + { + std::string warning = std::string("Child was neither a file or an error, but rather the following:\"") + std::string(child->getName()) + "\""; + popupAndPrintWarning(warning); + error = TRUE; + break; + } + } + } + else + { + std::string warning = std::string("Root node not named XuiDelta:\"") + path_in_textfield + "\""; + popupAndPrintWarning(warning); + error = TRUE; + } + } + else if(!error) + { + std::string warning = std::string("Unable to create tree from XML:\"") + path_in_textfield + "\""; + popupAndPrintWarning(warning); + error = TRUE; + } + + if(error) // if we encountered an error, reset the button to off + { + mToggleHighlightButton->setToggleState(FALSE); + } + else // only toggle if we didn't encounter an error + { + LLView::sHighlightingDiffs = !sHighlightingDiffs; + highlightChangedElements(); // *TODO: this is extraneous, right? + highlightChangedFiles(); // *TODO: this is extraneous, right? + } + } } void LLFloaterUIPreview::scanDiffFile(LLXmlTreeNode* file_node) { - // Get file name - std::string file_name; - file_node->getAttributeString("name",file_name); - if(std::string("") == file_name) - { - std::string warning = std::string("Empty file name encountered in differences:\"") + file_name + "\""; - popupAndPrintWarning(warning); - return; - } - - // Get a list of changed elements - // Get the first child first, then below get the next one; otherwise the iterator is invalid (bug or feature in XML code?) - for (LLXmlTreeNode* child = file_node->getFirstChild(); child != NULL; child = file_node->getNextChild()) - { - if(!strncmp("delta",child->getName().c_str(),6)) - { - std::string id; - child->getAttributeString("id",id); - if(mDiffsMap.find(file_name) == mDiffsMap.end()) - { - mDiffsMap.insert(std::make_pair(file_name,std::make_pair(StringListPtr(new StringList), StringListPtr(new StringList)))); - } - mDiffsMap[file_name].first->push_back(std::string(id.c_str())); - } - else - { - std::string warning = std::string("Child of file was not a delta, but rather the following:\"") + std::string(child->getName()) + "\""; - popupAndPrintWarning(warning); - return; - } - } + // Get file name + std::string file_name; + file_node->getAttributeString("name",file_name); + if(std::string("") == file_name) + { + std::string warning = std::string("Empty file name encountered in differences:\"") + file_name + "\""; + popupAndPrintWarning(warning); + return; + } + + // Get a list of changed elements + // Get the first child first, then below get the next one; otherwise the iterator is invalid (bug or feature in XML code?) + for (LLXmlTreeNode* child = file_node->getFirstChild(); child != NULL; child = file_node->getNextChild()) + { + if(!strncmp("delta",child->getName().c_str(),6)) + { + std::string id; + child->getAttributeString("id",id); + if(mDiffsMap.find(file_name) == mDiffsMap.end()) + { + mDiffsMap.insert(std::make_pair(file_name,std::make_pair(StringListPtr(new StringList), StringListPtr(new StringList)))); + } + mDiffsMap[file_name].first->push_back(std::string(id.c_str())); + } + else + { + std::string warning = std::string("Child of file was not a delta, but rather the following:\"") + std::string(child->getName()) + "\""; + popupAndPrintWarning(warning); + return; + } + } } void LLFloaterUIPreview::highlightChangedElements() { - if(NULL == mLiveFile) - { - return; - } - - // Process differences first (we want their warnings to be shown underneath other warnings) - StringListPtr changed_element_paths; - DiffMap::iterator iterExists = mDiffsMap.find(mLiveFile->mFileName); - if(iterExists != mDiffsMap.end()) - { - changed_element_paths = mDiffsMap[mLiveFile->mFileName].first; // retrieve list of changed element paths from map - } - - for(std::list<std::string>::iterator iter = changed_element_paths->begin(); iter != changed_element_paths->end(); ++iter) // for every changed element path - { - LLView* element = mDisplayedFloater; - if(!strncmp(iter->c_str(),".",1)) // if it's the root floater itself - { - continue; - } - - // Split element hierarchy path on period (*HACK: it's possible that the element name will have a period in it, in which case this won't work. See https://wiki.lindenlab.com/wiki/Viewer_Localization_Tool_Documentation.) - typedef boost::tokenizer<boost::char_separator<char> > tokenizer; - boost::char_separator<char> sep("."); - tokenizer tokens(*iter, sep); - tokenizer::iterator token_iter; - BOOL failed = FALSE; - for(token_iter = tokens.begin(); token_iter != tokens.end(); ++token_iter) - { - element = element->findChild<LLView>(*token_iter,FALSE); // try to find element: don't recur, and don't create if missing - - // if we still didn't find it... - if(NULL == element) - { - LL_INFOS() << "Unable to find element in XuiDelta file named \"" << *iter << "\" in file \"" << mLiveFile->mFileName << - "\". The element may no longer exist, the path may be incorrect, or it may not be a non-displayable element (not an LLView) such as a \"string\" type." << LL_ENDL; - failed = TRUE; - break; - } - } - - if(!failed) - { - // Now that we have a pointer to the actual element, add it to the list of elements to be highlighted - std::set<LLView*>::iterator iter2 = std::find(LLView::sPreviewHighlightedElements.begin(), LLView::sPreviewHighlightedElements.end(), element); - if(iter2 == LLView::sPreviewHighlightedElements.end()) - { - LLView::sPreviewHighlightedElements.insert(element); - } - } - } - - // Process errors second, so their warnings show up on top of other warnings - StringListPtr error_list; - if(iterExists != mDiffsMap.end()) - { - error_list = mDiffsMap[mLiveFile->mFileName].second; - } - for(std::list<std::string>::iterator iter = error_list->begin(); iter != error_list->end(); ++iter) // for every changed element path - { - std::string warning = std::string("Error listed among differences. Filename: \"") + mLiveFile->mFileName + "\". Message: \"" + *iter + "\""; - popupAndPrintWarning(warning); - } + if(NULL == mLiveFile) + { + return; + } + + // Process differences first (we want their warnings to be shown underneath other warnings) + StringListPtr changed_element_paths; + DiffMap::iterator iterExists = mDiffsMap.find(mLiveFile->mFileName); + if(iterExists != mDiffsMap.end()) + { + changed_element_paths = mDiffsMap[mLiveFile->mFileName].first; // retrieve list of changed element paths from map + } + + for(std::list<std::string>::iterator iter = changed_element_paths->begin(); iter != changed_element_paths->end(); ++iter) // for every changed element path + { + LLView* element = mDisplayedFloater; + if(!strncmp(iter->c_str(),".",1)) // if it's the root floater itself + { + continue; + } + + // Split element hierarchy path on period (*HACK: it's possible that the element name will have a period in it, in which case this won't work. See https://wiki.lindenlab.com/wiki/Viewer_Localization_Tool_Documentation.) + typedef boost::tokenizer<boost::char_separator<char> > tokenizer; + boost::char_separator<char> sep("."); + tokenizer tokens(*iter, sep); + tokenizer::iterator token_iter; + BOOL failed = FALSE; + for(token_iter = tokens.begin(); token_iter != tokens.end(); ++token_iter) + { + element = element->findChild<LLView>(*token_iter,FALSE); // try to find element: don't recur, and don't create if missing + + // if we still didn't find it... + if(NULL == element) + { + LL_INFOS() << "Unable to find element in XuiDelta file named \"" << *iter << "\" in file \"" << mLiveFile->mFileName << + "\". The element may no longer exist, the path may be incorrect, or it may not be a non-displayable element (not an LLView) such as a \"string\" type." << LL_ENDL; + failed = TRUE; + break; + } + } + + if(!failed) + { + // Now that we have a pointer to the actual element, add it to the list of elements to be highlighted + std::set<LLView*>::iterator iter2 = std::find(LLView::sPreviewHighlightedElements.begin(), LLView::sPreviewHighlightedElements.end(), element); + if(iter2 == LLView::sPreviewHighlightedElements.end()) + { + LLView::sPreviewHighlightedElements.insert(element); + } + } + } + + // Process errors second, so their warnings show up on top of other warnings + StringListPtr error_list; + if(iterExists != mDiffsMap.end()) + { + error_list = mDiffsMap[mLiveFile->mFileName].second; + } + for(std::list<std::string>::iterator iter = error_list->begin(); iter != error_list->end(); ++iter) // for every changed element path + { + std::string warning = std::string("Error listed among differences. Filename: \"") + mLiveFile->mFileName + "\". Message: \"" + *iter + "\""; + popupAndPrintWarning(warning); + } } void LLFloaterUIPreview::highlightChangedFiles() { - for(DiffMap::iterator iter = mDiffsMap.begin(); iter != mDiffsMap.end(); ++iter) // for every file listed in diffs - { - LLScrollListItem* item = mFileList->getItemByLabel(std::string(iter->first), FALSE, 1); - if(item) - { - item->setHighlighted(TRUE); - } - } + for(DiffMap::iterator iter = mDiffsMap.begin(); iter != mDiffsMap.end(); ++iter) // for every file listed in diffs + { + LLScrollListItem* item = mFileList->getItemByLabel(std::string(iter->first), FALSE, 1); + if(item) + { + item->setHighlighted(TRUE); + } + } } // Respond to button click to browse for an executable with which to edit XML files void LLFloaterUIPreview::onClickCloseDisplayedFloater(S32 caller_id) { - if(caller_id == PRIMARY_FLOATER) - { - mCloseOtherButton->setEnabled(FALSE); - mToggleOverlapButton->setEnabled(FALSE); - - if(mDisplayedFloater) - { - mLastDisplayedX = mDisplayedFloater->calcScreenRect().mLeft; - mLastDisplayedY = mDisplayedFloater->calcScreenRect().mBottom; - delete mDisplayedFloater; - mDisplayedFloater = NULL; - } - - if(mLiveFile) - { - delete mLiveFile; - mLiveFile = NULL; - } - - if(mToggleOverlapButton->getToggleState()) - { - mToggleOverlapButton->toggleState(); - onClickToggleOverlapping(); - } - - LLView::sPreviewClickedElement = NULL; // stop overlapping elements panel from drawing - mOverlapPanel->mLastClickedElement = NULL; - } - else - { - mCloseOtherButton_2->setEnabled(FALSE); - delete mDisplayedFloater_2; - mDisplayedFloater_2 = NULL; - } + if(caller_id == PRIMARY_FLOATER) + { + mCloseOtherButton->setEnabled(FALSE); + mToggleOverlapButton->setEnabled(FALSE); + + if(mDisplayedFloater) + { + mLastDisplayedX = mDisplayedFloater->calcScreenRect().mLeft; + mLastDisplayedY = mDisplayedFloater->calcScreenRect().mBottom; + delete mDisplayedFloater; + mDisplayedFloater = NULL; + } + + if(mLiveFile) + { + delete mLiveFile; + mLiveFile = NULL; + } + + if(mToggleOverlapButton->getToggleState()) + { + mToggleOverlapButton->toggleState(); + onClickToggleOverlapping(); + } + + LLView::sPreviewClickedElement = NULL; // stop overlapping elements panel from drawing + mOverlapPanel->mLastClickedElement = NULL; + } + else + { + mCloseOtherButton_2->setEnabled(FALSE); + delete mDisplayedFloater_2; + mDisplayedFloater_2 = NULL; + } } void append_view_tooltip(LLView* tooltip_view, std::string *tooltip_msg) { - LLRect rect = tooltip_view->getRect(); - LLRect parent_rect = tooltip_view->getParent()->getRect(); - S32 left = rect.mLeft; - // invert coordinate system for XUI top-left layout - S32 top = parent_rect.getHeight() - rect.mTop; - if (!tooltip_msg->empty()) - { - tooltip_msg->append("\n"); - } - std::string msg = llformat("%s %d, %d (%d x %d)", - tooltip_view->getName().c_str(), - left, - top, - rect.getWidth(), - rect.getHeight() ); - tooltip_msg->append( msg ); + LLRect rect = tooltip_view->getRect(); + LLRect parent_rect = tooltip_view->getParent()->getRect(); + S32 left = rect.mLeft; + // invert coordinate system for XUI top-left layout + S32 top = parent_rect.getHeight() - rect.mTop; + if (!tooltip_msg->empty()) + { + tooltip_msg->append("\n"); + } + std::string msg = llformat("%s %d, %d (%d x %d)", + tooltip_view->getName().c_str(), + left, + top, + rect.getWidth(), + rect.getHeight() ); + tooltip_msg->append( msg ); } BOOL LLPreviewedFloater::handleToolTip(S32 x, S32 y, MASK mask) { - if (!sShowRectangles) - { - return LLFloater::handleToolTip(x, y, mask); - } - - S32 screen_x, screen_y; - localPointToScreen(x, y, &screen_x, &screen_y); - std::string tooltip_msg; - LLView* tooltip_view = this; - LLView::tree_iterator_t end_it = endTreeDFS(); - for (LLView::tree_iterator_t it = beginTreeDFS(); it != end_it; ++it) - { - LLView* viewp = *it; - LLRect screen_rect; - viewp->localRectToScreen(viewp->getLocalRect(), &screen_rect); - if (!(viewp->getVisible() - && screen_rect.pointInRect(screen_x, screen_y))) - { - it.skipDescendants(); - } - // only report xui names for LLUICtrls, not the various container LLViews - - else if (dynamic_cast<LLUICtrl*>(viewp)) - { - // if we are in a new part of the tree (not a descendent of current tooltip_view) - // then push the results for tooltip_view and start with a new potential view - // NOTE: this emulates visiting only the leaf nodes that meet our criteria - - if (tooltip_view != this - && !viewp->hasAncestor(tooltip_view)) - { - append_view_tooltip(tooltip_view, &tooltip_msg); - } - tooltip_view = viewp; - } - } - - append_view_tooltip(tooltip_view, &tooltip_msg); - - LLToolTipMgr::instance().show(LLToolTip::Params() - .message(tooltip_msg) - .max_width(400)); - return TRUE; + if (!sShowRectangles) + { + return LLFloater::handleToolTip(x, y, mask); + } + + S32 screen_x, screen_y; + localPointToScreen(x, y, &screen_x, &screen_y); + std::string tooltip_msg; + LLView* tooltip_view = this; + LLView::tree_iterator_t end_it = endTreeDFS(); + for (LLView::tree_iterator_t it = beginTreeDFS(); it != end_it; ++it) + { + LLView* viewp = *it; + LLRect screen_rect; + viewp->localRectToScreen(viewp->getLocalRect(), &screen_rect); + if (!(viewp->getVisible() + && screen_rect.pointInRect(screen_x, screen_y))) + { + it.skipDescendants(); + } + // only report xui names for LLUICtrls, not the various container LLViews + + else if (dynamic_cast<LLUICtrl*>(viewp)) + { + // if we are in a new part of the tree (not a descendent of current tooltip_view) + // then push the results for tooltip_view and start with a new potential view + // NOTE: this emulates visiting only the leaf nodes that meet our criteria + + if (tooltip_view != this + && !viewp->hasAncestor(tooltip_view)) + { + append_view_tooltip(tooltip_view, &tooltip_msg); + } + tooltip_view = viewp; + } + } + + append_view_tooltip(tooltip_view, &tooltip_msg); + + LLToolTipMgr::instance().show(LLToolTip::Params() + .message(tooltip_msg) + .max_width(400)); + return TRUE; } BOOL LLPreviewedFloater::handleRightMouseDown(S32 x, S32 y, MASK mask) { - selectElement(this,x,y,0); - return TRUE; + selectElement(this,x,y,0); + return TRUE; } // *NOTE: In order to hide all of the overlapping elements of the selected element so as to see it in context, here is what you would need to do: @@ -1433,131 +1433,131 @@ BOOL LLPreviewedFloater::handleRightMouseDown(S32 x, S32 y, MASK mask) // ~Jacob, 8/08 BOOL LLPreviewedFloater::selectElement(LLView* parent, int x, int y, int depth) { - if(getVisible()) - { - BOOL handled = FALSE; - if(LLFloaterUIPreview::containerType(parent)) - { - for(child_list_const_iter_t child_it = parent->getChildList()->begin(); child_it != parent->getChildList()->end(); ++child_it) - { - LLView* child = *child_it; - S32 local_x = x - child->getRect().mLeft; - S32 local_y = y - child->getRect().mBottom; - if (child->pointInView(local_x, local_y) && - child->getVisible() && - selectElement(child, x, y, ++depth)) - { - handled = TRUE; - break; - } - } - } - - if(!handled) - { - LLView::sPreviewClickedElement = parent; - } - return TRUE; - } - else - { - return FALSE; - } + if(getVisible()) + { + BOOL handled = FALSE; + if(LLFloaterUIPreview::containerType(parent)) + { + for(child_list_const_iter_t child_it = parent->getChildList()->begin(); child_it != parent->getChildList()->end(); ++child_it) + { + LLView* child = *child_it; + S32 local_x = x - child->getRect().mLeft; + S32 local_y = y - child->getRect().mBottom; + if (child->pointInView(local_x, local_y) && + child->getVisible() && + selectElement(child, x, y, ++depth)) + { + handled = TRUE; + break; + } + } + } + + if(!handled) + { + LLView::sPreviewClickedElement = parent; + } + return TRUE; + } + else + { + return FALSE; + } } void LLPreviewedFloater::draw() { - if(NULL != mFloaterUIPreview) - { - // Set and unset sDrawPreviewHighlights flag so as to avoid using two flags - if(mFloaterUIPreview->mHighlightingOverlaps) - { - LLView::sDrawPreviewHighlights = TRUE; - } - - // If we're looking for truncations, draw debug rects for the displayed - // floater only. - bool old_debug_rects = LLView::sDebugRects; - bool old_show_names = LLView::sDebugRectsShowNames; - if (sShowRectangles) - { - LLView::sDebugRects = true; - LLView::sDebugRectsShowNames = false; - } - - LLFloater::draw(); - - LLView::sDebugRects = old_debug_rects; - LLView::sDebugRectsShowNames = old_show_names; - - if(mFloaterUIPreview->mHighlightingOverlaps) - { - LLView::sDrawPreviewHighlights = FALSE; - } - } + if(NULL != mFloaterUIPreview) + { + // Set and unset sDrawPreviewHighlights flag so as to avoid using two flags + if(mFloaterUIPreview->mHighlightingOverlaps) + { + LLView::sDrawPreviewHighlights = TRUE; + } + + // If we're looking for truncations, draw debug rects for the displayed + // floater only. + bool old_debug_rects = LLView::sDebugRects; + bool old_show_names = LLView::sDebugRectsShowNames; + if (sShowRectangles) + { + LLView::sDebugRects = true; + LLView::sDebugRectsShowNames = false; + } + + LLFloater::draw(); + + LLView::sDebugRects = old_debug_rects; + LLView::sDebugRectsShowNames = old_show_names; + + if(mFloaterUIPreview->mHighlightingOverlaps) + { + LLView::sDrawPreviewHighlights = FALSE; + } + } } void LLFloaterUIPreview::onClickToggleOverlapping() { - if(LLView::sHighlightingDiffs) - { - onClickToggleDiffHighlighting(); - mToggleHighlightButton->toggleState(); - } - LLView::sPreviewHighlightedElements.clear(); // clear lists first - - S32 width, height; - getResizeLimits(&width, &height); // illegal call of non-static member function - if(mHighlightingOverlaps) - { - mHighlightingOverlaps = !mHighlightingOverlaps; - // reset list of preview highlighted elements - setRect(LLRect(getRect().mLeft,getRect().mTop,getRect().mRight - mOverlapPanel->getRect().getWidth(),getRect().mBottom)); - setResizeLimits(width - mOverlapPanel->getRect().getWidth(), height); - } - else - { - mHighlightingOverlaps = !mHighlightingOverlaps; - displayFloater(FALSE,1); - setRect(LLRect(getRect().mLeft,getRect().mTop,getRect().mRight + mOverlapPanel->getRect().getWidth(),getRect().mBottom)); - setResizeLimits(width + mOverlapPanel->getRect().getWidth(), height); - } - getChildView("overlap_scroll")->setVisible( mHighlightingOverlaps); + if(LLView::sHighlightingDiffs) + { + onClickToggleDiffHighlighting(); + mToggleHighlightButton->toggleState(); + } + LLView::sPreviewHighlightedElements.clear(); // clear lists first + + S32 width, height; + getResizeLimits(&width, &height); // illegal call of non-static member function + if(mHighlightingOverlaps) + { + mHighlightingOverlaps = !mHighlightingOverlaps; + // reset list of preview highlighted elements + setRect(LLRect(getRect().mLeft,getRect().mTop,getRect().mRight - mOverlapPanel->getRect().getWidth(),getRect().mBottom)); + setResizeLimits(width - mOverlapPanel->getRect().getWidth(), height); + } + else + { + mHighlightingOverlaps = !mHighlightingOverlaps; + displayFloater(FALSE,1); + setRect(LLRect(getRect().mLeft,getRect().mTop,getRect().mRight + mOverlapPanel->getRect().getWidth(),getRect().mBottom)); + setResizeLimits(width + mOverlapPanel->getRect().getWidth(), height); + } + getChildView("overlap_scroll")->setVisible( mHighlightingOverlaps); } void LLFloaterUIPreview::findOverlapsInChildren(LLView* parent) { - if(parent->getChildCount() == 0 || !containerType(parent)) // if it has no children or isn't a container type, skip it - { - return; - } - - // for every child of the parent - for(child_list_const_iter_t child_it = parent->getChildList()->begin(); child_it != parent->getChildList()->end(); ++child_it) - { - LLView* child = *child_it; - if(overlapIgnorable(child)) - { - continue; - } - - // for every sibling - for(child_list_const_iter_t sibling_it = parent->getChildList()->begin(); sibling_it != parent->getChildList()->end(); ++sibling_it) // for each sibling - { - LLView* sibling = *sibling_it; - if(overlapIgnorable(sibling)) - { - continue; - } - - // if they overlap... (we don't care if they're visible or enabled -- we want to check those anyway, i.e. hidden tabs that can be later shown) - if(sibling != child && elementOverlap(child, sibling)) - { - mOverlapPanel->mOverlapMap[child].push_back(sibling); // add to the map - } - } - findOverlapsInChildren(child); // recur - } + if(parent->getChildCount() == 0 || !containerType(parent)) // if it has no children or isn't a container type, skip it + { + return; + } + + // for every child of the parent + for(child_list_const_iter_t child_it = parent->getChildList()->begin(); child_it != parent->getChildList()->end(); ++child_it) + { + LLView* child = *child_it; + if(overlapIgnorable(child)) + { + continue; + } + + // for every sibling + for(child_list_const_iter_t sibling_it = parent->getChildList()->begin(); sibling_it != parent->getChildList()->end(); ++sibling_it) // for each sibling + { + LLView* sibling = *sibling_it; + if(overlapIgnorable(sibling)) + { + continue; + } + + // if they overlap... (we don't care if they're visible or enabled -- we want to check those anyway, i.e. hidden tabs that can be later shown) + if(sibling != child && elementOverlap(child, sibling)) + { + mOverlapPanel->mOverlapMap[child].push_back(sibling); // add to the map + } + } + findOverlapsInChildren(child); // recur + } } // *HACK: don't overlap with the drag handle and various other elements @@ -1565,153 +1565,153 @@ void LLFloaterUIPreview::findOverlapsInChildren(LLView* parent) // *NOTE: If a list of elements which have localizable content were created, this function should return false if viewp's class is in that list. BOOL LLFloaterUIPreview::overlapIgnorable(LLView* viewp) { - return NULL != dynamic_cast<LLDragHandle*>(viewp) || - NULL != dynamic_cast<LLViewBorder*>(viewp) || - NULL != dynamic_cast<LLResizeBar*>(viewp); + return NULL != dynamic_cast<LLDragHandle*>(viewp) || + NULL != dynamic_cast<LLViewBorder*>(viewp) || + NULL != dynamic_cast<LLResizeBar*>(viewp); } // *HACK: these are the only two container types as of 8/08, per Richard // This is using dynamic casts because there is no object-oriented way to tell which elements are containers. BOOL LLFloaterUIPreview::containerType(LLView* viewp) { - return NULL != dynamic_cast<LLPanel*>(viewp) || NULL != dynamic_cast<LLLayoutStack*>(viewp); + return NULL != dynamic_cast<LLPanel*>(viewp) || NULL != dynamic_cast<LLLayoutStack*>(viewp); } // Check if two llview's rectangles overlap, with some tolerance BOOL LLFloaterUIPreview::elementOverlap(LLView* view1, LLView* view2) { - LLSD rec1 = view1->getRect().getValue(); - LLSD rec2 = view2->getRect().getValue(); - int tolerance = 2; - return (int)rec1[0] <= (int)rec2[2] - tolerance && - (int)rec2[0] <= (int)rec1[2] - tolerance && - (int)rec1[3] <= (int)rec2[1] - tolerance && - (int)rec2[3] <= (int)rec1[1] - tolerance; + LLSD rec1 = view1->getRect().getValue(); + LLSD rec2 = view2->getRect().getValue(); + int tolerance = 2; + return (int)rec1[0] <= (int)rec2[2] - tolerance && + (int)rec2[0] <= (int)rec1[2] - tolerance && + (int)rec1[3] <= (int)rec2[1] - tolerance && + (int)rec2[3] <= (int)rec1[1] - tolerance; } void LLOverlapPanel::draw() { - static const std::string current_selection_text("Current selection: "); - static const std::string overlapper_text("Overlapper: "); - LLColor4 text_color = LLColor4::grey; - gGL.color4fv(text_color.mV); - - if(!LLView::sPreviewClickedElement) - { - LLUI::translate(5,getRect().getHeight()-20); // translate to top-5,left-5 - LLView::sDrawPreviewHighlights = FALSE; - LLFontGL::getFontSansSerifSmall()->renderUTF8(current_selection_text, 0, 0, 0, text_color, - LLFontGL::LEFT, LLFontGL::BASELINE, LLFontGL::NORMAL, LLFontGL::NO_SHADOW); - } - else - { - OverlapMap::iterator iterExists = mOverlapMap.find(LLView::sPreviewClickedElement); - if(iterExists == mOverlapMap.end()) - { - return; - } - - std::list<LLView*> overlappers = mOverlapMap[LLView::sPreviewClickedElement]; - if(overlappers.size() == 0) - { - LLUI::translate(5,getRect().getHeight()-20); // translate to top-5,left-5 - LLView::sDrawPreviewHighlights = FALSE; - std::string current_selection = std::string(current_selection_text + LLView::sPreviewClickedElement->getName() + " (no elements overlap)"); - S32 text_width = LLFontGL::getFontSansSerifSmall()->getWidth(current_selection) + 10; - LLFontGL::getFontSansSerifSmall()->renderUTF8(current_selection, 0, 0, 0, text_color, - LLFontGL::LEFT, LLFontGL::BASELINE, LLFontGL::NORMAL, LLFontGL::NO_SHADOW); - // widen panel enough to fit this text - LLRect rect = getRect(); - setRect(LLRect(rect.mLeft,rect.mTop,rect.getWidth() < text_width ? rect.mLeft + text_width : rect.mRight,rect.mTop)); - return; - } - - // recalculate required with and height; otherwise use cached - BOOL need_to_recalculate_bounds = FALSE; - if(mLastClickedElement == NULL) - { - need_to_recalculate_bounds = TRUE; - } - - if(NULL == mLastClickedElement) - { - mLastClickedElement = LLView::sPreviewClickedElement; - } - - // recalculate bounds for scroll panel - if(need_to_recalculate_bounds || LLView::sPreviewClickedElement->getName() != mLastClickedElement->getName()) - { - // reset panel's rectangle to its default width and height (300x600) - LLRect panel_rect = getRect(); - setRect(LLRect(panel_rect.mLeft,panel_rect.mTop,panel_rect.mLeft+getRect().getWidth(),panel_rect.mTop-getRect().getHeight())); - - LLRect rect; - - // change bounds for selected element - int height_sum = mLastClickedElement->getRect().getHeight() + mSpacing + 80; - rect = getRect(); - setRect(LLRect(rect.mLeft,rect.mTop,rect.getWidth() > mLastClickedElement->getRect().getWidth() + 5 ? rect.mRight : rect.mLeft + mLastClickedElement->getRect().getWidth() + 5, rect.mBottom)); - - // and widen to accomodate text if that's wider - std::string display_text = current_selection_text + LLView::sPreviewClickedElement->getName(); - S32 text_width = LLFontGL::getFontSansSerifSmall()->getWidth(display_text) + 10; - rect = getRect(); - setRect(LLRect(rect.mLeft,rect.mTop,rect.getWidth() < text_width ? rect.mLeft + text_width : rect.mRight,rect.mTop)); - - std::list<LLView*> overlappers = mOverlapMap[LLView::sPreviewClickedElement]; - for(std::list<LLView*>::iterator overlap_it = overlappers.begin(); overlap_it != overlappers.end(); ++overlap_it) - { - LLView* viewp = *overlap_it; - height_sum += viewp->getRect().getHeight() + mSpacing*3; - - // widen panel's rectangle to accommodate widest overlapping element of this floater - rect = getRect(); - setRect(LLRect(rect.mLeft,rect.mTop,rect.getWidth() > viewp->getRect().getWidth() + 5 ? rect.mRight : rect.mLeft + viewp->getRect().getWidth() + 5, rect.mBottom)); - - // and widen to accomodate text if that's wider - std::string display_text = overlapper_text + viewp->getName(); - S32 text_width = LLFontGL::getFontSansSerifSmall()->getWidth(display_text) + 10; - rect = getRect(); - setRect(LLRect(rect.mLeft,rect.mTop,rect.getWidth() < text_width ? rect.mLeft + text_width : rect.mRight,rect.mTop)); - } - // change panel's height to accommodate all element heights plus spacing between them - rect = getRect(); - setRect(LLRect(rect.mLeft,rect.mTop,rect.mRight,rect.mTop-height_sum)); - } - - LLUI::translate(5,getRect().getHeight()-10); // translate to top left - LLView::sDrawPreviewHighlights = FALSE; - - // draw currently-selected element at top of overlappers - LLUI::translate(0,-mSpacing); - LLFontGL::getFontSansSerifSmall()->renderUTF8(current_selection_text + LLView::sPreviewClickedElement->getName(), 0, 0, 0, text_color, - LLFontGL::LEFT, LLFontGL::BASELINE, LLFontGL::NORMAL, LLFontGL::NO_SHADOW); - LLUI::translate(0,-mSpacing-LLView::sPreviewClickedElement->getRect().getHeight()); // skip spacing distance + height - LLView::sPreviewClickedElement->draw(); - - for(std::list<LLView*>::iterator overlap_it = overlappers.begin(); overlap_it != overlappers.end(); ++overlap_it) - { - LLView* viewp = *overlap_it; - - // draw separating line - LLUI::translate(0,-mSpacing); - gl_line_2d(0,0,getRect().getWidth()-10,0,LLColor4(192.0f/255.0f,192.0f/255.0f,192.0f/255.0f)); - - // draw name - LLUI::translate(0,-mSpacing); - LLFontGL::getFontSansSerifSmall()->renderUTF8(overlapper_text + viewp->getName(), 0, 0, 0, text_color, - LLFontGL::LEFT, LLFontGL::BASELINE, LLFontGL::NORMAL, LLFontGL::NO_SHADOW); - - // draw element - LLUI::translate(0,-mSpacing-viewp->getRect().getHeight()); // skip spacing distance + height - viewp->draw(); - } - mLastClickedElement = LLView::sPreviewClickedElement; - } + static const std::string current_selection_text("Current selection: "); + static const std::string overlapper_text("Overlapper: "); + LLColor4 text_color = LLColor4::grey; + gGL.color4fv(text_color.mV); + + if(!LLView::sPreviewClickedElement) + { + LLUI::translate(5,getRect().getHeight()-20); // translate to top-5,left-5 + LLView::sDrawPreviewHighlights = FALSE; + LLFontGL::getFontSansSerifSmall()->renderUTF8(current_selection_text, 0, 0, 0, text_color, + LLFontGL::LEFT, LLFontGL::BASELINE, LLFontGL::NORMAL, LLFontGL::NO_SHADOW); + } + else + { + OverlapMap::iterator iterExists = mOverlapMap.find(LLView::sPreviewClickedElement); + if(iterExists == mOverlapMap.end()) + { + return; + } + + std::list<LLView*> overlappers = mOverlapMap[LLView::sPreviewClickedElement]; + if(overlappers.size() == 0) + { + LLUI::translate(5,getRect().getHeight()-20); // translate to top-5,left-5 + LLView::sDrawPreviewHighlights = FALSE; + std::string current_selection = std::string(current_selection_text + LLView::sPreviewClickedElement->getName() + " (no elements overlap)"); + S32 text_width = LLFontGL::getFontSansSerifSmall()->getWidth(current_selection) + 10; + LLFontGL::getFontSansSerifSmall()->renderUTF8(current_selection, 0, 0, 0, text_color, + LLFontGL::LEFT, LLFontGL::BASELINE, LLFontGL::NORMAL, LLFontGL::NO_SHADOW); + // widen panel enough to fit this text + LLRect rect = getRect(); + setRect(LLRect(rect.mLeft,rect.mTop,rect.getWidth() < text_width ? rect.mLeft + text_width : rect.mRight,rect.mTop)); + return; + } + + // recalculate required with and height; otherwise use cached + BOOL need_to_recalculate_bounds = FALSE; + if(mLastClickedElement == NULL) + { + need_to_recalculate_bounds = TRUE; + } + + if(NULL == mLastClickedElement) + { + mLastClickedElement = LLView::sPreviewClickedElement; + } + + // recalculate bounds for scroll panel + if(need_to_recalculate_bounds || LLView::sPreviewClickedElement->getName() != mLastClickedElement->getName()) + { + // reset panel's rectangle to its default width and height (300x600) + LLRect panel_rect = getRect(); + setRect(LLRect(panel_rect.mLeft,panel_rect.mTop,panel_rect.mLeft+getRect().getWidth(),panel_rect.mTop-getRect().getHeight())); + + LLRect rect; + + // change bounds for selected element + int height_sum = mLastClickedElement->getRect().getHeight() + mSpacing + 80; + rect = getRect(); + setRect(LLRect(rect.mLeft,rect.mTop,rect.getWidth() > mLastClickedElement->getRect().getWidth() + 5 ? rect.mRight : rect.mLeft + mLastClickedElement->getRect().getWidth() + 5, rect.mBottom)); + + // and widen to accomodate text if that's wider + std::string display_text = current_selection_text + LLView::sPreviewClickedElement->getName(); + S32 text_width = LLFontGL::getFontSansSerifSmall()->getWidth(display_text) + 10; + rect = getRect(); + setRect(LLRect(rect.mLeft,rect.mTop,rect.getWidth() < text_width ? rect.mLeft + text_width : rect.mRight,rect.mTop)); + + std::list<LLView*> overlappers = mOverlapMap[LLView::sPreviewClickedElement]; + for(std::list<LLView*>::iterator overlap_it = overlappers.begin(); overlap_it != overlappers.end(); ++overlap_it) + { + LLView* viewp = *overlap_it; + height_sum += viewp->getRect().getHeight() + mSpacing*3; + + // widen panel's rectangle to accommodate widest overlapping element of this floater + rect = getRect(); + setRect(LLRect(rect.mLeft,rect.mTop,rect.getWidth() > viewp->getRect().getWidth() + 5 ? rect.mRight : rect.mLeft + viewp->getRect().getWidth() + 5, rect.mBottom)); + + // and widen to accomodate text if that's wider + std::string display_text = overlapper_text + viewp->getName(); + S32 text_width = LLFontGL::getFontSansSerifSmall()->getWidth(display_text) + 10; + rect = getRect(); + setRect(LLRect(rect.mLeft,rect.mTop,rect.getWidth() < text_width ? rect.mLeft + text_width : rect.mRight,rect.mTop)); + } + // change panel's height to accommodate all element heights plus spacing between them + rect = getRect(); + setRect(LLRect(rect.mLeft,rect.mTop,rect.mRight,rect.mTop-height_sum)); + } + + LLUI::translate(5,getRect().getHeight()-10); // translate to top left + LLView::sDrawPreviewHighlights = FALSE; + + // draw currently-selected element at top of overlappers + LLUI::translate(0,-mSpacing); + LLFontGL::getFontSansSerifSmall()->renderUTF8(current_selection_text + LLView::sPreviewClickedElement->getName(), 0, 0, 0, text_color, + LLFontGL::LEFT, LLFontGL::BASELINE, LLFontGL::NORMAL, LLFontGL::NO_SHADOW); + LLUI::translate(0,-mSpacing-LLView::sPreviewClickedElement->getRect().getHeight()); // skip spacing distance + height + LLView::sPreviewClickedElement->draw(); + + for(std::list<LLView*>::iterator overlap_it = overlappers.begin(); overlap_it != overlappers.end(); ++overlap_it) + { + LLView* viewp = *overlap_it; + + // draw separating line + LLUI::translate(0,-mSpacing); + gl_line_2d(0,0,getRect().getWidth()-10,0,LLColor4(192.0f/255.0f,192.0f/255.0f,192.0f/255.0f)); + + // draw name + LLUI::translate(0,-mSpacing); + LLFontGL::getFontSansSerifSmall()->renderUTF8(overlapper_text + viewp->getName(), 0, 0, 0, text_color, + LLFontGL::LEFT, LLFontGL::BASELINE, LLFontGL::NORMAL, LLFontGL::NO_SHADOW); + + // draw element + LLUI::translate(0,-mSpacing-viewp->getRect().getHeight()); // skip spacing distance + height + viewp->draw(); + } + mLastClickedElement = LLView::sPreviewClickedElement; + } } void LLFloaterUIPreviewUtil::registerFloater() { - LLFloaterReg::add("ui_preview", "floater_ui_preview.xml", - &LLFloaterReg::build<LLFloaterUIPreview>); + LLFloaterReg::add("ui_preview", "floater_ui_preview.xml", + &LLFloaterReg::build<LLFloaterUIPreview>); } |