Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Show remaining time in status bar and more #6

Closed
wants to merge 15 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
Tomighty.xcodeproj/project.xcworkspace/
Tomighty.xcodeproj/xcuserdata/
**/*.xcodeproj/project.xcworkspace/xcshareddata/*.xccheckout
**/*.xcodeproj/project.xcworkspace/xcuserdata/
**/*.xcodeproj/xcuserdata/
src/.idea/*
6 changes: 4 additions & 2 deletions src/Tomighty.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
30FA9D9F17A586A0005D0A80 /* start-long-break.tiff in Resources */ = {isa = PBXBuildFile; fileRef = 30FA9D9B17A586A0005D0A80 /* start-long-break.tiff */; };
30FA9DA117A586A0005D0A80 /* start-short-break.tiff in Resources */ = {isa = PBXBuildFile; fileRef = 30FA9D9D17A586A0005D0A80 /* start-short-break.tiff */; };
30FA9DA417A587CB005D0A80 /* stop.tiff in Resources */ = {isa = PBXBuildFile; fileRef = 30FA9DA317A587CB005D0A80 /* stop.tiff */; };
9495F93918C7DCDD00AEACC2 /* pause.tiff in Resources */ = {isa = PBXBuildFile; fileRef = 9495F93818C7DCDD00AEACC2 /* pause.tiff */; };
/* End PBXBuildFile section */

/* Begin PBXFileReference section */
Expand Down Expand Up @@ -84,6 +85,7 @@
30FA9D9B17A586A0005D0A80 /* start-long-break.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = "start-long-break.tiff"; sourceTree = "<group>"; };
30FA9D9D17A586A0005D0A80 /* start-short-break.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = "start-short-break.tiff"; sourceTree = "<group>"; };
30FA9DA317A587CB005D0A80 /* stop.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = stop.tiff; sourceTree = "<group>"; };
9495F93818C7DCDD00AEACC2 /* pause.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = pause.tiff; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand All @@ -101,6 +103,7 @@
301ABCF317A5A53300F19F3C /* Icons */ = {
isa = PBXGroup;
children = (
9495F93818C7DCDD00AEACC2 /* pause.tiff */,
3055C8C618297D540040918A /* status-normal.tiff */,
301ABCF117A5999400F19F3C /* clock.tiff */,
301ABCED17A593AA00F19F3C /* start-pomodoro.tiff */,
Expand Down Expand Up @@ -274,6 +277,7 @@
30FA9DA417A587CB005D0A80 /* stop.tiff in Resources */,
301ABCE617A5910C00F19F3C /* status-long-break.tiff in Resources */,
301ABCE817A5910C00F19F3C /* status-short-break.tiff in Resources */,
9495F93918C7DCDD00AEACC2 /* pause.tiff in Resources */,
301ABCEF17A593AA00F19F3C /* start-pomodoro.tiff in Resources */,
3055C8C718297D540040918A /* status-normal.tiff in Resources */,
301ABCF017A593AA00F19F3C /* status-pomodoro.tiff in Resources */,
Expand Down Expand Up @@ -339,7 +343,6 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ARCHS = "$(ARCHS_STANDARD_64_BIT)";
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_OBJC_ARC = YES;
Expand Down Expand Up @@ -372,7 +375,6 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ARCHS = "$(ARCHS_STANDARD_64_BIT)";
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_OBJC_ARC = YES;
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

26 changes: 17 additions & 9 deletions src/Tomighty/AppDelegate.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,27 +6,35 @@
// Copyright (c) 2013 Célio Cidral Jr. All rights reserved.
//

#import <Cocoa/Cocoa.h>
#import <AppKit/AppKit.h>
#import "TimerListener.h"

@class StatusIcon;

@interface AppDelegate : NSObject <NSApplicationDelegate, TimerListener>

@property (weak) IBOutlet NSMenu *statusMenu;
@property (weak) IBOutlet NSMenuItem *remainingTimeMenuItem;
@property (weak) IBOutlet NSMenuItem *stopTimerMenuItem;
@property (weak) IBOutlet NSMenuItem *pomodoroCountMenuItem;
@property (weak) IBOutlet NSMenuItem *resetPomodoroCountMenuItem;
@property (weak) IBOutlet NSMenuItem *startPomodoroMenuItem;
@property (weak) IBOutlet NSMenuItem *startShortBreakMenuItem;
@property (weak) IBOutlet NSMenuItem *startLongBreakMenuItem;
@property(weak) IBOutlet NSMenu *statusMenu;
@property(weak) IBOutlet NSMenuItem *remainingTimeMenuItem;
@property(weak) IBOutlet NSMenuItem *stopTimerMenuItem;
@property(weak) IBOutlet NSMenuItem *pomodoroCountMenuItem;
@property(weak) IBOutlet NSMenuItem *resetPomodoroCountMenuItem;
@property(weak) IBOutlet NSMenuItem *startPomodoroMenuItem;
@property(weak) IBOutlet NSMenuItem *startShortBreakMenuItem;
@property(weak) IBOutlet NSMenuItem *startLongBreakMenuItem;
@property(weak) IBOutlet NSMenuItem *pauseTimerMenuItem;

- (IBAction)startPomodoro:(id)sender;

- (IBAction)startShortBreak:(id)sender;

- (IBAction)startLongBreak:(id)sender;

- (IBAction)stopTimer:(id)sender;

- (IBAction)resetPomodoroCount:(id)sender;

- (IBAction)showPreferences:(id)sender;

- (IBAction)pauseTimer:(id)sender;

@end
154 changes: 114 additions & 40 deletions src/Tomighty/AppDelegate.m
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,15 @@
#import "Timer.h"
#import "Tomighty.h"

@implementation AppDelegate
{
__strong Tomighty *tomighty;
__strong Timer *timer;
__strong StatusIcon *statusIcon;
__strong PreferencesWindowController *preferencesWindow;
__strong Sounds *sounds;
__strong TimerContext *pomodoroContext;
__strong TimerContext *shortBreakContext;
__strong TimerContext *longBreakContext;
@implementation AppDelegate {
Tomighty *tomighty;
Timer *timer;
StatusIcon *statusIcon;
PreferencesWindowController *preferencesWindow;
Sounds *sounds;
TimerContext *pomodoroContext;
TimerContext *shortBreakContext;
TimerContext *longBreakContext;
}

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
Expand All @@ -35,9 +34,41 @@ - (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
pomodoroContext = [[TimerContext alloc] initWithName:@"Pomodoro"];
shortBreakContext = [[TimerContext alloc] initWithName:@"Short break"];
longBreakContext = [[TimerContext alloc] initWithName:@"Long break"];

[self initMenuItemsIcons];
[self updateRemainingTime:0];
[self updateStatusBarTitle:0 justStarted:NO];
[self updateTimerControlMenuItems];

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(preferencesChangedNotification:) name:PREF_CHANGED_NOTIFICATION object:nil];
}

- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self name:PREF_CHANGED_NOTIFICATION object:nil];
}

- (void)preferencesChangedNotification:(NSNotification *)notif {
NSString *changedKey = notif.userInfo[PREF_CHANGED_NOTIFICATION_ITEM_KEY];

if ([changedKey isEqualToString:PREF_GENERAL_SHOW_IN_STATUS]) {
[self updateStatusBarTitle:timer.secondsRemaining justStarted:NO];
}

if ([changedKey isEqualToString:PREF_SOUND_TICTAC_POMODORO] || [changedKey isEqualToString:PREF_SOUND_TICTAC_BREAK]) {
[sounds stopTicTac];
if (timer.context && [self shouldPlayTicTacSound:timer.context]) {
[sounds startTicTac];
}
}

if ([changedKey isEqualToString:PREF_GENERAL_ALLOW_PAUSE]) {
[self updateTimerControlMenuItems];

// unpause in case we were paused and pause menu item is hidden
if (![Preferences boolForKey:PREF_GENERAL_ALLOW_PAUSE] && timer.paused) {
timer.paused = NO;
}
}
}

- (void)initMenuItemsIcons {
Expand All @@ -46,32 +77,33 @@ - (void)initMenuItemsIcons {
[self.startPomodoroMenuItem setImage:[ImageLoader loadIcon:@"start-pomodoro"]];
[self.startShortBreakMenuItem setImage:[ImageLoader loadIcon:@"start-short-break"]];
[self.startLongBreakMenuItem setImage:[ImageLoader loadIcon:@"start-long-break"]];
[self.pauseTimerMenuItem setImage:[ImageLoader loadIcon:@"pause"]];
}

- (IBAction)showPreferences:(id)sender {
if(!preferencesWindow) {
if (!preferencesWindow) {
preferencesWindow = [[PreferencesWindowController alloc] init];
}
[preferencesWindow showWindow:nil];
[NSApp activateIgnoringOtherApps:YES];
}

- (IBAction)startPomodoro:(id)sender {
int minutes = [Preferences intValue:PREF_TIME_POMODORO];
NSInteger minutes = [Preferences integerForKey:PREF_TIME_POMODORO];
[self activateTimerMenuItem:self.startPomodoroMenuItem];
[statusIcon pomodoro];
[timer start:minutes context:pomodoroContext];
}

- (IBAction)startShortBreak:(id)sender {
int minutes = [Preferences intValue:PREF_TIME_SHORT_BREAK];
NSInteger minutes = [Preferences integerForKey:PREF_TIME_SHORT_BREAK];
[self activateTimerMenuItem:self.startShortBreakMenuItem];
[statusIcon shortBreak];
[timer start:minutes context:shortBreakContext];
}

- (IBAction)startLongBreak:(id)sender {
int minutes = [Preferences intValue:PREF_TIME_LONG_BREAK];
NSInteger minutes = [Preferences integerForKey:PREF_TIME_LONG_BREAK];
[self activateTimerMenuItem:self.startLongBreakMenuItem];
[statusIcon longBreak];
[timer start:minutes context:longBreakContext];
Expand All @@ -87,19 +119,26 @@ - (void)stopTimer:(id)sender {
[timer stop];
}

- (void)timerTick:(int)secondsRemaining {
- (IBAction)pauseTimer:(id)sender {
timer.paused = !timer.paused;
[self updateTimerControlMenuItems];
}

- (void)timerTick:(NSInteger)secondsRemaining {
[self updateRemainingTime:secondsRemaining];
[self updateStatusBarTitle:secondsRemaining justStarted:NO];
}

- (void)timerStarted:(int)secondsRemaining context:(TimerContext *)context {
- (void)timerStarted:(NSInteger)secondsRemaining context:(TimerContext *)context {
[self updateRemainingTime:secondsRemaining];
[self.stopTimerMenuItem setEnabled:YES];

if([Preferences intValue:PREF_SOUND_TIMER_START]) {
[self updateStatusBarTitle:secondsRemaining justStarted:YES];
[self updateTimerControlMenuItems];

if ([Preferences boolForKey:PREF_SOUND_TIMER_START]) {
[sounds crank];
}
if([self shouldPlayTicTacSound:context]) {

if ([self shouldPlayTicTacSound:context]) {
[sounds startTicTac];
}
}
Expand All @@ -108,19 +147,20 @@ - (void)timerStopped {
[sounds stopTicTac];
[statusIcon normal];
[self updateRemainingTime:0];
[self.stopTimerMenuItem setEnabled:NO];
[self updateStatusBarTitle:0 justStarted:NO];
[self updateTimerControlMenuItems];
[self deactivateAllTimerMenuItems];
}

- (void)timerFinished:(TimerContext *)context {
if([Preferences intValue:PREF_SOUND_TIMER_FINISH]) {
if ([Preferences boolForKey:PREF_SOUND_TIMER_FINISH]) {
[sounds bell];
}
if(context == pomodoroContext) {

if (context == pomodoroContext) {
[self incrementPomodoroCount];
}

[self showFinishNotification:context];
}

Expand All @@ -141,21 +181,52 @@ - (void)deactivateAllTimerMenuItems {
[self activateTimerMenuItem:NSOffState menuItem:self.startLongBreakMenuItem];
}

- (void)updateRemainingTime:(int)secondsRemaining {
int minutes = secondsRemaining / 60;
int seconds = secondsRemaining % 60;

NSString *text = [NSString stringWithFormat:@"%02d:%02d", minutes, seconds];
- (void)updateTimerControlMenuItems {
[self.pauseTimerMenuItem setHidden:![Preferences boolForKey:PREF_GENERAL_ALLOW_PAUSE]];
self.pauseTimerMenuItem.title = timer.paused ? @"Resume" : @"Pause";
[self.stopTimerMenuItem setEnabled:timer.active];
[self.pauseTimerMenuItem setEnabled:timer.active];
}

- (void)updateRemainingTime:(NSInteger)secondsRemaining {
NSInteger minutes = secondsRemaining / 60;
NSInteger seconds = secondsRemaining % 60;

NSString *text = [NSString stringWithFormat:@"%02d:%02d", (int) minutes, (int) seconds];
[self.remainingTimeMenuItem setTitle:text];
}

- (void)updateStatusBarTitle:(NSInteger)secondsRemaining justStarted:(BOOL)justStarted {
// just started parameter is used to prevent flickering when starting timer and
// we should display remaining minutes in status bar (it would show 26min for the
// first second and then 25min otherwise)

NSInteger showInStatus = [Preferences integerForKey:PREF_GENERAL_SHOW_IN_STATUS];
if (showInStatus == 0) {
[statusIcon setTitle:@""];
} else if (secondsRemaining <= 0) {
[statusIcon setTitle:@" Stopped"];
} else {
NSInteger minutes = secondsRemaining / 60;
NSInteger seconds = secondsRemaining % 60;

NSString *text = nil;
if (showInStatus == 1) {
text = [NSString stringWithFormat:@" %d m", (int) minutes + (justStarted ? 0 : 1)];
} else if (showInStatus == 2) {
text = [NSString stringWithFormat:@" %02d:%02d", (int) minutes, (int) seconds];
}
[statusIcon setTitle:text];
}
}

- (void)updatePomodoroCountText {
int pomodoroCount = [tomighty pomodoroCount];
NSInteger pomodoroCount = tomighty.pomodoroCount;
BOOL isPlural = pomodoroCount > 1;
NSString *text =
pomodoroCount > 0 ?
[NSString stringWithFormat:@"%d full pomodoro%@", pomodoroCount, isPlural ? @"s" : @""]
: @"No full pomodoro yet";
pomodoroCount > 0 ?
[NSString stringWithFormat:@"%d full pomodoro%@", (int) pomodoroCount, isPlural ? @"s" : @""]
: @"No full pomodoro yet";
[self.pomodoroCountMenuItem setTitle:text];
}

Expand All @@ -166,17 +237,20 @@ - (void)incrementPomodoroCount {
}

- (BOOL)shouldPlayTicTacSound:(TimerContext *)context {
if(context == pomodoroContext)
return [Preferences intValue:PREF_SOUND_TICTAC_POMODORO];
if (context == pomodoroContext)
return [Preferences boolForKey:PREF_SOUND_TICTAC_POMODORO];
else
return [Preferences intValue:PREF_SOUND_TICTAC_BREAK];
return [Preferences boolForKey:PREF_SOUND_TICTAC_BREAK];
}

- (void)showFinishNotification:(TimerContext *)context {
NSString *title = [NSString stringWithFormat:@"%@ finished", [context name]];
NSUserNotification *notification = [[NSUserNotification alloc] init];
[notification setTitle:title];
[notification setSoundName:NSUserNotificationDefaultSoundName];

// play notification sound only when not playing our sound. Notification sound was not defined in 10.7 so test for this too.
if (![Preferences boolForKey:PREF_SOUND_TIMER_FINISH] && &NSUserNotificationDefaultSoundName)
[notification setSoundName:NSUserNotificationDefaultSoundName];
[[NSUserNotificationCenter defaultUserNotificationCenter] deliverNotification:notification];
}

Expand Down
5 changes: 3 additions & 2 deletions src/Tomighty/ImageLoader.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@

@interface ImageLoader : NSObject

+ (NSImage*) loadIcon:(NSString*)name;
+ (NSImage*) loadTiffImage:(NSString*)name withSize:(int)size;
+ (NSImage *)loadIcon:(NSString *)name;

+ (NSImage *)loadTiffImage:(NSString *)name withSize:(int)size;

@end
Loading