Skip to content

Instantly share code, notes, and snippets.

@dvdsgl
Created January 2, 2011 04:38
Show Gist options
  • Save dvdsgl/762279 to your computer and use it in GitHub Desktop.
Save dvdsgl/762279 to your computer and use it in GitHub Desktop.
This is why MonoMac is hot
using System;
using System.Collections.Generic;
using MonoMac.Foundation;
using MonoMac.AppKit;
using MonoMac.ObjCRuntime;
using Cadenza;
namespace MySecretApp {
public class UserStateObserver {
public event EventHandler<UserStateEventArgs> UserStateChanged;
public UserState State {
get { return state; }
private set {
if (value != state)
UserStateChanged.Raise (this, new UserStateEventArgs (value));
state = value;
}
}
bool ScreenSaverIsOn;
UserState state;
List<NSTimer> Timers;
public UserStateObserver ()
{
state = UserState.Busy;
Timers = new List<NSTimer> ();
}
public void Start ()
{
TransitionTo (UserState.Idle, WheneverComputerSleeps);
TransitionTo (UserState.Busy, WheneverComputerWakes);
TransitionTo (UserState.Idle, WheneverScreenSaverBegins);
TransitionTo (UserState.Idle, Every (5.Minutes (), IfScreenSaverIsOn));
TransitionTo (UserState.Busy, WheneverScreenSaverEnds);
}
public void Stop ()
{
Timers.ForEach (timer => timer.Invalidate ());
}
void OnWorkspaceNotification (string notification, Action act)
{
var center = NSWorkspace.SharedWorkspace.NotificationCenter;
center.AddObserver (new NSString (notification), note => act ());
}
void OnDistributedNotification (string notification, Action act)
{
// TODO remove extraneous cast when API is typed correctly.
// TODO how do we remove an observer?
var center = NSDistributedNotificationCenter.DefaultCenter as NSDistributedNotificationCenter;
center.AddObserver (new NSString (notification), note => act ());
}
void TransitionTo (UserState state, Action<Action> whenever)
{
whenever (() => State = state);
}
/// <summary>
/// If foo is an Action<Action>, and bar is Action, then (Every (period, foo) (bar))
/// starts a timer which calls foo (bar) every period.
Action<Action> Every (TimeSpan period, Action<Action> act)
{
return transition => {
var timer = NSTimer.CreateRepeatingTimer (period, () => act (transition));
NSRunLoop.Current.AddTimer (timer, NSRunLoop.NSRunLoopCommonModes);
Timers.Add (timer);
};
}
void WheneverComputerSleeps (Action act)
{
OnWorkspaceNotification ("NSWorkspaceWillSleepNotification", act);
}
void WheneverComputerWakes (Action act)
{
OnWorkspaceNotification ("NSWorkspaceDidWakeNotification", act);
}
void WheneverScreenSaverBegins (Action act)
{
OnDistributedNotification ("com.apple.screensaver.didstart", () => {
ScreenSaverIsOn = true;
act ();
});
}
void IfScreenSaverIsOn (Action act)
{
if (ScreenSaverIsOn) act ();
}
void WheneverScreenSaverEnds (Action act)
{
OnDistributedNotification ("com.apple.screensaver.didstop", () => {
ScreenSaverIsOn = false;
act ();
});
}
}
}
@praeclarum
Copy link

Line 67: Do you want == instead of = ?

@dvdsgl
Copy link
Author

dvdsgl commented Jan 2, 2011

No, (() => State = state) is an Action that sets the state.

@praeclarum
Copy link

Oops, sorry for the mistake! Makes sense.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment