| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277 |
- //
- // Urho3D Engine
- // Copyright (c) 2008-2012 Lasse Öörni
- //
- // Permission is hereby granted, free of charge, to any person obtaining a copy
- // of this software and associated documentation files (the "Software"), to deal
- // in the Software without restriction, including without limitation the rights
- // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- // copies of the Software, and to permit persons to whom the Software is
- // furnished to do so, subject to the following conditions:
- //
- // The above copyright notice and this permission notice shall be included in
- // all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- // THE SOFTWARE.
- //
- #include "Precompiled.h"
- #include "Context.h"
- #include "Cursor.h"
- #include "InputEvents.h"
- #include "Window.h"
- #include "DebugNew.h"
- static const int DEFAULT_RESIZE_BORDER = 4;
- OBJECTTYPESTATIC(Window);
- Window::Window(Context* context) :
- BorderImage(context),
- movable_(false),
- resizable_(false),
- resizeBorder_(DEFAULT_RESIZE_BORDER, DEFAULT_RESIZE_BORDER, DEFAULT_RESIZE_BORDER, DEFAULT_RESIZE_BORDER),
- dragMode_(DRAG_NONE)
- {
- bringToFront_ = true;
- clipChildren_ = true;
- active_ = true;
- }
- Window::~Window()
- {
- }
- void Window::RegisterObject(Context* context)
- {
- context->RegisterFactory<Window>();
- }
- void Window::SetStyle(const XMLElement& element)
- {
- BorderImage::SetStyle(element);
-
- if (element.HasChild("resizeborder"))
- SetResizeBorder(element.GetChild("resizeborder").GetIntRect("value"));
- if (element.HasChild("movable"))
- SetMovable(element.GetChild("movable").GetBool("enable"));
- if (element.HasChild("resizable"))
- SetResizable(element.GetChild("resizable").GetBool("enable"));
- }
- void Window::OnHover(const IntVector2& position, const IntVector2& screenPosition, int buttons, int qualifiers, Cursor* cursor)
- {
- if (dragMode_ == DRAG_NONE)
- {
- WindowDragMode mode = GetDragMode(position);
- SetCursorShape(mode, cursor);
- }
- else
- SetCursorShape(dragMode_, cursor);
- }
- void Window::OnDragBegin(const IntVector2& position, const IntVector2& screenPosition, int buttons, int qualifiers, Cursor* cursor)
- {
- if (buttons != MOUSEB_LEFT || !CheckAlignment())
- {
- dragMode_ = DRAG_NONE;
- return;
- }
-
- dragBeginCursor_ = screenPosition;
- dragBeginPosition_ = GetPosition();
- dragBeginSize_ = GetSize();
- dragMode_ = GetDragMode(position);
- SetCursorShape(dragMode_, cursor);
- }
- void Window::OnDragMove(const IntVector2& position, const IntVector2& screenPosition, int buttons, int qualifiers, Cursor* cursor)
- {
- if (dragMode_ == DRAG_NONE)
- return;
-
- IntVector2 delta = screenPosition - dragBeginCursor_;
-
- switch (dragMode_)
- {
- case DRAG_MOVE:
- SetPosition(dragBeginPosition_ + delta);
- break;
-
- case DRAG_RESIZE_TOPLEFT:
- SetPosition(dragBeginPosition_ + delta);
- SetSize(dragBeginSize_ - delta);
- break;
-
- case DRAG_RESIZE_TOP:
- SetPosition(dragBeginPosition_.x_, dragBeginPosition_.y_ + delta.y_);
- SetSize(dragBeginSize_.x_, dragBeginSize_.y_ - delta.y_);
- break;
-
- case DRAG_RESIZE_TOPRIGHT:
- SetPosition(dragBeginPosition_.x_, dragBeginPosition_.y_ + delta.y_);
- SetSize(dragBeginSize_.x_ + delta.x_, dragBeginSize_.y_ - delta.y_);
- break;
-
- case DRAG_RESIZE_RIGHT:
- SetSize(dragBeginSize_.x_ + delta.x_, dragBeginSize_.y_);
- break;
-
- case DRAG_RESIZE_BOTTOMRIGHT:
- SetSize(dragBeginSize_ + delta);
- break;
-
- case DRAG_RESIZE_BOTTOM:
- SetSize(dragBeginSize_.x_, dragBeginSize_.y_ + delta.y_);
- break;
-
- case DRAG_RESIZE_BOTTOMLEFT:
- SetPosition(dragBeginPosition_.x_ + delta.x_, dragBeginPosition_.y_);
- SetSize(dragBeginSize_.x_ - delta.x_, dragBeginSize_.y_ + delta.y_);
- break;
-
- case DRAG_RESIZE_LEFT:
- SetPosition(dragBeginPosition_.x_ + delta.x_, dragBeginPosition_.y_);
- SetSize(dragBeginSize_.x_ - delta.x_, dragBeginSize_.y_);
- break;
- default:
- break;
- }
-
- ValidatePosition();
- SetCursorShape(dragMode_, cursor);
- }
- void Window::OnDragEnd(const IntVector2& position, const IntVector2& screenPosition, Cursor* cursor)
- {
- dragMode_ = DRAG_NONE;
- }
- void Window::SetMovable(bool enable)
- {
- movable_ = enable;
- }
- void Window::SetResizable(bool enable)
- {
- resizable_ = enable;
- }
- void Window::SetResizeBorder(const IntRect& rect)
- {
- resizeBorder_.left_ = Max(rect.left_, 0);
- resizeBorder_.top_ = Max(rect.top_, 0);
- resizeBorder_.right_ = Max(rect.right_, 0);
- resizeBorder_.bottom_ = Max(rect.bottom_, 0);
- }
- WindowDragMode Window::GetDragMode(const IntVector2& position) const
- {
- WindowDragMode mode = DRAG_NONE;
-
- // Top row
- if (position.y_ < resizeBorder_.top_)
- {
- if (movable_)
- mode = DRAG_MOVE;
- if (resizable_)
- {
- mode = DRAG_RESIZE_TOP;
- if (position.x_ < resizeBorder_.left_)
- mode = DRAG_RESIZE_TOPLEFT;
- if (position.x_ >= GetWidth() - resizeBorder_.right_)
- mode = DRAG_RESIZE_TOPRIGHT;
- }
- }
- // Bottom row
- else if (position.y_ >= GetHeight() - resizeBorder_.bottom_)
- {
- if (movable_)
- mode = DRAG_MOVE;
- if (resizable_)
- {
- mode = DRAG_RESIZE_BOTTOM;
- if (position.x_ < resizeBorder_.left_)
- mode = DRAG_RESIZE_BOTTOMLEFT;
- if (position.x_ >= GetWidth() - resizeBorder_.right_)
- mode = DRAG_RESIZE_BOTTOMRIGHT;
- }
- }
- // Middle
- else
- {
- if (movable_)
- mode = DRAG_MOVE;
- if (resizable_)
- {
- if (position.x_ < resizeBorder_.left_)
- mode = DRAG_RESIZE_LEFT;
- if (position.x_ >= GetWidth() - resizeBorder_.right_)
- mode = DRAG_RESIZE_RIGHT;
- }
- }
-
- return mode;
- }
- void Window::SetCursorShape(WindowDragMode mode, Cursor* cursor) const
- {
- if (!cursor)
- return;
-
- switch (mode)
- {
- case DRAG_RESIZE_TOP:
- case DRAG_RESIZE_BOTTOM:
- cursor->SetShape(CS_RESIZEVERTICAL);
- break;
-
- case DRAG_RESIZE_LEFT:
- case DRAG_RESIZE_RIGHT:
- cursor->SetShape(CS_RESIZEHORIZONTAL);
- break;
- case DRAG_RESIZE_TOPRIGHT:
- case DRAG_RESIZE_BOTTOMLEFT:
- cursor->SetShape(CS_RESIZEDIAGONAL_TOPRIGHT);
- break;
-
- case DRAG_RESIZE_TOPLEFT:
- case DRAG_RESIZE_BOTTOMRIGHT:
- cursor->SetShape(CS_RESIZEDIAGONAL_TOPLEFT);
- break;
- }
- }
- void Window::ValidatePosition()
- {
- // Check that window does not go more than halfway outside its parent in either dimension
- if (!parent_)
- return;
-
- const IntVector2& parentSize = parent_->GetSize();
- IntVector2 position = GetPosition();
- IntVector2 halfSize = GetSize() / 2;
-
- position.x_ = Clamp(position.x_, -halfSize.x_, parentSize.x_ - halfSize.x_);
- position.y_ = Clamp(position.y_, -halfSize.y_, parentSize.y_ - halfSize.y_);
-
- SetPosition(position);
- }
- bool Window::CheckAlignment() const
- {
- // Only top left-alignment is supported for move and resize
- if (GetHorizontalAlignment() == HA_LEFT && GetVerticalAlignment() == VA_TOP)
- return true;
- else
- return false;
- }
|