summaryrefslogtreecommitdiff
path: root/indra/llui
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llui')
-rw-r--r--indra/llui/llcheckboxctrl.cpp2
-rw-r--r--indra/llui/llcombobox.cpp32
-rw-r--r--indra/llui/llscrolllistctrl.cpp115
-rw-r--r--indra/llui/llscrolllistctrl.h14
-rw-r--r--indra/llui/llsliderctrl.cpp2
-rw-r--r--indra/llui/llspinctrl.cpp24
6 files changed, 125 insertions, 64 deletions
diff --git a/indra/llui/llcheckboxctrl.cpp b/indra/llui/llcheckboxctrl.cpp
index fde27132e6..215f6d40ed 100644
--- a/indra/llui/llcheckboxctrl.cpp
+++ b/indra/llui/llcheckboxctrl.cpp
@@ -156,7 +156,7 @@ void LLCheckBoxCtrl::onCommit()
void LLCheckBoxCtrl::setEnabled(BOOL b)
{
- LLUICtrl::setEnabled(b);
+ LLView::setEnabled(b);
mButton->setEnabled(b);
}
diff --git a/indra/llui/llcombobox.cpp b/indra/llui/llcombobox.cpp
index f13e0d54b9..f548045474 100644
--- a/indra/llui/llcombobox.cpp
+++ b/indra/llui/llcombobox.cpp
@@ -102,7 +102,7 @@ LLComboBox::LLComboBox( const LLString& name, const LLRect &rect, const LLString
LLUUID arrow_image_id( LLUI::sAssetsGroup->getString("combobox_arrow.tga") );
mArrowImage = LLUI::sImageProvider->getUIImageByID(arrow_image_id);
- mArrowImageWidth = llmax(8,mArrowImage->getWidth()); // In case image hasn't loaded yet
+ mArrowImageWidth = llmax(8,mArrowImage->getWidth(0)); // In case image hasn't loaded yet
}
@@ -202,7 +202,7 @@ LLView* LLComboBox::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *
void LLComboBox::setEnabled(BOOL enabled)
{
- LLUICtrl::setEnabled(enabled);
+ LLView::setEnabled(enabled);
mButton->setEnabled(enabled);
}
@@ -477,14 +477,15 @@ void LLComboBox::showList()
mList->arrange( 192, llfloor((F32)window_size.mY / LLUI::sGLScaleFactor.mV[VY]) - 50 );
// Make sure that we can see the whole list
- LLRect floater_area_local;
- gFloaterView->localRectToOtherView(gFloaterView->getLocalSnapRect(), &floater_area_local, this);
+ LLRect root_view_local;
+ LLView* root_view = getRootView();
+ root_view->localRectToOtherView(root_view->getLocalRect(), &root_view_local, this);
LLRect rect = mList->getRect();
if (mListPosition == BELOW)
{
- if (rect.getHeight() <= -floater_area_local.mBottom)
+ if (rect.getHeight() <= -root_view_local.mBottom)
{
// Move rect so it hangs off the bottom of this view
rect.setLeftTopAndSize(0, 0, rect.getWidth(), rect.getHeight() );
@@ -492,44 +493,44 @@ void LLComboBox::showList()
else
{
// stack on top or bottom, depending on which has more room
- if (-floater_area_local.mBottom > floater_area_local.mTop - mRect.getHeight())
+ if (-root_view_local.mBottom > root_view_local.mTop - mRect.getHeight())
{
// Move rect so it hangs off the bottom of this view
- rect.setLeftTopAndSize(0, 0, rect.getWidth(), llmin(-floater_area_local.mBottom, rect.getHeight()));
+ rect.setLeftTopAndSize(0, 0, rect.getWidth(), llmin(-root_view_local.mBottom, rect.getHeight()));
}
else
{
// move rect so it stacks on top of this view (clipped to size of screen)
- rect.setOriginAndSize(0, mRect.getHeight(), rect.getWidth(), llmin(floater_area_local.mTop - mRect.getHeight(), rect.getHeight()));
+ rect.setOriginAndSize(0, mRect.getHeight(), rect.getWidth(), llmin(root_view_local.mTop - mRect.getHeight(), rect.getHeight()));
}
}
}
else // ABOVE
{
- if (rect.getHeight() <= floater_area_local.mTop - mRect.getHeight())
+ if (rect.getHeight() <= root_view_local.mTop - mRect.getHeight())
{
// move rect so it stacks on top of this view (clipped to size of screen)
- rect.setOriginAndSize(0, mRect.getHeight(), rect.getWidth(), llmin(floater_area_local.mTop - mRect.getHeight(), rect.getHeight()));
+ rect.setOriginAndSize(0, mRect.getHeight(), rect.getWidth(), llmin(root_view_local.mTop - mRect.getHeight(), rect.getHeight()));
}
else
{
// stack on top or bottom, depending on which has more room
- if (-floater_area_local.mBottom > floater_area_local.mTop - mRect.getHeight())
+ if (-root_view_local.mBottom > root_view_local.mTop - mRect.getHeight())
{
// Move rect so it hangs off the bottom of this view
- rect.setLeftTopAndSize(0, 0, rect.getWidth(), llmin(-floater_area_local.mBottom, rect.getHeight()));
+ rect.setLeftTopAndSize(0, 0, rect.getWidth(), llmin(-root_view_local.mBottom, rect.getHeight()));
}
else
{
// move rect so it stacks on top of this view (clipped to size of screen)
- rect.setOriginAndSize(0, mRect.getHeight(), rect.getWidth(), llmin(floater_area_local.mTop - mRect.getHeight(), rect.getHeight()));
+ rect.setOriginAndSize(0, mRect.getHeight(), rect.getWidth(), llmin(root_view_local.mTop - mRect.getHeight(), rect.getHeight()));
}
}
}
mList->setOrigin(rect.mLeft, rect.mBottom);
mList->reshape(rect.getWidth(), rect.getHeight());
- mList->translateIntoRect(floater_area_local, FALSE);
+ mList->translateIntoRect(root_view_local, FALSE);
// Make sure we didn't go off bottom of screen
S32 x, y;
@@ -656,7 +657,8 @@ void LLComboBox::onItemSelected(LLUICtrl* item, void *userdata)
void LLComboBox::onListFocusChanged(LLUICtrl* list, void* user_data)
{
LLComboBox *self = (LLComboBox *) list->getParent();
- if (!list->hasFocus())
+ // user not manipulating list or clicking on drop down button
+ if (!self->mList->hasFocus() && !self->mButton->hasMouseCapture())
{
//*HACK: store the original value explicitly somewhere, not just in label
LLString orig_selection = self->mAllowTextEntry ? self->mTextEntry->getText() : self->mButton->getLabelSelected();
diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp
index f442855aca..146052538a 100644
--- a/indra/llui/llscrolllistctrl.cpp
+++ b/indra/llui/llscrolllistctrl.cpp
@@ -405,6 +405,7 @@ LLScrollListCtrl::LLScrollListCtrl(const LLString& name, const LLRect& rect,
mNumDynamicWidthColumns(0),
mTotalStaticColumnWidth(0),
mSortColumn(-1),
+ mSorted(TRUE),
mSortAscending(TRUE)
{
mItemListRect.setOriginAndSize(
@@ -623,22 +624,28 @@ BOOL LLScrollListCtrl::addItem( LLScrollListItem* item, EAddPosition pos )
{
case ADD_TOP:
mItemList.push_front(item);
+ setSorted(FALSE);
break;
case ADD_SORTED:
- mSortColumn = 0;
- mSortAscending = TRUE;
+ if (mSortColumn == -1)
+ {
+ mSortColumn = 0;
+ mSortAscending = TRUE;
+ }
mItemList.push_back(item);
std::sort(mItemList.begin(), mItemList.end(), SortScrollListItem(mSortColumn, mSortAscending));
break;
case ADD_BOTTOM:
mItemList.push_back(item);
+ setSorted(FALSE);
break;
default:
llassert(0);
mItemList.push_back(item);
+ setSorted(FALSE);
break;
}
@@ -1094,7 +1101,7 @@ void LLScrollListCtrl::selectNextItem( BOOL extend_selection)
}
}
- if ((mCommitOnSelectionChange || mCommitOnKeyboardMovement))
+ if (mCommitOnKeyboardMovement)
{
onCommit();
}
@@ -1685,8 +1692,7 @@ BOOL LLScrollListCtrl::handleMouseUp(S32 x, S32 y, MASK mask)
}
// always commit when mouse operation is completed inside list
- // this only needs to be done for lists that don't commit on selection change
- if (!mCommitOnSelectionChange && pointInView(x,y))
+ if (mItemListRect.pointInRect(x,y))
{
mSelectionChanged = FALSE;
onCommit();
@@ -2090,6 +2096,16 @@ void LLScrollListCtrl::commitIfChanged()
}
}
+void LLScrollListCtrl::setSorted(BOOL sorted)
+{
+ mSorted = sorted;
+}
+
+BOOL LLScrollListCtrl::isSorted()
+{
+ return mSorted;
+}
+
// Called by scrollbar
//static
void LLScrollListCtrl::onScrollChange( S32 new_pos, LLScrollbar* scrollbar, void* userdata )
@@ -2102,10 +2118,11 @@ void LLScrollListCtrl::onScrollChange( S32 new_pos, LLScrollbar* scrollbar, void
// First column is column 0
void LLScrollListCtrl::sortByColumn(U32 column, BOOL ascending)
{
- if (mSortColumn != column)
+ if (!mSorted || mSortColumn != column)
{
mSortColumn = column;
std::sort(mItemList.begin(), mItemList.end(), SortScrollListItem(mSortColumn, mSortAscending));
+ setSorted(TRUE);
}
// just reverse the list if changing sort order
@@ -2358,6 +2375,9 @@ LLView* LLScrollListCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFac
LLString sortname(columnname);
child->getAttributeString("sort", sortname);
+
+ BOOL sort_ascending = TRUE;
+ child->getAttributeBOOL("sort_ascending", sort_ascending);
LLString imagename;
child->getAttributeString("image", imagename);
@@ -2379,6 +2399,7 @@ LLView* LLScrollListCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFac
columns[index]["name"] = columnname;
columns[index]["sort"] = sortname;
+ columns[index]["sort_ascending"] = sort_ascending;
columns[index]["image"] = imagename;
columns[index]["label"] = labelname;
columns[index]["width"] = columnwidth;
@@ -2543,6 +2564,13 @@ void LLScrollListCtrl::addColumn(const LLSD& column, EAddPosition pos)
{
mDefaultColumn = 0;
}
+ // if no column name provided, just use ordinal as name
+ if (name.empty())
+ {
+ std::ostringstream new_name;
+ new_name << mColumnsIndexed.size();
+ name = new_name.str();
+ }
if (mColumns.find(name) == mColumns.end())
{
// Add column
@@ -2621,6 +2649,7 @@ void LLScrollListCtrl::onClickColumn(void *userdata)
U32 column_index = info->mIndex;
LLScrollListColumn* column = parent->mColumnsIndexed[info->mIndex];
+ bool ascending = column->mSortAscending;
if (column->mSortingColumn != column->mName)
{
if (parent->mColumns.find(column->mSortingColumn) != parent->mColumns.end())
@@ -2630,7 +2659,6 @@ void LLScrollListCtrl::onClickColumn(void *userdata)
}
}
- bool ascending = true;
if (column_index == parent->mSortColumn)
{
ascending = !parent->mSortAscending;
@@ -2715,6 +2743,7 @@ LLScrollListItem* LLScrollListCtrl::addElement(const LLSD& value, EAddPosition p
// Add any columns we don't already have
LLSD columns = value["columns"];
LLSD::array_const_iterator itor;
+ S32 col_index = 0 ;
for (itor = columns.beginArray(); itor != columns.endArray(); ++itor)
{
LLString column = (*itor)["column"].asString();
@@ -2723,21 +2752,39 @@ LLScrollListItem* LLScrollListCtrl::addElement(const LLSD& value, EAddPosition p
{
mDefaultColumn = 0;
}
- std::map<LLString, LLScrollListColumn>::iterator column_itor = mColumns.find(column);
- if (column_itor == mColumns.end())
+
+ LLScrollListColumn* columnp = NULL;
+
+ // empty columns strings index by ordinal
+ if (column.empty())
+ {
+ std::ostringstream new_name;
+ new_name << col_index;
+ column = new_name.str();
+ }
+
+ std::map<LLString, LLScrollListColumn>::iterator column_itor;
+ column_itor = mColumns.find(column);
+ if (column_itor != mColumns.end())
+ {
+ columnp = &column_itor->second;
+ }
+
+ // create new column on demand
+ if (!columnp)
{
LLSD new_column;
new_column["name"] = column;
new_column["label"] = column;
- new_column["width"] = 0;
+ new_column["width"] = (*itor)["width"];
addColumn(new_column);
- column_itor = mColumns.find(column);
+ columnp = &mColumns.find(column)->second;
new_item->setNumColumns(mColumns.size());
}
- S32 index = column_itor->second.mIndex;
- S32 width = column_itor->second.mWidth;
- LLFontGL::HAlign font_alignment = column_itor->second.mFontAlignment;
+ S32 index = columnp->mIndex;
+ S32 width = columnp->mWidth;
+ LLFontGL::HAlign font_alignment = columnp->mFontAlignment;
LLSD value = (*itor)["value"];
LLString fontname = (*itor)["font"].asString();
@@ -2770,11 +2817,13 @@ LLScrollListItem* LLScrollListCtrl::addElement(const LLSD& value, EAddPosition p
else
{
new_item->setColumn(index, new LLScrollListText(value.asString(), font, width, font_style, font_alignment));
- if (column_itor->second.mHeader && !value.asString().empty())
+ if (columnp->mHeader && !value.asString().empty())
{
- column_itor->second.mHeader->setHasResizableElement(TRUE);
+ columnp->mHeader->setHasResizableElement(TRUE);
}
}
+
+ col_index++;
}
S32 num_columns = mColumns.size();
@@ -2917,32 +2966,6 @@ LLColumnHeader::LLColumnHeader(const LLString& label, const LLRect &rect, LLScro
mAscendingText = "[LOW]...[HIGH](Ascending)";
mDescendingText = "[HIGH]...[LOW](Descending)";
- LLSD row;
- row["columns"][0]["column"] = "label";
- row["columns"][0]["value"] = mAscendingText.getString();
- row["columns"][0]["font"] = "SANSSERIF_SMALL";
- row["columns"][0]["width"] = 80;
-
- row["columns"][1]["column"] = "arrow";
- row["columns"][1]["type"] = "icon";
- row["columns"][1]["value"] = LLUI::sAssetsGroup->getString("up_arrow.tga");
- row["columns"][1]["width"] = 20;
-
- mList->addElement(row);
-
- row["columns"][0]["column"] = "label";
- row["columns"][0]["type"] = "text";
- row["columns"][0]["value"] = mDescendingText.getString();
- row["columns"][0]["font"] = "SANSSERIF_SMALL";
- row["columns"][0]["width"] = 80;
-
- row["columns"][1]["column"] = "arrow";
- row["columns"][1]["type"] = "icon";
- row["columns"][1]["value"] = LLUI::sAssetsGroup->getString("down_arrow.tga");
- row["columns"][1]["width"] = 20;
-
- mList->addElement(row);
-
mList->reshape(llmax(mList->getRect().getWidth(), 110, mRect.getWidth()), mList->getRect().getHeight());
// resize handles on left and right
@@ -2964,7 +2987,7 @@ void LLColumnHeader::draw()
{
if( getVisible() )
{
- mDrawArrow = !mColumn->mLabel.empty() && mColumn->mParentCtrl->getSortColumnName() == mColumn->mSortingColumn;
+ mDrawArrow = !mColumn->mLabel.empty() && mColumn->mParentCtrl->isSorted() && mColumn->mParentCtrl->getSortColumnName() == mColumn->mSortingColumn;
BOOL is_ascending = mColumn->mParentCtrl->getSortAscending();
mArrowImage = is_ascending ? LLUI::sImageProvider->getUIImageByID(LLUUID(LLUI::sAssetsGroup->getString("up_arrow.tga")))
@@ -3311,7 +3334,11 @@ void LLColumnHeader::setHasResizableElement(BOOL resizable)
void LLColumnHeader::enableResizeBar(BOOL enable)
{
- mResizeBar->setEnabled(enable);
+ // for now, dynamically spaced columns can't be resized
+ if (!mColumn->mDynamicWidth)
+ {
+ mResizeBar->setEnabled(enable);
+ }
}
BOOL LLColumnHeader::canResize()
diff --git a/indra/llui/llscrolllistctrl.h b/indra/llui/llscrolllistctrl.h
index 7a0a32c87e..de9b58bd1e 100644
--- a/indra/llui/llscrolllistctrl.h
+++ b/indra/llui/llscrolllistctrl.h
@@ -142,6 +142,7 @@ public:
LLScrollListColumn() :
mName(""),
mSortingColumn(""),
+ mSortAscending(TRUE),
mLabel(""),
mWidth(-1),
mRelWidth(-1.0),
@@ -156,6 +157,7 @@ public:
LLScrollListColumn(LLString name, LLString label, S32 width, F32 relwidth) :
mName(name),
mSortingColumn(name),
+ mSortAscending(TRUE),
mLabel(label),
mWidth(width),
mRelWidth(relwidth),
@@ -176,6 +178,11 @@ public:
{
mSortingColumn = sd.get("sort").asString();
}
+ mSortAscending = TRUE;
+ if (sd.has("sort_ascending"))
+ {
+ mSortAscending = sd.get("sort_ascending").asBoolean();
+ }
mLabel = sd.get("label").asString();
if (sd.has("relwidth") && (F32)sd.get("relwidth").asReal() > 0)
{
@@ -210,6 +217,7 @@ public:
LLString mName;
LLString mSortingColumn;
+ BOOL mSortAscending;
LLString mLabel;
S32 mWidth;
F32 mRelWidth;
@@ -381,8 +389,10 @@ public:
// Returns FALSE if not found.
BOOL setSelectedByValue(LLSD value, BOOL selected);
- virtual BOOL isSelected(LLSD value);
+ BOOL isSorted();
+ virtual BOOL isSelected(LLSD value);
+
BOOL selectFirstItem();
BOOL selectNthItem( S32 index );
BOOL selectItemAt(S32 x, S32 y, MASK mask);
@@ -552,6 +562,7 @@ protected:
void selectItem(LLScrollListItem* itemp, BOOL single_select = TRUE);
void deselectItem(LLScrollListItem* itemp);
void commitIfChanged();
+ void setSorted(BOOL sorted);
protected:
S32 mCurIndex; // For get[First/Next]Data
@@ -615,6 +626,7 @@ protected:
S32 mSortColumn;
BOOL mSortAscending;
+ BOOL mSorted;
std::map<LLString, LLScrollListColumn> mColumns;
std::vector<LLScrollListColumn*> mColumnsIndexed;
diff --git a/indra/llui/llsliderctrl.cpp b/indra/llui/llsliderctrl.cpp
index b3c49e81f1..8b5cd4690e 100644
--- a/indra/llui/llsliderctrl.cpp
+++ b/indra/llui/llsliderctrl.cpp
@@ -300,7 +300,7 @@ void LLSliderCtrl::onSliderCommit( LLUICtrl* caller, void *userdata )
void LLSliderCtrl::setEnabled(BOOL b)
{
- LLUICtrl::setEnabled( b );
+ LLView::setEnabled( b );
if( mLabelBox )
{
diff --git a/indra/llui/llspinctrl.cpp b/indra/llui/llspinctrl.cpp
index fbd8335e6c..34363eb506 100644
--- a/indra/llui/llspinctrl.cpp
+++ b/indra/llui/llspinctrl.cpp
@@ -123,6 +123,23 @@ LLSpinCtrl::~LLSpinCtrl()
}
+F32 clamp_precision(F32 value, S32 decimal_precision)
+{
+ // pow() isn't perfect
+
+ F64 clamped_value = value;
+ for (S32 i = 0; i < decimal_precision; i++)
+ clamped_value *= 10.0;
+
+ clamped_value = llround((F32)clamped_value);
+
+ for (S32 i = 0; i < decimal_precision; i++)
+ clamped_value /= 10.0;
+
+ return (F32)clamped_value;
+}
+
+
// static
void LLSpinCtrl::onUpBtn( void *userdata )
{
@@ -131,6 +148,7 @@ void LLSpinCtrl::onUpBtn( void *userdata )
{
// use getValue()/setValue() to force reload from/to control
F32 val = (F32)self->getValue().asReal() + self->mIncrement;
+ val = clamp_precision(val, self->mPrecision);
val = llmin( val, self->mMaxValue );
if( self->mValidateCallback )
@@ -163,6 +181,7 @@ void LLSpinCtrl::onDownBtn( void *userdata )
if( self->getEnabled() )
{
F32 val = (F32)self->getValue().asReal() - self->mIncrement;
+ val = clamp_precision(val, self->mPrecision);
val = llmax( val, self->mMinValue );
if( self->mValidateCallback )
@@ -224,12 +243,13 @@ void LLSpinCtrl::clear()
}
+
void LLSpinCtrl::updateEditor()
{
LLLocale locale(LLLocale::USER_LOCALE);
// Don't display very small negative values as -0.000
- F32 displayed_value = (F32)floor(getValue().asReal() * pow(10.0, (F64)mPrecision) + 0.5) / (F32)pow(10.0, (F64)mPrecision);
+ F32 displayed_value = clamp_precision((F32)getValue().asReal(), mPrecision);
// if( S32( displayed_value * pow( 10, mPrecision ) ) == 0 )
// {
@@ -301,7 +321,7 @@ void LLSpinCtrl::setFocus(BOOL b)
void LLSpinCtrl::setEnabled(BOOL b)
{
- LLUICtrl::setEnabled( b );
+ LLView::setEnabled( b );
mEditor->setEnabled( b );
}