diff --git a/EyePaint/App.config b/EyePaint/App.config
index 4c3dbb8..a6e5dcc 100644
--- a/EyePaint/App.config
+++ b/EyePaint/App.config
@@ -2,7 +2,7 @@
-
+
@@ -26,7 +26,7 @@
10
- 30
+ 10
30
@@ -34,6 +34,24 @@
100
+
+ 10
+
+
+
+
+
+ Måla med ögonen
+
+
+ Målning med ögonen
+
+
+ En målning gjord med ögonen.
+
+
+
+
diff --git a/EyePaint/App.xaml b/EyePaint/App.xaml
index 32f40b3..0dc0936 100644
--- a/EyePaint/App.xaml
+++ b/EyePaint/App.xaml
@@ -1,40 +1,38 @@
+ Startup="onStartup"
+ ShutdownMode="OnExplicitShutdown">
+
+
+
+
+
+
+
-
-
+
+
-
+
-
-
-
+
+
+
+
+
+
+
-
-
+
+
-
+
-
-
+
+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-
+
-
+
-
+
-
+
+
+
+
+
+
diff --git a/EyePaint/App.xaml.cs b/EyePaint/App.xaml.cs
index f5ac38a..25f0ee0 100644
--- a/EyePaint/App.xaml.cs
+++ b/EyePaint/App.xaml.cs
@@ -1,11 +1,10 @@
using System;
using System.Collections.Generic;
-using System.ComponentModel;
using System.Linq;
using System.Net;
using System.Net.Mail;
-using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
+using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
@@ -18,110 +17,112 @@ namespace EyePaint
///
/// Globally XAML bindable properties
///
- /* TODO
- public class AppProperties : DependencyObject
+ public class GlobalProperties : DependencyObject
{
- public static DependencyProperty TrackingProperty = DependencyProperty.Register("Tracking", typeof(bool), typeof(AppProperties));
+ public static DependencyProperty TrackingProperty = DependencyProperty.Register("Tracking", typeof(bool), typeof(GlobalProperties));
public bool Tracking
{
get { return (bool)GetValue(TrackingProperty); }
set { SetValue(TrackingProperty, value); }
}
-
- public static DependencyProperty GazeProperty = DependencyProperty.Register("Gaze", typeof(Point), typeof(AppProperties));
- public Point Gaze
- {
- get { return (Point)GetValue(GazeProperty); }
- set { SetValue(GazeProperty, value); }
- }
- }*/
-
- public class TrackingChangedEventArgs
- {
- public bool Tracking { get; set; }
}
///
- /// Eye tracking logic
+ /// Eye tracking logic and gaze enabled UI elements.
///
public partial class App : Application
{
- //TODO public AppProperties AppProperties { get; set; }
IEyeTracker iet;
Size resolution;
List gazes;
Dictionary offsets;
TimeSpan? time;
- public event EventHandler TrackingChanged;
- public bool Tracking;
+ PaintWindow paintWindow;
+ ResultWindow resultWindow;
+ public GlobalProperties Globals { get; set; }
+ bool tracking;
+ public bool Resettable;
int notTracking;
[DllImport("User32.dll")]
static public extern bool SetCursorPos(int X, int Y);
///
- /// Connects to the eye tracker on application startup.
+ /// Connect to the eye tracker on application startup.
///
void onStartup(object s, StartupEventArgs e)
{
- gazes = new List();
- offsets = new Dictionary();
- //AppProperties = new AppProperties();
+ new SettingsWindow();
- try
- {
- Uri url = new EyeTrackerCoreLibrary().GetConnectedEyeTracker();
- iet = new EyeTracker(url);
- iet.EyeTrackerError += onEyeTrackerError;
- iet.GazeData += onGazeData;
- Task.Factory.StartNew(() => iet.RunEventLoop());
- iet.Connect();
- iet.StartTracking();
- Mouse.OverrideCursor = Cursors.None;
- }
- catch (EyeTrackerException)
- {
- MessageBox.Show("Kameran verkar ha gått sönder. Prova att starta om datorn.");
- Application.Current.Shutdown();
- }
- catch (NullReferenceException)
- {
- MessageBox.Show("Kameran verkar saknas. Säkerställ att den är inkopplad och prova att starta om datorn.");
- Application.Current.Shutdown();
- }
- finally
+ Globals = new GlobalProperties();
+ var connected = connect();
+ if (!connected)
{
- (MainWindow = new MainWindow()).Show();
- resolution = new Size(MainWindow.ActualWidth, MainWindow.ActualHeight);
+ SendErrorReport("(EyePaint) Startup Error", "The eye tracker could not be found. Ensure that the cable is connected, restart the computer, and try launching the application again.");
+ new ErrorWindow().ShowDialog();
}
}
///
- /// Handles error data from the eye tracker. The application will be halted, the user will see an error on the screen, and a notification email is sent to the museum's technical staff.
+ /// Connect to the eye tracker and start gaze tracking. Return true iff a successful connection has been established.
+ ///
+ bool connect()
+ {
+ int retry = 0;
+ while (++retry < EyePaint.Properties.Settings.Default.ConnectionAttempts) try
+ {
+ // Connect to eye tracker.
+ gazes = new List();
+ offsets = new Dictionary();
+ Uri url = new EyeTrackerCoreLibrary().GetConnectedEyeTracker();
+ iet = new EyeTracker(url);
+ iet.EyeTrackerError += onEyeTrackerError;
+ iet.GazeData += onGazeData;
+ Task.Factory.StartNew(() => iet.RunEventLoop());
+ iet.Connect();
+ iet.StartTracking();
+ Mouse.OverrideCursor = Cursors.None;
+
+ // Display image result on a secondary screen.
+ resultWindow = new ResultWindow();
+ if (System.Windows.Forms.SystemInformation.MonitorCount > 1)
+ {
+ var wa = System.Windows.Forms.Screen.AllScreens[1].WorkingArea;
+ resultWindow.WindowStartupLocation = WindowStartupLocation.CenterOwner;
+ resultWindow.Left = wa.Left;
+ resultWindow.Top = wa.Top;
+ resultWindow.Topmost = true;
+ resultWindow.Show();
+ }
+
+ // Open paint window.
+ paintWindow = new PaintWindow();
+ paintWindow.Loaded += (_, __) => resolution = new Size(paintWindow.ActualWidth, paintWindow.ActualHeight);
+ paintWindow.ContentRendered += (_, __) => resultWindow.SetImageSource(paintWindow.Raster.Source);
+ paintWindow.Show();
+ return true;
+ }
+ catch (Exception)
+ {
+ Thread.Sleep(1000);
+ }
+ return false;
+ }
+
+ ///
+ /// Handles error data from the eye tracker. The application will be halted and the user will see an error on the screen while the application attempts to reestablish a connection to the eye tracker. If a connection cannot be reestablished a notification email is sent to the admin email.
///
void onEyeTrackerError(object s, EyeTrackerErrorEventArgs e)
{
- new ErrorWindow();
- try
- {
- var message = new MailMessage(
- EyePaint.Properties.Settings.Default.AdminEmail,
- EyePaint.Properties.Settings.Default.AdminEmail,
- "Tekniskt problem med stationen Måla med ögonen",
- "Kameran verkar ha gått sönder. Prova att starta om datorn."
- );
- var client = new SmtpClient(EyePaint.Properties.Settings.Default.SmtpServer);
- client.Credentials = CredentialCache.DefaultNetworkCredentials;
- client.Send(message);
- }
- catch (Exception)
- {
- MessageBox.Show("Felmeddelande kunde ej skickas via epost. Kameran verkar ha gått sönder. Prova att starta om datorn.");
- }
+ var ew = new ErrorWindow();
+ ew.Show();
+ var reconnected = connect();
+ if (reconnected) ew.Close();
+ else SendErrorReport("(EyePaint) Error " + e.ErrorCode, "The eye tracker encountered an error. Error: " + e.Message + ". Try rebooting the system.");
}
///
- /// Handles data from the eye tracker.
+ /// Handles data from the eye tracker. Places the mouse cursor at the average gaze point so that WPF mouse events can be used throughout the application.
///
void onGazeData(object s, GazeDataEventArgs e)
{
@@ -130,11 +131,10 @@ void onGazeData(object s, GazeDataEventArgs e)
// Determine if the user is inactive or just blinking.
if (++notTracking > EyePaint.Properties.Settings.Default.Blink)
{
- //TODO Dispatcher.Invoke(() => { if (AppProperties.Tracking) AppProperties.Tracking = false; });
- if (Tracking)
+ if (tracking)
{
- Tracking = false;
- if (TrackingChanged != null) TrackingChanged(this, new TrackingChangedEventArgs { Tracking = Tracking });
+ tracking = false;
+ Dispatcher.Invoke(() => Globals.Tracking = tracking);
}
}
}
@@ -144,11 +144,10 @@ void onGazeData(object s, GazeDataEventArgs e)
if (notTracking > 0)
{
notTracking = 0;
- if (!Tracking)
+ if (!tracking)
{
- //TODO Dispatcher.Invoke(() => { if (AppProperties.Tracking) AppProperties.Tracking = true; });
- Tracking = true;
- if (TrackingChanged != null) TrackingChanged(this, new TrackingChangedEventArgs { Tracking = Tracking });
+ tracking = true;
+ Dispatcher.Invoke(() => Globals.Tracking = tracking);
}
}
@@ -169,18 +168,16 @@ void onGazeData(object s, GazeDataEventArgs e)
var distances = offsets.Select(kvp => (gazePoint - kvp.Key).Length);
var distancesRatios = distances.Select(d => d / distances.Sum());
foreach (var v in offsets.Values.Zip(distancesRatios, (o, d) => (1.0 - d) * o)) gazePoint += v;
- // Place the mouse cursor at the gaze point so mouse events can be used throughout the app.
- SetCursorPos((int)gazePoint.X, (int)gazePoint.Y);
- // Store the gaze point.
- //TODO Dispatcher.Invoke(() => AppProperties.Gaze = gazePoint);
+ // Place the mouse cursor at the gaze point so mouse events can be used throughout the application.
+ SetCursorPos((int)gazePoint.X, (int)gazePoint.Y);
}
}
///
- /// Gaze click event handler for gaze enabled buttons.
+ /// When a gaze button is stared at for long enough a click event is raised on each animation completion.
///
- void onGazeClick(object s, EventArgs e)
+ void onGazeButtonFocused(object s, EventArgs e)
{
var c = s as Clock;
@@ -190,7 +187,7 @@ void onGazeClick(object s, EventArgs e)
time = null;
// Find button.
- var activeWindow = Application.Current.Windows.OfType().Single(x => x.IsActive);
+ var activeWindow = Application.Current.Windows.OfType().Single(w => w.IsActive);
var focusedButton = FocusManager.GetFocusedElement(activeWindow) as Button;
// Store calibration offset.
@@ -208,27 +205,49 @@ void onGazeClick(object s, EventArgs e)
}
///
- /// Gaze inactivity event handler for gaze enabled windows.
+ /// When a gaze button is touched a button click event is raised.
///
- void onInactivity(object s, EventArgs e)
+ void onGazeButtonTouched(object s, EventArgs e)
{
- Reset();
+ (s as Button).RaiseEvent(new RoutedEventArgs(Button.ClickEvent)); //TODO Verify this works with an actual touch screen.
}
///
- /// Clear previous gaze data and restart the main window.
+ /// Attempt to send an error report via email to an application defined admin email. If email could not be sent the error message will be displayed in a message box instead.
+ ///
+ public void SendErrorReport(string subject, string body)
+ {
+ try
+ {
+ var m = new MailMessage(EyePaint.Properties.Settings.Default.AdminEmail, EyePaint.Properties.Settings.Default.AdminEmail, subject, body);
+ var c = new SmtpClient(EyePaint.Properties.Settings.Default.SmtpServer);
+ c.Credentials = CredentialCache.DefaultNetworkCredentials;
+ c.Send(m);
+ }
+ catch (Exception)
+ {
+ MessageBox.Show("Email could not be sent. Make sure the application is configured correctly. Email: " + subject + " - " + body);
+ }
+ }
+
+ ///
+ /// Clear previous gaze data if neccessary.
///
public void Reset()
{
- gazes.Clear();
- offsets.Clear();
- time = null;
- TrackingChanged = null;
- Tracking = false;
- notTracking = 0;
- var mw = new MainWindow();
- mw.ContentRendered += (s, e) => { MainWindow.Close(); MainWindow = mw; };
- mw.Show();
+ if (Resettable)
+ {
+ offsets.Clear();
+ time = null;
+ var oldPaintWindow = paintWindow;
+ paintWindow = new PaintWindow();
+ paintWindow.ContentRendered += (s, e) =>
+ {
+ oldPaintWindow.Close();
+ resultWindow.SetImageSource(paintWindow.Raster.Source);
+ };
+ paintWindow.Show();
+ }
}
}
}
diff --git a/EyePaint/CalibrationWindow.xaml b/EyePaint/CalibrationWindow.xaml
index 1b6aded..48bc89e 100644
--- a/EyePaint/CalibrationWindow.xaml
+++ b/EyePaint/CalibrationWindow.xaml
@@ -2,23 +2,16 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Style="{StaticResource GazeWindow}"
- Topmost="True"
- AllowsTransparency="True"
- Background="#AA000000">
-
-
-
-
-
-
-
-
-
+ Background="#AA000000"
+ AllowsTransparency="True">
-
diff --git a/EyePaint/DialogWindow.xaml.cs b/EyePaint/DialogWindow.xaml.cs
index 9e5cdc1..7c0b67d 100644
--- a/EyePaint/DialogWindow.xaml.cs
+++ b/EyePaint/DialogWindow.xaml.cs
@@ -1,4 +1,5 @@
using System;
+using System.ComponentModel;
using System.Windows;
namespace EyePaint
@@ -8,18 +9,13 @@ namespace EyePaint
///
public partial class DialogWindow : Window
{
- public DialogWindow()
+ public DialogWindow(Window owner)
{
InitializeComponent();
+ Owner = owner;
ShowDialog();
}
- void onContentVisible(object s, EventArgs e)
- {
- IsEnabled = ((App)Application.Current).Tracking;
- ((App)Application.Current).TrackingChanged += (_s, _e) => Dispatcher.Invoke(() => IsEnabled = _e.Tracking);
- }
-
void onConfirm(object s, EventArgs e)
{
DialogResult = true;
diff --git a/EyePaint/ErrorWindow.xaml b/EyePaint/ErrorWindow.xaml
index 44ff6fa..1e3879e 100644
--- a/EyePaint/ErrorWindow.xaml
+++ b/EyePaint/ErrorWindow.xaml
@@ -2,8 +2,8 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Style="{StaticResource GazeWindow}"
- Topmost="True"
- KeyDown="onKeyDown">
+ Background="Black"
+ Topmost="True">
diff --git a/EyePaint/ErrorWindow.xaml.cs b/EyePaint/ErrorWindow.xaml.cs
index ceb6359..9ff6d6e 100644
--- a/EyePaint/ErrorWindow.xaml.cs
+++ b/EyePaint/ErrorWindow.xaml.cs
@@ -11,15 +11,6 @@ public partial class ErrorWindow : Window
public ErrorWindow()
{
InitializeComponent();
- ShowDialog();
- }
-
- void onKeyDown(object s, KeyEventArgs e)
- {
- switch (e.Key)
- {
- case Key.Escape: Close(); break;
- }
}
}
}
diff --git a/EyePaint/EyePaint.csproj b/EyePaint/EyePaint.csproj
index 9115854..6104d04 100644
--- a/EyePaint/EyePaint.csproj
+++ b/EyePaint/EyePaint.csproj
@@ -15,7 +15,7 @@
4
false
- D:\
+ C:\Users\Carl\Desktop\EyePaint\
true
Disk
false
@@ -25,9 +25,10 @@
false
false
true
- 12
- 1.0.0.%2a
+ 2
+ 2.0.0.%2a
false
+ true
true
true
@@ -62,7 +63,13 @@
true
- true
+ false
+
+
+ LocalIntranet
+
+
+ Properties\app.manifest
@@ -73,6 +80,7 @@
+
@@ -97,15 +105,15 @@
CalibrationWindow.xaml
-
- CountdownWindow.xaml
-
DialogWindow.xaml
ErrorWindow.xaml
+
+ ResultWindow.xaml
+
SettingsWindow.xaml
@@ -113,10 +121,6 @@
Designer
MSBuild:Compile
-
- Designer
- MSBuild:Compile
-
Designer
MSBuild:Compile
@@ -125,7 +129,7 @@
Designer
MSBuild:Compile
-
+
MSBuild:Compile
Designer
@@ -133,10 +137,14 @@
App.xaml
Code
-
- MainWindow.xaml
+
+ PaintWindow.xaml
Code
+
+ Designer
+ MSBuild:Compile
+
Designer
MSBuild:Compile
@@ -164,6 +172,7 @@
+
SettingsSingleFileGenerator
Settings.Designer.cs
@@ -174,9 +183,9 @@
-
+
False
- Microsoft .NET Framework 4.5 %28x86 and x64%29
+ Microsoft .NET Framework 4.5.1 %28x86 and x64%29
true
@@ -199,6 +208,10 @@
+
+
+
+
-
+
-
+
-
-
-
-
+
+
+
+
-
-
+
+
-
-
+
+
-
-
-
-
+
+
+
+
-
+
-
+
diff --git a/EyePaint/Properties/Settings.Designer.cs b/EyePaint/Properties/Settings.Designer.cs
index 7abd926..bc37c67 100644
--- a/EyePaint/Properties/Settings.Designer.cs
+++ b/EyePaint/Properties/Settings.Designer.cs
@@ -1,7 +1,7 @@
//------------------------------------------------------------------------------
//
// This code was generated by a tool.
-// Runtime Version:4.0.30319.34014
+// Runtime Version:4.0.30319.18444
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
@@ -85,7 +85,7 @@ public int Spacing {
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
- [global::System.Configuration.DefaultSettingValueAttribute("30")]
+ [global::System.Configuration.DefaultSettingValueAttribute("10")]
public int Stability {
get {
return ((int)(this["Stability"]));
@@ -118,5 +118,88 @@ public int Inertia {
this["Inertia"] = value;
}
}
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("10")]
+ public int ConnectionAttempts {
+ get {
+ return ((int)(this["ConnectionAttempts"]));
+ }
+ set {
+ this["ConnectionAttempts"] = value;
+ }
+ }
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ public global::FlickrNet.OAuthAccessToken FlickrAccessToken {
+ get {
+ return ((global::FlickrNet.OAuthAccessToken)(this["FlickrAccessToken"]));
+ }
+ set {
+ this["FlickrAccessToken"] = value;
+ }
+ }
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("")]
+ public string FlickrVerificationCode {
+ get {
+ return ((string)(this["FlickrVerificationCode"]));
+ }
+ set {
+ this["FlickrVerificationCode"] = value;
+ }
+ }
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("Måla med ögonen")]
+ public string FlickrPhotoset {
+ get {
+ return ((string)(this["FlickrPhotoset"]));
+ }
+ set {
+ this["FlickrPhotoset"] = value;
+ }
+ }
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("Målning med ögonen")]
+ public string FlickrTitle {
+ get {
+ return ((string)(this["FlickrTitle"]));
+ }
+ set {
+ this["FlickrTitle"] = value;
+ }
+ }
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("En målning gjord med ögonen.")]
+ public string FlickrDescription {
+ get {
+ return ((string)(this["FlickrDescription"]));
+ }
+ set {
+ this["FlickrDescription"] = value;
+ }
+ }
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("")]
+ public string FlickrTags {
+ get {
+ return ((string)(this["FlickrTags"]));
+ }
+ set {
+ this["FlickrTags"] = value;
+ }
+ }
}
}
diff --git a/EyePaint/Properties/Settings.settings b/EyePaint/Properties/Settings.settings
index 42ca82c..7f5411a 100644
--- a/EyePaint/Properties/Settings.settings
+++ b/EyePaint/Properties/Settings.settings
@@ -18,7 +18,7 @@
10
- 30
+ 10
30
@@ -26,5 +26,26 @@
100
+
+ 10
+
+
+
+
+
+
+
+
+ Måla med ögonen
+
+
+ Målning med ögonen
+
+
+ En målning gjord med ögonen.
+
+
+
+
\ No newline at end of file
diff --git a/EyePaint/Properties/app.manifest b/EyePaint/Properties/app.manifest
new file mode 100644
index 0000000..9a0d40a
--- /dev/null
+++ b/EyePaint/Properties/app.manifest
@@ -0,0 +1,54 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/EyePaint/ResultWindow.xaml b/EyePaint/ResultWindow.xaml
new file mode 100644
index 0000000..c9b4d2d
--- /dev/null
+++ b/EyePaint/ResultWindow.xaml
@@ -0,0 +1,8 @@
+
+
+
+
+
diff --git a/EyePaint/ResultWindow.xaml.cs b/EyePaint/ResultWindow.xaml.cs
new file mode 100644
index 0000000..e70e357
--- /dev/null
+++ b/EyePaint/ResultWindow.xaml.cs
@@ -0,0 +1,20 @@
+using System.Windows;
+using System.Windows.Media;
+
+namespace EyePaint
+{
+ ///
+ /// Used to display the resulting drawing in its own window.
+ ///
+ public partial class ResultWindow : Window
+ {
+ public ResultWindow()
+ {
+ InitializeComponent();
+ }
+
+ public void SetImageSource(ImageSource imageSource) {
+ Result.Source = imageSource;
+ }
+ }
+}
diff --git a/EyePaint/SettingsWindow.xaml b/EyePaint/SettingsWindow.xaml
index edc9f14..814a264 100644
--- a/EyePaint/SettingsWindow.xaml
+++ b/EyePaint/SettingsWindow.xaml
@@ -1,26 +1,107 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ Style="{StaticResource GazeWindow}"
+ Cursor="Arrow"
+ ContentRendered="onContentRendered">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/EyePaint/SettingsWindow.xaml.cs b/EyePaint/SettingsWindow.xaml.cs
index ba39beb..635358d 100644
--- a/EyePaint/SettingsWindow.xaml.cs
+++ b/EyePaint/SettingsWindow.xaml.cs
@@ -1,4 +1,10 @@
-using System.Windows;
+using FlickrNet;
+using System;
+using System.Net;
+using System.Net.Mail;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Media.Animation;
namespace EyePaint
{
@@ -7,17 +13,87 @@ namespace EyePaint
///
public partial class SettingsWindow : Window
{
+ OAuthRequestToken request;
+
public SettingsWindow()
{
InitializeComponent();
DataContext = Properties.Settings.Default;
+ ShowDialog();
+ }
+
+ void onContentRendered(object s, EventArgs e)
+ {
+ (FindResource("CountdownAnimation") as Storyboard).Begin();
+ }
+
+ void onClose(object s, EventArgs e)
+ {
+ (FindResource("CountdownAnimation") as Storyboard).Stop();
+ Close();
+ }
+
+ void onShowSettingsButtonClick(object s, RoutedEventArgs e)
+ {
+ Countdown.Visibility = Visibility.Collapsed;
+ Settings.Visibility = Visibility.Visible;
+ (FindResource("CountdownAnimation") as Storyboard).Stop();
}
void onSaveButtonClick(object s, RoutedEventArgs e)
{
Properties.Settings.Default.Save();
- MessageBox.Show("Inställningarna har sparats.");
+ MessageBox.Show("Settings saved.");
Close();
}
+
+ void onGetVerificationCodeButtonClick(object s, RoutedEventArgs e)
+ {
+ var f = new Flickr(Properties.Settings.Default.FlickrKey, Properties.Settings.Default.FlickrSecret);
+ request = f.OAuthGetRequestToken("oob");
+ var url = f.OAuthCalculateAuthorizationUrl(request.Token, AuthLevel.Write);
+ System.Diagnostics.Process.Start(url);
+ }
+
+ void onStoreVerificationCodeButtonClick(object s, RoutedEventArgs e)
+ {
+ if (request == null) MessageBox.Show("Request a new verification code first.");
+ else
+ {
+ try
+ {
+ var f = new Flickr(Properties.Settings.Default.FlickrKey, Properties.Settings.Default.FlickrSecret);
+ Properties.Settings.Default.FlickrAccessToken = f.OAuthGetAccessToken(request, FlickrCode.Text);
+ Properties.Settings.Default.Save();
+ MessageBox.Show("Login complete.");
+ }
+ catch (FlickrApiException)
+ {
+ MessageBox.Show("Login failed.");
+ }
+ }
+ }
+
+ void onSendEmailButtonClick(object s, RoutedEventArgs e)
+ {
+ try
+ {
+ var m = new MailMessage(
+ EyePaint.Properties.Settings.Default.AdminEmail,
+ EyePaint.Properties.Settings.Default.AdminEmail,
+ "(EyePaint) Test Email",
+ ""
+ );
+ var c = new SmtpClient(EyePaint.Properties.Settings.Default.SmtpServer);
+ c.Credentials = CredentialCache.DefaultNetworkCredentials;
+ c.Send(m);
+ }
+ catch (Exception)
+ {
+ MessageBox.Show("Email not sent.");
+ return;
+ }
+ MessageBox.Show("Email sent.");
+ }
}
}
diff --git a/EyePaint/packages.config b/EyePaint/packages.config
index d9080e2..a6877c4 100644
--- a/EyePaint/packages.config
+++ b/EyePaint/packages.config
@@ -1,4 +1,4 @@
-
+
\ No newline at end of file
diff --git a/README.md b/README.md
index 86124d2..d7da4ea 100644
--- a/README.md
+++ b/README.md
@@ -1,12 +1,14 @@
#EyePaint
+## Om programmet
+EyePaint (sv: Måla med ögonen) är ett Windows program skrivet i .NET som tillåter användaren att måla på skärmen med ögonen, genom att använda en Tobii EyeX (eller REX) eye tracker kamera.
+
## Installationsinstruktioner
-1. Programmet kräver en Tobii REX eye tracker och dess tillhörande drivrutiner (http://developer.tobii.com/downloads/).
+1. Programmet kräver en Tobii EyeX eller REX eye tracker och dess tillhörande drivrutiner (http://developer.tobii.com/downloads/).
1. Installera EyeX ramverket och följ instruktionerna.
2. Genomför en grundkalibrering.
- 3. Stäng av både ögonindikatorn och ögonstyrningen i Tobiis kontrollpanel. Måla med ögonen programmet kommunicerar direkt med eye trackern istället.
-2. Hårdvaruknapparna ska kopplas enligt:
- 1. Målaknappen -> Vänstermusklick
- 2. Omstartsknappen -> Tangentbordsknappen 's'
-3. Programmet behöver konfigureras efter installationen. Starta programmet och tryck ESC. Fyll i korrekt information i fälten och spara. Konfigurationen behöver bara göras en gång per installation.
-4. Kom ihåg att stänga av Windows Update, skärmsläckare, sovlägen m.m. på operativsystemsnivå, samt se till att applikationen autostartar med Windows.
-5. Applikationen kräver en internetuppkoppling för bilduppladdningen samt felhanteringsrutinen som använder epost.
+ 3. Stäng av ögonindikatorn i Tobiis kontrollpanel.
+2. Hårdvaruknappen för målning måste skicka vänstermusklicksignaler.
+3. Datorskärmen bör ha touchstöd.
+4. Programmet kräver en internetuppkoppling.
+5. Vid uppstart behöver programmet konfigureras. Starta programmet och klicka in i inställningsmenyn. Fyll i fälten och spara. Konfigurationen behöver bara göras en gång per installation.
+6. Kom ihåg att konfigurera operativsystemet också, såsom att stänga av Windows Update, skärmsläckaren, sovlägen m.m, samt se till att applikationen autostartar med Windows.