- Timestamp:
- 11/05/07 10:20:10 (17 years ago)
- Location:
- trunk/Cocoa/AntiRSI
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Cocoa/AntiRSI/AntiRSI.h
r333 r346 25 25 #define sLatestVersionURL @"http://web.sabi.net/nriley/software/AntiRSI-version.txt" 26 26 #define sURL @"http://web.sabi.net/nriley/software/#antirsi" 27 #define sVersion @"1.4njr 2"27 #define sVersion @"1.4njr3" 28 28 29 29 typedef enum _AntiRSIState { 30 31 32 30 s_normal = 0, 31 s_taking_micro_pause, 32 s_taking_work_break, 33 33 } AntiRSIState; 34 34 35 35 @interface AntiRSI : NSObject 36 36 { 37 38 39 40 41 42 37 // views to display current status in 38 IBOutlet AntiRSIView *view; 39 IBOutlet NSLevelIndicator *progress; 40 IBOutlet NSButton *postpone; 41 IBOutlet NSTextField *time; 42 IBOutlet NSTextField *next_break; 43 43 IBOutlet NSTextField *session_time; 44 44 IBOutlet NSTextField *status; 45 45 IBOutlet NSTextField *version; // XXX unused? 46 46 IBOutlet NSDatePicker *reset_session_time; 47 47 … … 50 50 IBOutlet NSMenuItem *session_time_item; 51 51 52 53 54 52 // dock icon image 53 NSImage* dock_image; 54 NSImage* original_dock_image; 55 55 CTBadge* dock_badge; 56 56 57 58 59 60 61 62 63 64 65 66 67 68 69 57 // window to display the views in 58 NSWindow *main_window; 59 60 // timer that ticks every second to update 61 NSTimer *mtimer; 62 63 // various timers 64 double micro_pause_t; 65 double work_break_t; 66 double micro_pause_taking_t; 67 double work_break_taking_t; 68 double work_break_taking_cached_t; 69 double work_break_taking_cached_date; 70 70 double session_t; 71 71 double date; 72 72 double reset_session_date; 73 73 74 75 76 77 78 79 80 81 82 83 84 85 86 74 // various timing lengths 75 int micro_pause_period; 76 int micro_pause_duration; 77 int work_break_period; 78 int work_break_duration; 79 80 double sample_interval; 81 82 // verious other options 83 bool lock_focus; 84 bool draw_dock_image; 85 bool draw_dock_badge; 86 bool draw_dock_image_q; 87 87 bool reset_session_timer_daily; 88 88 bool reset_session_timer_after; … … 90 90 int reset_session_timer_after_hours; 91 91 92 93 94 95 96 97 98 99 100 101 102 103 104 92 // various colors 93 NSColor* taking; 94 NSColor* elapsed; 95 NSColor* background; 96 NSColor* darkbackground; 97 98 // state we are in 99 AntiRSIState state; 100 101 // history filter 102 double h0; 103 double h1; 104 double h2; 105 105 } 106 106 … … 154 154 155 155 @end 156 157 158 -
trunk/Cocoa/AntiRSI/AntiRSI.m
r333 r346 34 34 NSCalendarDate *now = [NSCalendarDate calendarDate]; 35 35 NSCalendarDate *reset = 36 37 38 39 40 41 42 36 [NSCalendarDate dateWithYear:[now yearOfCommonEra] 37 month:[now monthOfYear] 38 day:[now dayOfMonth] 39 hour:[reset_session_timer_time hourOfDay] 40 minute:[reset_session_timer_time minuteOfHour] 41 second:0 42 timeZone:[NSTimeZone systemTimeZone]]; 43 43 if ([now compare:reset] != NSOrderedAscending) 44 44 reset = [reset dateByAddingYears:0 months:0 days:1 hours:0 minutes:0 seconds:0]; … … 49 49 - (void)setMicro_pause_duration:(float)f 50 50 { 51 52 53 54 55 51 micro_pause_duration = round(f); 52 if (s_taking_micro_pause == state) { 53 [progress setMaxValue:micro_pause_duration]; 54 [progress setDoubleValue:micro_pause_taking_t]; 55 } 56 56 } 57 57 … … 61 61 - (void)setWork_break_duration:(float)f 62 62 { 63 64 65 66 67 63 work_break_duration = 60 * round(f); 64 if (s_taking_work_break == state) { 65 [progress setMaxValue:work_break_duration / 60]; 66 [progress setDoubleValue:work_break_taking_t / 60 - 0.5]; 67 } 68 68 } 69 69 … … 82 82 - (void)installTimer:(double)interval 83 83 { 84 85 86 87 88 84 if (mtimer != nil) { 85 [mtimer invalidate]; 86 [mtimer autorelease]; 87 } 88 mtimer = [[NSTimer scheduledTimerWithTimeInterval:interval target:self selector:@selector(tick:) 89 89 userInfo:nil repeats:YES] retain]; 90 90 } … … 92 92 - (void)setSample_interval:(NSString *)s 93 93 { 94 95 96 97 98 99 100 94 sample_interval = 1; 95 if ([s isEqualToString:@"Super Smooth"]) sample_interval = 0.1; 96 if ([s isEqualToString:@"Smooth"]) sample_interval = 0.33; 97 if ([s isEqualToString:@"Normal"]) sample_interval = 1; 98 if ([s isEqualToString:@"Low"]) sample_interval = 2; 99 100 [self installTimer:sample_interval]; 101 101 } 102 102 103 103 - (void)setDraw_dock_image:(BOOL)b 104 104 { 105 106 107 108 109 110 105 draw_dock_image=b; 106 if (!b) { 107 [NSApp setApplicationIconImage:[NSImage imageNamed:@"AntiRSI"]]; 108 } else { 109 [self drawDockImage]; 110 } 111 111 } 112 112 113 113 - (void)setBackground:(NSColor *)c 114 114 { 115 116 117 118 119 120 121 122 123 124 115 [background autorelease]; 116 background=[c retain]; 117 118 // make new darkbackground color 119 float r,g,b,a; 120 [background getRed:&r green:&g blue:&b alpha:&a]; 121 [darkbackground autorelease]; 122 darkbackground=[[NSColor colorWithCalibratedRed:r*0.35 green:g*0.35 blue:b*0.35 alpha:a+0.2] retain]; 123 124 [self drawDockImage]; 125 125 } 126 126 127 127 - (void)setElapsed:(NSColor *)c 128 128 { 129 130 129 [elapsed autorelease]; 130 elapsed=[c retain]; 131 131 [dock_badge setBadgeColor:elapsed]; 132 132 badge_session_minutes = -1; 133 133 [self drawDockImage]; 134 134 } 135 135 136 136 - (void)setTaking:(NSColor *)c 137 137 { 138 139 140 138 [taking autorelease]; 139 taking=[c retain]; 140 [self drawDockImage]; 141 141 } 142 142 … … 145 145 - (void)resetTimers; 146 146 { 147 148 149 150 151 152 153 147 // set timers to 0 148 micro_pause_t = 0; 149 work_break_t = 0; 150 micro_pause_taking_t = 0; 151 work_break_taking_t = 0; 152 work_break_taking_cached_t = 0; 153 work_break_taking_cached_date = 0; 154 154 session_t = 0; 155 155 } … … 157 157 - (void)awakeFromNib 158 158 { 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 159 // want transparancy 160 [NSColor setIgnoresAlpha:NO]; 161 162 // initial colors 163 elapsed = [[NSColor colorWithCalibratedRed:0.3 green:0.3 blue:0.9 alpha:0.95] retain]; 164 taking = [[NSColor colorWithCalibratedRed:0.3 green:0.9 blue:0.3 alpha:0.90] retain]; 165 background = [NSColor colorWithCalibratedRed:0.9 green:0.9 blue:0.9 alpha:0.7]; 166 167 //initial values 168 micro_pause_period = 4*60; 169 micro_pause_duration = 13; 170 work_break_period = 50*60; 171 work_break_duration = 8*60; 172 sample_interval = 1; 173 174 // set current state 175 state = s_normal; 176 176 [self resetTimers]; 177 178 179 180 181 182 177 178 // initialize dock image 179 dock_image = [[NSImage alloc] initWithSize:NSMakeSize(128,128)]; 180 [dock_image setCacheMode:NSImageCacheNever]; 181 original_dock_image = [NSImage imageNamed:@"AntiRSI"]; 182 draw_dock_image_q = YES; 183 183 dock_badge = [[CTBadge systemBadge] retain]; 184 184 [dock_badge setBadgeColor:elapsed]; 185 186 187 188 189 190 191 192 193 194 195 196 197 185 186 // setup main window that will show either micropause or workbreak 187 main_window = [[NSWindow alloc] initWithContentRect:[view frame] 188 styleMask:NSBorderlessWindowMask 189 backing:NSBackingStoreBuffered defer:YES]; 190 [main_window setBackgroundColor:[NSColor clearColor]]; 191 [main_window setLevel:NSStatusWindowLevel]; 192 [main_window setAlphaValue:0.85]; 193 [main_window setOpaque:NO]; 194 [main_window setHasShadow:NO]; 195 [main_window setMovableByWindowBackground:YES]; 196 [main_window center]; 197 [main_window setContentView:view]; 198 198 NSTimeZone *utcZone = [NSTimeZone timeZoneForSecondsFromGMT:0]; 199 199 [reset_session_time setTimeZone:utcZone]; … … 201 201 NSFont *myriad = [NSFont fontWithName: @"Myriad" size: 40]; 202 202 if (myriad) [status setFont: myriad]; 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 203 204 // initialze history filter 205 h0 = 0; 206 h1 = 0; 207 h2 = 0; 208 209 // initialize ticks 210 date = [NSDate timeIntervalSinceReferenceDate]; 211 212 // set background now 213 [self setBackground:background]; 214 215 // create initial values 216 NSUserDefaultsController *dc = [NSUserDefaultsController sharedUserDefaultsController]; 217 NSMutableDictionary* initial = [NSMutableDictionary dictionaryWithObjectsAndKeys: 218 [NSNumber numberWithFloat:4], @"micro_pause_period", 219 [NSNumber numberWithFloat:13], @"micro_pause_duration", 220 [NSNumber numberWithFloat:50], @"work_break_period", 221 [NSNumber numberWithFloat:8], @"work_break_duration", 222 @"Smooth", @"sample_interval", 223 [NSNumber numberWithBool:YES], @"draw_dock_image", 224 [NSNumber numberWithBool:YES], @"draw_dock_badge", 225 [NSNumber numberWithBool:NO], @"lock_focus", 226 [NSNumber numberWithBool:NO], @"reset_session_timer_daily", 227 [NSNumber numberWithBool:NO], @"reset_session_timer_after", 228 [NSCalendarDate dateWithYear:2000 month:1 day:1 hour:6 minute:0 second:0 timeZone:utcZone], @"reset_session_timer_time", 229 [NSNumber numberWithInt:8], @"reset_session_timer_after_hours", 230 [NSArchiver archivedDataWithRootObject:elapsed], @"elapsed", 231 [NSArchiver archivedDataWithRootObject:taking], @"taking", 232 [NSArchiver archivedDataWithRootObject:background], @"background", 233 nil]; 234 234 [[NSUserDefaults standardUserDefaults] registerDefaults:initial]; 235 236 237 238 239 240 241 242 243 235 [dc setInitialValues:initial]; 236 237 // bind to defauls controller 238 [self bind:@"micro_pause_period" toObject:dc withKeyPath:@"values.micro_pause_period" options:nil]; 239 [self bind:@"micro_pause_duration" toObject:dc withKeyPath:@"values.micro_pause_duration" options:nil]; 240 [self bind:@"work_break_period" toObject:dc withKeyPath:@"values.work_break_period" options:nil]; 241 [self bind:@"work_break_duration" toObject:dc withKeyPath:@"values.work_break_duration" options:nil]; 242 [self bind:@"sample_interval" toObject:dc withKeyPath:@"values.sample_interval" options:nil]; 243 [self bind:@"draw_dock_image" toObject:dc withKeyPath:@"values.draw_dock_image" options:nil]; 244 244 [self bind:@"draw_dock_badge" toObject:dc withKeyPath:@"values.draw_dock_badge" options:nil]; 245 245 [self bind:@"lock_focus" toObject:dc withKeyPath:@"values.lock_focus" options:nil]; 246 246 [self bind:@"reset_session_timer_daily" toObject:dc withKeyPath:@"values.reset_session_timer_daily" options:nil]; 247 247 [self bind:@"reset_session_timer_after" toObject:dc withKeyPath:@"values.reset_session_timer_after" options:nil]; 248 248 [self bind:@"reset_session_timer_time" toObject:dc withKeyPath:@"values.reset_session_timer_time" options:nil]; 249 249 [self bind:@"reset_session_timer_after_hours" toObject:dc withKeyPath:@"values.reset_session_timer_after_hours" options:nil]; 250 251 252 253 254 255 256 257 258 259 260 261 262 250 NSDictionary* unarchive = [NSDictionary dictionaryWithObject:NSUnarchiveFromDataTransformerName forKey:@"NSValueTransformerName"]; 251 [self bind:@"elapsed" toObject:dc withKeyPath:@"values.elapsed" options:unarchive]; 252 [self bind:@"taking" toObject:dc withKeyPath:@"values.taking" options:unarchive]; 253 [self bind:@"background" toObject:dc withKeyPath:@"values.background" options:unarchive]; 254 255 // alert every binding 256 [dc revert:self]; 257 258 // start the timer 259 [self installTimer:sample_interval]; 260 261 // about dialog 262 [version setStringValue:[NSString stringWithFormat:@"Version %@", sVersion]]; 263 263 } 264 264 … … 266 266 - (void)tick:(NSTimer *)timer 267 267 { 268 269 270 271 272 268 // calculate time since last tick 269 NSTimeInterval new_date = [NSDate timeIntervalSinceReferenceDate]; 270 NSTimeInterval tick_time = new_date - date; 271 date = new_date; 272 273 273 if (reset_session_timer_daily && date >= reset_session_date) { 274 274 [self resetSession:nil]; … … 277 277 } 278 278 279 // check if we are still on track of normal time, otherwise we might have slept or something 280 if (tick_time > work_break_duration) { 281 // set timers to 0 282 micro_pause_t = 0; 283 work_break_t = 0; 284 micro_pause_taking_t = micro_pause_duration; 285 work_break_taking_t = work_break_duration; 286 if (s_normal != state) { 287 [self endBreak]; 288 } 289 // and do stuff on next tick 290 return; 279 // check if we are still on track of normal time, otherwise we might have slept or something 280 if (tick_time > work_break_duration) { 281 // set timers to 0 282 micro_pause_t = 0; 283 work_break_t = 0; 284 micro_pause_taking_t = micro_pause_duration; 285 work_break_taking_t = work_break_duration; 286 if (s_normal != state) { 287 [self endBreak]; 291 288 } 292 293 // just did a whole micropause beyond normal time294 if (tick_time > micro_pause_duration && s_taking_work_break != state) { 295 // set micro_pause timers to 0 296 micro_pause_t = 0; 297 micro_pause_taking_t = micro_pause_duration; 298 if (s_normal != state) {299 [self endBreak];300 }301 // and do stuff on next tick302 return;289 // and do stuff on next tick 290 return; 291 } 292 293 // just did a whole micropause beyond normal time 294 if (tick_time > micro_pause_duration && s_taking_work_break != state) { 295 // set micro_pause timers to 0 296 micro_pause_t = 0; 297 micro_pause_taking_t = micro_pause_duration; 298 if (s_normal != state) { 299 [self endBreak]; 303 300 } 304 305 // get idle time in seconds 306 CFTimeInterval idle_time = CGSSecondsSinceLastInputEvent(kCGAnyInputEventType); 301 // and do stuff on next tick 302 return; 303 } 304 305 // get idle time in seconds 306 CFTimeInterval idle_time = CGSSecondsSinceLastInputEvent(kCGAnyInputEventType); 307 307 // CFTimeInterval cgs_idle_time = idle_time; 308 308 // from other people's reverse engineering of this function, on MDD G4s this can return a large positive number when input is in progress … … 310 310 idle_time = 0; 311 311 } else if (CGEventSourceSecondsSinceLastEventType != NULL) { 312 312 CGEventType eventTypes[] = { kCGEventLeftMouseDown, kCGEventLeftMouseUp, kCGEventRightMouseDown, kCGEventRightMouseUp, kCGEventMouseMoved, kCGEventLeftMouseDragged, kCGEventRightMouseDragged, kCGEventKeyDown, kCGEventKeyUp, kCGEventFlagsChanged, kCGEventScrollWheel, kCGEventTabletPointer, kCGEventTabletProximity, kCGEventOtherMouseDown, kCGEventOtherMouseUp, kCGEventOtherMouseDragged, kCGEventNull }; 313 313 CFTimeInterval event_idle_time; 314 314 idle_time = DBL_MAX; … … 325 325 } 326 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 327 // calculate slack, this gives a sort of 3 history filtered idea. 328 BOOL slack = (h2 + h1 + h0 > 15); 329 330 // if new event comes in history bumps up 331 if (h0 >= idle_time || idle_time < sample_interval) { 332 h2 = h1; 333 h1 = h0; 334 } 335 h0 = idle_time; 336 337 switch (state) { 338 case s_normal: 339 // idle_time needs to be at least 0.3 * micro_pause_duration before kicking in 340 // but we cut the user some slack based on previous idle_times 341 if (idle_time <= micro_pause_duration * 0.3 && !slack) { 342 micro_pause_t += tick_time; 343 work_break_t += tick_time; 344 344 if (idle_time < 1) { 345 345 session_t += tick_time; 346 346 } 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 347 micro_pause_taking_t = 0; 348 if (work_break_taking_t > 0) { 349 work_break_taking_cached_t = work_break_taking_t; 350 work_break_taking_cached_date = date; 351 } 352 work_break_taking_t = 0; 353 } else if (micro_pause_t > 0) { 354 // oke, leaway is over, increase micro_pause_taking_t unless micro_pause is already over 355 //micro_pause_t stays put 356 work_break_t += tick_time; 357 micro_pause_taking_t += tick_time; 358 work_break_taking_t = 0; 359 } 360 361 // if micro_pause_taking_t is above micro_pause_duration, then micro pause is over, 362 // if still idleing workbreak_taking_t kicks in unless it is already over 363 if (micro_pause_taking_t >= micro_pause_duration && work_break_t > 0) { 364 work_break_taking_t += tick_time; 365 micro_pause_t = 0; 366 } 367 368 // if work_break_taking_t is above work_break_duration, then work break is over 369 if (work_break_taking_t >= work_break_duration) { 370 micro_pause_t = 0; 371 work_break_t = 0; 372 // micro_pause_taking_t stays put 373 // work_break_taking_t stays put 374 } 375 376 // if user needs to take a micro pause 377 if (micro_pause_t >= micro_pause_period) { 378 // anticipate next workbreak by not issuing this micro_pause ... 379 if (work_break_t > work_break_period - (micro_pause_period / 2)) { 380 work_break_t = work_break_period; 381 [self doWorkBreak]; 382 } else { 383 [self doMicroPause]; 384 } 385 } 386 387 // if user needs to take a work break 388 if (work_break_t >= work_break_period) { 389 // stop micro_pause stuff 390 micro_pause_t = 0; 391 micro_pause_taking_t = micro_pause_duration; 392 // and display window 393 [self doWorkBreak]; 394 } 395 break; 396 397 // taking a micro pause with window 398 case s_taking_micro_pause: 399 // continue updating timers 400 micro_pause_taking_t += tick_time; 401 work_break_t += tick_time; 402 403 // if we don't break, or interrupt the break, reset it 404 if (idle_time < 1 && !slack) { 405 micro_pause_taking_t = 0; 406 406 session_t += tick_time; 407 408 409 407 } 408 409 // update window 410 410 [self updateBreakWindowDuration:micro_pause_duration progress:micro_pause_taking_t 411 411 nextBreak:work_break_period - work_break_t]; 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 412 413 // check if we done enough 414 if (micro_pause_taking_t > micro_pause_duration) { 415 micro_pause_t = 0; 416 [self endBreak]; 417 } 418 419 // if workbreak must be run ... 420 if (work_break_t >= work_break_period) { 421 // stop micro_pause stuff 422 micro_pause_t = 0; 423 micro_pause_taking_t = micro_pause_duration; 424 // and display window 425 [self doWorkBreak]; 426 } else { 427 427 double slip = (micro_pause_duration - micro_pause_taking_t) - (int)(micro_pause_duration - micro_pause_taking_t); 428 428 [self installTimer: slip < 0.1 ? 1 : slip]; 429 429 } 430 431 432 433 434 435 436 437 430 break; 431 432 // taking a work break with window 433 case s_taking_work_break: 434 // increase work_break_taking_t 435 if (idle_time >= 2 || work_break_taking_t < 3) { 436 work_break_taking_t += tick_time; 437 } else if (idle_time < 1) { 438 438 session_t += tick_time; 439 439 } 440 441 440 441 // draw window 442 442 [self updateBreakWindowDuration:work_break_duration progress:work_break_taking_t 443 443 nextBreak:work_break_period + work_break_duration - work_break_taking_t]; 444 445 446 447 448 449 450 451 452 444 445 // and check if we done enough 446 if (work_break_taking_t > work_break_duration) { 447 micro_pause_t = 0; 448 micro_pause_taking_t = micro_pause_duration; 449 work_break_t = 0; 450 work_break_taking_t = work_break_duration; 451 [self endBreak]; 452 } else { 453 453 double slip = (work_break_duration - work_break_taking_t) - (int)(work_break_duration - work_break_taking_t); 454 454 [self installTimer: slip < 0.1 ? 1 : slip]; 455 455 } 456 457 458 459 460 456 break; 457 } 458 459 // draw dock image 460 if (draw_dock_image) [self drawDockImage]; 461 461 } 462 462 … … 471 471 - (void)drawDockImage 472 472 { 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 473 [dock_image lockFocus]; 474 475 // clear all 476 [[NSColor clearColor] set]; 477 NSRectFill(NSMakeRect(0,0,127,127)); 478 479 NSBezierPath* p; 480 float end; 481 482 //draw background circle 483 [darkbackground set]; 484 p =[NSBezierPath bezierPathWithOvalInRect:NSMakeRect(6,6,115,115)]; 485 [p setLineWidth:4]; 486 [p stroke]; 487 488 //fill 489 [background set]; 490 [[NSBezierPath bezierPathWithOvalInRect:NSMakeRect(8,8,111,111)] fill]; 491 492 //put dot in middle 493 [darkbackground set]; 494 [[NSBezierPath bezierPathWithOvalInRect:NSMakeRect(59,59,9,9)] fill]; 495 496 // reuse this one 497 p = [NSBezierPath bezierPath]; 498 499 // draw work_break 500 [elapsed set]; 501 end = 360 - (360.0 / work_break_period * work_break_t - 90); 502 if (end <= 90) end=90.1; 503 [p appendBezierPathWithArcWithCenter:NSMakePoint(63.5, 63.5) radius:40 startAngle:90 endAngle:end clockwise:YES]; 504 [p setLineWidth:22]; 505 [p stroke]; 506 507 // draw work break taking 508 [taking set]; 509 [p removeAllPoints]; 510 end = 360 - (360.0 / work_break_duration * work_break_taking_t - 90); 511 if (end <= 90) end=90.1; 512 [p appendBezierPathWithArcWithCenter:NSMakePoint(63.5, 63.5) radius:40 startAngle:90 endAngle:end clockwise:YES]; 513 [p setLineWidth:18]; 514 [p stroke]; 515 516 // draw micro pause 517 [elapsed set]; 518 [p removeAllPoints]; 519 end = 360 - (360.0 / micro_pause_period * micro_pause_t - 90); 520 if (end <= 90) end = 90.1; 521 [p appendBezierPathWithArcWithCenter:NSMakePoint(63.5, 63.5) radius:17 startAngle:90 endAngle:end clockwise:YES]; 522 [p setLineWidth:22]; 523 [p stroke]; 524 525 // draw micro pause taking 526 [taking set]; 527 [p removeAllPoints]; 528 end = 360 - (360.0 / micro_pause_duration * micro_pause_taking_t - 90); 529 if (end <= 90) end = 90.1; 530 [p appendBezierPathWithArcWithCenter:NSMakePoint(63.5, 63.5) radius:17 startAngle:90 endAngle:end clockwise:YES]; 531 [p setLineWidth:18]; 532 [p stroke]; 533 534 534 // draw session time 535 535 if (draw_dock_badge) { … … 544 544 } 545 545 546 547 548 549 546 [dock_image unlockFocus]; 547 548 // and set it in the dock check draw_dock_image one last time ... 549 if (draw_dock_image_q) [NSApp setApplicationIconImage:dock_image]; 550 550 } 551 551 … … 553 553 - (void)endBreak 554 554 { 555 556 557 558 555 [main_window orderOut:NULL]; 556 state = s_normal; 557 // reset time interval to user's choice 558 [self installTimer:sample_interval]; 559 559 } 560 560 … … 562 562 - (void)doMicroPause 563 563 { 564 565 566 567 564 micro_pause_taking_t = 0; 565 [status setStringValue:@"Micro Pause"]; 566 [progress setMaxValue:micro_pause_duration]; 567 [progress setDoubleValue:micro_pause_taking_t]; 568 568 [progress setWarningValue: 1]; 569 569 [progress setCriticalValue: micro_pause_duration]; 570 571 572 573 574 570 [postpone setHidden:YES]; 571 state = s_taking_micro_pause; 572 [self tick: nil]; 573 [main_window center]; 574 [main_window orderFrontRegardless]; 575 575 } 576 576 … … 578 578 - (void)doWorkBreak 579 579 { 580 581 582 583 584 585 586 587 588 580 work_break_taking_t = 0; 581 // incase you were already having an implicit work break and clicked the take work break now button 582 // not more then 20 seconds ago we took a natural break longer then 0.2 * normal work break duration 583 if (date - work_break_taking_cached_date < 20 && work_break_taking_cached_t > work_break_duration * 0.2) { 584 work_break_taking_t = work_break_taking_cached_t; 585 } 586 [status setStringValue:@"Work Break"]; 587 [progress setMaxValue:work_break_duration / 60]; 588 [progress setDoubleValue:work_break_taking_t / 60 - 0.5]; 589 589 [progress setWarningValue: 0]; 590 590 [progress setCriticalValue: 0.4]; 591 592 591 [postpone setHidden:NO]; 592 state = s_taking_work_break; 593 593 [self tick: nil]; 594 595 594 [main_window center]; 595 [main_window orderFrontRegardless]; 596 596 } 597 597 … … 599 599 { 600 600 return [NSString stringWithFormat:@"Session: %d:%02d:%02d", (int)session_t / 3600, 601 601 ((int)session_t / 60) % 60, lrint(session_t) % 60]; 602 602 } 603 603 … … 609 609 // time left 610 610 double timeLeft = duration - progress_t; 611 611 [time setStringValue:[NSString stringWithFormat:@"%d:%02d", (int)timeLeft / 60, lrint(timeLeft) % 60]]; 612 612 613 613 // cumulative typing time in this session (e.g. today) … … 615 615 616 616 // next break 617 618 619 620 621 622 minutes / 60, minutes % 60]];623 624 625 626 617 int minutes = round(nextBreak / 60.0); 618 619 // nice hours, minutes ... 620 if (minutes > 60) { 621 [next_break setStringValue:[NSString stringWithFormat:@"next break in %d:%02d hours", 622 minutes / 60, minutes % 60]]; 623 } else { 624 [next_break setStringValue:[NSString stringWithFormat:@"next break in %d minutes", minutes]]; 625 } 626 627 627 // if user likes to be interrupted 628 628 if (lock_focus) { … … 635 635 - (IBAction)gotoWebsite:(id)sender 636 636 { 637 637 [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:sURL]]; 638 638 } 639 639 … … 641 641 - (IBAction)checkForUpdate:(id)sender 642 642 { 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 643 NSString *latest_version = 644 [NSString stringWithContentsOfURL: [NSURL URLWithString:sLatestVersionURL]]; 645 646 if (latest_version == Nil) latest_version = @""; 647 latest_version = [latest_version stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; 648 649 if ([latest_version length] == 0) { 650 NSRunInformationalAlertPanel( 651 @"Unable to Determine", 652 @"Unable to determine the latest AntiRSI version number.", 653 @"Ok", nil, nil); 654 } else if ([latest_version compare:sVersion] == NSOrderedDescending) { 655 int r = NSRunInformationalAlertPanel( 656 @"New Version", 657 [NSString stringWithFormat:@"A new version (%@) of AntiRSI is available; would you like to go to the website now?", latest_version], 658 @"Goto Website", @"Cancel", nil); 659 if (r == NSOKButton) { 660 [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:sURL]]; 661 } 662 662 } else { 663 663 NSRunInformationalAlertPanel( 664 665 666 664 @"No Update Available", 665 @"This is the latest version of AntiRSI.", 666 @"OK", nil, nil); 667 667 } 668 668 } … … 671 671 - (IBAction)postpone:(id)sender 672 672 { 673 674 675 676 677 678 679 680 681 673 if (s_taking_work_break == state) { 674 micro_pause_t = 0; 675 micro_pause_taking_t = 0; 676 work_break_taking_t = 0; 677 work_break_taking_cached_t = 0; 678 work_break_t -= 10*60; // decrease with 10 minutes 679 if (work_break_t < 0) work_break_t = 0; 680 [self endBreak]; 681 } 682 682 } 683 683 684 684 - (IBAction)breakNow:(id)sender 685 685 { 686 686 [self doWorkBreak]; 687 687 } 688 688 … … 698 698 - (BOOL)validateMenuItem:(NSMenuItem *)anItem 699 699 { 700 701 702 703 704 705 700 if ([anItem action] == @selector(breakNow:) && state == s_normal) 701 return YES; 702 703 if ([anItem action] == @selector(postpone:) && state == s_taking_work_break) 704 return YES; 705 706 706 if ([anItem action] == @selector(resetSession:)) 707 708 709 710 711 707 return YES; 708 709 if ([anItem action] == @selector(gotoWebsite:)) 710 return YES; 711 712 712 if ([anItem action] == @selector(checkForUpdate:)) 713 714 715 713 return YES; 714 715 return NO; 716 716 } 717 717 … … 719 719 - (void)applicationWillTerminate:(NSNotification *)aNotification 720 720 { 721 722 723 724 725 726 727 728 729 730 731 732 733 721 // make sure timer doesn't tick once more ... 722 draw_dock_image_q = NO; 723 [mtimer invalidate]; 724 [mtimer autorelease]; 725 mtimer = nil; 726 [dock_image release]; 727 // stupid fix for icon beeing restored ... it is not my fault, 728 // the dock or NSImage or setApplicationIconImage seem to be caching or taking 729 // snapshot or something ... ! 730 [NSApp setApplicationIconImage:original_dock_image]; 731 [NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; 732 [NSApp setApplicationIconImage:original_dock_image]; 733 734 734 } 735 735 -
trunk/Cocoa/AntiRSI/AntiRSI.xcodeproj/project.pbxproj
r332 r346 48 48 464D9B780C6A760B005A0582 /* CTBadge_5.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = CTBadge_5.pdf; sourceTree = "<group>"; }; 49 49 4DB6164C061B59EA002EF355 /* AntiRSI.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = AntiRSI.h; sourceTree = "<group>"; }; 50 4DB6164D061B59EA002EF355 /* AntiRSI.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = AntiRSI.m; sourceTree = "<group>"; wrapsLines = 1; };50 4DB6164D061B59EA002EF355 /* AntiRSI.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = AntiRSI.m; sourceTree = "<group>"; tabWidth = 8; wrapsLines = 1; }; 51 51 4DF73F65061E136200B0D9C9 /* AntiRSIView.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = AntiRSIView.m; sourceTree = "<group>"; }; 52 52 4DF73F66061E136200B0D9C9 /* AntiRSIView.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = AntiRSIView.h; sourceTree = "<group>"; }; … … 221 221 isa = PBXProject; 222 222 buildConfigurationList = E1203B7F0894152100759E75 /* Build configuration list for PBXProject "AntiRSI" */; 223 compatibilityVersion = "Xcode 2.4"; 223 224 hasScannedForEncodings = 1; 224 225 knownRegions = ( … … 231 232 mainGroup = 29B97314FDCFA39411CA2CEA /* AntiRSI */; 232 233 projectDirPath = ""; 234 projectRoot = ""; 233 235 targets = ( 234 236 8D1107260486CEB800E47090 /* AntiRSI */, -
trunk/Cocoa/AntiRSI/AntiRSIView.m
r329 r346 35 35 float radius = 25.0; // correct value to duplicate Panther's App Switcher 36 36 NSBezierPath *bgPath = [NSBezierPath bezierPath]; 37 37 38 38 /* XXX from Casey Marshall's version; does it help with the hole-in-window problem? */ 39 39 [[NSColor clearColor] set]; 40 40 NSRectFill(bgRect); 41 41 /* XXX end */ -
trunk/Cocoa/AntiRSI/Info.plist
r332 r346 18 18 <string>ONNE</string> 19 19 <key>CFBundleVersion</key> 20 <string>1.4njr 2</string>20 <string>1.4njr3</string> 21 21 <key>NSMainNibFile</key> 22 22 <string>MainMenu</string>
Note:
See TracChangeset
for help on using the changeset viewer.