Window.cpp 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  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. mMinSize(0, 0),
  33. mMaxSize(M_MAX_INT, M_MAX_INT),
  34. mResizeBorder(DEFAULT_RESIZE_BORDER, DEFAULT_RESIZE_BORDER, DEFAULT_RESIZE_BORDER, DEFAULT_RESIZE_BORDER),
  35. mDragMode(DRAG_NONE)
  36. {
  37. mBringToFront = true;
  38. mEnabled = true;
  39. validateSize();
  40. }
  41. Window::~Window()
  42. {
  43. }
  44. void Window::setStyle(const XMLElement& element, ResourceCache* cache)
  45. {
  46. BorderImage::setStyle(element, cache);
  47. if (element.hasChildElement("minsize"))
  48. setMinSize(element.getChildElement("minsize").getIntVector2("value"));
  49. if (element.hasChildElement("maxsize"))
  50. setMaxSize(element.getChildElement("maxsize").getIntVector2("value"));
  51. if (element.hasChildElement("resizeborder"))
  52. setResizeBorder(element.getChildElement("resizeborder").getIntRect("value"));
  53. if (element.hasChildElement("movable"))
  54. setMovable(element.getChildElement("movable").getBool("enable"));
  55. if (element.hasChildElement("resizable"))
  56. setResizable(element.getChildElement("resizable").getBool("enable"));
  57. }
  58. void Window::onDragStart(const IntVector2& position, const IntVector2& screenPosition, int buttons, int qualifiers)
  59. {
  60. if ((buttons != MOUSEB_LEFT) || (!checkAlignment()))
  61. {
  62. mDragMode = DRAG_NONE;
  63. return;
  64. }
  65. mDragStartPosition = screenPosition;
  66. mOriginalPosition = getPosition();
  67. mOriginalSize = getSize();
  68. // Identify drag type
  69. // Top row
  70. if (position.mY < mResizeBorder.mTop)
  71. {
  72. if (mMovable)
  73. mDragMode = DRAG_MOVE;
  74. if (mResizable)
  75. {
  76. mDragMode = DRAG_RESIZE_TOP;
  77. if (position.mX < mResizeBorder.mLeft)
  78. mDragMode = DRAG_RESIZE_TOPLEFT;
  79. if (position.mX >= mOriginalSize.mX - mResizeBorder.mRight)
  80. mDragMode = DRAG_RESIZE_TOPRIGHT;
  81. }
  82. }
  83. // Bottom row
  84. else if (position.mY >= mOriginalSize.mY - mResizeBorder.mBottom)
  85. {
  86. if (mMovable)
  87. mDragMode = DRAG_MOVE;
  88. if (mResizable)
  89. {
  90. mDragMode = DRAG_RESIZE_BOTTOM;
  91. if (position.mX < mResizeBorder.mLeft)
  92. mDragMode = DRAG_RESIZE_BOTTOMLEFT;
  93. if (position.mX >= mOriginalSize.mX - mResizeBorder.mRight)
  94. mDragMode = DRAG_RESIZE_BOTTOMRIGHT;
  95. }
  96. }
  97. // Middle
  98. else
  99. {
  100. if (mMovable)
  101. mDragMode = DRAG_MOVE;
  102. if (mResizable)
  103. {
  104. if (position.mX < mResizeBorder.mLeft)
  105. mDragMode = DRAG_RESIZE_LEFT;
  106. if (position.mX >= mOriginalSize.mX - mResizeBorder.mRight)
  107. mDragMode = DRAG_RESIZE_RIGHT;
  108. }
  109. }
  110. }
  111. void Window::onDragMove(const IntVector2& position, const IntVector2& screenPosition, int buttons, int qualifiers)
  112. {
  113. if (mDragMode == DRAG_NONE)
  114. return;
  115. IntVector2 delta = screenPosition - mDragStartPosition;
  116. switch (mDragMode)
  117. {
  118. case DRAG_MOVE:
  119. setPosition(mOriginalPosition + delta);
  120. break;
  121. case DRAG_RESIZE_TOPLEFT:
  122. setPosition(mOriginalPosition + delta);
  123. setSize(mOriginalSize - delta);
  124. break;
  125. case DRAG_RESIZE_TOP:
  126. setPosition(mOriginalPosition.mX, mOriginalPosition.mY + delta.mY);
  127. setSize(mOriginalSize.mX, mOriginalSize.mY - delta.mY);
  128. break;
  129. case DRAG_RESIZE_TOPRIGHT:
  130. setPosition(mOriginalPosition.mX, mOriginalPosition.mY + delta.mY);
  131. setSize(mOriginalSize.mX + delta.mX, mOriginalSize.mY - delta.mY);
  132. break;
  133. case DRAG_RESIZE_RIGHT:
  134. setSize(mOriginalSize.mX + delta.mX, mOriginalSize.mY);
  135. break;
  136. case DRAG_RESIZE_BOTTOMRIGHT:
  137. setSize(mOriginalSize + delta);
  138. break;
  139. case DRAG_RESIZE_BOTTOM:
  140. setSize(mOriginalSize.mX, mOriginalSize.mY + delta.mY);
  141. break;
  142. case DRAG_RESIZE_BOTTOMLEFT:
  143. setPosition(mOriginalPosition.mX + delta.mX, mOriginalPosition.mY);
  144. setSize(mOriginalSize.mX - delta.mX, mOriginalSize.mY + delta.mY);
  145. break;
  146. case DRAG_RESIZE_LEFT:
  147. setPosition(mOriginalPosition.mX + delta.mX, mOriginalPosition.mY);
  148. setSize(mOriginalSize.mX - delta.mX, mOriginalSize.mY);
  149. break;
  150. }
  151. validateSize();
  152. validatePosition();
  153. }
  154. void Window::onDragEnd(const IntVector2& position, const IntVector2& screenPosition)
  155. {
  156. mDragMode = DRAG_NONE;
  157. }
  158. void Window::setMovable(bool enable)
  159. {
  160. mMovable = enable;
  161. }
  162. void Window::setResizable(bool enable)
  163. {
  164. mResizable = enable;
  165. }
  166. void Window::setMinSize(const IntVector2& minSize)
  167. {
  168. mMinSize = minSize;
  169. validateSize();
  170. }
  171. void Window::setMinSize(int width, int height)
  172. {
  173. setMinSize(IntVector2(width, height));
  174. }
  175. void Window::setMaxSize(const IntVector2& maxSize)
  176. {
  177. mMaxSize = maxSize;
  178. validateSize();
  179. }
  180. void Window::setMaxSize(int width, int height)
  181. {
  182. setMaxSize(IntVector2(width, height));
  183. }
  184. void Window::setResizeBorder(const IntRect& rect)
  185. {
  186. mResizeBorder.mLeft = max(rect.mLeft, 0);
  187. mResizeBorder.mTop = max(rect.mTop, 0);
  188. mResizeBorder.mRight = max(rect.mRight, 0);
  189. mResizeBorder.mBottom = max(rect.mBottom, 0);
  190. }
  191. void Window::setResizeBorder(int left, int top, int right, int bottom)
  192. {
  193. setResizeBorder(IntRect(left, top, right, bottom));
  194. }
  195. void Window::validateSize()
  196. {
  197. mMinSize.mX = max(mMinSize.mX, 0);
  198. mMinSize.mY = max(mMinSize.mY, 0);
  199. mMaxSize.mX = max(mMaxSize.mX, mMinSize.mX);
  200. mMaxSize.mY = max(mMaxSize.mY, mMinSize.mX);
  201. IntVector2 size = getSize();
  202. size.mX = clamp(size.mX, mMinSize.mX, mMaxSize.mX);
  203. size.mY = clamp(size.mY, mMinSize.mY, mMaxSize.mY);
  204. setSize(size);
  205. }
  206. void Window::validatePosition()
  207. {
  208. // Check that window does not go more than halfway outside its parent in either dimension
  209. if (!mParent)
  210. return;
  211. const IntVector2& parentSize = mParent->getSize();
  212. IntVector2 position = getPosition();
  213. IntVector2 halfSize = getSize() / 2;
  214. position.mX = clamp(position.mX, -halfSize.mX, parentSize.mX - halfSize.mX);
  215. position.mY = clamp(position.mY, -halfSize.mY, parentSize.mY - halfSize.mY);
  216. setPosition(position);
  217. }
  218. bool Window::checkAlignment() const
  219. {
  220. // Only top left-alignment is supported for move and resize
  221. if ((getHorizontalAlignment() == HA_LEFT) && (getVerticalAlignment() == VA_TOP))
  222. return true;
  223. else
  224. return false;
  225. }