llresizehandle.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:9k
源码类别:

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file llresizehandle.cpp
  3.  * @brief LLResizeHandle base class
  4.  *
  5.  * $LicenseInfo:firstyear=2001&license=viewergpl$
  6.  * 
  7.  * Copyright (c) 2001-2010, Linden Research, Inc.
  8.  * 
  9.  * Second Life Viewer Source Code
  10.  * The source code in this file ("Source Code") is provided by Linden Lab
  11.  * to you under the terms of the GNU General Public License, version 2.0
  12.  * ("GPL"), unless you have obtained a separate licensing agreement
  13.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  14.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16.  * 
  17.  * There are special exceptions to the terms and conditions of the GPL as
  18.  * it is applied to this Source Code. View the full text of the exception
  19.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  20.  * online at
  21.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22.  * 
  23.  * By copying, modifying or distributing this software, you acknowledge
  24.  * that you have read and understood your obligations described above,
  25.  * and agree to abide by those obligations.
  26.  * 
  27.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29.  * COMPLETENESS OR PERFORMANCE.
  30.  * $/LicenseInfo$
  31.  */
  32. #include "linden_common.h"
  33. #include "llresizehandle.h"
  34. #include "llfocusmgr.h"
  35. #include "llmath.h"
  36. #include "llui.h"
  37. #include "llmenugl.h"
  38. #include "llcontrol.h"
  39. #include "llfloater.h"
  40. #include "llwindow.h"
  41. const S32 RESIZE_BORDER_WIDTH = 3;
  42. LLResizeHandle::Params::Params()
  43. : corner("corner"),
  44. min_width("min_width"),
  45. min_height("min_height")
  46. {
  47. name = "resize_handle";
  48. }
  49. LLResizeHandle::LLResizeHandle(const LLResizeHandle::Params& p)
  50. : LLView(p),
  51. mDragLastScreenX( 0 ),
  52. mDragLastScreenY( 0 ),
  53. mLastMouseScreenX( 0 ),
  54. mLastMouseScreenY( 0 ),
  55. mImage( NULL ),
  56. mMinWidth( p.min_width ),
  57. mMinHeight( p.min_height ),
  58. mCorner( p.corner )
  59. {
  60. if( RIGHT_BOTTOM == mCorner)
  61. {
  62. mImage = LLUI::getUIImage("Resize_Corner");
  63. }
  64. switch( p.corner )
  65. {
  66. case LEFT_TOP: setFollows( FOLLOWS_LEFT | FOLLOWS_TOP ); break;
  67. case LEFT_BOTTOM: setFollows( FOLLOWS_LEFT | FOLLOWS_BOTTOM ); break;
  68. case RIGHT_TOP: setFollows( FOLLOWS_RIGHT | FOLLOWS_TOP ); break;
  69. case RIGHT_BOTTOM: setFollows( FOLLOWS_RIGHT | FOLLOWS_BOTTOM ); break;
  70. }
  71. }
  72. BOOL LLResizeHandle::handleMouseDown(S32 x, S32 y, MASK mask)
  73. {
  74. BOOL handled = FALSE;
  75. if( pointInHandle(x, y) )
  76. {
  77. handled = TRUE;
  78. // Route future Mouse messages here preemptively.  (Release on mouse up.)
  79. // No handler needed for focus lost since this clas has no state that depends on it.
  80. gFocusMgr.setMouseCapture( this );
  81. localPointToScreen(x, y, &mDragLastScreenX, &mDragLastScreenY);
  82. mLastMouseScreenX = mDragLastScreenX;
  83. mLastMouseScreenY = mDragLastScreenY;
  84. }
  85. return handled;
  86. }
  87. BOOL LLResizeHandle::handleMouseUp(S32 x, S32 y, MASK mask)
  88. {
  89. BOOL handled = FALSE;
  90. if( hasMouseCapture() )
  91. {
  92. // Release the mouse
  93. gFocusMgr.setMouseCapture( NULL );
  94. handled = TRUE;
  95. }
  96. else if( pointInHandle(x, y) )
  97. {
  98. handled = TRUE;
  99. }
  100. return handled;
  101. }
  102. BOOL LLResizeHandle::handleHover(S32 x, S32 y, MASK mask)
  103. {
  104. BOOL handled = FALSE;
  105. // We only handle the click if the click both started and ended within us
  106. if( hasMouseCapture() )
  107. {
  108. // Make sure the mouse in still over the application.  We don't want to make the parent
  109. // so big that we can't see the resize handle any more.
  110. S32 screen_x;
  111. S32 screen_y;
  112. localPointToScreen(x, y, &screen_x, &screen_y);
  113. const LLRect valid_rect = getRootView()->getRect();
  114. screen_x = llclamp( screen_x, valid_rect.mLeft, valid_rect.mRight );
  115. screen_y = llclamp( screen_y, valid_rect.mBottom, valid_rect.mTop );
  116. LLView* resizing_view = getParent();
  117. if( resizing_view )
  118. {
  119. // undock floater when user resize it
  120. LLFloater* floater_parent = dynamic_cast<LLFloater*>(getParent());
  121. if (floater_parent && floater_parent->isDocked()) 
  122. {
  123. floater_parent->setDocked(false, false);
  124. }
  125. // Resize the parent
  126. LLRect orig_rect = resizing_view->getRect();
  127. LLRect scaled_rect = orig_rect;
  128. S32 delta_x = screen_x - mDragLastScreenX;
  129. S32 delta_y = screen_y - mDragLastScreenY;
  130. LLCoordGL mouse_dir;
  131. // use hysteresis on mouse motion to preserve user intent when mouse stops moving
  132. mouse_dir.mX = (screen_x == mLastMouseScreenX) ? mLastMouseDir.mX : screen_x - mLastMouseScreenX;
  133. mouse_dir.mY = (screen_y == mLastMouseScreenY) ? mLastMouseDir.mY : screen_y - mLastMouseScreenY;
  134. mLastMouseScreenX = screen_x;
  135. mLastMouseScreenY = screen_y;
  136. mLastMouseDir = mouse_dir;
  137. S32 x_multiple = 1;
  138. S32 y_multiple = 1;
  139. switch( mCorner )
  140. {
  141. case LEFT_TOP:
  142. x_multiple = -1; 
  143. y_multiple =  1;
  144. break;
  145. case LEFT_BOTTOM:
  146. x_multiple = -1; 
  147. y_multiple = -1;
  148. break;
  149. case RIGHT_TOP:
  150. x_multiple =  1; 
  151. y_multiple =  1;
  152. break;
  153. case RIGHT_BOTTOM:
  154. x_multiple =  1; 
  155. y_multiple = -1;
  156. break;
  157. }
  158. S32 new_width = orig_rect.getWidth() + x_multiple * delta_x;
  159. if( new_width < mMinWidth )
  160. {
  161. new_width = mMinWidth;
  162. delta_x = x_multiple * (mMinWidth - orig_rect.getWidth());
  163. }
  164. S32 new_height = orig_rect.getHeight() + y_multiple * delta_y;
  165. if( new_height < mMinHeight )
  166. {
  167. new_height = mMinHeight;
  168. delta_y = y_multiple * (mMinHeight - orig_rect.getHeight());
  169. }
  170. switch( mCorner )
  171. {
  172. case LEFT_TOP:
  173. scaled_rect.translate(delta_x, 0);
  174. break;
  175. case LEFT_BOTTOM:
  176. scaled_rect.translate(delta_x, delta_y);
  177. break;
  178. case RIGHT_TOP:
  179. break;
  180. case RIGHT_BOTTOM:
  181. scaled_rect.translate(0, delta_y);
  182. break;
  183. }
  184. // temporarily set new parent rect
  185. scaled_rect.mRight = scaled_rect.mLeft + new_width;
  186. scaled_rect.mTop = scaled_rect.mBottom + new_height;
  187. resizing_view->setRect(scaled_rect);
  188. LLView* snap_view = NULL;
  189. LLView* test_view = NULL;
  190. static LLUICachedControl<S32> snap_margin ("SnapMargin", 0);
  191. // now do snapping
  192. switch(mCorner)
  193. {
  194. case LEFT_TOP:
  195. snap_view = resizing_view->findSnapEdge(scaled_rect.mLeft, mouse_dir, SNAP_LEFT, SNAP_PARENT_AND_SIBLINGS, snap_margin);
  196. test_view = resizing_view->findSnapEdge(scaled_rect.mTop, mouse_dir, SNAP_TOP, SNAP_PARENT_AND_SIBLINGS, snap_margin);
  197. if (!snap_view)
  198. {
  199. snap_view = test_view;
  200. }
  201. break;
  202. case LEFT_BOTTOM:
  203. snap_view = resizing_view->findSnapEdge(scaled_rect.mLeft, mouse_dir, SNAP_LEFT, SNAP_PARENT_AND_SIBLINGS, snap_margin);
  204. test_view = resizing_view->findSnapEdge(scaled_rect.mBottom, mouse_dir, SNAP_BOTTOM, SNAP_PARENT_AND_SIBLINGS, snap_margin);
  205. if (!snap_view)
  206. {
  207. snap_view = test_view;
  208. }
  209. break;
  210. case RIGHT_TOP:
  211. snap_view = resizing_view->findSnapEdge(scaled_rect.mRight, mouse_dir, SNAP_RIGHT, SNAP_PARENT_AND_SIBLINGS, snap_margin);
  212. test_view = resizing_view->findSnapEdge(scaled_rect.mTop, mouse_dir, SNAP_TOP, SNAP_PARENT_AND_SIBLINGS, snap_margin);
  213. if (!snap_view)
  214. {
  215. snap_view = test_view;
  216. }
  217. break;
  218. case RIGHT_BOTTOM:
  219. snap_view = resizing_view->findSnapEdge(scaled_rect.mRight, mouse_dir, SNAP_RIGHT, SNAP_PARENT_AND_SIBLINGS, snap_margin);
  220. test_view = resizing_view->findSnapEdge(scaled_rect.mBottom, mouse_dir, SNAP_BOTTOM, SNAP_PARENT_AND_SIBLINGS, snap_margin);
  221. if (!snap_view)
  222. {
  223. snap_view = test_view;
  224. }
  225. break;
  226. }
  227. // register "snap" behavior with snapped view
  228. resizing_view->setSnappedTo(snap_view);
  229. // reset parent rect
  230. resizing_view->setRect(orig_rect);
  231. // translate and scale to new shape
  232. resizing_view->setShape(scaled_rect, true);
  233. // update last valid mouse cursor position based on resized view's actual size
  234. LLRect new_rect = resizing_view->getRect();
  235. switch(mCorner)
  236. {
  237. case LEFT_TOP:
  238. mDragLastScreenX += new_rect.mLeft - orig_rect.mLeft;
  239. mDragLastScreenY += new_rect.mTop - orig_rect.mTop;
  240. break;
  241. case LEFT_BOTTOM:
  242. mDragLastScreenX += new_rect.mLeft - orig_rect.mLeft;
  243. mDragLastScreenY += new_rect.mBottom- orig_rect.mBottom;
  244. break;
  245. case RIGHT_TOP:
  246. mDragLastScreenX += new_rect.mRight - orig_rect.mRight;
  247. mDragLastScreenY += new_rect.mTop - orig_rect.mTop;
  248. break;
  249. case RIGHT_BOTTOM:
  250. mDragLastScreenX += new_rect.mRight - orig_rect.mRight;
  251. mDragLastScreenY += new_rect.mBottom- orig_rect.mBottom;
  252. break;
  253. default:
  254. break;
  255. }
  256. }
  257. handled = TRUE;
  258. }
  259. else // don't have mouse capture
  260. {
  261. if( pointInHandle( x, y ) )
  262. {
  263. handled = TRUE;
  264. }
  265. }
  266. if( handled )
  267. {
  268. switch( mCorner )
  269. {
  270. case RIGHT_BOTTOM:
  271. case LEFT_TOP:
  272. getWindow()->setCursor(UI_CURSOR_SIZENWSE); 
  273. break;
  274. case LEFT_BOTTOM:
  275. case RIGHT_TOP:
  276. getWindow()->setCursor(UI_CURSOR_SIZENESW); 
  277. break;
  278. }
  279. }
  280. return handled;
  281. } // end handleHover
  282. // assumes GL state is set for 2D
  283. void LLResizeHandle::draw()
  284. {
  285. if( mImage.notNull() && getVisible() && (RIGHT_BOTTOM == mCorner) ) 
  286. {
  287. mImage->draw(0, 0);
  288. }
  289. }
  290. BOOL LLResizeHandle::pointInHandle( S32 x, S32 y )
  291. {
  292. if( pointInView(x, y) )
  293. {
  294. const S32 TOP_BORDER = (getRect().getHeight() - RESIZE_BORDER_WIDTH);
  295. const S32 RIGHT_BORDER = (getRect().getWidth() - RESIZE_BORDER_WIDTH);
  296. switch( mCorner )
  297. {
  298. case LEFT_TOP: return (x <= RESIZE_BORDER_WIDTH) || (y >= TOP_BORDER);
  299. case LEFT_BOTTOM: return (x <= RESIZE_BORDER_WIDTH) || (y <= RESIZE_BORDER_WIDTH);
  300. case RIGHT_TOP: return (x >= RIGHT_BORDER) || (y >= TOP_BORDER);
  301. case RIGHT_BOTTOM: return TRUE;
  302. }
  303. }
  304. return FALSE;
  305. }