got it working. Looks like the data is what we expect.
[cpuHistory.git] / MainController.m
blob4515fb6744669f740ab36b97c7e8a467c11e2c01
1 /*
2  *      Memory Monitor
3  *
4  *      Copyright © 2001-2003 Bernhard Baehr
5  *
6  *      MainController.m - Main Application Controller Class
7  *
8  *      This program is free software; you can redistribute it and/or modify
9  *      it under the terms of the GNU General Public License as published by
10  *      the Free Software Foundation; either version 2 of the License, or
11  *      (at your option) any later version.
12  *
13  *      This program is distributed in the hope that it will be useful,
14  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *      GNU General Public License for more details.
17  *
18  *      You should have received a copy of the GNU General Public License
19  *      along with this program; if not, write to the Free Software
20  *      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  */
24 #import "MainController.h"
27 #define GRAPH_SIZE      128
30 @implementation MainController
33 - (void)drawImageOnWindow
35         [displayImage drawInRect:NSMakeRect(0, 0, NSWidth([window frame]), NSHeight([window frame]))
36                 fromRect:NSMakeRect(0, 0, GRAPH_SIZE, GRAPH_SIZE) operation:NSCompositeCopy
37                 fraction:1.0];
41 - (void)showHideWindow
43         float   size;
44         
45         if ([[preferences objectForKey:SHOW_GRAPH_WINDOW_KEY] boolValue]) {
46                 size = [[preferences objectForKey:GRAPH_WINDOW_SIZE_KEY] floatValue];
47                 [window setContentSize:NSMakeSize(size, size)];
48                 [window orderWindow:NSWindowBelow relativeTo:[preferences windowNumber]];
49                 [window setLevel:([[preferences objectForKey:GRAPH_WINDOW_ON_TOP_KEY] boolValue] ?
50                         NSFloatingWindowLevel : NSNormalWindowLevel)];
51         } else
52                 [window orderOut:self];
56 - (void)drawPageins:(int)pageins pageouts:(int)pageouts
58         int                     paging;
59         NSString                *string;
60         NSMutableDictionary     *fontAttrs;
61         
62         // draw paging rate into the icon image
63         if ([[preferences objectForKey:SHOW_PAGING_RATE_KEY] boolValue]) {
64                 paging = (pageins + pageouts) / (0.1 * [[preferences objectForKey:UPDATE_FREQUENCY_KEY] floatValue]);
65                 if (paging != 0) {
66                         if (pageins == 0)
67                                 string = NSLocalizedString(@"out", @"");
68                         else if (pageouts == 0)
69                                 string = NSLocalizedString(@"in", @"");
70                         else
71                                 string = NSLocalizedString(@"i/o", @"");
72                         fontAttrs = [[NSMutableDictionary alloc] initWithObjectsAndKeys:
73                                 [NSFont boldSystemFontOfSize:48.0], NSFontAttributeName,
74                                 [NSColor blackColor], NSForegroundColorAttributeName,
75                                 nil];
76                         [string drawAtPoint:NSMakePoint(4.0, 60.0) withAttributes:fontAttrs];
77                         [fontAttrs setObject:[NSColor whiteColor] forKey:NSForegroundColorAttributeName];
78                         [string drawAtPoint:NSMakePoint(2.0, 62.0) withAttributes:fontAttrs];
79                         string = [NSString stringWithFormat:@"%d", paging];
80                         [fontAttrs setObject:[NSColor blackColor] forKey:NSForegroundColorAttributeName];
81                         [string drawAtPoint:NSMakePoint(4.0, 12.0) withAttributes:fontAttrs];
82                         [fontAttrs setObject:[NSColor whiteColor] forKey:NSForegroundColorAttributeName];
83                         [string drawAtPoint:NSMakePoint(2.0, 14.0) withAttributes:fontAttrs];
84                         [fontAttrs release];
85                 }
86         }
90 - (void)drawComplete
91 // completely redraw graphImage, put graph and pageing rate into displayImage
92 {       
93         VMData                  vmdata;
94         int                     lastpageins, lastpageouts, x;
95         float                   y, yy;
96         
97         BOOL pageinAtopPageout = [[preferences objectForKey:PAGEIN_ATOP_PAGEOUT_KEY] boolValue];
98         double pagingmax = [[preferences objectForKey:PAGING_SCALE_MAX_KEY] doubleValue];
99         double interval = 0.1 * [[preferences objectForKey:UPDATE_FREQUENCY_KEY] floatValue];
100         double pgfactor = 1.0 / (pagingmax * interval);
101         
102         [graphImage lockFocus];
104         // draw the memory usage graph
105         [memInfo startIterate];
106         for (x = 0; [memInfo getNext:&vmdata]; x++) {
107                 y = vmdata.wired * GRAPH_SIZE;
108                 [[preferences objectForKey:WIRED_COLOR_KEY] set];
109                 NSRectFill (NSMakeRect(x - 1, 0.0, x, y));
110                 yy = y;
111                 y += vmdata.active * GRAPH_SIZE;
112                 [[preferences objectForKey:ACTIVE_COLOR_KEY] set];
113                 NSRectFill (NSMakeRect(x - 1, yy, x, y));
114                 yy = y;
115                 y += vmdata.inactive * GRAPH_SIZE;
116                 [[preferences objectForKey:INACTIVE_COLOR_KEY] set];
117                 NSRectFill (NSMakeRect(x - 1, yy, x, y));
118                 [[preferences objectForKey:FREE_COLOR_KEY] set];
119                 NSRectFill (NSMakeRect(x - 1, y, x, GRAPH_SIZE));
120         }
121         
123         TODO paging curves: we don't need these here anymore.
125         // draw the paging curves on top of the memory usage graph
126         [memInfo startIterate];
127         for (lastpageins = lastpageouts = x = 0; [memInfo getNext:&vmdata]; x++) {
128                 if (pageinAtopPageout) {
129                         y = GRAPH_SIZE * (1.0 - vmdata.pageins * pgfactor);
130                         yy = GRAPH_SIZE * (1.0 - lastpageins * pgfactor);
131                 } else {
132                         y = GRAPH_SIZE * vmdata.pageins * pgfactor;
133                         yy = GRAPH_SIZE * lastpageins * pgfactor;
134                 }
135                 [[preferences objectForKey:PAGEIN_COLOR_KEY] set];
136                 [NSBezierPath strokeLineFromPoint:NSMakePoint(x, yy) toPoint:NSMakePoint(x+1, y)];      
137                 if (pageinAtopPageout) {
138                         y = GRAPH_SIZE * vmdata.pageouts * pgfactor;
139                         yy = GRAPH_SIZE * lastpageouts * pgfactor;
140                 } else {
141                         y = GRAPH_SIZE * (1.0 - vmdata.pageouts * pgfactor);
142                         yy = GRAPH_SIZE * (1.0 - lastpageouts * pgfactor);
143                 }
144                 [[preferences objectForKey:PAGEOUT_COLOR_KEY] set];
145                 [NSBezierPath strokeLineFromPoint:NSMakePoint(x, yy) toPoint:NSMakePoint(x+1, y)];                      
146                 lastpageins = vmdata.pageins;
147                 lastpageouts = vmdata.pageouts;
148         }
149         
150         // transfer graph image to icon image
151         [graphImage unlockFocus];
152         [displayImage lockFocus];       
153         [graphImage compositeToPoint:NSMakePoint(0.0, 0.0) operation:NSCompositeCopy];
154         
155         // draw paging rate into the icon image
156         [self drawPageins:vmdata.pageins pageouts:vmdata.pageouts];
157         
158         [displayImage unlockFocus];
162 - (void)drawDelta
163 // update graphImage (based on previous graphImage), put graph and pageing rate into displayImage
164 {       
165         VMData                  vmdata, vmdata0;
166         float                   y, yy;
167         
168         BOOL pageinAtopPageout = [[preferences objectForKey:PAGEIN_ATOP_PAGEOUT_KEY] boolValue];
169         double pagingmax = [[preferences objectForKey:PAGING_SCALE_MAX_KEY] doubleValue];
170         double interval = 0.1 * [[preferences objectForKey:UPDATE_FREQUENCY_KEY] floatValue];
171         double pgfactor = 1.0 / (pagingmax * interval);
172         
173         [graphImage lockFocus];
175         // offset the old graph image
176         [graphImage compositeToPoint:NSMakePoint(-1, 0) operation:NSCompositeCopy];
177                 
178         [memInfo getLast:&vmdata0];
179         [memInfo getCurrent:&vmdata];
180         
181         // draw chronological graph into graph image
182         y = vmdata.wired * GRAPH_SIZE;
183         [[preferences objectForKey:WIRED_COLOR_KEY] set];
184         NSRectFill (NSMakeRect(GRAPH_SIZE - 1, 0.0, GRAPH_SIZE - 1, y));
185         yy = y;
186         y += vmdata.active * GRAPH_SIZE;
187         [[preferences objectForKey:ACTIVE_COLOR_KEY] set];
188         NSRectFill (NSMakeRect(GRAPH_SIZE - 1, yy, GRAPH_SIZE - 1, y));
189         yy = y;
190         y += vmdata.inactive * GRAPH_SIZE;
191         [[preferences objectForKey:INACTIVE_COLOR_KEY] set];
192         NSRectFill (NSMakeRect(GRAPH_SIZE - 1, yy, GRAPH_SIZE - 1, y));
193         [[preferences objectForKey:FREE_COLOR_KEY] set];
194         NSRectFill (NSMakeRect(GRAPH_SIZE - 1, y, GRAPH_SIZE - 1, GRAPH_SIZE));
196         if (pageinAtopPageout) {
197                 y = GRAPH_SIZE * (1.0 - vmdata.pageins * pgfactor);
198                 yy = GRAPH_SIZE * (1.0 - vmdata0.pageins * pgfactor);
199         } else {
200                 y = GRAPH_SIZE * vmdata.pageins * pgfactor;
201                 yy = GRAPH_SIZE * vmdata0.pageins * pgfactor;
202         }
203         [[preferences objectForKey:PAGEIN_COLOR_KEY] set];
204         [NSBezierPath strokeLineFromPoint:NSMakePoint(GRAPH_SIZE - 1, yy) toPoint:NSMakePoint(GRAPH_SIZE, y)];
206         if (pageinAtopPageout) {
207                 y = GRAPH_SIZE * vmdata.pageouts * pgfactor;
208                 yy = GRAPH_SIZE * vmdata0.pageouts * pgfactor;
209         } else {
210                 y = GRAPH_SIZE * (1.0 - vmdata.pageouts * pgfactor);
211                 yy = GRAPH_SIZE * (1.0 - vmdata0.pageouts * pgfactor);
212         }
213         [[preferences objectForKey:PAGEOUT_COLOR_KEY] set];
214         [NSBezierPath strokeLineFromPoint:NSMakePoint(GRAPH_SIZE - 1, yy) toPoint:NSMakePoint(GRAPH_SIZE, y)];                  
216         // transfer graph image to icon image
217         [graphImage unlockFocus];
218         [displayImage lockFocus];
219         [graphImage compositeToPoint:NSMakePoint(0.0, 0.0) operation:NSCompositeCopy];
221         // draw paging rate into the icon image
222         [self drawPageins:vmdata.pageins pageouts:vmdata.pageouts];
224         [displayImage unlockFocus];
228 - (void)setApplicationIcon
229 // set the (scaled) application icon
231         float inc = GRAPH_SIZE * (1.0 - [[preferences objectForKey:DOCK_ICON_SIZE_KEY] floatValue]);
232         [iconImage lockFocus];
233         [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];
234         [iconImage unlockFocus];
235         [NSApp setApplicationIconImage:iconImage];
239 - (void)refreshGraph
240 // get a new sample and refresh the graph
242         [memInfo refresh];
243         [self drawDelta];
244         [self setApplicationIcon];
245         
246         if ([[preferences objectForKey:SHOW_GRAPH_WINDOW_KEY] boolValue]) {
247                 [window disableFlushWindow];
248                 [view display];
249                 [window enableFlushWindow];
250                 [window flushWindow];
251         }
255 - (void)updateGraph
256 // completely redraw the graph (to show new preferences settings)
258         [self drawComplete];
259         [iconImage lockFocus];
260         [[NSColor clearColor] set];
261         NSRectFill (NSMakeRect(0, 0, GRAPH_SIZE, GRAPH_SIZE));
262         [iconImage unlockFocus];
263         [self setApplicationIcon];
264         
265         if ([[preferences objectForKey:SHOW_GRAPH_WINDOW_KEY] boolValue]) {
266                 [window disableFlushWindow];
267                 [view display];
268                 [window enableFlushWindow];
269                 [window flushWindow];
270         }
274 - (void)setTimer
276         double newInterval = 0.1 * [[preferences objectForKey:UPDATE_FREQUENCY_KEY] floatValue];
278         if (timer) {
279                 if (fabs([timer timeInterval] - newInterval) < 0.001)
280                         return;         /* frequency not changed */
281                 [timer invalidate];
282                 [timer release];
283         }
284         timer = [NSTimer scheduledTimerWithTimeInterval:newInterval
285                 target:self selector:@selector(refreshGraph) userInfo:nil repeats:YES];
286         [timer retain];
290 - (void)showPreferences:(id)sender
292         [NSApp activateIgnoringOtherApps:YES];  /* activate application when called from Dock menu */
293         [preferences showPreferences:self];
297 - (void)showAboutBox:(id)sender
299         [NSApp activateIgnoringOtherApps:YES];  /* activate application when called from Dock menu */
300         [NSApp orderFrontStandardAboutPanel:sender];
304 - (BOOL)isLoginItem
306         id      obj;
307         
308         NSString *memoryMonitorPath = [[NSBundle mainBundle] bundlePath];
309         NSDictionary *loginItemDict = [NSDictionary dictionaryWithContentsOfFile:[NSString stringWithFormat:@"%@/Library/Preferences/loginwindow.plist", NSHomeDirectory()]];
310         NSEnumerator *loginItemEnumerator = [[loginItemDict objectForKey:@"AutoLaunchedApplicationDictionary"] objectEnumerator];
312         while ((obj = [loginItemEnumerator nextObject])) {
313                 if ([[obj objectForKey:@"Path"] isEqualTo:memoryMonitorPath])
314                         return (YES);
315         }
316         return (NO);
320 - (unsigned)systemVersion
321 // returns the system version normally retrieved with Gestalt(gestaltSystemVersion, &systemVersion)
323         const char      *p;
324         
325         unsigned version = 0;
326         
327         for (p = [[[NSDictionary dictionaryWithContentsOfFile:@"/System/Library/CoreServices/SystemVersion.plist"]
328                 objectForKey:@"ProductVersion"] cString]; *p; p++) {
329                 if (*p != '.')
330                         version = (version << 4) | (*p - '0');
331         }
332         if (version < 0x1000)   // for 10.0, 10.1
333                 version <<= 4;
334         return (version);
338 - (BOOL)updateFrameName
339 // calculate the frameName used to save the window position; return TRUE iff the name changed,
340 // i. e. the display configuration changed since last call of this method
342         NSRect          rect;
343         NSScreen        *screen;
344         BOOL            nameDidChange;
345         
346         NSString *string = @"MMWL";     // MemoryMonitorWindowLocation
347         NSEnumerator *enumerator = [[NSScreen screens] objectEnumerator];
349         while ((screen = [enumerator nextObject])) {
350                 rect = [screen frame];
351                 string = [string
352                         stringByAppendingString:[NSString stringWithFormat:@"%.0f%.0f%.0f%.0f",
353                         rect.origin.x, rect.origin.y, rect.size.width, rect.size.height]];
354         }
355         nameDidChange = ! [string isEqualToString:frameName];
356         [frameName release];
357         frameName = string;
358         [frameName retain];
359         return (nameDidChange);
363 - (void)applicationDidFinishLaunching:(NSNotification *)notification
365         preferences = [[Preferences alloc] init];
366         memInfo = [[MemInfo alloc] initWithCapacity:GRAPH_SIZE];
367         cpuInfo = [[CPUInfo alloc] init];
368         
369         displayImage = [[NSImage allocWithZone:[self zone]] initWithSize:NSMakeSize(GRAPH_SIZE, GRAPH_SIZE)];
370         graphImage = [[NSImage allocWithZone:[self zone]] initWithSize:NSMakeSize(GRAPH_SIZE, GRAPH_SIZE)];
371         iconImage = [[NSImage allocWithZone:[self zone]] initWithSize:NSMakeSize(GRAPH_SIZE, GRAPH_SIZE)];
372         [self drawComplete];
374         window = [[TranslucentWindow allocWithZone:[self zone]]
375                 initWithContentRect:NSMakeRect(0.0, 0.0, GRAPH_SIZE, GRAPH_SIZE)
376                 styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:NO];
377         [window setReleasedWhenClosed:NO];
378         [window setBackgroundColor:[NSColor clearColor]];
379         [self updateFrameName];
380         if (! [window setFrameUsingName:frameName]) {
381                 // for compatibility with version 1.1 preferences file
382                 [window setFrameUsingName:@"MemoryMonitorWindowLocation"];
383                 [NSWindow removeFrameUsingName:@"MemoryMonitorWindowLocation"];
384                 [window saveFrameUsingName:frameName];
385         }
386         [window setDelegate:self];
388         view = [[TranslucentView allocWithZone:[self zone]] initWithFrame:NSMakeRect(0.0, 0.0, GRAPH_SIZE, GRAPH_SIZE)];
389         [window setContentView:view];
390         [view setContentDrawer:self method:@selector(drawImageOnWindow)];
391         [view setAutoresizingMask:(NSViewHeightSizable | NSViewWidthSizable)];
392         [view setToolTip:@"Memory Monitor"];
393         
394         
395         [self showHideWindow];
397         [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(showHideWindow) name:PREFERENCES_CHANGED object:nil];
398         [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updateGraph) name:PREFERENCES_CHANGED object:nil];
399         [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(setTimer) name:PREFERENCES_CHANGED object:nil];
401         if ([self systemVersion] < 0x1010 && [self isLoginItem])
402                 [NSTimer scheduledTimerWithTimeInterval:30 target:self selector:@selector(setTimer) userInfo:nil repeats:NO];
403         else
404                 [self setTimer];
408 - (void)applicationWillTerminate:(NSNotification *)aNotification 
410         if (timer) {
411                 [timer invalidate];
412                 [timer release];
413                 timer = nil;
414         }
415         [preferences savePreferences];
416         [NSApp setApplicationIconImage:[NSImage imageNamed:@"MemoryMonitor.icns"]];     
420 - (void)applicationDidChangeScreenParameters:(NSNotification *)aNotification
422         [self updateFrameName];
423         [window setFrameUsingName:frameName];
427 - (void)windowDidMove:(NSNotification *)aNotification
429         if (! [self updateFrameName])
430                 [window saveFrameUsingName:frameName];
434 @end