diff options
Diffstat (limited to 'indra/llui/llscrolllistcolumn.cpp')
-rw-r--r-- | indra/llui/llscrolllistcolumn.cpp | 680 |
1 files changed, 340 insertions, 340 deletions
diff --git a/indra/llui/llscrolllistcolumn.cpp b/indra/llui/llscrolllistcolumn.cpp index a935ea2f11..c6be401676 100644 --- a/indra/llui/llscrolllistcolumn.cpp +++ b/indra/llui/llscrolllistcolumn.cpp @@ -1,340 +1,340 @@ -/** - * @file llscrollcolumnheader.cpp - * @brief Scroll lists are composed of rows (items), each of which - * contains columns (cells). - * - * $LicenseInfo:firstyear=2007&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$ - */ - -#include "linden_common.h" - -#include "llscrolllistcolumn.h" - -#include "llbutton.h" -#include "llresizebar.h" -#include "llscrolllistcell.h" -#include "llscrolllistctrl.h" -#include "llscrolllistitem.h" -#include "lluictrlfactory.h" - -const S32 MIN_COLUMN_WIDTH = 20; - -// defaults for LLScrollColumnHeader param block pulled from widgets/scroll_column_header.xml -static LLWidgetNameRegistry::StaticRegistrar sRegisterColumnHeaderParams(&typeid(LLScrollColumnHeader::Params), "scroll_column_header"); - -//--------------------------------------------------------------------------- -// LLScrollColumnHeader -//--------------------------------------------------------------------------- -LLScrollColumnHeader::Params::Params() -: column("column") -{} - - -LLScrollColumnHeader::LLScrollColumnHeader(const LLScrollColumnHeader::Params& p) -: LLButton(p), // use combobox params to steal images - mColumn(p.column), - mHasResizableElement(false) -{ - setClickedCallback(boost::bind(&LLScrollColumnHeader::onClick, this, _2)); - - // resize handles on left and right - const S32 RESIZE_BAR_THICKNESS = 3; - LLResizeBar::Params resize_bar_p; - resize_bar_p.resizing_view(this); - resize_bar_p.rect(LLRect(getRect().getWidth() - RESIZE_BAR_THICKNESS, getRect().getHeight(), getRect().getWidth(), 0)); - resize_bar_p.min_size(MIN_COLUMN_WIDTH); - resize_bar_p.side(LLResizeBar::RIGHT); - resize_bar_p.enabled(false); - mResizeBar = LLUICtrlFactory::create<LLResizeBar>(resize_bar_p); - addChild(mResizeBar); -} - -LLScrollColumnHeader::~LLScrollColumnHeader() -{} - -void LLScrollColumnHeader::draw() -{ - std::string sort_column = mColumn->mParentCtrl->getSortColumnName(); - bool draw_arrow = !mColumn->mLabel.empty() - && mColumn->mParentCtrl->isSorted() - // check for indirect sorting column as well as column's sorting name - && (sort_column == mColumn->mSortingColumn || sort_column == mColumn->mName); - - bool is_ascending = mColumn->mParentCtrl->getSortAscending(); - if (draw_arrow) - { - setImageOverlay(is_ascending ? "up_arrow.tga" : "down_arrow.tga", LLFontGL::RIGHT, LLColor4::white); - } - else - { - setImageOverlay(LLUUID::null); - } - - // Draw children - LLButton::draw(); -} - -bool LLScrollColumnHeader::handleDoubleClick(S32 x, S32 y, MASK mask) -{ - if (canResize() && mResizeBar->getRect().pointInRect(x, y)) - { - // reshape column to max content width - mColumn->mParentCtrl->calcMaxContentWidth(); - LLRect column_rect = getRect(); - column_rect.mRight = column_rect.mLeft + mColumn->mMaxContentWidth; - setShape(column_rect, true); - } - else - { - onClick(LLSD()); - } - return true; -} - -void LLScrollColumnHeader::onClick(const LLSD& data) -{ - if (mColumn) - { - LLScrollListCtrl::onClickColumn(mColumn); - } -} - -LLView* LLScrollColumnHeader::findSnapEdge(S32& new_edge_val, const LLCoordGL& mouse_dir, ESnapEdge snap_edge, ESnapType snap_type, S32 threshold, S32 padding) -{ - // this logic assumes dragging on right - llassert(snap_edge == SNAP_RIGHT); - - // use higher snap threshold for column headers - threshold = llmin(threshold, 10); - - LLRect snap_rect = getSnapRect(); - - mColumn->mParentCtrl->calcMaxContentWidth(); - - S32 snap_delta = mColumn->mMaxContentWidth - snap_rect.getWidth(); - - // x coord growing means column growing, so same signs mean we're going in right direction - if (llabs(snap_delta) <= threshold && mouse_dir.mX * snap_delta > 0 ) - { - new_edge_val = snap_rect.mRight + snap_delta; - } - else - { - LLScrollListColumn* next_column = mColumn->mParentCtrl->getColumn(mColumn->mIndex + 1); - while (next_column) - { - if (next_column->mHeader) - { - snap_delta = (next_column->mHeader->getSnapRect().mRight - next_column->mMaxContentWidth) - snap_rect.mRight; - if (llabs(snap_delta) <= threshold && mouse_dir.mX * snap_delta > 0 ) - { - new_edge_val = snap_rect.mRight + snap_delta; - } - break; - } - next_column = mColumn->mParentCtrl->getColumn(next_column->mIndex + 1); - } - } - - return this; -} - -void LLScrollColumnHeader::handleReshape(const LLRect& new_rect, bool by_user) -{ - S32 new_width = new_rect.getWidth(); - S32 delta_width = new_width - (getRect().getWidth() /*+ mColumn->mParentCtrl->getColumnPadding()*/); - - if (delta_width != 0) - { - S32 remaining_width = -delta_width; - S32 col; - for (col = mColumn->mIndex + 1; col < mColumn->mParentCtrl->getNumColumns(); col++) - { - LLScrollListColumn* columnp = mColumn->mParentCtrl->getColumn(col); - if (!columnp) continue; - - if (columnp->mHeader && columnp->mHeader->canResize()) - { - // how many pixels in width can this column afford to give up? - S32 resize_buffer_amt = llmax(0, columnp->getWidth() - MIN_COLUMN_WIDTH); - - // user shrinking column, need to add width to other columns - if (delta_width < 0) - { - if (columnp->getWidth() > 0) - { - // statically sized column, give all remaining width to this column - columnp->setWidth(columnp->getWidth() + remaining_width); - if (columnp->mRelWidth > 0.f) - { - columnp->mRelWidth = (F32)columnp->getWidth() / (F32)mColumn->mParentCtrl->getItemListRect().getWidth(); - } - // all padding went to this widget, we're done - break; - } - } - else - { - // user growing column, need to take width from other columns - remaining_width += resize_buffer_amt; - - if (columnp->getWidth() > 0) - { - columnp->setWidth(columnp->getWidth() - llmin(columnp->getWidth() - MIN_COLUMN_WIDTH, delta_width)); - if (columnp->mRelWidth > 0.f) - { - columnp->mRelWidth = (F32)columnp->getWidth() / (F32)mColumn->mParentCtrl->getItemListRect().getWidth(); - } - } - - if (remaining_width >= 0) - { - // width sucked up from neighboring columns, done - break; - } - } - } - } - - // clamp resize amount to maximum that can be absorbed by other columns - if (delta_width > 0) - { - delta_width += llmin(remaining_width, 0); - } - - // propagate constrained delta_width to new width for this column - new_width = getRect().getWidth() + delta_width - mColumn->mParentCtrl->getColumnPadding(); - - // use requested width - mColumn->setWidth(new_width); - - // update proportional spacing - if (mColumn->mRelWidth > 0.f) - { - mColumn->mRelWidth = (F32)new_width / (F32)mColumn->mParentCtrl->getItemListRect().getWidth(); - } - - // tell scroll list to layout columns again - // do immediate update to get proper feedback to resize handle - // which needs to know how far the resize actually went - const bool force_update = true; - mColumn->mParentCtrl->updateColumns(force_update); - } -} - -void LLScrollColumnHeader::setHasResizableElement(bool resizable) -{ - if (mHasResizableElement != resizable) - { - mColumn->mParentCtrl->dirtyColumns(); - mHasResizableElement = resizable; - } -} - -void LLScrollColumnHeader::updateResizeBars() -{ - S32 num_resizable_columns = 0; - S32 col; - for (col = 0; col < mColumn->mParentCtrl->getNumColumns(); col++) - { - LLScrollListColumn* columnp = mColumn->mParentCtrl->getColumn(col); - if (columnp && columnp->mHeader && columnp->mHeader->canResize()) - { - num_resizable_columns++; - } - } - - S32 num_resizers_enabled = 0; - - // now enable/disable resize handles on resizable columns if we have at least two - for (col = 0; col < mColumn->mParentCtrl->getNumColumns(); col++) - { - LLScrollListColumn* columnp = mColumn->mParentCtrl->getColumn(col); - if (!columnp || !columnp->mHeader) continue; - bool enable = num_resizable_columns >= 2 && num_resizers_enabled < (num_resizable_columns - 1) && columnp->mHeader->canResize(); - columnp->mHeader->enableResizeBar(enable); - if (enable) - { - num_resizers_enabled++; - } - } -} - -void LLScrollColumnHeader::enableResizeBar(bool enable) -{ - mResizeBar->setEnabled(enable); -} - -bool LLScrollColumnHeader::canResize() -{ - return getVisible() && (mHasResizableElement || mColumn->mDynamicWidth); -} - -void LLScrollListColumn::SortNames::declareValues() -{ - declare("ascending", LLScrollListColumn::ASCENDING); - declare("descending", LLScrollListColumn::DESCENDING); -} - -// -// LLScrollListColumn -// -//static -const LLScrollListColumn::Params& LLScrollListColumn::getDefaultParams() -{ - return LLUICtrlFactory::getDefaultParams<LLScrollListColumn>(); -} - - -LLScrollListColumn::LLScrollListColumn(const Params& p, LLScrollListCtrl* parent) -: mWidth(0), - mIndex (-1), - mParentCtrl(parent), - mName(p.name), - mLabel(p.header.label), - mHeader(NULL), - mMaxContentWidth(0), - mDynamicWidth(p.width.dynamic_width), - mRelWidth(p.width.relative_width), - mFontAlignment(p.halign), - mSortingColumn(p.sort_column) -{ - if (p.sort_ascending.isProvided()) - { - mSortDirection = p.sort_ascending() ? ASCENDING : DESCENDING; - } - else - { - mSortDirection = p.sort_direction; - } - - setWidth(p.width.pixel_width); -} - -void LLScrollListColumn::setWidth(S32 width) -{ - if (!mDynamicWidth && mRelWidth <= 0.f) - { - mParentCtrl->updateStaticColumnWidth(this, width); - } - mWidth = width; -} +/**
+ * @file llscrollcolumnheader.cpp
+ * @brief Scroll lists are composed of rows (items), each of which
+ * contains columns (cells).
+ *
+ * $LicenseInfo:firstyear=2007&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$
+ */
+
+#include "linden_common.h"
+
+#include "llscrolllistcolumn.h"
+
+#include "llbutton.h"
+#include "llresizebar.h"
+#include "llscrolllistcell.h"
+#include "llscrolllistctrl.h"
+#include "llscrolllistitem.h"
+#include "lluictrlfactory.h"
+
+const S32 MIN_COLUMN_WIDTH = 20;
+
+// defaults for LLScrollColumnHeader param block pulled from widgets/scroll_column_header.xml
+static LLWidgetNameRegistry::StaticRegistrar sRegisterColumnHeaderParams(&typeid(LLScrollColumnHeader::Params), "scroll_column_header");
+
+//---------------------------------------------------------------------------
+// LLScrollColumnHeader
+//---------------------------------------------------------------------------
+LLScrollColumnHeader::Params::Params()
+: column("column")
+{}
+
+
+LLScrollColumnHeader::LLScrollColumnHeader(const LLScrollColumnHeader::Params& p)
+: LLButton(p), // use combobox params to steal images
+ mColumn(p.column),
+ mHasResizableElement(false)
+{
+ setClickedCallback(boost::bind(&LLScrollColumnHeader::onClick, this, _2));
+
+ // resize handles on left and right
+ const S32 RESIZE_BAR_THICKNESS = 3;
+ LLResizeBar::Params resize_bar_p;
+ resize_bar_p.resizing_view(this);
+ resize_bar_p.rect(LLRect(getRect().getWidth() - RESIZE_BAR_THICKNESS, getRect().getHeight(), getRect().getWidth(), 0));
+ resize_bar_p.min_size(MIN_COLUMN_WIDTH);
+ resize_bar_p.side(LLResizeBar::RIGHT);
+ resize_bar_p.enabled(false);
+ mResizeBar = LLUICtrlFactory::create<LLResizeBar>(resize_bar_p);
+ addChild(mResizeBar);
+}
+
+LLScrollColumnHeader::~LLScrollColumnHeader()
+{}
+
+void LLScrollColumnHeader::draw()
+{
+ std::string sort_column = mColumn->mParentCtrl->getSortColumnName();
+ bool draw_arrow = !mColumn->mLabel.empty()
+ && mColumn->mParentCtrl->isSorted()
+ // check for indirect sorting column as well as column's sorting name
+ && (sort_column == mColumn->mSortingColumn || sort_column == mColumn->mName);
+
+ bool is_ascending = mColumn->mParentCtrl->getSortAscending();
+ if (draw_arrow)
+ {
+ setImageOverlay(is_ascending ? "up_arrow.tga" : "down_arrow.tga", LLFontGL::RIGHT, LLColor4::white);
+ }
+ else
+ {
+ setImageOverlay(LLUUID::null);
+ }
+
+ // Draw children
+ LLButton::draw();
+}
+
+bool LLScrollColumnHeader::handleDoubleClick(S32 x, S32 y, MASK mask)
+{
+ if (canResize() && mResizeBar->getRect().pointInRect(x, y))
+ {
+ // reshape column to max content width
+ mColumn->mParentCtrl->calcMaxContentWidth();
+ LLRect column_rect = getRect();
+ column_rect.mRight = column_rect.mLeft + mColumn->mMaxContentWidth;
+ setShape(column_rect, true);
+ }
+ else
+ {
+ onClick(LLSD());
+ }
+ return true;
+}
+
+void LLScrollColumnHeader::onClick(const LLSD& data)
+{
+ if (mColumn)
+ {
+ LLScrollListCtrl::onClickColumn(mColumn);
+ }
+}
+
+LLView* LLScrollColumnHeader::findSnapEdge(S32& new_edge_val, const LLCoordGL& mouse_dir, ESnapEdge snap_edge, ESnapType snap_type, S32 threshold, S32 padding)
+{
+ // this logic assumes dragging on right
+ llassert(snap_edge == SNAP_RIGHT);
+
+ // use higher snap threshold for column headers
+ threshold = llmin(threshold, 10);
+
+ LLRect snap_rect = getSnapRect();
+
+ mColumn->mParentCtrl->calcMaxContentWidth();
+
+ S32 snap_delta = mColumn->mMaxContentWidth - snap_rect.getWidth();
+
+ // x coord growing means column growing, so same signs mean we're going in right direction
+ if (llabs(snap_delta) <= threshold && mouse_dir.mX * snap_delta > 0 )
+ {
+ new_edge_val = snap_rect.mRight + snap_delta;
+ }
+ else
+ {
+ LLScrollListColumn* next_column = mColumn->mParentCtrl->getColumn(mColumn->mIndex + 1);
+ while (next_column)
+ {
+ if (next_column->mHeader)
+ {
+ snap_delta = (next_column->mHeader->getSnapRect().mRight - next_column->mMaxContentWidth) - snap_rect.mRight;
+ if (llabs(snap_delta) <= threshold && mouse_dir.mX * snap_delta > 0 )
+ {
+ new_edge_val = snap_rect.mRight + snap_delta;
+ }
+ break;
+ }
+ next_column = mColumn->mParentCtrl->getColumn(next_column->mIndex + 1);
+ }
+ }
+
+ return this;
+}
+
+void LLScrollColumnHeader::handleReshape(const LLRect& new_rect, bool by_user)
+{
+ S32 new_width = new_rect.getWidth();
+ S32 delta_width = new_width - (getRect().getWidth() /*+ mColumn->mParentCtrl->getColumnPadding()*/);
+
+ if (delta_width != 0)
+ {
+ S32 remaining_width = -delta_width;
+ S32 col;
+ for (col = mColumn->mIndex + 1; col < mColumn->mParentCtrl->getNumColumns(); col++)
+ {
+ LLScrollListColumn* columnp = mColumn->mParentCtrl->getColumn(col);
+ if (!columnp) continue;
+
+ if (columnp->mHeader && columnp->mHeader->canResize())
+ {
+ // how many pixels in width can this column afford to give up?
+ S32 resize_buffer_amt = llmax(0, columnp->getWidth() - MIN_COLUMN_WIDTH);
+
+ // user shrinking column, need to add width to other columns
+ if (delta_width < 0)
+ {
+ if (columnp->getWidth() > 0)
+ {
+ // statically sized column, give all remaining width to this column
+ columnp->setWidth(columnp->getWidth() + remaining_width);
+ if (columnp->mRelWidth > 0.f)
+ {
+ columnp->mRelWidth = (F32)columnp->getWidth() / (F32)mColumn->mParentCtrl->getItemListRect().getWidth();
+ }
+ // all padding went to this widget, we're done
+ break;
+ }
+ }
+ else
+ {
+ // user growing column, need to take width from other columns
+ remaining_width += resize_buffer_amt;
+
+ if (columnp->getWidth() > 0)
+ {
+ columnp->setWidth(columnp->getWidth() - llmin(columnp->getWidth() - MIN_COLUMN_WIDTH, delta_width));
+ if (columnp->mRelWidth > 0.f)
+ {
+ columnp->mRelWidth = (F32)columnp->getWidth() / (F32)mColumn->mParentCtrl->getItemListRect().getWidth();
+ }
+ }
+
+ if (remaining_width >= 0)
+ {
+ // width sucked up from neighboring columns, done
+ break;
+ }
+ }
+ }
+ }
+
+ // clamp resize amount to maximum that can be absorbed by other columns
+ if (delta_width > 0)
+ {
+ delta_width += llmin(remaining_width, 0);
+ }
+
+ // propagate constrained delta_width to new width for this column
+ new_width = getRect().getWidth() + delta_width - mColumn->mParentCtrl->getColumnPadding();
+
+ // use requested width
+ mColumn->setWidth(new_width);
+
+ // update proportional spacing
+ if (mColumn->mRelWidth > 0.f)
+ {
+ mColumn->mRelWidth = (F32)new_width / (F32)mColumn->mParentCtrl->getItemListRect().getWidth();
+ }
+
+ // tell scroll list to layout columns again
+ // do immediate update to get proper feedback to resize handle
+ // which needs to know how far the resize actually went
+ const bool force_update = true;
+ mColumn->mParentCtrl->updateColumns(force_update);
+ }
+}
+
+void LLScrollColumnHeader::setHasResizableElement(bool resizable)
+{
+ if (mHasResizableElement != resizable)
+ {
+ mColumn->mParentCtrl->dirtyColumns();
+ mHasResizableElement = resizable;
+ }
+}
+
+void LLScrollColumnHeader::updateResizeBars()
+{
+ S32 num_resizable_columns = 0;
+ S32 col;
+ for (col = 0; col < mColumn->mParentCtrl->getNumColumns(); col++)
+ {
+ LLScrollListColumn* columnp = mColumn->mParentCtrl->getColumn(col);
+ if (columnp && columnp->mHeader && columnp->mHeader->canResize())
+ {
+ num_resizable_columns++;
+ }
+ }
+
+ S32 num_resizers_enabled = 0;
+
+ // now enable/disable resize handles on resizable columns if we have at least two
+ for (col = 0; col < mColumn->mParentCtrl->getNumColumns(); col++)
+ {
+ LLScrollListColumn* columnp = mColumn->mParentCtrl->getColumn(col);
+ if (!columnp || !columnp->mHeader) continue;
+ bool enable = num_resizable_columns >= 2 && num_resizers_enabled < (num_resizable_columns - 1) && columnp->mHeader->canResize();
+ columnp->mHeader->enableResizeBar(enable);
+ if (enable)
+ {
+ num_resizers_enabled++;
+ }
+ }
+}
+
+void LLScrollColumnHeader::enableResizeBar(bool enable)
+{
+ mResizeBar->setEnabled(enable);
+}
+
+bool LLScrollColumnHeader::canResize()
+{
+ return getVisible() && (mHasResizableElement || mColumn->mDynamicWidth);
+}
+
+void LLScrollListColumn::SortNames::declareValues()
+{
+ declare("ascending", LLScrollListColumn::ASCENDING);
+ declare("descending", LLScrollListColumn::DESCENDING);
+}
+
+//
+// LLScrollListColumn
+//
+//static
+const LLScrollListColumn::Params& LLScrollListColumn::getDefaultParams()
+{
+ return LLUICtrlFactory::getDefaultParams<LLScrollListColumn>();
+}
+
+
+LLScrollListColumn::LLScrollListColumn(const Params& p, LLScrollListCtrl* parent)
+: mWidth(0),
+ mIndex (-1),
+ mParentCtrl(parent),
+ mName(p.name),
+ mLabel(p.header.label),
+ mHeader(NULL),
+ mMaxContentWidth(0),
+ mDynamicWidth(p.width.dynamic_width),
+ mRelWidth(p.width.relative_width),
+ mFontAlignment(p.halign),
+ mSortingColumn(p.sort_column)
+{
+ if (p.sort_ascending.isProvided())
+ {
+ mSortDirection = p.sort_ascending() ? ASCENDING : DESCENDING;
+ }
+ else
+ {
+ mSortDirection = p.sort_direction;
+ }
+
+ setWidth(p.width.pixel_width);
+}
+
+void LLScrollListColumn::setWidth(S32 width)
+{
+ if (!mDynamicWidth && mRelWidth <= 0.f)
+ {
+ mParentCtrl->updateStaticColumnWidth(this, width);
+ }
+ mWidth = width;
+}
|