210 lines
5.7 KiB
C++
210 lines
5.7 KiB
C++
// Fill out your copyright notice in the Description page of Project Settings.
|
|
|
|
|
|
#include "SChildWindow.h"
|
|
|
|
#include "SCanvas.h"
|
|
#include "SConstraintCanvas.h"
|
|
#include "SlateOptMacros.h"
|
|
#include "SWindowTitleBar.h"
|
|
#include "WindowManager.h"
|
|
#include "Thread/MainThreadEventList.h"
|
|
#include "UI/Widget/IChildWindow.h"
|
|
|
|
DECLARE_THREAD_MESSAGE(FMainThreadEventList, OnWindowResized,
|
|
SChildWindow* Window;
|
|
FVector2f Size;
|
|
)
|
|
{
|
|
Args.Window->GetOnWindowResize().ExecuteIfBound(Args.Size);
|
|
}
|
|
|
|
BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION
|
|
|
|
void SChildWindow::Construct(const FArguments& InArgs, SConstraintCanvas::FSlot* InSlot)
|
|
{
|
|
Slot = InSlot;
|
|
Slot->SetAnchors(FAnchors(0.f, 0.f, 0.f, 0.f));
|
|
Slot->SetAlignment(FVector2D(0, 0));
|
|
OnClose = InArgs._OnClose;
|
|
OnWindowMove = InArgs._OnWindowMove;
|
|
OnWindowResize = InArgs._OnWindowResize;
|
|
BorderSize = InArgs._BorderSize;
|
|
ResizeHandleSize = InArgs._ResizeHandleSize;
|
|
IsSingletonWindow = InArgs._IsSingletonWindow;
|
|
Content = InArgs._Content;
|
|
|
|
ChildSlot
|
|
[
|
|
SNew(SBorder)
|
|
[
|
|
SNew(SVerticalBox)
|
|
+SVerticalBox::Slot()
|
|
.AutoHeight()
|
|
[
|
|
SNew(SBox)
|
|
.HeightOverride(GetTitleBarHeight())
|
|
[
|
|
SAssignNew(TitleBar, SChildWindowTitleBar)
|
|
.Title(InArgs._Title)
|
|
.OnClose_Raw(this, &SChildWindow::OnCloseClicked)
|
|
.OnWindowMoveDelta_Raw(this, &SChildWindow::MoveWindowDelta)
|
|
.OnMaximize(this, &SChildWindow::OnMaximize)
|
|
]
|
|
]
|
|
+SVerticalBox::Slot()
|
|
.FillHeight(1.f)
|
|
.Padding(BorderSize.X, BorderSize.Y, BorderSize.X, BorderSize.Y + ResizeHandleSize.Y)
|
|
[
|
|
Content->GetWidget()
|
|
]
|
|
]
|
|
];
|
|
}
|
|
|
|
FReply SChildWindow::OnMouseButtonDown(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent)
|
|
{
|
|
FWindowManager::Get().FrontChildWindow(SharedThis(this));
|
|
if (GetCursor() == EMouseCursor::ResizeSouthEast)
|
|
{
|
|
BeginResizePos = MouseEvent.GetScreenSpacePosition();
|
|
BeginResizeMargin = Slot->GetOffset();
|
|
IsOnResize = true;
|
|
return FReply::Handled().CaptureMouse(AsShared());
|
|
}
|
|
return FReply::Unhandled();
|
|
}
|
|
|
|
FReply SChildWindow::OnMouseButtonUp(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent)
|
|
{
|
|
TitleBar->OnMouseButtonUp(MyGeometry, MouseEvent);
|
|
if (IsOnResize)
|
|
{
|
|
IsOnResize = false;
|
|
return FReply::Handled().ReleaseMouseCapture();
|
|
}
|
|
return FReply::Unhandled();
|
|
}
|
|
|
|
FReply SChildWindow::OnMouseMove(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent)
|
|
{
|
|
if (TitleBar->IsMaximized())
|
|
return FReply::Unhandled();
|
|
|
|
if (IsOnResize)
|
|
{
|
|
const FVector2D Offset = (BeginResizePos - MouseEvent.GetScreenSpacePosition()) / MyGeometry.Scale;
|
|
|
|
FMargin Margin = BeginResizeMargin;
|
|
Margin.Right = BeginResizeMargin.Right - Offset.X;
|
|
Margin.Bottom = BeginResizeMargin.Bottom - Offset.Y;
|
|
|
|
Margin.Right = FMath::Max(Margin.Right, 50);
|
|
Margin.Bottom = FMath::Max(Margin.Bottom, GetTitleBarHeight() + ResizeHandleSize.Y);
|
|
const FVector2f& Size = Margin.GetDesiredSize2f();
|
|
// PUSH_THREAD_EVENT(OnWindowResized, this, Size);
|
|
OnWindowResize.ExecuteIfBound(Size);
|
|
Slot->SetOffset(Margin);
|
|
}
|
|
else
|
|
{
|
|
const FVector2D LocalMousePos = MyGeometry.AbsoluteToLocal(MouseEvent.GetScreenSpacePosition());
|
|
const FVector2D ResizeLU = MyGeometry.Size - ResizeHandleSize; // Resize handle left up
|
|
|
|
if (LocalMousePos.ComponentwiseAllGreaterThan(ResizeLU))
|
|
{
|
|
SetCursor(EMouseCursor::ResizeSouthEast);
|
|
}
|
|
else
|
|
{
|
|
SetCursor(EMouseCursor::Default);
|
|
}
|
|
}
|
|
|
|
return FReply::Unhandled();
|
|
}
|
|
|
|
void SChildWindow::MoveWindow(FVector2f Position)
|
|
{
|
|
Position = FVector2f::Max(Position, FVector2f::ZeroVector);
|
|
Position = FVector2f::Min(Position, GetDesiredSize());
|
|
|
|
FMargin Margin = Slot->GetOffset();
|
|
Margin.Left = Position.X;
|
|
Margin.Top = Position.Y;
|
|
Slot->SetOffset(Margin);
|
|
Position.Y += GetTitleBarHeight();
|
|
Position.X += BorderSize.X;
|
|
OnWindowMove.ExecuteIfBound(Position);
|
|
}
|
|
|
|
float SChildWindow::GetTitleBarHeight()
|
|
{
|
|
return 24;
|
|
}
|
|
|
|
void SChildWindow::MoveWindowDelta(FVector2f Delta)
|
|
{
|
|
FMargin Margin = Slot->GetOffset();
|
|
Margin.Left += Delta.X;
|
|
Margin.Top += Delta.Y;
|
|
|
|
const FVector2f& ParentSize = GetParentWidget()->GetTickSpaceGeometry().Size;
|
|
Margin.Left = FMath::Max(Margin.Left, 0);
|
|
Margin.Top = FMath::Max(Margin.Top, 0);
|
|
Margin.Left = FMath::Min(Margin.Left, ParentSize.X - 100);
|
|
Margin.Top = FMath::Min(Margin.Top, ParentSize.Y - 100);
|
|
|
|
Slot->SetOffset(Margin);
|
|
|
|
FVector2f WindowPos(Margin.Left, Margin.Top);
|
|
WindowPos.Y += GetTitleBarHeight();
|
|
WindowPos.X += BorderSize.X;
|
|
OnWindowMove.ExecuteIfBound(WindowPos);
|
|
}
|
|
|
|
void SChildWindow::ResizeWindow(FVector2f Size)
|
|
{
|
|
const float TitleBarHeight = GetTitleBarHeight();
|
|
FMargin Margin = Slot->GetOffset();
|
|
Margin.Right = Size.X + BorderSize.X * 2;
|
|
Margin.Bottom = Size.Y + TitleBarHeight + BorderSize.Y * 2;
|
|
Slot->SetOffset(Margin);
|
|
OnWindowResize.ExecuteIfBound(Size);
|
|
}
|
|
|
|
void SChildWindow::OnMaximize(bool bArg)
|
|
{
|
|
if (bArg)
|
|
{
|
|
LastMargin = Slot->GetOffset();
|
|
Slot->SetAnchors(FAnchors(0.f, 0.f, 1.f, 1.f));
|
|
Slot->SetOffset(FMargin(0, 0, 0, 0));
|
|
// PUSH_THREAD_EVENT(OnWindowResized, this, Slot->GetOwner()->GetOwner().GetTickSpaceGeometry().Size);
|
|
OnWindowResize.ExecuteIfBound(Slot->GetOwner()->GetOwner().GetTickSpaceGeometry().Size);
|
|
}
|
|
else
|
|
{
|
|
Slot->SetAnchors(FAnchors(0.f, 0.f, 0.f, 0.f));
|
|
Slot->SetOffset(LastMargin);
|
|
// PUSH_THREAD_EVENT(OnWindowResized, this, Slot->GetOwner()->GetOwner().GetTickSpaceGeometry().Size);
|
|
OnWindowResize.ExecuteIfBound(Slot->GetOwner()->GetOwner().GetTickSpaceGeometry().Size);
|
|
}
|
|
}
|
|
|
|
void SChildWindow::OnCloseClicked()
|
|
{
|
|
if (IsSingletonWindow)
|
|
{
|
|
SetVisibility(EVisibility::Collapsed);
|
|
}
|
|
else
|
|
{
|
|
if (const TSharedPtr<SConstraintCanvas> Parent = StaticCastSharedPtr<SConstraintCanvas>(GetParentWidget()))
|
|
Parent->RemoveSlot(AsShared());
|
|
}
|
|
OnClose.ExecuteIfBound();
|
|
}
|
|
|
|
END_SLATE_FUNCTION_BUILD_OPTIMIZATION
|