Esempio n. 1
0
FVector2D SWeakWidget::ComputeDesiredSize() const
{	
	TSharedRef<SWidget> ReferencedWidget = WeakChild.GetWidget();

	if ( ReferencedWidget != SNullWidget::NullWidget && ReferencedWidget->GetVisibility() != EVisibility::Collapsed )
	{
		return ReferencedWidget->GetDesiredSize();
	}

	return FVector2D::ZeroVector;
}
void FGridSlotExtension::ExtendSelection(const TArray< FWidgetReference >& Selection, TArray< TSharedRef<FDesignerSurfaceElement> >& SurfaceElements)
{
	SelectionCache = Selection;

	TSharedRef<SButton> UpArrow = SNew(SButton)
		.Text(LOCTEXT("UpArrow", "↑"))
		.ContentPadding(FMargin(6, 2))
		.OnClicked(this, &FGridSlotExtension::HandleShiftRow, -1);

	TSharedRef<SButton> DownArrow = SNew(SButton)
		.Text(LOCTEXT("DownArrow", "↓"))
		.ContentPadding(FMargin(6, 2))
		.OnClicked(this, &FGridSlotExtension::HandleShiftRow, 1);

	TSharedRef<SButton> LeftArrow = SNew(SButton)
		.Text(LOCTEXT("LeftArrow", "←"))
		.ContentPadding(FMargin(2, 6))
		.OnClicked(this, &FGridSlotExtension::HandleShiftColumn, -1);

	TSharedRef<SButton> RightArrow = SNew(SButton)
		.Text(LOCTEXT("RightArrow", "→"))
		.ContentPadding(FMargin(2, 6))
		.OnClicked(this, &FGridSlotExtension::HandleShiftColumn, 1);

	UpArrow->SlatePrepass();
	DownArrow->SlatePrepass();
	LeftArrow->SlatePrepass();
	RightArrow->SlatePrepass();

	SurfaceElements.Add(MakeShareable(new FDesignerSurfaceElement(LeftArrow, EExtensionLayoutLocation::CenterLeft, FVector2D(-LeftArrow->GetDesiredSize().X, LeftArrow->GetDesiredSize().Y * -0.5f))));
	SurfaceElements.Add(MakeShareable(new FDesignerSurfaceElement(RightArrow, EExtensionLayoutLocation::CenterRight, FVector2D(0, RightArrow->GetDesiredSize().Y * -0.5f))));
	SurfaceElements.Add(MakeShareable(new FDesignerSurfaceElement(UpArrow, EExtensionLayoutLocation::TopCenter, FVector2D(UpArrow->GetDesiredSize().X * -0.5f, -UpArrow->GetDesiredSize().Y))));
	SurfaceElements.Add(MakeShareable(new FDesignerSurfaceElement(DownArrow, EExtensionLayoutLocation::BottomCenter, FVector2D(DownArrow->GetDesiredSize().X * -0.5f, 0))));
}
Esempio n. 3
0
/**
 * Open or close the popup
 *
 * @param InIsOpen  If true, open the popup. Otherwise close it.
 */
void SMenuAnchor::SetIsOpen( bool InIsOpen, const bool bFocusMenu )
{
	// Prevent redundant opens/closes
	if ( IsOpen() != InIsOpen )
	{
		if ( InIsOpen )
		{
			TSharedPtr< SWidget > MenuContentPtr = OnGetMenuContent.IsBound() ? OnGetMenuContent.Execute() : MenuContent;

			if ( MenuContentPtr.IsValid() )
			{
				// OPEN POPUP
				if ( OnMenuOpenChanged.IsBound() )
				{
					OnMenuOpenChanged.Execute(true);
				}

				// This can be called at any time so we use the push menu override that explicitly allows us to specify our parent

				// Figure out where the menu anchor is on the screen, so we can set the initial position of our pop-up window
				SlatePrepass();

				// NOTE: Careful, GeneratePathToWidget can be reentrant in that it can call visibility delegates and such
				FWidgetPath MyWidgetPath;
				FSlateApplication::Get().GeneratePathToWidgetChecked(AsShared(), MyWidgetPath);
				const FGeometry& MyGeometry = MyWidgetPath.Widgets.Last().Geometry;

				// @todo Slate: This code does not properly propagate the layout scale of the widget we are creating the popup for.
				// The popup instead has a scale of one, but a computed size as if the contents were scaled. This code should ideally
				// wrap the contents with an SFxWidget that applies the necessary layout scale. This is a very rare case right now.

				// Figure out how big the content widget is so we can set the window's initial size properly
				TSharedRef< SWidget > MenuContentRef = MenuContentPtr.ToSharedRef();
				MenuContentRef->SlatePrepass();

				// Combo-boxes never size down smaller than the widget that spawned them, but all
				// other pop-up menus are currently auto-sized
				const FVector2D DesiredContentSize = MenuContentRef->GetDesiredSize();  // @todo: This is ignoring any window border size!
				const EMenuPlacement PlacementMode = Placement.Get();

				const FVector2D NewPosition = MyGeometry.AbsolutePosition;
				FVector2D NewWindowSize = DesiredContentSize;
				const FVector2D SummonLocationSize = MyGeometry.Size;

				FPopupTransitionEffect TransitionEffect(FPopupTransitionEffect::None);
				if ( PlacementMode == MenuPlacement_ComboBox || PlacementMode == MenuPlacement_ComboBoxRight )
				{
					TransitionEffect = FPopupTransitionEffect(FPopupTransitionEffect::ComboButton);
					NewWindowSize = FVector2D(FMath::Max(MyGeometry.Size.X, DesiredContentSize.X), DesiredContentSize.Y);
				}
				else if ( PlacementMode == MenuPlacement_BelowAnchor )
				{
					TransitionEffect = FPopupTransitionEffect(FPopupTransitionEffect::TopMenu);
				}
				else if ( PlacementMode == MenuPlacement_MenuRight )
				{
					TransitionEffect = FPopupTransitionEffect(FPopupTransitionEffect::SubMenu);
				}

				if ( Method == CreateNewWindow )
				{
					// Open the pop-up
					TSharedRef<SWindow> PopupWindow = FSlateApplication::Get().PushMenu(AsShared(), MenuContentRef, NewPosition, TransitionEffect, bFocusMenu, false, NewWindowSize, SummonLocationSize);
					PopupWindow->SetRequestDestroyWindowOverride(FRequestDestroyWindowOverride::CreateSP(this, &SMenuAnchor::RequestClosePopupWindow));
					PopupWindowPtr = PopupWindow;
				}
				else
				{
					// We are re-using the current window instead of creating a new one.
					// The popup will be presented via an overlay service.
					ensure(Method == UseCurrentWindow);
					Children[1]
						[
							MenuContentRef
						];

					// We want to support dismissing the popup widget when the user clicks outside it.
					FSlateApplication::Get().GetPopupSupport().RegisterClickNotification(MenuContentRef, FOnClickedOutside::CreateSP(this, &SMenuAnchor::OnClickedOutsidePopup));
				}

				if ( bFocusMenu )
				{
					FSlateApplication::Get().SetKeyboardFocus(MenuContentRef, EKeyboardFocusCause::SetDirectly);
				}
			}
		}
		else
		{
			// CLOSE POPUP

			if (Method == CreateNewWindow)
			{
				// Close the Popup window.
				TSharedPtr<SWindow> PopupWindow = PopupWindowPtr.Pin();
				if ( PopupWindow.IsValid() )
				{
					// Request that the popup be closed.
					PopupWindow->RequestDestroyWindow();
				}
			}
			else
			{
				// Close the popup overlay
				ensure(Method==UseCurrentWindow);
				Children[1].DetachWidget();
			}

			if (OnMenuOpenChanged.IsBound())
			{
				OnMenuOpenChanged.Execute(false);
			}
		}
	}
}
void FVerticalSlotExtension::ExtendSelection(const TArray< FWidgetReference >& Selection, TArray< TSharedRef<FDesignerSurfaceElement> >& SurfaceElements)
{
	SelectionCache = Selection;

	TSharedRef<SButton> UpArrow = SNew(SButton)
		.Text(LOCTEXT("UpArrow", "↑"))
		.ContentPadding(FMargin(6, 2))
		.IsEnabled(this, &FVerticalSlotExtension::CanShift, -1)
		.OnClicked(this, &FVerticalSlotExtension::HandleShiftVertical, -1);

	TSharedRef<SButton> DownArrow = SNew(SButton)
		.Text(LOCTEXT("DownArrow", "↓"))
		.ContentPadding(FMargin(6, 2))
		.IsEnabled(this, &FVerticalSlotExtension::CanShift, 1)
		.OnClicked(this, &FVerticalSlotExtension::HandleShiftVertical, 1);

	UpArrow->SlatePrepass();
	DownArrow->SlatePrepass();

	SurfaceElements.Add(MakeShareable(new FDesignerSurfaceElement(UpArrow, EExtensionLayoutLocation::TopCenter, FVector2D(UpArrow->GetDesiredSize().X * -0.5f, -UpArrow->GetDesiredSize().Y))));
	SurfaceElements.Add(MakeShareable(new FDesignerSurfaceElement(DownArrow, EExtensionLayoutLocation::BottomCenter, FVector2D(DownArrow->GetDesiredSize().X * -0.5f, 0))));
}
Esempio n. 5
0
/**
 * Open or close the popup
 *
 * @param InIsOpen  If true, open the popup. Otherwise close it.
 */
void SMenuAnchor::SetIsOpen( bool InIsOpen, const bool bFocusMenu )
{
	// Prevent redundant opens/closes
	if ( IsOpen() != InIsOpen )
	{
		if ( InIsOpen )
		{
			if ( OnGetMenuContent.IsBound() )
			{
				SetMenuContent(OnGetMenuContent.Execute());
			}

			if ( MenuContent.IsValid() )
			{
				// OPEN POPUP
				if ( OnMenuOpenChanged.IsBound() )
				{
					OnMenuOpenChanged.Execute(true);
				}

				// Figure out where the menu anchor is on the screen, so we can set the initial position of our pop-up window
				// This can be called at any time so we use the push menu override that explicitly allows us to specify our parent
				// NOTE: Careful, GeneratePathToWidget can be reentrant in that it can call visibility delegates and such
				FWidgetPath MyWidgetPath;
				FSlateApplication::Get().GeneratePathToWidgetUnchecked(AsShared(), MyWidgetPath);
				if (MyWidgetPath.IsValid())
				{
					const FGeometry& MyGeometry = MyWidgetPath.Widgets.Last().Geometry;
					const float LayoutScaleMultiplier =  MyGeometry.GetAccumulatedLayoutTransform().GetScale();

					SlatePrepass(LayoutScaleMultiplier);

					// Figure out how big the content widget is so we can set the window's initial size properly
					TSharedRef< SWidget > MenuContentRef = MenuContent.ToSharedRef();
					MenuContentRef->SlatePrepass(LayoutScaleMultiplier);

					// Combo-boxes never size down smaller than the widget that spawned them, but all
					// other pop-up menus are currently auto-sized
					const FVector2D DesiredContentSize = MenuContentRef->GetDesiredSize();  // @todo slate: This is ignoring any window border size!
					const EMenuPlacement PlacementMode = Placement.Get();

					const FVector2D NewPosition = MyGeometry.AbsolutePosition;
					FVector2D NewWindowSize = DesiredContentSize;
					const FVector2D SummonLocationSize = MyGeometry.Size;

					FPopupTransitionEffect TransitionEffect( FPopupTransitionEffect::None );
					if ( PlacementMode == MenuPlacement_ComboBox || PlacementMode == MenuPlacement_ComboBoxRight )
					{
						TransitionEffect = FPopupTransitionEffect( FPopupTransitionEffect::ComboButton );
						NewWindowSize = FVector2D( FMath::Max( MyGeometry.Size.X, DesiredContentSize.X ), DesiredContentSize.Y );
					}
					else if ( PlacementMode == MenuPlacement_BelowAnchor )
					{
						TransitionEffect = FPopupTransitionEffect( FPopupTransitionEffect::TopMenu );
					}
					else if ( PlacementMode == MenuPlacement_MenuRight )
					{
						TransitionEffect = FPopupTransitionEffect( FPopupTransitionEffect::SubMenu );
					}

					MethodInUse = Method.IsSet()
						? Method.GetValue()
						: QueryPopupMethod(MyWidgetPath);

					if (MethodInUse == EPopupMethod::CreateNewWindow)
					{
						// Open the pop-up
						const bool bIsCollapsedByParent = false;	// don't auto-close child menus when the parent gets focus
						TSharedPtr<IMenu> NewMenu = FSlateApplication::Get().PushMenu(AsShared(), MyWidgetPath, MenuContentRef, NewPosition, TransitionEffect, bFocusMenu, SummonLocationSize, MethodInUse, bIsCollapsedByParent);

						PopupMenuPtr = NewMenu;
						check(NewMenu.IsValid() && NewMenu->GetOwnedWindow().IsValid());
						NewMenu->GetOnMenuDismissed().AddSP(this, &SMenuAnchor::OnMenuClosed);
						PopupWindowPtr = NewMenu->GetOwnedWindow();
					}
					else
					{
						// We are re-using the current window instead of creating a new one.
						// The popup will be presented via an overlay service.
						ensure(MethodInUse == EPopupMethod::UseCurrentWindow);
						TSharedRef<SWindow> PopupWindow = MyWidgetPath.GetWindow();
						PopupWindowPtr = PopupWindow;

						if (bFocusMenu)
						{
							FSlateApplication::Get().ReleaseMouseCapture();
						}

						TSharedRef<SMenuAnchor> SharedThis = StaticCastSharedRef<SMenuAnchor>(AsShared());

						const bool bIsCollapsedByParent = false;	// don't auto-close child menus when the parent gets focus
						TSharedPtr<IMenu> NewMenu = FSlateApplication::Get().PushHostedMenu(
							SharedThis, MyWidgetPath, SharedThis, MenuContentRef, WrappedContent, TransitionEffect, bIsCollapsedByParent);

						PopupMenuPtr = NewMenu;
						check(NewMenu.IsValid());
						check(NewMenu->GetParentWindow().ToSharedRef() == PopupWindow);
						check(WrappedContent.IsValid());

						Children[1]
						[
							WrappedContent.ToSharedRef()
						];

						if (bFocusMenu)
						{
							FSlateApplication::Get().SetKeyboardFocus(MenuContentRef, EFocusCause::SetDirectly);
						}
					}
				}
			}
		}
		else
		{
			// CLOSE POPUP
			if (PopupMenuPtr.IsValid())
			{
				PopupMenuPtr.Pin()->Dismiss();
			}
			else
			{
				PopupWindowPtr.Reset();
				MethodInUse.Reset();
			}
		}
	}
}
void FHorizontalSlotExtension::ExtendSelection(const TArray< FWidgetReference >& Selection, TArray< TSharedRef<FDesignerSurfaceElement> >& SurfaceElements)
{
    SelectionCache = Selection;

    TSharedRef<SButton> LeftArrow = SNew(SButton)
                                    .Text(LOCTEXT("LeftArrow", "←"))
                                    .ContentPadding(FMargin(2, 6))
                                    .IsEnabled(this, &FHorizontalSlotExtension::CanShift, -1)
                                    .OnClicked(this, &FHorizontalSlotExtension::HandleShift, -1);

    TSharedRef<SButton> RightArrow = SNew(SButton)
                                     .Text(LOCTEXT("RightArrow", "→"))
                                     .ContentPadding(FMargin(2, 6))
                                     .IsEnabled(this, &FHorizontalSlotExtension::CanShift, 1)
                                     .OnClicked(this, &FHorizontalSlotExtension::HandleShift, 1);

    LeftArrow->SlatePrepass();
    RightArrow->SlatePrepass();

    SurfaceElements.Add(MakeShareable(new FDesignerSurfaceElement(LeftArrow, EExtensionLayoutLocation::CenterLeft, FVector2D(-LeftArrow->GetDesiredSize().X, LeftArrow->GetDesiredSize().Y * -0.5f))));
    SurfaceElements.Add(MakeShareable(new FDesignerSurfaceElement(RightArrow, EExtensionLayoutLocation::CenterRight, FVector2D(0, RightArrow->GetDesiredSize().Y * -0.5f))));
}