summaryrefslogtreecommitdiff
path: root/indra/llui/lldraghandle.cpp
diff options
context:
space:
mode:
authorJames Cook <james@lindenlab.com>2007-01-02 08:33:20 +0000
committerJames Cook <james@lindenlab.com>2007-01-02 08:33:20 +0000
commit420b91db29485df39fd6e724e782c449158811cb (patch)
treeb471a94563af914d3ed3edd3e856d21cb1b69945 /indra/llui/lldraghandle.cpp
Print done when done.
Diffstat (limited to 'indra/llui/lldraghandle.cpp')
-rw-r--r--indra/llui/lldraghandle.cpp353
1 files changed, 353 insertions, 0 deletions
diff --git a/indra/llui/lldraghandle.cpp b/indra/llui/lldraghandle.cpp
new file mode 100644
index 0000000000..a88fbb7744
--- /dev/null
+++ b/indra/llui/lldraghandle.cpp
@@ -0,0 +1,353 @@
+/**
+ * @file lldraghandle.cpp
+ * @brief LLDragHandle base class
+ *
+ * Copyright (c) 2001-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+// 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)" <<llendl;
+ handled = TRUE;
+ }
+ else if( getVisible() )
+ {
+ getWindow()->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());
+}