Skip to content

Commit

Permalink
Theme WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
cwensley committed Nov 26, 2024
1 parent 7fe8980 commit 886dd61
Show file tree
Hide file tree
Showing 14 changed files with 302 additions and 16 deletions.
41 changes: 30 additions & 11 deletions src/Eto.Mac/Forms/ApplicationHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
using System.Runtime.CompilerServices;
namespace Eto.Mac.Forms
{
public class ApplicationHandler : WidgetHandler<NSApplication, Application, Application.ICallback>, Application.IHandler
public class ApplicationHandler : MacObject<NSApplication, Application, Application.ICallback>, Application.IHandler
{
bool attached;

Expand Down Expand Up @@ -115,7 +115,7 @@ static void restart_WillTerminate(object sender, EventArgs e)
var args = new string[]
{
"-c",
"open \"$1\"",
"open \"$1\"",
string.Empty,
NSBundle.MainBundle.BundlePath
};
Expand All @@ -129,7 +129,7 @@ public void Invoke(Action action)
else
Control.InvokeOnMainThread(action);
}

public void AsyncInvoke(Action action)
{
Control.BeginInvokeOnMainThread(action);
Expand All @@ -150,23 +150,23 @@ public void Restart()
Control.Delegate = oldDelegate;
}

static readonly IntPtr selNextEventMatchingMaskUntilDateInModeDequeue_Handle = Selector.GetHandle ("nextEventMatchingMask:untilDate:inMode:dequeue:");
static readonly IntPtr selSendEvent_Handle = Selector.GetHandle ("sendEvent:");
static readonly IntPtr selNextEventMatchingMaskUntilDateInModeDequeue_Handle = Selector.GetHandle("nextEventMatchingMask:untilDate:inMode:dequeue:");
static readonly IntPtr selSendEvent_Handle = Selector.GetHandle("sendEvent:");

public void RunIteration()
{
MacView.InMouseTrackingLoop = false;
// drain the event queue only for a short period of time so it doesn't lock up
var date = NSDate.FromTimeIntervalSinceNow(0.001);
for (;;)
for (; ; )
{
// dequeue the event
var evt = Control.NextEvent(NSEventMask.AnyEvent, date, NSRunLoopMode.Default, true);

// no event? cool, let's get out of here
if (evt == null)
break;

// dispatch the event
Control.SendEvent(evt);
}
Expand Down Expand Up @@ -196,7 +196,7 @@ public void Run()


EtoBundle.Init();

EtoFontManager.Install();

if (Control.Delegate == null)
Expand Down Expand Up @@ -227,7 +227,7 @@ public void Open(string url)

#if Mac64
delegate void UncaughtExceptionHandlerDelegate(IntPtr nsexceptionPtr);

[DllImport(Constants.FoundationLibrary)]
static extern void NSSetUncaughtExceptionHandler(UncaughtExceptionHandlerDelegate handler);

Expand Down Expand Up @@ -275,6 +275,12 @@ public override void AttachEvent(string id)
NSNotificationCenter.DefaultCenter.AddObserver(NSApplication.DidBecomeActiveNotification, SharedApplication_ActiveChanged);
NSNotificationCenter.DefaultCenter.AddObserver(NSApplication.DidResignActiveNotification, SharedApplication_ActiveChanged);
break;
case Application.CurrentThemeChangedEvent:
AddControlObserver(new NSString("effectiveAppearance"), e =>
{
Callback.OnThemeChanged(Widget, EventArgs.Empty);
});
break;
default:
base.AttachEvent(id);
break;
Expand Down Expand Up @@ -325,5 +331,18 @@ public void EnableFullScreen()
public Keys AlternateModifier => Keys.Alt;

public bool IsActive => NSApplication.SharedApplication.Active;

public Theme CurrentTheme
{
get
{
var appearance = NSApplication.SharedApplication.Appearance;
return new Theme(new ThemeHandler(appearance));
}
set
{
NSApplication.SharedApplication.Appearance = ThemeHandler.GetControl(value);
}
}
}
}
60 changes: 60 additions & 0 deletions src/Eto.Mac/Forms/ThemeHandler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Eto.Mac.Forms;

public class ThemeHandler : WidgetHandler<NSAppearance, Theme>, Theme.IHandler
{
public ThemeHandler(NSAppearance appearance)
{
Control = appearance;
}

public string Name
{
get
{
var name = Control?.Name.ToString() ?? Application.Instance.Localize(Widget, "System");
if (name.StartsWith("NSAppearanceName"))
return name.Substring("NSAppearanceName".Length);
return name;
}
}

public ThemeStyle Style => Control.Name.ToString().ToLowerInvariant().Contains("dark") ? ThemeStyle.Dark : ThemeStyle.Light;

public override bool Equals(object obj)
{
if (obj is ThemeHandler themeHandler)
{
if (Control == null && themeHandler.Control == null)
return true;
return Control.Equals(themeHandler.Control);
}
return base.Equals(obj);
}

public override int GetHashCode()
{
return Control?.GetHashCode() ?? 0;
}
}

public class ThemesHandler : Themes.IHandler
{
public Theme System => new Theme(new ThemeHandler(null));
public Theme Light => new Theme(new ThemeHandler(NSAppearance.GetAppearance(NSAppearance.NameAqua)));
public Theme Dark => new Theme(new ThemeHandler(NSAppearance.GetAppearance(NSAppearance.NameDarkAqua)));
public Theme None => System;

public IEnumerable<Theme> GetThemes()
{
yield return new Theme(new ThemeHandler(null));
yield return new Theme(new ThemeHandler(NSAppearance.GetAppearance(NSAppearance.NameAqua)));
yield return new Theme(new ThemeHandler(NSAppearance.GetAppearance(NSAppearance.NameDarkAqua)));
yield return new Theme(new ThemeHandler(NSAppearance.GetAppearance(NSAppearance.NameVibrantLight)));
yield return new Theme(new ThemeHandler(NSAppearance.GetAppearance(NSAppearance.NameVibrantDark)));
}
}
1 change: 1 addition & 0 deletions src/Eto.Mac/Platform.cs
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@ public static void AddTo(Eto.Platform p)
p.Add<DataFormats.IHandler>(() => new DataFormatsHandler());
p.Add<Taskbar.IHandler>(() => new TaskbarHandler());
p.Add<Window.IWindowHandler>(() => new WindowHandler());
p.Add<Themes.IHandler>(() => new ThemesHandler());

// IO
p.Add<SystemIcons.IHandler>(() => new SystemIconsHandler());
Expand Down
2 changes: 1 addition & 1 deletion src/Eto.Wpf/Eto.Wpf.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
<UseWPF>true</UseWPF>
<UseWindowsForms>true</UseWindowsForms>
<!-- Suppress warning NU1701: Package 'Extended.Wpf.Toolkit 3.2.0' was restored using '.NETFramework,Version=v4.6.1' instead of the project target framework '.NETCoreApp,Version=v3.0'. This package may not be fully compatible with your project. -->
<NoWarn>NU1701;MSB4011;$(NoWarn)</NoWarn>
<NoWarn>NU1701;MSB4011;WPF0001;$(NoWarn)</NoWarn>
</PropertyGroup>

<PropertyGroup>
Expand Down
22 changes: 22 additions & 0 deletions src/Eto.Wpf/Forms/ApplicationHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -235,13 +235,35 @@ public Keys AlternateModifier
get { return Keys.Alt; }
}

public Theme CurrentTheme
{
get
{
#if NET9_0_OR_GREATER
return new Theme(new ThemeHandler(Control.ThemeMode));
#else
return null;
#endif
}
set
{
#if NET9_0_OR_GREATER
Control.ThemeMode = ThemeHandler.GetControl(value);
#endif
}
}


public void Open(string url)
{
Process.Start(new ProcessStartInfo(url) { UseShellExecute = true });
}

public void Run()
{
#if NET9_0_OR_GREATER
// Control.ThemeMode = sw.ThemeMode.System;
#endif
Callback.OnInitialized(Widget, EventArgs.Empty);
if (!_attached)
{
Expand Down
50 changes: 50 additions & 0 deletions src/Eto.Wpf/Forms/ThemeHandler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Eto.Wpf.Forms;

#if NET9_0_OR_GREATER

public class ThemeHandler : WidgetHandler<sw.ThemeMode, Theme, Theme.ICallback>, Theme.IHandler
{
public ThemeHandler(sw.ThemeMode mode)
{
Control = mode;
}

public string Name => Control.ToString();

public ThemeStyle Style
{
get
{
if (Control == sw.ThemeMode.System)
return ThemeStyle.System;
if (Control == sw.ThemeMode.Light)
return ThemeStyle.Light;
if (Control == sw.ThemeMode.Dark)
return ThemeStyle.Dark;
return ThemeStyle.Light;
}
}
}

public class ThemesHandler : Themes.IHandler
{
public Theme Light => new Theme(new ThemeHandler(sw.ThemeMode.Light));
public Theme Dark => new Theme(new ThemeHandler(sw.ThemeMode.Dark));
public Theme System => new Theme(new ThemeHandler(sw.ThemeMode.System));
public Theme None => new Theme(new ThemeHandler(sw.ThemeMode.None));

public IEnumerable<Theme> GetThemes()
{
yield return new Theme(new ThemeHandler(sw.ThemeMode.System));
yield return new Theme(new ThemeHandler(sw.ThemeMode.Light));
yield return new Theme(new ThemeHandler(sw.ThemeMode.Dark));
yield return new Theme(new ThemeHandler(sw.ThemeMode.None));
}
}

#endif
3 changes: 3 additions & 0 deletions src/Eto.Wpf/Platform.cs
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,9 @@ public static void AddTo(Eto.Platform p)
p.Add<DataFormats.IHandler>(() => new DataFormatsHandler());
p.Add<Taskbar.IHandler>(() => new TaskbarHandler());
p.Add<Window.IWindowHandler>(() => new WindowHandler());
#if NET9_0_OR_GREATER
p.Add<Themes.IHandler>(() => new ThemesHandler());
#endif

// IO
p.Add<SystemIcons.IHandler>(() => new SystemIconsHandler());
Expand Down
2 changes: 1 addition & 1 deletion src/Eto.Wpf/themes/controls/DataGrid.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
</Style>

<Style TargetType="efc:EtoDataGrid">
<Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"/>
<!-- <Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"/>-->
</Style>

</ResourceDictionary>
2 changes: 1 addition & 1 deletion src/Eto.Wpf/themes/controls/Window.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
xmlns:local="clr-namespace:Xceed.Wpf.Toolkit;assembly=Xceed.Wpf.Toolkit">

<Style TargetType="ef:EtoWindowContent">
<Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
<!--<Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>-->
</Style>

</ResourceDictionary>
25 changes: 25 additions & 0 deletions src/Eto/Forms/Application.cs
Original file line number Diff line number Diff line change
Expand Up @@ -272,13 +272,30 @@ void HandleClosed(object sender, EventArgs e)
/// </summary>
/// <value>The name.</value>
public string Name { get; set; }

public Theme CurrentTheme
{
get => Handler.CurrentTheme;
set => Handler.CurrentTheme = value;
}

public const string CurrentThemeChangedEvent = "Application.CurrentThemeChanged";

public event EventHandler<EventArgs> CurrentThemeChanged
{
add { Properties.AddHandlerEvent(CurrentThemeChangedEvent, value); }
remove { Properties.RemoveEvent(CurrentThemeChangedEvent, value); }
}

protected virtual void OnCurrentThemeChanged(EventArgs e) => Properties.TriggerEvent(CurrentThemeChangedEvent, this, e);

static Application()
{
EventLookup.Register<Application>(c => c.OnTerminating(null), Application.TerminatingEvent);
EventLookup.Register<Application>(c => c.OnUnhandledException(null), Application.UnhandledExceptionEvent);
EventLookup.Register<Application>(c => c.OnNotificationActivated(null), Application.NotificationActivatedEvent);
EventLookup.Register<Application>(c => c.OnIsActiveChanged(null), Application.IsActiveChangedEvent);
EventLookup.Register<Application>(c => c.OnCurrentThemeChanged(null), Application.CurrentThemeChangedEvent);
}

/// <summary>
Expand Down Expand Up @@ -609,6 +626,7 @@ public string Localize(object source, string text)
/// Raises the IsActiveChanged event.
/// </summary>
void OnIsActiveChanged(Application wiget, EventArgs e);
void OnThemeChanged(Application wiget, EventArgs e);
}

/// <summary>
Expand Down Expand Up @@ -659,6 +677,12 @@ public void OnIsActiveChanged(Application widget, EventArgs e)
using (widget.Platform.Context)
widget.OnIsActiveChanged(e);
}

public void OnThemeChanged(Application widget, EventArgs e)
{
using (widget.Platform.Context)
widget.OnCurrentThemeChanged(e);
}
}

/// <summary>
Expand Down Expand Up @@ -767,5 +791,6 @@ public void OnIsActiveChanged(Application widget, EventArgs e)
/// Gets a value indicating that the application is currently the active application
/// </summary>
bool IsActive { get; }
Theme CurrentTheme { get; set; }
}
}
Loading

0 comments on commit 886dd61

Please sign in to comment.