Window.cpp 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. //
  2. // Urho3D Engine
  3. // Copyright (c) 2008-2011 Lasse Öörni
  4. //
  5. // Permission is hereby granted, free of charge, to any person obtaining a copy
  6. // of this software and associated documentation files (the "Software"), to deal
  7. // in the Software without restriction, including without limitation the rights
  8. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. // copies of the Software, and to permit persons to whom the Software is
  10. // furnished to do so, subject to the following conditions:
  11. //
  12. // The above copyright notice and this permission notice shall be included in
  13. // all copies or substantial portions of the Software.
  14. //
  15. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  21. // THE SOFTWARE.
  22. //
  23. #include "Precompiled.h"
  24. #include "InputEvents.h"
  25. #include "Window.h"
  26. #include "DebugNew.h"
  27. static const int DEFAULT_RESIZE_BORDER = 4;
  28. Window::Window(const std::string& name) :
  29. BorderImage(name),
  30. mMovable(false),
  31. mResizable(false),
  32. mResizeBorder(DEFAULT_RESIZE_BORDER, DEFAULT_RESIZE_BORDER, DEFAULT_RESIZE_BORDER, DEFAULT_RESIZE_BORDER),
  33. mDragMode(DRAG_NONE)
  34. {
  35. mBringToFront = true;
  36. mClipChildren = true;
  37. mEnabled = true;
  38. mFocusMode = FM_RESETFOCUS;
  39. }
  40. Window::~Window()
  41. {
  42. }
  43. void Window::setStyle(const XMLElement& element, ResourceCache* cache)
  44. {
  45. BorderImage::setStyle(element, cache);
  46. if (element.hasChildElement("resizeborder"))
  47. setResizeBorder(element.getChildElement("resizeborder").getIntRect("value"));
  48. if (element.hasChildElement("movable"))
  49. setMovable(element.getChildElement("movable").getBool("enable"));
  50. if (element.hasChildElement("resizable"))
  51. setResizable(element.getChildElement("resizable").getBool("enable"));
  52. }
  53. void Window::onDragStart(const IntVector2& position, const IntVector2& screenPosition, int buttons, int qualifiers)
  54. {
  55. if ((buttons != MOUSEB_LEFT) || (!checkAlignment()))
  56. {
  57. mDragMode = DRAG_NONE;
  58. return;
  59. }
  60. mDragStartPosition = screenPosition;
  61. mOriginalPosition = getPosition();
  62. mOriginalSize = getSize();
  63. // Identify drag type
  64. // Top row
  65. if (position.mY < mResizeBorder.mTop)
  66. {
  67. if (mMovable)
  68. mDragMode = DRAG_MOVE;
  69. if (mResizable)
  70. {
  71. mDragMode = DRAG_RESIZE_TOP;
  72. if (position.mX < mResizeBorder.mLeft)
  73. mDragMode = DRAG_RESIZE_TOPLEFT;
  74. if (position.mX >= mOriginalSize.mX - mResizeBorder.mRight)
  75. mDragMode = DRAG_RESIZE_TOPRIGHT;
  76. }
  77. }
  78. // Bottom row
  79. else if (position.mY >= mOriginalSize.mY - mResizeBorder.mBottom)
  80. {
  81. if (mMovable)
  82. mDragMode = DRAG_MOVE;
  83. if (mResizable)
  84. {
  85. mDragMode = DRAG_RESIZE_BOTTOM;
  86. if (position.mX < mResizeBorder.mLeft)
  87. mDragMode = DRAG_RESIZE_BOTTOMLEFT;
  88. if (position.mX >= mOriginalSize.mX - mResizeBorder.mRight)
  89. mDragMode = DRAG_RESIZE_BOTTOMRIGHT;
  90. }
  91. }
  92. // Middle
  93. else
  94. {
  95. if (mMovable)
  96. mDragMode = DRAG_MOVE;
  97. if (mResizable)
  98. {
  99. if (position.mX < mResizeBorder.mLeft)
  100. mDragMode = DRAG_RESIZE_LEFT;
  101. if (position.mX >= mOriginalSize.mX - mResizeBorder.mRight)
  102. mDragMode = DRAG_RESIZE_RIGHT;
  103. }
  104. }
  105. }
  106. void Window::onDragMove(const IntVector2& position, const IntVector2& screenPosition, int buttons, int qualifiers)
  107. {
  108. if (mDragMode == DRAG_NONE)
  109. return;
  110. IntVector2 delta = screenPosition - mDragStartPosition;
  111. switch (mDragMode)
  112. {
  113. case DRAG_MOVE:
  114. setPosition(mOriginalPosition + delta);
  115. break;
  116. case DRAG_RESIZE_TOPLEFT:
  117. setPosition(mOriginalPosition + delta);
  118. setSize(mOriginalSize - delta);
  119. break;
  120. case DRAG_RESIZE_TOP:
  121. setPosition(mOriginalPosition.mX, mOriginalPosition.mY + delta.mY);
  122. setSize(mOriginalSize.mX, mOriginalSize.mY - delta.mY);
  123. break;
  124. case DRAG_RESIZE_TOPRIGHT:
  125. setPosition(mOriginalPosition.mX, mOriginalPosition.mY + delta.mY);
  126. setSize(mOriginalSize.mX + delta.mX, mOriginalSize.mY - delta.mY);
  127. break;
  128. case DRAG_RESIZE_RIGHT:
  129. setSize(mOriginalSize.mX + delta.mX, mOriginalSize.mY);
  130. break;
  131. case DRAG_RESIZE_BOTTOMRIGHT:
  132. setSize(mOriginalSize + delta);
  133. break;
  134. case DRAG_RESIZE_BOTTOM:
  135. setSize(mOriginalSize.mX, mOriginalSize.mY + delta.mY);
  136. break;
  137. case DRAG_RESIZE_BOTTOMLEFT:
  138. setPosition(mOriginalPosition.mX + delta.mX, mOriginalPosition.mY);
  139. setSize(mOriginalSize.mX - delta.mX, mOriginalSize.mY + delta.mY);
  140. break;
  141. case DRAG_RESIZE_LEFT:
  142. setPosition(mOriginalPosition.mX + delta.mX, mOriginalPosition.mY);
  143. setSize(mOriginalSize.mX - delta.mX, mOriginalSize.mY);
  144. break;
  145. }
  146. validatePosition();
  147. }
  148. void Window::onDragEnd(const IntVector2& position, const IntVector2& screenPosition)
  149. {
  150. mDragMode = DRAG_NONE;
  151. }
  152. void Window::setMovable(bool enable)
  153. {
  154. mMovable = enable;
  155. }
  156. void Window::setResizable(bool enable)
  157. {
  158. mResizable = enable;
  159. }
  160. void Window::setResizeBorder(const IntRect& rect)
  161. {
  162. mResizeBorder.mLeft = max(rect.mLeft, 0);
  163. mResizeBorder.mTop = max(rect.mTop, 0);
  164. mResizeBorder.mRight = max(rect.mRight, 0);
  165. mResizeBorder.mBottom = max(rect.mBottom, 0);
  166. }
  167. void Window::setResizeBorder(int left, int top, int right, int bottom)
  168. {
  169. setResizeBorder(IntRect(left, top, right, bottom));
  170. }
  171. void Window::validatePosition()
  172. {
  173. // Check that window does not go more than halfway outside its parent in either dimension
  174. if (!mParent)
  175. return;
  176. const IntVector2& parentSize = mParent->getSize();
  177. IntVector2 position = getPosition();
  178. IntVector2 halfSize = getSize() / 2;
  179. position.mX = clamp(position.mX, -halfSize.mX, parentSize.mX - halfSize.mX);
  180. position.mY = clamp(position.mY, -halfSize.mY, parentSize.mY - halfSize.mY);
  181. setPosition(position);
  182. }
  183. bool Window::checkAlignment() const
  184. {
  185. // Only top left-alignment is supported for move and resize
  186. if ((getHorizontalAlignment() == HA_LEFT) && (getVerticalAlignment() == VA_TOP))
  187. return true;
  188. else
  189. return false;
  190. }