177 lines
5.5 KiB
C++
177 lines
5.5 KiB
C++
#include "BorderlessWindowFrame.h"
|
|
|
|
#include <algorithm>
|
|
|
|
namespace XCEngine::UI::Editor::Host {
|
|
|
|
namespace {
|
|
|
|
using ::XCEngine::UI::UIPoint;
|
|
using ::XCEngine::UI::UIRect;
|
|
|
|
bool IsPointInsideRect(const UIRect& rect, const UIPoint& point) {
|
|
return rect.width > 0.0f &&
|
|
rect.height > 0.0f &&
|
|
point.x >= rect.x &&
|
|
point.x <= rect.x + rect.width &&
|
|
point.y >= rect.y &&
|
|
point.y <= rect.y + rect.height;
|
|
}
|
|
|
|
int ClampMinimum(int value, int minimum) {
|
|
return (std::max)(value, minimum);
|
|
}
|
|
|
|
} // namespace
|
|
|
|
BorderlessWindowResizeEdge HitTestBorderlessWindowResizeEdge(
|
|
const UIRect& clientRect,
|
|
const UIPoint& point,
|
|
const BorderlessWindowFrameMetrics& metrics) {
|
|
const float edge = (std::max)(metrics.resizeBorderThickness, 0.0f);
|
|
if (edge <= 0.0f || !IsPointInsideRect(clientRect, point)) {
|
|
return BorderlessWindowResizeEdge::None;
|
|
}
|
|
|
|
const bool left = point.x <= clientRect.x + edge;
|
|
const bool right = point.x >= clientRect.x + clientRect.width - edge;
|
|
const bool top = point.y <= clientRect.y + edge;
|
|
const bool bottom = point.y >= clientRect.y + clientRect.height - edge;
|
|
|
|
if (left && top) {
|
|
return BorderlessWindowResizeEdge::TopLeft;
|
|
}
|
|
if (right && top) {
|
|
return BorderlessWindowResizeEdge::TopRight;
|
|
}
|
|
if (left && bottom) {
|
|
return BorderlessWindowResizeEdge::BottomLeft;
|
|
}
|
|
if (right && bottom) {
|
|
return BorderlessWindowResizeEdge::BottomRight;
|
|
}
|
|
if (left) {
|
|
return BorderlessWindowResizeEdge::Left;
|
|
}
|
|
if (right) {
|
|
return BorderlessWindowResizeEdge::Right;
|
|
}
|
|
if (top) {
|
|
return BorderlessWindowResizeEdge::Top;
|
|
}
|
|
if (bottom) {
|
|
return BorderlessWindowResizeEdge::Bottom;
|
|
}
|
|
return BorderlessWindowResizeEdge::None;
|
|
}
|
|
|
|
LPCWSTR ResolveBorderlessWindowResizeCursor(BorderlessWindowResizeEdge edge) {
|
|
switch (edge) {
|
|
case BorderlessWindowResizeEdge::Left:
|
|
case BorderlessWindowResizeEdge::Right:
|
|
return IDC_SIZEWE;
|
|
case BorderlessWindowResizeEdge::Top:
|
|
case BorderlessWindowResizeEdge::Bottom:
|
|
return IDC_SIZENS;
|
|
case BorderlessWindowResizeEdge::TopLeft:
|
|
case BorderlessWindowResizeEdge::BottomRight:
|
|
return IDC_SIZENWSE;
|
|
case BorderlessWindowResizeEdge::TopRight:
|
|
case BorderlessWindowResizeEdge::BottomLeft:
|
|
return IDC_SIZENESW;
|
|
case BorderlessWindowResizeEdge::None:
|
|
default:
|
|
return IDC_ARROW;
|
|
}
|
|
}
|
|
|
|
RECT ComputeBorderlessWindowResizeRect(
|
|
const RECT& initialRect,
|
|
const POINT& initialScreenPoint,
|
|
const POINT& currentScreenPoint,
|
|
BorderlessWindowResizeEdge edge,
|
|
int minimumOuterWidth,
|
|
int minimumOuterHeight) {
|
|
RECT result = initialRect;
|
|
const LONG deltaX = currentScreenPoint.x - initialScreenPoint.x;
|
|
const LONG deltaY = currentScreenPoint.y - initialScreenPoint.y;
|
|
const int minimumWidth = ClampMinimum(minimumOuterWidth, 1);
|
|
const int minimumHeight = ClampMinimum(minimumOuterHeight, 1);
|
|
|
|
switch (edge) {
|
|
case BorderlessWindowResizeEdge::Left:
|
|
case BorderlessWindowResizeEdge::TopLeft:
|
|
case BorderlessWindowResizeEdge::BottomLeft:
|
|
result.left += deltaX;
|
|
if (result.right - result.left < minimumWidth) {
|
|
result.left = result.right - minimumWidth;
|
|
}
|
|
break;
|
|
case BorderlessWindowResizeEdge::None:
|
|
case BorderlessWindowResizeEdge::Top:
|
|
case BorderlessWindowResizeEdge::Bottom:
|
|
case BorderlessWindowResizeEdge::Right:
|
|
case BorderlessWindowResizeEdge::TopRight:
|
|
case BorderlessWindowResizeEdge::BottomRight:
|
|
break;
|
|
}
|
|
|
|
switch (edge) {
|
|
case BorderlessWindowResizeEdge::Right:
|
|
case BorderlessWindowResizeEdge::TopRight:
|
|
case BorderlessWindowResizeEdge::BottomRight:
|
|
result.right += deltaX;
|
|
if (result.right - result.left < minimumWidth) {
|
|
result.right = result.left + minimumWidth;
|
|
}
|
|
break;
|
|
case BorderlessWindowResizeEdge::None:
|
|
case BorderlessWindowResizeEdge::Left:
|
|
case BorderlessWindowResizeEdge::Top:
|
|
case BorderlessWindowResizeEdge::Bottom:
|
|
case BorderlessWindowResizeEdge::TopLeft:
|
|
case BorderlessWindowResizeEdge::BottomLeft:
|
|
break;
|
|
}
|
|
|
|
switch (edge) {
|
|
case BorderlessWindowResizeEdge::Top:
|
|
case BorderlessWindowResizeEdge::TopLeft:
|
|
case BorderlessWindowResizeEdge::TopRight:
|
|
result.top += deltaY;
|
|
if (result.bottom - result.top < minimumHeight) {
|
|
result.top = result.bottom - minimumHeight;
|
|
}
|
|
break;
|
|
case BorderlessWindowResizeEdge::None:
|
|
case BorderlessWindowResizeEdge::Left:
|
|
case BorderlessWindowResizeEdge::Right:
|
|
case BorderlessWindowResizeEdge::Bottom:
|
|
case BorderlessWindowResizeEdge::BottomLeft:
|
|
case BorderlessWindowResizeEdge::BottomRight:
|
|
break;
|
|
}
|
|
|
|
switch (edge) {
|
|
case BorderlessWindowResizeEdge::Bottom:
|
|
case BorderlessWindowResizeEdge::BottomLeft:
|
|
case BorderlessWindowResizeEdge::BottomRight:
|
|
result.bottom += deltaY;
|
|
if (result.bottom - result.top < minimumHeight) {
|
|
result.bottom = result.top + minimumHeight;
|
|
}
|
|
break;
|
|
case BorderlessWindowResizeEdge::None:
|
|
case BorderlessWindowResizeEdge::Left:
|
|
case BorderlessWindowResizeEdge::Top:
|
|
case BorderlessWindowResizeEdge::Right:
|
|
case BorderlessWindowResizeEdge::TopLeft:
|
|
case BorderlessWindowResizeEdge::TopRight:
|
|
break;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
} // namespace XCEngine::UI::Editor::Host
|