lldraghandle.cpp

Go to the documentation of this file.
00001 
00032 // A widget for dragging a view around the screen using the mouse.
00033 
00034 #include "linden_common.h"
00035 
00036 #include "lldraghandle.h"
00037 
00038 #include "llmath.h"
00039 
00040 //#include "llviewerwindow.h"
00041 #include "llui.h"
00042 #include "llmenugl.h"
00043 #include "lltextbox.h"
00044 #include "llcontrol.h"
00045 #include "llresmgr.h"
00046 #include "llfontgl.h"
00047 #include "llwindow.h"
00048 #include "llfocusmgr.h"
00049 
00050 const S32 LEADING_PAD = 5;
00051 const S32 TITLE_PAD = 8;
00052 const S32 BORDER_PAD = 1;
00053 const S32 LEFT_PAD = BORDER_PAD + TITLE_PAD + LEADING_PAD;
00054 const S32 RIGHT_PAD = BORDER_PAD + 32; // HACK: space for close btn and minimize btn
00055 
00056 S32 LLDragHandle::sSnapMargin = 5;
00057 
00058 LLDragHandle::LLDragHandle( const LLString& name, const LLRect& rect, const LLString& title )
00059 :       LLView( name, rect, TRUE ),
00060         mDragLastScreenX( 0 ),
00061         mDragLastScreenY( 0 ),
00062         mLastMouseScreenX( 0 ),
00063         mLastMouseScreenY( 0 ),
00064         mDragHighlightColor(    LLUI::sColorsGroup->getColor( "DefaultHighlightLight" ) ),
00065         mDragShadowColor(               LLUI::sColorsGroup->getColor( "DefaultShadowDark" ) ),
00066         mTitleBox( NULL ),
00067         mMaxTitleWidth( 0 ),
00068         mForeground( TRUE )
00069 {
00070         sSnapMargin = LLUI::sConfigGroup->getS32("SnapMargin");
00071 
00072         setSaveToXML(false);
00073 }
00074 
00075 void LLDragHandle::setTitleVisible(BOOL visible) 
00076 { 
00077         mTitleBox->setVisible(visible); 
00078 }
00079 
00080 LLDragHandleTop::LLDragHandleTop(const LLString& name, const LLRect &rect, const LLString& title)
00081 :       LLDragHandle(name, rect, title)
00082 {
00083         setFollowsAll();
00084         setTitle( title );
00085 }
00086 
00087 EWidgetType LLDragHandleTop::getWidgetType() const
00088 {
00089         return WIDGET_TYPE_DRAG_HANDLE_TOP;
00090 }
00091 
00092 LLString LLDragHandleTop::getWidgetTag() const
00093 {
00094         return LL_DRAG_HANDLE_TOP_TAG;
00095 }
00096 
00097 LLDragHandleLeft::LLDragHandleLeft(const LLString& name, const LLRect &rect, const LLString& title)
00098 :       LLDragHandle(name, rect, title)
00099 {
00100         setFollowsAll();
00101         setTitle( title );
00102 }
00103 
00104 EWidgetType LLDragHandleLeft::getWidgetType() const
00105 {
00106         return WIDGET_TYPE_DRAG_HANDLE_LEFT;
00107 }
00108 
00109 LLString LLDragHandleLeft::getWidgetTag() const
00110 {
00111         return LL_DRAG_HANDLE_LEFT_TAG;
00112 }
00113 
00114 void LLDragHandleTop::setTitle(const LLString& title)
00115 {
00116         if( mTitleBox )
00117         {
00118                 removeChild(mTitleBox);
00119                 delete mTitleBox;
00120         }
00121 
00122         LLString trimmed_title = title;
00123         LLString::trim(trimmed_title);
00124 
00125         const LLFontGL* font = gResMgr->getRes( LLFONT_SANSSERIF );
00126         mTitleBox = new LLTextBox( "Drag Handle Title", mRect, trimmed_title, font );
00127         mTitleBox->setFollows(FOLLOWS_TOP | FOLLOWS_LEFT | FOLLOWS_RIGHT);
00128         mTitleBox->setFontStyle(LLFontGL::DROP_SHADOW_SOFT);
00129         reshapeTitleBox();
00130         
00131         // allow empty titles, as default behavior replaces them with title box name
00132         if (trimmed_title.empty())
00133         {
00134                 mTitleBox->setText(LLString::null);
00135         }
00136         addChild( mTitleBox );
00137 }
00138 
00139 
00140 const LLString& LLDragHandleTop::getTitle() const
00141 {
00142         return mTitleBox->getText();
00143 }
00144 
00145 
00146 void LLDragHandleLeft::setTitle(const LLString& )
00147 {
00148         if( mTitleBox )
00149         {
00150                 removeChild(mTitleBox);
00151                 delete mTitleBox;
00152         }
00153 
00154         mTitleBox = NULL;
00155 
00156         /* no title on left edge */
00157 }
00158 
00159 
00160 const LLString& LLDragHandleLeft::getTitle() const
00161 {
00162         return LLString::null;
00163 }
00164 
00165 
00166 void LLDragHandleTop::draw()
00167 {
00168         /* Disable lines.  Can drag anywhere in most windows.  JC
00169         if( getVisible() && mEnabled && mForeground) 
00170         {
00171                 const S32 BORDER_PAD = 2;
00172                 const S32 HPAD = 2;
00173                 const S32 VPAD = 2;
00174                 S32 left = BORDER_PAD + HPAD;
00175                 S32 top = mRect.getHeight() - 2 * VPAD;
00176                 S32 right = mRect.getWidth() - HPAD;
00177 //              S32 bottom = VPAD;
00178 
00179                 // draw lines for drag areas
00180 
00181                 const S32 LINE_SPACING = (DRAG_HANDLE_HEIGHT - 2 * VPAD) / 4;
00182                 S32 line = top - LINE_SPACING;
00183 
00184                 LLRect title_rect = mTitleBox->getRect();
00185                 S32 title_right = title_rect.mLeft + mTitleWidth;
00186                 BOOL show_right_side = title_right < mRect.getWidth();
00187 
00188                 for( S32 i=0; i<4; i++ )
00189                 {
00190                         gl_line_2d(left, line+1, title_rect.mLeft - LEADING_PAD, line+1, mDragHighlightColor);
00191                         if( show_right_side )
00192                         {
00193                                 gl_line_2d(title_right, line+1, right, line+1, mDragHighlightColor);
00194                         }
00195 
00196                         gl_line_2d(left, line, title_rect.mLeft - LEADING_PAD, line, mDragShadowColor);
00197                         if( show_right_side )
00198                         {
00199                                 gl_line_2d(title_right, line, right, line, mDragShadowColor);
00200                         }
00201                         line -= LINE_SPACING;
00202                 }
00203         }
00204         */
00205 
00206         // Colorize the text to match the frontmost state
00207         if (mTitleBox)
00208         {
00209                 mTitleBox->setEnabled(mForeground);
00210         }
00211 
00212         LLView::draw();
00213 }
00214 
00215 
00216 // assumes GL state is set for 2D
00217 void LLDragHandleLeft::draw()
00218 {
00219         /* Disable lines.  Can drag anywhere in most windows. JC
00220         if( getVisible() && mEnabled && mForeground ) 
00221         {
00222                 const S32 BORDER_PAD = 2;
00223 //              const S32 HPAD = 2;
00224                 const S32 VPAD = 2;
00225                 const S32 LINE_SPACING = 3;
00226 
00227                 S32 left = BORDER_PAD + LINE_SPACING;
00228                 S32 top = mRect.getHeight() - 2 * VPAD;
00229 //              S32 right = mRect.getWidth() - HPAD;
00230                 S32 bottom = VPAD;
00231  
00232                 // draw lines for drag areas
00233 
00234                 // no titles yet
00235                 //LLRect title_rect = mTitleBox->getRect();
00236                 //S32 title_right = title_rect.mLeft + mTitleWidth;
00237                 //BOOL show_right_side = title_right < mRect.getWidth();
00238 
00239                 S32 line = left;
00240                 for( S32 i=0; i<4; i++ )
00241                 {
00242                         gl_line_2d(line, top, line, bottom, mDragHighlightColor);
00243 
00244                         gl_line_2d(line+1, top, line+1, bottom, mDragShadowColor);
00245 
00246                         line += LINE_SPACING;
00247                 }
00248         }
00249         */
00250 
00251         // Colorize the text to match the frontmost state
00252         if (mTitleBox)
00253         {
00254                 mTitleBox->setEnabled(mForeground);
00255         }
00256 
00257         LLView::draw();
00258 }
00259 
00260 void LLDragHandleTop::reshapeTitleBox()
00261 {
00262         const LLFontGL* font = gResMgr->getRes( LLFONT_SANSSERIF );
00263         S32 title_width = font->getWidth( mTitleBox->getText() ) + TITLE_PAD;
00264         if (mMaxTitleWidth > 0)
00265                 title_width = llmin(title_width, mMaxTitleWidth);
00266         S32 title_height = llround(font->getLineHeight());
00267         LLRect title_rect;
00268         title_rect.setLeftTopAndSize( 
00269                 LEFT_PAD, 
00270                 mRect.getHeight() - BORDER_PAD,
00271                 mRect.getWidth() - LEFT_PAD - RIGHT_PAD,
00272                 title_height);
00273 
00274         mTitleBox->setRect( title_rect );
00275 }
00276 
00277 void LLDragHandleTop::reshape(S32 width, S32 height, BOOL called_from_parent)
00278 {
00279         LLView::reshape(width, height, called_from_parent);
00280         reshapeTitleBox();
00281 }
00282 
00283 void LLDragHandleLeft::reshape(S32 width, S32 height, BOOL called_from_parent)
00284 {
00285         LLView::reshape(width, height, called_from_parent);
00286 }
00287 
00288 //-------------------------------------------------------------
00289 // UI event handling
00290 //-------------------------------------------------------------
00291 
00292 BOOL LLDragHandle::handleMouseDown(S32 x, S32 y, MASK mask)
00293 {
00294         // Route future Mouse messages here preemptively.  (Release on mouse up.)
00295         // No handler needed for focus lost since this clas has no state that depends on it.
00296         gFocusMgr.setMouseCapture(this);
00297 
00298         localPointToScreen(x, y, &mDragLastScreenX, &mDragLastScreenY);
00299         mLastMouseScreenX = mDragLastScreenX;
00300         mLastMouseScreenY = mDragLastScreenY;
00301 
00302         // Note: don't pass on to children
00303         return TRUE;
00304 }
00305 
00306 
00307 BOOL LLDragHandle::handleMouseUp(S32 x, S32 y, MASK mask)
00308 {
00309         if( hasMouseCapture() )
00310         {
00311                 // Release the mouse
00312                 gFocusMgr.setMouseCapture( NULL );
00313         }
00314 
00315         // Note: don't pass on to children
00316         return TRUE;
00317 }
00318 
00319 
00320 BOOL LLDragHandle::handleHover(S32 x, S32 y, MASK mask)
00321 {
00322         BOOL    handled = FALSE;
00323 
00324         // We only handle the click if the click both started and ended within us
00325         if( hasMouseCapture() )
00326         {
00327                 S32 screen_x;
00328                 S32 screen_y;
00329                 localPointToScreen(x, y, &screen_x, &screen_y);
00330 
00331                 // Resize the parent
00332                 S32 delta_x = screen_x - mDragLastScreenX;
00333                 S32 delta_y = screen_y - mDragLastScreenY;
00334 
00335                 LLRect original_rect = getParent()->getRect();
00336                 LLRect translated_rect = getParent()->getRect();
00337                 translated_rect.translate(delta_x, delta_y);
00338                 // temporarily slam dragged window to new position
00339                 getParent()->setRect(translated_rect);
00340                 S32 pre_snap_x = getParent()->getRect().mLeft;
00341                 S32 pre_snap_y = getParent()->getRect().mBottom;
00342                 mDragLastScreenX = screen_x;
00343                 mDragLastScreenY = screen_y;
00344 
00345                 LLRect new_rect;
00346                 LLCoordGL mouse_dir;
00347                 // use hysteresis on mouse motion to preserve user intent when mouse stops moving
00348                 mouse_dir.mX = (screen_x == mLastMouseScreenX) ? mLastMouseDir.mX : screen_x - mLastMouseScreenX;
00349                 mouse_dir.mY = (screen_y == mLastMouseScreenY) ? mLastMouseDir.mY : screen_y - mLastMouseScreenY;
00350                 mLastMouseDir = mouse_dir;
00351                 mLastMouseScreenX = screen_x;
00352                 mLastMouseScreenY = screen_y;
00353 
00354                 LLView* snap_view = getParent()->findSnapRect(new_rect, mouse_dir, SNAP_PARENT_AND_SIBLINGS, sSnapMargin);
00355 
00356                 getParent()->snappedTo(snap_view);
00357                 delta_x = new_rect.mLeft - pre_snap_x;
00358                 delta_y = new_rect.mBottom - pre_snap_y;
00359                 translated_rect.translate(delta_x, delta_y);
00360 
00361                 // restore original rect so delta are detected, then call user reshape method to handle snapped floaters, etc
00362                 getParent()->setRect(original_rect);
00363                 getParent()->userSetShape(translated_rect);
00364 
00365                 mDragLastScreenX += delta_x;
00366                 mDragLastScreenY += delta_y;
00367 
00368                 getWindow()->setCursor(UI_CURSOR_ARROW);
00369                 lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << " (active)" <<llendl;                
00370                 handled = TRUE;
00371         }
00372         else if( getVisible() )
00373         {
00374                 getWindow()->setCursor(UI_CURSOR_ARROW);
00375                 lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << " (inactive)" << llendl;             
00376                 handled = TRUE;
00377         }
00378 
00379         // Note: don't pass on to children
00380 
00381         return handled;
00382 }
00383 
00384 void LLDragHandle::setValue(const LLSD& value)
00385 {
00386         setTitle(value.asString());
00387 }

Generated on Thu Jul 1 06:08:24 2010 for Second Life Viewer by  doxygen 1.4.7