Window.cpp 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. //
  2. // Copyright (c) 2008-2013 the Urho3D project.
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to deal
  6. // in the Software without restriction, including without limitation the rights
  7. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. // copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20. // THE SOFTWARE.
  21. //
  22. #include "Precompiled.h"
  23. #include "Context.h"
  24. #include "Cursor.h"
  25. #include "InputEvents.h"
  26. #include "Window.h"
  27. #include "DebugNew.h"
  28. namespace Urho3D
  29. {
  30. static const int DEFAULT_RESIZE_BORDER = 4;
  31. OBJECTTYPESTATIC(Window);
  32. Window::Window(Context* context) :
  33. BorderImage(context),
  34. movable_(false),
  35. resizable_(false),
  36. resizeBorder_(DEFAULT_RESIZE_BORDER, DEFAULT_RESIZE_BORDER, DEFAULT_RESIZE_BORDER, DEFAULT_RESIZE_BORDER),
  37. dragMode_(DRAG_NONE)
  38. {
  39. bringToFront_ = true;
  40. clipChildren_ = true;
  41. active_ = true;
  42. }
  43. Window::~Window()
  44. {
  45. }
  46. void Window::RegisterObject(Context* context)
  47. {
  48. context->RegisterFactory<Window>();
  49. REF_ACCESSOR_ATTRIBUTE(Window, VAR_INTRECT, "Resize Border", GetResizeBorder, SetResizeBorder, IntRect, IntRect(DEFAULT_RESIZE_BORDER, \
  50. DEFAULT_RESIZE_BORDER, DEFAULT_RESIZE_BORDER, DEFAULT_RESIZE_BORDER), AM_FILE);
  51. ACCESSOR_ATTRIBUTE(Window, VAR_BOOL, "Is Movable", IsMovable, SetMovable, bool, false, AM_FILE);
  52. ACCESSOR_ATTRIBUTE(Window, VAR_BOOL, "Is Resizable", IsResizable, SetResizable, bool, false, AM_FILE);
  53. COPY_BASE_ATTRIBUTES(Window, BorderImage);
  54. }
  55. void Window::OnHover(const IntVector2& position, const IntVector2& screenPosition, int buttons, int qualifiers, Cursor* cursor)
  56. {
  57. if (dragMode_ == DRAG_NONE)
  58. {
  59. WindowDragMode mode = GetDragMode(position);
  60. SetCursorShape(mode, cursor);
  61. }
  62. else
  63. SetCursorShape(dragMode_, cursor);
  64. }
  65. void Window::OnDragBegin(const IntVector2& position, const IntVector2& screenPosition, int buttons, int qualifiers, Cursor* cursor)
  66. {
  67. if (buttons != MOUSEB_LEFT || !CheckAlignment())
  68. {
  69. dragMode_ = DRAG_NONE;
  70. return;
  71. }
  72. dragBeginCursor_ = screenPosition;
  73. dragBeginPosition_ = GetPosition();
  74. dragBeginSize_ = GetSize();
  75. dragMode_ = GetDragMode(position);
  76. SetCursorShape(dragMode_, cursor);
  77. }
  78. void Window::OnDragMove(const IntVector2& position, const IntVector2& screenPosition, int buttons, int qualifiers, Cursor* cursor)
  79. {
  80. if (dragMode_ == DRAG_NONE)
  81. return;
  82. IntVector2 delta = screenPosition - dragBeginCursor_;
  83. switch (dragMode_)
  84. {
  85. case DRAG_MOVE:
  86. SetPosition(dragBeginPosition_ + delta);
  87. break;
  88. case DRAG_RESIZE_TOPLEFT:
  89. SetPosition(dragBeginPosition_ + delta);
  90. SetSize(dragBeginSize_ - delta);
  91. break;
  92. case DRAG_RESIZE_TOP:
  93. SetPosition(dragBeginPosition_.x_, dragBeginPosition_.y_ + delta.y_);
  94. SetSize(dragBeginSize_.x_, dragBeginSize_.y_ - delta.y_);
  95. break;
  96. case DRAG_RESIZE_TOPRIGHT:
  97. SetPosition(dragBeginPosition_.x_, dragBeginPosition_.y_ + delta.y_);
  98. SetSize(dragBeginSize_.x_ + delta.x_, dragBeginSize_.y_ - delta.y_);
  99. break;
  100. case DRAG_RESIZE_RIGHT:
  101. SetSize(dragBeginSize_.x_ + delta.x_, dragBeginSize_.y_);
  102. break;
  103. case DRAG_RESIZE_BOTTOMRIGHT:
  104. SetSize(dragBeginSize_ + delta);
  105. break;
  106. case DRAG_RESIZE_BOTTOM:
  107. SetSize(dragBeginSize_.x_, dragBeginSize_.y_ + delta.y_);
  108. break;
  109. case DRAG_RESIZE_BOTTOMLEFT:
  110. SetPosition(dragBeginPosition_.x_ + delta.x_, dragBeginPosition_.y_);
  111. SetSize(dragBeginSize_.x_ - delta.x_, dragBeginSize_.y_ + delta.y_);
  112. break;
  113. case DRAG_RESIZE_LEFT:
  114. SetPosition(dragBeginPosition_.x_ + delta.x_, dragBeginPosition_.y_);
  115. SetSize(dragBeginSize_.x_ - delta.x_, dragBeginSize_.y_);
  116. break;
  117. default:
  118. break;
  119. }
  120. ValidatePosition();
  121. SetCursorShape(dragMode_, cursor);
  122. }
  123. void Window::OnDragEnd(const IntVector2& position, const IntVector2& screenPosition, Cursor* cursor)
  124. {
  125. dragMode_ = DRAG_NONE;
  126. }
  127. void Window::SetMovable(bool enable)
  128. {
  129. movable_ = enable;
  130. }
  131. void Window::SetResizable(bool enable)
  132. {
  133. resizable_ = enable;
  134. }
  135. void Window::SetResizeBorder(const IntRect& rect)
  136. {
  137. resizeBorder_.left_ = Max(rect.left_, 0);
  138. resizeBorder_.top_ = Max(rect.top_, 0);
  139. resizeBorder_.right_ = Max(rect.right_, 0);
  140. resizeBorder_.bottom_ = Max(rect.bottom_, 0);
  141. }
  142. WindowDragMode Window::GetDragMode(const IntVector2& position) const
  143. {
  144. WindowDragMode mode = DRAG_NONE;
  145. // Top row
  146. if (position.y_ < resizeBorder_.top_)
  147. {
  148. if (movable_)
  149. mode = DRAG_MOVE;
  150. if (resizable_)
  151. {
  152. mode = DRAG_RESIZE_TOP;
  153. if (position.x_ < resizeBorder_.left_)
  154. mode = DRAG_RESIZE_TOPLEFT;
  155. if (position.x_ >= GetWidth() - resizeBorder_.right_)
  156. mode = DRAG_RESIZE_TOPRIGHT;
  157. }
  158. }
  159. // Bottom row
  160. else if (position.y_ >= GetHeight() - resizeBorder_.bottom_)
  161. {
  162. if (movable_)
  163. mode = DRAG_MOVE;
  164. if (resizable_)
  165. {
  166. mode = DRAG_RESIZE_BOTTOM;
  167. if (position.x_ < resizeBorder_.left_)
  168. mode = DRAG_RESIZE_BOTTOMLEFT;
  169. if (position.x_ >= GetWidth() - resizeBorder_.right_)
  170. mode = DRAG_RESIZE_BOTTOMRIGHT;
  171. }
  172. }
  173. // Middle
  174. else
  175. {
  176. if (movable_)
  177. mode = DRAG_MOVE;
  178. if (resizable_)
  179. {
  180. if (position.x_ < resizeBorder_.left_)
  181. mode = DRAG_RESIZE_LEFT;
  182. if (position.x_ >= GetWidth() - resizeBorder_.right_)
  183. mode = DRAG_RESIZE_RIGHT;
  184. }
  185. }
  186. return mode;
  187. }
  188. void Window::SetCursorShape(WindowDragMode mode, Cursor* cursor) const
  189. {
  190. if (!cursor)
  191. return;
  192. switch (mode)
  193. {
  194. case DRAG_RESIZE_TOP:
  195. case DRAG_RESIZE_BOTTOM:
  196. cursor->SetShape(CS_RESIZEVERTICAL);
  197. break;
  198. case DRAG_RESIZE_LEFT:
  199. case DRAG_RESIZE_RIGHT:
  200. cursor->SetShape(CS_RESIZEHORIZONTAL);
  201. break;
  202. case DRAG_RESIZE_TOPRIGHT:
  203. case DRAG_RESIZE_BOTTOMLEFT:
  204. cursor->SetShape(CS_RESIZEDIAGONAL_TOPRIGHT);
  205. break;
  206. case DRAG_RESIZE_TOPLEFT:
  207. case DRAG_RESIZE_BOTTOMRIGHT:
  208. cursor->SetShape(CS_RESIZEDIAGONAL_TOPLEFT);
  209. break;
  210. default:
  211. break;
  212. }
  213. }
  214. void Window::ValidatePosition()
  215. {
  216. // Check that window does not go more than halfway outside its parent in either dimension
  217. if (!parent_)
  218. return;
  219. const IntVector2& parentSize = parent_->GetSize();
  220. IntVector2 position = GetPosition();
  221. IntVector2 halfSize = GetSize() / 2;
  222. position.x_ = Clamp(position.x_, -halfSize.x_, parentSize.x_ - halfSize.x_);
  223. position.y_ = Clamp(position.y_, -halfSize.y_, parentSize.y_ - halfSize.y_);
  224. SetPosition(position);
  225. }
  226. bool Window::CheckAlignment() const
  227. {
  228. // Only top left-alignment is supported for move and resize
  229. if (GetHorizontalAlignment() == HA_LEFT && GetVerticalAlignment() == VA_TOP)
  230. return true;
  231. else
  232. return false;
  233. }
  234. }