00001
00032 #include "linden_common.h"
00033
00034 #include "llresizehandle.h"
00035
00036 #include "llfocusmgr.h"
00037 #include "llmath.h"
00038 #include "llui.h"
00039 #include "llmenugl.h"
00040 #include "llcontrol.h"
00041 #include "llfloater.h"
00042 #include "llwindow.h"
00043
00044 const S32 RESIZE_BORDER_WIDTH = 3;
00045
00046 LLResizeHandle::LLResizeHandle( const LLString& name, const LLRect& rect, S32 min_width, S32 min_height, ECorner corner )
00047 :
00048 LLView( name, rect, TRUE ),
00049 mDragLastScreenX( 0 ),
00050 mDragLastScreenY( 0 ),
00051 mLastMouseScreenX( 0 ),
00052 mLastMouseScreenY( 0 ),
00053 mImage( NULL ),
00054 mMinWidth( min_width ),
00055 mMinHeight( min_height ),
00056 mCorner( corner )
00057 {
00058 setSaveToXML(false);
00059
00060 if( RIGHT_BOTTOM == mCorner)
00061 {
00062 LLUUID image_id(LLUI::sConfigGroup->getString("UIImgResizeBottomRightUUID"));
00063 mImage = LLUI::sImageProvider->getUIImageByID(image_id);
00064 }
00065
00066 switch( mCorner )
00067 {
00068 case LEFT_TOP: setFollows( FOLLOWS_LEFT | FOLLOWS_TOP ); break;
00069 case LEFT_BOTTOM: setFollows( FOLLOWS_LEFT | FOLLOWS_BOTTOM ); break;
00070 case RIGHT_TOP: setFollows( FOLLOWS_RIGHT | FOLLOWS_TOP ); break;
00071 case RIGHT_BOTTOM: setFollows( FOLLOWS_RIGHT | FOLLOWS_BOTTOM ); break;
00072 }
00073
00074
00075 setSaveToXML(FALSE);
00076 }
00077
00078 EWidgetType LLResizeHandle::getWidgetType() const
00079 {
00080 return WIDGET_TYPE_RESIZE_HANDLE;
00081 }
00082
00083 LLString LLResizeHandle::getWidgetTag() const
00084 {
00085 return LL_RESIZE_HANDLE_TAG;
00086 }
00087
00088 BOOL LLResizeHandle::handleMouseDown(S32 x, S32 y, MASK mask)
00089 {
00090 BOOL handled = FALSE;
00091 if( getVisible() && pointInHandle(x, y) )
00092 {
00093 handled = TRUE;
00094 if( mEnabled )
00095 {
00096
00097
00098 gFocusMgr.setMouseCapture( this );
00099
00100 localPointToScreen(x, y, &mDragLastScreenX, &mDragLastScreenY);
00101 mLastMouseScreenX = mDragLastScreenX;
00102 mLastMouseScreenY = mDragLastScreenY;
00103 }
00104 }
00105
00106 return handled;
00107 }
00108
00109
00110 BOOL LLResizeHandle::handleMouseUp(S32 x, S32 y, MASK mask)
00111 {
00112 BOOL handled = FALSE;
00113
00114 if( hasMouseCapture() )
00115 {
00116
00117 gFocusMgr.setMouseCapture( NULL );
00118 handled = TRUE;
00119 }
00120 else
00121 if( getVisible() && pointInHandle(x, y) )
00122 {
00123 handled = TRUE;
00124 }
00125
00126 return handled;
00127 }
00128
00129
00130 BOOL LLResizeHandle::handleHover(S32 x, S32 y, MASK mask)
00131 {
00132 BOOL handled = FALSE;
00133
00134
00135 if( hasMouseCapture() )
00136 {
00137
00138
00139
00140 S32 screen_x;
00141 S32 screen_y;
00142 localPointToScreen(x, y, &screen_x, &screen_y);
00143 const LLRect valid_rect = getRootView()->getRect();
00144 screen_x = llclamp( screen_x, valid_rect.mLeft, valid_rect.mRight );
00145 screen_y = llclamp( screen_y, valid_rect.mBottom, valid_rect.mTop );
00146
00147 LLView* resizing_view = getParent();
00148 if( resizing_view )
00149 {
00150
00151 LLRect orig_rect = resizing_view->getRect();
00152 LLRect scaled_rect = orig_rect;
00153 S32 delta_x = screen_x - mDragLastScreenX;
00154 S32 delta_y = screen_y - mDragLastScreenY;
00155 LLCoordGL mouse_dir;
00156
00157 mouse_dir.mX = (screen_x == mLastMouseScreenX) ? mLastMouseDir.mX : screen_x - mLastMouseScreenX;
00158 mouse_dir.mY = (screen_y == mLastMouseScreenY) ? mLastMouseDir.mY : screen_y - mLastMouseScreenY;
00159 mLastMouseScreenX = screen_x;
00160 mLastMouseScreenY = screen_y;
00161 mLastMouseDir = mouse_dir;
00162
00163 S32 x_multiple = 1;
00164 S32 y_multiple = 1;
00165 switch( mCorner )
00166 {
00167 case LEFT_TOP:
00168 x_multiple = -1;
00169 y_multiple = 1;
00170 break;
00171 case LEFT_BOTTOM:
00172 x_multiple = -1;
00173 y_multiple = -1;
00174 break;
00175 case RIGHT_TOP:
00176 x_multiple = 1;
00177 y_multiple = 1;
00178 break;
00179 case RIGHT_BOTTOM:
00180 x_multiple = 1;
00181 y_multiple = -1;
00182 break;
00183 }
00184
00185 S32 new_width = orig_rect.getWidth() + x_multiple * delta_x;
00186 if( new_width < mMinWidth )
00187 {
00188 new_width = mMinWidth;
00189 delta_x = x_multiple * (mMinWidth - orig_rect.getWidth());
00190 }
00191
00192 S32 new_height = orig_rect.getHeight() + y_multiple * delta_y;
00193 if( new_height < mMinHeight )
00194 {
00195 new_height = mMinHeight;
00196 delta_y = y_multiple * (mMinHeight - orig_rect.getHeight());
00197 }
00198
00199 switch( mCorner )
00200 {
00201 case LEFT_TOP:
00202 scaled_rect.translate(delta_x, 0);
00203 break;
00204 case LEFT_BOTTOM:
00205 scaled_rect.translate(delta_x, delta_y);
00206 break;
00207 case RIGHT_TOP:
00208 break;
00209 case RIGHT_BOTTOM:
00210 scaled_rect.translate(0, delta_y);
00211 break;
00212 }
00213
00214
00215 scaled_rect.mRight = scaled_rect.mLeft + new_width;
00216 scaled_rect.mTop = scaled_rect.mBottom + new_height;
00217 resizing_view->setRect(scaled_rect);
00218
00219 LLView* snap_view = NULL;
00220 LLView* test_view = NULL;
00221
00222
00223 switch(mCorner)
00224 {
00225 case LEFT_TOP:
00226 snap_view = resizing_view->findSnapEdge(scaled_rect.mLeft, mouse_dir, SNAP_LEFT, SNAP_PARENT_AND_SIBLINGS, LLUI::sConfigGroup->getS32("SnapMargin"));
00227 test_view = resizing_view->findSnapEdge(scaled_rect.mTop, mouse_dir, SNAP_TOP, SNAP_PARENT_AND_SIBLINGS, LLUI::sConfigGroup->getS32("SnapMargin"));
00228 if (!snap_view)
00229 {
00230 snap_view = test_view;
00231 }
00232 break;
00233 case LEFT_BOTTOM:
00234 snap_view = resizing_view->findSnapEdge(scaled_rect.mLeft, mouse_dir, SNAP_LEFT, SNAP_PARENT_AND_SIBLINGS, LLUI::sConfigGroup->getS32("SnapMargin"));
00235 test_view = resizing_view->findSnapEdge(scaled_rect.mBottom, mouse_dir, SNAP_BOTTOM, SNAP_PARENT_AND_SIBLINGS, LLUI::sConfigGroup->getS32("SnapMargin"));
00236 if (!snap_view)
00237 {
00238 snap_view = test_view;
00239 }
00240 break;
00241 case RIGHT_TOP:
00242 snap_view = resizing_view->findSnapEdge(scaled_rect.mRight, mouse_dir, SNAP_RIGHT, SNAP_PARENT_AND_SIBLINGS, LLUI::sConfigGroup->getS32("SnapMargin"));
00243 test_view = resizing_view->findSnapEdge(scaled_rect.mTop, mouse_dir, SNAP_TOP, SNAP_PARENT_AND_SIBLINGS, LLUI::sConfigGroup->getS32("SnapMargin"));
00244 if (!snap_view)
00245 {
00246 snap_view = test_view;
00247 }
00248 break;
00249 case RIGHT_BOTTOM:
00250 snap_view = resizing_view->findSnapEdge(scaled_rect.mRight, mouse_dir, SNAP_RIGHT, SNAP_PARENT_AND_SIBLINGS, LLUI::sConfigGroup->getS32("SnapMargin"));
00251 test_view = resizing_view->findSnapEdge(scaled_rect.mBottom, mouse_dir, SNAP_BOTTOM, SNAP_PARENT_AND_SIBLINGS, LLUI::sConfigGroup->getS32("SnapMargin"));
00252 if (!snap_view)
00253 {
00254 snap_view = test_view;
00255 }
00256 break;
00257 }
00258
00259
00260 resizing_view->snappedTo(snap_view);
00261
00262
00263 resizing_view->setRect(orig_rect);
00264
00265
00266 resizing_view->userSetShape(scaled_rect);
00267
00268
00269 LLRect new_rect = resizing_view->getRect();
00270 switch(mCorner)
00271 {
00272 case LEFT_TOP:
00273 mDragLastScreenX += new_rect.mLeft - orig_rect.mLeft;
00274 mDragLastScreenY += new_rect.mTop - orig_rect.mTop;
00275 break;
00276 case LEFT_BOTTOM:
00277 mDragLastScreenX += new_rect.mLeft - orig_rect.mLeft;
00278 mDragLastScreenY += new_rect.mBottom- orig_rect.mBottom;
00279 break;
00280 case RIGHT_TOP:
00281 mDragLastScreenX += new_rect.mRight - orig_rect.mRight;
00282 mDragLastScreenY += new_rect.mTop - orig_rect.mTop;
00283 break;
00284 case RIGHT_BOTTOM:
00285 mDragLastScreenX += new_rect.mRight - orig_rect.mRight;
00286 mDragLastScreenY += new_rect.mBottom- orig_rect.mBottom;
00287 break;
00288 default:
00289 break;
00290 }
00291 }
00292
00293 handled = TRUE;
00294 }
00295 else
00296 if( getVisible() && pointInHandle( x, y ) )
00297 {
00298 handled = TRUE;
00299 }
00300
00301 if( handled )
00302 {
00303 switch( mCorner )
00304 {
00305 case RIGHT_BOTTOM:
00306 case LEFT_TOP:
00307 getWindow()->setCursor(UI_CURSOR_SIZENWSE);
00308 break;
00309 case LEFT_BOTTOM:
00310 case RIGHT_TOP:
00311 getWindow()->setCursor(UI_CURSOR_SIZENESW);
00312 break;
00313 }
00314 }
00315
00316 return handled;
00317 }
00318
00319
00320 void LLResizeHandle::draw()
00321 {
00322 if( mImage.notNull() && getVisible() && (RIGHT_BOTTOM == mCorner) )
00323 {
00324 gl_draw_image( 0, 0, mImage );
00325 }
00326 }
00327
00328
00329 BOOL LLResizeHandle::pointInHandle( S32 x, S32 y )
00330 {
00331 if( pointInView(x, y) )
00332 {
00333 const S32 TOP_BORDER = (mRect.getHeight() - RESIZE_BORDER_WIDTH);
00334 const S32 RIGHT_BORDER = (mRect.getWidth() - RESIZE_BORDER_WIDTH);
00335
00336 switch( mCorner )
00337 {
00338 case LEFT_TOP: return (x <= RESIZE_BORDER_WIDTH) || (y >= TOP_BORDER);
00339 case LEFT_BOTTOM: return (x <= RESIZE_BORDER_WIDTH) || (y <= RESIZE_BORDER_WIDTH);
00340 case RIGHT_TOP: return (x >= RIGHT_BORDER) || (y >= TOP_BORDER);
00341 case RIGHT_BOTTOM: return TRUE;
00342 }
00343 }
00344 return FALSE;
00345 }