Index: trunk/Cocoa/AntiRSI/AntiRSI.m
===================================================================
--- trunk/Cocoa/AntiRSI/AntiRSI.m	(revision 331)
+++ trunk/Cocoa/AntiRSI/AntiRSI.m	(revision 332)
@@ -102,4 +102,5 @@
 	[elapsed autorelease];
 	elapsed=[c retain];
+    [dock_badge setBadgeColor:elapsed];
 	[self drawDockImage];
 }
@@ -152,4 +153,6 @@
 	original_dock_image = [NSImage imageNamed:@"AntiRSI"];
 	draw_dock_image_q = YES;
+    dock_badge = [[CTBadge systemBadge] retain];
+    [dock_badge setBadgeColor:elapsed];
 	
 	// setup main window that will show either micropause or workbreak
@@ -165,4 +168,6 @@
 	[main_window center];
 	[main_window setContentView:view];
+    NSTimeZone *utcZone = [NSTimeZone timeZoneForSecondsFromGMT:0];
+    [reset_session_time setTimeZone:utcZone];
     [progress setEnabled:NO];
     NSFont *myriad = [NSFont fontWithName: @"Myriad" size: 40];
@@ -181,19 +186,26 @@
 	
 	// create initial values
-	NSMutableDictionary* initial = [NSMutableDictionary dictionaryWithCapacity:10];
-	[initial setObject:[NSNumber numberWithFloat:4] forKey:@"micro_pause_period"];
-	[initial setObject:[NSNumber numberWithFloat:13] forKey:@"micro_pause_duration"];
-	[initial setObject:[NSNumber numberWithFloat:50] forKey:@"work_break_period"];
-	[initial setObject:[NSNumber numberWithFloat:8] forKey:@"work_break_duration"];
-	[initial setObject:@"Smooth" forKey:@"sample_interval"];
-	[initial setObject:[NSNumber numberWithBool:YES] forKey:@"draw_dock_image"];
-	[initial setObject:[NSNumber numberWithBool:NO] forKey:@"lock_focus"];
-	[initial setObject:[NSArchiver archivedDataWithRootObject:elapsed] forKey:@"elapsed"];
-	[initial setObject:[NSArchiver archivedDataWithRootObject:taking] forKey:@"taking"];
-	[initial setObject:[NSArchiver archivedDataWithRootObject:background] forKey:@"background"];
-	[[NSUserDefaultsController sharedUserDefaultsController] setInitialValues:initial];
+	NSUserDefaultsController *dc = [NSUserDefaultsController sharedUserDefaultsController];
+	NSMutableDictionary* initial = [NSMutableDictionary dictionaryWithObjectsAndKeys:
+        [NSNumber numberWithFloat:4], @"micro_pause_period",
+        [NSNumber numberWithFloat:13], @"micro_pause_duration",
+        [NSNumber numberWithFloat:50], @"work_break_period",
+        [NSNumber numberWithFloat:8], @"work_break_duration",
+        @"Smooth", @"sample_interval",
+        [NSNumber numberWithBool:YES], @"draw_dock_image",
+        [NSNumber numberWithBool:YES], @"draw_dock_badge",
+        [NSNumber numberWithBool:NO], @"lock_focus",
+        [NSNumber numberWithBool:NO], @"reset_session_timer_daily",
+        [NSNumber numberWithBool:NO], @"reset_session_timer_after",
+        [NSCalendarDate dateWithYear:2000 month:1 day:1 hour:6 minute:0 second:0 timeZone:utcZone], @"reset_session_timer_time",
+        [NSNumber numberWithInt:8], @"reset_session_timer_after_hours",
+        [NSArchiver archivedDataWithRootObject:elapsed], @"elapsed",
+        [NSArchiver archivedDataWithRootObject:taking], @"taking",
+        [NSArchiver archivedDataWithRootObject:background], @"background",
+        nil];
+    [[NSUserDefaults standardUserDefaults] registerDefaults:initial];
+	[dc setInitialValues:initial];
 
 	// bind to defauls controller
-	id dc = [NSUserDefaultsController sharedUserDefaultsController];
 	[self bind:@"micro_pause_period" toObject:dc withKeyPath:@"values.micro_pause_period" options:nil];
 	[self bind:@"micro_pause_duration" toObject:dc withKeyPath:@"values.micro_pause_duration" options:nil];
@@ -202,12 +214,20 @@
 	[self bind:@"sample_interval" toObject:dc withKeyPath:@"values.sample_interval" options:nil];
 	[self bind:@"draw_dock_image" toObject:dc withKeyPath:@"values.draw_dock_image" options:nil];
+    [self bind:@"draw_dock_badge" toObject:dc withKeyPath:@"values.draw_dock_badge" options:nil];
 	[self bind:@"lock_focus" toObject:dc withKeyPath:@"values.lock_focus" options:nil];
+    [self bind:@"reset_session_timer_daily" toObject:dc withKeyPath:@"values.reset_session_timer_daily" options:nil];
+    [self bind:@"reset_session_timer_after" toObject:dc withKeyPath:@"values.reset_session_timer_after" options:nil];
+    [self bind:@"reset_session_timer_time" toObject:dc withKeyPath:@"values.reset_session_timer_time" options:nil];
+    [self bind:@"reset_session_timer_after_hours" toObject:dc withKeyPath:@"values.reset_session_timer_after_hours" options:nil];
 	NSDictionary* unarchive = [NSDictionary dictionaryWithObject:NSUnarchiveFromDataTransformerName forKey:@"NSValueTransformerName"];
 	[self bind:@"elapsed" toObject:dc withKeyPath:@"values.elapsed" options:unarchive];
 	[self bind:@"taking" toObject:dc withKeyPath:@"values.taking" options:unarchive];
 	[self bind:@"background" toObject:dc withKeyPath:@"values.background" options:unarchive];
-
+    
+    // watch for timer changes
+    [dc addObserver:self forKeyPath:@"values.reset_session_timer_time" options:0 context:NULL];
+    
 	// alert every binding
-	[[NSUserDefaultsController sharedUserDefaultsController] revert:self];
+	[dc revert:self];
 
 	// start the timer
@@ -218,12 +238,42 @@
 }
 
+- (void)computeResetSessionDate;
+{
+    NSTimeZone *systemZone = [NSTimeZone systemTimeZone];
+    NSCalendarDate *today = [NSCalendarDate calendarDate];
+    NSCalendarDate *reset = [NSCalendarDate dateWithTimeIntervalSinceReferenceDate:[reset_session_timer_time timeIntervalSinceReferenceDate]];
+    [reset setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];
+    reset = [NSCalendarDate dateWithYear:[today yearOfCommonEra]
+                                   month:[today monthOfYear]
+                                     day:[today dayOfMonth]
+                                    hour:[reset hourOfDay]
+                                  minute:[reset minuteOfHour]
+                                  second:0
+                                timeZone:systemZone];
+    if ([today compare:reset] != NSOrderedAscending)
+        reset = [reset dateByAddingYears:0 months:0 days:1 hours:0 minutes:0 seconds:0];
+    reset_session_date = [reset timeIntervalSinceReferenceDate];
+}
+
+- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context;
+{
+    if ([keyPath isEqualToString:@"values.reset_session_timer_time"])
+        [self computeResetSessionDate];
+}
+
 // tick every second and update status
 - (void)tick:(NSTimer *)timer
 {
 	// calculate time since last tick
-	double new_date = [NSDate timeIntervalSinceReferenceDate];
-	double tick_time = new_date - date;
+	NSTimeInterval new_date = [NSDate timeIntervalSinceReferenceDate];
+	NSTimeInterval tick_time = new_date - date;
 	date = new_date;
-	
+
+    if (reset_session_timer_daily && date >= reset_session_date) {
+        [self resetSession:nil];
+        [self computeResetSessionDate];
+        return;
+    }
+    
 	// check if we are still on track of normal time, otherwise we might have slept or something
 	if (tick_time > work_break_duration) {
@@ -268,4 +318,9 @@
     }
     // NSLog(@"CGEventSource %.2f, CGS %.2f", idle_time, cgs_idle_time);
+    
+    if (reset_session_timer_after && idle_time > reset_session_timer_after_hours * 3600) {
+        [self resetSession:nil];
+        return;
+    }
     
 	// calculate slack, this gives a sort of 3 history filtered idea.
@@ -476,4 +531,17 @@
 	[p stroke];
 	
+    // draw session time
+    if (draw_dock_badge) {
+        static NSImage *badge = nil;
+        static int badge_session_minutes = -1;
+        int session_minutes = (int)session_t / 60;
+        if (badge_session_minutes != session_minutes) {
+            if (badge != nil) [badge release];
+            badge = [[dock_badge badgeOverlayImageForString: [NSString stringWithFormat:@"%d:%02d", session_minutes / 60, session_minutes % 60] insetX: 3 y: 3] retain];
+            badge_session_minutes = session_minutes;
+        }
+        [badge compositeToPoint:NSZeroPoint operation:NSCompositeSourceOver];
+    }
+    
 	[dock_image unlockFocus];
 
