diff options
author | James Cook <james@lindenlab.com> | 2007-01-02 08:33:20 +0000 |
---|---|---|
committer | James Cook <james@lindenlab.com> | 2007-01-02 08:33:20 +0000 |
commit | 420b91db29485df39fd6e724e782c449158811cb (patch) | |
tree | b471a94563af914d3ed3edd3e856d21cb1b69945 /indra/llui/lluictrl.cpp |
Print done when done.
Diffstat (limited to 'indra/llui/lluictrl.cpp')
-rw-r--r-- | indra/llui/lluictrl.cpp | 341 |
1 files changed, 341 insertions, 0 deletions
diff --git a/indra/llui/lluictrl.cpp b/indra/llui/lluictrl.cpp new file mode 100644 index 0000000000..0d9791c660 --- /dev/null +++ b/indra/llui/lluictrl.cpp @@ -0,0 +1,341 @@ +/** + * @file lluictrl.cpp + * @author James Cook, Richard Nelson, Tom Yedwab + * @brief Abstract base class for UI controls + * + * Copyright (c) 2001-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +//#include "llviewerprecompiledheaders.h" +#include "linden_common.h" + +#include "lluictrl.h" + +#include "llgl.h" +#include "llui.h" +#include "lluiconstants.h" +#include "llfocusmgr.h" +#include "v3color.h" + +#include "llstring.h" +#include "llfontgl.h" +#include "llkeyboard.h" + +const U32 MAX_STRING_LENGTH = 10; + +LLUICtrl::LLUICtrl() : + mCommitCallback(NULL), + mFocusReceivedCallback(NULL), + mFocusChangedCallback(NULL), + mValidateCallback(NULL), + mCallbackUserData(NULL), + mTentative(FALSE), + mTabStop(TRUE), + mIsChrome(FALSE) +{ +} + +LLUICtrl::LLUICtrl(const LLString& name, const LLRect& rect, BOOL mouse_opaque, + void (*on_commit_callback)(LLUICtrl*, void*), + void* callback_userdata, + U32 reshape) +: // can't make this automatically follow top and left, breaks lots + // of buttons in the UI. JC 7/20/2002 + LLView( name, rect, mouse_opaque, reshape ), + mCommitCallback( on_commit_callback) , + mFocusReceivedCallback( NULL ), + mFocusChangedCallback( NULL ), + mValidateCallback( NULL ), + mCallbackUserData( callback_userdata ), + mTentative( FALSE ), + mTabStop( TRUE ), + mIsChrome(FALSE) +{ +} + +LLUICtrl::~LLUICtrl() +{ + gFocusMgr.releaseFocusIfNeeded( this ); // calls onCommit() +} + +void LLUICtrl::onCommit() +{ + if( mCommitCallback ) + { + mCommitCallback( this, mCallbackUserData ); + } +} + +// virtual +BOOL LLUICtrl::setTextArg( const LLString& key, const LLString& text ) +{ + return FALSE; +} + +// virtual +BOOL LLUICtrl::setLabelArg( const LLString& key, const LLString& text ) +{ + return FALSE; +} + +// virtual +LLCtrlSelectionInterface* LLUICtrl::getSelectionInterface() +{ + return NULL; +} + +// virtual +LLCtrlListInterface* LLUICtrl::getListInterface() +{ + return NULL; +} + +// virtual +LLCtrlScrollInterface* LLUICtrl::getScrollInterface() +{ + return NULL; +} + +// virtual +void LLUICtrl::setTabStop( BOOL b ) +{ + mTabStop = b; +} + +// virtual +BOOL LLUICtrl::hasTabStop() const +{ + return mTabStop; +} + +// virtual +BOOL LLUICtrl::acceptsTextInput() const +{ + return FALSE; +} + +// virtual +void LLUICtrl::onTabInto() +{ +} + +// virtual +void LLUICtrl::clear() +{ +} + +// virtual +void LLUICtrl::setIsChrome(BOOL is_chrome) +{ + mIsChrome = is_chrome; +} + +// virtual +BOOL LLUICtrl::getIsChrome() const +{ + return mIsChrome; +} + +void LLUICtrl::onFocusReceived() +{ + if( mFocusReceivedCallback ) + { + mFocusReceivedCallback( this, mCallbackUserData ); + } + if( mFocusChangedCallback ) + { + mFocusChangedCallback( this, mCallbackUserData ); + } +} + +void LLUICtrl::onFocusLost() +{ + if( mFocusChangedCallback ) + { + mFocusChangedCallback( this, mCallbackUserData ); + } +} + +BOOL LLUICtrl::hasFocus() const +{ + return (gFocusMgr.childHasKeyboardFocus(this)); +} + +void LLUICtrl::setFocus(BOOL b) +{ + // focus NEVER goes to ui ctrls that are disabled! + if (!mEnabled) + { + return; + } + if( b ) + { + if (!hasFocus()) + { + gFocusMgr.setKeyboardFocus( this, &LLUICtrl::onFocusLostCallback ); + onFocusReceived(); + } + } + else + { + if( gFocusMgr.childHasKeyboardFocus(this)) + { + gFocusMgr.setKeyboardFocus( NULL, NULL ); + onFocusLost(); + } + } +} + +// static +void LLUICtrl::onFocusLostCallback( LLUICtrl* old_focus ) +{ + old_focus->onFocusLost(); +} + +// this comparator uses the crazy disambiguating logic of LLCompareByTabOrder, +// but to switch up the order so that children that have the default tab group come first +// and those that are prior to the default tab group come last +class CompareByDefaultTabGroup: public LLCompareByTabOrder +{ +public: + CompareByDefaultTabGroup(LLView::child_tab_order_t order, S32 default_tab_group): + LLCompareByTabOrder(order), + mDefaultTabGroup(default_tab_group) {} +protected: + /*virtual*/ bool compareTabOrders(const LLView::tab_order_t & a, const LLView::tab_order_t & b) const + { + S32 ag = a.first; // tab group for a + S32 bg = b.first; // tab group for b + // these two ifs have the effect of moving elements prior to the default tab group to the end of the list + // (still sorted relative to each other, though) + if(ag < mDefaultTabGroup && bg >= mDefaultTabGroup) return false; + if(bg < mDefaultTabGroup && ag >= mDefaultTabGroup) return true; + return a < b; // sort correctly if they're both on the same side of the default tab group + } + S32 mDefaultTabGroup; +}; + +// sorter for plugging into the query +class DefaultTabGroupFirstSorter : public LLQuerySorter, public LLSingleton<DefaultTabGroupFirstSorter> +{ +public: + /*virtual*/ void operator() (LLView * parent, viewList_t &children) const + { + children.sort(CompareByDefaultTabGroup(parent->getCtrlOrder(), parent->getDefaultTabGroup())); + } +}; + +BOOL LLUICtrl::focusFirstItem(BOOL prefer_text_fields) +{ + // try to select default tab group child + LLCtrlQuery query = LLView::getTabOrderQuery(); + // sort things such that the default tab group is at the front + query.setSorter(DefaultTabGroupFirstSorter::getInstance()); + LLView::child_list_t result = query(this); + if(result.size() > 0) + { + LLUICtrl * ctrl = static_cast<LLUICtrl*>(result.front()); + if(!ctrl->hasFocus()) + { + ctrl->setFocus(TRUE); + ctrl->onTabInto(); + gFocusMgr.triggerFocusFlash(); + } + return TRUE; + } + // fall back on default behavior if we didn't find anything + return LLView::focusFirstItem(prefer_text_fields); +} + +/* +// Don't let the children handle the tool tip. Handle it here instead. +BOOL LLUICtrl::handleToolTip(S32 x, S32 y, LLString& msg, LLRect* sticky_rect_screen) +{ + BOOL handled = FALSE; + if (getVisible() && pointInView( x, y ) ) + { + if( !mToolTipMsg.empty() ) + { + msg = mToolTipMsg; + + // Convert rect local to screen coordinates + localPointToScreen( + 0, 0, + &(sticky_rect_screen->mLeft), &(sticky_rect_screen->mBottom) ); + localPointToScreen( + mRect.getWidth(), mRect.getHeight(), + &(sticky_rect_screen->mRight), &(sticky_rect_screen->mTop) ); + + handled = TRUE; + } + } + + if (!handled) + { + return LLView::handleToolTip(x, y, msg, sticky_rect_screen); + } + + return handled; +}*/ + +void LLUICtrl::initFromXML(LLXMLNodePtr node, LLView* parent) +{ + BOOL has_tab_stop = hasTabStop(); + node->getAttributeBOOL("tab_stop", has_tab_stop); + + setTabStop(has_tab_stop); + + LLView::initFromXML(node, parent); +} + +LLXMLNodePtr LLUICtrl::getXML(bool save_children) const +{ + LLXMLNodePtr node = LLView::getXML(save_children); + node->createChild("tab_stop", TRUE)->setBoolValue(hasTabStop()); + + return node; +} + +// *NOTE: If other classes derive from LLPanel, they will need to be +// added to this function. +LLPanel* LLUICtrl::getParentPanel() const +{ + LLView* parent = getParent(); + while (parent + && parent->getWidgetType() != WIDGET_TYPE_PANEL + && parent->getWidgetType() != WIDGET_TYPE_FLOATER) + { + parent = parent->getParent(); + } + return reinterpret_cast<LLPanel*>(parent); +} + +// virtual +void LLUICtrl::setTentative(BOOL b) +{ + mTentative = b; +} + +// virtual +BOOL LLUICtrl::getTentative() const +{ + return mTentative; +} + +// virtual +void LLUICtrl::setDoubleClickCallback( void (*cb)(void*) ) +{ +} + +// virtual +void LLUICtrl::setColor(const LLColor4& color) +{ } + +// virtual +void LLUICtrl::setMinValue(LLSD min_value) +{ } + +// virtual +void LLUICtrl::setMaxValue(LLSD max_value) +{ } |