Ejemplo n.º 1
0
void UJavascriptEditorLibrary::OpenPopupWindow(UWidget* Widget, const FVector2D& PopupDesiredSize, const FText& HeadingText)
{
	// Create the contents of the popup
	TSharedRef<SWidget> ActualWidget = Widget->TakeWidget();

	// Wrap the picker widget in a multibox-style menu body
	FMenuBuilder MenuBuilder(/*BShouldCloseAfterSelection=*/ false, /*CommandList=*/ nullptr);
	MenuBuilder.BeginSection("OpenPopupWindow", HeadingText);
	MenuBuilder.AddWidget(ActualWidget, FText::GetEmpty(), /*bNoIndent=*/ true);
	MenuBuilder.EndSection();

	auto WindowContents = MenuBuilder.MakeWidget();

	// Determine where the pop-up should open
	TSharedPtr<SWindow> ParentWindow = FSlateApplication::Get().GetActiveTopLevelWindow();
	FVector2D WindowPosition = FSlateApplication::Get().GetCursorPos();
	if (!ParentWindow.IsValid())
	{
		return;
	}

	if (ParentWindow.IsValid())
	{
		FSlateRect ParentMonitorRect = ParentWindow->GetFullScreenInfo();
		const FVector2D MonitorCenter((ParentMonitorRect.Right + ParentMonitorRect.Left) * 0.5f, (ParentMonitorRect.Top + ParentMonitorRect.Bottom) * 0.5f);
		WindowPosition = MonitorCenter - PopupDesiredSize * 0.5f;

		// Open the pop-up
		FPopupTransitionEffect TransitionEffect(FPopupTransitionEffect::None);
		auto Menu = FSlateApplication::Get().PushMenu(ParentWindow.ToSharedRef(), FWidgetPath(), WindowContents, WindowPosition, TransitionEffect, /*bFocusImmediately=*/ true);
	}
}
Ejemplo n.º 2
0
TSharedPtr<SWindow> FGlobalEditorCommonCommands::OpenPopup(TSharedRef<SWidget> WindowContents, const FVector2D& PopupDesiredSize)
{
	// Determine where the pop-up should open
	TSharedPtr<SWindow> ParentWindow = FSlateApplication::Get().GetActiveTopLevelWindow();
	FVector2D WindowPosition = FSlateApplication::Get().GetCursorPos();
	if (!ParentWindow.IsValid())
	{
		TSharedPtr<SDockTab> LevelEditorTab = FModuleManager::Get().GetModuleChecked<FLevelEditorModule>("LevelEditor").GetLevelEditorTab();
		ParentWindow = LevelEditorTab->GetParentWindow();
		check(ParentWindow.IsValid());
	}

	if (ParentWindow.IsValid())
	{
		FSlateRect ParentMonitorRect = ParentWindow->GetFullScreenInfo();
		const FVector2D MonitorCenter((ParentMonitorRect.Right + ParentMonitorRect.Left) * 0.5f, (ParentMonitorRect.Top + ParentMonitorRect.Bottom) * 0.5f);
		WindowPosition = MonitorCenter - PopupDesiredSize * 0.5f;

		// Open the pop-up
		FPopupTransitionEffect TransitionEffect(FPopupTransitionEffect::None);
		TSharedRef<SWindow> PopupWindow = FSlateApplication::Get().PushMenu(ParentWindow.ToSharedRef(), WindowContents, WindowPosition, TransitionEffect, /*bFocusImmediately=*/ true);
		
		return PopupWindow;
	}

	return TSharedPtr<SWindow>();
}
Ejemplo 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);
			}
		}
	}
}
Ejemplo n.º 4
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();
			}
		}
	}
}