3 * Christopher Bowns, 2008
5 * Formerly: Memory Monitor, by Bernhard Baehr
7 * Copyright © 2001-2003 Bernhard Baehr
9 * MainController.m - Main Application Controller Class
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 #import "MainController.h"
30 #define GRAPH_SIZE 128
33 @implementation MainController
36 - (void)drawImageOnWindow
38 [displayImage drawInRect:NSMakeRect(0, 0, NSWidth([window frame]), NSHeight([window frame]))
39 fromRect:NSMakeRect(0, 0, GRAPH_SIZE, GRAPH_SIZE) operation:NSCompositeCopy
44 - (void)showHideWindow
48 if ([[preferences objectForKey:SHOW_GRAPH_WINDOW_KEY] boolValue]) {
49 size = [[preferences objectForKey:GRAPH_WINDOW_SIZE_KEY] floatValue];
50 [window setContentSize:NSMakeSize(size, size)];
51 [window orderWindow:NSWindowBelow relativeTo:[preferences windowNumber]];
52 [window setLevel:([[preferences objectForKey:GRAPH_WINDOW_ON_TOP_KEY] boolValue] ?
53 NSFloatingWindowLevel : NSNormalWindowLevel)];
55 [window orderOut:self];
60 // completely redraw graphImage, put graph into displayImage
69 double interval = 0.1 * [[preferences objectForKey:UPDATE_FREQUENCY_KEY] floatValue];
71 [graphImage lockFocus];
73 // draw the memory usage graph
74 // [memInfo startIterate];
75 [cpuInfo startIterate];
76 // for (x = 0; [memInfo getNext:&vmdata]; x++) {
77 for (x = 0; [cpuInfo getNext:&cpudata]; x++) {
79 // y = vmdata.wired * GRAPH_SIZE;
80 y = cpudata.user * GRAPH_SIZE;
81 [[preferences objectForKey:WIRED_COLOR_KEY] set];
82 NSRectFill (NSMakeRect(x - 1, 0.0, x, y));
84 // y += vmdata.active * GRAPH_SIZE;
85 y += cpudata.sys * GRAPH_SIZE;
86 [[preferences objectForKey:ACTIVE_COLOR_KEY] set];
87 NSRectFill (NSMakeRect(x - 1, yy, x, y));
89 // y += vmdata.inactive * GRAPH_SIZE;
90 y += cpudata.nice * GRAPH_SIZE;
91 [[preferences objectForKey:INACTIVE_COLOR_KEY] set];
92 NSRectFill (NSMakeRect(x - 1, yy, x, y));
95 [[preferences objectForKey:FREE_COLOR_KEY] set];
96 NSRectFill (NSMakeRect(x - 1, y, x, GRAPH_SIZE));
99 // transfer graph image to icon image
100 [graphImage unlockFocus];
101 [displayImage lockFocus];
102 [graphImage compositeToPoint:NSMakePoint(0.0, 0.0) operation:NSCompositeCopy];
104 [displayImage unlockFocus];
109 // update graphImage (based on previous graphImage), put graph into displayImage
111 // VMData vmdata, vmdata0;
112 CPUData cpudata, cpudata0;
115 double interval = 0.1 * [[preferences objectForKey:UPDATE_FREQUENCY_KEY] floatValue];
117 [graphImage lockFocus];
119 // offset the old graph image
120 [graphImage compositeToPoint:NSMakePoint(-1, 0) operation:NSCompositeCopy];
122 // [memInfo getLast:&vmdata0];
123 [cpuInfo getLast:&cpudata0];
124 // [memInfo getCurrent:&vmdata];
125 [cpuInfo getCurrent:&cpudata];
127 // draw chronological graph into graph image
128 // y = vmdata.wired * GRAPH_SIZE;
129 y = cpudata.user * GRAPH_SIZE;
130 [[preferences objectForKey:WIRED_COLOR_KEY] set];
131 NSRectFill (NSMakeRect(GRAPH_SIZE - 1, 0.0, GRAPH_SIZE - 1, y));
134 // y += vmdata.active * GRAPH_SIZE;
135 y += cpudata.sys * GRAPH_SIZE;
136 [[preferences objectForKey:ACTIVE_COLOR_KEY] set];
137 NSRectFill (NSMakeRect(GRAPH_SIZE - 1, yy, GRAPH_SIZE - 1, y));
140 // y += vmdata.inactive * GRAPH_SIZE;
141 y += cpudata.nice * GRAPH_SIZE;
142 [[preferences objectForKey:INACTIVE_COLOR_KEY] set];
143 NSRectFill (NSMakeRect(GRAPH_SIZE - 1, yy, GRAPH_SIZE - 1, y));
146 [[preferences objectForKey:FREE_COLOR_KEY] set];
147 NSRectFill (NSMakeRect(GRAPH_SIZE - 1, y, GRAPH_SIZE - 1, GRAPH_SIZE));
150 // transfer graph image to icon image
151 [graphImage unlockFocus];
152 [displayImage lockFocus];
153 [graphImage compositeToPoint:NSMakePoint(0.0, 0.0) operation:NSCompositeCopy];
155 [displayImage unlockFocus];
159 - (void)setApplicationIcon
160 // set the (scaled) application icon
162 float inc = GRAPH_SIZE * (1.0 - [[preferences objectForKey:DOCK_ICON_SIZE_KEY] floatValue]);
163 [iconImage lockFocus];
164 [displayImage drawInRect:NSMakeRect(inc, inc, GRAPH_SIZE - 2 * inc, GRAPH_SIZE - 2 * inc) fromRect:NSMakeRect(0, 0, GRAPH_SIZE, GRAPH_SIZE) operation:NSCompositeCopy fraction:1.0];
165 [iconImage unlockFocus];
166 [NSApp setApplicationIconImage:iconImage];
171 // get a new sample and refresh the graph
173 // [memInfo refresh];
176 [self setApplicationIcon];
178 if ([[preferences objectForKey:SHOW_GRAPH_WINDOW_KEY] boolValue]) {
179 [window disableFlushWindow];
181 [window enableFlushWindow];
182 [window flushWindow];
188 // completely redraw the graph (to show new preferences settings)
191 [iconImage lockFocus];
192 [[NSColor clearColor] set];
193 NSRectFill (NSMakeRect(0, 0, GRAPH_SIZE, GRAPH_SIZE));
194 [iconImage unlockFocus];
195 [self setApplicationIcon];
197 if ([[preferences objectForKey:SHOW_GRAPH_WINDOW_KEY] boolValue]) {
198 [window disableFlushWindow];
200 [window enableFlushWindow];
201 [window flushWindow];
208 double newInterval = 0.1 * [[preferences objectForKey:UPDATE_FREQUENCY_KEY] floatValue];
211 if (fabs([timer timeInterval] - newInterval) < 0.001)
212 return; /* frequency not changed */
216 timer = [NSTimer scheduledTimerWithTimeInterval:newInterval
217 target:self selector:@selector(refreshGraph) userInfo:nil repeats:YES];
222 - (void)showPreferences:(id)sender
224 [NSApp activateIgnoringOtherApps:YES]; /* activate application when called from Dock menu */
225 [preferences showPreferences:self];
229 - (void)showAboutBox:(id)sender
231 [NSApp activateIgnoringOtherApps:YES]; /* activate application when called from Dock menu */
232 [NSApp orderFrontStandardAboutPanel:sender];
240 NSString *memoryMonitorPath = [[NSBundle mainBundle] bundlePath];
241 NSDictionary *loginItemDict = [NSDictionary dictionaryWithContentsOfFile:[NSString stringWithFormat:@"%@/Library/Preferences/loginwindow.plist", NSHomeDirectory()]];
242 NSEnumerator *loginItemEnumerator = [[loginItemDict objectForKey:@"AutoLaunchedApplicationDictionary"] objectEnumerator];
244 while ((obj = [loginItemEnumerator nextObject])) {
245 if ([[obj objectForKey:@"Path"] isEqualTo:memoryMonitorPath])
252 - (unsigned)systemVersion
253 // returns the system version normally retrieved with Gestalt(gestaltSystemVersion, &systemVersion)
257 unsigned version = 0;
259 for (p = [[[NSDictionary dictionaryWithContentsOfFile:@"/System/Library/CoreServices/SystemVersion.plist"]
260 objectForKey:@"ProductVersion"] cString]; *p; p++) {
262 version = (version << 4) | (*p - '0');
264 if (version < 0x1000) // for 10.0, 10.1
270 - (BOOL)updateFrameName
271 // calculate the frameName used to save the window position; return TRUE iff the name changed,
272 // i. e. the display configuration changed since last call of this method
278 NSString *string = @"MMWL"; // MemoryMonitorWindowLocation
279 NSEnumerator *enumerator = [[NSScreen screens] objectEnumerator];
281 while ((screen = [enumerator nextObject])) {
282 rect = [screen frame];
284 stringByAppendingString:[NSString stringWithFormat:@"%.0f%.0f%.0f%.0f",
285 rect.origin.x, rect.origin.y, rect.size.width, rect.size.height]];
287 nameDidChange = ! [string isEqualToString:frameName];
291 return (nameDidChange);
295 - (void)applicationDidFinishLaunching:(NSNotification *)notification
297 preferences = [[Preferences alloc] init];
298 // memInfo = [[MemInfo alloc] initWithCapacity:GRAPH_SIZE];
299 cpuInfo = [[CPUInfo alloc] initWithCapacity:GRAPH_SIZE];
301 displayImage = [[NSImage allocWithZone:[self zone]] initWithSize:NSMakeSize(GRAPH_SIZE, GRAPH_SIZE)];
302 graphImage = [[NSImage allocWithZone:[self zone]] initWithSize:NSMakeSize(GRAPH_SIZE, GRAPH_SIZE)];
303 iconImage = [[NSImage allocWithZone:[self zone]] initWithSize:NSMakeSize(GRAPH_SIZE, GRAPH_SIZE)];
306 window = [[TranslucentWindow allocWithZone:[self zone]]
307 initWithContentRect:NSMakeRect(0.0, 0.0, GRAPH_SIZE, GRAPH_SIZE)
308 styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:NO];
309 [window setReleasedWhenClosed:NO];
310 [window setBackgroundColor:[NSColor clearColor]];
311 [self updateFrameName];
312 if (! [window setFrameUsingName:frameName]) {
313 // for compatibility with version 1.1 preferences file
314 [window setFrameUsingName:@"MemoryMonitorWindowLocation"];
315 [NSWindow removeFrameUsingName:@"MemoryMonitorWindowLocation"];
316 [window saveFrameUsingName:frameName];
318 [window setDelegate:self];
320 view = [[TranslucentView allocWithZone:[self zone]] initWithFrame:NSMakeRect(0.0, 0.0, GRAPH_SIZE, GRAPH_SIZE)];
321 [window setContentView:view];
322 [view setContentDrawer:self method:@selector(drawImageOnWindow)];
323 [view setAutoresizingMask:(NSViewHeightSizable | NSViewWidthSizable)];
324 [view setToolTip:@"Memory Monitor"];
327 [self showHideWindow];
329 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(showHideWindow) name:PREFERENCES_CHANGED object:nil];
330 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updateGraph) name:PREFERENCES_CHANGED object:nil];
331 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(setTimer) name:PREFERENCES_CHANGED object:nil];
333 if ([self systemVersion] < 0x1010 && [self isLoginItem])
334 [NSTimer scheduledTimerWithTimeInterval:30 target:self selector:@selector(setTimer) userInfo:nil repeats:NO];
340 - (void)applicationWillTerminate:(NSNotification *)aNotification
347 [preferences savePreferences];
348 [NSApp setApplicationIconImage:[NSImage imageNamed:@"MemoryMonitor.icns"]];
352 - (void)applicationDidChangeScreenParameters:(NSNotification *)aNotification
354 [self updateFrameName];
355 [window setFrameUsingName:frameName];
359 - (void)windowDidMove:(NSNotification *)aNotification
361 if (! [self updateFrameName])
362 [window saveFrameUsingName:frameName];