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