From 38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 Mon Sep 17 00:00:00 2001 From: Jacek Antonelli Date: Fri, 15 Aug 2008 23:44:46 -0500 Subject: Second Life viewer sources 1.13.2.12 --- linden/indra/llui/lldraghandle.cpp | 372 +++++++++++++++++++++++++++++++++++++ 1 file changed, 372 insertions(+) create mode 100644 linden/indra/llui/lldraghandle.cpp (limited to 'linden/indra/llui/lldraghandle.cpp') diff --git a/linden/indra/llui/lldraghandle.cpp b/linden/indra/llui/lldraghandle.cpp new file mode 100644 index 0000000..261d149 --- /dev/null +++ b/linden/indra/llui/lldraghandle.cpp @@ -0,0 +1,372 @@ +/** + * @file lldraghandle.cpp + * @brief LLDragHandle base class + * + * Copyright (c) 2001-2007, Linden Research, Inc. + * + * 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. + */ + +// A widget for dragging a view around the screen using the mouse. + +#include "linden_common.h" + +#include "lldraghandle.h" + +#include "llmath.h" + +//#include "llviewerwindow.h" +#include "llui.h" +#include "llmenugl.h" +#include "lltextbox.h" +#include "llcontrol.h" +#include "llresmgr.h" +#include "llfontgl.h" +#include "llwindow.h" +#include "llfocusmgr.h" + +const S32 LEADING_PAD = 5; +const S32 TITLE_PAD = 8; +const S32 BORDER_PAD = 1; +const S32 LEFT_PAD = BORDER_PAD + TITLE_PAD + LEADING_PAD; +const S32 RIGHT_PAD = BORDER_PAD + 32; // HACK: space for close btn and minimize btn + +S32 LLDragHandle::sSnapMargin = 5; + +LLDragHandle::LLDragHandle( const LLString& name, const LLRect& rect, const LLString& title ) +: LLView( name, rect, TRUE ), + mDragLastScreenX( 0 ), + mDragLastScreenY( 0 ), + mLastMouseScreenX( 0 ), + mLastMouseScreenY( 0 ), + mDragHighlightColor( LLUI::sColorsGroup->getColor( "DefaultHighlightLight" ) ), + mDragShadowColor( LLUI::sColorsGroup->getColor( "DefaultShadowDark" ) ), + mTitleBox( NULL ), + mMaxTitleWidth( 0 ), + mForeground( TRUE ) +{ + sSnapMargin = LLUI::sConfigGroup->getS32("SnapMargin"); + + setSaveToXML(false); +} + +void LLDragHandle::setTitleVisible(BOOL visible) +{ + mTitleBox->setVisible(visible); +} + +LLDragHandleTop::LLDragHandleTop(const LLString& name, const LLRect &rect, const LLString& title) +: LLDragHandle(name, rect, title) +{ + setFollowsAll(); + setTitle( title ); +} + +EWidgetType LLDragHandleTop::getWidgetType() const +{ + return WIDGET_TYPE_DRAG_HANDLE_TOP; +} + +LLString LLDragHandleTop::getWidgetTag() const +{ + return LL_DRAG_HANDLE_TOP_TAG; +} + +LLDragHandleLeft::LLDragHandleLeft(const LLString& name, const LLRect &rect, const LLString& title) +: LLDragHandle(name, rect, title) +{ + setFollowsAll(); + setTitle( title ); +} + +EWidgetType LLDragHandleLeft::getWidgetType() const +{ + return WIDGET_TYPE_DRAG_HANDLE_LEFT; +} + +LLString LLDragHandleLeft::getWidgetTag() const +{ + return LL_DRAG_HANDLE_LEFT_TAG; +} + +void LLDragHandleTop::setTitle(const LLString& title) +{ + if( mTitleBox ) + { + removeChild(mTitleBox); + delete mTitleBox; + } + + LLString trimmed_title = title; + LLString::trim(trimmed_title); + + const LLFontGL* font = gResMgr->getRes( LLFONT_SANSSERIF ); + mTitleBox = new LLTextBox( "Drag Handle Title", mRect, trimmed_title, font ); + mTitleBox->setFollows(FOLLOWS_TOP | FOLLOWS_LEFT | FOLLOWS_RIGHT); + reshapeTitleBox(); + + // allow empty titles, as default behavior replaces them with title box name + if (trimmed_title.empty()) + { + mTitleBox->setText(LLString::null); + } + addChild( mTitleBox ); +} + + +const LLString& LLDragHandleTop::getTitle() const +{ + return mTitleBox->getText(); +} + + +void LLDragHandleLeft::setTitle(const LLString& ) +{ + if( mTitleBox ) + { + removeChild(mTitleBox); + delete mTitleBox; + } + + mTitleBox = NULL; + + /* no title on left edge */ +} + + +const LLString& LLDragHandleLeft::getTitle() const +{ + return LLString::null; +} + + +void LLDragHandleTop::draw() +{ + /* Disable lines. Can drag anywhere in most windows. JC + if( getVisible() && mEnabled && mForeground) + { + const S32 BORDER_PAD = 2; + const S32 HPAD = 2; + const S32 VPAD = 2; + S32 left = BORDER_PAD + HPAD; + S32 top = mRect.getHeight() - 2 * VPAD; + S32 right = mRect.getWidth() - HPAD; +// S32 bottom = VPAD; + + // draw lines for drag areas + + const S32 LINE_SPACING = (DRAG_HANDLE_HEIGHT - 2 * VPAD) / 4; + S32 line = top - LINE_SPACING; + + LLRect title_rect = mTitleBox->getRect(); + S32 title_right = title_rect.mLeft + mTitleWidth; + BOOL show_right_side = title_right < mRect.getWidth(); + + for( S32 i=0; i<4; i++ ) + { + gl_line_2d(left, line+1, title_rect.mLeft - LEADING_PAD, line+1, mDragHighlightColor); + if( show_right_side ) + { + gl_line_2d(title_right, line+1, right, line+1, mDragHighlightColor); + } + + gl_line_2d(left, line, title_rect.mLeft - LEADING_PAD, line, mDragShadowColor); + if( show_right_side ) + { + gl_line_2d(title_right, line, right, line, mDragShadowColor); + } + line -= LINE_SPACING; + } + } + */ + + // Colorize the text to match the frontmost state + if (mTitleBox) + { + mTitleBox->setEnabled(mForeground); + } + + LLView::draw(); +} + + +// assumes GL state is set for 2D +void LLDragHandleLeft::draw() +{ + /* Disable lines. Can drag anywhere in most windows. JC + if( getVisible() && mEnabled && mForeground ) + { + const S32 BORDER_PAD = 2; +// const S32 HPAD = 2; + const S32 VPAD = 2; + const S32 LINE_SPACING = 3; + + S32 left = BORDER_PAD + LINE_SPACING; + S32 top = mRect.getHeight() - 2 * VPAD; +// S32 right = mRect.getWidth() - HPAD; + S32 bottom = VPAD; + + // draw lines for drag areas + + // no titles yet + //LLRect title_rect = mTitleBox->getRect(); + //S32 title_right = title_rect.mLeft + mTitleWidth; + //BOOL show_right_side = title_right < mRect.getWidth(); + + S32 line = left; + for( S32 i=0; i<4; i++ ) + { + gl_line_2d(line, top, line, bottom, mDragHighlightColor); + + gl_line_2d(line+1, top, line+1, bottom, mDragShadowColor); + + line += LINE_SPACING; + } + } + */ + + // Colorize the text to match the frontmost state + if (mTitleBox) + { + mTitleBox->setEnabled(mForeground); + } + + LLView::draw(); +} + +void LLDragHandleTop::reshapeTitleBox() +{ + const LLFontGL* font = gResMgr->getRes( LLFONT_SANSSERIF ); + S32 title_width = font->getWidth( mTitleBox->getText() ) + TITLE_PAD; + if (mMaxTitleWidth > 0) + title_width = llmin(title_width, mMaxTitleWidth); + S32 title_height = llround(font->getLineHeight()); + LLRect title_rect; + title_rect.setLeftTopAndSize( + LEFT_PAD, + mRect.getHeight() - BORDER_PAD, + mRect.getWidth() - LEFT_PAD - RIGHT_PAD, + title_height); + + mTitleBox->setRect( title_rect ); +} + +void LLDragHandleTop::reshape(S32 width, S32 height, BOOL called_from_parent) +{ + LLView::reshape(width, height, called_from_parent); + reshapeTitleBox(); +} + +void LLDragHandleLeft::reshape(S32 width, S32 height, BOOL called_from_parent) +{ + LLView::reshape(width, height, called_from_parent); +} + +//------------------------------------------------------------- +// UI event handling +//------------------------------------------------------------- + +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 ); + + localPointToScreen(x, y, &mDragLastScreenX, &mDragLastScreenY); + mLastMouseScreenX = mDragLastScreenX; + mLastMouseScreenY = mDragLastScreenY; + + // Note: don't pass on to children + return TRUE; +} + + +BOOL LLDragHandle::handleMouseUp(S32 x, S32 y, MASK mask) +{ + if( gFocusMgr.getMouseCapture() == this ) + { + // Release the mouse + gFocusMgr.setMouseCapture( NULL, NULL ); + } + + // Note: don't pass on to children + return TRUE; +} + + +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 ) + { + S32 screen_x; + S32 screen_y; + localPointToScreen(x, y, &screen_x, &screen_y); + + // Resize the parent + S32 delta_x = screen_x - mDragLastScreenX; + S32 delta_y = screen_y - mDragLastScreenY; + getParent()->translate(delta_x, delta_y); + S32 pre_snap_x = getParent()->getRect().mLeft; + S32 pre_snap_y = getParent()->getRect().mBottom; + mDragLastScreenX = screen_x; + mDragLastScreenY = screen_y; + + LLRect new_rect; + 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; + mouse_dir.mY = (screen_y == mLastMouseScreenY) ? mLastMouseDir.mY : screen_y - mLastMouseScreenY; + mLastMouseDir = mouse_dir; + mLastMouseScreenX = screen_x; + mLastMouseScreenY = screen_y; + + LLView* snap_view = getParent()->findSnapRect(new_rect, mouse_dir, SNAP_PARENT_AND_SIBLINGS, sSnapMargin); + + getParent()->snappedTo(snap_view); + delta_x = new_rect.mLeft - pre_snap_x; + delta_y = new_rect.mBottom - pre_snap_y; + getParent()->translate(delta_x, delta_y); + mDragLastScreenX += delta_x; + mDragLastScreenY += delta_y; + + getWindow()->setCursor(UI_CURSOR_ARROW); + lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << " (active)" <setCursor(UI_CURSOR_ARROW); + lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << " (inactive)" << llendl; + handled = TRUE; + } + + // Note: don't pass on to children + + return handled; +} + +void LLDragHandle::setValue(const LLSD& value) +{ + setTitle(value.asString()); +} -- cgit v1.1