PageRenderTime 38ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/indra/llui/llresizebar.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 299 lines | 219 code | 41 blank | 39 comment | 14 complexity | 30e2d1a91fc601037a81f9a8c7d5d798 MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file llresizebar.cpp
  3. * @brief LLResizeBar base class
  4. *
  5. * $LicenseInfo:firstyear=2001&license=viewerlgpl$
  6. * Second Life Viewer Source Code
  7. * Copyright (C) 2010, Linden Research, Inc.
  8. *
  9. * This library is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU Lesser General Public
  11. * License as published by the Free Software Foundation;
  12. * version 2.1 of the License only.
  13. *
  14. * This library is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public
  20. * License along with this library; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22. *
  23. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  24. * $/LicenseInfo$
  25. */
  26. #include "linden_common.h"
  27. #include "llresizebar.h"
  28. #include "llmath.h"
  29. #include "llui.h"
  30. #include "llmenugl.h"
  31. #include "llfocusmgr.h"
  32. #include "llwindow.h"
  33. LLResizeBar::LLResizeBar(const LLResizeBar::Params& p)
  34. : LLView(p),
  35. mDragLastScreenX( 0 ),
  36. mDragLastScreenY( 0 ),
  37. mLastMouseScreenX( 0 ),
  38. mLastMouseScreenY( 0 ),
  39. mMinSize( p.min_size ),
  40. mMaxSize( p.max_size ),
  41. mSide( p.side ),
  42. mSnappingEnabled(p.snapping_enabled),
  43. mAllowDoubleClickSnapping(p.allow_double_click_snapping),
  44. mResizingView(p.resizing_view)
  45. {
  46. setFollowsNone();
  47. // set up some generically good follow code.
  48. switch( mSide )
  49. {
  50. case LEFT:
  51. setFollowsLeft();
  52. setFollowsTop();
  53. setFollowsBottom();
  54. break;
  55. case TOP:
  56. setFollowsTop();
  57. setFollowsLeft();
  58. setFollowsRight();
  59. break;
  60. case RIGHT:
  61. setFollowsRight();
  62. setFollowsTop();
  63. setFollowsBottom();
  64. break;
  65. case BOTTOM:
  66. setFollowsBottom();
  67. setFollowsLeft();
  68. setFollowsRight();
  69. break;
  70. default:
  71. break;
  72. }
  73. }
  74. BOOL LLResizeBar::handleMouseDown(S32 x, S32 y, MASK mask)
  75. {
  76. if (!canResize()) return FALSE;
  77. // Route future Mouse messages here preemptively. (Release on mouse up.)
  78. // No handler needed for focus lost since this clas has no state that depends on it.
  79. gFocusMgr.setMouseCapture( this );
  80. localPointToScreen(x, y, &mDragLastScreenX, &mDragLastScreenY);
  81. mLastMouseScreenX = mDragLastScreenX;
  82. mLastMouseScreenY = mDragLastScreenY;
  83. return TRUE;
  84. }
  85. BOOL LLResizeBar::handleMouseUp(S32 x, S32 y, MASK mask)
  86. {
  87. BOOL handled = FALSE;
  88. if( hasMouseCapture() )
  89. {
  90. // Release the mouse
  91. gFocusMgr.setMouseCapture( NULL );
  92. handled = TRUE;
  93. }
  94. else
  95. {
  96. handled = TRUE;
  97. }
  98. return handled;
  99. }
  100. BOOL LLResizeBar::handleHover(S32 x, S32 y, MASK mask)
  101. {
  102. BOOL handled = FALSE;
  103. // We only handle the click if the click both started and ended within us
  104. if( hasMouseCapture() )
  105. {
  106. S32 screen_x;
  107. S32 screen_y;
  108. localPointToScreen(x, y, &screen_x, &screen_y);
  109. S32 delta_x = screen_x - mDragLastScreenX;
  110. S32 delta_y = screen_y - mDragLastScreenY;
  111. LLCoordGL mouse_dir;
  112. // use hysteresis on mouse motion to preserve user intent when mouse stops moving
  113. mouse_dir.mX = (screen_x == mLastMouseScreenX) ? mLastMouseDir.mX : screen_x - mLastMouseScreenX;
  114. mouse_dir.mY = (screen_y == mLastMouseScreenY) ? mLastMouseDir.mY : screen_y - mLastMouseScreenY;
  115. mLastMouseDir = mouse_dir;
  116. mLastMouseScreenX = screen_x;
  117. mLastMouseScreenY = screen_y;
  118. // Make sure the mouse in still over the application. We don't want to make the parent
  119. // so big that we can't see the resize handle any more.
  120. LLRect valid_rect = getRootView()->getRect();
  121. if( valid_rect.localPointInRect( screen_x, screen_y ) && mResizingView )
  122. {
  123. // undock floater when user resize it
  124. LLFloater* parent = dynamic_cast<LLFloater*>( getParent());
  125. if (parent && parent->isDocked())
  126. {
  127. parent->setDocked( false, false);
  128. }
  129. // Resize the parent
  130. LLRect orig_rect = mResizingView->getRect();
  131. LLRect scaled_rect = orig_rect;
  132. S32 new_width = orig_rect.getWidth();
  133. S32 new_height = orig_rect.getHeight();
  134. switch( mSide )
  135. {
  136. case LEFT:
  137. new_width = llclamp(orig_rect.getWidth() - delta_x, mMinSize, mMaxSize);
  138. delta_x = orig_rect.getWidth() - new_width;
  139. scaled_rect.translate(delta_x, 0);
  140. break;
  141. case TOP:
  142. new_height = llclamp(orig_rect.getHeight() + delta_y, mMinSize, mMaxSize);
  143. delta_y = new_height - orig_rect.getHeight();
  144. break;
  145. case RIGHT:
  146. new_width = llclamp(orig_rect.getWidth() + delta_x, mMinSize, mMaxSize);
  147. delta_x = new_width - orig_rect.getWidth();
  148. break;
  149. case BOTTOM:
  150. new_height = llclamp(orig_rect.getHeight() - delta_y, mMinSize, mMaxSize);
  151. delta_y = orig_rect.getHeight() - new_height;
  152. scaled_rect.translate(0, delta_y);
  153. break;
  154. }
  155. notifyParent(LLSD().with("action", "resize")
  156. .with("view_name", mResizingView->getName())
  157. .with("new_height", new_height)
  158. .with("new_width", new_width));
  159. scaled_rect.mTop = scaled_rect.mBottom + new_height;
  160. scaled_rect.mRight = scaled_rect.mLeft + new_width;
  161. mResizingView->setRect(scaled_rect);
  162. LLView* snap_view = NULL;
  163. if (mSnappingEnabled)
  164. {
  165. static LLUICachedControl<S32> snap_margin ("SnapMargin", 0);
  166. switch( mSide )
  167. {
  168. case LEFT:
  169. snap_view = mResizingView->findSnapEdge(scaled_rect.mLeft, mouse_dir, SNAP_LEFT, SNAP_PARENT_AND_SIBLINGS, snap_margin);
  170. break;
  171. case TOP:
  172. snap_view = mResizingView->findSnapEdge(scaled_rect.mTop, mouse_dir, SNAP_TOP, SNAP_PARENT_AND_SIBLINGS, snap_margin);
  173. break;
  174. case RIGHT:
  175. snap_view = mResizingView->findSnapEdge(scaled_rect.mRight, mouse_dir, SNAP_RIGHT, SNAP_PARENT_AND_SIBLINGS, snap_margin);
  176. break;
  177. case BOTTOM:
  178. snap_view = mResizingView->findSnapEdge(scaled_rect.mBottom, mouse_dir, SNAP_BOTTOM, SNAP_PARENT_AND_SIBLINGS, snap_margin);
  179. break;
  180. }
  181. }
  182. // register "snap" behavior with snapped view
  183. mResizingView->setSnappedTo(snap_view);
  184. // restore original rectangle so the appropriate changes are detected
  185. mResizingView->setRect(orig_rect);
  186. // change view shape as user operation
  187. mResizingView->setShape(scaled_rect, true);
  188. // update last valid mouse cursor position based on resized view's actual size
  189. LLRect new_rect = mResizingView->getRect();
  190. switch(mSide)
  191. {
  192. case LEFT:
  193. mDragLastScreenX += new_rect.mLeft - orig_rect.mLeft;
  194. break;
  195. case RIGHT:
  196. mDragLastScreenX += new_rect.mRight - orig_rect.mRight;
  197. break;
  198. case TOP:
  199. mDragLastScreenY += new_rect.mTop - orig_rect.mTop;
  200. break;
  201. case BOTTOM:
  202. mDragLastScreenY += new_rect.mBottom- orig_rect.mBottom;
  203. break;
  204. default:
  205. break;
  206. }
  207. }
  208. handled = TRUE;
  209. }
  210. else
  211. {
  212. handled = TRUE;
  213. }
  214. if( handled && canResize() )
  215. {
  216. switch( mSide )
  217. {
  218. case LEFT:
  219. case RIGHT:
  220. getWindow()->setCursor(UI_CURSOR_SIZEWE);
  221. break;
  222. case TOP:
  223. case BOTTOM:
  224. getWindow()->setCursor(UI_CURSOR_SIZENS);
  225. break;
  226. }
  227. }
  228. return handled;
  229. } // end LLResizeBar::handleHover
  230. BOOL LLResizeBar::handleDoubleClick(S32 x, S32 y, MASK mask)
  231. {
  232. LLRect orig_rect = mResizingView->getRect();
  233. LLRect scaled_rect = orig_rect;
  234. if (mSnappingEnabled && mAllowDoubleClickSnapping)
  235. {
  236. switch( mSide )
  237. {
  238. case LEFT:
  239. mResizingView->findSnapEdge(scaled_rect.mLeft, LLCoordGL(0, 0), SNAP_LEFT, SNAP_PARENT_AND_SIBLINGS, S32_MAX);
  240. scaled_rect.mLeft = scaled_rect.mRight - llclamp(scaled_rect.getWidth(), mMinSize, mMaxSize);
  241. break;
  242. case TOP:
  243. mResizingView->findSnapEdge(scaled_rect.mTop, LLCoordGL(0, 0), SNAP_TOP, SNAP_PARENT_AND_SIBLINGS, S32_MAX);
  244. scaled_rect.mTop = scaled_rect.mBottom + llclamp(scaled_rect.getHeight(), mMinSize, mMaxSize);
  245. break;
  246. case RIGHT:
  247. mResizingView->findSnapEdge(scaled_rect.mRight, LLCoordGL(0, 0), SNAP_RIGHT, SNAP_PARENT_AND_SIBLINGS, S32_MAX);
  248. scaled_rect.mRight = scaled_rect.mLeft + llclamp(scaled_rect.getWidth(), mMinSize, mMaxSize);
  249. break;
  250. case BOTTOM:
  251. mResizingView->findSnapEdge(scaled_rect.mBottom, LLCoordGL(0, 0), SNAP_BOTTOM, SNAP_PARENT_AND_SIBLINGS, S32_MAX);
  252. scaled_rect.mBottom = scaled_rect.mTop - llclamp(scaled_rect.getHeight(), mMinSize, mMaxSize);
  253. break;
  254. }
  255. mResizingView->setShape(scaled_rect, true);
  256. }
  257. return TRUE;
  258. }