adding xcodeproj files
[cpuHistory.git] / MainController.m
blob0eb7dcd79573273feaa648723d5f0fe68c9ab037
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         }
122         // draw the paging curves on top of the memory usage graph
123         [memInfo startIterate];
124         for (lastpageins = lastpageouts = x = 0; [memInfo getNext:&vmdata]; x++) {
125                 if (pageinAtopPageout) {
126                         y = GRAPH_SIZE * (1.0 - vmdata.pageins * pgfactor);
127                         yy = GRAPH_SIZE * (1.0 - lastpageins * pgfactor);
128                 } else {
129                         y = GRAPH_SIZE * vmdata.pageins * pgfactor;
130                         yy = GRAPH_SIZE * lastpageins * pgfactor;
131                 }
132                 [[preferences objectForKey:PAGEIN_COLOR_KEY] set];
133                 [NSBezierPath strokeLineFromPoint:NSMakePoint(x, yy) toPoint:NSMakePoint(x+1, y)];      
134                 if (pageinAtopPageout) {
135                         y = GRAPH_SIZE * vmdata.pageouts * pgfactor;
136                         yy = GRAPH_SIZE * lastpageouts * pgfactor;
137                 } else {
138                         y = GRAPH_SIZE * (1.0 - vmdata.pageouts * pgfactor);
139                         yy = GRAPH_SIZE * (1.0 - lastpageouts * pgfactor);
140                 }
141                 [[preferences objectForKey:PAGEOUT_COLOR_KEY] set];
142                 [NSBezierPath strokeLineFromPoint:NSMakePoint(x, yy) toPoint:NSMakePoint(x+1, y)];                      
143                 lastpageins = vmdata.pageins;
144                 lastpageouts = vmdata.pageouts;
145         }
146         
147         // transfer graph image to icon image
148         [graphImage unlockFocus];
149         [displayImage lockFocus];       
150         [graphImage compositeToPoint:NSMakePoint(0.0, 0.0) operation:NSCompositeCopy];
151         
152         // draw paging rate into the icon image
153         [self drawPageins:vmdata.pageins pageouts:vmdata.pageouts];
154         
155         [displayImage unlockFocus];
159 - (void)drawDelta
160 // update graphImage (based on previous graphImage), put graph and pageing rate into displayImage
161 {       
162         VMData                  vmdata, vmdata0;
163         float                   y, yy;
164         
165         BOOL pageinAtopPageout = [[preferences objectForKey:PAGEIN_ATOP_PAGEOUT_KEY] boolValue];
166         double pagingmax = [[preferences objectForKey:PAGING_SCALE_MAX_KEY] doubleValue];
167         double interval = 0.1 * [[preferences objectForKey:UPDATE_FREQUENCY_KEY] floatValue];
168         double pgfactor = 1.0 / (pagingmax * interval);
169         
170         [graphImage lockFocus];
172         // offset the old graph image
173         [graphImage compositeToPoint:NSMakePoint(-1, 0) operation:NSCompositeCopy];
174                 
175         [memInfo getLast:&vmdata0];
176         [memInfo getCurrent:&vmdata];
177         
178         // draw chronological graph into graph image
179         y = vmdata.wired * GRAPH_SIZE;
180         [[preferences objectForKey:WIRED_COLOR_KEY] set];
181         NSRectFill (NSMakeRect(GRAPH_SIZE - 1, 0.0, GRAPH_SIZE - 1, y));
182         yy = y;
183         y += vmdata.active * GRAPH_SIZE;
184         [[preferences objectForKey:ACTIVE_COLOR_KEY] set];
185         NSRectFill (NSMakeRect(GRAPH_SIZE - 1, yy, GRAPH_SIZE - 1, y));
186         yy = y;
187         y += vmdata.inactive * GRAPH_SIZE;
188         [[preferences objectForKey:INACTIVE_COLOR_KEY] set];
189         NSRectFill (NSMakeRect(GRAPH_SIZE - 1, yy, GRAPH_SIZE - 1, y));
190         [[preferences objectForKey:FREE_COLOR_KEY] set];
191         NSRectFill (NSMakeRect(GRAPH_SIZE - 1, y, GRAPH_SIZE - 1, GRAPH_SIZE));
193         if (pageinAtopPageout) {
194                 y = GRAPH_SIZE * (1.0 - vmdata.pageins * pgfactor);
195                 yy = GRAPH_SIZE * (1.0 - vmdata0.pageins * pgfactor);
196         } else {
197                 y = GRAPH_SIZE * vmdata.pageins * pgfactor;
198                 yy = GRAPH_SIZE * vmdata0.pageins * pgfactor;
199         }
200         [[preferences objectForKey:PAGEIN_COLOR_KEY] set];
201         [NSBezierPath strokeLineFromPoint:NSMakePoint(GRAPH_SIZE - 1, yy) toPoint:NSMakePoint(GRAPH_SIZE, y)];
203         if (pageinAtopPageout) {
204                 y = GRAPH_SIZE * vmdata.pageouts * pgfactor;
205                 yy = GRAPH_SIZE * vmdata0.pageouts * pgfactor;
206         } else {
207                 y = GRAPH_SIZE * (1.0 - vmdata.pageouts * pgfactor);
208                 yy = GRAPH_SIZE * (1.0 - vmdata0.pageouts * pgfactor);
209         }
210         [[preferences objectForKey:PAGEOUT_COLOR_KEY] set];
211         [NSBezierPath strokeLineFromPoint:NSMakePoint(GRAPH_SIZE - 1, yy) toPoint:NSMakePoint(GRAPH_SIZE, y)];                  
213         // transfer graph image to icon image
214         [graphImage unlockFocus];
215         [displayImage lockFocus];
216         [graphImage compositeToPoint:NSMakePoint(0.0, 0.0) operation:NSCompositeCopy];
218         // draw paging rate into the icon image
219         [self drawPageins:vmdata.pageins pageouts:vmdata.pageouts];
221         [displayImage unlockFocus];
225 - (void)setApplicationIcon
226 // set the (scaled) application icon
228         float inc = GRAPH_SIZE * (1.0 - [[preferences objectForKey:DOCK_ICON_SIZE_KEY] floatValue]);
229         [iconImage lockFocus];
230         [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];
231         [iconImage unlockFocus];
232         [NSApp setApplicationIconImage:iconImage];
236 - (void)refreshGraph
237 // get a new sample and refresh the graph
239         [memInfo refresh];
240         [self drawDelta];
241         [self setApplicationIcon];
242         
243         if ([[preferences objectForKey:SHOW_GRAPH_WINDOW_KEY] boolValue]) {
244                 [window disableFlushWindow];
245                 [view display];
246                 [window enableFlushWindow];
247                 [window flushWindow];
248         }
252 - (void)updateGraph
253 // completely redraw the graph (to show new preferences settings)
255         [self drawComplete];
256         [iconImage lockFocus];
257         [[NSColor clearColor] set];
258         NSRectFill (NSMakeRect(0, 0, GRAPH_SIZE, GRAPH_SIZE));
259         [iconImage unlockFocus];
260         [self setApplicationIcon];
261         
262         if ([[preferences objectForKey:SHOW_GRAPH_WINDOW_KEY] boolValue]) {
263                 [window disableFlushWindow];
264                 [view display];
265                 [window enableFlushWindow];
266                 [window flushWindow];
267         }
271 - (void)setTimer
273         double newInterval = 0.1 * [[preferences objectForKey:UPDATE_FREQUENCY_KEY] floatValue];
275         if (timer) {
276                 if (fabs([timer timeInterval] - newInterval) < 0.001)
277                         return;         /* frequency not changed */
278                 [timer invalidate];
279                 [timer release];
280         }
281         timer = [NSTimer scheduledTimerWithTimeInterval:newInterval
282                 target:self selector:@selector(refreshGraph) userInfo:nil repeats:YES];
283         [timer retain];
287 - (void)showPreferences:(id)sender
289         [NSApp activateIgnoringOtherApps:YES];  /* activate application when called from Dock menu */
290         [preferences showPreferences:self];
294 - (void)showAboutBox:(id)sender
296         [NSApp activateIgnoringOtherApps:YES];  /* activate application when called from Dock menu */
297         [NSApp orderFrontStandardAboutPanel:sender];
301 - (BOOL)isLoginItem
303         id      obj;
304         
305         NSString *memoryMonitorPath = [[NSBundle mainBundle] bundlePath];
306         NSDictionary *loginItemDict = [NSDictionary dictionaryWithContentsOfFile:[NSString stringWithFormat:@"%@/Library/Preferences/loginwindow.plist", NSHomeDirectory()]];
307         NSEnumerator *loginItemEnumerator = [[loginItemDict objectForKey:@"AutoLaunchedApplicationDictionary"] objectEnumerator];
309         while ((obj = [loginItemEnumerator nextObject])) {
310                 if ([[obj objectForKey:@"Path"] isEqualTo:memoryMonitorPath])
311                         return (YES);
312         }
313         return (NO);
317 - (unsigned)systemVersion
318 // returns the system version normally retrieved with Gestalt(gestaltSystemVersion, &systemVersion)
320         const char      *p;
321         
322         unsigned version = 0;
323         
324         for (p = [[[NSDictionary dictionaryWithContentsOfFile:@"/System/Library/CoreServices/SystemVersion.plist"]
325                 objectForKey:@"ProductVersion"] cString]; *p; p++) {
326                 if (*p != '.')
327                         version = (version << 4) | (*p - '0');
328         }
329         if (version < 0x1000)   // for 10.0, 10.1
330                 version <<= 4;
331         return (version);
335 - (BOOL)updateFrameName
336 // calculate the frameName used to save the window position; return TRUE iff the name changed,
337 // i. e. the display configuration changed since last call of this method
339         NSRect          rect;
340         NSScreen        *screen;
341         BOOL            nameDidChange;
342         
343         NSString *string = @"MMWL";     // MemoryMonitorWindowLocation
344         NSEnumerator *enumerator = [[NSScreen screens] objectEnumerator];
346         while ((screen = [enumerator nextObject])) {
347                 rect = [screen frame];
348                 string = [string
349                         stringByAppendingString:[NSString stringWithFormat:@"%.0f%.0f%.0f%.0f",
350                         rect.origin.x, rect.origin.y, rect.size.width, rect.size.height]];
351         }
352         nameDidChange = ! [string isEqualToString:frameName];
353         [frameName release];
354         frameName = string;
355         [frameName retain];
356         return (nameDidChange);
360 - (void)applicationDidFinishLaunching:(NSNotification *)notification
362         preferences = [[Preferences alloc] init];
363         memInfo = [[MemInfo alloc] initWithCapacity:GRAPH_SIZE];
364         
365         displayImage = [[NSImage allocWithZone:[self zone]] initWithSize:NSMakeSize(GRAPH_SIZE, GRAPH_SIZE)];
366         graphImage = [[NSImage allocWithZone:[self zone]] initWithSize:NSMakeSize(GRAPH_SIZE, GRAPH_SIZE)];
367         iconImage = [[NSImage allocWithZone:[self zone]] initWithSize:NSMakeSize(GRAPH_SIZE, GRAPH_SIZE)];
368         [self drawComplete];
370         window = [[TranslucentWindow allocWithZone:[self zone]]
371                 initWithContentRect:NSMakeRect(0.0, 0.0, GRAPH_SIZE, GRAPH_SIZE)
372                 styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:NO];
373         [window setReleasedWhenClosed:NO];
374         [window setBackgroundColor:[NSColor clearColor]];
375         [self updateFrameName];
376         if (! [window setFrameUsingName:frameName]) {
377                 // for compatibility with version 1.1 preferences file
378                 [window setFrameUsingName:@"MemoryMonitorWindowLocation"];
379                 [NSWindow removeFrameUsingName:@"MemoryMonitorWindowLocation"];
380                 [window saveFrameUsingName:frameName];
381         }
382         [window setDelegate:self];
384         view = [[TranslucentView allocWithZone:[self zone]] initWithFrame:NSMakeRect(0.0, 0.0, GRAPH_SIZE, GRAPH_SIZE)];
385         [window setContentView:view];
386         [view setContentDrawer:self method:@selector(drawImageOnWindow)];
387         [view setAutoresizingMask:(NSViewHeightSizable | NSViewWidthSizable)];
388         [view setToolTip:@"Memory Monitor"];
389         
390         
391         [self showHideWindow];
393         [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(showHideWindow) name:PREFERENCES_CHANGED object:nil];
394         [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updateGraph) name:PREFERENCES_CHANGED object:nil];
395         [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(setTimer) name:PREFERENCES_CHANGED object:nil];
397         if ([self systemVersion] < 0x1010 && [self isLoginItem])
398                 [NSTimer scheduledTimerWithTimeInterval:30 target:self selector:@selector(setTimer) userInfo:nil repeats:NO];
399         else
400                 [self setTimer];
404 - (void)applicationWillTerminate:(NSNotification *)aNotification 
406         if (timer) {
407                 [timer invalidate];
408                 [timer release];
409                 timer = nil;
410         }
411         [preferences savePreferences];
412         [NSApp setApplicationIconImage:[NSImage imageNamed:@"MemoryMonitor.icns"]];     
416 - (void)applicationDidChangeScreenParameters:(NSNotification *)aNotification
418         [self updateFrameName];
419         [window setFrameUsingName:frameName];
423 - (void)windowDidMove:(NSNotification *)aNotification
425         if (! [self updateFrameName])
426                 [window saveFrameUsingName:frameName];
430 @end