PageRenderTime 39ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/indra/llui/lldraghandle.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 386 lines | 215 code | 56 blank | 115 comment | 14 complexity | 2bacc5d9dfe5c66903373c2fc719a542 MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file lldraghandle.cpp
  3. * @brief LLDragHandle 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. // A widget for dragging a view around the screen using the mouse.
  27. #include "linden_common.h"
  28. #include "lldraghandle.h"
  29. #include "llmath.h"
  30. //#include "llviewerwindow.h"
  31. #include "llui.h"
  32. #include "llmenugl.h"
  33. #include "lltextbox.h"
  34. #include "llcontrol.h"
  35. #include "llfontgl.h"
  36. #include "llwindow.h"
  37. #include "llfocusmgr.h"
  38. #include "lluictrlfactory.h"
  39. const S32 LEADING_PAD = 5;
  40. const S32 TITLE_HPAD = 8;
  41. const S32 BORDER_PAD = 1;
  42. const S32 LEFT_PAD = BORDER_PAD + TITLE_HPAD + LEADING_PAD;
  43. const S32 RIGHT_PAD = BORDER_PAD + 32; // HACK: space for close btn and minimize btn
  44. S32 LLDragHandle::sSnapMargin = 5;
  45. LLDragHandle::LLDragHandle(const LLDragHandle::Params& p)
  46. : LLView(p),
  47. mDragLastScreenX( 0 ),
  48. mDragLastScreenY( 0 ),
  49. mLastMouseScreenX( 0 ),
  50. mLastMouseScreenY( 0 ),
  51. mTitleBox( NULL ),
  52. mMaxTitleWidth( 0 ),
  53. mForeground( TRUE ),
  54. mDragHighlightColor(p.drag_highlight_color()),
  55. mDragShadowColor(p.drag_shadow_color())
  56. {
  57. static LLUICachedControl<S32> snap_margin ("SnapMargin", 0);
  58. sSnapMargin = snap_margin;
  59. }
  60. LLDragHandle::~LLDragHandle()
  61. {
  62. removeChild(mTitleBox);
  63. delete mTitleBox;
  64. }
  65. void LLDragHandle::initFromParams(const LLDragHandle::Params& p)
  66. {
  67. LLView::initFromParams(p);
  68. setTitle( p.label );
  69. }
  70. void LLDragHandle::setTitleVisible(BOOL visible)
  71. {
  72. if(mTitleBox)
  73. {
  74. mTitleBox->setVisible(visible);
  75. }
  76. }
  77. void LLDragHandleTop::setTitle(const std::string& title)
  78. {
  79. std::string trimmed_title = title;
  80. LLStringUtil::trim(trimmed_title);
  81. if( mTitleBox )
  82. {
  83. mTitleBox->setText(trimmed_title);
  84. }
  85. else
  86. {
  87. const LLFontGL* font = LLFontGL::getFontSansSerif();
  88. LLTextBox::Params params;
  89. params.name("Drag Handle Title");
  90. params.rect(getRect());
  91. params.initial_value(trimmed_title);
  92. params.font(font);
  93. params.follows.flags(FOLLOWS_TOP | FOLLOWS_LEFT | FOLLOWS_RIGHT);
  94. params.font_shadow(LLFontGL::DROP_SHADOW_SOFT);
  95. params.use_ellipses = true;
  96. params.parse_urls = false; //cancel URL replacement in floater title
  97. mTitleBox = LLUICtrlFactory::create<LLTextBox> (params);
  98. addChild( mTitleBox );
  99. }
  100. reshapeTitleBox();
  101. }
  102. std::string LLDragHandleTop::getTitle() const
  103. {
  104. return mTitleBox == NULL ? LLStringUtil::null : mTitleBox->getText();
  105. }
  106. void LLDragHandleLeft::setTitle(const std::string& )
  107. {
  108. if( mTitleBox )
  109. {
  110. removeChild(mTitleBox);
  111. delete mTitleBox;
  112. mTitleBox = NULL;
  113. }
  114. /* no title on left edge */
  115. }
  116. std::string LLDragHandleLeft::getTitle() const
  117. {
  118. return LLStringUtil::null;
  119. }
  120. void LLDragHandleTop::draw()
  121. {
  122. /* Disable lines. Can drag anywhere in most windows. JC
  123. if( getVisible() && getEnabled() && mForeground)
  124. {
  125. const S32 BORDER_PAD = 2;
  126. const S32 HPAD = 2;
  127. const S32 VPAD = 2;
  128. S32 left = BORDER_PAD + HPAD;
  129. S32 top = getRect().getHeight() - 2 * VPAD;
  130. S32 right = getRect().getWidth() - HPAD;
  131. // S32 bottom = VPAD;
  132. // draw lines for drag areas
  133. const S32 LINE_SPACING = (DRAG_HANDLE_HEIGHT - 2 * VPAD) / 4;
  134. S32 line = top - LINE_SPACING;
  135. LLRect title_rect = mTitleBox->getRect();
  136. S32 title_right = title_rect.mLeft + mTitleWidth;
  137. BOOL show_right_side = title_right < getRect().getWidth();
  138. for( S32 i=0; i<4; i++ )
  139. {
  140. gl_line_2d(left, line+1, title_rect.mLeft - LEADING_PAD, line+1, mDragHighlightColor);
  141. if( show_right_side )
  142. {
  143. gl_line_2d(title_right, line+1, right, line+1, mDragHighlightColor);
  144. }
  145. gl_line_2d(left, line, title_rect.mLeft - LEADING_PAD, line, mDragShadowColor);
  146. if( show_right_side )
  147. {
  148. gl_line_2d(title_right, line, right, line, mDragShadowColor);
  149. }
  150. line -= LINE_SPACING;
  151. }
  152. }
  153. */
  154. // Colorize the text to match the frontmost state
  155. if (mTitleBox)
  156. {
  157. mTitleBox->setEnabled(getForeground());
  158. }
  159. LLView::draw();
  160. }
  161. // assumes GL state is set for 2D
  162. void LLDragHandleLeft::draw()
  163. {
  164. /* Disable lines. Can drag anywhere in most windows. JC
  165. if( getVisible() && getEnabled() && mForeground )
  166. {
  167. const S32 BORDER_PAD = 2;
  168. // const S32 HPAD = 2;
  169. const S32 VPAD = 2;
  170. const S32 LINE_SPACING = 3;
  171. S32 left = BORDER_PAD + LINE_SPACING;
  172. S32 top = getRect().getHeight() - 2 * VPAD;
  173. // S32 right = getRect().getWidth() - HPAD;
  174. S32 bottom = VPAD;
  175. // draw lines for drag areas
  176. // no titles yet
  177. //LLRect title_rect = mTitleBox->getRect();
  178. //S32 title_right = title_rect.mLeft + mTitleWidth;
  179. //BOOL show_right_side = title_right < getRect().getWidth();
  180. S32 line = left;
  181. for( S32 i=0; i<4; i++ )
  182. {
  183. gl_line_2d(line, top, line, bottom, mDragHighlightColor);
  184. gl_line_2d(line+1, top, line+1, bottom, mDragShadowColor);
  185. line += LINE_SPACING;
  186. }
  187. }
  188. */
  189. // Colorize the text to match the frontmost state
  190. if (mTitleBox)
  191. {
  192. mTitleBox->setEnabled(getForeground());
  193. }
  194. LLView::draw();
  195. }
  196. void LLDragHandleTop::reshapeTitleBox()
  197. {
  198. static LLUICachedControl<S32> title_vpad("UIFloaterTitleVPad", 0);
  199. if( ! mTitleBox)
  200. {
  201. return;
  202. }
  203. const LLFontGL* font = LLFontGL::getFontSansSerif();
  204. S32 title_width = getRect().getWidth();
  205. title_width -= LEFT_PAD + 2 * BORDER_PAD + getButtonsRect().getWidth();
  206. S32 title_height = llround(font->getLineHeight());
  207. LLRect title_rect;
  208. title_rect.setLeftTopAndSize(
  209. LEFT_PAD,
  210. getRect().getHeight() - title_vpad,
  211. title_width,
  212. title_height);
  213. // calls reshape on mTitleBox
  214. mTitleBox->setShape( title_rect );
  215. }
  216. void LLDragHandleTop::reshape(S32 width, S32 height, BOOL called_from_parent)
  217. {
  218. LLView::reshape(width, height, called_from_parent);
  219. reshapeTitleBox();
  220. }
  221. void LLDragHandleLeft::reshape(S32 width, S32 height, BOOL called_from_parent)
  222. {
  223. LLView::reshape(width, height, called_from_parent);
  224. }
  225. //-------------------------------------------------------------
  226. // UI event handling
  227. //-------------------------------------------------------------
  228. BOOL LLDragHandle::handleMouseDown(S32 x, S32 y, MASK mask)
  229. {
  230. // Route future Mouse messages here preemptively. (Release on mouse up.)
  231. // No handler needed for focus lost since this clas has no state that depends on it.
  232. gFocusMgr.setMouseCapture(this);
  233. localPointToScreen(x, y, &mDragLastScreenX, &mDragLastScreenY);
  234. mLastMouseScreenX = mDragLastScreenX;
  235. mLastMouseScreenY = mDragLastScreenY;
  236. // Note: don't pass on to children
  237. return TRUE;
  238. }
  239. BOOL LLDragHandle::handleMouseUp(S32 x, S32 y, MASK mask)
  240. {
  241. if( hasMouseCapture() )
  242. {
  243. // Release the mouse
  244. gFocusMgr.setMouseCapture( NULL );
  245. }
  246. // Note: don't pass on to children
  247. return TRUE;
  248. }
  249. BOOL LLDragHandle::handleHover(S32 x, S32 y, MASK mask)
  250. {
  251. BOOL handled = FALSE;
  252. // We only handle the click if the click both started and ended within us
  253. if( hasMouseCapture() )
  254. {
  255. S32 screen_x;
  256. S32 screen_y;
  257. localPointToScreen(x, y, &screen_x, &screen_y);
  258. // Resize the parent
  259. S32 delta_x = screen_x - mDragLastScreenX;
  260. S32 delta_y = screen_y - mDragLastScreenY;
  261. // if dragging a docked floater we want to undock
  262. if (((LLFloater*)getParent())->isDocked())
  263. {
  264. const S32 SLOP = 12;
  265. if (delta_y <= -SLOP ||
  266. delta_y >= SLOP)
  267. {
  268. ((LLFloater*)getParent())->setDocked(false, false);
  269. return TRUE;
  270. }
  271. else
  272. {
  273. return FALSE;
  274. }
  275. }
  276. LLRect original_rect = getParent()->getRect();
  277. LLRect translated_rect = getParent()->getRect();
  278. translated_rect.translate(delta_x, delta_y);
  279. // temporarily slam dragged window to new position
  280. getParent()->setRect(translated_rect);
  281. S32 pre_snap_x = getParent()->getRect().mLeft;
  282. S32 pre_snap_y = getParent()->getRect().mBottom;
  283. mDragLastScreenX = screen_x;
  284. mDragLastScreenY = screen_y;
  285. LLRect new_rect;
  286. LLCoordGL mouse_dir;
  287. // use hysteresis on mouse motion to preserve user intent when mouse stops moving
  288. mouse_dir.mX = (screen_x == mLastMouseScreenX) ? mLastMouseDir.mX : screen_x - mLastMouseScreenX;
  289. mouse_dir.mY = (screen_y == mLastMouseScreenY) ? mLastMouseDir.mY : screen_y - mLastMouseScreenY;
  290. mLastMouseDir = mouse_dir;
  291. mLastMouseScreenX = screen_x;
  292. mLastMouseScreenY = screen_y;
  293. LLView* snap_view = getParent()->findSnapRect(new_rect, mouse_dir, SNAP_PARENT_AND_SIBLINGS, sSnapMargin);
  294. getParent()->setSnappedTo(snap_view);
  295. delta_x = new_rect.mLeft - pre_snap_x;
  296. delta_y = new_rect.mBottom - pre_snap_y;
  297. translated_rect.translate(delta_x, delta_y);
  298. // restore original rect so delta are detected, then call user reshape method to handle snapped floaters, etc
  299. getParent()->setRect(original_rect);
  300. getParent()->setShape(translated_rect, true);
  301. mDragLastScreenX += delta_x;
  302. mDragLastScreenY += delta_y;
  303. getWindow()->setCursor(UI_CURSOR_ARROW);
  304. lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << " (active)" <<llendl;
  305. handled = TRUE;
  306. }
  307. else
  308. {
  309. getWindow()->setCursor(UI_CURSOR_ARROW);
  310. lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << " (inactive)" << llendl;
  311. handled = TRUE;
  312. }
  313. // Note: don't pass on to children
  314. return handled;
  315. }
  316. void LLDragHandle::setValue(const LLSD& value)
  317. {
  318. setTitle(value.asString());
  319. }