summaryrefslogtreecommitdiff
path: root/indra/llui
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llui')
-rw-r--r--indra/llui/llbutton.cpp15
-rw-r--r--indra/llui/llbutton.h1
-rw-r--r--indra/llui/lldockablefloater.cpp58
-rw-r--r--indra/llui/lldockablefloater.h10
-rw-r--r--indra/llui/llfloater.cpp24
-rw-r--r--indra/llui/llfloater.h2
-rw-r--r--indra/llui/llfloaterreg.cpp9
-rw-r--r--indra/llui/lllineeditor.cpp81
-rw-r--r--indra/llui/lllineeditor.h16
-rw-r--r--indra/llui/llmenugl.cpp42
-rw-r--r--indra/llui/llpanel.cpp41
-rw-r--r--indra/llui/llpanel.h1
-rw-r--r--indra/llui/llresmgr.cpp8
-rw-r--r--indra/llui/llscrollbar.cpp12
-rw-r--r--indra/llui/llscrollbar.h7
-rw-r--r--indra/llui/llscrolllistctrl.cpp3
-rw-r--r--indra/llui/llscrolllistitem.h4
-rw-r--r--indra/llui/llsearcheditor.cpp6
-rw-r--r--indra/llui/lltabcontainer.cpp13
-rw-r--r--indra/llui/lltabcontainer.h5
-rw-r--r--indra/llui/lltextbase.cpp212
-rw-r--r--indra/llui/lltextbase.h18
-rw-r--r--indra/llui/lltexteditor.cpp9
-rw-r--r--indra/llui/lltexteditor.h1
-rw-r--r--indra/llui/lltooltip.cpp2
-rw-r--r--indra/llui/lltooltip.h1
-rw-r--r--indra/llui/llui.cpp16
-rw-r--r--indra/llui/llui.h7
-rw-r--r--indra/llui/lluictrl.cpp44
-rw-r--r--indra/llui/lluictrl.h21
-rw-r--r--indra/llui/lluictrlfactory.cpp16
-rw-r--r--indra/llui/lluictrlfactory.h2
-rw-r--r--indra/llui/lluiimage.cpp3
-rw-r--r--indra/llui/lluiimage.h6
-rw-r--r--indra/llui/lluistring.h4
-rw-r--r--indra/llui/llview.cpp15
-rw-r--r--indra/llui/llview.h16
37 files changed, 431 insertions, 320 deletions
diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp
index 219c2ee254..f28fca35c5 100644
--- a/indra/llui/llbutton.cpp
+++ b/indra/llui/llbutton.cpp
@@ -52,6 +52,7 @@
#include "llrender.h"
#include "lluictrlfactory.h"
#include "llhelp.h"
+#include "lldockablefloater.h"
static LLDefaultChildRegistry::Register<LLButton> r("button");
@@ -1057,6 +1058,20 @@ void LLButton::setFloaterToggle(LLUICtrl* ctrl, const LLSD& sdname)
}
// static
+void LLButton::setDockableFloaterToggle(LLUICtrl* ctrl, const LLSD& sdname)
+{
+ LLButton* button = dynamic_cast<LLButton*>(ctrl);
+ if (!button)
+ return;
+ // Get the visibility control name for the floater
+ std::string vis_control_name = LLFloaterReg::declareVisibilityControl(sdname.asString());
+ // Set the button control value (toggle state) to the floater visibility control (Sets the value as well)
+ button->setControlVariable(LLUI::sSettingGroups["floater"]->getControl(vis_control_name));
+ // Set the clicked callback to toggle the floater
+ button->setClickedCallback(boost::bind(&LLDockableFloater::toggleInstance, sdname));
+}
+
+// static
void LLButton::showHelp(LLUICtrl* ctrl, const LLSD& sdname)
{
// search back through the button's parents for a panel
diff --git a/indra/llui/llbutton.h b/indra/llui/llbutton.h
index 73ba457d34..7ca520b935 100644
--- a/indra/llui/llbutton.h
+++ b/indra/llui/llbutton.h
@@ -232,6 +232,7 @@ public:
static void onHeldDown(void *userdata); // to be called by gIdleCallbacks
static void toggleFloaterAndSetToggleState(LLUICtrl* ctrl, const LLSD& sdname);
static void setFloaterToggle(LLUICtrl* ctrl, const LLSD& sdname);
+ static void setDockableFloaterToggle(LLUICtrl* ctrl, const LLSD& sdname);
static void showHelp(LLUICtrl* ctrl, const LLSD& sdname);
void setForcePressedState(BOOL b) { mForcePressedState = b; }
diff --git a/indra/llui/lldockablefloater.cpp b/indra/llui/lldockablefloater.cpp
index c512ef25be..228d0e701f 100644
--- a/indra/llui/lldockablefloater.cpp
+++ b/indra/llui/lldockablefloater.cpp
@@ -33,24 +33,36 @@
#include "linden_common.h"
#include "lldockablefloater.h"
+#include "llfloaterreg.h"
//static
LLHandle<LLFloater> LLDockableFloater::sInstanceHandle;
+//static
+void LLDockableFloater::init(LLDockableFloater* thiz)
+{
+ thiz->setDocked(thiz->mDockControl.get() != NULL
+ && thiz->mDockControl.get()->isDockVisible());
+ thiz->resetInstance();
+
+ // all dockable floaters should have close, dock and minimize buttons
+ thiz->setCanClose(TRUE);
+ thiz->setCanDock(true);
+ thiz->setCanMinimize(TRUE);
+}
+
LLDockableFloater::LLDockableFloater(LLDockControl* dockControl,
const LLSD& key, const Params& params) :
LLFloater(key, params), mDockControl(dockControl), mUniqueDocking(true)
{
- setDocked(mDockControl.get() != NULL && mDockControl.get()->isDockVisible());
- resetInstance();
+ init(this);
}
LLDockableFloater::LLDockableFloater(LLDockControl* dockControl, bool uniqueDocking,
const LLSD& key, const Params& params) :
LLFloater(key, params), mDockControl(dockControl), mUniqueDocking(uniqueDocking)
{
- setDocked(mDockControl.get() != NULL && mDockControl.get()->isDockVisible());
- resetInstance();
+ init(this);
}
LLDockableFloater::~LLDockableFloater()
@@ -64,6 +76,33 @@ BOOL LLDockableFloater::postBuild()
return LLView::postBuild();
}
+//static
+void LLDockableFloater::toggleInstance(const LLSD& sdname)
+{
+ LLSD key;
+ std::string name = sdname.asString();
+
+ LLDockableFloater* instance =
+ dynamic_cast<LLDockableFloater*> (LLFloaterReg::findInstance(name));
+ // if floater closed or docked
+ if (instance == NULL || instance != NULL && instance->isDocked())
+ {
+ LLFloaterReg::toggleInstance(name, key);
+ // restore button toggle state
+ if (instance != NULL)
+ {
+ instance->storeVisibilityControl();
+ }
+ }
+ // if floater undocked
+ else if (instance != NULL)
+ {
+ instance->setMinimized(FALSE);
+ instance->setVisible(TRUE);
+ instance->setFocus(TRUE);
+ }
+}
+
void LLDockableFloater::resetInstance()
{
if (mUniqueDocking && sInstanceHandle.get() != this)
@@ -91,6 +130,17 @@ void LLDockableFloater::setVisible(BOOL visible)
LLFloater::setVisible(visible);
}
+void LLDockableFloater::setMinimized(BOOL minimize)
+{
+ if(minimize && isDocked())
+ {
+ setVisible(FALSE);
+ }
+ setCanDock(!minimize);
+
+ LLFloater::setMinimized(minimize);
+}
+
void LLDockableFloater::onDockHidden()
{
setCanDock(FALSE);
diff --git a/indra/llui/lldockablefloater.h b/indra/llui/lldockablefloater.h
index 7d91d007ee..499ce9ae8d 100644
--- a/indra/llui/lldockablefloater.h
+++ b/indra/llui/lldockablefloater.h
@@ -44,6 +44,8 @@
class LLDockableFloater : public LLFloater
{
static const U32 UNDOCK_LEAP_HEIGHT = 12;
+
+ static void init(LLDockableFloater* thiz);
public:
LOG_CLASS(LLDockableFloater);
LLDockableFloater(LLDockControl* dockControl, const LLSD& key,
@@ -54,6 +56,8 @@ public:
static LLHandle<LLFloater> getInstanceHandle() { return sInstanceHandle; }
+ static void toggleInstance(const LLSD& sdname);
+
/**
* If descendant class overrides postBuild() in order to perform specific
* construction then it must still invoke its superclass' implementation.
@@ -68,6 +72,12 @@ public:
*/
/*virtual*/ void setVisible(BOOL visible);
+ /**
+ * If descendant class overrides setMinimized() then it must still invoke its
+ * superclass' implementation.
+ */
+ /*virtual*/ void setMinimized(BOOL minimize);
+
virtual void onDockHidden();
virtual void onDockShown();
diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp
index 66defbbf0a..647c816fdf 100644
--- a/indra/llui/llfloater.cpp
+++ b/indra/llui/llfloater.cpp
@@ -916,6 +916,9 @@ void LLFloater::setMinimized(BOOL minimize)
if (minimize)
{
+ // minimized flag should be turned on before release focus
+ mMinimized = TRUE;
+
mExpandedRect = getRect();
// If the floater has been dragged while minimized in the
@@ -977,8 +980,6 @@ void LLFloater::setMinimized(BOOL minimize)
}
}
- mMinimized = TRUE;
-
// Reshape *after* setting mMinimized
reshape( minimized_width, floater_header_size, TRUE);
}
@@ -1432,7 +1433,18 @@ void LLFloater::onClickHelp( LLFloater* self )
{
if (self && LLUI::sHelpImpl)
{
- LLUI::sHelpImpl->showTopic(self->getHelpTopic());
+ // get the help topic for this floater
+ std::string help_topic = self->getHelpTopic();
+
+ // but use a more specific help topic for the currently
+ // displayed tab inside of this floater, if present
+ LLPanel *curtab = self->childGetVisibleTabWithHelp();
+ if (curtab)
+ {
+ help_topic = curtab->getHelpTopic();
+ }
+
+ LLUI::sHelpImpl->showTopic(help_topic);
}
}
@@ -2554,10 +2566,10 @@ void LLFloater::initFromParams(const LLFloater::Params& p)
LLFastTimer::DeclareTimer POST_BUILD("Floater Post Build");
-void LLFloater::initFloaterXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr output_node)
+bool LLFloater::initFloaterXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr output_node)
{
Params params(LLUICtrlFactory::getDefaultParams<LLFloater>());
- LLXUIParser::instance().readXUI(node, params);
+ LLXUIParser::instance().readXUI(node, params); // *TODO: Error checking
if (output_node)
{
@@ -2603,5 +2615,7 @@ void LLFloater::initFloaterXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr o
gFloaterView->adjustToFitScreen(this, FALSE); // Floaters loaded from XML should all fit on screen
moveResizeHandlesToFront();
+
+ return true; // *TODO: Error checking
}
diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h
index 466d060068..cbe374252f 100644
--- a/indra/llui/llfloater.h
+++ b/indra/llui/llfloater.h
@@ -146,7 +146,7 @@ public:
static void setupParamsForExport(Params& p, LLView* parent);
void initFromParams(const LLFloater::Params& p);
- void initFloaterXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr output_node = NULL);
+ bool initFloaterXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr output_node = NULL);
/*virtual*/ void handleReshape(const LLRect& new_rect, bool by_user = false);
/*virtual*/ BOOL canSnapTo(const LLView* other_view);
diff --git a/indra/llui/llfloaterreg.cpp b/indra/llui/llfloaterreg.cpp
index 8617ba940e..8e56951dbf 100644
--- a/indra/llui/llfloaterreg.cpp
+++ b/indra/llui/llfloaterreg.cpp
@@ -124,8 +124,13 @@ LLFloater* LLFloaterReg::getInstance(const std::string& name, const LLSD& key)
res = build_func(key);
- LLUICtrlFactory::getInstance()->buildFloater(res, xui_file, NULL);
-
+ bool success = LLUICtrlFactory::getInstance()->buildFloater(res, xui_file, NULL);
+ if (!success)
+ {
+ llwarns << "Failed to buid floater type: '" << name << "'." << llendl;
+ return NULL;
+ }
+
// Note: key should eventually be a non optional LLFloater arg; for now, set mKey to be safe
res->mKey = key;
res->setInstanceName(name);
diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp
index 693ea5bb45..e053477d58 100644
--- a/indra/llui/lllineeditor.cpp
+++ b/indra/llui/lllineeditor.cpp
@@ -148,6 +148,7 @@ LLLineEditor::LLLineEditor(const LLLineEditor::Params& p)
mBgImage( p.background_image ),
mBgImageDisabled( p.background_image_disabled ),
mBgImageFocused( p.background_image_focused ),
+ mHaveHistory(FALSE),
mReplaceNewlinesWithSpaces( TRUE ),
mLabel(p.label),
mCursorColor(p.cursor_color()),
@@ -164,13 +165,8 @@ LLLineEditor::LLLineEditor(const LLLineEditor::Params& p)
mTripleClickTimer.reset();
setText(p.default_text());
- // line history support:
- // - initialize line history list
- mLineHistory.insert( mLineHistory.end(), "" );
- // - disable line history by default
- mHaveHistory = FALSE;
- // - reset current history line pointer
- mCurrentHistoryLine = 0;
+ // Initialize current history line iterator
+ mCurrentHistoryLine = mLineHistory.begin();
LLRect border_rect(getLocalRect());
// adjust for gl line drawing glitch
@@ -278,16 +274,31 @@ void LLLineEditor::updateHistory()
// reset current history line number.
// Be sure only to remember lines that are not empty and that are
// different from the last on the list.
- if( mHaveHistory && mText.length() && ( mLineHistory.empty() || getText() != mLineHistory.back() ) )
+ if( mHaveHistory && getLength() )
{
- // discard possible empty line at the end of the history
- // inserted by setText()
- if( !mLineHistory.back().length() )
+ if( !mLineHistory.empty() )
{
- mLineHistory.pop_back();
+ // When not empty, last line of history should always be blank.
+ if( mLineHistory.back().empty() )
+ {
+ // discard the empty line
+ mLineHistory.pop_back();
+ }
+ else
+ {
+ LL_WARNS("") << "Last line of history was not blank." << LL_ENDL;
+ }
+ }
+
+ // Add text to history, ignoring duplicates
+ if( mLineHistory.empty() || getText() != mLineHistory.back() )
+ {
+ mLineHistory.push_back( getText() );
}
- mLineHistory.insert( mLineHistory.end(), getText() );
- mCurrentHistoryLine = mLineHistory.size() - 1;
+
+ // Restore the blank line and set mCurrentHistoryLine to point at it
+ mLineHistory.push_back( "" );
+ mCurrentHistoryLine = mLineHistory.end() - 1;
}
}
@@ -357,11 +368,8 @@ void LLLineEditor::setText(const LLStringExplicit &new_text)
}
setCursor(llmin((S32)mText.length(), getCursor()));
- // Newly set text goes always in the last line of history.
- // Possible empty strings (as with chat line) will be deleted later.
- mLineHistory.insert( mLineHistory.end(), new_text );
// Set current history line to end of history.
- mCurrentHistoryLine = mLineHistory.size() - 1;
+ mCurrentHistoryLine = mLineHistory.end() - 1;
mPrevText = mText;
}
@@ -1254,9 +1262,9 @@ BOOL LLLineEditor::handleSpecialKey(KEY key, MASK mask)
case KEY_UP:
if( mHaveHistory && ( MASK_CONTROL == mask ) )
{
- if( mCurrentHistoryLine > 0 )
+ if( mCurrentHistoryLine > mLineHistory.begin() )
{
- mText.assign( mLineHistory[ --mCurrentHistoryLine ] );
+ mText.assign( *(--mCurrentHistoryLine) );
setCursor(llmin((S32)mText.length(), getCursor()));
}
else
@@ -1271,9 +1279,9 @@ BOOL LLLineEditor::handleSpecialKey(KEY key, MASK mask)
case KEY_DOWN:
if( mHaveHistory && ( MASK_CONTROL == mask ) )
{
- if( !mLineHistory.empty() && mCurrentHistoryLine < mLineHistory.size() - 1 )
+ if( !mLineHistory.empty() && mCurrentHistoryLine < mLineHistory.end() - 1 )
{
- mText.assign( mLineHistory[ ++mCurrentHistoryLine ] );
+ mText.assign( *(++mCurrentHistoryLine) );
setCursor(llmin((S32)mText.length(), getCursor()));
}
else
@@ -2291,14 +2299,20 @@ BOOL LLLineEditor::hasPreeditString() const
void LLLineEditor::resetPreedit()
{
- if (hasPreeditString())
+ if (hasSelection())
{
- if (hasSelection())
+ if (hasPreeditString())
{
llwarns << "Preedit and selection!" << llendl;
deselect();
}
-
+ else
+ {
+ deleteSelection();
+ }
+ }
+ if (hasPreeditString())
+ {
const S32 preedit_pos = mPreeditPositions.front();
mText.erase(preedit_pos, mPreeditPositions.back() - preedit_pos);
mText.insert(preedit_pos, mPreeditOverwrittenWString);
@@ -2500,20 +2514,3 @@ LLWString LLLineEditor::getConvertedText() const
}
return text;
}
-
-namespace LLInitParam
-{
- template<>
- bool ParamCompare<LLLinePrevalidateFunc>::equals(const LLLinePrevalidateFunc &a, const LLLinePrevalidateFunc &b)
- {
- return false;
- }
-
- template<>
- bool ParamCompare<boost::function<void (LLLineEditor *)> >::equals(
- const boost::function<void (LLLineEditor *)> &a,
- const boost::function<void (LLLineEditor *)> &b)
- {
- return false;
- }
-}
diff --git a/indra/llui/lllineeditor.h b/indra/llui/lllineeditor.h
index 48d68b9935..3d7bbdff89 100644
--- a/indra/llui/lllineeditor.h
+++ b/indra/llui/lllineeditor.h
@@ -286,8 +286,9 @@ protected:
// line history support:
BOOL mHaveHistory; // flag for enabled line history
- std::vector<std::string> mLineHistory; // line history storage
- U32 mCurrentHistoryLine; // currently browsed history line
+ typedef std::vector<std::string> line_history_t;
+ line_history_t mLineHistory; // line history storage
+ line_history_t::iterator mCurrentHistoryLine; // currently browsed history line
LLViewBorder* mBorder;
const LLFontGL* mGLFont;
@@ -390,15 +391,4 @@ private:
}; // end class LLLineEditor
-namespace LLInitParam
-{
- template<>
- bool ParamCompare<LLLinePrevalidateFunc>::equals(
- const LLLinePrevalidateFunc &a, const LLLinePrevalidateFunc &b);
-
- template<>
- bool ParamCompare<boost::function<void (LLLineEditor *)> >::equals(
- const boost::function<void (LLLineEditor *)> &a, const boost::function<void (LLLineEditor *)> &b);
-}
-
#endif // LL_LINEEDITOR_
diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp
index 14bee0465c..cf013efca0 100644
--- a/indra/llui/llmenugl.cpp
+++ b/indra/llui/llmenugl.cpp
@@ -279,47 +279,7 @@ BOOL LLMenuItemGL::addToAcceleratorList(std::list <LLKeyBinding*> *listp)
// the current accelerator key and mask to the provided string.
void LLMenuItemGL::appendAcceleratorString( std::string& st ) const
{
- // break early if this is a silly thing to do.
- if( KEY_NONE == mAcceleratorKey )
- {
- return;
- }
-
- // Append any masks
-#ifdef LL_DARWIN
- // Standard Mac names for modifier keys in menu equivalents
- // We could use the symbol characters, but they only exist in certain fonts.
- if( mAcceleratorMask & MASK_CONTROL )
- {
- if ( mAcceleratorMask & MASK_MAC_CONTROL )
- {
- st.append( "Ctrl-" );
- }
- else
- {
- st.append( "Cmd-" ); // Symbol would be "\xE2\x8C\x98"
- }
- }
- if( mAcceleratorMask & MASK_ALT )
- st.append( "Opt-" ); // Symbol would be "\xE2\x8C\xA5"
- if( mAcceleratorMask & MASK_SHIFT )
- st.append( "Shift-" ); // Symbol would be "\xE2\x8C\xA7"
-#else
- if( mAcceleratorMask & MASK_CONTROL )
- st.append( "Ctrl-" );
- if( mAcceleratorMask & MASK_ALT )
- st.append( "Alt-" );
- if( mAcceleratorMask & MASK_SHIFT )
- st.append( "Shift-" );
-#endif
-
- std::string keystr = LLKeyboard::stringFromKey( mAcceleratorKey );
- if ((mAcceleratorMask & MASK_NORMALKEYS) &&
- (keystr[0] == '-' || keystr[0] == '='))
- {
- st.append( " " );
- }
- st.append( keystr );
+ st = LLKeyboard::stringFromAccelerator( mAcceleratorMask, mAcceleratorKey );
LL_DEBUGS("HotKeys") << "appendAcceleratorString: " << st << LL_ENDL;
}
diff --git a/indra/llui/llpanel.cpp b/indra/llui/llpanel.cpp
index 69ff3dddc3..742427525b 100644
--- a/indra/llui/llpanel.cpp
+++ b/indra/llui/llpanel.cpp
@@ -810,6 +810,47 @@ LLPanel *LLPanel::childGetVisibleTab(const std::string& id) const
return NULL;
}
+static LLPanel *childGetVisibleTabWithHelp(LLView *parent)
+{
+ LLView *child;
+
+ // look through immediate children first for an active tab with help
+ for (child = parent->getFirstChild(); child; child = parent->findNextSibling(child))
+ {
+ LLTabContainer *tab = dynamic_cast<LLTabContainer *>(child);
+ if (tab && tab->getVisible())
+ {
+ LLPanel *curTabPanel = tab->getCurrentPanel();
+ if (curTabPanel && !curTabPanel->getHelpTopic().empty())
+ {
+ return curTabPanel;
+ }
+ }
+ }
+
+ // then try a bit harder and recurse through all children
+ for (child = parent->getFirstChild(); child; child = parent->findNextSibling(child))
+ {
+ if (child->getVisible())
+ {
+ LLPanel* tab = ::childGetVisibleTabWithHelp(child);
+ if (tab)
+ {
+ return tab;
+ }
+ }
+ }
+
+ // couldn't find any active tabs with a help topic string
+ return NULL;
+}
+
+LLPanel *LLPanel::childGetVisibleTabWithHelp()
+{
+ // find a visible tab with a help topic (to determine help context)
+ return ::childGetVisibleTabWithHelp(this);
+}
+
void LLPanel::childSetPrevalidate(const std::string& id, BOOL (*func)(const LLWString &) )
{
LLLineEditor* child = findChild<LLLineEditor>(id);
diff --git a/indra/llui/llpanel.h b/indra/llui/llpanel.h
index 0594762333..e8db68ffbb 100644
--- a/indra/llui/llpanel.h
+++ b/indra/llui/llpanel.h
@@ -208,6 +208,7 @@ public:
// LLTabContainer
void childShowTab(const std::string& id, const std::string& tabname, bool visible = true);
LLPanel *childGetVisibleTab(const std::string& id) const;
+ LLPanel *childGetVisibleTabWithHelp();
// LLTextBox/LLTextEditor/LLLineEditor
void childSetText(const std::string& id, const LLStringExplicit& text) { childSetValue(id, LLSD(text)); }
diff --git a/indra/llui/llresmgr.cpp b/indra/llui/llresmgr.cpp
index a4e23a605b..ed870d46d5 100644
--- a/indra/llui/llresmgr.cpp
+++ b/indra/llui/llresmgr.cpp
@@ -279,6 +279,14 @@ std::string LLResMgr::getMonetaryString( S32 input ) const
void LLResMgr::getIntegerString( std::string& output, S32 input ) const
{
+ // handle special case of input value being zero
+ if (input == 0)
+ {
+ output = "0";
+ return;
+ }
+
+ // *NOTE: this method does not handle negative input integers correctly
S32 fraction = 0;
std::string fraction_string;
S32 remaining_count = input;
diff --git a/indra/llui/llscrollbar.cpp b/indra/llui/llscrollbar.cpp
index 7db34a0608..cb4147709d 100644
--- a/indra/llui/llscrollbar.cpp
+++ b/indra/llui/llscrollbar.cpp
@@ -640,15 +640,3 @@ void LLScrollbar::onLineDownBtnPressed( const LLSD& data )
{
changeLine( mStepSize, TRUE );
}
-
-
-namespace LLInitParam
-{
- template<>
- bool ParamCompare<boost::function<void (S32, LLScrollbar*)> >::equals(
- const boost::function<void (S32, LLScrollbar*)> &a,
- const boost::function<void (S32, LLScrollbar*)> &b)
- {
- return false;
- }
-}
diff --git a/indra/llui/llscrollbar.h b/indra/llui/llscrollbar.h
index e4c5712fb7..2e95779624 100644
--- a/indra/llui/llscrollbar.h
+++ b/indra/llui/llscrollbar.h
@@ -167,11 +167,4 @@ private:
};
-namespace LLInitParam
-{
- template<>
- bool ParamCompare<boost::function<void (S32, LLScrollbar*)> >::equals(
- const boost::function<void (S32, LLScrollbar*)> &a, const boost::function<void (S32, LLScrollbar*)> &b);
-}
-
#endif // LL_SCROLLBAR_H
diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp
index 7b74b1f93b..a6cd6412e5 100644
--- a/indra/llui/llscrolllistctrl.cpp
+++ b/indra/llui/llscrolllistctrl.cpp
@@ -1411,6 +1411,7 @@ void LLScrollListCtrl::drawItems()
cur_y,
mItemListRect.getWidth(),
mLineHeight );
+ item->setRect(item_rect);
//llinfos << item_rect.getWidth() << llendl;
@@ -1708,7 +1709,7 @@ BOOL LLScrollListCtrl::handleMouseDown(S32 x, S32 y, MASK mask)
}
BOOL LLScrollListCtrl::handleMouseUp(S32 x, S32 y, MASK mask)
-{
+{
if (hasMouseCapture())
{
// release mouse capture immediately so
diff --git a/indra/llui/llscrolllistitem.h b/indra/llui/llscrolllistitem.h
index 0ec7fbcc2c..15b86cc945 100644
--- a/indra/llui/llscrolllistitem.h
+++ b/indra/llui/llscrolllistitem.h
@@ -97,6 +97,9 @@ public:
LLUUID getUUID() const { return mItemValue.asUUID(); }
LLSD getValue() const { return mItemValue; }
+
+ void setRect(LLRect rect) { mRectangle = rect; }
+ LLRect getRect() const { return mRectangle; }
void addColumn( const LLScrollListCell::Params& p );
@@ -122,6 +125,7 @@ private:
void* mUserdata;
LLSD mItemValue;
std::vector<LLScrollListCell *> mColumns;
+ LLRect mRectangle;
};
#endif
diff --git a/indra/llui/llsearcheditor.cpp b/indra/llui/llsearcheditor.cpp
index b87f645f3f..fad2b7bc99 100644
--- a/indra/llui/llsearcheditor.cpp
+++ b/indra/llui/llsearcheditor.cpp
@@ -37,9 +37,9 @@
#include "llsearcheditor.h"
LLSearchEditor::LLSearchEditor(const LLSearchEditor::Params& p)
-: LLUICtrl(p)
- , mSearchButton(NULL)
- , mClearButton(NULL)
+: LLUICtrl(p),
+ mSearchButton(NULL),
+ mClearButton(NULL)
{
S32 srch_btn_top = p.search_button.top_pad + p.search_button.rect.height;
S32 srch_btn_right = p.search_button.rect.width + p.search_button.left_pad;
diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp
index b1067ad6f3..3ca05ff0ff 100644
--- a/indra/llui/lltabcontainer.cpp
+++ b/indra/llui/lltabcontainer.cpp
@@ -107,9 +107,10 @@ static LLDefaultChildRegistry::Register<LLTabContainer> r2("tab_container");
LLTabContainer::Params::Params()
: tab_width("tab_width"),
- tab_position("tab_position"),
tab_min_width("tab_min_width"),
tab_max_width("tab_max_width"),
+ tab_height("tab_height"),
+ tab_position("tab_position"),
hide_tabs("hide_tabs", false),
tab_padding_right("tab_padding_right"),
tab_top_image_unselected("tab_top_image_unselected"),
@@ -136,6 +137,7 @@ LLTabContainer::LLTabContainer(const LLTabContainer::Params& p)
mLockedTabCount(0),
mMinTabWidth(0),
mMaxTabWidth(p.tab_max_width),
+ mTabHeight(p.tab_height),
mPrevArrowBtn(NULL),
mNextArrowBtn(NULL),
mIsVertical( p.tab_position == LEFT ),
@@ -802,7 +804,6 @@ void LLTabContainer::addTabPanel(const TabPanelParams& panel)
static LLUICachedControl<S32> tabcntrv_pad ("UITabCntrvPad", 0);
static LLUICachedControl<S32> tabcntr_button_panel_overlap ("UITabCntrButtonPanelOverlap", 0);
- static LLUICachedControl<S32> tabcntr_tab_height ("UITabCntrTabHeight", 0);
static LLUICachedControl<S32> tab_padding ("UITabPadding", 0);
if (child->getParent() == this)
{
@@ -830,14 +831,14 @@ void LLTabContainer::addTabPanel(const TabPanelParams& panel)
{
if( getTabPosition() == LLTabContainer::TOP )
{
- S32 tab_height = mIsVertical ? BTN_HEIGHT : tabcntr_tab_height;
+ S32 tab_height = mIsVertical ? BTN_HEIGHT : mTabHeight;
tab_panel_top = getRect().getHeight() - getTopBorderHeight() - (tab_height - tabcntr_button_panel_overlap);
tab_panel_bottom = LLPANEL_BORDER_WIDTH;
}
else
{
tab_panel_top = getRect().getHeight() - getTopBorderHeight();
- tab_panel_bottom = (tabcntr_tab_height - tabcntr_button_panel_overlap); // Run to the edge, covering up the border
+ tab_panel_bottom = (mTabHeight - tabcntr_button_panel_overlap); // Run to the edge, covering up the border
}
}
else
@@ -886,13 +887,13 @@ void LLTabContainer::addTabPanel(const TabPanelParams& panel)
}
else if( getTabPosition() == LLTabContainer::TOP )
{
- btn_rect.setLeftTopAndSize( 0, getRect().getHeight() - getTopBorderHeight() + tab_fudge, button_width, tabcntr_tab_height );
+ btn_rect.setLeftTopAndSize( 0, getRect().getHeight() - getTopBorderHeight() + tab_fudge, button_width, mTabHeight);
tab_img = mImageTopUnselected.get();
tab_selected_img = mImageTopSelected.get();
}
else
{
- btn_rect.setOriginAndSize( 0, 0 + tab_fudge, button_width, tabcntr_tab_height );
+ btn_rect.setOriginAndSize( 0, 0 + tab_fudge, button_width, mTabHeight);
tab_img = mImageBottomUnselected.get();
tab_selected_img = mImageBottomSelected.get();
}
diff --git a/indra/llui/lltabcontainer.h b/indra/llui/lltabcontainer.h
index 7bbecc1abc..e3af5384b1 100644
--- a/indra/llui/lltabcontainer.h
+++ b/indra/llui/lltabcontainer.h
@@ -67,7 +67,9 @@ public:
Optional<TabPosition, TabPositions> tab_position;
Optional<S32> tab_width,
tab_min_width,
- tab_max_width;
+ tab_max_width,
+ tab_height;
+
Optional<bool> hide_tabs;
Optional<S32> tab_padding_right;
@@ -246,6 +248,7 @@ private:
S32 mMaxTabWidth;
S32 mTotalTabWidth;
+ S32 mTabHeight;
LLFrameTimer mDragAndDropDelayTimer;
diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp
index 3dacf979c7..3c5213a0b3 100644
--- a/indra/llui/lltextbase.cpp
+++ b/indra/llui/lltextbase.cpp
@@ -124,17 +124,6 @@ struct LLTextBase::line_end_compare
//////////////////////////////////////////////////////////////////////////
//
-// LLTextBase::DocumentPanel
-//
-
-
-LLTextBase::DocumentPanel::DocumentPanel(const Params& p)
-: LLPanel(p)
-{}
-
-
-//////////////////////////////////////////////////////////////////////////
-//
// LLTextBase
//
@@ -157,8 +146,7 @@ LLTextBase::Params::Params()
bg_readonly_color("bg_readonly_color"),
bg_writeable_color("bg_writeable_color"),
bg_focus_color("bg_focus_color"),
- hide_scrollbar("hide_scrollbar"),
- clip_to_rect("clip_to_rect", true),
+ allow_scroll("allow_scroll", true),
track_end("track_end", false),
read_only("read_only", false),
v_pad("v_pad", 0),
@@ -205,35 +193,42 @@ LLTextBase::LLTextBase(const LLTextBase::Params &p)
mSelectionStart( 0 ),
mSelectionEnd( 0 ),
mIsSelecting( FALSE ),
- mClip(p.clip_to_rect),
mWordWrap(p.wrap),
mUseEllipses( p.use_ellipses ),
mParseHTML(p.allow_html),
mParseHighlights(p.parse_highlights),
- mHideScrollbar(p.hide_scrollbar)
-{
- LLScrollContainer::Params scroll_params;
- scroll_params.name = "text scroller";
- scroll_params.rect = getLocalRect();
- scroll_params.follows.flags = FOLLOWS_ALL;
- scroll_params.is_opaque = false;
- scroll_params.mouse_opaque = false;
- scroll_params.min_auto_scroll_rate = 200;
- scroll_params.max_auto_scroll_rate = 800;
- scroll_params.hide_scrollbar = p.hide_scrollbar;
- scroll_params.border_visible = p.border_visible;
- mScroller = LLUICtrlFactory::create<LLScrollContainer>(scroll_params);
- addChild(mScroller);
-
- LLPanel::Params panel_params;
- panel_params.name = "text_contents";
- panel_params.rect = LLRect(0, 500, 500, 0);
- panel_params.background_visible = p.bg_visible;
- panel_params.background_opaque = true;
- panel_params.mouse_opaque = false;
-
- mDocumentPanel = LLUICtrlFactory::create<DocumentPanel>(panel_params);
- mScroller->addChild(mDocumentPanel);
+ mBGVisible(p.bg_visible),
+ mScroller(NULL)
+{
+ if(p.allow_scroll)
+ {
+ LLScrollContainer::Params scroll_params;
+ scroll_params.name = "text scroller";
+ scroll_params.rect = getLocalRect();
+ scroll_params.follows.flags = FOLLOWS_ALL;
+ scroll_params.is_opaque = false;
+ scroll_params.mouse_opaque = false;
+ scroll_params.min_auto_scroll_rate = 200;
+ scroll_params.max_auto_scroll_rate = 800;
+ scroll_params.border_visible = p.border_visible;
+ mScroller = LLUICtrlFactory::create<LLScrollContainer>(scroll_params);
+ addChild(mScroller);
+ }
+
+ LLView::Params view_params;
+ view_params.name = "text_contents";
+ view_params.rect = LLRect(0, 500, 500, 0);
+ view_params.mouse_opaque = false;
+
+ mDocumentView = LLUICtrlFactory::create<LLView>(view_params);
+ if (mScroller)
+ {
+ mScroller->addChild(mDocumentView);
+ }
+ else
+ {
+ addChild(mDocumentView);
+ }
createDefaultSegment();
@@ -314,7 +309,7 @@ void LLTextBase::drawSelectionBackground()
LLRect selection_rect = mTextRect;
// Skip through the lines we aren't drawing.
- LLRect content_display_rect = mScroller->getVisibleContentRect();
+ LLRect content_display_rect = getVisibleDocumentRect();
// binary search for line that starts before top of visible buffer
line_list_t::const_iterator line_iter = std::lower_bound(mLineInfoList.begin(), mLineInfoList.end(), content_display_rect.mTop, compare_bottom());
@@ -418,6 +413,9 @@ void LLTextBase::drawCursor()
return;
}
+ if (!mTextRect.contains(cursor_rect))
+ return;
+
// Draw the cursor
// (Flash the cursor every half second starting a fixed time after the last keystroke)
F32 elapsed = mCursorBlinkTimer.getElapsedTimeF32();
@@ -496,8 +494,7 @@ void LLTextBase::drawText()
selection_right = llmax( mSelectionStart, mSelectionEnd );
}
- LLRect scrolled_view_rect = mScroller->getVisibleContentRect();
- LLRect content_rect = mScroller->getContentWindowRect();
+ LLRect scrolled_view_rect = getVisibleDocumentRect();
std::pair<S32, S32> line_range = getVisibleLines();
S32 first_line = line_range.first;
S32 last_line = line_range.second;
@@ -540,7 +537,7 @@ void LLTextBase::drawText()
LLRect text_rect(line.mRect.mLeft + mTextRect.mLeft - scrolled_view_rect.mLeft,
line.mRect.mTop - scrolled_view_rect.mBottom + mTextRect.mBottom,
- mDocumentPanel->getRect().getWidth() - scrolled_view_rect.mLeft,
+ mDocumentView->getRect().getWidth() - scrolled_view_rect.mLeft,
line.mRect.mBottom - scrolled_view_rect.mBottom + mTextRect.mBottom);
// draw a single line of text
@@ -645,6 +642,7 @@ S32 LLTextBase::insertStringNoUndo(S32 pos, const LLWString &wstr, LLTextBase::s
}
onValueChange(pos, pos + insert_len);
+ needsReflow();
return insert_len;
}
@@ -704,6 +702,7 @@ S32 LLTextBase::removeStringNoUndo(S32 pos, S32 length)
createDefaultSegment();
onValueChange(pos, pos);
+ needsReflow();
return -length; // This will be wrong if someone calls removeStringNoUndo with an excessive length
}
@@ -719,6 +718,7 @@ S32 LLTextBase::overwriteCharNoUndo(S32 pos, llwchar wc)
getViewModel()->setDisplay(text);
onValueChange(pos, pos + 1);
+ needsReflow();
return 1;
}
@@ -949,29 +949,31 @@ void LLTextBase::draw()
// then update scroll position, as cursor may have moved
updateScrollFromCursor();
- LLColor4 bg_color = mReadOnly
- ? mReadOnlyBgColor.get()
- : hasFocus()
- ? mFocusBgColor.get()
- : mWriteableBgColor.get();
+ if (mBGVisible)
+ {
+ // clip background rect against extents, if we support scrolling
+ LLLocalClipRect clip(getLocalRect(), mScroller != NULL);
- mDocumentPanel->setBackgroundColor(bg_color);
+ LLColor4 bg_color = mReadOnly
+ ? mReadOnlyBgColor.get()
+ : hasFocus()
+ ? mFocusBgColor.get()
+ : mWriteableBgColor.get();
+ gl_rect_2d(mDocumentView->getRect(), bg_color, TRUE);
+ }
+ // draw document view
LLUICtrl::draw();
+
{
- LLLocalClipRect clip(mTextRect, mClip);
+ // only clip if we support scrolling (mScroller != NULL)
+ LLLocalClipRect clip(mTextRect, mScroller != NULL);
drawSelectionBackground();
drawText();
drawCursor();
}
}
-//virtual
-void LLTextBase::clear()
-{
- getViewModel()->setDisplay(LLWStringUtil::null);
- clearSegments();
-}
//virtual
void LLTextBase::setColor( const LLColor4& c )
@@ -1000,14 +1002,14 @@ void LLTextBase::updateScrollFromCursor()
// Update scroll position even in read-only mode (when there's no cursor displayed)
// because startOfDoc()/endOfDoc() modify cursor position. See EXT-736.
- if (!mScrollNeeded)
+ if (!mScrollNeeded || !mScroller)
{
return;
}
mScrollNeeded = FALSE;
// scroll so that the cursor is at the top of the page
- LLRect scroller_doc_window = mScroller->getVisibleContentRect();
+ LLRect scroller_doc_window = getVisibleDocumentRect();
LLRect cursor_rect_doc = getLocalRectFromDocIndex(mCursorPos);
cursor_rect_doc.translate(scroller_doc_window.mLeft, scroller_doc_window.mBottom);
mScroller->scrollToShowRect(cursor_rect_doc, LLRect(0, scroller_doc_window.getHeight() - 5, scroller_doc_window.getWidth(), 5));
@@ -1042,7 +1044,7 @@ void LLTextBase::reflow(S32 start_index)
{
mReflowNeeded = FALSE;
- bool scrolled_to_bottom = mScroller->isAtBottom();
+ bool scrolled_to_bottom = mScroller ? mScroller->isAtBottom() : false;
LLRect old_cursor_rect = getLocalRectFromDocIndex(mCursorPos);
bool follow_selection = mTextRect.overlaps(old_cursor_rect); // cursor is visible
@@ -1104,12 +1106,17 @@ void LLTextBase::reflow(S32 start_index)
S32 segment_width = segment->getWidth(seg_offset, character_count);
remaining_pixels -= segment_width;
- S32 text_left = getLeftOffset(text_width - remaining_pixels);
seg_offset += character_count;
S32 last_segment_char_on_line = segment->getStart() + seg_offset;
+ S32 text_left = getLeftOffset(text_width - remaining_pixels);
+ LLRect line_rect(text_left,
+ cur_top,
+ text_left + (text_width - remaining_pixels),
+ cur_top - line_height);
+
// if we didn't finish the current segment...
if (last_segment_char_on_line < segment->getEnd())
{
@@ -1127,10 +1134,7 @@ void LLTextBase::reflow(S32 start_index)
mLineInfoList.push_back(line_info(
line_start_index,
last_segment_char_on_line,
- LLRect(text_left,
- cur_top,
- text_left + (text_width - remaining_pixels),
- cur_top - line_height),
+ line_rect,
line_count));
line_start_index = segment->getStart() + seg_offset;
@@ -1145,15 +1149,12 @@ void LLTextBase::reflow(S32 start_index)
mLineInfoList.push_back(line_info(
line_start_index,
last_segment_char_on_line,
- LLRect(text_left,
- cur_top,
- text_left + (text_width - remaining_pixels),
- cur_top - line_height),
+ line_rect,
line_count));
cur_top -= llround((F32)line_height * mLineSpacingMult) + mLineSpacingPixels;
break;
}
- // finished a segment and there are segments remaining on this line
+ // ...or finished a segment and there are segments remaining on this line
else
{
// subtract pixels used and increment segment
@@ -1183,17 +1184,29 @@ void LLTextBase::reflow(S32 start_index)
mContentsRect.stretch(1);
}
- // change mDocumentPanel document size to accomodate reflowed text
+ // change mDocumentView size to accomodate reflowed text
LLRect document_rect;
- document_rect.setOriginAndSize(1, 1,
- mScroller->getContentWindowRect().getWidth(),
- llmax(mScroller->getContentWindowRect().getHeight(), mContentsRect.getHeight()));
- mDocumentPanel->setShape(document_rect);
+ if (mScroller)
+ {
+ // document is size of scroller or size of text contents, whichever is larger
+ document_rect.setOriginAndSize(0, 0,
+ mScroller->getContentWindowRect().getWidth(),
+ llmax(mScroller->getContentWindowRect().getHeight(), mContentsRect.getHeight()));
+ }
+ else
+ {
+ // document size is just extents of reflowed text, reset to origin 0,0
+ document_rect.set(0,
+ getLocalRect().getHeight(),
+ getLocalRect().getWidth(),
+ llmin(0, getLocalRect().getHeight() - mContentsRect.getHeight()));
+ }
+ mDocumentView->setShape(document_rect);
// after making document big enough to hold all the text, move the text to fit in the document
if (!mLineInfoList.empty())
{
- S32 delta_pos = mDocumentPanel->getRect().getHeight() - mLineInfoList.begin()->mRect.mTop - mVPad;
+ S32 delta_pos = mDocumentView->getRect().getHeight() - mLineInfoList.begin()->mRect.mTop - mVPad;
// move line segments to fit new document rect
for (line_list_t::iterator it = mLineInfoList.begin(); it != mLineInfoList.end(); ++it)
{
@@ -1215,9 +1228,9 @@ void LLTextBase::reflow(S32 start_index)
}
// apply scroll constraints after reflowing text
- if (!hasMouseCapture())
+ if (!hasMouseCapture() && mScroller)
{
- LLRect visible_content_rect = mScroller->getVisibleContentRect();
+ LLRect visible_content_rect = getVisibleDocumentRect();
if (scrolled_to_bottom && mTrackEnd)
{
// keep bottom of text buffer visible
@@ -1329,7 +1342,7 @@ S32 LLTextBase::getLineOffsetFromDocIndex( S32 startpos, bool include_wordwrap)
S32 LLTextBase::getFirstVisibleLine() const
{
- LLRect visible_region = mScroller->getVisibleContentRect();
+ LLRect visible_region = getVisibleDocumentRect();
// binary search for line that starts before top of visible buffer
line_list_t::const_iterator iter = std::lower_bound(mLineInfoList.begin(), mLineInfoList.end(), visible_region.mTop, compare_bottom());
@@ -1339,7 +1352,7 @@ S32 LLTextBase::getFirstVisibleLine() const
std::pair<S32, S32> LLTextBase::getVisibleLines(bool fully_visible)
{
- LLRect visible_region = mScroller->getVisibleContentRect();
+ LLRect visible_region = getVisibleDocumentRect();
line_list_t::const_iterator first_iter;
line_list_t::const_iterator last_iter;
@@ -1370,12 +1383,12 @@ LLTextViewModel* LLTextBase::getViewModel() const
void LLTextBase::addDocumentChild(LLView* view)
{
- mDocumentPanel->addChild(view);
+ mDocumentView->addChild(view);
}
void LLTextBase::removeDocumentChild(LLView* view)
{
- mDocumentPanel->removeChild(view);
+ mDocumentView->removeChild(view);
}
@@ -1481,11 +1494,10 @@ void LLTextBase::createUrlContextMenu(S32 x, S32 y, const std::string &in_url)
void LLTextBase::setText(const LLStringExplicit &utf8str)
{
// clear out the existing text and segments
- clear();
-
- truncate();
+ getViewModel()->setDisplay(LLWStringUtil::null);
- createDefaultSegment();
+ clearSegments();
+// createDefaultSegment();
startOfDoc();
deselect();
@@ -1496,10 +1508,9 @@ void LLTextBase::setText(const LLStringExplicit &utf8str)
appendText(text, false);
- needsReflow();
-
//resetDirty();
onValueChange(0, getLength());
+ needsReflow();
}
//virtual
@@ -1767,7 +1778,7 @@ LLWString LLTextBase::getWText() const
S32 LLTextBase::getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round ) const
{
// Figure out which line we're nearest to.
- LLRect visible_region = mScroller->getVisibleContentRect();
+ LLRect visible_region = getVisibleDocumentRect();
// binary search for line that starts before local_y
line_list_t::const_iterator line_iter = std::lower_bound(mLineInfoList.begin(), mLineInfoList.end(), local_y - mTextRect.mBottom + visible_region.mBottom, compare_bottom());
@@ -1838,7 +1849,7 @@ LLRect LLTextBase::getLocalRectFromDocIndex(S32 pos) const
// find line that contains cursor
line_list_t::const_iterator line_iter = std::upper_bound(mLineInfoList.begin(), mLineInfoList.end(), pos, line_end_compare());
- LLRect scrolled_view_rect = mScroller->getVisibleContentRect();
+ LLRect scrolled_view_rect = getVisibleDocumentRect();
local_rect.mLeft = mTextRect.mLeft - scrolled_view_rect.mLeft + line_iter->mRect.mLeft;
local_rect.mBottom = mTextRect.mBottom + (line_iter->mRect.mBottom - scrolled_view_rect.mBottom);
local_rect.mTop = mTextRect.mBottom + (line_iter->mRect.mTop - scrolled_view_rect.mBottom);
@@ -1917,7 +1928,7 @@ void LLTextBase::endOfDoc()
void LLTextBase::changePage( S32 delta )
{
const S32 PIXEL_OVERLAP_ON_PAGE_CHANGE = 10;
- if (delta == 0) return;
+ if (delta == 0 || !mScroller) return;
LLRect cursor_rect = getLocalRectFromDocIndex(mCursorPos);
@@ -1970,7 +1981,7 @@ void LLTextBase::changeLine( S32 delta )
new_line = line + 1;
}
- LLRect visible_region = mScroller->getVisibleContentRect();
+ LLRect visible_region = getVisibleDocumentRect();
S32 new_cursor_pos = getDocIndexFromLocalCoord(mDesiredXPixel, mLineInfoList[new_line].mRect.mBottom + mTextRect.mBottom - visible_region.mBottom, TRUE);
setCursorPos(new_cursor_pos, true);
@@ -2047,7 +2058,7 @@ S32 LLTextBase::getEditableIndex(S32 index, bool increasing_direction)
void LLTextBase::updateTextRect()
{
LLRect old_text_rect = mTextRect;
- mTextRect = mScroller->getContentWindowRect();
+ mTextRect = mScroller ? mScroller->getContentWindowRect() : getLocalRect();
//FIXME: replace border with image?
if (mBorderVisible)
{
@@ -2081,6 +2092,22 @@ void LLTextBase::endSelection()
}
}
+// get portion of document that is visible in text editor
+LLRect LLTextBase::getVisibleDocumentRect() const
+{
+ if (mScroller)
+ {
+ return mScroller->getVisibleContentRect();
+ }
+ else
+ {
+ // entire document rect when not scrolling
+ LLRect doc_rect = mDocumentView->getLocalRect();
+ doc_rect.translate(-mDocumentView->getRect().mLeft, -mDocumentView->getRect().mBottom);
+ return doc_rect;
+ }
+}
+
//
// LLTextSegment
//
@@ -2150,6 +2177,7 @@ F32 LLNormalTextSegment::draw(S32 start, S32 end, S32 selection_start, S32 selec
{
if ( mStyle->isImage() && (start >= 0) && (end <= mEnd - mStart))
{
+ LLColor4 color = LLColor4::white % mEditor.getDrawContext().mAlpha;
LLUIImagePtr image = mStyle->getImage();
S32 style_image_height = image->getHeight();
S32 style_image_width = image->getWidth();
@@ -2398,7 +2426,7 @@ S32 LLInlineViewSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 lin
void LLInlineViewSegment::updateLayout(const LLTextBase& editor)
{
LLRect start_rect = editor.getLocalRectFromDocIndex(mStart);
- LLRect doc_rect = editor.getDocumentPanel()->getRect();
+ LLRect doc_rect = editor.getDocumentView()->getRect();
mView->setOrigin(doc_rect.mLeft + start_rect.mLeft, doc_rect.mBottom + start_rect.mBottom);
}
diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h
index f20134fd6d..903396c78a 100644
--- a/indra/llui/lltextbase.h
+++ b/indra/llui/lltextbase.h
@@ -80,8 +80,7 @@ public:
border_visible,
track_end,
read_only,
- hide_scrollbar,
- clip_to_rect,
+ allow_scroll,
wrap,
use_ellipses,
allow_html,
@@ -118,7 +117,6 @@ public:
// LLUICtrl interface
/*virtual*/ BOOL acceptsTextInput() const { return !mReadOnly; }
- /*virtual*/ void clear();
/*virtual*/ void setColor( const LLColor4& c );
/*virtual*/ void setValue(const LLSD& value );
/*virtual*/ LLTextViewModel* getViewModel() const;
@@ -149,16 +147,13 @@ public:
S32 getLength() const { return getWText().length(); }
S32 getLineCount() const { return mLineInfoList.size(); }
- class DocumentPanel : public LLPanel
- {
- public:
- DocumentPanel(const Params&);
- };
void addDocumentChild(LLView* view);
void removeDocumentChild(LLView* view);
- const DocumentPanel* getDocumentPanel() const { return mDocumentPanel; }
+ const LLView* getDocumentView() const { return mDocumentView; }
LLRect getTextRect() { return mTextRect; }
LLRect getContentsRect();
+ LLRect getVisibleDocumentRect() const;
+
S32 getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round ) const;
LLRect getLocalRectFromDocIndex(S32 pos) const;
@@ -344,13 +339,12 @@ protected:
bool mUseEllipses;
bool mTrackEnd; // if true, keeps scroll position at end of document during resize
bool mReadOnly;
- bool mClip;
- bool mHideScrollbar;
+ bool mBGVisible; // render background?
S32 mMaxTextByteLength; // Maximum length mText is allowed to be in bytes
// support widgets
LLContextMenu* mPopupMenu;
- DocumentPanel* mDocumentPanel;
+ LLView* mDocumentView;
class LLScrollContainer* mScroller;
// transient state
diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp
index 997c5b8fa8..74ffad0f53 100644
--- a/indra/llui/lltexteditor.cpp
+++ b/indra/llui/lltexteditor.cpp
@@ -990,7 +990,7 @@ void LLTextEditor::removeChar()
// Add a single character to the text
S32 LLTextEditor::addChar(S32 pos, llwchar wc)
{
- if ( (wstring_utf8_length( getWText() ) + wchar_utf8_length( wc )) >= mMaxTextByteLength)
+ if ( (wstring_utf8_length( getWText() ) + wchar_utf8_length( wc )) > mMaxTextByteLength)
{
make_ui_sound("UISndBadKeystroke");
return 0;
@@ -2916,3 +2916,10 @@ void LLTextEditor::onKeyStroke()
{
mKeystrokeSignal(this);
}
+
+//virtual
+void LLTextEditor::clear()
+{
+ getViewModel()->setDisplay(LLWStringUtil::null);
+ clearSegments();
+}
diff --git a/indra/llui/lltexteditor.h b/indra/llui/lltexteditor.h
index 0e5707a3a6..e232efbfb3 100644
--- a/indra/llui/lltexteditor.h
+++ b/indra/llui/lltexteditor.h
@@ -116,6 +116,7 @@ public:
virtual void setEnabled(BOOL enabled);
// uictrl overrides
+ virtual void clear();
virtual void setFocus( BOOL b );
virtual BOOL isDirty() const;
diff --git a/indra/llui/lltooltip.cpp b/indra/llui/lltooltip.cpp
index c55273cacf..f30e56b907 100644
--- a/indra/llui/lltooltip.cpp
+++ b/indra/llui/lltooltip.cpp
@@ -147,6 +147,7 @@ static LLDefaultChildRegistry::Register<LLToolTip> r("tool_tip");
LLToolTip::Params::Params()
: max_width("max_width", 200),
padding("padding", 4),
+ wrap("wrap", true),
pos("pos"),
message("message"),
delay_time("delay_time", LLUI::sSettingGroups["config"]->getF32( "ToolTipDelay" )),
@@ -181,6 +182,7 @@ LLToolTip::LLToolTip(const LLToolTip::Params& p)
params.bg_visible = false;
params.font = p.font;
params.use_ellipses = true;
+ params.wrap = p.wrap;
mTextBox = LLUICtrlFactory::create<LLTextBox> (params);
addChild(mTextBox);
diff --git a/indra/llui/lltooltip.h b/indra/llui/lltooltip.h
index 6715da1611..63e7249a12 100644
--- a/indra/llui/lltooltip.h
+++ b/indra/llui/lltooltip.h
@@ -83,6 +83,7 @@ public:
Optional<LLUIImage*> image;
Optional<S32> max_width;
Optional<S32> padding;
+ Optional<bool> wrap;
Params();
};
diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp
index eb1b60244d..da9384f876 100644
--- a/indra/llui/llui.cpp
+++ b/indra/llui/llui.cpp
@@ -1556,6 +1556,9 @@ void LLUI::initClass(const settings_map_t& settings,
// Button initialization callback for toggle buttons
LLUICtrl::CommitCallbackRegistry::defaultRegistrar().add("Button.SetFloaterToggle", boost::bind(&LLButton::setFloaterToggle, _1, _2));
+ // Button initialization callback for toggle buttons on dockale floaters
+ LLUICtrl::CommitCallbackRegistry::defaultRegistrar().add("Button.SetDockableFloaterToggle", boost::bind(&LLButton::setDockableFloaterToggle, _1, _2));
+
// Display the help topic for the current context
LLUICtrl::CommitCallbackRegistry::defaultRegistrar().add("Button.ShowHelp", boost::bind(&LLButton::showHelp, _1, _2));
@@ -1915,16 +1918,11 @@ namespace LLInitParam
declare("blue", LLColor4::blue);
}
- template<>
- class ParamCompare<const LLFontGL*>
+ bool ParamCompare<const LLFontGL*, false>::equals(const LLFontGL* a, const LLFontGL* b)
{
- public:
- static bool equals(const LLFontGL* a, const LLFontGL* b)
- {
- return !(a->getFontDesc() < b->getFontDesc())
- && !(b->getFontDesc() < a->getFontDesc());
- }
- };
+ return !(a->getFontDesc() < b->getFontDesc())
+ && !(b->getFontDesc() < a->getFontDesc());
+ }
TypedParam<const LLFontGL*>::TypedParam(BlockDescriptor& descriptor, const char* _name, const LLFontGL*const value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count)
: super_t(descriptor, _name, value, func, min_count, max_count),
diff --git a/indra/llui/llui.h b/indra/llui/llui.h
index f071e8dc47..6ab78ab3cd 100644
--- a/indra/llui/llui.h
+++ b/indra/llui/llui.h
@@ -437,6 +437,13 @@ namespace LLInitParam
};
template<>
+ struct ParamCompare<const LLFontGL*, false>
+ {
+ static bool equals(const LLFontGL* a, const LLFontGL* b);
+ };
+
+
+ template<>
class TypedParam<LLCoordGL>
: public BlockValue<LLCoordGL>
{
diff --git a/indra/llui/lluictrl.cpp b/indra/llui/lluictrl.cpp
index 5b72f87a78..0faff5eff6 100644
--- a/indra/llui/lluictrl.cpp
+++ b/indra/llui/lluictrl.cpp
@@ -795,16 +795,29 @@ bool LLUICtrl::findHelpTopic(std::string& help_topic_out)
LLUICtrl* ctrl = this;
// search back through the control's parents for a panel
- // with a help_topic string defined
+ // or tab with a help_topic string defined
while (ctrl)
{
LLPanel *panel = dynamic_cast<LLPanel *>(ctrl);
- if (panel && !panel->getHelpTopic().empty())
+
+ if (panel)
{
- help_topic_out = panel->getHelpTopic();
- return true; // success
+ // does the panel have an active tab with a help topic?
+ LLPanel *tab = panel->childGetVisibleTabWithHelp();
+ if (tab)
+ {
+ help_topic_out = tab->getHelpTopic();
+ return true; // success (tab)
+ }
+
+ // otherwise, does the panel have a help topic itself?
+ if (!panel->getHelpTopic().empty())
+ {
+ help_topic_out = panel->getHelpTopic();
+ return true; // success (panel)
+ }
}
-
+
ctrl = ctrl->getParentUICtrl();
}
@@ -836,24 +849,3 @@ BOOL LLUICtrl::getTentative() const
// virtual
void LLUICtrl::setColor(const LLColor4& color)
{ }
-
-
-namespace LLInitParam
-{
- template<>
- bool ParamCompare<LLUICtrl::commit_callback_t>::equals(
- const LLUICtrl::commit_callback_t &a,
- const LLUICtrl::commit_callback_t &b)
- {
- return false;
- }
-
-
- template<>
- bool ParamCompare<LLUICtrl::enable_callback_t>::equals(
- const LLUICtrl::enable_callback_t &a,
- const LLUICtrl::enable_callback_t &b)
- {
- return false;
- }
-}
diff --git a/indra/llui/lluictrl.h b/indra/llui/lluictrl.h
index 69207eb8ea..45fe47772b 100644
--- a/indra/llui/lluictrl.h
+++ b/indra/llui/lluictrl.h
@@ -228,7 +228,11 @@ public:
// Default to no-op:
virtual void onTabInto();
+
+ // Clear any user-provided input (text in a text editor, checked checkbox,
+ // selected radio button, etc.). Defaults to no-op.
virtual void clear();
+
virtual void setColor(const LLColor4& color);
BOOL focusNextItem(BOOL text_entry_only);
@@ -323,21 +327,4 @@ private:
class DefaultTabGroupFirstSorter;
};
-namespace LLInitParam
-{
- template<>
- bool ParamCompare<LLUICtrl::commit_callback_t>::equals(
- const LLUICtrl::commit_callback_t &a,
- const LLUICtrl::commit_callback_t &b);
-
- template<>
- bool ParamCompare<LLUICtrl::enable_callback_t>::equals(
- const LLUICtrl::enable_callback_t &a,
- const LLUICtrl::enable_callback_t &b);
-
- template<>
- bool ParamCompare<LLLazyValue<LLColor4> >::equals(
- const LLLazyValue<LLColor4> &a, const LLLazyValue<LLColor4> &b);
-}
-
#endif // LL_LLUICTRL_H
diff --git a/indra/llui/lluictrlfactory.cpp b/indra/llui/lluictrlfactory.cpp
index 4ce6677294..209ee76940 100644
--- a/indra/llui/lluictrlfactory.cpp
+++ b/indra/llui/lluictrlfactory.cpp
@@ -170,7 +170,7 @@ static LLFastTimer::DeclareTimer FTM_BUILD_FLOATERS("Build Floaters");
//-----------------------------------------------------------------------------
// buildFloater()
//-----------------------------------------------------------------------------
-void LLUICtrlFactory::buildFloater(LLFloater* floaterp, const std::string& filename, LLXMLNodePtr output_node)
+bool LLUICtrlFactory::buildFloater(LLFloater* floaterp, const std::string& filename, LLXMLNodePtr output_node)
{
LLFastTimer timer(FTM_BUILD_FLOATERS);
LLXMLNodePtr root;
@@ -182,22 +182,24 @@ void LLUICtrlFactory::buildFloater(LLFloater* floaterp, const std::string& filen
if (!LLUICtrlFactory::getLocalizedXMLNode(filename, root))
{
llwarns << "Couldn't parse floater from: " << LLUI::getLocalizedSkinPath() + gDirUtilp->getDirDelimiter() + filename << llendl;
- return;
+ return false;
}
}
else if (!LLUICtrlFactory::getLayeredXMLNode(filename, root))
{
llwarns << "Couldn't parse floater from: " << LLUI::getSkinPath() + gDirUtilp->getDirDelimiter() + filename << llendl;
- return;
+ return false;
}
// root must be called floater
if( !(root->hasName("floater") || root->hasName("multi_floater")) )
{
llwarns << "Root node should be named floater in: " << filename << llendl;
- return;
+ return false;
}
-
+
+ bool res = true;
+
lldebugs << "Building floater " << filename << llendl;
mFileNames.push_back(gDirUtilp->findSkinnedFilename(LLUI::getSkinPath(), filename));
{
@@ -210,7 +212,7 @@ void LLUICtrlFactory::buildFloater(LLFloater* floaterp, const std::string& filen
floaterp->getCommitCallbackRegistrar().pushScope();
floaterp->getEnableCallbackRegistrar().pushScope();
- floaterp->initFloaterXML(root, floaterp->getParent(), output_node);
+ res = floaterp->initFloaterXML(root, floaterp->getParent(), output_node);
floaterp->setXMLFilename(filename);
@@ -223,6 +225,8 @@ void LLUICtrlFactory::buildFloater(LLFloater* floaterp, const std::string& filen
}
}
mFileNames.pop_back();
+
+ return res;
}
//-----------------------------------------------------------------------------
diff --git a/indra/llui/lluictrlfactory.h b/indra/llui/lluictrlfactory.h
index 3c77c655b8..5e6dad312c 100644
--- a/indra/llui/lluictrlfactory.h
+++ b/indra/llui/lluictrlfactory.h
@@ -157,7 +157,7 @@ public:
return ParamDefaults<typename T::Params, 0>::instance().get();
}
- void buildFloater(LLFloater* floaterp, const std::string &filename, LLXMLNodePtr output_node);
+ bool buildFloater(LLFloater* floaterp, const std::string &filename, LLXMLNodePtr output_node);
BOOL buildPanel(LLPanel* panelp, const std::string &filename, LLXMLNodePtr output_node = NULL);
// Does what you want for LLFloaters and LLPanels
diff --git a/indra/llui/lluiimage.cpp b/indra/llui/lluiimage.cpp
index ab0d65e731..6c1a32722f 100644
--- a/indra/llui/lluiimage.cpp
+++ b/indra/llui/lluiimage.cpp
@@ -152,8 +152,7 @@ namespace LLInitParam
}
- template<>
- bool ParamCompare<LLUIImage*>::equals(
+ bool ParamCompare<LLUIImage*, false>::equals(
LLUIImage* const &a,
LLUIImage* const &b)
{
diff --git a/indra/llui/lluiimage.h b/indra/llui/lluiimage.h
index 4ec24e98dc..9d734bcfdf 100644
--- a/indra/llui/lluiimage.h
+++ b/indra/llui/lluiimage.h
@@ -108,8 +108,10 @@ namespace LLInitParam
// Need custom comparison function for our test app, which only loads
// LLUIImage* as NULL.
template<>
- bool ParamCompare<LLUIImage*>::equals(
- LLUIImage* const &a, LLUIImage* const &b);
+ struct ParamCompare<LLUIImage*, false>
+ {
+ static bool equals(LLUIImage* const &a, LLUIImage* const &b);
+ };
}
typedef LLPointer<LLUIImage> LLUIImagePtr;
diff --git a/indra/llui/lluistring.h b/indra/llui/lluistring.h
index aedeca27cb..195f21a6a7 100644
--- a/indra/llui/lluistring.h
+++ b/indra/llui/lluistring.h
@@ -51,9 +51,9 @@
// llinfos << mMessage.getString() << llendl; // outputs "Welcome Steve to Second Life"
// mMessage.setArg("[USERNAME]", "Joe");
// llinfos << mMessage.getString() << llendl; // outputs "Welcome Joe to Second Life"
-// mMessage = "Recepci￳n a la [SECONDLIFE] [USERNAME]"
+// mMessage = "Bienvenido a la [SECONDLIFE] [USERNAME]"
// mMessage.setArg("[SECONDLIFE]", "Segunda Vida");
-// llinfos << mMessage.getString() << llendl; // outputs "Recepci￳n a la Segunda Vida Joe"
+// llinfos << mMessage.getString() << llendl; // outputs "Bienvenido a la Segunda Vida Joe"
// Implementation Notes:
// Attempting to have operator[](const std::string& s) return mArgs[s] fails because we have
diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp
index 1df8838738..7db6eab9ad 100644
--- a/indra/llui/llview.cpp
+++ b/indra/llui/llview.cpp
@@ -57,14 +57,13 @@
#include "lltexteditor.h"
#include "lltextbox.h"
-BOOL LLView::sDebugRects = FALSE;
-BOOL LLView::sDebugKeys = FALSE;
S32 LLView::sDepth = 0;
-BOOL LLView::sDebugMouseHandling = FALSE;
+bool LLView::sDebugRects = false;
+bool LLView::sDebugRectsShowNames = true;
+bool LLView::sDebugKeys = false;
+bool LLView::sDebugMouseHandling = false;
std::string LLView::sMouseHandlerMessage;
-//BOOL LLView::sEditingUI = FALSE;
BOOL LLView::sForceReshape = FALSE;
-//LLView* LLView::sEditingUIView = NULL;
std::set<LLView*> LLView::sPreviewHighlightedElements;
BOOL LLView::sHighlightingDiffs = FALSE;
LLView* LLView::sPreviewClickedElement = NULL;
@@ -1353,7 +1352,7 @@ void LLView::drawDebugRect()
LLRect debug_rect = mUseBoundingRect ? mBoundingRect : mRect;
// draw red rectangle for the border
- LLColor4 border_color(0.f, 0.f, 0.f, 1.f);
+ LLColor4 border_color(0.25f, 0.25f, 0.25f, 1.f);
if(preview_iter != sPreviewHighlightedElements.end())
{
if(LLView::sPreviewClickedElement && this == sPreviewClickedElement)
@@ -1388,7 +1387,9 @@ void LLView::drawDebugRect()
gGL.end();
// Draw the name if it's not a leaf node or not in editing or preview mode
- if (mChildList.size() && preview_iter == sPreviewHighlightedElements.end())
+ if (mChildList.size()
+ && preview_iter == sPreviewHighlightedElements.end()
+ && sDebugRectsShowNames)
{
//char temp[256];
S32 x, y;
diff --git a/indra/llui/llview.h b/indra/llui/llview.h
index 7ddff2bd9e..5e35068733 100644
--- a/indra/llui/llview.h
+++ b/indra/llui/llview.h
@@ -586,14 +586,20 @@ private:
default_widget_map_t& getDefaultWidgetMap() const;
public:
- static BOOL sDebugRects; // Draw debug rects behind everything.
- static BOOL sDebugKeys;
+ // Depth in view hierarchy during rendering
static S32 sDepth;
- static BOOL sDebugMouseHandling;
+
+ // Draw debug rectangles around widgets to help with alignment and spacing
+ static bool sDebugRects;
+
+ // Draw widget names and sizes when drawing debug rectangles, turning this
+ // off is useful to make the rectangles themselves easier to see.
+ static bool sDebugRectsShowNames;
+
+ static bool sDebugKeys;
+ static bool sDebugMouseHandling;
static std::string sMouseHandlerMessage;
static S32 sSelectID;
-// static BOOL sEditingUI;
-// static LLView* sEditingUIView;
static std::set<LLView*> sPreviewHighlightedElements; // DEV-16869
static BOOL sHighlightingDiffs; // DEV-16869
static LLView* sPreviewClickedElement; // DEV-16869