Native Mac OS X OtaClock replica
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

MainWindow.m 7.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. //
  2. // MainWindow.m
  3. // OtaClock
  4. //
  5. // Created by Thomas Buck on 16.08.15.
  6. // Copyright (c) 2015 xythobuz. All rights reserved.
  7. //
  8. #import "MainView.h"
  9. #import "MainWindow.h"
  10. #define RESIZE_START 1
  11. #define RESIZE_END 5
  12. #define RESIZE_STEP 1
  13. #define CONFIG_START_SCALE @"window_scale"
  14. #define CONFIG_KEEP_POSITION @"keep_position"
  15. #define CONFIG_KEEP_ON_TOP @"keep_on_top"
  16. #define MOUSE_CENTER_X 337
  17. #define MOUSE_CENTER_Y 237
  18. #define EYE_BLINK 0
  19. #define EYE_TOP_RIGHT 4
  20. #define EYE_TOP_LEFT 2
  21. #define EYE_BOTTOM_RIGHT 3
  22. #define EYE_BOTTOM_LEFT 1
  23. @interface MainWindow ()
  24. @property (assign) NSSize defaultSize;
  25. @property (assign) NSInteger startScale;
  26. @property (assign) NSInteger lastEyeState;
  27. @property (weak) IBOutlet MainView *mainView;
  28. @property (weak) IBOutlet NSMenuItem *lockPositionItem;
  29. @property (weak) IBOutlet NSMenuItem *keepOnTopItem;
  30. @property (weak) IBOutlet NSMenuItem *changeSize1;
  31. @property (weak) IBOutlet NSMenuItem *changeSize2;
  32. @property (weak) IBOutlet NSMenuItem *changeSize3;
  33. @property (weak) IBOutlet NSMenuItem *changeSize4;
  34. @property (weak) IBOutlet NSMenuItem *changeSize5;
  35. @end
  36. @implementation MainWindow
  37. @synthesize dragStart;
  38. @synthesize keepPosition;
  39. @synthesize defaultSize;
  40. @synthesize startScale;
  41. @synthesize lastEyeState;
  42. - (id)initWithContentRect:(NSRect)contentRect
  43. styleMask:(NSUInteger)aStyle
  44. backing:(NSBackingStoreType)bufferingType
  45. defer:(BOOL)flag {
  46. self = [super initWithContentRect:contentRect styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:NO];
  47. if (self != nil) {
  48. [self setAlphaValue:1.0];
  49. [self setOpaque:NO];
  50. lastEyeState = EYE_TOP_LEFT;
  51. NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
  52. // load and see if window should be kept on top
  53. if ([defaults objectForKey:CONFIG_KEEP_ON_TOP] != nil) {
  54. if ([defaults boolForKey:CONFIG_KEEP_ON_TOP]) {
  55. [self setLevel:NSFloatingWindowLevel];
  56. }
  57. }
  58. // load and see if window pos should be fixed
  59. if ([defaults objectForKey:CONFIG_KEEP_POSITION] == nil) {
  60. keepPosition = NO;
  61. } else {
  62. keepPosition = [defaults boolForKey:CONFIG_KEEP_POSITION];
  63. }
  64. // load window scale factor
  65. if ([defaults objectForKey:CONFIG_START_SCALE] == nil) {
  66. startScale = 1;
  67. } else {
  68. startScale = [defaults integerForKey:CONFIG_START_SCALE];
  69. }
  70. }
  71. [self setAcceptsMouseMovedEvents:YES];
  72. [NSEvent addGlobalMonitorForEventsMatchingMask:NSMouseMovedMask handler:^(NSEvent *mouseMovedEvent) { [self mouseMoved:mouseMovedEvent]; }];
  73. return self;
  74. }
  75. - (void)setDefaultBackgroundSize:(NSSize)size {
  76. defaultSize = size;
  77. NSRect frame = [self frame];
  78. frame.size = defaultSize;
  79. frame.size.width *= startScale;
  80. frame.size.height *= startScale;
  81. // We need to do all initialization of view state in here, because they are not ready in init
  82. if (keepPosition) [self.lockPositionItem setState:NSOnState];
  83. if ([self level] == NSFloatingWindowLevel) [self.keepOnTopItem setState:NSOnState];
  84. if (startScale == 1) [self.changeSize1 setState:NSOnState];
  85. if (startScale == 2) [self.changeSize2 setState:NSOnState];
  86. if (startScale == 3) [self.changeSize3 setState:NSOnState];
  87. if (startScale == 4) [self.changeSize4 setState:NSOnState];
  88. if (startScale == 5) [self.changeSize5 setState:NSOnState];
  89. [[self.mainView render] drawWith:lastEyeState]; // Initialize render image
  90. [self setFrame:frame display:YES];
  91. }
  92. - (IBAction)changeSize:(NSMenuItem *)sender {
  93. NSRect frame = [self frame];
  94. [self.changeSize1 setState:NSOffState];
  95. [self.changeSize2 setState:NSOffState];
  96. [self.changeSize3 setState:NSOffState];
  97. [self.changeSize4 setState:NSOffState];
  98. [self.changeSize5 setState:NSOffState];
  99. BOOL found = NO;
  100. for (int i = RESIZE_START; i <= RESIZE_END; i += RESIZE_STEP) {
  101. NSString *title = [NSString stringWithFormat:@"%dx", i];
  102. if ([[sender title] isEqualToString:title]) {
  103. [sender setState:NSOnState];
  104. NSSize newSize = defaultSize;
  105. newSize.height *= i;
  106. newSize.width *= i;
  107. frame.size = newSize;
  108. found = YES;
  109. NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
  110. [defaults setInteger:i forKey:CONFIG_START_SCALE];
  111. [defaults synchronize];
  112. }
  113. }
  114. if (found == NO) {
  115. NSLog(@"Unknown changeSize sender: %@", sender);
  116. } else {
  117. [self setFrame:frame display:YES];
  118. }
  119. }
  120. - (IBAction)lockPosition:(NSMenuItem *)sender {
  121. BOOL state = [sender state];
  122. if (state == NSOffState) {
  123. // Lock position
  124. state = NSOnState;
  125. [sender setState:state];
  126. self.keepPosition = YES;
  127. NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
  128. [defaults setBool:YES forKey:CONFIG_KEEP_POSITION];
  129. [defaults synchronize];
  130. } else {
  131. // Unlock position
  132. state = NSOffState;
  133. [sender setState:state];
  134. self.keepPosition = NO;
  135. NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
  136. [defaults setBool:NO forKey:CONFIG_KEEP_POSITION];
  137. [defaults synchronize];
  138. }
  139. }
  140. - (IBAction)keepOnTop:(NSMenuItem *)sender {
  141. BOOL state = [sender state];
  142. if (state == NSOffState) {
  143. // Keep window on top
  144. state = NSOnState;
  145. [sender setState:state];
  146. [self setLevel:NSFloatingWindowLevel];
  147. NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
  148. [defaults setBool:YES forKey:CONFIG_KEEP_ON_TOP];
  149. [defaults synchronize];
  150. } else {
  151. // Don't keep window on top
  152. state = NSOffState;
  153. [sender setState:state];
  154. [self setLevel:NSNormalWindowLevel];
  155. NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
  156. [defaults setBool:NO forKey:CONFIG_KEEP_ON_TOP];
  157. [defaults synchronize];
  158. }
  159. }
  160. - (BOOL)canBecomeKeyWindow {
  161. return YES;
  162. }
  163. - (void)mouseDown:(NSEvent *)theEvent {
  164. dragStart = [theEvent locationInWindow];
  165. }
  166. - (void)mouseDragged:(NSEvent *)theEvent {
  167. NSRect screenVisibleFrame = [[NSScreen mainScreen] visibleFrame];
  168. NSRect windowFrame = [self frame];
  169. NSPoint newOrigin = windowFrame.origin;
  170. if (self.keepPosition == NO) {
  171. NSPoint currentLocation = [theEvent locationInWindow];
  172. newOrigin.x += (currentLocation.x - dragStart.x);
  173. newOrigin.y += (currentLocation.y - dragStart.y);
  174. if ((newOrigin.y + windowFrame.size.height) > (screenVisibleFrame.origin.y + screenVisibleFrame.size.height)) {
  175. newOrigin.y = screenVisibleFrame.origin.y + (screenVisibleFrame.size.height - windowFrame.size.height);
  176. }
  177. [self setFrameOrigin:newOrigin];
  178. }
  179. }
  180. - (void)mouseMoved:(NSEvent *)theEvent {
  181. NSPoint mousePoint = [NSEvent mouseLocation];
  182. mousePoint.x -= [self frame].origin.x;
  183. mousePoint.y -= [self frame].origin.y;
  184. BOOL top = (mousePoint.y > MOUSE_CENTER_Y);
  185. BOOL right = (mousePoint.x > MOUSE_CENTER_X);
  186. NSInteger eyeState = EYE_BOTTOM_LEFT;
  187. if (top && right) {
  188. eyeState = EYE_TOP_RIGHT;
  189. } else if (top && (!right)) {
  190. eyeState = EYE_TOP_LEFT;
  191. } else if ((!top) && right) {
  192. eyeState = EYE_BOTTOM_RIGHT;
  193. }
  194. if (eyeState != lastEyeState) {
  195. lastEyeState = eyeState;
  196. [[self.mainView render] drawWith:lastEyeState];
  197. self.mainView.needsDisplay = YES;
  198. }
  199. }
  200. @end