From b2afb8800bb033a04bb3ecdf0363068d56648ef1 Mon Sep 17 00:00:00 2001 From: Jacek Antonelli Date: Fri, 15 Aug 2008 23:44:54 -0500 Subject: Second Life viewer sources 1.15.0.2 --- linden/indra/llui/files.lst | 1 + linden/indra/llui/llalertdialog.cpp | 1 + linden/indra/llui/llalertdialog.h | 1 + linden/indra/llui/llbutton.cpp | 63 +- linden/indra/llui/llbutton.h | 12 +- linden/indra/llui/llcallbackmap.h | 1 + linden/indra/llui/llcheckboxctrl.cpp | 3 +- linden/indra/llui/llcheckboxctrl.h | 1 + linden/indra/llui/llclipboard.cpp | 1 + linden/indra/llui/llclipboard.h | 1 + linden/indra/llui/llcombobox.cpp | 292 +++----- linden/indra/llui/llcombobox.h | 30 +- linden/indra/llui/llctrlselectioninterface.cpp | 1 + linden/indra/llui/llctrlselectioninterface.h | 1 + linden/indra/llui/lldraghandle.cpp | 9 +- linden/indra/llui/lldraghandle.h | 1 + linden/indra/llui/lleditmenuhandler.cpp | 1 + linden/indra/llui/lleditmenuhandler.h | 1 + linden/indra/llui/llfloater.cpp | 73 +- linden/indra/llui/llfloater.h | 1 + linden/indra/llui/llfocusmgr.cpp | 70 +- linden/indra/llui/llfocusmgr.h | 17 +- linden/indra/llui/llhtmlhelp.h | 40 + linden/indra/llui/lliconctrl.cpp | 1 + linden/indra/llui/lliconctrl.h | 1 + linden/indra/llui/llkeywords.cpp | 1 + linden/indra/llui/llkeywords.h | 1 + linden/indra/llui/lllineeditor.cpp | 35 +- linden/indra/llui/lllineeditor.h | 8 +- linden/indra/llui/llmemberlistener.h | 1 + linden/indra/llui/llmenugl.cpp | 31 +- linden/indra/llui/llmenugl.h | 2 + linden/indra/llui/llmodaldialog.cpp | 21 +- linden/indra/llui/llmodaldialog.h | 1 + linden/indra/llui/llpanel.cpp | 1 + linden/indra/llui/llpanel.h | 1 + linden/indra/llui/llradiogroup.cpp | 1 + linden/indra/llui/llradiogroup.h | 1 + linden/indra/llui/llresizebar.cpp | 130 ++-- linden/indra/llui/llresizebar.h | 5 +- linden/indra/llui/llresizehandle.cpp | 118 +-- linden/indra/llui/llresizehandle.h | 5 +- linden/indra/llui/llresmgr.cpp | 5 +- linden/indra/llui/llresmgr.h | 1 + linden/indra/llui/llrootview.cpp | 1 + linden/indra/llui/llrootview.h | 1 + linden/indra/llui/llscrollbar.cpp | 11 +- linden/indra/llui/llscrollbar.h | 1 + linden/indra/llui/llscrollcontainer.cpp | 3 +- linden/indra/llui/llscrollcontainer.h | 1 + linden/indra/llui/llscrollingpanellist.cpp | 1 + linden/indra/llui/llscrollingpanellist.h | 1 + linden/indra/llui/llscrolllistctrl.cpp | 972 ++++++++++++++++++++----- linden/indra/llui/llscrolllistctrl.h | 163 ++++- linden/indra/llui/llslider.cpp | 13 +- linden/indra/llui/llslider.h | 1 + linden/indra/llui/llsliderctrl.cpp | 5 +- linden/indra/llui/llsliderctrl.h | 1 + linden/indra/llui/llspinctrl.cpp | 29 +- linden/indra/llui/llspinctrl.h | 1 + linden/indra/llui/llstyle.cpp | 1 + linden/indra/llui/llstyle.h | 1 + linden/indra/llui/lltabcontainer.cpp | 141 +++- linden/indra/llui/lltabcontainer.h | 5 + linden/indra/llui/lltabcontainervertical.cpp | 9 +- linden/indra/llui/lltabcontainervertical.h | 1 + linden/indra/llui/lltextbox.cpp | 9 +- linden/indra/llui/lltextbox.h | 1 + linden/indra/llui/lltexteditor.cpp | 42 +- linden/indra/llui/lltexteditor.h | 8 +- linden/indra/llui/llui.cpp | 20 +- linden/indra/llui/llui.h | 4 + linden/indra/llui/llui.vcproj | 3 + linden/indra/llui/lluiconstants.h | 1 + linden/indra/llui/lluictrl.cpp | 14 + linden/indra/llui/lluictrl.h | 3 + linden/indra/llui/lluictrlfactory.cpp | 5 + linden/indra/llui/lluictrlfactory.h | 1 + linden/indra/llui/lluistring.cpp | 1 + linden/indra/llui/lluistring.h | 1 + linden/indra/llui/lluixmltags.h | 1 + linden/indra/llui/llundo.cpp | 1 + linden/indra/llui/llundo.h | 1 + linden/indra/llui/llview.cpp | 39 +- linden/indra/llui/llview.h | 11 +- linden/indra/llui/llviewborder.cpp | 1 + linden/indra/llui/llviewborder.h | 1 + linden/indra/llui/llviewquery.cpp | 1 + linden/indra/llui/llviewquery.h | 1 + 89 files changed, 1753 insertions(+), 773 deletions(-) create mode 100644 linden/indra/llui/llhtmlhelp.h (limited to 'linden/indra/llui') diff --git a/linden/indra/llui/files.lst b/linden/indra/llui/files.lst index 96bb170..5a62573 100644 --- a/linden/indra/llui/files.lst +++ b/linden/indra/llui/files.lst @@ -8,6 +8,7 @@ llui/lldraghandle.cpp llui/lleditmenuhandler.cpp llui/llfloater.cpp llui/llfocusmgr.cpp +llui/llhtmlhelp.h llui/lliconctrl.cpp llui/llkeywords.cpp llui/lllineeditor.cpp diff --git a/linden/indra/llui/llalertdialog.cpp b/linden/indra/llui/llalertdialog.cpp index 6523e44..547efae 100644 --- a/linden/indra/llui/llalertdialog.cpp +++ b/linden/indra/llui/llalertdialog.cpp @@ -4,6 +4,7 @@ * * Copyright (c) 2001-2007, Linden Research, Inc. * + * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement diff --git a/linden/indra/llui/llalertdialog.h b/linden/indra/llui/llalertdialog.h index 1085f23..d389236 100644 --- a/linden/indra/llui/llalertdialog.h +++ b/linden/indra/llui/llalertdialog.h @@ -4,6 +4,7 @@ * * Copyright (c) 2001-2007, Linden Research, Inc. * + * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement diff --git a/linden/indra/llui/llbutton.cpp b/linden/indra/llui/llbutton.cpp index 41c2269..d35dd57 100644 --- a/linden/indra/llui/llbutton.cpp +++ b/linden/indra/llui/llbutton.cpp @@ -4,6 +4,7 @@ * * Copyright (c) 2001-2007, Linden Research, Inc. * + * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement @@ -65,7 +66,9 @@ LLButton::LLButton( const LLString& name, const LLRect& rect, const LLString& co mMouseUpCallback( NULL ), mHeldDownCallback( NULL ), mGLFont( NULL ), + mMouseDownFrame( 0 ), mHeldDownDelay( 0.5f ), // seconds until held-down callback is called + mHeldDownFrameDelay( 0 ), mImageUnselected( NULL ), mImageSelected( NULL ), mImageHoverSelected( NULL ), @@ -118,7 +121,9 @@ LLButton::LLButton(const LLString& name, const LLRect& rect, mMouseUpCallback( NULL ), mHeldDownCallback( NULL ), mGLFont( NULL ), + mMouseDownFrame( 0 ), mHeldDownDelay( 0.5f ), // seconds until held-down callback is called + mHeldDownFrameDelay( 0 ), mImageUnselected( NULL ), mImageSelected( NULL ), mImageHoverSelected( NULL ), @@ -215,9 +220,9 @@ void LLButton::init(void (*click_callback)(void*), void *callback_data, const LL LLButton::~LLButton() { - if( this == gFocusMgr.getMouseCapture() ) + if( hasMouseCapture() ) { - gFocusMgr.setMouseCapture( NULL, NULL ); + gFocusMgr.setMouseCapture( NULL ); } } @@ -303,7 +308,7 @@ BOOL LLButton::handleKeyHere(KEY key, MASK mask, BOOL called_from_parent ) BOOL LLButton::handleMouseDown(S32 x, S32 y, MASK mask) { // Route future Mouse messages here preemptively. (Release on mouse up.) - gFocusMgr.setMouseCapture( this, &LLButton::onMouseCaptureLost ); + gFocusMgr.setMouseCapture( this ); if (hasTabStop() && !getIsChrome()) { @@ -316,6 +321,7 @@ BOOL LLButton::handleMouseDown(S32 x, S32 y, MASK mask) } mMouseDownTimer.start(); + mMouseDownFrame = LLFrameTimer::getFrameCount(); if (mSoundFlags & MOUSE_DOWN) { @@ -329,19 +335,17 @@ BOOL LLButton::handleMouseDown(S32 x, S32 y, MASK mask) BOOL LLButton::handleMouseUp(S32 x, S32 y, MASK mask) { // We only handle the click if the click both started and ended within us - if( this == gFocusMgr.getMouseCapture() ) + if( hasMouseCapture() ) { + // Always release the mouse + gFocusMgr.setMouseCapture( NULL ); + // Regardless of where mouseup occurs, handle callback if (mMouseUpCallback) { (*mMouseUpCallback)(mCallbackUserData); } - mMouseDownTimer.stop(); - - // Always release the mouse - gFocusMgr.setMouseCapture( NULL, NULL ); - // DO THIS AT THE VERY END to allow the button to be destroyed as a result of being clicked. // If mouseup in the widget, it's been clicked if (pointInView(x, y)) @@ -356,6 +360,9 @@ BOOL LLButton::handleMouseUp(S32 x, S32 y, MASK mask) (*mClickedCallback)( mCallbackUserData ); } } + + mMouseDownTimer.stop(); + mMouseDownTimer.reset(); } return TRUE; @@ -375,14 +382,14 @@ BOOL LLButton::handleHover(S32 x, S32 y, MASK mask) if (mMouseDownTimer.getStarted() && NULL != mHeldDownCallback) { F32 elapsed = mMouseDownTimer.getElapsedTimeF32(); - if( mHeldDownDelay < elapsed ) + if( mHeldDownDelay <= elapsed && mHeldDownFrameDelay <= LLFrameTimer::getFrameCount() - mMouseDownFrame) { mHeldDownCallback( mCallbackUserData ); } } // We only handle the click if the click both started and ended within us - if( this == gFocusMgr.getMouseCapture() ) + if( hasMouseCapture() ) { handled = TRUE; } @@ -431,7 +438,7 @@ void LLButton::draw() cursor_pos_gl.mY = llround((F32)cursor_pos_gl.mY / LLUI::sGLScaleFactor.mV[VY]); screenPointToLocal(cursor_pos_gl.mX, cursor_pos_gl.mY, &local_mouse_x, &local_mouse_y); - BOOL pressed = pressed_by_keyboard || (this == gFocusMgr.getMouseCapture() && pointInView(local_mouse_x, local_mouse_y)); + BOOL pressed = pressed_by_keyboard || (hasMouseCapture() && pointInView(local_mouse_x, local_mouse_y)); BOOL display_state = FALSE; if( pressed ) @@ -819,11 +826,10 @@ void LLButton::setHoverImages( const LLString& image_name, const LLString& selec setImageHoverSelected(selected_name); } -// static -void LLButton::onMouseCaptureLost( LLMouseHandler* old_captor ) +void LLButton::onMouseCaptureLost() { - LLButton* self = (LLButton*) old_captor; - self->mMouseDownTimer.stop(); + mMouseDownTimer.stop(); + mMouseDownTimer.reset(); } //------------------------------------------------------------------------- @@ -947,6 +953,19 @@ LLXMLNodePtr LLButton::getXML(bool save_children) const return node; } +void clicked_help(void* data) +{ + LLButton* self = (LLButton*)data; + if (!self) return; + + if (!LLUI::sHtmlHelp) + { + return; + } + + LLUI::sHtmlHelp->show(self->getHelpURL()); +} + // static LLView* LLButton::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory) { @@ -1023,9 +1042,21 @@ LLView* LLButton::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *fa { button->setLabelSelected(node->getTextContents()); } + + if (node->hasAttribute("help_url")) + { + LLString help_url; + node->getAttributeString("help_url",help_url); + button->setHelpURLCallback(help_url); + } button->initFromXML(node, parent); return button; } +void LLButton::setHelpURLCallback(std::string help_url) +{ + mHelpURL = help_url; + setClickedCallback(clicked_help,this); +} diff --git a/linden/indra/llui/llbutton.h b/linden/indra/llui/llbutton.h index fe906a6..44e8776 100644 --- a/linden/indra/llui/llbutton.h +++ b/linden/indra/llui/llbutton.h @@ -4,6 +4,7 @@ * * Copyright (c) 2001-2007, Linden Research, Inc. * + * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement @@ -94,6 +95,8 @@ public: virtual BOOL handleHover(S32 x, S32 y, MASK mask); virtual void draw(); + virtual void onMouseCaptureLost(); + // HACK: "committing" a button is the same as clicking on it. virtual void onCommit(); @@ -104,7 +107,7 @@ public: void setMouseDownCallback( void (*cb)(void *data) ) { mMouseDownCallback = cb; } // mouse down within button void setMouseUpCallback( void (*cb)(void *data) ) { mMouseUpCallback = cb; } // mouse up, EVEN IF NOT IN BUTTON void setHeldDownCallback( void (*cb)(void *data) ) { mHeldDownCallback = cb; } // Mouse button held down and in button - void setHeldDownDelay( F32 seconds) { mHeldDownDelay = seconds; } + void setHeldDownDelay( F32 seconds, S32 frames = 0) { mHeldDownDelay = seconds; mHeldDownFrameDelay = frames; } F32 getHeldDownTime() const { return mMouseDownTimer.getElapsedTimeF32(); } @@ -159,7 +162,6 @@ public: void setBorderEnabled(BOOL b) { mBorderEnabled = b; } static void onHeldDown(void *userdata); // to be called by gIdleCallbacks - static void onMouseCaptureLost(LLMouseHandler* old_captor); void setFixedBorder(S32 width, S32 height) { mFixedWidth = width; mFixedHeight = height; } void setHoverGlowStrength(F32 strength) { mHoverGlowStrength = strength; } @@ -181,6 +183,8 @@ public: void setCommitOnReturn(BOOL commit) { mCommitOnReturn = commit; } BOOL getCommitOnReturn() { return mCommitOnReturn; } + void setHelpURLCallback(std::string help_url); + LLString getHelpURL() { return mHelpURL; } protected: virtual void drawBorder(const LLColor4& color, S32 size); @@ -194,7 +198,9 @@ protected: const LLFontGL *mGLFont; LLFrameTimer mMouseDownTimer; + S32 mMouseDownFrame; F32 mHeldDownDelay; // seconds, after which held-down callbacks get called + S32 mHeldDownFrameDelay; // frames, after which held-down callbacks get called LLPointer mImageUnselected; LLUIString mUnselectedLabel; @@ -259,6 +265,8 @@ protected: BOOL mNeedsHighlight; BOOL mCommitOnReturn; + LLString mHelpURL; + LLPointer mImagep; static LLFrameTimer sFlashingTimer; diff --git a/linden/indra/llui/llcallbackmap.h b/linden/indra/llui/llcallbackmap.h index 3a0e3b3..4a47f60 100644 --- a/linden/indra/llui/llcallbackmap.h +++ b/linden/indra/llui/llcallbackmap.h @@ -4,6 +4,7 @@ * * Copyright (c) 2006-2007, Linden Research, Inc. * + * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement diff --git a/linden/indra/llui/llcheckboxctrl.cpp b/linden/indra/llui/llcheckboxctrl.cpp index 9f11ff8..5f3350e 100644 --- a/linden/indra/llui/llcheckboxctrl.cpp +++ b/linden/indra/llui/llcheckboxctrl.cpp @@ -4,6 +4,7 @@ * * Copyright (c) 2001-2007, Linden Research, Inc. * + * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement @@ -175,7 +176,7 @@ void LLCheckBoxCtrl::onCommit() void LLCheckBoxCtrl::setEnabled(BOOL b) { - LLUICtrl::setEnabled(b); + LLView::setEnabled(b); mButton->setEnabled(b); } diff --git a/linden/indra/llui/llcheckboxctrl.h b/linden/indra/llui/llcheckboxctrl.h index 77dc39d..1b895cb 100644 --- a/linden/indra/llui/llcheckboxctrl.h +++ b/linden/indra/llui/llcheckboxctrl.h @@ -4,6 +4,7 @@ * * Copyright (c) 2001-2007, Linden Research, Inc. * + * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement diff --git a/linden/indra/llui/llclipboard.cpp b/linden/indra/llui/llclipboard.cpp index d7c25fb..19f0188 100644 --- a/linden/indra/llui/llclipboard.cpp +++ b/linden/indra/llui/llclipboard.cpp @@ -4,6 +4,7 @@ * * Copyright (c) 2001-2007, Linden Research, Inc. * + * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement diff --git a/linden/indra/llui/llclipboard.h b/linden/indra/llui/llclipboard.h index 00bd73e..dc4cb32 100644 --- a/linden/indra/llui/llclipboard.h +++ b/linden/indra/llui/llclipboard.h @@ -4,6 +4,7 @@ * * Copyright (c) 2001-2007, Linden Research, Inc. * + * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement diff --git a/linden/indra/llui/llcombobox.cpp b/linden/indra/llui/llcombobox.cpp index 7c3755a..983dd43 100644 --- a/linden/indra/llui/llcombobox.cpp +++ b/linden/indra/llui/llcombobox.cpp @@ -4,6 +4,7 @@ * * Copyright (c) 2001-2007, Linden Research, Inc. * + * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement @@ -59,7 +60,7 @@ LLComboBox::LLComboBox( const LLString& name, const LLRect &rect, const LLString ) : LLUICtrl(name, rect, TRUE, commit_callback, callback_userdata, FOLLOWS_LEFT | FOLLOWS_TOP), - mDrawButton(TRUE), + mDrawArrow(TRUE), mTextEntry(NULL), mArrowImage(NULL), mArrowImageWidth(8), @@ -67,8 +68,8 @@ LLComboBox::LLComboBox( const LLString& name, const LLRect &rect, const LLString mMaxChars(20), mTextEntryTentative(TRUE), mPrearrangeCallback( NULL ), - mTextEntryCallback( NULL ), - mListWidth(list_width) + mListPosition(BELOW), + mTextEntryCallback( NULL ) { // For now, all comboboxes don't take keyboard focus when clicked. // This might change if it is part of a modal dialog. @@ -76,7 +77,7 @@ LLComboBox::LLComboBox( const LLString& name, const LLRect &rect, const LLString // Revert to standard behavior. When this control's parent is hidden, it needs to // hide this ctrl--which won't just happen automatically since when LLComboBox is - // showing its list, it's also set to TopView. When keyboard focus is cleared all + // showing its list, it's also set to TopCtrl. When keyboard focus is cleared all // controls (including this one) know that they are no longer editing. mKeyboardFocusOnClick = TRUE; @@ -87,7 +88,8 @@ LLComboBox::LLComboBox( const LLString& name, const LLRect &rect, const LLString // Text label button mButton = new LLSquareButton("comboxbox button", r, label, NULL, LLString::null, - &LLComboBox::onButtonClick, this); + NULL, this); + mButton->setMouseDownCallback(onButtonDown); mButton->setFont(LLFontGL::sSansSerifSmall); mButton->setFollows(FOLLOWS_LEFT | FOLLOWS_BOTTOM | FOLLOWS_RIGHT); mButton->setHAlign( LLFontGL::LEFT ); @@ -110,6 +112,7 @@ LLComboBox::LLComboBox( const LLString& name, const LLRect &rect, const LLString mList->setVisible(FALSE); mList->setBgWriteableColor( LLColor4(1,1,1,1) ); mList->setCommitOnKeyboardMovement(FALSE); + mList->setFocusChangedCallback(onListFocusChanged); addChild(mList); LLRect border_rect(0, mRect.getHeight(), mRect.getWidth(), 0); @@ -119,7 +122,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 } @@ -219,115 +222,10 @@ LLView* LLComboBox::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory * void LLComboBox::setEnabled(BOOL enabled) { - LLUICtrl::setEnabled(enabled); + LLView::setEnabled(enabled); mButton->setEnabled(enabled); } -// *HACK: these are all hacks to support the fact that the combobox -// has mouse capture so we can hide the list when we don't handle the -// mouse up event -BOOL LLComboBox::handleHover(S32 x, S32 y, MASK mask) -{ - if (mList->getVisible()) - { - S32 local_x, local_y; - LLView::localPointToOtherView(x, y, &local_x, &local_y, mList); - if (mList->pointInView(local_x, local_y)) - { - return mList->handleHover(local_x, local_y, mask); - } - } - return LLUICtrl::handleHover(x, y, mask); -} - -BOOL LLComboBox::handleMouseDown(S32 x, S32 y, MASK mask) -{ - if (mList->getVisible()) - { - S32 local_x, local_y; - LLView::localPointToOtherView(x, y, &local_x, &local_y, mList); - if (mList->pointInView(local_x, local_y)) - { - return mList->handleMouseDown(local_x, local_y, mask); - } - } - BOOL has_focus_now = hasFocus(); - BOOL handled = LLUICtrl::handleMouseDown(x, y, mask); - if (handled && !has_focus_now) - { - onFocusReceived(); - } - - return handled; -} - -BOOL LLComboBox::handleRightMouseDown(S32 x, S32 y, MASK mask) -{ - if (mList->getVisible()) - { - S32 local_x, local_y; - LLView::localPointToOtherView(x, y, &local_x, &local_y, mList); - if (mList->pointInView(local_x, local_y)) - { - return mList->handleRightMouseDown(local_x, local_y, mask); - } - } - return LLUICtrl::handleRightMouseDown(x, y, mask); -} - -BOOL LLComboBox::handleRightMouseUp(S32 x, S32 y, MASK mask) -{ - if (mList->getVisible()) - { - S32 local_x, local_y; - LLView::localPointToOtherView(x, y, &local_x, &local_y, mList); - if (mList->pointInView(local_x, local_y)) - { - return mList->handleRightMouseUp(local_x, local_y, mask); - } - } - return LLUICtrl::handleRightMouseUp(x, y, mask); -} - -BOOL LLComboBox::handleDoubleClick(S32 x, S32 y, MASK mask) -{ - if (mList->getVisible()) - { - S32 local_x, local_y; - LLView::localPointToOtherView(x, y, &local_x, &local_y, mList); - if (mList->pointInView(local_x, local_y)) - { - return mList->handleDoubleClick(local_x, local_y, mask); - } - } - return LLUICtrl::handleDoubleClick(x, y, mask); -} - -BOOL LLComboBox::handleMouseUp(S32 x, S32 y, MASK mask) -{ - BOOL handled = childrenHandleMouseUp(x, y, mask) != NULL; - - if (!handled && mList->getVisible()) - { - S32 local_x, local_y; - LLView::localPointToOtherView(x, y, &local_x, &local_y, mList); - if (mList->pointInView(local_x, local_y)) - { - handled = mList->handleMouseUp(local_x, local_y, mask); - } - } - - if( !handled && gFocusMgr.getMouseCapture() == this ) - { - // Mouse events that we didn't handle cause the list to be hidden. - // Eat mouse event, regardless of where on the screen it happens. - hideList(); - handled = TRUE; - } - - return handled; -} - void LLComboBox::clear() { if (mTextEntry) @@ -512,12 +410,13 @@ void LLComboBox::onFocusLost() { mTextEntry->selectAll(); } + LLUICtrl::onFocusLost(); } void LLComboBox::setButtonVisible(BOOL visible) { mButton->setVisible(visible); - mDrawButton = visible; + mDrawArrow = visible; if (mTextEntry) { LLRect text_entry_rect(0, mRect.getHeight(), mRect.getWidth(), 0); @@ -541,15 +440,17 @@ void LLComboBox::draw() // Draw children LLUICtrl::draw(); - if (mDrawButton) + if (mDrawArrow) { // Paste the graphic on the right edge if (!mArrowImage.isNull()) { - S32 left = mRect.getWidth() - mArrowImageWidth - LLUI::sConfigGroup->getS32("DropShadowButton"); + S32 arrow_height = llmin(mRect.getHeight(), mArrowImage->getHeight()); + S32 arrow_width = llround((F32)mArrowImage->getWidth() * ((F32)arrow_height / (F32)mArrowImage->getHeight())); + + S32 left = mRect.getWidth() - mArrowImage->getWidth() - LLUI::sConfigGroup->getS32("DropShadowButton"); - gl_draw_image( left, 0, mArrowImage, - LLColor4::white); + gl_draw_scaled_image( left, 0, arrow_width, arrow_height, mArrowImage, LLColor4::white); } } } @@ -595,18 +496,61 @@ void LLComboBox::showList() //HACK: shouldn't have to know about scale here mList->arrange( 192, llfloor((F32)window_size.mY / LLUI::sGLScaleFactor.mV[VY]) - 50 ); - // Move rect so it hangs off the bottom of this view + // Make sure that we can see the whole list + LLRect root_view_local; + LLView* root_view = getRootView(); + root_view->localRectToOtherView(root_view->getLocalRect(), &root_view_local, this); + LLRect rect = mList->getRect(); - rect.setLeftTopAndSize(0, 0, rect.getWidth(), rect.getHeight() ); - mList->setRect(rect); + if (mListPosition == BELOW) + { + 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() ); + } + else + { + // stack on top or bottom, depending on which has more room + 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(-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(root_view_local.mTop - mRect.getHeight(), rect.getHeight())); + } + } + } + else // ABOVE + { + 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(root_view_local.mTop - mRect.getHeight(), rect.getHeight())); + } + else + { + // stack on top or bottom, depending on which has more room + 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(-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(root_view_local.mTop - mRect.getHeight(), rect.getHeight())); + } + } - // Make sure that we can see the whole list - LLRect floater_area_screen; - LLRect floater_area_local; - gFloaterView->getParent()->localRectToScreen( gFloaterView->getRect(), &floater_area_screen ); - screenRectToLocal( floater_area_screen, &floater_area_local ); - mList->translateIntoRect( floater_area_local, FALSE ); + } + mList->setOrigin(rect.mLeft, rect.mBottom); + mList->reshape(rect.getWidth(), rect.getHeight()); + mList->translateIntoRect(root_view_local, FALSE); // Make sure we didn't go off bottom of screen S32 x, y; @@ -617,7 +561,12 @@ void LLComboBox::showList() mList->translate(0, -y); } - gFocusMgr.setMouseCapture( this, LLComboBox::onMouseCaptureLost ); + // pass mouse capture on to list if button is depressed + if (mButton->hasMouseCapture()) + { + gFocusMgr.setMouseCapture(mList); + } + // NB: this call will trigger the focuslost callback which will hide the list, so do it first // before finally showing the list @@ -627,14 +576,13 @@ void LLComboBox::showList() // so that the callback is not immediately triggered on setFocus() mList->selectFirstItem(); } - gFocusMgr.setKeyboardFocus(mList, onListFocusLost); + mList->setFocus(TRUE); // Show the list and push the button down mButton->setToggleState(TRUE); mList->setVisible(TRUE); - gFocusMgr.setTopView(mList, LLComboBox::onTopViewLost ); - + gFocusMgr.setTopCtrl(mList); } void LLComboBox::hideList() @@ -643,37 +591,21 @@ void LLComboBox::hideList() mList->setVisible(FALSE); mList->highlightNthItem(-1); - if( gFocusMgr.getTopView() == mList ) - { - gFocusMgr.setTopView(NULL, NULL); - } - - if( gFocusMgr.getMouseCapture() == this ) + if( gFocusMgr.getTopCtrl() == mList ) { - gFocusMgr.setMouseCapture( NULL, NULL ); + gFocusMgr.setTopCtrl(NULL); } - if( gFocusMgr.getKeyboardFocus() == mList ) - { - if (mAllowTextEntry) - { - mTextEntry->setFocus(TRUE); - } - else - { - setFocus(TRUE); - } - } + //mList->setFocus(FALSE); } - //------------------------------------------------------------------ // static functions //------------------------------------------------------------------ // static -void LLComboBox::onButtonClick(void *userdata) +void LLComboBox::onButtonDown(void *userdata) { LLComboBox *self = (LLComboBox *)userdata; @@ -720,50 +652,47 @@ void LLComboBox::onItemSelected(LLUICtrl* item, void *userdata) const LLString& name = self->mList->getSimpleSelectedItem(); - self->hideList(); - S32 cur_id = self->getCurrentIndex(); if (cur_id != -1) { - self->setLabel(self->mList->getSimpleSelectedItem()); + self->setLabel(name); if (self->mAllowTextEntry) { - self->mTextEntry->setText(name); - self->mTextEntry->setTentative(FALSE); gFocusMgr.setKeyboardFocus(self->mTextEntry, NULL); self->mTextEntry->selectAll(); } - else - { - self->mButton->setLabelUnselected( name ); - self->mButton->setLabelSelected( name ); - self->mButton->setDisabledLabel( name ); - self->mButton->setDisabledSelectedLabel( name ); - } + } + else + { + // invalid selection, just restore existing value + self->mList->selectSimpleItem(self->mButton->getLabelSelected()); } self->onCommit(); -} -// static -void LLComboBox::onTopViewLost(LLView* old_focus) -{ - LLComboBox *self = (LLComboBox *) old_focus->getParent(); self->hideList(); } - // static -void LLComboBox::onMouseCaptureLost(LLMouseHandler*) +void LLComboBox::onListFocusChanged(LLUICtrl* list, void* user_data) { - // Can't hide the list here. If the list scrolls off the screen, - // and you click in the arrow buttons of the scroll bar, they must capture - // the mouse to handle scrolling-while-mouse-down. + LLComboBox *self = (LLComboBox *) list->getParent(); + // 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(); + + self->hideList(); + + // reassert original selection + self->mList->selectSimpleItem(orig_selection, FALSE); + } } BOOL LLComboBox::handleToolTip(S32 x, S32 y, LLString& msg, LLRect* sticky_rect_screen) { - + LLString tool_tip; if (LLUI::sShowXUINames) @@ -875,6 +804,7 @@ void LLComboBox::setAllowTextEntry(BOOL allow, S32 max_chars, BOOL set_tentative mTextEntry->setCommitOnFocusLost(FALSE); mTextEntry->setText(cur_label); mTextEntry->setIgnoreTab(TRUE); + mTextEntry->setFollowsAll(); addChild(mTextEntry); mMaxChars = max_chars; } @@ -882,6 +812,8 @@ void LLComboBox::setAllowTextEntry(BOOL allow, S32 max_chars, BOOL set_tentative { mTextEntry->setVisible(TRUE); } + + mButton->setFollows(FOLLOWS_BOTTOM | FOLLOWS_TOP | FOLLOWS_RIGHT); } else if (!allow && mAllowTextEntry) { @@ -892,6 +824,7 @@ void LLComboBox::setAllowTextEntry(BOOL allow, S32 max_chars, BOOL set_tentative { mTextEntry->setVisible(FALSE); } + mButton->setFollowsAll(); } mAllowTextEntry = allow; mTextEntryTentative = set_tentative; @@ -927,6 +860,7 @@ void LLComboBox::onTextEntry(LLLineEditor* line_editor, void* user_data) else { line_editor->setTentative(self->mTextEntryTentative); + self->mList->deselectAllItems(); } return; } @@ -1141,15 +1075,3 @@ BOOL LLComboBox::operateOnAll(EOperation op) } return FALSE; } - -//static -void LLComboBox::onListFocusLost(LLUICtrl* old_focus) -{ - // if focus is going to nothing (user hit ESC), take it back - LLComboBox* combo = (LLComboBox*)old_focus->getParent(); - combo->hideList(); - if (gFocusMgr.getKeyboardFocus() == NULL) - { - combo->focusFirstItem(); - } -} diff --git a/linden/indra/llui/llcombobox.h b/linden/indra/llui/llcombobox.h index 5de9463..8c317ee 100644 --- a/linden/indra/llui/llcombobox.h +++ b/linden/indra/llui/llcombobox.h @@ -4,6 +4,7 @@ * * Copyright (c) 2001-2007, Linden Research, Inc. * + * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement @@ -53,6 +54,12 @@ class LLComboBox : public LLUICtrl, public LLCtrlListInterface { public: + typedef enum e_preferred_position + { + ABOVE, + BELOW + } EPreferredPosition; + LLComboBox( const LLString& name, const LLRect &rect, @@ -77,12 +84,6 @@ public: virtual BOOL handleToolTip(S32 x, S32 y, LLString& msg, LLRect* sticky_rect); virtual BOOL handleKeyHere(KEY key, MASK mask, BOOL called_from_parent); virtual BOOL handleUnicodeCharHere(llwchar uni_char, BOOL called_from_parent); - virtual BOOL handleHover(S32 x, S32 y, MASK mask); - virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask); - virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); - virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); - virtual BOOL handleRightMouseUp(S32 x, S32 y, MASK mask); - virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask); // LLUICtrl interface virtual void clear(); // select nothing @@ -165,34 +166,31 @@ public: void setButtonVisible(BOOL visible); - static void onButtonClick(void *userdata); + static void onButtonDown(void *userdata); static void onItemSelected(LLUICtrl* item, void *userdata); - static void onTopViewLost(LLView* old_focus); - static void onMouseCaptureLost(LLMouseHandler* old_captor); + static void onListFocusChanged(LLUICtrl* item, void *userdata); static void onTextEntry(LLLineEditor* line_editor, void* user_data); static void onTextCommit(LLUICtrl* caller, void* user_data); void updateSelection(); - void showList(); - void hideList(); - - static void onListFocusLost(LLUICtrl* old_focus); - + virtual void showList(); + virtual void hideList(); + protected: LLButton* mButton; LLScrollListCtrl* mList; LLViewBorder* mBorder; BOOL mKeyboardFocusOnClick; - BOOL mDrawButton; + BOOL mDrawArrow; LLLineEditor* mTextEntry; LLPointer mArrowImage; S32 mArrowImageWidth; BOOL mAllowTextEntry; S32 mMaxChars; BOOL mTextEntryTentative; + EPreferredPosition mListPosition; void (*mPrearrangeCallback)(LLUICtrl*,void*); void (*mTextEntryCallback)(LLLineEditor*, void*); - S32 mListWidth; // width of pop-up list, 0 = use combobox width }; #endif diff --git a/linden/indra/llui/llctrlselectioninterface.cpp b/linden/indra/llui/llctrlselectioninterface.cpp index 446eb63..3b71942 100644 --- a/linden/indra/llui/llctrlselectioninterface.cpp +++ b/linden/indra/llui/llctrlselectioninterface.cpp @@ -4,6 +4,7 @@ * * Copyright (c) 2006-2007, Linden Research, Inc. * + * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement diff --git a/linden/indra/llui/llctrlselectioninterface.h b/linden/indra/llui/llctrlselectioninterface.h index 189d2e1..878648d 100644 --- a/linden/indra/llui/llctrlselectioninterface.h +++ b/linden/indra/llui/llctrlselectioninterface.h @@ -4,6 +4,7 @@ * * Copyright (c) 2006-2007, Linden Research, Inc. * + * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement diff --git a/linden/indra/llui/lldraghandle.cpp b/linden/indra/llui/lldraghandle.cpp index 261d149..9e80c99 100644 --- a/linden/indra/llui/lldraghandle.cpp +++ b/linden/indra/llui/lldraghandle.cpp @@ -4,6 +4,7 @@ * * Copyright (c) 2001-2007, Linden Research, Inc. * + * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement @@ -288,7 +289,7 @@ BOOL LLDragHandle::handleMouseDown(S32 x, S32 y, MASK mask) { // Route future Mouse messages here preemptively. (Release on mouse up.) // No handler needed for focus lost since this clas has no state that depends on it. - gFocusMgr.setMouseCapture(this, NULL ); + gFocusMgr.setMouseCapture(this); localPointToScreen(x, y, &mDragLastScreenX, &mDragLastScreenY); mLastMouseScreenX = mDragLastScreenX; @@ -301,10 +302,10 @@ BOOL LLDragHandle::handleMouseDown(S32 x, S32 y, MASK mask) BOOL LLDragHandle::handleMouseUp(S32 x, S32 y, MASK mask) { - if( gFocusMgr.getMouseCapture() == this ) + if( hasMouseCapture() ) { // Release the mouse - gFocusMgr.setMouseCapture( NULL, NULL ); + gFocusMgr.setMouseCapture( NULL ); } // Note: don't pass on to children @@ -317,7 +318,7 @@ BOOL LLDragHandle::handleHover(S32 x, S32 y, MASK mask) BOOL handled = FALSE; // We only handle the click if the click both started and ended within us - if( gFocusMgr.getMouseCapture() == this ) + if( hasMouseCapture() ) { S32 screen_x; S32 screen_y; diff --git a/linden/indra/llui/lldraghandle.h b/linden/indra/llui/lldraghandle.h index 5344358..691851d 100644 --- a/linden/indra/llui/lldraghandle.h +++ b/linden/indra/llui/lldraghandle.h @@ -4,6 +4,7 @@ * * Copyright (c) 2001-2007, Linden Research, Inc. * + * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement diff --git a/linden/indra/llui/lleditmenuhandler.cpp b/linden/indra/llui/lleditmenuhandler.cpp index 7425aa8..85b4464 100644 --- a/linden/indra/llui/lleditmenuhandler.cpp +++ b/linden/indra/llui/lleditmenuhandler.cpp @@ -4,6 +4,7 @@ * * Copyright (c) 2006-2007, Linden Research, Inc. * + * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement diff --git a/linden/indra/llui/lleditmenuhandler.h b/linden/indra/llui/lleditmenuhandler.h index 35e223b..ec3d246 100644 --- a/linden/indra/llui/lleditmenuhandler.h +++ b/linden/indra/llui/lleditmenuhandler.h @@ -4,6 +4,7 @@ * * Copyright (c) 2006-2007, Linden Research, Inc. * + * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement diff --git a/linden/indra/llui/llfloater.cpp b/linden/indra/llui/llfloater.cpp index 02a410e..12758b3 100644 --- a/linden/indra/llui/llfloater.cpp +++ b/linden/indra/llui/llfloater.cpp @@ -4,6 +4,7 @@ * * Copyright (c) 2002-2007, Linden Research, Inc. * + * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement @@ -57,6 +58,8 @@ extern BOOL gNoRender; const S32 MINIMIZED_WIDTH = 160; const S32 CLOSE_BOX_FROM_TOP = 1; +// use this to control "jumping" behavior when Ctrl-Tabbing +const S32 TABBED_FLOATER_OFFSET = 0; LLString LLFloater::sButtonActiveImageNames[BUTTON_COUNT] = { @@ -298,7 +301,6 @@ void LLFloater::init(const LLString& title, mRect.getHeight() - LLPANEL_BORDER_WIDTH - close_box_size); mDragHandle = new LLDragHandleLeft("drag", drag_handle_rect, title ); } - mDragHandle->setSaveToXML(false); addChild(mDragHandle); // Resize Handle @@ -314,28 +316,24 @@ void LLFloater::init(const LLString& title, "resizebar_left", LLRect( 0, mRect.getHeight(), RESIZE_BAR_THICKNESS, 0), min_width, min_height, LLResizeBar::LEFT ); - mResizeBar[0]->setSaveToXML(false); addChild( mResizeBar[0] ); mResizeBar[1] = new LLResizeBar( "resizebar_top", LLRect( 0, mRect.getHeight(), mRect.getWidth(), mRect.getHeight() - RESIZE_BAR_THICKNESS), min_width, min_height, LLResizeBar::TOP ); - mResizeBar[1]->setSaveToXML(false); addChild( mResizeBar[1] ); mResizeBar[2] = new LLResizeBar( "resizebar_right", LLRect( mRect.getWidth() - RESIZE_BAR_THICKNESS, mRect.getHeight(), mRect.getWidth(), 0), min_width, min_height, LLResizeBar::RIGHT ); - mResizeBar[2]->setSaveToXML(false); addChild( mResizeBar[2] ); mResizeBar[3] = new LLResizeBar( "resizebar_bottom", LLRect( 0, RESIZE_BAR_THICKNESS, mRect.getWidth(), 0), min_width, min_height, LLResizeBar::BOTTOM ); - mResizeBar[3]->setSaveToXML(false); addChild( mResizeBar[3] ); @@ -346,7 +344,6 @@ void LLFloater::init(const LLString& title, min_width, min_height, LLResizeHandle::RIGHT_BOTTOM); - mResizeHandle[0]->setSaveToXML(false); addChild(mResizeHandle[0]); mResizeHandle[1] = new LLResizeHandle( "resize", @@ -354,7 +351,6 @@ void LLFloater::init(const LLString& title, min_width, min_height, LLResizeHandle::RIGHT_TOP ); - mResizeHandle[1]->setSaveToXML(false); addChild(mResizeHandle[1]); mResizeHandle[2] = new LLResizeHandle( "resize", @@ -362,7 +358,6 @@ void LLFloater::init(const LLString& title, min_width, min_height, LLResizeHandle::LEFT_BOTTOM ); - mResizeHandle[2]->setSaveToXML(false); addChild(mResizeHandle[2]); mResizeHandle[3] = new LLResizeHandle( "resize", @@ -370,7 +365,6 @@ void LLFloater::init(const LLString& title, min_width, min_height, LLResizeHandle::LEFT_TOP ); - mResizeHandle[3]->setSaveToXML(false); addChild(mResizeHandle[3]); } else @@ -482,14 +476,14 @@ void LLFloater::setVisible( BOOL visible ) if( !visible ) { - if( gFocusMgr.childIsTopView( this ) ) + if( gFocusMgr.childIsTopCtrl( this ) ) { - gFocusMgr.setTopView(NULL, NULL); + gFocusMgr.setTopCtrl(NULL); } if( gFocusMgr.childHasMouseCapture( this ) ) { - gFocusMgr.setMouseCapture(NULL, NULL); + gFocusMgr.setMouseCapture(NULL); } } @@ -603,9 +597,9 @@ void LLFloater::close(bool app_quitting) void LLFloater::releaseFocus() { - if( gFocusMgr.childIsTopView( this ) ) + if( gFocusMgr.childIsTopCtrl( this ) ) { - gFocusMgr.setTopView(NULL, NULL); + gFocusMgr.setTopCtrl(NULL); } if( gFocusMgr.childHasKeyboardFocus( this ) ) @@ -615,7 +609,7 @@ void LLFloater::releaseFocus() if( gFocusMgr.childHasMouseCapture( this ) ) { - gFocusMgr.setMouseCapture(NULL, NULL); + gFocusMgr.setMouseCapture(NULL); } } @@ -1483,28 +1477,24 @@ void LLFloater::setCanResize(BOOL can_resize) "resizebar_left", LLRect( 0, mRect.getHeight(), RESIZE_BAR_THICKNESS, 0), mMinWidth, mMinHeight, LLResizeBar::LEFT ); - mResizeBar[0]->setSaveToXML(false); addChild( mResizeBar[0] ); mResizeBar[1] = new LLResizeBar( "resizebar_top", LLRect( 0, mRect.getHeight(), mRect.getWidth(), mRect.getHeight() - RESIZE_BAR_THICKNESS), mMinWidth, mMinHeight, LLResizeBar::TOP ); - mResizeBar[1]->setSaveToXML(false); addChild( mResizeBar[1] ); mResizeBar[2] = new LLResizeBar( "resizebar_right", LLRect( mRect.getWidth() - RESIZE_BAR_THICKNESS, mRect.getHeight(), mRect.getWidth(), 0), mMinWidth, mMinHeight, LLResizeBar::RIGHT ); - mResizeBar[2]->setSaveToXML(false); addChild( mResizeBar[2] ); mResizeBar[3] = new LLResizeBar( "resizebar_bottom", LLRect( 0, RESIZE_BAR_THICKNESS, mRect.getWidth(), 0), mMinWidth, mMinHeight, LLResizeBar::BOTTOM ); - mResizeBar[3]->setSaveToXML(false); addChild( mResizeBar[3] ); @@ -1515,7 +1505,6 @@ void LLFloater::setCanResize(BOOL can_resize) mMinWidth, mMinHeight, LLResizeHandle::RIGHT_BOTTOM); - mResizeHandle[0]->setSaveToXML(false); addChild(mResizeHandle[0]); mResizeHandle[1] = new LLResizeHandle( "resize", @@ -1523,7 +1512,6 @@ void LLFloater::setCanResize(BOOL can_resize) mMinWidth, mMinHeight, LLResizeHandle::RIGHT_TOP ); - mResizeHandle[1]->setSaveToXML(false); addChild(mResizeHandle[1]); mResizeHandle[2] = new LLResizeHandle( "resize", @@ -1531,7 +1519,6 @@ void LLFloater::setCanResize(BOOL can_resize) mMinWidth, mMinHeight, LLResizeHandle::LEFT_BOTTOM ); - mResizeHandle[2]->setSaveToXML(false); addChild(mResizeHandle[2]); mResizeHandle[3] = new LLResizeHandle( "resize", @@ -1539,7 +1526,6 @@ void LLFloater::setCanResize(BOOL can_resize) mMinWidth, mMinHeight, LLResizeHandle::LEFT_TOP ); - mResizeHandle[3]->setSaveToXML(false); addChild(mResizeHandle[3]); } mResizable = can_resize; @@ -2041,8 +2027,7 @@ void LLFloaterView::focusFrontFloater() void LLFloaterView::getMinimizePosition(S32 *left, S32 *bottom) { S32 col = 0; - LLRect snap_rect_local = getSnapRect(); - snap_rect_local.translate(-mRect.mLeft, -mRect.mBottom); + LLRect snap_rect_local = getLocalSnapRect(); for(S32 row = snap_rect_local.mBottom; row < snap_rect_local.getHeight() - LLFLOATER_HEADER_SIZE; row += LLFLOATER_HEADER_SIZE ) //loop rows @@ -2165,8 +2150,7 @@ void LLFloaterView::adjustToFitScreen(LLFloater* floater, BOOL allow_partial_out S32 screen_width = getSnapRect().getWidth(); S32 screen_height = getSnapRect().getHeight(); // convert to local coordinate frame - LLRect snap_rect_local = getSnapRect(); - snap_rect_local.translate(-mRect.mLeft, -mRect.mBottom); + LLRect snap_rect_local = getLocalSnapRect(); if( floater->isResizable() ) { @@ -2207,32 +2191,27 @@ void LLFloaterView::adjustToFitScreen(LLFloater* floater, BOOL allow_partial_out void LLFloaterView::draw() { - if( getVisible() ) - { - refresh(); - - // hide focused floater if in cycle mode, so that it can be drawn on top - LLFloater* focused_floater = getFocusedFloater(); - BOOL floater_visible = FALSE; - if (mFocusCycleMode && focused_floater) - { - floater_visible = focused_floater->getVisible(); - focused_floater->setVisible(FALSE); - } + refresh(); - // And actually do the draw - LLView::draw(); + // hide focused floater if in cycle mode, so that it can be drawn on top + LLFloater* focused_floater = getFocusedFloater(); - // manually draw focused floater on top when in cycle mode - if (mFocusCycleMode && focused_floater) + if (mFocusCycleMode && focused_floater) + { + child_list_const_iter_t child_it = getChildList()->begin(); + for (;child_it != getChildList()->end(); ++child_it) { - // draw focused item on top for better feedback - focused_floater->setVisible(floater_visible); - if (floater_visible) + if ((*child_it) != focused_floater) { - drawChild(focused_floater); + drawChild(*child_it); } } + + drawChild(focused_floater, -TABBED_FLOATER_OFFSET, TABBED_FLOATER_OFFSET); + } + else + { + LLView::draw(); } } diff --git a/linden/indra/llui/llfloater.h b/linden/indra/llui/llfloater.h index 25b2697..e752d8b 100644 --- a/linden/indra/llui/llfloater.h +++ b/linden/indra/llui/llfloater.h @@ -4,6 +4,7 @@ * * Copyright (c) 2002-2007, Linden Research, Inc. * + * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement diff --git a/linden/indra/llui/llfocusmgr.cpp b/linden/indra/llui/llfocusmgr.cpp index f02996b..f79164e 100644 --- a/linden/indra/llui/llfocusmgr.cpp +++ b/linden/indra/llui/llfocusmgr.cpp @@ -4,6 +4,7 @@ * * Copyright (c) 2002-2007, Linden Research, Inc. * + * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement @@ -40,18 +41,16 @@ LLFocusMgr::LLFocusMgr() mLockedView( NULL ), mKeyboardLockedFocusLostCallback( NULL ), mMouseCaptor( NULL ), - mMouseCaptureLostCallback( NULL ), mKeyboardFocus( NULL ), mDefaultKeyboardFocus( NULL ), mKeyboardFocusLostCallback( NULL ), - mTopView( NULL ), - mTopViewLostCallback( NULL ), + mTopCtrl( NULL ), mFocusWeight(0.f), mAppHasFocus(TRUE) // Macs don't seem to notify us that we've gotten focus, so default to true #ifdef _DEBUG , mMouseCaptorName("none") , mKeyboardFocusName("none") - , mTopViewName("none") + , mTopCtrlName("none") #endif { } @@ -65,7 +64,7 @@ void LLFocusMgr::releaseFocusIfNeeded( LLView* view ) { if( childHasMouseCapture( view ) ) { - setMouseCapture( NULL, NULL ); + setMouseCapture( NULL ); } if( childHasKeyboardFocus( view )) @@ -82,9 +81,9 @@ void LLFocusMgr::releaseFocusIfNeeded( LLView* view ) } } - if( childIsTopView( view ) ) + if( childIsTopCtrl( view ) ) { - setTopView( NULL, NULL ); + setTopCtrl( NULL ); } } @@ -127,13 +126,13 @@ void LLFocusMgr::setKeyboardFocus(LLUICtrl* new_focus, FocusLostCallback on_focu // If we've got a default keyboard focus, and the caller is // releasing keyboard focus, move to the default. - if (mDefaultKeyboardFocus != NULL && new_focus == NULL) + if (mDefaultKeyboardFocus != NULL && mKeyboardFocus == NULL) { mDefaultKeyboardFocus->setFocus(TRUE); } - LLView* focus_subtree = new_focus; - LLView* viewp = new_focus; + LLView* focus_subtree = mKeyboardFocus; + LLView* viewp = mKeyboardFocus; // find root-most focus root while(viewp) { @@ -147,13 +146,13 @@ void LLFocusMgr::setKeyboardFocus(LLUICtrl* new_focus, FocusLostCallback on_focu if (focus_subtree) { - mFocusHistory[focus_subtree->mViewHandle] = new_focus ? new_focus->mViewHandle : LLViewHandle::sDeadHandle; + mFocusHistory[focus_subtree->mViewHandle] = mKeyboardFocus ? mKeyboardFocus->mViewHandle : LLViewHandle::sDeadHandle; } } if (lock) { - mLockedView = new_focus; + mLockedView = mKeyboardFocus; mKeyboardLockedFocusLostCallback = on_focus_lost; } } @@ -217,16 +216,13 @@ void LLFocusMgr::removeKeyboardFocusWithoutCallback( LLView* focus ) } -void LLFocusMgr::setMouseCapture( LLMouseHandler* new_captor, void (*on_capture_lost)(LLMouseHandler* old_captor) ) +void LLFocusMgr::setMouseCapture( LLMouseHandler* new_captor ) { //if (mFocusLocked) //{ // return; //} - void (*old_callback)(LLMouseHandler*) = mMouseCaptureLostCallback; - mMouseCaptureLostCallback = on_capture_lost; - if( new_captor != mMouseCaptor ) { LLMouseHandler* old_captor = mMouseCaptor; @@ -249,9 +245,9 @@ void LLFocusMgr::setMouseCapture( LLMouseHandler* new_captor, void (*on_capture_ } */ - if( old_callback ) + if( old_captor ) { - old_callback( old_captor ); + old_captor->onMouseCaptureLost(); } #ifdef _DEBUG @@ -269,7 +265,6 @@ void LLFocusMgr::removeMouseCaptureWithoutCallback( LLMouseHandler* captor ) if( mMouseCaptor == captor ) { mMouseCaptor = NULL; - mMouseCaptureLostCallback = NULL; #ifdef _DEBUG mMouseCaptorName = "none"; #endif @@ -277,9 +272,9 @@ void LLFocusMgr::removeMouseCaptureWithoutCallback( LLMouseHandler* captor ) } -BOOL LLFocusMgr::childIsTopView( LLView* parent ) +BOOL LLFocusMgr::childIsTopCtrl( LLView* parent ) { - LLView* top_view = mTopView; + LLView* top_view = (LLView*)mTopCtrl; while( top_view ) { if( top_view == parent ) @@ -294,36 +289,25 @@ BOOL LLFocusMgr::childIsTopView( LLView* parent ) // set new_top = NULL to release top_view. -void LLFocusMgr::setTopView( LLView* new_top, void (*on_top_lost)(LLView* old_top) ) +void LLFocusMgr::setTopCtrl( LLUICtrl* new_top ) { - void (*old_callback)(LLView*) = mTopViewLostCallback; - mTopViewLostCallback = on_top_lost; - - if( new_top != mTopView ) + if( new_top != mTopCtrl ) { - LLView* old_top = mTopView; - mTopView = new_top; - if( old_callback ) - { - old_callback( old_top ); - } - - mTopView = new_top; + mTopCtrl = new_top; #ifdef _DEBUG - mTopViewName = new_top ? new_top->getName() : "none"; + mTopCtrlName = new_top ? new_top->getName() : "none"; #endif } } -void LLFocusMgr::removeTopViewWithoutCallback( LLView* top_view ) +void LLFocusMgr::removeTopCtrlWithoutCallback( LLUICtrl* top_view ) { - if( mTopView == top_view ) + if( mTopCtrl == top_view ) { - mTopView = NULL; - mTopViewLostCallback = NULL; + mTopCtrl = NULL; #ifdef _DEBUG - mTopViewName = "none"; + mTopCtrlName = "none"; #endif } } @@ -362,6 +346,12 @@ void LLFocusMgr::setAppHasFocus(BOOL focus) { triggerFocusFlash(); } + + // release focus from "top ctrl"s, which generally hides them + if (!focus && mTopCtrl && mTopCtrl->hasFocus()) + { + mTopCtrl->setFocus(FALSE); + } mAppHasFocus = focus; } diff --git a/linden/indra/llui/llfocusmgr.h b/linden/indra/llui/llfocusmgr.h index 5687b99..e189945 100644 --- a/linden/indra/llui/llfocusmgr.h +++ b/linden/indra/llui/llfocusmgr.h @@ -4,6 +4,7 @@ * * Copyright (c) 2002-2007, Linden Research, Inc. * + * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement @@ -46,7 +47,7 @@ public: ~LLFocusMgr(); // Mouse Captor - void setMouseCapture(LLMouseHandler* new_captor,void (*on_capture_lost)(LLMouseHandler* old_captor)); // new_captor = NULL to release the mouse. + void setMouseCapture(LLMouseHandler* new_captor); // new_captor = NULL to release the mouse. LLMouseHandler* getMouseCapture() { return mMouseCaptor; } void removeMouseCaptureWithoutCallback( LLMouseHandler* captor ); BOOL childHasMouseCapture( LLView* parent ); @@ -73,10 +74,10 @@ public: // Top View - void setTopView(LLView* new_top, void (*on_top_lost)(LLView* old_top)); - LLView* getTopView() const { return mTopView; } - void removeTopViewWithoutCallback( LLView* top_view ); - BOOL childIsTopView( LLView* parent ); + void setTopCtrl(LLUICtrl* new_top); + LLUICtrl* getTopCtrl() const { return mTopCtrl; } + void removeTopCtrlWithoutCallback( LLUICtrl* top_view ); + BOOL childIsTopCtrl( LLView* parent ); // All Three void releaseFocusIfNeeded( LLView* top_view ); @@ -89,7 +90,6 @@ protected: // Mouse Captor LLMouseHandler* mMouseCaptor; // Mouse events are premptively routed to this object - void (*mMouseCaptureLostCallback)(LLMouseHandler*); // The object to which mouse events are routed is called before another object takes its place // Keyboard Focus LLUICtrl* mKeyboardFocus; // Keyboard events are preemptively routed to this object @@ -97,8 +97,7 @@ protected: FocusLostCallback mKeyboardFocusLostCallback; // The object to which keyboard events are routed is called before another object takes its place // Top View - LLView* mTopView; - void (*mTopViewLostCallback)(LLView*); + LLUICtrl* mTopCtrl; LLFrameTimer mFocusTimer; F32 mFocusWeight; @@ -111,7 +110,7 @@ protected: #ifdef _DEBUG LLString mMouseCaptorName; LLString mKeyboardFocusName; - LLString mTopViewName; + LLString mTopCtrlName; #endif }; diff --git a/linden/indra/llui/llhtmlhelp.h b/linden/indra/llui/llhtmlhelp.h new file mode 100644 index 0000000..4b2a43a --- /dev/null +++ b/linden/indra/llui/llhtmlhelp.h @@ -0,0 +1,40 @@ +/** + * @file llhtmlhelp.h + * @brief HTML Help floater interface + * + * Copyright (c) 2006-2007, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlife.com/developers/opensource/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at http://secondlife.com/developers/opensource/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + */ + +#ifndef LL_LLHTMLHELP_H +#define LL_LLHTMLHELP_H + +class LLHtmlHelp +{ +public: + virtual ~LLHtmlHelp() {} + virtual void show(std::string start_url = "")=0; + virtual BOOL getFloaterOpened()=0; +}; + +#endif // LL_LLFLOATERHTMLHELP_H diff --git a/linden/indra/llui/lliconctrl.cpp b/linden/indra/llui/lliconctrl.cpp index 7dbd2bf..2d3071b 100644 --- a/linden/indra/llui/lliconctrl.cpp +++ b/linden/indra/llui/lliconctrl.cpp @@ -4,6 +4,7 @@ * * Copyright (c) 2001-2007, Linden Research, Inc. * + * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement diff --git a/linden/indra/llui/lliconctrl.h b/linden/indra/llui/lliconctrl.h index e0a2df0..8dbe6db 100644 --- a/linden/indra/llui/lliconctrl.h +++ b/linden/indra/llui/lliconctrl.h @@ -4,6 +4,7 @@ * * Copyright (c) 2001-2007, Linden Research, Inc. * + * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement diff --git a/linden/indra/llui/llkeywords.cpp b/linden/indra/llui/llkeywords.cpp index 05ec652..8997bd6 100644 --- a/linden/indra/llui/llkeywords.cpp +++ b/linden/indra/llui/llkeywords.cpp @@ -4,6 +4,7 @@ * * Copyright (c) 2000-2007, Linden Research, Inc. * + * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement diff --git a/linden/indra/llui/llkeywords.h b/linden/indra/llui/llkeywords.h index dc2745e..040df53 100644 --- a/linden/indra/llui/llkeywords.h +++ b/linden/indra/llui/llkeywords.h @@ -4,6 +4,7 @@ * * Copyright (c) 2001-2007, Linden Research, Inc. * + * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement diff --git a/linden/indra/llui/lllineeditor.cpp b/linden/indra/llui/lllineeditor.cpp index 1ca17fe..ec156ba 100644 --- a/linden/indra/llui/lllineeditor.cpp +++ b/linden/indra/llui/lllineeditor.cpp @@ -4,6 +4,7 @@ * * Copyright (c) 2001-2007, Linden Research, Inc. * + * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement @@ -115,7 +116,7 @@ LLLineEditor::LLLineEditor(const LLString& name, const LLRect& rect, S32 max_length_bytes, void (*commit_callback)(LLUICtrl* caller, void* user_data ), void (*keystroke_callback)(LLLineEditor* caller, void* user_data ), - void (*focus_lost_callback)(LLLineEditor* caller, void* user_data ), + void (*focus_lost_callback)(LLUICtrl* caller, void* user_data ), void* userdata, LLLinePrevalidateFunc prevalidate_func, LLViewBorder::EBevel border_bevel, @@ -132,7 +133,6 @@ LLLineEditor::LLLineEditor(const LLString& name, const LLRect& rect, mCommitOnFocusLost( TRUE ), mRevertOnEsc( TRUE ), mKeystrokeCallback( keystroke_callback ), - mFocusLostCallback( focus_lost_callback ), mIsSelecting( FALSE ), mSelectionStart( 0 ), mSelectionEnd( 0 ), @@ -166,6 +166,8 @@ LLLineEditor::LLLineEditor(const LLString& name, const LLRect& rect, mGLFont = LLFontGL::sSansSerifSmall; } + setFocusLostCallback(focus_lost_callback); + mMinHPixels = mBorderThickness + UI_LINEEDITOR_H_PAD + mBorderLeft; mMaxHPixels = mRect.getWidth() - mMinHPixels - mBorderThickness - mBorderRight; @@ -186,7 +188,6 @@ LLLineEditor::LLLineEditor(const LLString& name, const LLRect& rect, LLLineEditor::~LLLineEditor() { - mFocusLostCallback = NULL; mCommitOnFocusLost = FALSE; gFocusMgr.releaseFocusIfNeeded( this ); @@ -211,11 +212,8 @@ LLString LLLineEditor::getWidgetTag() const void LLLineEditor::onFocusLost() { - if( mFocusLostCallback ) - { - mFocusLostCallback( this, mCallbackUserData ); - } - + LLUICtrl::onFocusLost(); + if( mCommitOnFocusLost && mText.getString() != mPrevText) { onCommit(); @@ -502,7 +500,7 @@ BOOL LLLineEditor::handleMouseDown(S32 x, S32 y, MASK mask) startSelection(); } - gFocusMgr.setMouseCapture( this, &LLLineEditor::onMouseCaptureLost ); + gFocusMgr.setMouseCapture( this ); } // delay cursor flashing @@ -515,14 +513,14 @@ BOOL LLLineEditor::handleMouseDown(S32 x, S32 y, MASK mask) BOOL LLLineEditor::handleHover(S32 x, S32 y, MASK mask) { BOOL handled = FALSE; - if (gFocusMgr.getMouseCapture() != this && (x < mBorderLeft || x > (mRect.getWidth() - mBorderRight))) + if (!hasMouseCapture() && (x < mBorderLeft || x > (mRect.getWidth() - mBorderRight))) { return LLUICtrl::handleHover(x, y, mask); } if( getVisible() ) { - if( (gFocusMgr.getMouseCapture() == this) && mIsSelecting ) + if( (hasMouseCapture()) && mIsSelecting ) { if (x != mLastSelectionX || y != mLastSelectionY) { @@ -580,9 +578,9 @@ BOOL LLLineEditor::handleMouseUp(S32 x, S32 y, MASK mask) { BOOL handled = FALSE; - if( gFocusMgr.getMouseCapture() == this ) + if( hasMouseCapture() ) { - gFocusMgr.setMouseCapture( NULL, NULL ); + gFocusMgr.setMouseCapture( NULL ); handled = TRUE; } @@ -1916,11 +1914,9 @@ BOOL LLLineEditor::prevalidateASCII(const LLWString &str) return rv; } -//static -void LLLineEditor::onMouseCaptureLost( LLMouseHandler* old_captor ) +void LLLineEditor::onMouseCaptureLost() { - LLLineEditor* self = (LLLineEditor*) old_captor; - self->endSelection(); + endSelection(); } @@ -1935,11 +1931,6 @@ void LLLineEditor::setKeystrokeCallback(void (*keystroke_callback)(LLLineEditor* mKeystrokeCallback = keystroke_callback; } -void LLLineEditor::setFocusLostCallback(void (*keystroke_callback)(LLLineEditor* caller, void* user_data)) -{ - mFocusLostCallback = keystroke_callback; -} - // virtual LLXMLNodePtr LLLineEditor::getXML(bool save_children) const { diff --git a/linden/indra/llui/lllineeditor.h b/linden/indra/llui/lllineeditor.h index 427860d..65c75ab 100644 --- a/linden/indra/llui/lllineeditor.h +++ b/linden/indra/llui/lllineeditor.h @@ -4,6 +4,7 @@ * * Copyright (c) 2001-2007, Linden Research, Inc. * + * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement @@ -70,7 +71,7 @@ public: S32 max_length_bytes = 254, void (*commit_callback)(LLUICtrl* caller, void* user_data) = NULL, void (*keystroke_callback)(LLLineEditor* caller, void* user_data) = NULL, - void (*focus_lost_callback)(LLLineEditor* caller, void* user_data) = NULL, + void (*focus_lost_callback)(LLUICtrl* caller, void* user_data) = NULL, void* userdata = NULL, LLLinePrevalidateFunc prevalidate_func = NULL, LLViewBorder::EBevel border_bevel = LLViewBorder::BEVEL_IN, @@ -91,6 +92,7 @@ public: /*virtual*/ BOOL handleDoubleClick(S32 x,S32 y,MASK mask); /*virtual*/ BOOL handleKeyHere(KEY key, MASK mask, BOOL called_from_parent ); /*virtual*/ BOOL handleUnicodeCharHere(llwchar uni_char, BOOL called_from_parent); + /*virtual*/ void onMouseCaptureLost(); // LLEditMenuHandler overrides virtual void cut(); @@ -185,7 +187,6 @@ public: void setSelectAllonFocusReceived(BOOL b); void setKeystrokeCallback(void (*keystroke_callback)(LLLineEditor* caller, void* user_data)); - void setFocusLostCallback(void (*keystroke_callback)(LLLineEditor* caller, void* user_data)); void setMaxTextLength(S32 max_text_length); void setBorderWidth(S32 left, S32 right); @@ -205,8 +206,6 @@ public: static BOOL postvalidateFloat(const LLString &str); - static void onMouseCaptureLost( LLMouseHandler* old_captor ); - protected: void removeChar(); void addChar(const llwchar c); @@ -241,7 +240,6 @@ protected: BOOL mRevertOnEsc; void (*mKeystrokeCallback)( LLLineEditor* caller, void* userdata ); - void (*mFocusLostCallback)( LLLineEditor* caller, void* userdata ); BOOL mIsSelecting; // Selection for clipboard operations S32 mSelectionStart; diff --git a/linden/indra/llui/llmemberlistener.h b/linden/indra/llui/llmemberlistener.h index 93bcff5..92e7278 100755 --- a/linden/indra/llui/llmemberlistener.h +++ b/linden/indra/llui/llmemberlistener.h @@ -4,6 +4,7 @@ * * Copyright (c) 2006-2007, Linden Research, Inc. * + * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement diff --git a/linden/indra/llui/llmenugl.cpp b/linden/indra/llui/llmenugl.cpp index 1748956..1920aac 100644 --- a/linden/indra/llui/llmenugl.cpp +++ b/linden/indra/llui/llmenugl.cpp @@ -4,6 +4,7 @@ * * Copyright (c) 2001-2007, Linden Research, Inc. * + * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement @@ -3254,6 +3255,7 @@ LLPieMenu::LLPieMenu(const LLString& name, const LLString& label) mUseInfiniteRadius(FALSE), mHoverItem(NULL), mHoverThisFrame(FALSE), + mHoveredAnyItem(FALSE), mOuterRingAlpha(1.f), mCurRadius(0.f), mRightMouseDown(FALSE) @@ -3268,6 +3270,7 @@ LLPieMenu::LLPieMenu(const LLString& name) mUseInfiniteRadius(FALSE), mHoverItem(NULL), mHoverThisFrame(FALSE), + mHoveredAnyItem(FALSE), mOuterRingAlpha(1.f), mCurRadius(0.f), mRightMouseDown(FALSE) @@ -3338,12 +3341,12 @@ BOOL LLPieMenu::handleHover( S32 x, S32 y, MASK mask ) // release mouse capture after short period of visibility if we're using a finite boundary // so that right click outside of boundary will trigger new pie menu - if (gFocusMgr.getMouseCapture() == this && + if (hasMouseCapture() && !mRightMouseDown && mShrinkBorderTimer.getStarted() && mShrinkBorderTimer.getElapsedTimeF32() >= PIE_SHRINK_TIME) { - gFocusMgr.setMouseCapture(NULL, NULL); + gFocusMgr.setMouseCapture(NULL); mUseInfiniteRadius = FALSE; } @@ -3395,6 +3398,7 @@ BOOL LLPieMenu::handleHover( S32 x, S32 y, MASK mask ) break; } } + mHoveredAnyItem = TRUE; } else { @@ -3456,7 +3460,7 @@ BOOL LLPieMenu::handleRightMouseDown(S32 x, S32 y, MASK mask) if (clicked_in_pie) { // capture mouse cursor as if on initial menu show - gFocusMgr.setMouseCapture(this, NULL); + gFocusMgr.setMouseCapture(this); mShrinkBorderTimer.stop(); mUseInfiniteRadius = TRUE; handled = TRUE; @@ -3482,11 +3486,22 @@ BOOL LLPieMenu::handleRightMouseUp( S32 x, S32 y, MASK mask ) mShrinkBorderTimer.getElapsedTimeF32() > PIE_SHRINK_TIME) { mUseInfiniteRadius = FALSE; - gFocusMgr.setMouseCapture(NULL, NULL); + gFocusMgr.setMouseCapture(NULL); } + S32 delta_x = x /*+ mShiftHoriz*/ - getLocalRect().getCenterX(); + S32 delta_y = y /*+ mShiftVert*/ - getLocalRect().getCenterY(); + if (!mHoveredAnyItem && !mFirstMouseDown && (delta_x * delta_x) + (delta_y * delta_y) < PIE_CENTER_SIZE * PIE_CENTER_SIZE) + { + // user released right mouse button in middle of pie, interpret this as closing the menu + sMenuContainer->hideMenus(); + return TRUE; + } + + BOOL result = handleMouseUp( x, y, mask ); mRightMouseDown = FALSE; + mHoveredAnyItem = FALSE; return result; } @@ -3893,6 +3908,8 @@ void LLPieMenu::show(S32 x, S32 y, BOOL mouse_down) mRightMouseDown = mouse_down; mFirstMouseDown = mouse_down; mUseInfiniteRadius = TRUE; + mHoveredAnyItem = FALSE; + if (!mFirstMouseDown) { make_ui_sound("UISndPieMenuAppear"); @@ -3902,7 +3919,7 @@ void LLPieMenu::show(S32 x, S32 y, BOOL mouse_down) // we want all mouse events in case user does quick right click again off of pie menu // rectangle, to support gestural menu traversal - gFocusMgr.setMouseCapture(this, NULL); + gFocusMgr.setMouseCapture(this); if (mouse_down) { @@ -3929,10 +3946,11 @@ void LLPieMenu::hide(BOOL item_selected) mFirstMouseDown = FALSE; mRightMouseDown = FALSE; mUseInfiniteRadius = FALSE; + mHoveredAnyItem = FALSE; LLView::setVisible(FALSE); - gFocusMgr.setMouseCapture(NULL, NULL); + gFocusMgr.setMouseCapture(NULL); } ///============================================================================ @@ -4529,6 +4547,7 @@ void LLTearOffMenu::onFocusLost() { // remove highlight from parent item and our own menu mMenu->clearHoverItem(); + LLFloater::onFocusLost(); } BOOL LLTearOffMenu::handleUnicodeChar(llwchar uni_char, BOOL called_from_parent) diff --git a/linden/indra/llui/llmenugl.h b/linden/indra/llui/llmenugl.h index c4a0043..6051a26 100644 --- a/linden/indra/llui/llmenugl.h +++ b/linden/indra/llui/llmenugl.h @@ -4,6 +4,7 @@ * * Copyright (c) 2001-2007, Linden Research, Inc. * + * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement @@ -691,6 +692,7 @@ private: BOOL mUseInfiniteRadius; // allow picking pie menu items anywhere outside of center circle LLMenuItemGL* mHoverItem; BOOL mHoverThisFrame; + BOOL mHoveredAnyItem; LLFrameTimer mShrinkBorderTimer; F32 mOuterRingAlpha; // for rendering pie menus as both bounded and unbounded F32 mCurRadius; diff --git a/linden/indra/llui/llmodaldialog.cpp b/linden/indra/llui/llmodaldialog.cpp index c875e7c..788dead 100644 --- a/linden/indra/llui/llmodaldialog.cpp +++ b/linden/indra/llui/llmodaldialog.cpp @@ -4,6 +4,7 @@ * * Copyright (c) 2002-2007, Linden Research, Inc. * + * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement @@ -84,8 +85,8 @@ void LLModalDialog::startModal() } // This is a modal dialog. It sucks up all mouse and keyboard operations. - gFocusMgr.setMouseCapture( this, NULL ); - gFocusMgr.setTopView( this, NULL ); + gFocusMgr.setMouseCapture( this ); + gFocusMgr.setTopCtrl( this ); setFocus(TRUE); sModalStack.push_front( this ); @@ -126,10 +127,10 @@ void LLModalDialog::setVisible( BOOL visible ) if( visible ) { // This is a modal dialog. It sucks up all mouse and keyboard operations. - gFocusMgr.setMouseCapture( this, NULL ); + gFocusMgr.setMouseCapture( this ); // The dialog view is a root view - gFocusMgr.setTopView( this, NULL ); + gFocusMgr.setTopCtrl( this ); setFocus( TRUE ); } else @@ -241,9 +242,9 @@ void LLModalDialog::draw() if (mModal) { // If we've lost focus to a non-child, get it back ASAP. - if( gFocusMgr.getTopView() != this ) + if( gFocusMgr.getTopCtrl() != this ) { - gFocusMgr.setTopView( this, NULL); + gFocusMgr.setTopCtrl( this ); } if( !gFocusMgr.childHasKeyboardFocus( this ) ) @@ -253,7 +254,7 @@ void LLModalDialog::draw() if( !gFocusMgr.childHasMouseCapture( this ) ) { - gFocusMgr.setMouseCapture( this, NULL ); + gFocusMgr.setMouseCapture( this ); } } } @@ -278,7 +279,7 @@ void LLModalDialog::onAppFocusLost() LLModalDialog* instance = LLModalDialog::sModalStack.front(); if( gFocusMgr.childHasMouseCapture( instance ) ) { - gFocusMgr.setMouseCapture( NULL, NULL ); + gFocusMgr.setMouseCapture( NULL ); } if( gFocusMgr.childHasKeyboardFocus( instance ) ) @@ -296,9 +297,9 @@ void LLModalDialog::onAppFocusGained() LLModalDialog* instance = LLModalDialog::sModalStack.front(); // This is a modal dialog. It sucks up all mouse and keyboard operations. - gFocusMgr.setMouseCapture( instance, NULL ); + gFocusMgr.setMouseCapture( instance ); instance->setFocus(TRUE); - gFocusMgr.setTopView( instance, NULL ); + gFocusMgr.setTopCtrl( instance ); instance->centerOnScreen(); } diff --git a/linden/indra/llui/llmodaldialog.h b/linden/indra/llui/llmodaldialog.h index 2fc101c..c2564af 100644 --- a/linden/indra/llui/llmodaldialog.h +++ b/linden/indra/llui/llmodaldialog.h @@ -4,6 +4,7 @@ * * Copyright (c) 2002-2007, Linden Research, Inc. * + * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement diff --git a/linden/indra/llui/llpanel.cpp b/linden/indra/llui/llpanel.cpp index 8d3fba6..9e444c1 100644 --- a/linden/indra/llui/llpanel.cpp +++ b/linden/indra/llui/llpanel.cpp @@ -4,6 +4,7 @@ * * Copyright (c) 2001-2007, Linden Research, Inc. * + * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement diff --git a/linden/indra/llui/llpanel.h b/linden/indra/llui/llpanel.h index d9bd19c..9da942e 100644 --- a/linden/indra/llui/llpanel.h +++ b/linden/indra/llui/llpanel.h @@ -5,6 +5,7 @@ * * Copyright (c) 2001-2007, Linden Research, Inc. * + * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement diff --git a/linden/indra/llui/llradiogroup.cpp b/linden/indra/llui/llradiogroup.cpp index f52faf9..eda54b1 100644 --- a/linden/indra/llui/llradiogroup.cpp +++ b/linden/indra/llui/llradiogroup.cpp @@ -4,6 +4,7 @@ * * Copyright (c) 2001-2007, Linden Research, Inc. * + * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement diff --git a/linden/indra/llui/llradiogroup.h b/linden/indra/llui/llradiogroup.h index 9324113..0cd5901 100644 --- a/linden/indra/llui/llradiogroup.h +++ b/linden/indra/llui/llradiogroup.h @@ -4,6 +4,7 @@ * * Copyright (c) 2001-2007, Linden Research, Inc. * + * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement diff --git a/linden/indra/llui/llresizebar.cpp b/linden/indra/llui/llresizebar.cpp index 1298b75..79127a8 100644 --- a/linden/indra/llui/llresizebar.cpp +++ b/linden/indra/llui/llresizebar.cpp @@ -4,6 +4,7 @@ * * Copyright (c) 2001-2007, Linden Research, Inc. * + * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement @@ -40,8 +41,8 @@ LLResizeBar::LLResizeBar( const LLString& name, const LLRect& rect, S32 min_width, S32 min_height, Side side ) : LLView( name, rect, TRUE ), - mDragStartScreenX( 0 ), - mDragStartScreenY( 0 ), + mDragLastScreenX( 0 ), + mDragLastScreenY( 0 ), mLastMouseScreenX( 0 ), mLastMouseScreenY( 0 ), mMinWidth( min_width ), @@ -74,6 +75,8 @@ LLResizeBar::LLResizeBar( const LLString& name, const LLRect& rect, S32 min_widt default: break; } + // this is just a decorator + setSaveToXML(FALSE); } @@ -83,12 +86,11 @@ BOOL LLResizeBar::handleMouseDown(S32 x, S32 y, MASK mask) { // Route future Mouse messages here preemptively. (Release on mouse up.) // No handler needed for focus lost since this clas has no state that depends on it. - gFocusMgr.setMouseCapture( this, NULL ); + gFocusMgr.setMouseCapture( this ); - //localPointToScreen(x, y, &mDragStartScreenX, &mDragStartScreenX); - localPointToOtherView(x, y, &mDragStartScreenX, &mDragStartScreenY, getParent()->getParent()); - mLastMouseScreenX = mDragStartScreenX; - mLastMouseScreenY = mDragStartScreenY; + localPointToScreen(x, y, &mDragLastScreenX, &mDragLastScreenY); + mLastMouseScreenX = mDragLastScreenX; + mLastMouseScreenY = mDragLastScreenY; } return TRUE; @@ -99,10 +101,10 @@ BOOL LLResizeBar::handleMouseUp(S32 x, S32 y, MASK mask) { BOOL handled = FALSE; - if( gFocusMgr.getMouseCapture() == this ) + if( hasMouseCapture() ) { // Release the mouse - gFocusMgr.setMouseCapture( NULL, NULL ); + gFocusMgr.setMouseCapture( NULL ); handled = TRUE; } else @@ -127,74 +129,73 @@ BOOL LLResizeBar::handleHover(S32 x, S32 y, MASK mask) BOOL handled = FALSE; // We only handle the click if the click both started and ended within us - if( gFocusMgr.getMouseCapture() == this ) + if( hasMouseCapture() ) { - // *NOTE: this, of course, is fragile - LLView* floater_view = getParent()->getParent(); - S32 floater_view_x; - S32 floater_view_y; - localPointToOtherView(x, y, &floater_view_x, &floater_view_y, floater_view); + S32 screen_x; + S32 screen_y; + localPointToScreen(x, y, &screen_x, &screen_y); - S32 delta_x = floater_view_x - mDragStartScreenX; - S32 delta_y = floater_view_y - mDragStartScreenY; + S32 delta_x = screen_x - mDragLastScreenX; + S32 delta_y = screen_y - mDragLastScreenY; LLCoordGL mouse_dir; // use hysteresis on mouse motion to preserve user intent when mouse stops moving - mouse_dir.mX = (floater_view_x == mLastMouseScreenX) ? mLastMouseDir.mX : floater_view_x - mLastMouseScreenX; - mouse_dir.mY = (floater_view_y == mLastMouseScreenY) ? mLastMouseDir.mY : floater_view_y - mLastMouseScreenY; + mouse_dir.mX = (screen_x == mLastMouseScreenX) ? mLastMouseDir.mX : screen_x - mLastMouseScreenX; + mouse_dir.mY = (screen_y == mLastMouseScreenY) ? mLastMouseDir.mY : screen_y - mLastMouseScreenY; mLastMouseDir = mouse_dir; - mLastMouseScreenX = floater_view_x; - mLastMouseScreenY = floater_view_y; + mLastMouseScreenX = screen_x; + mLastMouseScreenY = screen_y; // Make sure the mouse in still over the application. We don't want to make the parent // so big that we can't see the resize handle any more. - LLRect valid_rect = floater_view->getRect(); - LLView* parentView = getParent(); - if( valid_rect.localPointInRect( floater_view_x, floater_view_y ) && parentView ) + LLRect valid_rect = getRootView()->getRect(); + LLView* resizing_view = getParent(); + + if( valid_rect.localPointInRect( screen_x, screen_y ) && resizing_view ) { // Resize the parent - LLRect parent_rect = parentView->getRect(); - LLRect scaled_rect = parent_rect; + LLRect orig_rect = resizing_view->getRect(); + LLRect scaled_rect = orig_rect; - S32 new_width = parent_rect.getWidth(); - S32 new_height = parent_rect.getHeight(); + S32 new_width = orig_rect.getWidth(); + S32 new_height = orig_rect.getHeight(); switch( mSide ) { case LEFT: - new_width = parent_rect.getWidth() - delta_x; + new_width = orig_rect.getWidth() - delta_x; if( new_width < mMinWidth ) { new_width = mMinWidth; - delta_x = parent_rect.getWidth() - mMinWidth; + delta_x = orig_rect.getWidth() - mMinWidth; } scaled_rect.translate(delta_x, 0); break; case TOP: - new_height = parent_rect.getHeight() + delta_y; + new_height = orig_rect.getHeight() + delta_y; if( new_height < mMinHeight ) { new_height = mMinHeight; - delta_y = mMinHeight - parent_rect.getHeight(); + delta_y = mMinHeight - orig_rect.getHeight(); } break; case RIGHT: - new_width = parent_rect.getWidth() + delta_x; + new_width = orig_rect.getWidth() + delta_x; if( new_width < mMinWidth ) { new_width = mMinWidth; - delta_x = mMinWidth - parent_rect.getWidth(); + delta_x = mMinWidth - orig_rect.getWidth(); } break; case BOTTOM: - new_height = parent_rect.getHeight() - delta_y; + new_height = orig_rect.getHeight() - delta_y; if( new_height < mMinHeight ) { new_height = mMinHeight; - delta_y = parent_rect.getHeight() - mMinHeight; + delta_y = orig_rect.getHeight() - mMinHeight; } scaled_rect.translate(0, delta_y); break; @@ -202,56 +203,59 @@ BOOL LLResizeBar::handleHover(S32 x, S32 y, MASK mask) scaled_rect.mTop = scaled_rect.mBottom + new_height; scaled_rect.mRight = scaled_rect.mLeft + new_width; - parentView->setRect(scaled_rect); - - S32 snap_delta_x = 0; - S32 snap_delta_y = 0; + resizing_view->setRect(scaled_rect); LLView* snap_view = NULL; switch( mSide ) { case LEFT: - snap_view = parentView->findSnapEdge(snap_delta_x, mouse_dir, SNAP_LEFT, SNAP_PARENT_AND_SIBLINGS, LLUI::sConfigGroup->getS32("SnapMargin")); - snap_delta_x -= scaled_rect.mLeft; - scaled_rect.mLeft += snap_delta_x; + snap_view = resizing_view->findSnapEdge(scaled_rect.mLeft, mouse_dir, SNAP_LEFT, SNAP_PARENT_AND_SIBLINGS, LLUI::sConfigGroup->getS32("SnapMargin")); break; case TOP: - snap_view = parentView->findSnapEdge(snap_delta_y, mouse_dir, SNAP_TOP, SNAP_PARENT_AND_SIBLINGS, LLUI::sConfigGroup->getS32("SnapMargin")); - snap_delta_y -= scaled_rect.mTop; - scaled_rect.mTop += snap_delta_y; + snap_view = resizing_view->findSnapEdge(scaled_rect.mTop, mouse_dir, SNAP_TOP, SNAP_PARENT_AND_SIBLINGS, LLUI::sConfigGroup->getS32("SnapMargin")); break; case RIGHT: - snap_view = parentView->findSnapEdge(snap_delta_x, mouse_dir, SNAP_RIGHT, SNAP_PARENT_AND_SIBLINGS, LLUI::sConfigGroup->getS32("SnapMargin")); - snap_delta_x -= scaled_rect.mRight; - scaled_rect.mRight += snap_delta_x; + snap_view = resizing_view->findSnapEdge(scaled_rect.mRight, mouse_dir, SNAP_RIGHT, SNAP_PARENT_AND_SIBLINGS, LLUI::sConfigGroup->getS32("SnapMargin")); break; case BOTTOM: - snap_view = parentView->findSnapEdge(snap_delta_y, mouse_dir, SNAP_BOTTOM, SNAP_PARENT_AND_SIBLINGS, LLUI::sConfigGroup->getS32("SnapMargin")); - snap_delta_y -= scaled_rect.mBottom; - scaled_rect.mBottom += snap_delta_y; + snap_view = resizing_view->findSnapEdge(scaled_rect.mBottom, mouse_dir, SNAP_BOTTOM, SNAP_PARENT_AND_SIBLINGS, LLUI::sConfigGroup->getS32("SnapMargin")); break; } - parentView->snappedTo(snap_view); + // register "snap" behavior with snapped view + resizing_view->snappedTo(snap_view); - parentView->setRect(parent_rect); + // restore original rectangle so the appropriate changes are detected + resizing_view->setRect(orig_rect); + // change view shape as user operation + resizing_view->userSetShape(scaled_rect); - parentView->reshape(scaled_rect.getWidth(), scaled_rect.getHeight(), FALSE); - parentView->translate(scaled_rect.mLeft - parentView->getRect().mLeft, scaled_rect.mBottom - parentView->getRect().mBottom); - - floater_view_x = mDragStartScreenX + delta_x; - floater_view_y = mDragStartScreenY + delta_y; - mDragStartScreenX = floater_view_x + snap_delta_x; - mDragStartScreenY = floater_view_y + snap_delta_y; + // update last valid mouse cursor position based on resized view's actual size + LLRect new_rect = resizing_view->getRect(); + switch(mSide) + { + case LEFT: + mDragLastScreenX += new_rect.mLeft - orig_rect.mLeft; + break; + case RIGHT: + mDragLastScreenX += new_rect.mRight - orig_rect.mRight; + break; + case TOP: + mDragLastScreenY += new_rect.mTop - orig_rect.mTop; + break; + case BOTTOM: + mDragLastScreenY += new_rect.mBottom- orig_rect.mBottom; + break; + default: + break; + } } - lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << " (active)" << llendl; handled = TRUE; } else { - lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << " (inactive)" << llendl; handled = TRUE; } diff --git a/linden/indra/llui/llresizebar.h b/linden/indra/llui/llresizebar.h index 5862ffc..e1fc0f9 100644 --- a/linden/indra/llui/llresizebar.h +++ b/linden/indra/llui/llresizebar.h @@ -4,6 +4,7 @@ * * Copyright (c) 2001-2007, Linden Research, Inc. * + * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement @@ -49,8 +50,8 @@ public: void setResizeLimits( S32 min_width, S32 min_height ) { mMinWidth = min_width; mMinHeight = min_height; } protected: - S32 mDragStartScreenX; - S32 mDragStartScreenY; + S32 mDragLastScreenX; + S32 mDragLastScreenY; S32 mLastMouseScreenX; S32 mLastMouseScreenY; LLCoordGL mLastMouseDir; diff --git a/linden/indra/llui/llresizehandle.cpp b/linden/indra/llui/llresizehandle.cpp index fc15bcc..d9b8fac 100644 --- a/linden/indra/llui/llresizehandle.cpp +++ b/linden/indra/llui/llresizehandle.cpp @@ -4,6 +4,7 @@ * * Copyright (c) 2001-2007, Linden Research, Inc. * + * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement @@ -42,8 +43,8 @@ const S32 RESIZE_BORDER_WIDTH = 3; LLResizeHandle::LLResizeHandle( const LLString& name, const LLRect& rect, S32 min_width, S32 min_height, ECorner corner ) : LLView( name, rect, TRUE ), - mDragStartScreenX( 0 ), - mDragStartScreenY( 0 ), + mDragLastScreenX( 0 ), + mDragLastScreenY( 0 ), mLastMouseScreenX( 0 ), mLastMouseScreenY( 0 ), mImage( NULL ), @@ -66,6 +67,9 @@ LLResizeHandle::LLResizeHandle( const LLString& name, const LLRect& rect, S32 mi case RIGHT_TOP: setFollows( FOLLOWS_RIGHT | FOLLOWS_TOP ); break; case RIGHT_BOTTOM: setFollows( FOLLOWS_RIGHT | FOLLOWS_BOTTOM ); break; } + + // decorator object, don't serialize + setSaveToXML(FALSE); } EWidgetType LLResizeHandle::getWidgetType() const @@ -88,11 +92,11 @@ BOOL LLResizeHandle::handleMouseDown(S32 x, S32 y, MASK mask) { // Route future Mouse messages here preemptively. (Release on mouse up.) // No handler needed for focus lost since this clas has no state that depends on it. - gFocusMgr.setMouseCapture( this, NULL ); + gFocusMgr.setMouseCapture( this ); - localPointToScreen(x, y, &mDragStartScreenX, &mDragStartScreenY); - mLastMouseScreenX = mDragStartScreenX; - mLastMouseScreenY = mDragStartScreenY; + localPointToScreen(x, y, &mDragLastScreenX, &mDragLastScreenY); + mLastMouseScreenX = mDragLastScreenX; + mLastMouseScreenY = mDragLastScreenY; } } @@ -104,10 +108,10 @@ BOOL LLResizeHandle::handleMouseUp(S32 x, S32 y, MASK mask) { BOOL handled = FALSE; - if( gFocusMgr.getMouseCapture() == this ) + if( hasMouseCapture() ) { // Release the mouse - gFocusMgr.setMouseCapture( NULL, NULL ); + gFocusMgr.setMouseCapture( NULL ); handled = TRUE; } else @@ -125,7 +129,7 @@ BOOL LLResizeHandle::handleHover(S32 x, S32 y, MASK mask) BOOL handled = FALSE; // We only handle the click if the click both started and ended within us - if( gFocusMgr.getMouseCapture() == this ) + if( hasMouseCapture() ) { // Make sure the mouse in still over the application. We don't want to make the parent // so big that we can't see the resize handle any more. @@ -133,18 +137,18 @@ BOOL LLResizeHandle::handleHover(S32 x, S32 y, MASK mask) S32 screen_x; S32 screen_y; localPointToScreen(x, y, &screen_x, &screen_y); - const LLRect& valid_rect = gFloaterView->getRect(); // Assumes that the parent is a floater. + const LLRect valid_rect = getRootView()->getRect(); screen_x = llclamp( screen_x, valid_rect.mLeft, valid_rect.mRight ); screen_y = llclamp( screen_y, valid_rect.mBottom, valid_rect.mTop ); - LLView* parentView = getParent(); - if( parentView ) + LLView* resizing_view = getParent(); + if( resizing_view ) { // Resize the parent - LLRect parent_rect = parentView->getRect(); - LLRect scaled_rect = parent_rect; - S32 delta_x = screen_x - mDragStartScreenX; - S32 delta_y = screen_y - mDragStartScreenY; + LLRect orig_rect = resizing_view->getRect(); + LLRect scaled_rect = orig_rect; + S32 delta_x = screen_x - mDragLastScreenX; + S32 delta_y = screen_y - mDragLastScreenY; LLCoordGL mouse_dir; // use hysteresis on mouse motion to preserve user intent when mouse stops moving mouse_dir.mX = (screen_x == mLastMouseScreenX) ? mLastMouseDir.mX : screen_x - mLastMouseScreenX; @@ -175,18 +179,18 @@ BOOL LLResizeHandle::handleHover(S32 x, S32 y, MASK mask) break; } - S32 new_width = parent_rect.getWidth() + x_multiple * delta_x; + S32 new_width = orig_rect.getWidth() + x_multiple * delta_x; if( new_width < mMinWidth ) { new_width = mMinWidth; - delta_x = x_multiple * (mMinWidth - parent_rect.getWidth()); + delta_x = x_multiple * (mMinWidth - orig_rect.getWidth()); } - S32 new_height = parent_rect.getHeight() + y_multiple * delta_y; + S32 new_height = orig_rect.getHeight() + y_multiple * delta_y; if( new_height < mMinHeight ) { new_height = mMinHeight; - delta_y = y_multiple * (mMinHeight - parent_rect.getHeight()); + delta_y = y_multiple * (mMinHeight - orig_rect.getHeight()); } switch( mCorner ) @@ -207,10 +211,7 @@ BOOL LLResizeHandle::handleHover(S32 x, S32 y, MASK mask) // temporarily set new parent rect scaled_rect.mRight = scaled_rect.mLeft + new_width; scaled_rect.mTop = scaled_rect.mBottom + new_height; - parentView->setRect(scaled_rect); - - S32 snap_delta_x = 0; - S32 snap_delta_y = 0; + resizing_view->setRect(scaled_rect); LLView* snap_view = NULL; LLView* test_view = NULL; @@ -219,77 +220,78 @@ BOOL LLResizeHandle::handleHover(S32 x, S32 y, MASK mask) switch(mCorner) { case LEFT_TOP: - snap_view = parentView->findSnapEdge(snap_delta_x, mouse_dir, SNAP_LEFT, SNAP_PARENT_AND_SIBLINGS, LLUI::sConfigGroup->getS32("SnapMargin")); - snap_delta_x -= scaled_rect.mLeft; - test_view = parentView->findSnapEdge(snap_delta_y, mouse_dir, SNAP_TOP, SNAP_PARENT_AND_SIBLINGS, LLUI::sConfigGroup->getS32("SnapMargin")); - snap_delta_y -= scaled_rect.mTop; + snap_view = resizing_view->findSnapEdge(scaled_rect.mLeft, mouse_dir, SNAP_LEFT, SNAP_PARENT_AND_SIBLINGS, LLUI::sConfigGroup->getS32("SnapMargin")); + test_view = resizing_view->findSnapEdge(scaled_rect.mTop, mouse_dir, SNAP_TOP, SNAP_PARENT_AND_SIBLINGS, LLUI::sConfigGroup->getS32("SnapMargin")); if (!snap_view) { snap_view = test_view; } - scaled_rect.mLeft += snap_delta_x; - scaled_rect.mTop += snap_delta_y; break; case LEFT_BOTTOM: - snap_view = parentView->findSnapEdge(snap_delta_x, mouse_dir, SNAP_LEFT, SNAP_PARENT_AND_SIBLINGS, LLUI::sConfigGroup->getS32("SnapMargin")); - snap_delta_x -= scaled_rect.mLeft; - test_view = parentView->findSnapEdge(snap_delta_y, mouse_dir, SNAP_BOTTOM, SNAP_PARENT_AND_SIBLINGS, LLUI::sConfigGroup->getS32("SnapMargin")); - snap_delta_y -= scaled_rect.mBottom; + snap_view = resizing_view->findSnapEdge(scaled_rect.mLeft, mouse_dir, SNAP_LEFT, SNAP_PARENT_AND_SIBLINGS, LLUI::sConfigGroup->getS32("SnapMargin")); + test_view = resizing_view->findSnapEdge(scaled_rect.mBottom, mouse_dir, SNAP_BOTTOM, SNAP_PARENT_AND_SIBLINGS, LLUI::sConfigGroup->getS32("SnapMargin")); if (!snap_view) { snap_view = test_view; } - scaled_rect.mLeft += snap_delta_x; - scaled_rect.mBottom += snap_delta_y; break; case RIGHT_TOP: - snap_view = parentView->findSnapEdge(snap_delta_x, mouse_dir, SNAP_RIGHT, SNAP_PARENT_AND_SIBLINGS, LLUI::sConfigGroup->getS32("SnapMargin")); - snap_delta_x -= scaled_rect.mRight; - test_view = parentView->findSnapEdge(snap_delta_y, mouse_dir, SNAP_TOP, SNAP_PARENT_AND_SIBLINGS, LLUI::sConfigGroup->getS32("SnapMargin")); - snap_delta_y -= scaled_rect.mTop; + snap_view = resizing_view->findSnapEdge(scaled_rect.mRight, mouse_dir, SNAP_RIGHT, SNAP_PARENT_AND_SIBLINGS, LLUI::sConfigGroup->getS32("SnapMargin")); + test_view = resizing_view->findSnapEdge(scaled_rect.mTop, mouse_dir, SNAP_TOP, SNAP_PARENT_AND_SIBLINGS, LLUI::sConfigGroup->getS32("SnapMargin")); if (!snap_view) { snap_view = test_view; } - scaled_rect.mRight += snap_delta_x; - scaled_rect.mTop += snap_delta_y; break; case RIGHT_BOTTOM: - snap_view = parentView->findSnapEdge(snap_delta_x, mouse_dir, SNAP_RIGHT, SNAP_PARENT_AND_SIBLINGS, LLUI::sConfigGroup->getS32("SnapMargin")); - snap_delta_x -= scaled_rect.mRight; - test_view = parentView->findSnapEdge(snap_delta_y, mouse_dir, SNAP_BOTTOM, SNAP_PARENT_AND_SIBLINGS, LLUI::sConfigGroup->getS32("SnapMargin")); - snap_delta_y -= scaled_rect.mBottom; + snap_view = resizing_view->findSnapEdge(scaled_rect.mRight, mouse_dir, SNAP_RIGHT, SNAP_PARENT_AND_SIBLINGS, LLUI::sConfigGroup->getS32("SnapMargin")); + test_view = resizing_view->findSnapEdge(scaled_rect.mBottom, mouse_dir, SNAP_BOTTOM, SNAP_PARENT_AND_SIBLINGS, LLUI::sConfigGroup->getS32("SnapMargin")); if (!snap_view) { snap_view = test_view; } - scaled_rect.mRight += snap_delta_x; - scaled_rect.mBottom += snap_delta_y; break; } - parentView->snappedTo(snap_view); + // register "snap" behavior with snapped view + resizing_view->snappedTo(snap_view); // reset parent rect - parentView->setRect(parent_rect); + resizing_view->setRect(orig_rect); // translate and scale to new shape - parentView->reshape(scaled_rect.getWidth(), scaled_rect.getHeight(), FALSE); - parentView->translate(scaled_rect.mLeft - parentView->getRect().mLeft, scaled_rect.mBottom - parentView->getRect().mBottom); + resizing_view->userSetShape(scaled_rect); - screen_x = mDragStartScreenX + delta_x + snap_delta_x; - screen_y = mDragStartScreenY + delta_y + snap_delta_y; - mDragStartScreenX = screen_x; - mDragStartScreenY = screen_y; + // update last valid mouse cursor position based on resized view's actual size + LLRect new_rect = resizing_view->getRect(); + switch(mCorner) + { + case LEFT_TOP: + mDragLastScreenX += new_rect.mLeft - orig_rect.mLeft; + mDragLastScreenY += new_rect.mTop - orig_rect.mTop; + break; + case LEFT_BOTTOM: + mDragLastScreenX += new_rect.mLeft - orig_rect.mLeft; + mDragLastScreenY += new_rect.mBottom- orig_rect.mBottom; + break; + case RIGHT_TOP: + mDragLastScreenX += new_rect.mRight - orig_rect.mRight; + mDragLastScreenY += new_rect.mTop - orig_rect.mTop; + break; + case RIGHT_BOTTOM: + mDragLastScreenX += new_rect.mRight - orig_rect.mRight; + mDragLastScreenY += new_rect.mBottom- orig_rect.mBottom; + break; + default: + break; + } } - lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << " (active) " << llendl; handled = TRUE; } else if( getVisible() && pointInHandle( x, y ) ) { - lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << " (inactive) " << llendl; handled = TRUE; } diff --git a/linden/indra/llui/llresizehandle.h b/linden/indra/llui/llresizehandle.h index dcde8e6..b091f1f 100644 --- a/linden/indra/llui/llresizehandle.h +++ b/linden/indra/llui/llresizehandle.h @@ -4,6 +4,7 @@ * * Copyright (c) 2001-2007, Linden Research, Inc. * + * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement @@ -56,8 +57,8 @@ protected: BOOL pointInHandle( S32 x, S32 y ); protected: - S32 mDragStartScreenX; - S32 mDragStartScreenY; + S32 mDragLastScreenX; + S32 mDragLastScreenY; S32 mLastMouseScreenX; S32 mLastMouseScreenY; LLCoordGL mLastMouseDir; diff --git a/linden/indra/llui/llresmgr.cpp b/linden/indra/llui/llresmgr.cpp index a73b487..2350093 100644 --- a/linden/indra/llui/llresmgr.cpp +++ b/linden/indra/llui/llresmgr.cpp @@ -4,6 +4,7 @@ * * Copyright (c) 2001-2007, Linden Research, Inc. * + * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement @@ -440,8 +441,8 @@ const LLString LLLocale::SYSTEM_LOCALE("English_United States.1252"); const LLString LLLocale::USER_LOCALE("en_US.iso8859-1");// = LLString::null; const LLString LLLocale::SYSTEM_LOCALE("en_US.iso8859-1"); #else // LL_LINUX likes this -const LLString LLLocale::USER_LOCALE("en_US.utf8");// = LLString::null; -const LLString LLLocale::SYSTEM_LOCALE("en_US.utf8"); +const LLString LLLocale::USER_LOCALE("en_US.utf8"); +const LLString LLLocale::SYSTEM_LOCALE("C"); #endif diff --git a/linden/indra/llui/llresmgr.h b/linden/indra/llui/llresmgr.h index 0bb4e0d..836d352 100644 --- a/linden/indra/llui/llresmgr.h +++ b/linden/indra/llui/llresmgr.h @@ -4,6 +4,7 @@ * * Copyright (c) 2001-2007, Linden Research, Inc. * + * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement diff --git a/linden/indra/llui/llrootview.cpp b/linden/indra/llui/llrootview.cpp index 49e512c..d78244d 100644 --- a/linden/indra/llui/llrootview.cpp +++ b/linden/indra/llui/llrootview.cpp @@ -4,6 +4,7 @@ * * Copyright (c) 2006-2007, Linden Research, Inc. * + * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement diff --git a/linden/indra/llui/llrootview.h b/linden/indra/llui/llrootview.h index 84a989b..ce98006 100644 --- a/linden/indra/llui/llrootview.h +++ b/linden/indra/llui/llrootview.h @@ -4,6 +4,7 @@ * * Copyright (c) 2006-2007, Linden Research, Inc. * + * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement diff --git a/linden/indra/llui/llscrollbar.cpp b/linden/indra/llui/llscrollbar.cpp index 578fdb1..4edf81e 100644 --- a/linden/indra/llui/llscrollbar.cpp +++ b/linden/indra/llui/llscrollbar.cpp @@ -4,6 +4,7 @@ * * Copyright (c) 2001-2007, Linden Research, Inc. * + * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement @@ -233,7 +234,7 @@ BOOL LLScrollbar::handleMouseDown(S32 x, S32 y, MASK mask) { // Start dragging the thumb // No handler needed for focus lost since this clas has no state that depends on it. - gFocusMgr.setMouseCapture( this, NULL ); + gFocusMgr.setMouseCapture( this ); mDragStartX = x; mDragStartY = y; mOrigRect.mTop = mThumbRect.mTop; @@ -274,7 +275,7 @@ BOOL LLScrollbar::handleHover(S32 x, S32 y, MASK mask) // because they'll capture the mouse whenever they need hover events. BOOL handled = FALSE; - if( gFocusMgr.getMouseCapture() == this ) + if( hasMouseCapture() ) { S32 height = mRect.getHeight(); S32 width = mRect.getWidth(); @@ -427,9 +428,9 @@ BOOL LLScrollbar::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, BOOL LLScrollbar::handleMouseUp(S32 x, S32 y, MASK mask) { BOOL handled = FALSE; - if( gFocusMgr.getMouseCapture() == this ) + if( hasMouseCapture() ) { - gFocusMgr.setMouseCapture( NULL, NULL ); + gFocusMgr.setMouseCapture( NULL ); handled = TRUE; } else @@ -461,7 +462,7 @@ void LLScrollbar::draw() screenPointToLocal(cursor_pos_gl.mX, cursor_pos_gl.mY, &local_mouse_x, &local_mouse_y); BOOL other_captor = gFocusMgr.getMouseCapture() && gFocusMgr.getMouseCapture() != this; - BOOL hovered = mEnabled && !other_captor && (gFocusMgr.getMouseCapture() == this || mThumbRect.pointInRect(local_mouse_x, local_mouse_y)); + BOOL hovered = mEnabled && !other_captor && (hasMouseCapture() || mThumbRect.pointInRect(local_mouse_x, local_mouse_y)); if (hovered) { mCurGlowStrength = lerp(mCurGlowStrength, mHoverGlowStrength, LLCriticalDamp::getInterpolant(0.05f)); diff --git a/linden/indra/llui/llscrollbar.h b/linden/indra/llui/llscrollbar.h index b7689ea..f6ac17d 100644 --- a/linden/indra/llui/llscrollbar.h +++ b/linden/indra/llui/llscrollbar.h @@ -4,6 +4,7 @@ * * Copyright (c) 2001-2007, Linden Research, Inc. * + * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement diff --git a/linden/indra/llui/llscrollcontainer.cpp b/linden/indra/llui/llscrollcontainer.cpp index 73be607..cf43ee1 100644 --- a/linden/indra/llui/llscrollcontainer.cpp +++ b/linden/indra/llui/llscrollcontainer.cpp @@ -4,6 +4,7 @@ * * Copyright (c) 2001-2007, Linden Research, Inc. * + * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement @@ -456,7 +457,7 @@ void LLScrollableContainerView::draw() // auto-focus when scrollbar active // this allows us to capture user intent (i.e. stop automatically scrolling the view/etc) if (!gFocusMgr.childHasKeyboardFocus(this) && - (gFocusMgr.getMouseCapture() == mScrollbar[VERTICAL] || gFocusMgr.getMouseCapture() == mScrollbar[HORIZONTAL])) + (mScrollbar[VERTICAL]->hasMouseCapture() || mScrollbar[HORIZONTAL]->hasMouseCapture())) { focusFirstItem(); } diff --git a/linden/indra/llui/llscrollcontainer.h b/linden/indra/llui/llscrollcontainer.h index f6bacda..3b3bbef 100644 --- a/linden/indra/llui/llscrollcontainer.h +++ b/linden/indra/llui/llscrollcontainer.h @@ -4,6 +4,7 @@ * * Copyright (c) 2001-2007, Linden Research, Inc. * + * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement diff --git a/linden/indra/llui/llscrollingpanellist.cpp b/linden/indra/llui/llscrollingpanellist.cpp index 209785e..eb806e4 100644 --- a/linden/indra/llui/llscrollingpanellist.cpp +++ b/linden/indra/llui/llscrollingpanellist.cpp @@ -4,6 +4,7 @@ * * Copyright (c) 2006-2007, Linden Research, Inc. * + * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement diff --git a/linden/indra/llui/llscrollingpanellist.h b/linden/indra/llui/llscrollingpanellist.h index 94e34e6..29e3d41 100644 --- a/linden/indra/llui/llscrollingpanellist.h +++ b/linden/indra/llui/llscrollingpanellist.h @@ -3,6 +3,7 @@ * * Copyright (c) 2006-2007, Linden Research, Inc. * + * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement diff --git a/linden/indra/llui/llscrolllistctrl.cpp b/linden/indra/llui/llscrolllistctrl.cpp index 4d5c49f..22987dc 100644 --- a/linden/indra/llui/llscrolllistctrl.cpp +++ b/linden/indra/llui/llscrolllistctrl.cpp @@ -4,6 +4,7 @@ * * Copyright (c) 2001-2007, Linden Research, Inc. * + * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement @@ -48,8 +49,11 @@ #include "llwindow.h" #include "llcontrol.h" #include "llkeyboard.h" +#include "llresizebar.h" const S32 LIST_BORDER_PAD = 2; // white space inside the border and to the left of the scrollbar +const S32 MIN_COLUMN_WIDTH = 20; +const S32 LIST_SNAP_PADDING = 5; // local structures & classes. struct SortScrollListItem @@ -152,6 +156,19 @@ BOOL LLScrollListCheck::handleClick() } // +// LLScrollListSeparator +// +LLScrollListSeparator::LLScrollListSeparator(S32 width) : mWidth(width) +{ +} + +void LLScrollListSeparator::drawToWidth(S32 width, const LLColor4& color, const LLColor4& highlight_color) const +{ + //*FIXME: use dynamic item heights and make separators narrow, and inactive + gl_line_2d(5, 8, llmax(5, width - 5), 8, color); +} + +// // LLScrollListText // U32 LLScrollListText::sCount = 0; @@ -273,7 +290,7 @@ LLScrollListItem::~LLScrollListItem() std::for_each(mColumns.begin(), mColumns.end(), DeletePointer()); } -BOOL LLScrollListItem::handleMouseDown(S32 x, S32 y, MASK mask) +BOOL LLScrollListItem::handleClick(S32 x, S32 y, MASK mask) { BOOL handled = FALSE; @@ -374,14 +391,13 @@ LLScrollListCtrl::LLScrollListCtrl(const LLString& name, const LLRect& rect, mPageLines(0), mHeadingHeight(20), mMaxSelectable(0), - mHeadingFont(NULL), mAllowMultipleSelection( allow_multiple_selection ), mAllowKeyboardMovement(TRUE), mCommitOnKeyboardMovement(TRUE), mCommitOnSelectionChange(FALSE), mSelectionChanged(FALSE), mCanSelect(TRUE), - mDisplayColumnButtons(FALSE), + mDisplayColumnHeaders(FALSE), mCollapseEmptyColumns(FALSE), mIsPopup(FALSE), mMaxItemCount(INT_MAX), @@ -396,21 +412,21 @@ LLScrollListCtrl::LLScrollListCtrl(const LLString& name, const LLRect& rect, mFgUnselectedColor( LLUI::sColorsGroup->getColor("ScrollUnselectedColor") ), mFgDisabledColor( LLUI::sColorsGroup->getColor("ScrollDisabledColor") ), mHighlightedColor( LLUI::sColorsGroup->getColor("ScrollHighlightedColor") ), + mHighlightedItem(-1), mBorderThickness( 2 ), mOnDoubleClickCallback( NULL ), mOnMaximumSelectCallback( NULL ), mOnSortChangedCallback( NULL ), - mHighlightedItem(-1), + mDrewSelected(FALSE), mBorder(NULL), - mDefaultColumn("SIMPLE"), mSearchColumn(0), + mDefaultColumn("SIMPLE"), mNumDynamicWidthColumns(0), mTotalStaticColumnWidth(0), - mSortColumn(0), - mSortAscending(TRUE), - - mDrewSelected(FALSE) + mSortColumn(-1), + mSorted(TRUE), + mSortAscending(TRUE) { mItemListRect.setOriginAndSize( mBorderThickness + LIST_BORDER_PAD, @@ -497,6 +513,7 @@ void LLScrollListCtrl::clearRows() mScrollLines = 0; mLastSelected = NULL; + updateMaxContentWidth(NULL); } @@ -546,7 +563,6 @@ S32 LLScrollListCtrl::getFirstSelectedIndex() return -1; } - LLScrollListItem* LLScrollListCtrl::getFirstData() const { if (mItemList.size() == 0) @@ -556,6 +572,15 @@ LLScrollListItem* LLScrollListCtrl::getFirstData() const return mItemList[0]; } +LLScrollListItem* LLScrollListCtrl::getLastData() const +{ + if (mItemList.size() == 0) + { + return NULL; + } + return mItemList[mItemList.size() - 1]; +} + std::vector LLScrollListCtrl::getAllData() const { std::vector ret; @@ -573,7 +598,7 @@ void LLScrollListCtrl::reshape( S32 width, S32 height, BOOL called_from_parent ) { LLUICtrl::reshape( width, height, called_from_parent ); - S32 heading_size = (mDisplayColumnButtons ? mHeadingHeight : 0); + S32 heading_size = (mDisplayColumnHeaders ? mHeadingHeight : 0); mItemListRect.setOriginAndSize( mBorderThickness + LIST_BORDER_PAD, @@ -586,10 +611,8 @@ void LLScrollListCtrl::reshape( S32 width, S32 height, BOOL called_from_parent ) mScrollbar->setPageSize( mPageLines ); updateColumns(); - updateColumnButtons(); } - // Attempt to size the control to show all items. // Do not make larger than width or height. void LLScrollListCtrl::arrange(S32 max_width, S32 max_height) @@ -621,35 +644,83 @@ 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; } updateLineHeight(); mPageLines = mLineHeight ? mItemListRect.getHeight() / mLineHeight : 0; - mScrollbar->setVisible(mPageLines < getItemCount()); + BOOL scrollbar_visible = mPageLines < getItemCount(); + + if (scrollbar_visible != mScrollbar->getVisible()) + { + mScrollbar->setVisible(mPageLines < getItemCount()); + updateColumns(); + } mScrollbar->setPageSize( mPageLines ); mScrollbar->setDocSize( getItemCount() ); + + updateMaxContentWidth(item); } + return not_too_big; } +void LLScrollListCtrl::updateMaxContentWidth(LLScrollListItem* added_item) +{ + const S32 HEADING_TEXT_PADDING = 30; + const S32 COLUMN_TEXT_PADDING = 20; + + std::map::iterator column_itor; + for (column_itor = mColumns.begin(); column_itor != mColumns.end(); ++column_itor) + { + LLScrollListColumn* column = &column_itor->second; + + if (!added_item) + { + // update on all items + column->mMaxContentWidth = column->mHeader ? LLFontGL::sSansSerifSmall->getWidth(column->mLabel) + mColumnPadding + HEADING_TEXT_PADDING : 0; + item_list::iterator iter; + for (iter = mItemList.begin(); iter != mItemList.end(); iter++) + { + LLScrollListCell* cellp = (*iter)->getColumn(column->mIndex); + if (!cellp) continue; + + column->mMaxContentWidth = llmax(LLFontGL::sSansSerifSmall->getWidth(cellp->getText()) + mColumnPadding + COLUMN_TEXT_PADDING, column->mMaxContentWidth); + } + } + else + { + LLScrollListCell* cellp = added_item->getColumn(column->mIndex); + if (!cellp) continue; + + column->mMaxContentWidth = llmax(LLFontGL::sSansSerifSmall->getWidth(cellp->getText()) + mColumnPadding + COLUMN_TEXT_PADDING, column->mMaxContentWidth); + } + } +} + // Line height is the max height of all the cells in all the items. void LLScrollListCtrl::updateLineHeight() @@ -678,60 +749,82 @@ void LLScrollListCtrl::updateColumns() for (column_itor = mColumns.begin(); column_itor != mColumns.end(); ++column_itor) { LLScrollListColumn *column = &column_itor->second; + S32 new_width = column->mWidth; if (column->mRelWidth >= 0) { - column->mWidth = (S32)llround(column->mRelWidth*mItemListRect.getWidth()); + new_width = (S32)llround(column->mRelWidth*mItemListRect.getWidth()); } else if (column->mDynamicWidth) { - column->mWidth = (mItemListRect.getWidth() - mTotalStaticColumnWidth) / mNumDynamicWidthColumns; - + new_width = (mItemListRect.getWidth() - mTotalStaticColumnWidth) / mNumDynamicWidthColumns; + } + + if (new_width != column->mWidth) + { + column->mWidth = new_width; } mColumnsIndexed[column_itor->second.mIndex] = column; } -} -void LLScrollListCtrl::updateColumnButtons() -{ - std::map::iterator column_itor; - for (column_itor = mColumns.begin(); column_itor != mColumns.end(); ++column_itor) + item_list::iterator iter; + for (iter = mItemList.begin(); iter != mItemList.end(); iter++) { - LLScrollListColumn* column = &column_itor->second; - LLButton *button = column->mButton; - - if (button) + LLScrollListItem *itemp = *iter; + S32 num_cols = itemp->getNumColumns(); + S32 i = 0; + for (LLScrollListCell* cell = itemp->getColumn(i); i < num_cols; cell = itemp->getColumn(++i)) { - mColumnsIndexed[column->mIndex] = column; + if (i >= (S32)mColumnsIndexed.size()) break; + + cell->setWidth(mColumnsIndexed[i]->mWidth); + } + } + // update headers + std::vector::iterator column_ordered_it; + S32 left = mItemListRect.mLeft; + LLColumnHeader* last_header = NULL; + for (column_ordered_it = mColumnsIndexed.begin(); column_ordered_it != mColumnsIndexed.end(); ++column_ordered_it) + { + if ((*column_ordered_it)->mWidth <= 0) + { + // skip hidden columns + } + LLScrollListColumn* column = *column_ordered_it; + + if (column->mHeader) + { + last_header = column->mHeader; S32 top = mItemListRect.mTop; - S32 left = mItemListRect.mLeft; - { - std::map::iterator itor; - for (itor = mColumns.begin(); itor != mColumns.end(); ++itor) - { - if (itor->second.mIndex < column->mIndex && - itor->second.mWidth > 0) - { - left += itor->second.mWidth + mColumnPadding; - } - } - } - S32 right = left+column->mWidth; - if (column->mIndex != (S32)mColumns.size()-1) + S32 right = left + column->mWidth; + + if (column->mIndex != (S32)mColumnsIndexed.size()-1) { right += mColumnPadding; } - LLRect temp_rect = LLRect(left,top+mHeadingHeight,right,top); - button->setRect(temp_rect); - button->setFont(mHeadingFont); - button->setVisible(mDisplayColumnButtons); + right = llmax(left, llmin(mItemListRect.getWidth(), right)); + + S32 header_width = right - left; + + last_header->reshape(header_width, mHeadingHeight); + last_header->translate(left - last_header->getRect().mLeft, top - last_header->getRect().mBottom); + last_header->setVisible(mDisplayColumnHeaders && header_width > 0); + left = right; } } + + // expand last column header we encountered to full list width + if (last_header) + { + S32 header_strip_width = mItemListRect.getWidth() + (mScrollbar->getVisible() ? 0 : SCROLLBAR_SIZE); + S32 new_width = llmax(0, mItemListRect.mLeft + header_strip_width - last_header->getRect().mLeft); + last_header->reshape(new_width, last_header->getRect().getHeight()); + } } void LLScrollListCtrl::setDisplayHeading(BOOL display) { - mDisplayColumnButtons = display; + mDisplayColumnHeaders = display; updateColumns(); @@ -745,15 +838,7 @@ void LLScrollListCtrl::setHeadingHeight(S32 heading_height) reshape(mRect.getWidth(), mRect.getHeight()); // Resize - mScrollbar->reshape(SCROLLBAR_SIZE, mItemListRect.getHeight()); - - updateColumnButtons(); -} - -void LLScrollListCtrl::setHeadingFont(const LLFontGL* heading_font) -{ - mHeadingFont = heading_font; - updateColumnButtons(); + mScrollbar->reshape(SCROLLBAR_SIZE, mItemListRect.getHeight() + (mDisplayColumnHeaders ? mHeadingHeight : 0)); } void LLScrollListCtrl::setCollapseEmptyColumns(BOOL collapse) @@ -873,6 +958,7 @@ void LLScrollListCtrl::deleteSingleItem(S32 target_index) } delete itemp; mItemList.erase(mItemList.begin() + target_index); + updateMaxContentWidth(NULL); } void LLScrollListCtrl::deleteSelectedItems() @@ -892,6 +978,7 @@ void LLScrollListCtrl::deleteSelectedItems() } } mLastSelected = NULL; + updateMaxContentWidth(NULL); } void LLScrollListCtrl::highlightNthItem(S32 target_index) @@ -1033,7 +1120,7 @@ void LLScrollListCtrl::selectNextItem( BOOL extend_selection) } } - if ((mCommitOnSelectionChange || mCommitOnKeyboardMovement)) + if (mCommitOnKeyboardMovement) { onCommit(); } @@ -1486,109 +1573,153 @@ BOOL LLScrollListCtrl::handleScrollWheel(S32 x, S32 y, S32 clicks) return handled; } - -BOOL LLScrollListCtrl::handleMouseDown(S32 x, S32 y, MASK mask) +BOOL LLScrollListCtrl::selectItemAt(S32 x, S32 y, MASK mask) { - BOOL handled = LLView::childrenHandleMouseDown(x, y, mask) != NULL; + if (!mCanSelect) return FALSE; - // set keyboard focus first, in case click action wants to move focus elsewhere - setFocus(TRUE); + BOOL selection_changed = FALSE; - if( !handled && mCanSelect) + LLScrollListItem* hit_item = hitItem(x, y); + if( hit_item ) { - LLScrollListItem* hit_item = hitItem(x, y); - if( hit_item ) + if( mAllowMultipleSelection ) { - if( mAllowMultipleSelection ) + if (mask & MASK_SHIFT) { - if (mask & MASK_SHIFT) + if (mLastSelected == NULL) { - if (mLastSelected == NULL) - { - selectItem(hit_item); - } - else + selectItem(hit_item); + } + else + { + // Select everthing between mLastSelected and hit_item + bool selecting = false; + item_list::iterator itor; + // If we multiselect backwards, we'll stomp on mLastSelected, + // meaning that we never stop selecting until hitting max or + // the end of the list. + LLScrollListItem* lastSelected = mLastSelected; + for (itor = mItemList.begin(); itor != mItemList.end(); ++itor) { - // Select everthing between mLastSelected and hit_item - bool selecting = false; - item_list::iterator itor; - // If we multiselect backwards, we'll stomp on mLastSelected, - // meaning that we never stop selecting until hitting max or - // the end of the list. - LLScrollListItem* lastSelected = mLastSelected; - for (itor = mItemList.begin(); itor != mItemList.end(); ++itor) + if(mMaxSelectable > 0 && getAllSelected().size() >= mMaxSelectable) { - if(mMaxSelectable > 0 && getAllSelected().size() >= mMaxSelectable) - { - if(mOnMaximumSelectCallback) - { - mOnMaximumSelectCallback(mCallbackUserData); - } - break; - } - LLScrollListItem *item = *itor; - if (item == hit_item || item == lastSelected) - { - selectItem(item, FALSE); - selecting = !selecting; - } - if (selecting) + if(mOnMaximumSelectCallback) { - selectItem(item, FALSE); + mOnMaximumSelectCallback(mCallbackUserData); } + break; + } + LLScrollListItem *item = *itor; + if (item == hit_item || item == lastSelected) + { + selectItem(item, FALSE); + selecting = !selecting; + } + if (selecting) + { + selectItem(item, FALSE); } } } - else if (mask & MASK_CONTROL) + } + else if (mask & MASK_CONTROL) + { + if (hit_item->getSelected()) + { + deselectItem(hit_item); + } + else { - if (hit_item->getSelected()) + if(!(mMaxSelectable > 0 && getAllSelected().size() >= mMaxSelectable)) { - deselectItem(hit_item); + selectItem(hit_item, FALSE); } else { - if(!(mMaxSelectable > 0 && getAllSelected().size() >= mMaxSelectable)) + if(mOnMaximumSelectCallback) { - selectItem(hit_item, FALSE); - } - else - { - if(mOnMaximumSelectCallback) - { - mOnMaximumSelectCallback(mCallbackUserData); - } + mOnMaximumSelectCallback(mCallbackUserData); } } } - else - { - deselectAllItems(TRUE); - selectItem(hit_item); - } } else { + deselectAllItems(TRUE); selectItem(hit_item); } - - hit_item->handleMouseDown(x - mBorderThickness - LIST_BORDER_PAD, - 1, mask); - // always commit on mousedown - onCommit(); - mSelectionChanged = FALSE; - - // clear search string on mouse operations - mSearchString.clear(); } else { - mLastSelected = NULL; + selectItem(hit_item); } + + hit_item->handleClick(x - mBorderThickness - LIST_BORDER_PAD, + 1, mask); + + selection_changed = mSelectionChanged; + if (mCommitOnSelectionChange) + { + commitIfChanged(); + } + + // clear search string on mouse operations + mSearchString.clear(); + } + else + { + //mLastSelected = NULL; + //deselectAllItems(TRUE); + } + + return selection_changed; +} + + +BOOL LLScrollListCtrl::handleMouseDown(S32 x, S32 y, MASK mask) +{ + BOOL handled = LLView::childrenHandleMouseDown(x, y, mask) != NULL; + + if( !handled ) + { + // set keyboard focus first, in case click action wants to move focus elsewhere + setFocus(TRUE); + + // clear selection changed flag so because user is starting a selection operation + mSelectionChanged = FALSE; + + gFocusMgr.setMouseCapture(this); + selectItemAt(x, y, mask); } return TRUE; } +BOOL LLScrollListCtrl::handleMouseUp(S32 x, S32 y, MASK mask) +{ + if (hasMouseCapture()) + { + if(mask == MASK_NONE) + { + selectItemAt(x, y, mask); + } + } + + if (hasMouseCapture()) + { + gFocusMgr.setMouseCapture(NULL); + } + + // always commit when mouse operation is completed inside list + if (mItemListRect.pointInRect(x,y)) + { + mSelectionChanged = FALSE; + onCommit(); + } + + return LLUICtrl::handleMouseUp(x, y, mask); +} + BOOL LLScrollListCtrl::handleDoubleClick(S32 x, S32 y, MASK mask) { //BOOL handled = FALSE; @@ -1647,31 +1778,35 @@ BOOL LLScrollListCtrl::handleHover(S32 x,S32 y,MASK mask) { BOOL handled = FALSE; - if(getVisible()) + if (hasMouseCapture()) { - if (mCanSelect) + if(mask == MASK_NONE) { - LLScrollListItem* item = hitItem(x, y); - if (item) - { - highlightNthItem(getItemIndex(item)); - } - else - { - highlightNthItem(-1); - } + selectItemAt(x, y, mask); } - - handled = LLView::handleHover( x, y, mask ); - - if( !handled ) + } + else if (mCanSelect) + { + LLScrollListItem* item = hitItem(x, y); + if (item) + { + highlightNthItem(getItemIndex(item)); + } + else { - // Opaque - getWindow()->setCursor(UI_CURSOR_ARROW); - lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << llendl; - handled = TRUE; + highlightNthItem(-1); } } + + handled = LLUICtrl::handleHover( x, y, mask ); + + //if( !handled ) + //{ + // // Opaque + // getWindow()->setCursor(UI_CURSOR_ARROW); + // lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << llendl; + // handled = TRUE; + //} return handled; } @@ -1980,6 +2115,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 ) @@ -1992,9 +2137,19 @@ void LLScrollListCtrl::onScrollChange( S32 new_pos, LLScrollbar* scrollbar, void // First column is column 0 void LLScrollListCtrl::sortByColumn(U32 column, BOOL ascending) { - mSortColumn = column; - mSortAscending = ascending; - std::sort(mItemList.begin(), mItemList.end(), SortScrollListItem(mSortColumn, mSortAscending)); + 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 + if(mSortAscending != ascending) + { + std::reverse(mItemList.begin(), mItemList.end()); + mSortAscending = ascending; + } } void LLScrollListCtrl::sortByColumn(LLString name, BOOL ascending) @@ -2066,7 +2221,7 @@ LLXMLNodePtr LLScrollListCtrl::getXML(bool save_children) const node->createChild("draw_border", TRUE)->setBoolValue((mBorder != NULL)); - node->createChild("draw_heading", TRUE)->setBoolValue(mDisplayColumnButtons); + node->createChild("draw_heading", TRUE)->setBoolValue(mDisplayColumnHeaders); node->createChild("background_visible", TRUE)->setBoolValue(mBackgroundVisible); @@ -2215,13 +2370,6 @@ LLView* LLScrollListCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFac node->getAttributeS32("heading_height", heading_height); scroll_list->setHeadingHeight(heading_height); } - if (node->hasAttribute("heading_font")) - { - LLString heading_font(""); - node->getAttributeString("heading_font", heading_font); - LLFontGL* gl_font = LLFontGL::fontFromName(heading_font.c_str()); - scroll_list->setHeadingFont(gl_font); - } scroll_list->setCollapseEmptyColumns(collapse_empty_columns); scroll_list->setScrollListParameters(node); @@ -2246,6 +2394,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); @@ -2267,6 +2418,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; @@ -2427,10 +2579,17 @@ BOOL LLScrollListCtrl::canDeselect() void LLScrollListCtrl::addColumn(const LLSD& column, EAddPosition pos) { LLString name = column["name"].asString(); - if (mColumns.size() == 0) + if (mColumns.empty()) { 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 @@ -2470,30 +2629,28 @@ void LLScrollListCtrl::addColumn(const LLSD& column, EAddPosition pos) right += mColumnPadding; } LLRect temp_rect = LLRect(left,top+mHeadingHeight,right,top); - new_column->mButton = new LLSquareButton(button_name, temp_rect, "", mHeadingFont, "", onClickColumn, NULL); + new_column->mHeader = new LLColumnHeader(button_name, temp_rect, new_column); if(column["image"].asString() != "") { - //new_column->mButton->setScaleImage(false); - new_column->mButton->setImageSelected(column["image"].asString()); - new_column->mButton->setImageUnselected(column["image"].asString()); + //new_column->mHeader->setScaleImage(false); + new_column->mHeader->setImage(column["image"].asString()); } else { - new_column->mButton->setLabelSelected(new_column->mLabel); - new_column->mButton->setLabelUnselected(new_column->mLabel); + new_column->mHeader->setLabel(new_column->mLabel); + //new_column->mHeader->setLabel(new_column->mLabel); } //RN: although it might be useful to change sort order with the keyboard, // mixing tab stops on child items along with the parent item is not supported yet - new_column->mButton->setTabStop(FALSE); - addChild(new_column->mButton); - new_column->mButton->setVisible(mDisplayColumnButtons); + new_column->mHeader->setTabStop(FALSE); + addChild(new_column->mHeader); + new_column->mHeader->setVisible(mDisplayColumnHeaders); // Move scroll to front removeChild(mScrollbar); addChild(mScrollbar); - - new_column->mButton->setCallbackUserData(new_column); + } } updateColumns(); @@ -2511,6 +2668,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()) @@ -2520,7 +2678,6 @@ void LLScrollListCtrl::onClickColumn(void *userdata) } } - bool ascending = true; if (column_index == parent->mSortColumn) { ascending = !parent->mSortAscending; @@ -2536,7 +2693,7 @@ void LLScrollListCtrl::onClickColumn(void *userdata) std::string LLScrollListCtrl::getSortColumnName() { - LLScrollListColumn* column = mColumnsIndexed[mSortColumn]; + LLScrollListColumn* column = mSortColumn >= 0 ? mColumnsIndexed[mSortColumn] : NULL; if (column) return column->mName; else return ""; @@ -2547,11 +2704,11 @@ void LLScrollListCtrl::clearColumns() std::map::iterator itor; for (itor = mColumns.begin(); itor != mColumns.end(); ++itor) { - LLButton *button = itor->second.mButton; - if (button) + LLColumnHeader *header = itor->second.mHeader; + if (header) { - removeChild(button); - delete button; + removeChild(header); + delete header; } } mColumns.clear(); @@ -2563,14 +2720,22 @@ void LLScrollListCtrl::setColumnLabel(const LLString& column, const LLString& la if (itor != mColumns.end()) { itor->second.mLabel = label; - if (itor->second.mButton) + if (itor->second.mHeader) { - itor->second.mButton->setLabelSelected(label); - itor->second.mButton->setLabelUnselected(label); + itor->second.mHeader->setLabel(label); } } } +LLScrollListColumn* LLScrollListCtrl::getColumn(S32 index) +{ + if (index < 0 || index >= (S32)mColumnsIndexed.size()) + { + return NULL; + } + return mColumnsIndexed[index]; +} + void LLScrollListCtrl::setColumnHeadings(LLSD headings) { mColumns.clear(); @@ -2597,6 +2762,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(); @@ -2605,21 +2771,39 @@ LLScrollListItem* LLScrollListCtrl::addElement(const LLSD& value, EAddPosition p { mDefaultColumn = 0; } - std::map::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::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(); @@ -2645,10 +2829,20 @@ LLScrollListItem* LLScrollListCtrl::addElement(const LLSD& value, EAddPosition p LLRect(0, 0, width, width), "label"); new_item->setColumn(index, new LLScrollListCheck(ctrl,width)); } + else if (type == "separator") + { + new_item->setColumn(index, new LLScrollListSeparator(width)); + } else { new_item->setColumn(index, new LLScrollListText(value.asString(), font, width, font_style, font_alignment)); + if (columnp->mHeader && !value.asString().empty()) + { + columnp->mHeader->setHasResizableElement(TRUE); + } } + + col_index++; } S32 num_columns = mColumns.size(); @@ -2744,6 +2938,14 @@ void LLScrollListCtrl::setFocus(BOOL b) } LLUICtrl::setFocus(b); } + +//virtual +void LLScrollListCtrl::onFocusReceived() +{ + // forget latent selection changes when getting focus + mSelectionChanged = FALSE; +} + //virtual void LLScrollListCtrl::onFocusLost() { @@ -2754,5 +2956,411 @@ void LLScrollListCtrl::onFocusLost() getParent()->onFocusLost(); } } + if (hasMouseCapture()) + { + gFocusMgr.setMouseCapture(NULL); + } + LLUICtrl::onFocusLost(); } +LLColumnHeader::LLColumnHeader(const LLString& label, const LLRect &rect, LLScrollListColumn* column, const LLFontGL* fontp) : + LLComboBox(label, rect, label, NULL, NULL), + mColumn(column), + mOrigLabel(label), + mShowSortOptions(FALSE), + mHasResizableElement(FALSE) +{ + mListPosition = LLComboBox::ABOVE; + setCommitCallback(onSelectSort); + setCallbackUserData(this); + mButton->setTabStop(FALSE); + // require at least two frames between mouse down and mouse up event to capture intentional "hold" not just bad framerate + mButton->setHeldDownDelay(LLUI::sConfigGroup->getF32("ColumnHeaderDropDownDelay"), 2); + mButton->setHeldDownCallback(onHeldDown); + mButton->setClickedCallback(onClick); + mButton->setMouseDownCallback(onMouseDown); + + mButton->setCallbackUserData(this); + + mAscendingText = "[LOW]...[HIGH](Ascending)"; + mDescendingText = "[HIGH]...[LOW](Descending)"; + + mList->reshape(llmax(mList->getRect().getWidth(), 110, mRect.getWidth()), mList->getRect().getHeight()); + + // resize handles on left and right + const S32 RESIZE_BAR_THICKNESS = 3; + mResizeBar = new LLResizeBar( + "resizebar", + LLRect( mRect.getWidth() - RESIZE_BAR_THICKNESS, mRect.getHeight(), mRect.getWidth(), 0), + MIN_COLUMN_WIDTH, mRect.getHeight(), LLResizeBar::RIGHT ); + addChild(mResizeBar); + + mResizeBar->setEnabled(FALSE); +} + +LLColumnHeader::~LLColumnHeader() +{ +} + +void LLColumnHeader::draw() +{ + if( getVisible() ) + { + 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"))) + : LLUI::sImageProvider->getUIImageByID(LLUUID(LLUI::sAssetsGroup->getString("down_arrow.tga"))); + + //BOOL clip = mRect.mRight > mColumn->mParentCtrl->getItemListRect().getWidth(); + //LLGLEnable scissor_test(clip ? GL_SCISSOR_TEST : GL_FALSE); + + //LLRect column_header_local_rect(-mRect.mLeft, mRect.getHeight(), mColumn->mParentCtrl->getItemListRect().getWidth() - mRect.mLeft, 0); + //LLUI::setScissorRegionLocal(column_header_local_rect); + + // Draw children + LLComboBox::draw(); + + if (mList->getVisible()) + { + // sync sort order with list selection every frame + mColumn->mParentCtrl->sortByColumn(mColumn->mSortingColumn, getCurrentIndex() == 0); + } + + } +} + +BOOL LLColumnHeader::handleDoubleClick(S32 x, S32 y, MASK mask) +{ + if (canResize() && mResizeBar->getRect().pointInRect(x, y)) + { + // reshape column to max content width + LLRect column_rect = getRect(); + column_rect.mRight = column_rect.mLeft + mColumn->mMaxContentWidth; + userSetShape(column_rect); + } + else + { + onClick(this); + } + return TRUE; +} + +void LLColumnHeader::setImage(const LLString &image_name) +{ + if (mButton) + { + mButton->setImageSelected(image_name); + mButton->setImageUnselected(image_name); + } +} + +//static +void LLColumnHeader::onClick(void* user_data) +{ + LLColumnHeader* headerp = (LLColumnHeader*)user_data; + if (!headerp) return; + + LLScrollListColumn* column = headerp->mColumn; + if (!column) return; + + if (headerp->mList->getVisible()) + { + headerp->hideList(); + } + + LLScrollListCtrl::onClickColumn(column); + + // propage new sort order to sort order list + headerp->mList->selectNthItem(column->mParentCtrl->getSortAscending() ? 0 : 1); +} + +//static +void LLColumnHeader::onMouseDown(void* user_data) +{ + // for now, do nothing but block the normal showList() behavior + return; +} + +//static +void LLColumnHeader::onHeldDown(void* user_data) +{ + LLColumnHeader* headerp = (LLColumnHeader*)user_data; + headerp->showList(); +} + +void LLColumnHeader::showList() +{ + if (mShowSortOptions) + { + //LLSD item_val = mColumn->mParentCtrl->getFirstData()->getValue(); + mOrigLabel = mButton->getLabelSelected(); + + // move sort column over to this column and do initial sort + mColumn->mParentCtrl->sortByColumn(mColumn->mSortingColumn, mColumn->mParentCtrl->getSortAscending()); + + LLString low_item_text; + LLString high_item_text; + + LLScrollListItem* itemp = mColumn->mParentCtrl->getFirstData(); + if (itemp) + { + LLScrollListCell* cell = itemp->getColumn(mColumn->mIndex); + if (cell && cell->isText()) + { + if (mColumn->mParentCtrl->getSortAscending()) + { + low_item_text = cell->getText(); + } + else + { + high_item_text = cell->getText(); + } + } + } + + itemp = mColumn->mParentCtrl->getLastData(); + if (itemp) + { + LLScrollListCell* cell = itemp->getColumn(mColumn->mIndex); + if (cell && cell->isText()) + { + if (mColumn->mParentCtrl->getSortAscending()) + { + high_item_text = cell->getText(); + } + else + { + low_item_text = cell->getText(); + } + } + } + + LLString::truncate(low_item_text, 3); + LLString::truncate(high_item_text, 3); + + LLString ascending_string; + LLString descending_string; + + if (low_item_text.empty() || high_item_text.empty()) + { + ascending_string = "Ascending"; + descending_string = "Descending"; + } + else + { + mAscendingText.setArg("[LOW]", low_item_text); + mAscendingText.setArg("[HIGH]", high_item_text); + mDescendingText.setArg("[LOW]", low_item_text); + mDescendingText.setArg("[HIGH]", high_item_text); + ascending_string = mAscendingText.getString(); + descending_string = mDescendingText.getString(); + } + + S32 text_width = LLFontGL::sSansSerifSmall->getWidth(ascending_string); + text_width = llmax(text_width, LLFontGL::sSansSerifSmall->getWidth(descending_string)) + 10; + text_width = llmax(text_width, mRect.getWidth() - 30); + + mList->getColumn(0)->mWidth = text_width; + ((LLScrollListText*)mList->getFirstData()->getColumn(0))->setText(ascending_string); + ((LLScrollListText*)mList->getLastData()->getColumn(0))->setText(descending_string); + + mList->reshape(llmax(text_width + 30, 110, mRect.getWidth()), mList->getRect().getHeight()); + + LLComboBox::showList(); + } +} + +//static +void LLColumnHeader::onSelectSort(LLUICtrl* ctrl, void* user_data) +{ + LLColumnHeader* headerp = (LLColumnHeader*)user_data; + if (!headerp) return; + + LLScrollListColumn* column = headerp->mColumn; + if (!column) return; + LLScrollListCtrl *parent = column->mParentCtrl; + if (!parent) return; + + if (headerp->getCurrentIndex() == 0) + { + // ascending + parent->sortByColumn(column->mSortingColumn, TRUE); + } + else + { + // descending + parent->sortByColumn(column->mSortingColumn, FALSE); + } + + // restore original column header + headerp->setLabel(headerp->mOrigLabel); +} + +LLView* LLColumnHeader::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, 15); + + LLRect snap_rect = getSnapRect(); + + 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 LLColumnHeader::userSetShape(const LLRect& new_rect) +{ + S32 new_width = new_rect.getWidth(); + S32 delta_width = new_width - (mRect.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) break; + + 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->mWidth - MIN_COLUMN_WIDTH); + + // user shrinking column, need to add width to other columns + if (delta_width < 0) + { + if (!columnp->mDynamicWidth && columnp->mWidth > 0) + { + // statically sized column, give all remaining width to this column + columnp->mWidth -= remaining_width; + if (columnp->mRelWidth > 0.f) + { + columnp->mRelWidth = (F32)columnp->mWidth / (F32)mColumn->mParentCtrl->getItemListRect().getWidth(); + } + } + break; + } + else + { + // user growing column, need to take width from other columns + remaining_width -= resize_buffer_amt; + + if (!columnp->mDynamicWidth && columnp->mWidth > 0) + { + columnp->mWidth -= llmin(columnp->mWidth - MIN_COLUMN_WIDTH, delta_width); + if (columnp->mRelWidth > 0.f) + { + columnp->mRelWidth = (F32)columnp->mWidth / (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 -= llmax(remaining_width, 0); + } + + // propagate constrained delta_width to new width for this column + new_width = mRect.getWidth() + delta_width - mColumn->mParentCtrl->getColumnPadding(); + + // use requested width + mColumn->mWidth = 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 + mColumn->mParentCtrl->updateColumns(); + } +} + +void LLColumnHeader::setHasResizableElement(BOOL resizable) +{ + // for now, dynamically spaced columns can't be resized + if (mColumn->mDynamicWidth) return; + + if (resizable != mHasResizableElement) + { + mHasResizableElement = resizable; + + S32 num_resizable_columns = 0; + S32 col; + for (col = 0; col < mColumn->mParentCtrl->getNumColumns(); col++) + { + LLScrollListColumn* columnp = mColumn->mParentCtrl->getColumn(col); + if (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->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 LLColumnHeader::enableResizeBar(BOOL enable) +{ + // for now, dynamically spaced columns can't be resized + if (!mColumn->mDynamicWidth) + { + mResizeBar->setEnabled(enable); + } +} + +BOOL LLColumnHeader::canResize() +{ + return getVisible() && (mHasResizableElement || mColumn->mDynamicWidth); +} diff --git a/linden/indra/llui/llscrolllistctrl.h b/linden/indra/llui/llscrolllistctrl.h index a1c4853..eed07b8 100644 --- a/linden/indra/llui/llscrolllistctrl.h +++ b/linden/indra/llui/llscrolllistctrl.h @@ -4,6 +4,7 @@ * * Copyright (c) 2001-2007, Linden Research, Inc. * + * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement @@ -42,9 +43,12 @@ #include "llviewborder.h" #include "llframetimer.h" #include "llcheckboxctrl.h" +#include "llcombobox.h" class LLScrollbar; class LLScrollListCtrl; +class LLColumnHeader; +class LLResizeBar; class LLScrollListCell { @@ -58,11 +62,27 @@ public: virtual const BOOL getVisible() const { return TRUE; } virtual void setWidth(S32 width) = 0; virtual void highlightText(S32 offset, S32 num_chars) {} + virtual BOOL isText() = 0; virtual BOOL handleClick() { return FALSE; } virtual void setEnabled(BOOL enable) { } }; +class LLScrollListSeparator : public LLScrollListCell +{ +public: + LLScrollListSeparator(S32 width); + virtual ~LLScrollListSeparator() {}; + virtual void drawToWidth(S32 width, const LLColor4& color, const LLColor4& highlight_color) const; // truncate to given width, if possible + virtual S32 getWidth() const {return mWidth;} + virtual S32 getHeight() const { return 5; }; + virtual void setWidth(S32 width) {mWidth = width; } + virtual BOOL isText() { return FALSE; } + +protected: + S32 mWidth; +}; + class LLScrollListText : public LLScrollListCell { public: @@ -77,6 +97,7 @@ public: virtual const BOOL getVisible() const { return mVisible; } virtual void highlightText(S32 offset, S32 num_chars) {mHighlightOffset = offset; mHighlightCount = num_chars;} void setText(const LLString& text); + virtual BOOL isText() { return TRUE; } private: LLUIString mText; @@ -105,6 +126,7 @@ public: virtual const LLString& getText() const { return mImageUUID; } virtual const LLString& getTextLower() const { return mImageUUID; } virtual void setWidth(S32 width) { mWidth = width; } + virtual BOOL isText() { return FALSE; } private: LLPointer mIcon; @@ -126,6 +148,7 @@ public: virtual void setEnabled(BOOL enable) { if (mCheckBox) mCheckBox->setEnabled(enable); } LLCheckBoxCtrl* getCheckBox() { return mCheckBox; } + virtual BOOL isText() { return FALSE; } private: LLCheckBoxCtrl* mCheckBox; @@ -136,20 +159,50 @@ class LLScrollListColumn { public: // Default constructor - LLScrollListColumn() : mName(""), mSortingColumn(""), mLabel(""), mWidth(-1), mRelWidth(-1.0), mDynamicWidth(FALSE), mIndex(-1), mParentCtrl(NULL), mButton(NULL), mFontAlignment(LLFontGL::LEFT) + LLScrollListColumn() : + mName(""), + mSortingColumn(""), + mSortAscending(TRUE), + mLabel(""), + mWidth(-1), + mRelWidth(-1.0), + mDynamicWidth(FALSE), + mMaxContentWidth(0), + mIndex(-1), + mParentCtrl(NULL), + mHeader(NULL), + mFontAlignment(LLFontGL::LEFT) { } - LLScrollListColumn(LLString name, LLString label, S32 width, F32 relwidth) - : mName(name), mSortingColumn(name), mLabel(label), mWidth(width), mRelWidth(relwidth), mDynamicWidth(FALSE), mIndex(-1), mParentCtrl(NULL), mButton(NULL) { } + LLScrollListColumn(LLString name, LLString label, S32 width, F32 relwidth) : + mName(name), + mSortingColumn(name), + mSortAscending(TRUE), + mLabel(label), + mWidth(width), + mRelWidth(relwidth), + mDynamicWidth(FALSE), + mMaxContentWidth(0), + mIndex(-1), + mParentCtrl(NULL), + mHeader(NULL) + { } LLScrollListColumn(const LLSD &sd) { + mMaxContentWidth = 0; + mName = sd.get("name").asString(); mSortingColumn = mName; if (sd.has("sort")) { 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) { @@ -179,21 +232,57 @@ public: mIndex = -1; mParentCtrl = NULL; - mButton = NULL; + mHeader = NULL; } LLString mName; LLString mSortingColumn; + BOOL mSortAscending; LLString mLabel; S32 mWidth; F32 mRelWidth; BOOL mDynamicWidth; + S32 mMaxContentWidth; S32 mIndex; LLScrollListCtrl* mParentCtrl; - LLButton* mButton; + LLColumnHeader* mHeader; LLFontGL::HAlign mFontAlignment; }; +class LLColumnHeader : public LLComboBox +{ +public: + LLColumnHeader(const LLString& label, const LLRect &rect, LLScrollListColumn* column, const LLFontGL *font = NULL); + ~LLColumnHeader(); + + /*virtual*/ void draw(); + /*virtual*/ BOOL handleDoubleClick(S32 x, S32 y, MASK mask); + /*virtual*/ void showList(); + /*virtual*/ LLView* findSnapEdge(S32& new_edge_val, const LLCoordGL& mouse_dir, ESnapEdge snap_edge, ESnapType snap_type, S32 threshold, S32 padding); + /*virtual*/ void userSetShape(const LLRect& new_rect); + + void setImage(const LLString &image_name); + LLScrollListColumn* getColumn() { return mColumn; } + void setHasResizableElement(BOOL resizable); + BOOL canResize(); + void enableResizeBar(BOOL enable); + LLString getLabel() { return mOrigLabel; } + + static void onSelectSort(LLUICtrl* ctrl, void* user_data); + static void onClick(void* user_data); + static void onMouseDown(void* user_data); + static void onHeldDown(void* user_data); + +protected: + LLScrollListColumn* mColumn; + LLResizeBar* mResizeBar; + LLString mOrigLabel; + LLUIString mAscendingText; + LLUIString mDescendingText; + BOOL mShowSortOptions; + BOOL mHasResizableElement; +}; + class LLScrollListItem { public: @@ -235,7 +324,7 @@ public: LLScrollListCell *getColumn(const S32 i) const { if (i < (S32)mColumns.size()) { return mColumns[i]; } return NULL; } - virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); + virtual BOOL handleClick(S32 x, S32 y, MASK mask); LLString getContentsCSV(); @@ -282,6 +371,10 @@ public: virtual void addColumn(const LLSD& column, EAddPosition pos = ADD_BOTTOM); virtual void clearColumns(); virtual void setColumnLabel(const LLString& column, const LLString& label); + + virtual LLScrollListColumn* getColumn(S32 index); + virtual S32 getNumColumns() const { return mColumnsIndexed.size(); } + // Adds a single element, from an array of: // "columns" => [ "column" => column name, "value" => value, "type" => type, "font" => font, "font-style" => style ], "id" => uuid // Creates missing columns automatically. @@ -316,11 +409,14 @@ 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); + void deleteSingleItem( S32 index ) ; void deleteSelectedItems(); void deselectAllItems(BOOL no_commit_on_change = FALSE); // by default, go ahead and commit on selection change @@ -357,23 +453,6 @@ public: LLScrollListItem* addStringUUIDItem(const LLString& item_text, const LLUUID& id, EAddPosition pos = ADD_BOTTOM, BOOL enabled = TRUE, S32 column_width = 0); LLUUID getStringUUIDSelectedItem(); - // "Full" interface: use this when you're creating a list that has one or more of the following: - // * contains icons - // * contains multiple columns - // * allows multiple selection - // * has items that are not guarenteed to have unique names - // * has additional per-item data (e.g. a UUID or void* userdata) - // - // To add items using this approach, create new LLScrollListItems and LLScrollListCells. Add the - // cells (column entries) to each item, and add the item to the LLScrollListCtrl. - // - // The LLScrollListCtrl owns its items and is responsible for deleting them - // (except in the case that the addItem() call fails, in which case it is up - // to the caller to delete the item) - - // returns FALSE if item faile to be added to list, does NOT delete 'item' - // TomY TODO - Deprecate this API and remove it - BOOL addItem( LLScrollListItem* item, EAddPosition pos = ADD_BOTTOM ); LLScrollListItem* getFirstSelected() const; virtual S32 getFirstSelectedIndex(); std::vector getAllSelected() const; @@ -382,6 +461,7 @@ public: // iterate over all items LLScrollListItem* getFirstData() const; + LLScrollListItem* getLastData() const; std::vector getAllData() const; void setAllowMultipleSelection(BOOL mult ) { mAllowMultipleSelection = mult; } @@ -398,6 +478,7 @@ public: void setBackgroundVisible(BOOL b) { mBackgroundVisible = b; } void setDrawStripes(BOOL b) { mDrawStripes = b; } void setColumnPadding(const S32 c) { mColumnPadding = c; } + S32 getColumnPadding() { return mColumnPadding; } void setCommitOnKeyboardMovement(BOOL b) { mCommitOnKeyboardMovement = b; } void setCommitOnSelectionChange(BOOL b) { mCommitOnSelectionChange = b; } void setAllowKeyboardMovement(BOOL b) { mAllowKeyboardMovement = b; } @@ -417,6 +498,7 @@ public: // Overridden from LLView virtual void draw(); virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); + virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask); virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask); virtual BOOL handleHover(S32 x, S32 y, MASK mask); virtual BOOL handleKeyHere(KEY key, MASK mask, BOOL called_from_parent); @@ -424,6 +506,7 @@ public: virtual BOOL handleScrollWheel(S32 x, S32 y, S32 clicks); virtual void setEnabled(BOOL enabled); virtual void setFocus( BOOL b ); + virtual void onFocusReceived(); virtual void onFocusLost(); virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); @@ -431,17 +514,18 @@ public: virtual LLRect getRequiredRect(); static BOOL rowPreceeds(LLScrollListItem *new_row, LLScrollListItem *test_row); + LLRect getItemListRect() { return mItemListRect; } + // Used "internally" by the scroll bar. static void onScrollChange( S32 new_pos, LLScrollbar* src, void* userdata ); static void onClickColumn(void *userdata); void updateColumns(); - void updateColumnButtons(); + void updateMaxContentWidth(LLScrollListItem* changed_item); void setDisplayHeading(BOOL display); void setHeadingHeight(S32 heading_height); - void setHeadingFont(const LLFontGL* heading_font); void setCollapseEmptyColumns(BOOL collapse); void setIsPopup(BOOL is_popup) { mIsPopup = is_popup; } @@ -473,6 +557,22 @@ public: S32 selectMultiple( LLDynamicArray ids ); protected: + // "Full" interface: use this when you're creating a list that has one or more of the following: + // * contains icons + // * contains multiple columns + // * allows multiple selection + // * has items that are not guarenteed to have unique names + // * has additional per-item data (e.g. a UUID or void* userdata) + // + // To add items using this approach, create new LLScrollListItems and LLScrollListCells. Add the + // cells (column entries) to each item, and add the item to the LLScrollListCtrl. + // + // The LLScrollListCtrl owns its items and is responsible for deleting them + // (except in the case that the addItem() call fails, in which case it is up + // to the caller to delete the item) + + // returns FALSE if item faile to be added to list, does NOT delete 'item' + BOOL addItem( LLScrollListItem* item, EAddPosition pos = ADD_BOTTOM ); void selectPrevItem(BOOL extend_selection); void selectNextItem(BOOL extend_selection); void drawItems(); @@ -482,6 +582,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 @@ -492,7 +593,6 @@ protected: S32 mPageLines; // max number of lines is it possible to see on the screen given mRect and mLineHeight S32 mHeadingHeight; // the height of the column header buttons, if visible U32 mMaxSelectable; - const LLFontGL* mHeadingFont; // the font to use for column head buttons, if visible LLScrollbar* mScrollbar; BOOL mAllowMultipleSelection; BOOL mAllowKeyboardMovement; @@ -500,7 +600,7 @@ protected: BOOL mCommitOnSelectionChange; BOOL mSelectionChanged; BOOL mCanSelect; - BOOL mDisplayColumnButtons; + BOOL mDisplayColumnHeaders; BOOL mCollapseEmptyColumns; BOOL mIsPopup; @@ -544,8 +644,9 @@ protected: S32 mNumDynamicWidthColumns; S32 mTotalStaticColumnWidth; - U32 mSortColumn; - BOOL mSortAscending; + S32 mSortColumn; + BOOL mSortAscending; + BOOL mSorted; std::map mColumns; std::vector mColumnsIndexed; diff --git a/linden/indra/llui/llslider.cpp b/linden/indra/llui/llslider.cpp index 20d77bf..8c0d2a1 100644 --- a/linden/indra/llui/llslider.cpp +++ b/linden/indra/llui/llslider.cpp @@ -4,6 +4,7 @@ * * Copyright (c) 2002-2007, Linden Research, Inc. * + * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement @@ -117,7 +118,7 @@ F32 LLSlider::getValueF32() const BOOL LLSlider::handleHover(S32 x, S32 y, MASK mask) { - if( gFocusMgr.getMouseCapture() == this ) + if( hasMouseCapture() ) { S32 left_edge = THUMB_WIDTH/2; S32 right_edge = mRect.getWidth() - (THUMB_WIDTH/2); @@ -144,9 +145,9 @@ BOOL LLSlider::handleMouseUp(S32 x, S32 y, MASK mask) { BOOL handled = FALSE; - if( gFocusMgr.getMouseCapture() == this ) + if( hasMouseCapture() ) { - gFocusMgr.setMouseCapture( NULL, NULL ); + gFocusMgr.setMouseCapture( NULL ); if( mMouseUpCallback ) { @@ -194,7 +195,7 @@ BOOL LLSlider::handleMouseDown(S32 x, S32 y, MASK mask) // Start dragging the thumb // No handler needed for focus lost since this class has no state that depends on it. - gFocusMgr.setMouseCapture( this, NULL ); + gFocusMgr.setMouseCapture( this ); mDragStartThumbRect = mThumbRect; } make_ui_sound("UISndClick"); @@ -261,12 +262,12 @@ void LLSlider::draw() if (!thumb_imagep) { gl_rect_2d(mThumbRect, mThumbCenterColor, TRUE); - if (gFocusMgr.getMouseCapture() == this) + if (hasMouseCapture()) { gl_rect_2d(mDragStartThumbRect, mThumbCenterColor % opacity, FALSE); } } - else if( gFocusMgr.getMouseCapture() == this ) + else if( hasMouseCapture() ) { gl_draw_scaled_image_with_border(mDragStartThumbRect.mLeft, mDragStartThumbRect.mBottom, 16, 16, mDragStartThumbRect.getWidth(), mDragStartThumbRect.getHeight(), thumb_imagep, mThumbCenterColor % 0.3f, TRUE); diff --git a/linden/indra/llui/llslider.h b/linden/indra/llui/llslider.h index 1cf1a90..4f42a56 100644 --- a/linden/indra/llui/llslider.h +++ b/linden/indra/llui/llslider.h @@ -4,6 +4,7 @@ * * Copyright (c) 2002-2007, Linden Research, Inc. * + * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement diff --git a/linden/indra/llui/llsliderctrl.cpp b/linden/indra/llui/llsliderctrl.cpp index c62ec9a..9a67bca 100644 --- a/linden/indra/llui/llsliderctrl.cpp +++ b/linden/indra/llui/llsliderctrl.cpp @@ -4,6 +4,7 @@ * * Copyright (c) 2002-2007, Linden Research, Inc. * + * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement @@ -205,7 +206,7 @@ void LLSliderCtrl::clear() BOOL LLSliderCtrl::isMouseHeldDown() { - return gFocusMgr.getMouseCapture() == mSlider; + return mSlider->hasMouseCapture(); } void LLSliderCtrl::updateText() @@ -319,7 +320,7 @@ void LLSliderCtrl::onSliderCommit( LLUICtrl* caller, void *userdata ) void LLSliderCtrl::setEnabled(BOOL b) { - LLUICtrl::setEnabled( b ); + LLView::setEnabled( b ); if( mLabelBox ) { diff --git a/linden/indra/llui/llsliderctrl.h b/linden/indra/llui/llsliderctrl.h index baa0c42..26c9dee 100644 --- a/linden/indra/llui/llsliderctrl.h +++ b/linden/indra/llui/llsliderctrl.h @@ -4,6 +4,7 @@ * * Copyright (c) 2002-2007, Linden Research, Inc. * + * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement diff --git a/linden/indra/llui/llspinctrl.cpp b/linden/indra/llui/llspinctrl.cpp index 1f33279..668ddfa 100644 --- a/linden/indra/llui/llspinctrl.cpp +++ b/linden/indra/llui/llspinctrl.cpp @@ -4,6 +4,7 @@ * * Copyright (c) 2001-2007, Linden Research, Inc. * + * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement @@ -142,6 +143,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 ) { @@ -150,6 +168,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 ) @@ -182,6 +201,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 ) @@ -243,12 +263,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 ) // { @@ -320,7 +341,7 @@ void LLSpinCtrl::setFocus(BOOL b) void LLSpinCtrl::setEnabled(BOOL b) { - LLUICtrl::setEnabled( b ); + LLView::setEnabled( b ); mEditor->setEnabled( b ); } @@ -335,8 +356,8 @@ void LLSpinCtrl::setTentative(BOOL b) BOOL LLSpinCtrl::isMouseHeldDown() { return - gFocusMgr.getMouseCapture() == mDownBtn || - gFocusMgr.getMouseCapture() == mUpBtn; + mDownBtn->hasMouseCapture() + || mUpBtn->hasMouseCapture(); } void LLSpinCtrl::onCommit() diff --git a/linden/indra/llui/llspinctrl.h b/linden/indra/llui/llspinctrl.h index 46776ed..dcc305e 100644 --- a/linden/indra/llui/llspinctrl.h +++ b/linden/indra/llui/llspinctrl.h @@ -4,6 +4,7 @@ * * Copyright (c) 2002-2007, Linden Research, Inc. * + * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement diff --git a/linden/indra/llui/llstyle.cpp b/linden/indra/llui/llstyle.cpp index aaacb46..1efb4cc 100644 --- a/linden/indra/llui/llstyle.cpp +++ b/linden/indra/llui/llstyle.cpp @@ -4,6 +4,7 @@ * * Copyright (c) 2001-2007, Linden Research, Inc. * + * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement diff --git a/linden/indra/llui/llstyle.h b/linden/indra/llui/llstyle.h index 424db40..e6e88e7 100644 --- a/linden/indra/llui/llstyle.h +++ b/linden/indra/llui/llstyle.h @@ -4,6 +4,7 @@ * * Copyright (c) 2001-2007, Linden Research, Inc. * + * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement diff --git a/linden/indra/llui/lltabcontainer.cpp b/linden/indra/llui/lltabcontainer.cpp index 4687414..db09717 100644 --- a/linden/indra/llui/lltabcontainer.cpp +++ b/linden/indra/llui/lltabcontainer.cpp @@ -4,6 +4,7 @@ * * Copyright (c) 2001-2007, Linden Research, Inc. * + * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement @@ -476,6 +477,24 @@ void LLTabContainerCommon::onPrevBtn( void* userdata ) self->mScrolled = FALSE; } + +void LLTabContainerCommon::onJumpFirstBtn( void* userdata ) +{ + LLTabContainer* self = (LLTabContainer*) userdata; + + self->mScrollPos = 0; + +} + + +void LLTabContainerCommon::onJumpLastBtn( void* userdata ) +{ + LLTabContainer* self = (LLTabContainer*) userdata; + + self->mScrollPos = self->mMaxScrollPos; +} + + // static void LLTabContainerCommon::onPrevBtnHeld( void* userdata ) { @@ -692,6 +711,8 @@ LLTabContainer::LLTabContainer( LLTabContainerCommon(name, rect, pos, close_callback, callback_userdata, bordered), mLeftArrowBtn(NULL), mRightArrowBtn(NULL), + mJumpLeftArrowBtn(NULL), + mJumpRightArrowBtn(NULL), mRightTabBtnOffset(0), mMinTabWidth(TABCNTR_TAB_MIN_WIDTH), mMaxTabWidth(TABCNTR_TAB_MAX_WIDTH), @@ -708,6 +729,8 @@ LLTabContainer::LLTabContainer( LLTabContainerCommon(name, rect_control, pos, close_callback, callback_userdata, bordered), mLeftArrowBtn(NULL), mRightArrowBtn(NULL), + mJumpLeftArrowBtn(NULL), + mJumpRightArrowBtn(NULL), mRightTabBtnOffset(0), mMinTabWidth(TABCNTR_TAB_MIN_WIDTH), mMaxTabWidth(TABCNTR_TAB_MAX_WIDTH), @@ -739,14 +762,35 @@ void LLTabContainer::initButtons() S32 btn_top = (mTabPosition == TOP ) ? mRect.getHeight() - mTopBorderHeight : TABCNTR_ARROW_BTN_SIZE + 1; LLRect left_arrow_btn_rect; - left_arrow_btn_rect.setLeftTopAndSize( LLPANEL_BORDER_WIDTH+1, btn_top + arrow_fudge, TABCNTR_ARROW_BTN_SIZE, TABCNTR_ARROW_BTN_SIZE ); + left_arrow_btn_rect.setLeftTopAndSize( LLPANEL_BORDER_WIDTH+1+TABCNTR_ARROW_BTN_SIZE, btn_top + arrow_fudge, TABCNTR_ARROW_BTN_SIZE, TABCNTR_ARROW_BTN_SIZE ); + + LLRect jump_left_arrow_btn_rect; + jump_left_arrow_btn_rect.setLeftTopAndSize( LLPANEL_BORDER_WIDTH+1, btn_top + arrow_fudge, TABCNTR_ARROW_BTN_SIZE, TABCNTR_ARROW_BTN_SIZE ); S32 right_pad = TABCNTR_ARROW_BTN_SIZE + LLPANEL_BORDER_WIDTH + 1; + LLRect right_arrow_btn_rect; - right_arrow_btn_rect.setLeftTopAndSize( mRect.getWidth() - mRightTabBtnOffset - right_pad, + right_arrow_btn_rect.setLeftTopAndSize( mRect.getWidth() - mRightTabBtnOffset - right_pad - TABCNTR_ARROW_BTN_SIZE, btn_top + arrow_fudge, TABCNTR_ARROW_BTN_SIZE, TABCNTR_ARROW_BTN_SIZE ); + + LLRect jump_right_arrow_btn_rect; + jump_right_arrow_btn_rect.setLeftTopAndSize( mRect.getWidth() - mRightTabBtnOffset - right_pad, + btn_top + arrow_fudge, + TABCNTR_ARROW_BTN_SIZE, TABCNTR_ARROW_BTN_SIZE ); + + out_id = "UIImgBtnJumpLeftOutUUID"; + in_id = "UIImgBtnJumpLeftInUUID"; + mJumpLeftArrowBtn = new LLButton( + "Jump Left Arrow", jump_left_arrow_btn_rect, + out_id, in_id, "", + &LLTabContainer::onJumpFirstBtn, this, LLFontGL::sSansSerif ); + mJumpLeftArrowBtn->setFollowsLeft(); + mJumpLeftArrowBtn->setSaveToXML(false); + mJumpLeftArrowBtn->setTabStop(FALSE); + addChild(mJumpLeftArrowBtn); + out_id = "UIImgBtnScrollLeftOutUUID"; in_id = "UIImgBtnScrollLeftInUUID"; mLeftArrowBtn = new LLButton( @@ -758,6 +802,18 @@ void LLTabContainer::initButtons() mLeftArrowBtn->setSaveToXML(false); mLeftArrowBtn->setTabStop(FALSE); addChild(mLeftArrowBtn); + + out_id = "UIImgBtnJumpRightOutUUID"; + in_id = "UIImgBtnJumpRightInUUID"; + mJumpRightArrowBtn = new LLButton( + "Jump Right Arrow", jump_right_arrow_btn_rect, + out_id, in_id, "", + &LLTabContainer::onJumpLastBtn, this, + LLFontGL::sSansSerif); + mJumpRightArrowBtn->setFollowsRight(); + mJumpRightArrowBtn->setSaveToXML(false); + mJumpRightArrowBtn->setTabStop(FALSE); + addChild(mJumpRightArrowBtn); out_id = "UIImgBtnScrollRightOutUUID"; in_id = "UIImgBtnScrollRightInUUID"; @@ -772,15 +828,20 @@ void LLTabContainer::initButtons() mRightArrowBtn->setTabStop(FALSE); addChild(mRightArrowBtn); + if( mTabPosition == TOP ) { mRightArrowBtn->setFollowsTop(); mLeftArrowBtn->setFollowsTop(); + mJumpLeftArrowBtn->setFollowsTop(); + mJumpRightArrowBtn->setFollowsTop(); } else { mRightArrowBtn->setFollowsBottom(); mLeftArrowBtn->setFollowsBottom(); + mJumpLeftArrowBtn->setFollowsBottom(); + mJumpRightArrowBtn->setFollowsBottom(); } // set default tab group to be panel contents @@ -971,7 +1032,7 @@ void LLTabContainer::updateMaxScrollPos() if( tab_space > available_space ) { - S32 available_width_with_arrows = mRect.getWidth() - mRightTabBtnOffset - 2 * (LLPANEL_BORDER_WIDTH + TABCNTR_ARROW_BTN_SIZE + 1); + S32 available_width_with_arrows = mRect.getWidth() - mRightTabBtnOffset - 2 * (LLPANEL_BORDER_WIDTH + TABCNTR_ARROW_BTN_SIZE + TABCNTR_ARROW_BTN_SIZE + 1); // subtract off reserved portion on left available_width_with_arrows -= TABCNTR_TAB_PARTIAL_WIDTH; @@ -1002,7 +1063,7 @@ void LLTabContainer::updateMaxScrollPos() void LLTabContainer::commitHoveredButton(S32 x, S32 y) { - if (gFocusMgr.getMouseCapture() == this) + if (hasMouseCapture()) { for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter) { @@ -1078,7 +1139,7 @@ BOOL LLTabContainer::selectTab(S32 which) } else { - S32 available_width_with_arrows = mRect.getWidth() - mRightTabBtnOffset - 2 * (LLPANEL_BORDER_WIDTH + TABCNTR_ARROW_BTN_SIZE + 1); + S32 available_width_with_arrows = mRect.getWidth() - mRightTabBtnOffset - 2 * (LLPANEL_BORDER_WIDTH + TABCNTR_ARROW_BTN_SIZE + TABCNTR_ARROW_BTN_SIZE + 1); S32 running_tab_width = tuple->mButton->getRect().getWidth(); S32 j = i - 1; S32 min_scroll_pos = i; @@ -1120,7 +1181,7 @@ void LLTabContainer::draw() S32 cur_scroll_pos = mScrollPos; if (cur_scroll_pos > 0) { - S32 available_width_with_arrows = mRect.getWidth() - mRightTabBtnOffset - 2 * (LLPANEL_BORDER_WIDTH + TABCNTR_ARROW_BTN_SIZE + 1); + S32 available_width_with_arrows = mRect.getWidth() - mRightTabBtnOffset - 2 * (LLPANEL_BORDER_WIDTH + TABCNTR_ARROW_BTN_SIZE + TABCNTR_ARROW_BTN_SIZE + 1); for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter) { if (cur_scroll_pos == 0) @@ -1141,11 +1202,13 @@ void LLTabContainer::draw() if( getVisible() ) { BOOL has_scroll_arrows = (mMaxScrollPos > 0) || (mScrollPosPixels > 0); + mJumpLeftArrowBtn->setVisible( has_scroll_arrows ); + mJumpRightArrowBtn->setVisible( has_scroll_arrows ); mLeftArrowBtn->setVisible( has_scroll_arrows ); mRightArrowBtn->setVisible( has_scroll_arrows ); // Set the leftmost position of the tab buttons. - S32 left = LLPANEL_BORDER_WIDTH + (has_scroll_arrows ? TABCNTR_ARROW_BTN_SIZE : TABCNTR_TAB_H_PAD); + S32 left = LLPANEL_BORDER_WIDTH + (has_scroll_arrows ? (TABCNTR_ARROW_BTN_SIZE * 2) : TABCNTR_TAB_H_PAD); left -= mScrollPosPixels; // Hide all the buttons @@ -1234,7 +1297,19 @@ BOOL LLTabContainer::handleMouseDown( S32 x, S32 y, MASK mask ) BOOL has_scroll_arrows = (mMaxScrollPos > 0); if (has_scroll_arrows) - { + { + if (mJumpLeftArrowBtn->getRect().pointInRect(x, y)) + { + S32 local_x = x - mJumpLeftArrowBtn->getRect().mLeft; + S32 local_y = y - mJumpLeftArrowBtn->getRect().mBottom; + handled = mJumpLeftArrowBtn->handleMouseDown(local_x, local_y, mask); + } + if (mJumpRightArrowBtn->getRect().pointInRect(x, y)) + { + S32 local_x = x - mJumpRightArrowBtn->getRect().mLeft; + S32 local_y = y - mJumpRightArrowBtn->getRect().mBottom; + handled = mJumpRightArrowBtn->handleMouseDown(local_x, local_y, mask); + } if (mLeftArrowBtn->getRect().pointInRect(x, y)) { S32 local_x = x - mLeftArrowBtn->getRect().mLeft; @@ -1256,14 +1331,14 @@ BOOL LLTabContainer::handleMouseDown( S32 x, S32 y, MASK mask ) if (mTabList.size() > 0) { LLTabTuple* firsttuple = mTabList[0]; - LLRect tab_rect(has_scroll_arrows ? mLeftArrowBtn->getRect().mRight : mLeftArrowBtn->getRect().mLeft, + LLRect tab_rect(has_scroll_arrows ? mLeftArrowBtn->getRect().mRight : mJumpLeftArrowBtn->getRect().mLeft, firsttuple->mButton->getRect().mTop, - has_scroll_arrows ? mRightArrowBtn->getRect().mLeft : mRightArrowBtn->getRect().mRight, + has_scroll_arrows ? mRightArrowBtn->getRect().mLeft : mJumpRightArrowBtn->getRect().mRight, firsttuple->mButton->getRect().mBottom ); if( tab_rect.pointInRect( x, y ) ) { LLButton* tab_button = mTabList[getCurrentPanelIndex()]->mButton; - gFocusMgr.setMouseCapture(this, NULL); + gFocusMgr.setMouseCapture(this); gFocusMgr.setKeyboardFocus(tab_button, NULL); } } @@ -1276,7 +1351,19 @@ BOOL LLTabContainer::handleHover( S32 x, S32 y, MASK mask ) BOOL has_scroll_arrows = (mMaxScrollPos > 0); if (has_scroll_arrows) - { + { + if (mJumpLeftArrowBtn->getRect().pointInRect(x, y)) + { + S32 local_x = x - mJumpLeftArrowBtn->getRect().mLeft; + S32 local_y = y - mJumpLeftArrowBtn->getRect().mBottom; + handled = mJumpLeftArrowBtn->handleHover(local_x, local_y, mask); + } + if (mJumpRightArrowBtn->getRect().pointInRect(x, y)) + { + S32 local_x = x - mJumpRightArrowBtn->getRect().mLeft; + S32 local_y = y - mJumpRightArrowBtn->getRect().mBottom; + handled = mJumpRightArrowBtn->handleHover(local_x, local_y, mask); + } if (mLeftArrowBtn->getRect().pointInRect(x, y)) { S32 local_x = x - mLeftArrowBtn->getRect().mLeft; @@ -1306,6 +1393,18 @@ BOOL LLTabContainer::handleMouseUp( S32 x, S32 y, MASK mask ) if (has_scroll_arrows) { + if (mJumpLeftArrowBtn->getRect().pointInRect(x, y)) + { + S32 local_x = x - mJumpLeftArrowBtn->getRect().mLeft; + S32 local_y = y - mJumpLeftArrowBtn->getRect().mBottom; + handled = mJumpLeftArrowBtn->handleMouseUp(local_x, local_y, mask); + } + if (mJumpRightArrowBtn->getRect().pointInRect(x, y)) + { + S32 local_x = x - mJumpRightArrowBtn->getRect().mLeft; + S32 local_y = y - mJumpRightArrowBtn->getRect().mBottom; + handled = mJumpRightArrowBtn->handleMouseUp(local_x, local_y, mask); + } if (mLeftArrowBtn->getRect().pointInRect(x, y)) { S32 local_x = x - mLeftArrowBtn->getRect().mLeft; @@ -1326,7 +1425,7 @@ BOOL LLTabContainer::handleMouseUp( S32 x, S32 y, MASK mask ) commitHoveredButton(x, y); LLPanel* cur_panel = getCurrentPanel(); - if (gFocusMgr.getMouseCapture() == this) + if (hasMouseCapture()) { if (cur_panel) { @@ -1337,7 +1436,7 @@ BOOL LLTabContainer::handleMouseUp( S32 x, S32 y, MASK mask ) mTabList[getCurrentPanelIndex()]->mButton->setFocus(TRUE); } } - gFocusMgr.setMouseCapture(NULL, NULL); + gFocusMgr.setMouseCapture(NULL); } return handled; } @@ -1351,7 +1450,7 @@ BOOL LLTabContainer::handleToolTip( S32 x, S32 y, LLString& msg, LLRect* sticky_ BOOL has_scroll_arrows = (mMaxScrollPos > 0); LLRect clip( - has_scroll_arrows ? mLeftArrowBtn->getRect().mRight : mLeftArrowBtn->getRect().mLeft, + has_scroll_arrows ? mJumpLeftArrowBtn->getRect().mRight : mJumpLeftArrowBtn->getRect().mLeft, firsttuple->mButton->getRect().mTop, has_scroll_arrows ? mRightArrowBtn->getRect().mLeft : mRightArrowBtn->getRect().mRight, 0 ); @@ -1457,6 +1556,18 @@ BOOL LLTabContainer::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDrag if (has_scroll_arrows) { + if (mJumpLeftArrowBtn->getRect().pointInRect(x, y)) + { + S32 local_x = x - mJumpLeftArrowBtn->getRect().mLeft; + S32 local_y = y - mJumpLeftArrowBtn->getRect().mBottom; + mJumpLeftArrowBtn->handleHover(local_x, local_y, mask); + } + if (mJumpRightArrowBtn->getRect().pointInRect(x, y)) + { + S32 local_x = x - mJumpRightArrowBtn->getRect().mLeft; + S32 local_y = y - mJumpRightArrowBtn->getRect().mBottom; + mJumpRightArrowBtn->handleHover(local_x, local_y, mask); + } if (mLeftArrowBtn->getRect().pointInRect(x, y)) { S32 local_x = x - mLeftArrowBtn->getRect().mLeft; diff --git a/linden/indra/llui/lltabcontainer.h b/linden/indra/llui/lltabcontainer.h index c3146a1..5fe6bc5 100644 --- a/linden/indra/llui/lltabcontainer.h +++ b/linden/indra/llui/lltabcontainer.h @@ -4,6 +4,7 @@ * * Copyright (c) 2001-2007, Linden Research, Inc. * + * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement @@ -128,6 +129,8 @@ public: static void onNextBtnHeld(void* userdata); static void onPrevBtn(void* userdata); static void onPrevBtnHeld(void* userdata); + static void onJumpFirstBtn( void* userdata ); + static void onJumpLastBtn( void* userdata ); virtual void setRightTabBtnOffset( S32 offset ) { } virtual void setPanelTitle(S32 index, const LLString& title) { } @@ -242,7 +245,9 @@ public: protected: LLButton* mLeftArrowBtn; + LLButton* mJumpLeftArrowBtn; LLButton* mRightArrowBtn; + LLButton* mJumpRightArrowBtn; S32 mRightTabBtnOffset; // Extra room to the right of the tab buttons. diff --git a/linden/indra/llui/lltabcontainervertical.cpp b/linden/indra/llui/lltabcontainervertical.cpp index 121adf1..a921b4b 100644 --- a/linden/indra/llui/lltabcontainervertical.cpp +++ b/linden/indra/llui/lltabcontainervertical.cpp @@ -4,6 +4,7 @@ * * Copyright (c) 2001-2007, Linden Research, Inc. * + * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement @@ -279,7 +280,7 @@ void LLTabContainerVertical::updateMaxScrollPos() void LLTabContainerVertical::commitHoveredButton(S32 x, S32 y) { - if (gFocusMgr.getMouseCapture() == this) + if (hasMouseCapture()) { for(std::vector::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter) { @@ -473,7 +474,7 @@ BOOL LLTabContainerVertical::handleMouseDown( S32 x, S32 y, MASK mask ) if( tab_rect.pointInRect( x, y ) ) { LLButton* tab_button = mTabList[getCurrentPanelIndex()]->mButton; - gFocusMgr.setMouseCapture(this, NULL); + gFocusMgr.setMouseCapture(this); gFocusMgr.setKeyboardFocus(tab_button, NULL); } } @@ -536,7 +537,7 @@ BOOL LLTabContainerVertical::handleMouseUp( S32 x, S32 y, MASK mask ) commitHoveredButton(x, y); LLPanel* cur_panel = getCurrentPanel(); - if (gFocusMgr.getMouseCapture() == this) + if (hasMouseCapture()) { if (cur_panel) { @@ -545,7 +546,7 @@ BOOL LLTabContainerVertical::handleMouseUp( S32 x, S32 y, MASK mask ) mTabList[getCurrentPanelIndex()]->mButton->setFocus(TRUE); } } - gFocusMgr.setMouseCapture(NULL, NULL); + gFocusMgr.setMouseCapture(NULL); } return handled; diff --git a/linden/indra/llui/lltabcontainervertical.h b/linden/indra/llui/lltabcontainervertical.h index 81b2331..77817c2 100644 --- a/linden/indra/llui/lltabcontainervertical.h +++ b/linden/indra/llui/lltabcontainervertical.h @@ -4,6 +4,7 @@ * * Copyright (c) 2001-2007, Linden Research, Inc. * + * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement diff --git a/linden/indra/llui/lltextbox.cpp b/linden/indra/llui/lltextbox.cpp index d70f223..884d638 100644 --- a/linden/indra/llui/lltextbox.cpp +++ b/linden/indra/llui/lltextbox.cpp @@ -4,6 +4,7 @@ * * Copyright (c) 2001-2007, Linden Research, Inc. * + * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement @@ -113,7 +114,7 @@ BOOL LLTextBox::handleMouseDown(S32 x, S32 y, MASK mask) handled = TRUE; // Route future Mouse messages here preemptively. (Release on mouse up.) - gFocusMgr.setMouseCapture( this, NULL ); + gFocusMgr.setMouseCapture( this ); if (mSoundFlags & MOUSE_DOWN) { @@ -134,12 +135,12 @@ BOOL LLTextBox::handleMouseUp(S32 x, S32 y, MASK mask) // HACK: Only do this if there actually is a click callback, so that // overly large text boxes in the older UI won't start eating clicks. if (mClickedCallback - && this == gFocusMgr.getMouseCapture()) + && hasMouseCapture()) { handled = TRUE; // Release the mouse - gFocusMgr.setMouseCapture( NULL, NULL ); + gFocusMgr.setMouseCapture( NULL ); if (mSoundFlags & MOUSE_UP) { @@ -347,7 +348,7 @@ void LLTextBox::draw() void LLTextBox::reshape(S32 width, S32 height, BOOL called_from_parent) { // reparse line lengths - setText(mText); + setLineLengths(); LLView::reshape(width, height, called_from_parent); } diff --git a/linden/indra/llui/lltextbox.h b/linden/indra/llui/lltextbox.h index 7e445e1..45d6acb 100644 --- a/linden/indra/llui/lltextbox.h +++ b/linden/indra/llui/lltextbox.h @@ -4,6 +4,7 @@ * * Copyright (c) 2001-2007, Linden Research, Inc. * + * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement diff --git a/linden/indra/llui/lltexteditor.cpp b/linden/indra/llui/lltexteditor.cpp index 8f22545..787eba5 100644 --- a/linden/indra/llui/lltexteditor.cpp +++ b/linden/indra/llui/lltexteditor.cpp @@ -4,6 +4,7 @@ * * Copyright (c) 2001-2007, Linden Research, Inc. * + * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement @@ -812,6 +813,31 @@ LLWString LLTextEditor::getWSubString(S32 pos, S32 len) return mWText.substr(pos, len); } +LLTextSegment* LLTextEditor::getCurrentSegment() +{ + return getSegmentAtOffset(mCursorPos); +} + +LLTextSegment* LLTextEditor::getPreviousSegment() +{ + // find segment index at character to left of cursor (or rightmost edge of selection) + S32 idx = llmax(0, getSegmentIdxAtOffset(mCursorPos) - 1); + return idx >= 0 ? mSegments[idx] : NULL; +} + +void LLTextEditor::getSelectedSegments(std::vector& segments) +{ + S32 left = hasSelection() ? llmin(mSelectionStart, mSelectionEnd) : mCursorPos; + S32 right = hasSelection() ? llmax(mSelectionStart, mSelectionEnd) : mCursorPos; + S32 first_idx = llmax(0, getSegmentIdxAtOffset(left)); + S32 last_idx = llmax(0, first_idx, getSegmentIdxAtOffset(right)); + + for (S32 idx = first_idx; idx <= last_idx; ++idx) + { + segments.push_back(mSegments[idx]); + } +} + S32 LLTextEditor::getCursorPosFromLocalCoord( S32 local_x, S32 local_y, BOOL round ) { // If round is true, if the position is on the right half of a character, the cursor @@ -1201,7 +1227,7 @@ BOOL LLTextEditor::handleMouseDown(S32 x, S32 y, MASK mask) setCursorAtLocalPos( x, y, TRUE ); startSelection(); } - gFocusMgr.setMouseCapture( this, &LLTextEditor::onMouseCaptureLost ); + gFocusMgr.setMouseCapture( this ); } handled = TRUE; @@ -1227,7 +1253,7 @@ BOOL LLTextEditor::handleHover(S32 x, S32 y, MASK mask) mHoverSegment = NULL; if( getVisible() ) { - if(gFocusMgr.getMouseCapture() == this ) + if(hasMouseCapture() ) { if( mIsSelecting ) { @@ -1360,9 +1386,9 @@ BOOL LLTextEditor::handleMouseUp(S32 x, S32 y, MASK mask) // Delay cursor flashing mKeystrokeTimer.reset(); - if( gFocusMgr.getMouseCapture() == this ) + if( hasMouseCapture() ) { - gFocusMgr.setMouseCapture( NULL, NULL ); + gFocusMgr.setMouseCapture( NULL ); handled = TRUE; } @@ -2473,6 +2499,8 @@ void LLTextEditor::onFocusLost() // Make sure cursor is shown again getWindow()->showCursorFromMouseMove(); + + LLUICtrl::onFocusLost(); } void LLTextEditor::setEnabled(BOOL enabled) @@ -3753,11 +3781,9 @@ S32 LLTextEditor::getSegmentIdxAtOffset(S32 offset) } } -//static -void LLTextEditor::onMouseCaptureLost( LLMouseHandler* old_captor ) +void LLTextEditor::onMouseCaptureLost() { - LLTextEditor* self = (LLTextEditor*) old_captor; - self->endSelection(); + endSelection(); } void LLTextEditor::setOnScrollEndCallback(void (*callback)(void*), void* userdata) diff --git a/linden/indra/llui/lltexteditor.h b/linden/indra/llui/lltexteditor.h index e5ba8ca..32375be 100644 --- a/linden/indra/llui/lltexteditor.h +++ b/linden/indra/llui/lltexteditor.h @@ -4,6 +4,7 @@ * * Copyright (c) 2001-2007, Linden Research, Inc. * + * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement @@ -94,6 +95,8 @@ public: virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDragAndDropType cargo_type, void *cargo_data, EAcceptance *accept, LLString& tooltip_msg); + virtual void onMouseCaptureLost(); + // view overrides virtual void reshape(S32 width, S32 height, BOOL called_from_parent); @@ -209,7 +212,6 @@ public: void setHandleEditKeysDirectly( BOOL b ) { mHandleEditKeysDirectly = b; } // Callbacks - static void onMouseCaptureLost( LLMouseHandler* old_captor ); static void setLinkColor(LLColor4 color) { mLinkColor = color; } static void setURLCallbacks( void (*callback1) (const char* url), BOOL (*callback2) (LLString url) ) @@ -239,6 +241,10 @@ public: llwchar getWChar(S32 pos); LLWString getWSubString(S32 pos, S32 len); + LLTextSegment* getCurrentSegment(); + LLTextSegment* getPreviousSegment(); + void getSelectedSegments(std::vector& segments); + protected: S32 getLength() const; void getSegmentAndOffset( S32 startpos, S32* segidxp, S32* offsetp ); diff --git a/linden/indra/llui/llui.cpp b/linden/indra/llui/llui.cpp index 61dede2..9d689b5 100644 --- a/linden/indra/llui/llui.cpp +++ b/linden/indra/llui/llui.cpp @@ -4,6 +4,7 @@ * * Copyright (c) 2001-2007, Linden Research, Inc. * + * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement @@ -74,6 +75,7 @@ LLImageProviderInterface* LLUI::sImageProvider = NULL; LLUIAudioCallback LLUI::sAudioCallback = NULL; LLVector2 LLUI::sGLScaleFactor(1.f, 1.f); LLWindow* LLUI::sWindow = NULL; +LLHtmlHelp* LLUI::sHtmlHelp = NULL; BOOL LLUI::sShowXUINames = FALSE; // // Functions @@ -406,7 +408,7 @@ void gl_corners_2d(S32 left, S32 top, S32 right, S32 bottom, S32 length, F32 max void gl_draw_image( S32 x, S32 y, LLImageGL* image, const LLColor4& color ) { - gl_draw_scaled_rotated_image( x, y, image->getWidth(), image->getHeight(), 0.f, image, color ); + gl_draw_scaled_rotated_image( x, y, image->getWidth(0), image->getHeight(0), 0.f, image, color ); } void gl_draw_scaled_image(S32 x, S32 y, S32 width, S32 height, LLImageGL* image, const LLColor4& color) @@ -458,8 +460,8 @@ void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 border_width, S32 border glColor4fv(color.mV); - F32 border_width_fraction = (F32)border_width / (F32)image->getWidth(); - F32 border_height_fraction = (F32)border_height / (F32)image->getHeight(); + F32 border_width_fraction = (F32)border_width / (F32)image->getWidth(0); + F32 border_height_fraction = (F32)border_height / (F32)image->getHeight(0); glBegin(GL_QUADS); { @@ -592,7 +594,7 @@ void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 border_width, S32 border void gl_draw_rotated_image(S32 x, S32 y, F32 degrees, LLImageGL* image, const LLColor4& color) { - gl_draw_scaled_rotated_image( x, y, image->getWidth(), image->getHeight(), degrees, image, color ); + gl_draw_scaled_rotated_image( x, y, image->getWidth(0), image->getHeight(0), degrees, image, color ); } void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degrees, LLImageGL* image, const LLColor4& color) @@ -1742,6 +1744,10 @@ LLString LLUI::locateSkin(const LLString& filename) if (!gDirUtilp->fileExists(found_file)) { LLString localization(sConfigGroup->getString("Language")); + if(localization == "default") + { + localization = sConfigGroup->getString("SystemLanguage"); + } LLString local_skin = "xui" + slash + localization + slash + filename; found_file = gDirUtilp->getExpandedFilename(LL_PATH_SKINS, local_skin); } @@ -1781,3 +1787,9 @@ LLUUID LLUI::findAssetUUIDByName(const LLString &asset_name) } return LLUUID( foundValue ); } + +// static +void LLUI::setHtmlHelp(LLHtmlHelp* html_help) +{ + LLUI::sHtmlHelp = html_help; +} diff --git a/linden/indra/llui/llui.h b/linden/indra/llui/llui.h index cd57990..6b8a86a 100644 --- a/linden/indra/llui/llui.h +++ b/linden/indra/llui/llui.h @@ -4,6 +4,7 @@ * * Copyright (c) 2001-2007, Linden Research, Inc. * + * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement @@ -34,6 +35,7 @@ #include "llcontrol.h" #include "llrect.h" #include "llcoord.h" +#include "llhtmlhelp.h" class LLColor4; class LLVector3; @@ -170,6 +172,7 @@ public: static void setLineWidth(F32 width); static LLUUID findAssetUUIDByName(const LLString& name); static LLVector2 getWindowSize(); + static void setHtmlHelp(LLHtmlHelp* html_help); public: static LLControlGroup* sConfigGroup; static LLControlGroup* sColorsGroup; @@ -179,6 +182,7 @@ public: static LLVector2 sGLScaleFactor; static LLWindow* sWindow; static BOOL sShowXUINames; + static LLHtmlHelp* sHtmlHelp; }; // UI widgets diff --git a/linden/indra/llui/llui.vcproj b/linden/indra/llui/llui.vcproj index e3d0da6..37428d2 100644 --- a/linden/indra/llui/llui.vcproj +++ b/linden/indra/llui/llui.vcproj @@ -310,6 +310,9 @@ RelativePath=".\llfocusmgr.h"> + + getString("Language"); + if(language == "default") + { + language = LLUI::sConfigGroup->getString("SystemLanguage"); + } } path_val_ui.setArg("[Language]", language); LLString fullpath = app_dir + path_val_ui.getString(); diff --git a/linden/indra/llui/lluictrlfactory.h b/linden/indra/llui/lluictrlfactory.h index b96dc5d..18b0ba9 100644 --- a/linden/indra/llui/lluictrlfactory.h +++ b/linden/indra/llui/lluictrlfactory.h @@ -4,6 +4,7 @@ * * Copyright (c) 2003-2007, Linden Research, Inc. * + * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement diff --git a/linden/indra/llui/lluistring.cpp b/linden/indra/llui/lluistring.cpp index 5029082..49b6fca 100755 --- a/linden/indra/llui/lluistring.cpp +++ b/linden/indra/llui/lluistring.cpp @@ -4,6 +4,7 @@ * * Copyright (c) 2006-2007, Linden Research, Inc. * + * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement diff --git a/linden/indra/llui/lluistring.h b/linden/indra/llui/lluistring.h index efd200a..37792aa 100755 --- a/linden/indra/llui/lluistring.h +++ b/linden/indra/llui/lluistring.h @@ -5,6 +5,7 @@ * * Copyright (c) 2006-2007, Linden Research, Inc. * + * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement diff --git a/linden/indra/llui/lluixmltags.h b/linden/indra/llui/lluixmltags.h index 5de4d90..08c5f67 100644 --- a/linden/indra/llui/lluixmltags.h +++ b/linden/indra/llui/lluixmltags.h @@ -3,6 +3,7 @@ * * Copyright (c) 2006-2007, Linden Research, Inc. * + * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement diff --git a/linden/indra/llui/llundo.cpp b/linden/indra/llui/llundo.cpp index b662a1a..4e62bad 100644 --- a/linden/indra/llui/llundo.cpp +++ b/linden/indra/llui/llundo.cpp @@ -4,6 +4,7 @@ * * Copyright (c) 2001-2007, Linden Research, Inc. * + * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement diff --git a/linden/indra/llui/llundo.h b/linden/indra/llui/llundo.h index 10d556f..9a4bece 100644 --- a/linden/indra/llui/llundo.h +++ b/linden/indra/llui/llundo.h @@ -4,6 +4,7 @@ * * Copyright (c) 2000-2007, Linden Research, Inc. * + * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement diff --git a/linden/indra/llui/llview.cpp b/linden/indra/llui/llview.cpp index 13f1ddc..d150e10 100644 --- a/linden/indra/llui/llview.cpp +++ b/linden/indra/llui/llview.cpp @@ -5,6 +5,7 @@ * * Copyright (c) 2001-2007, Linden Research, Inc. * + * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement @@ -174,18 +175,12 @@ LLView::~LLView() gFocusMgr.removeKeyboardFocusWithoutCallback( this ); } - if( gFocusMgr.getMouseCapture() == this ) + if( hasMouseCapture() ) { llwarns << "View holding mouse capture deleted: " << getName() << ". Mouse capture removed." << llendl; gFocusMgr.removeMouseCaptureWithoutCallback( this ); } - if( gFocusMgr.getTopView() == this ) - { - llwarns << "View holding top view deleted: " << getName() << ". Top view removed." << llendl; - gFocusMgr.removeTopViewWithoutCallback( this ); - } - sViewHandleMap.erase(mViewHandle); deleteAllChildren(); @@ -752,9 +747,9 @@ void LLView::setEnabled(BOOL enabled) // virtual void LLView::setVisible(BOOL visible) { - if( !visible && (gFocusMgr.getTopView() == this) ) + if( !visible && (gFocusMgr.getTopCtrl() == this) ) { - gFocusMgr.setTopView( NULL, NULL ); + gFocusMgr.setTopCtrl( NULL ); } if ( mVisible != visible ) @@ -1053,7 +1048,14 @@ LLView* LLView::childrenHandleDragAndDrop(S32 x, S32 y, MASK mask, return handled_view; } +void LLView::onMouseCaptureLost() +{ +} +BOOL LLView::hasMouseCapture() +{ + return gFocusMgr.getMouseCapture() == this; +} BOOL LLView::handleMouseUp(S32 x, S32 y, MASK mask) { @@ -1610,6 +1612,13 @@ const LLRect LLView::getLocalRect() const return local_rect; } +const LLRect LLView::getLocalSnapRect() const +{ + LLRect local_snap_rect = getSnapRect(); + local_snap_rect.translate(-mRect.mLeft, -mRect.mBottom); + return local_snap_rect; +} + void LLView::updateRect() { if (mSpanChildren && mChildList.size()) @@ -2106,6 +2115,12 @@ const LLCtrlQuery & LLView::getFocusRootsQuery() } +void LLView::userSetShape(const LLRect& new_rect) +{ + reshape(new_rect.getWidth(), new_rect.getHeight()); + translate(new_rect.mLeft - mRect.mLeft, new_rect.mBottom - mRect.mBottom); +} + LLView* LLView::findSnapRect(LLRect& new_rect, const LLCoordGL& mouse_dir, LLView::ESnapType snap_type, S32 threshold, S32 padding) { @@ -2127,8 +2142,7 @@ LLView* LLView::findSnapRect(LLRect& new_rect, const LLCoordGL& mouse_dir, BOOL snapped_x = FALSE; BOOL snapped_y = FALSE; - LLRect parent_local_snap_rect = mParentView->getSnapRect(); - parent_local_snap_rect.translate(-mParentView->getRect().mLeft, -mParentView->getRect().mBottom); + LLRect parent_local_snap_rect = mParentView->getLocalSnapRect(); if (snap_type == SNAP_PARENT || snap_type == SNAP_PARENT_AND_SIBLINGS) { @@ -2303,8 +2317,7 @@ LLView* LLView::findSnapEdge(S32& new_edge_val, const LLCoordGL& mouse_dir, ESna BOOL snapped_x = FALSE; BOOL snapped_y = FALSE; - LLRect parent_local_snap_rect = mParentView->getSnapRect(); - parent_local_snap_rect.translate(-mParentView->getRect().mLeft, -mParentView->getRect().mBottom); + LLRect parent_local_snap_rect = mParentView->getLocalSnapRect(); if (snap_type == SNAP_PARENT || snap_type == SNAP_PARENT_AND_SIBLINGS) { diff --git a/linden/indra/llui/llview.h b/linden/indra/llui/llview.h index 3885789..cb9a35c 100644 --- a/linden/indra/llui/llview.h +++ b/linden/indra/llui/llview.h @@ -4,6 +4,7 @@ * * Copyright (c) 2001-2007, Linden Research, Inc. * + * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement @@ -313,6 +314,7 @@ public: const LLRect getScreenRect() const; const LLRect getLocalRect() const; virtual const LLRect getSnapRect() const { return mRect; } + virtual const LLRect getLocalSnapRect() const; virtual LLRect getRequiredRect(); // Get required size for this object. 0 for width/height means don't care. virtual void updateRect(); // apply procedural updates to own rectangle @@ -334,12 +336,13 @@ public: // Default behavior is to use reshape flags to resize child views virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); - virtual void translate( S32 x, S32 y ); virtual void setOrigin( S32 x, S32 y ) { mRect.translate( x - mRect.mLeft, y - mRect.mBottom ); } BOOL translateIntoRect( const LLRect& constraint, BOOL allow_partial_outside ); - LLView* findSnapRect(LLRect& new_rect, const LLCoordGL& mouse_dir, LLView::ESnapType snap_type, S32 threshold, S32 padding = 0); - LLView* findSnapEdge(S32& new_edge_val, const LLCoordGL& mouse_dir, ESnapEdge snap_edge, ESnapType snap_type, S32 threshold, S32 padding = 0); + + virtual void userSetShape(const LLRect& new_rect); + virtual LLView* findSnapRect(LLRect& new_rect, const LLCoordGL& mouse_dir, LLView::ESnapType snap_type, S32 threshold, S32 padding = 0); + virtual LLView* findSnapEdge(S32& new_edge_val, const LLCoordGL& mouse_dir, ESnapEdge snap_edge, ESnapType snap_type, S32 threshold, S32 padding = 0); // Defaults to other_view->getVisible() virtual BOOL canSnapTo(LLView* other_view); @@ -364,6 +367,8 @@ public: /*virtual*/ BOOL handleScrollWheel(S32 x, S32 y, S32 clicks); /*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); /*virtual*/ BOOL handleRightMouseUp(S32 x, S32 y, MASK mask); + /*virtual*/ void onMouseCaptureLost(); + /*virtual*/ BOOL hasMouseCapture(); // Default behavior is to pass the tooltip event to children, // then display mToolTipMsg if no child handled it. diff --git a/linden/indra/llui/llviewborder.cpp b/linden/indra/llui/llviewborder.cpp index c26a818..4c2b602 100644 --- a/linden/indra/llui/llviewborder.cpp +++ b/linden/indra/llui/llviewborder.cpp @@ -4,6 +4,7 @@ * * Copyright (c) 2001-2007, Linden Research, Inc. * + * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement diff --git a/linden/indra/llui/llviewborder.h b/linden/indra/llui/llviewborder.h index 2795a71..7e5de4b 100644 --- a/linden/indra/llui/llviewborder.h +++ b/linden/indra/llui/llviewborder.h @@ -4,6 +4,7 @@ * * Copyright (c) 2001-2007, Linden Research, Inc. * + * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement diff --git a/linden/indra/llui/llviewquery.cpp b/linden/indra/llui/llviewquery.cpp index 89b2192..3f9ccf4 100644 --- a/linden/indra/llui/llviewquery.cpp +++ b/linden/indra/llui/llviewquery.cpp @@ -4,6 +4,7 @@ * * Copyright (c) 2001-2007, Linden Research, Inc. * + * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement diff --git a/linden/indra/llui/llviewquery.h b/linden/indra/llui/llviewquery.h index 7ab401a..a35726a 100644 --- a/linden/indra/llui/llviewquery.h +++ b/linden/indra/llui/llviewquery.h @@ -4,6 +4,7 @@ * * Copyright (c) 2001-2007, Linden Research, Inc. * + * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement -- cgit v1.1