updated release notes.
[cpuHistory.git] / MainController.m
blob403dbe5328bbb7205dbab1033d09d2e7314d1b4d
1 /*
2  *      CPU History
3  *      Christopher Bowns, 2008
4  *      
5  *      Formerly: Memory Monitor, by Bernhard Baehr
6  *
7  *      Copyright © 2001-2003 Bernhard Baehr
8  *
9  *      MainController.m - Main Application Controller Class
10  *
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.
15  *
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.
20  *
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
24  */
27 #import "MainController.h"
30 #define GRAPH_SIZE      128
31 // define GRAPH_WIDTH   8
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
40                 fraction:1.0];
44 - (void)showHideWindow
46         float   size;
47         
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)];
54         } else
55                 [window orderOut:self];
59 - (void)drawComplete
60 // completely redraw graphImage, put graph into displayImage
61 {       
62         CPUData                 cpudata;
63         
64         
65         int                             x;
66         float                   y, yy;
67         int barWidth = (int)[[preferences objectForKey:BAR_WIDTH_SIZE_KEY] floatValue];
68         // double interval = 0.1 * [[preferences objectForKey:UPDATE_FREQUENCY_KEY] floatValue];
69         
70         [graphImage lockFocus];
72         // draw the cpu usage graph
73         [cpuInfo startIterate];
74         // for (x = 0; [memInfo getNext:&vmdata]; x++) {
75         for (x = 0; [cpuInfo getNext:&cpudata]; x+=barWidth) {
76                 
77                 // y += vmdata.active * GRAPH_SIZE;
78                 y = cpudata.sys * GRAPH_SIZE;
79                 [[preferences objectForKey:SYS_COLOR_KEY] set];
80                 NSRectFill (NSMakeRect(x - barWidth, 0.0, x, y));
81                 yy = y;
82                 // y += vmdata.inactive * GRAPH_SIZE;
83                 y += cpudata.nice * GRAPH_SIZE;
84                 [[preferences objectForKey:NICE_COLOR_KEY] set];
85                 NSRectFill (NSMakeRect(x - barWidth, yy, x, y));
86                 // y = vmdata.wired * GRAPH_SIZE;
87                 yy = y;
88                 
89                 y += cpudata.user * GRAPH_SIZE;
90                 [[preferences objectForKey:USER_COLOR_KEY] set];
91                 NSRectFill (NSMakeRect(x - barWidth, yy, x, y));
92                 
93                 // free data here
94                 [[preferences objectForKey:IDLE_COLOR_KEY] set];
95                 NSRectFill (NSMakeRect(x - barWidth, y, x, GRAPH_SIZE));
96         }
97         
98         // transfer graph image to icon image
99         [graphImage unlockFocus];
100         [displayImage lockFocus];       
101         [graphImage compositeToPoint:NSMakePoint(0.0, 0.0) operation:NSCompositeCopy];
102                 
103         [displayImage unlockFocus];
107 - (void)drawDelta
108 // update graphImage (based on previous graphImage), put graph into displayImage
109 {       
110         // VMData                       vmdata, vmdata0;
111         CPUData                 cpudata, cpudata0;
112         int barWidth = (int)[[preferences objectForKey:BAR_WIDTH_SIZE_KEY] floatValue];
113         float                   y, yy;
114         
115         // double interval = 0.1 * [[preferences objectForKey:UPDATE_FREQUENCY_KEY] floatValue];
116         
117         [graphImage lockFocus];
119         // offset the old graph image
120         [graphImage compositeToPoint:NSMakePoint(-barWidth, 0) operation:NSCompositeCopy];
121                 
122         // [memInfo getLast:&vmdata0];
123         [cpuInfo getLast:&cpudata0];
124         // [memInfo getCurrent:&vmdata];
125         [cpuInfo getCurrent:&cpudata];
126         
127         // draw chronological graph into graph image
128         
129         // y += vmdata.active * GRAPH_SIZE;
130         y = cpudata.sys * GRAPH_SIZE;
131         [[preferences objectForKey:SYS_COLOR_KEY] set];
132         NSRectFill (NSMakeRect(GRAPH_SIZE - barWidth, 0.0, GRAPH_SIZE - barWidth, y));
133         yy = y;
134         
135         // y += vmdata.inactive * GRAPH_SIZE;
136         y += cpudata.nice * GRAPH_SIZE;
137         [[preferences objectForKey:NICE_COLOR_KEY] set];
138         NSRectFill (NSMakeRect(GRAPH_SIZE - barWidth, yy, GRAPH_SIZE - barWidth, y));
139         yy = y;
140         
141         // y = vmdata.wired * GRAPH_SIZE;
142         y += cpudata.user * GRAPH_SIZE;
143         [[preferences objectForKey:USER_COLOR_KEY] set];
144         NSRectFill (NSMakeRect(GRAPH_SIZE - barWidth, yy, GRAPH_SIZE - barWidth, y));
146         // free data here
147         [[preferences objectForKey:IDLE_COLOR_KEY] set];
148         NSRectFill (NSMakeRect(GRAPH_SIZE - barWidth, y, GRAPH_SIZE - barWidth, GRAPH_SIZE));
151         // transfer graph image to icon image
152         [graphImage unlockFocus];
153         [displayImage lockFocus];
154         [graphImage compositeToPoint:NSMakePoint(0.0, 0.0) operation:NSCompositeCopy];
156         [displayImage unlockFocus];
160 - (void)setApplicationIcon
161 // set the (scaled) application icon
163         float inc = GRAPH_SIZE * (1.0 - [[preferences objectForKey:DOCK_ICON_SIZE_KEY] floatValue]); // icon scaling
164         [iconImage lockFocus];
165         [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];
166         [iconImage unlockFocus];
167         [NSApp setApplicationIconImage:iconImage];
171 - (void)refreshGraph
172 // get a new sample and refresh the graph
174         // [memInfo refresh];
175         [cpuInfo refresh];
176         [self drawDelta];
177         [self setApplicationIcon];
178         
179         if ([[preferences objectForKey:SHOW_GRAPH_WINDOW_KEY] boolValue]) {
180                 [window disableFlushWindow];
181                 [view display];
182                 [window enableFlushWindow];
183                 [window flushWindow];
184         }
188 - (void)updateGraph
189 // completely redraw the graph (to show new preferences settings)
191         [self drawComplete];
192         [iconImage lockFocus];
193         [[NSColor clearColor] set];
194         NSRectFill (NSMakeRect(0, 0, GRAPH_SIZE, GRAPH_SIZE));
195         [iconImage unlockFocus];
196         [self setApplicationIcon];
197         
198         if ([[preferences objectForKey:SHOW_GRAPH_WINDOW_KEY] boolValue]) {
199                 [window disableFlushWindow];
200                 [view display];
201                 [window enableFlushWindow];
202                 [window flushWindow];
203         }
207 - (void)setTimer
209         double newInterval = 0.1 * [[preferences objectForKey:UPDATE_FREQUENCY_KEY] floatValue];
211         if (timer) {
212                 if (fabs([timer timeInterval] - newInterval) < 0.001)
213                         return;         /* frequency not changed */
214                 [timer invalidate];
215                 [timer release];
216         }
217         timer = [NSTimer scheduledTimerWithTimeInterval:newInterval
218                 target:self selector:@selector(refreshGraph) userInfo:nil repeats:YES];
219         [timer retain];
223 - (void)showPreferences:(id)sender
225         [NSApp activateIgnoringOtherApps:YES];  /* activate application when called from Dock menu */
226         [preferences showPreferences:self];
230 - (void)showAboutBox:(id)sender
232         [NSApp activateIgnoringOtherApps:YES];  /* activate application when called from Dock menu */
233         [NSApp orderFrontStandardAboutPanel:sender];
237 - (BOOL)isLoginItem
239         id      obj;
240         
241         NSString *cpuHistoryPath = [[NSBundle mainBundle] bundlePath];
242         NSDictionary *loginItemDict = [NSDictionary dictionaryWithContentsOfFile:[NSString stringWithFormat:@"%@/Library/Preferences/loginwindow.plist", NSHomeDirectory()]];
243         NSEnumerator *loginItemEnumerator = [[loginItemDict objectForKey:@"AutoLaunchedApplicationDictionary"] objectEnumerator];
245         while ((obj = [loginItemEnumerator nextObject])) {
246                 if ([[obj objectForKey:@"Path"] isEqualTo:cpuHistoryPath])
247                         return (YES);
248         }
249         return (NO);
253 - (BOOL)updateFrameName
254 // calculate the frameName used to save the window position; return TRUE iff the name changed,
255 // i. e. the display configuration changed since last call of this method
257         NSRect          rect;
258         NSScreen        *screen;
259         BOOL            nameDidChange;
260         
261         NSString *string = @"CHWL";     // CPUHistoryWindowLocation
262         NSEnumerator *enumerator = [[NSScreen screens] objectEnumerator];
264         while ((screen = [enumerator nextObject])) {
265                 rect = [screen frame];
266                 string = [string
267                         stringByAppendingString:[NSString stringWithFormat:@"%.0f%.0f%.0f%.0f",
268                         rect.origin.x, rect.origin.y, rect.size.width, rect.size.height]];
269         }
270         nameDidChange = ! [string isEqualToString:frameName];
271         [frameName release];
272         frameName = string;
273         [frameName retain];
274         return (nameDidChange);
278 - (void)applicationDidFinishLaunching:(NSNotification *)notification
280         [NSApp setApplicationIconImage:[NSImage imageNamed:@"CPUHistory.icns"]];
281         
282         preferences = [[Preferences alloc] init];
283         // memInfo = [[MemInfo alloc] initWithCapacity:GRAPH_SIZE];
284         cpuInfo = [[CPUInfo alloc] initWithCapacity:GRAPH_SIZE];
285         if (nil == cpuInfo) //then we need to bomb out. We can't do anything else.
286         {
287                 NSLog(@"%s failed to create CPUInfo object!", _cmd);
288                 NSString *errorStr = [[NSString alloc] initWithFormat:@"There's not enough memory to allocate the CPU data array. Sorry, but I have to quit now."];
289                 /* now display error dialog and quit */
290                 NSRunAlertPanel(@"Error", errorStr, @"OK", nil, nil);
291                 
292                 [errorStr release];
293                 [preferences release];
294                 [NSApp terminate:nil];
295         }
296         
297         displayImage = [[NSImage allocWithZone:[self zone]] initWithSize:NSMakeSize(GRAPH_SIZE, GRAPH_SIZE)];
298         graphImage = [[NSImage allocWithZone:[self zone]] initWithSize:NSMakeSize(GRAPH_SIZE, GRAPH_SIZE)];
299         iconImage = [[NSImage allocWithZone:[self zone]] initWithSize:NSMakeSize(GRAPH_SIZE, GRAPH_SIZE)];
300         [self drawComplete];
302         window = [[TranslucentWindow allocWithZone:[self zone]]
303                 initWithContentRect:NSMakeRect(0.0, 0.0, GRAPH_SIZE, GRAPH_SIZE)
304                 styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:NO];
305         [window setReleasedWhenClosed:NO];
306         [window setBackgroundColor:[NSColor clearColor]];
307         [self updateFrameName];
308         [window setDelegate:self];
310         view = [[TranslucentView allocWithZone:[self zone]] initWithFrame:NSMakeRect(0.0, 0.0, GRAPH_SIZE, GRAPH_SIZE)];
311         [window setContentView:view];
312         [view setContentDrawer:self method:@selector(drawImageOnWindow)];
313         [view setAutoresizingMask:(NSViewHeightSizable | NSViewWidthSizable)];
314         [view setToolTip:@"CPU History"];
315         
316         
317         [self showHideWindow];
319         [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(showHideWindow) name:PREFERENCES_CHANGED object:nil];
320         [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updateGraph) name:PREFERENCES_CHANGED object:nil];
321         [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(setTimer) name:PREFERENCES_CHANGED object:nil];
323 /*      if ([self systemVersion] < 0x1010 && [self isLoginItem])
324                 [NSTimer scheduledTimerWithTimeInterval:30 target:self selector:@selector(setTimer) userInfo:nil repeats:NO];
325         else
326 */ // We can stop supporting 10.1 now. Welcome to 2003, people.
327         [self setTimer];
331 - (void)applicationWillTerminate:(NSNotification *)aNotification
333         if (timer) {
334                 [timer invalidate];
335                 [timer release];
336                 timer = nil;
337         }
338         [preferences savePreferences];
339         [NSApp setApplicationIconImage:[NSImage imageNamed:@"CPUHistory.icns"]];
343 - (void)applicationDidChangeScreenParameters:(NSNotification *)aNotification
345         [self updateFrameName];
346         [window setFrameUsingName:frameName];
350 - (void)windowDidMove:(NSNotification *)aNotification
352         if (! [self updateFrameName])
353                 [window saveFrameUsingName:frameName];
357 @end