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         if(mTitleBox)
00078         {
00079                 mTitleBox->setVisible(visible); 
00080         }
00081 }
00082 
00083 void LLDragHandle::setTitleBox(LLTextBox* titlebox)
00084 {       
00085         if( mTitleBox )
00086         {
00087                 removeChild(mTitleBox);
00088                 delete mTitleBox;
00089         }
00090         mTitleBox = titlebox;
00091         if(mTitleBox)
00092         {
00093                 addChild( mTitleBox );
00094         }
00095 }
00096 
00097 LLDragHandleTop::LLDragHandleTop(const LLString& name, const LLRect &rect, const LLString& title)
00098 :       LLDragHandle(name, rect, title)
00099 {
00100         setFollowsAll();
00101         setTitle( title );
00102 }
00103 
00104 LLDragHandleLeft::LLDragHandleLeft(const LLString& name, const LLRect &rect, const LLString& title)
00105 :       LLDragHandle(name, rect, title)
00106 {
00107         setFollowsAll();
00108         setTitle( title );
00109 }
00110 
00111 void LLDragHandleTop::setTitle(const LLString& title)
00112 {
00113         LLString trimmed_title = title;
00114         LLString::trim(trimmed_title);
00115 
00116         const LLFontGL* font = LLResMgr::getInstance()->getRes( LLFONT_SANSSERIF );
00117         LLTextBox* titlebox = new LLTextBox( "Drag Handle Title", getRect(), trimmed_title, font );
00118         titlebox->setFollows(FOLLOWS_TOP | FOLLOWS_LEFT | FOLLOWS_RIGHT);
00119         titlebox->setFontStyle(LLFontGL::DROP_SHADOW_SOFT);
00120         
00121         setTitleBox(titlebox);
00122         reshapeTitleBox();
00123 }
00124 
00125 
00126 const LLString& LLDragHandleTop::getTitle() const
00127 {
00128         return getTitleBox() == NULL ? LLString::null : getTitleBox()->getText();
00129 }
00130 
00131 
00132 void LLDragHandleLeft::setTitle(const LLString& )
00133 {
00134         setTitleBox(NULL);
00135         /* no title on left edge */
00136 }
00137 
00138 
00139 const LLString& LLDragHandleLeft::getTitle() const
00140 {
00141         return LLString::null;
00142 }
00143 
00144 
00145 void LLDragHandleTop::draw()
00146 {
00147         /* Disable lines.  Can drag anywhere in most windows.  JC
00148         if( getVisible() && getEnabled() && mForeground) 
00149         {
00150                 const S32 BORDER_PAD = 2;
00151                 const S32 HPAD = 2;
00152                 const S32 VPAD = 2;
00153                 S32 left = BORDER_PAD + HPAD;
00154                 S32 top = getRect().getHeight() - 2 * VPAD;
00155                 S32 right = getRect().getWidth() - HPAD;
00156 //              S32 bottom = VPAD;
00157 
00158                 // draw lines for drag areas
00159 
00160                 const S32 LINE_SPACING = (DRAG_HANDLE_HEIGHT - 2 * VPAD) / 4;
00161                 S32 line = top - LINE_SPACING;
00162 
00163                 LLRect title_rect = mTitleBox->getRect();
00164                 S32 title_right = title_rect.mLeft + mTitleWidth;
00165                 BOOL show_right_side = title_right < getRect().getWidth();
00166 
00167                 for( S32 i=0; i<4; i++ )
00168                 {
00169                         gl_line_2d(left, line+1, title_rect.mLeft - LEADING_PAD, line+1, mDragHighlightColor);
00170                         if( show_right_side )
00171                         {
00172                                 gl_line_2d(title_right, line+1, right, line+1, mDragHighlightColor);
00173                         }
00174 
00175                         gl_line_2d(left, line, title_rect.mLeft - LEADING_PAD, line, mDragShadowColor);
00176                         if( show_right_side )
00177                         {
00178                                 gl_line_2d(title_right, line, right, line, mDragShadowColor);
00179                         }
00180                         line -= LINE_SPACING;
00181                 }
00182         }
00183         */
00184 
00185         // Colorize the text to match the frontmost state
00186         if (getTitleBox())
00187         {
00188                 getTitleBox()->setEnabled(getForeground());
00189         }
00190 
00191         LLView::draw();
00192 }
00193 
00194 
00195 // assumes GL state is set for 2D
00196 void LLDragHandleLeft::draw()
00197 {
00198         /* Disable lines.  Can drag anywhere in most windows. JC
00199         if( getVisible() && getEnabled() && mForeground ) 
00200         {
00201                 const S32 BORDER_PAD = 2;
00202 //              const S32 HPAD = 2;
00203                 const S32 VPAD = 2;
00204                 const S32 LINE_SPACING = 3;
00205 
00206                 S32 left = BORDER_PAD + LINE_SPACING;
00207                 S32 top = getRect().getHeight() - 2 * VPAD;
00208 //              S32 right = getRect().getWidth() - HPAD;
00209                 S32 bottom = VPAD;
00210  
00211                 // draw lines for drag areas
00212 
00213                 // no titles yet
00214                 //LLRect title_rect = mTitleBox->getRect();
00215                 //S32 title_right = title_rect.mLeft + mTitleWidth;
00216                 //BOOL show_right_side = title_right < getRect().getWidth();
00217 
00218                 S32 line = left;
00219                 for( S32 i=0; i<4; i++ )
00220                 {
00221                         gl_line_2d(line, top, line, bottom, mDragHighlightColor);
00222 
00223                         gl_line_2d(line+1, top, line+1, bottom, mDragShadowColor);
00224 
00225                         line += LINE_SPACING;
00226                 }
00227         }
00228         */
00229 
00230         // Colorize the text to match the frontmost state
00231         if (getTitleBox())
00232         {
00233                 getTitleBox()->setEnabled(getForeground());
00234         }
00235 
00236         LLView::draw();
00237 }
00238 
00239 void LLDragHandleTop::reshapeTitleBox()
00240 {
00241         if( ! getTitleBox())
00242         {
00243                 return;
00244         }
00245         const LLFontGL* font = LLResMgr::getInstance()->getRes( LLFONT_SANSSERIF );
00246         S32 title_width = font->getWidth( getTitleBox()->getText() ) + TITLE_PAD;
00247         if (getMaxTitleWidth() > 0)
00248                 title_width = llmin(title_width, getMaxTitleWidth());
00249         S32 title_height = llround(font->getLineHeight());
00250         LLRect title_rect;
00251         title_rect.setLeftTopAndSize( 
00252                 LEFT_PAD, 
00253                 getRect().getHeight() - BORDER_PAD,
00254                 getRect().getWidth() - LEFT_PAD - RIGHT_PAD,
00255                 title_height);
00256 
00257         getTitleBox()->setRect( title_rect );
00258 }
00259 
00260 void LLDragHandleTop::reshape(S32 width, S32 height, BOOL called_from_parent)
00261 {
00262         LLView::reshape(width, height, called_from_parent);
00263         reshapeTitleBox();
00264 }
00265 
00266 void LLDragHandleLeft::reshape(S32 width, S32 height, BOOL called_from_parent)
00267 {
00268         LLView::reshape(width, height, called_from_parent);
00269 }
00270 
00271 //-------------------------------------------------------------
00272 // UI event handling
00273 //-------------------------------------------------------------
00274 
00275 BOOL LLDragHandle::handleMouseDown(S32 x, S32 y, MASK mask)
00276 {
00277         // Route future Mouse messages here preemptively.  (Release on mouse up.)
00278         // No handler needed for focus lost since this clas has no state that depends on it.
00279         gFocusMgr.setMouseCapture(this);
00280 
00281         localPointToScreen(x, y, &mDragLastScreenX, &mDragLastScreenY);
00282         mLastMouseScreenX = mDragLastScreenX;
00283         mLastMouseScreenY = mDragLastScreenY;
00284 
00285         // Note: don't pass on to children
00286         return TRUE;
00287 }
00288 
00289 
00290 BOOL LLDragHandle::handleMouseUp(S32 x, S32 y, MASK mask)
00291 {
00292         if( hasMouseCapture() )
00293         {
00294                 // Release the mouse
00295                 gFocusMgr.setMouseCapture( NULL );
00296         }
00297 
00298         // Note: don't pass on to children
00299         return TRUE;
00300 }
00301 
00302 
00303 BOOL LLDragHandle::handleHover(S32 x, S32 y, MASK mask)
00304 {
00305         BOOL    handled = FALSE;
00306 
00307         // We only handle the click if the click both started and ended within us
00308         if( hasMouseCapture() )
00309         {
00310                 S32 screen_x;
00311                 S32 screen_y;
00312                 localPointToScreen(x, y, &screen_x, &screen_y);
00313 
00314                 // Resize the parent
00315                 S32 delta_x = screen_x - mDragLastScreenX;
00316                 S32 delta_y = screen_y - mDragLastScreenY;
00317 
00318                 LLRect original_rect = getParent()->getRect();
00319                 LLRect translated_rect = getParent()->getRect();
00320                 translated_rect.translate(delta_x, delta_y);
00321                 // temporarily slam dragged window to new position
00322                 getParent()->setRect(translated_rect);
00323                 S32 pre_snap_x = getParent()->getRect().mLeft;
00324                 S32 pre_snap_y = getParent()->getRect().mBottom;
00325                 mDragLastScreenX = screen_x;
00326                 mDragLastScreenY = screen_y;
00327 
00328                 LLRect new_rect;
00329                 LLCoordGL mouse_dir;
00330                 // use hysteresis on mouse motion to preserve user intent when mouse stops moving
00331                 mouse_dir.mX = (screen_x == mLastMouseScreenX) ? mLastMouseDir.mX : screen_x - mLastMouseScreenX;
00332                 mouse_dir.mY = (screen_y == mLastMouseScreenY) ? mLastMouseDir.mY : screen_y - mLastMouseScreenY;
00333                 mLastMouseDir = mouse_dir;
00334                 mLastMouseScreenX = screen_x;
00335                 mLastMouseScreenY = screen_y;
00336 
00337                 LLView* snap_view = getParent()->findSnapRect(new_rect, mouse_dir, SNAP_PARENT_AND_SIBLINGS, sSnapMargin);
00338 
00339                 getParent()->snappedTo(snap_view);
00340                 delta_x = new_rect.mLeft - pre_snap_x;
00341                 delta_y = new_rect.mBottom - pre_snap_y;
00342                 translated_rect.translate(delta_x, delta_y);
00343 
00344                 // restore original rect so delta are detected, then call user reshape method to handle snapped floaters, etc
00345                 getParent()->setRect(original_rect);
00346                 getParent()->userSetShape(translated_rect);
00347 
00348                 mDragLastScreenX += delta_x;
00349                 mDragLastScreenY += delta_y;
00350 
00351                 getWindow()->setCursor(UI_CURSOR_ARROW);
00352                 lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << " (active)" <<llendl;                
00353                 handled = TRUE;
00354         }
00355         else
00356         {
00357                 getWindow()->setCursor(UI_CURSOR_ARROW);
00358                 lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << " (inactive)" << llendl;             
00359                 handled = TRUE;
00360         }
00361 
00362         // Note: don't pass on to children
00363 
00364         return handled;
00365 }
00366 
00367 void LLDragHandle::setValue(const LLSD& value)
00368 {
00369         setTitle(value.asString());
00370 }

Generated on Fri May 16 08:32:51 2008 for SecondLife by  doxygen 1.5.5