Skip to content

Commit

Permalink
fix(Studio): Remaining issues with WPF
Browse files Browse the repository at this point in the history
  • Loading branch information
psyGamer committed Sep 30, 2024
1 parent 9fcf165 commit d5d2071
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 30 deletions.
2 changes: 1 addition & 1 deletion Studio/CelesteStudio.WPF/CelesteStudio.WPF.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<OutputType>WinExe</OutputType>
<TargetFramework>net7.0-windows</TargetFramework>
<RuntimeIdentifiers>win-x64;win-arm64</RuntimeIdentifiers>

Expand Down
7 changes: 6 additions & 1 deletion Studio/CelesteStudio.WPF/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,12 @@ public static void Main(string[] args) {

UpdateTheme(Settings.Instance.Theme.DarkMode);

studio.PreLoad += (_, _) => ApplyTheme(studio, Settings.Instance.Theme.DarkMode);
var nativeWindow = ((IWpfWindow)studio.Handler).Control;
nativeWindow.SourceInitialized += (_, _) => {
ApplyTheme(studio, Settings.Instance.Theme.DarkMode);
studio.WPFHackEnabled = false;
};

Settings.ThemeChanged += () => ApplyTheme(studio, Settings.Instance.Theme.DarkMode);

app.Run(studio);
Expand Down
65 changes: 40 additions & 25 deletions Studio/CelesteStudio/Editing/GameInfoPanel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,15 @@ protected override void OnPaint(PaintEventArgs e) {

// The StackLayouts don't fit the exact content size on their own..
public int ActualWidth => EditingTemplate
? Math.Max(infoTemplateArea.Width, buttonsPanel.Width)
: Math.Max(Math.Max(frameInfo.Width, gameStatus.Width), subpixelIndicator.Visible ? subpixelIndicator.Width : 0);
? (int)(Math.Max(infoTemplateArea.GetPreferredSize().Width, buttonsPanel.GetPreferredSize().Width))
: (int)(Math.Max(Math.Max(frameInfo.GetPreferredSize().Width, gameStatus.GetPreferredSize().Width), subpixelIndicator.Visible ? subpixelIndicator.GetPreferredSize().Width : 0));
public int ActualHeight => EditingTemplate
? infoTemplateArea.Height + buttonsPanel.Height
: frameInfo.Height + gameStatus.Height + (subpixelIndicator.Visible ? subpixelIndicator.Height : 0);
? (int)(infoTemplateArea.GetPreferredSize().Height + buttonsPanel.GetPreferredSize().Height)
: (int)(frameInfo.GetPreferredSize().Height + gameStatus.GetPreferredSize().Height + (subpixelIndicator.Visible ? subpixelIndicator.GetPreferredSize().Height : 0));

public int AvailableWidth {
set => infoTemplateArea.Width = Math.Max(0, value);
}

private readonly Label frameInfo;
private readonly Label gameStatus;
Expand Down Expand Up @@ -135,17 +139,16 @@ public GameInfo() {
// Always have an empty line at the bottom
infoTemplateArea.Height = (int)((lineCount + 1) * infoTemplateArea.Font.LineHeight()) + 2;
};
SizeChanged += (_, _) => {
infoTemplateArea.Width = Math.Max(0, Width);
};

// Finish editing info template
doneButton.Click += (_, _) => {
CommunicationWrapper.SetCustomInfoTemplate(infoTemplateArea.Text);
Content = showPanel;
OnSizeChanged(EventArgs.Empty);
};
cancelButton.Click += (_, _) => {
Content = showPanel;
OnSizeChanged(EventArgs.Empty);
};

// Update displayed data
Expand All @@ -166,12 +169,18 @@ public GameInfo() {
};

// Manually forward size changes, since the StackLayouts won't do it..
frameInfo.SizeChanged += (_, _) => OnSizeChanged(EventArgs.Empty);
gameStatus.SizeChanged += (_, _) => OnSizeChanged(EventArgs.Empty);
subpixelIndicator.SizeChanged += (_, _) => OnSizeChanged(EventArgs.Empty);
frameInfo.SizeChanged += ForwardSize;
gameStatus.SizeChanged += ForwardSize;
subpixelIndicator.SizeChanged += ForwardSize;

infoTemplateArea.SizeChanged += ForwardSize;
buttonsPanel.SizeChanged += ForwardSize;

infoTemplateArea.SizeChanged += (_, _) => OnSizeChanged(EventArgs.Empty);
buttonsPanel.SizeChanged += (_, _) => OnSizeChanged(EventArgs.Empty);
void ForwardSize(object? _1, EventArgs _2) {
Content.Width = ActualWidth;
Content.Height = ActualHeight;
OnSizeChanged(EventArgs.Empty);
}

// React to settings changes
Settings.ThemeChanged += () => {
Expand Down Expand Up @@ -202,6 +211,7 @@ protected override void OnMouseDown(MouseEventArgs e) {
public void SetupContextMenu(GameInfoPopout? popout = null) {
var editCustomInfoItem = MenuEntry.Status_EditCustomInfoTemplate.ToAction(() => {
Content = editPanel;
OnSizeChanged(EventArgs.Empty);
infoTemplateArea.Text = CommunicationWrapper.GetCustomInfoTemplate();
});
editCustomInfoItem.Enabled = CommunicationWrapper.Connected;
Expand Down Expand Up @@ -273,14 +283,16 @@ private void RecalcGameStatus() {

public sealed class GameInfoPanel : Panel {
private sealed class PopoutButton : Drawable {
public const int ButtonSize = IconSize + BackgroundPadding * 2;

private const int IconSize = 20;
private const int BackgroundPadding = 5;

public Action? Click;
private void PerformClick() => Click?.Invoke();

public PopoutButton() {
Width = Height = IconSize + BackgroundPadding * 2;
Width = Height = ButtonSize;
}

protected override void OnPaint(PaintEventArgs e) {
Expand Down Expand Up @@ -335,24 +347,22 @@ public GameInfoPanel() {
forceClosePopout = false;
};

var popoutButton = new PopoutButton { Visible = true };
var popoutButton = new PopoutButton { Visible = false };
popoutButton.Click += () => {
Settings.Instance.GameInfo = GameInfoType.Popout;
Settings.OnChanged();
Settings.Save();
};

// Only show popout button while hovering Info HUD
MouseEnter += (_, _) => popoutButton.Visible = true;
MouseEnter += (_, _) => popoutButton.Visible = !gameInfo.EditingTemplate;
MouseLeave += (_, _) => popoutButton.Visible = false;

layout.Add(popoutButton, ClientSize.Width - Padding.Left - Padding.Right - popoutButton.Width, 0);
// WPF doesn't like it when the button starts out as invisible before being added for some reason
Shown += (_, _) => popoutButton.Visible = false;
layout.Add(popoutButton, ClientSize.Width - Padding.Left - Padding.Right - PopoutButton.ButtonSize, 0);

SizeChanged += (_, _) => {
if (popoutForm == null && gameInfo.EditingTemplate) {
gameInfo.Width = ClientSize.Width - Padding.Left - Padding.Right;
if (popoutForm == null) {
gameInfo.AvailableWidth = ClientSize.Width - Padding.Left - Padding.Right;
}
LimitSize();
};
Expand Down Expand Up @@ -382,15 +392,20 @@ void LimitSize() {
return;
}

// Causes the game-info to fit to the scrollable again
scrollable.Content = gameInfo;

// Limit height to certain percentage of entire the window
scrollable.Size = new Size(
Math.Max(0, ClientSize.Width - Padding.Left - Padding.Right),
Math.Min(gameInfo.ActualHeight + Padding.Top + Padding.Bottom, (int)(Studio.Instance.Height * Settings.Instance.MaxGameInfoHeight)) - Padding.Top - Padding.Bottom);
scrollable.ScrollSize = new Size(gameInfo.ActualWidth, gameInfo.ActualHeight);

// Don't show while editing template (cause overlap)
popoutButton.Visible = !gameInfo.EditingTemplate;

// Account for scroll bar
bool scrollBarVisible = gameInfo.Height > scrollable.Height;
layout.Move(popoutButton, ClientSize.Width - Padding.Left - Padding.Right - popoutButton.Width - (scrollBarVisible ? Studio.ScrollBarSize : 0), 0);
layout.Move(popoutButton, ClientSize.Width - Padding.Left - Padding.Right - PopoutButton.ButtonSize - (scrollBarVisible ? Studio.ScrollBarSize : 0), 0);
}

void UpdateGameInfoStatus() {
Expand Down Expand Up @@ -466,9 +481,7 @@ public GameInfoPopout() {
};

SizeChanged += (_, _) => {
if (gameInfo.EditingTemplate) {
gameInfo.Width = ClientSize.Width - Padding.Left - Padding.Right;
}
gameInfo.AvailableWidth = ClientSize.Width - Padding.Left - Padding.Right;
};

Load += (_, _) => Studio.Instance.WindowCreationCallback(this);
Expand All @@ -492,6 +505,8 @@ public GameInfoPopout() {
}
Location = lastLocation;
}

gameInfo.AvailableWidth = ClientSize.Width - Padding.Left - Padding.Right;
};
}

Expand Down
11 changes: 8 additions & 3 deletions Studio/CelesteStudio/Studio.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@ static Studio() {
/// Path to the Celeste install or null if it couldn't be found
public static string? CelesteDirectory { get; private set; }

/// For some **UNHOLY** reasons, not calling Content.UpdateLayout() in RecalculateLayout() places during startup causes themeing to crash.
/// _However_, while this hack is active, you can't resize the window, so this has to be disabled again as soon as possible...
/// I would personally like to burn WPF to the ground ._.
public bool WPFHackEnabled = true;

public readonly Editor Editor;
public readonly GameInfo GameInfo;

Expand Down Expand Up @@ -288,9 +293,9 @@ private void RecalculateLayout() {
Math.Max(0, ClientSize.Width),
Math.Max(0, ClientSize.Height - Math.Max(0, gameInfoPanel.Height)));

gameInfoPanel.UpdateLayout();
editorScrollable.UpdateLayout();
Content.UpdateLayout();
if (Eto.Platform.Instance.IsWpf && WPFHackEnabled) {
Content.UpdateLayout();
}
}

private void ApplySettings() {
Expand Down

0 comments on commit d5d2071

Please sign in to comment.