I am having a confusing issue. I try to draw a graph, and call setNeedsDisplay each time new data is added to the graph.
The graph receives new data via addData:(NSNotification*)theNote, which then tries several ways to call setNeedsDisplay to redraw the view. The data does not get redrawn properly, however, at this time. If I drag the window to another screen, or if I click on the graph and call setNeedsDisplay from mouseDown then the view is redrawn correctly. By monitoring the size of dirtyRect using NSLog, I have tracked the problem to a too small dirtyRect. But I cannot even guess how to correct this. Any ideas out there?
//
// graphView.m
// miniMRTOF
//
// Created by シューリ ピーター on 8/1/16.
// Copyright © 2016 シューリ ピーター. All rights reserved.
//
#import "graphView.h"
@implementation graphView
- (id)initWithFrame:(NSRect)frame{
self = [super initWithFrame:frame];
if (self) {
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
[nc addObserver:self selector:@selector(addData:) name:AddDataNotification object:nil];
theData = [[NSMutableArray alloc] init];
NSLog(@"graphView initialized");
}
return self;
}
-(void)addData:(NSNotification*)theNote{
NSLog(@"graphView has gotten the note");
NSMutableArray *theThermalArray = [[NSMutableArray alloc] init];
theThermalArray = [[theNote userInfo] objectForKey:@"theThermals"];
float ave = 0;
int n = 0;
for (int i=0; i<16; i++){
float f_i = [[theThermalArray objectAtIndex:i] floatValue];
ave += f_i;
if(f_i != 0) n++;
}
ave /= n;
[theData addObject:[NSNumber numberWithFloat:ave]];
NSLog(@"graphView has added %0.3f and now has %lu components", ave, (unsigned long)[theData count]);
[self setNeedsDisplay:YES];
[[self.window contentView] setNeedsDisplay:YES];
[self performSelectorOnMainThread:@selector(redraw) withObject:nil waitUntilDone:YES];
}
-(void)redraw{
[self setNeedsDisplay:YES];
[[self.window contentView] setNeedsDisplay:YES];
}
- (void)drawRect:(NSRect)dirtyRect {
[super drawRect:dirtyRect];
// Drawing code here.
NSLog(@"dirtyRect: x:%0.2f, y:%0.2f, w:%0.2f, h:%0.2f", dirtyRect.origin.x, dirtyRect.origin.y, dirtyRect.size.width, dirtyRect.size.height);
float xScale = ([self bounds].size.width)/((float)[theData count]+1e-3);//(maxX - minX);
float yScale = [self bounds].size.height/(maxT - minT);
[[NSColor whiteColor] set];
NSRect fillArea = [self bounds];
[NSBezierPath fillRect:fillArea];
if(dirtyRect.size.height < 100){
NSLog(@"small dirtyRect");
[[NSColor grayColor] set];
[NSBezierPath fillRect:dirtyRect];
}
dirtyRect = [self bounds];
int dataCount = (int)[theData count];
NSBezierPath *pathForFrame = [[NSBezierPath alloc] init];
NSPoint P0 = {1,1};
NSPoint P1 = {1, [self bounds].size.height};
NSPoint P2 = {[self bounds].size.width, 1};
[pathForFrame moveToPoint:P0];
[pathForFrame lineToPoint:P1];
[pathForFrame moveToPoint:P0];
[pathForFrame lineToPoint:P2];
[[NSColor redColor] set];
[pathForFrame stroke];
NSLog(@"drawing %i points", dataCount);
NSBezierPath *pathForPlot = [[NSBezierPath alloc] init];
if(dataCount<maxRawPlotData){
if(dataCount>1){
NSPoint p1;
p1.y = [[theData objectAtIndex:0] floatValue];
p1.x = (0-minX)*xScale;
p1.y = (p1.y-minT)*yScale;
[pathForPlot moveToPoint:p1];
NSLog(@"point: %0.1f, %0.1f", p1.x, p1.y);
}
for(int i=1; i<dataCount; i++){
NSPoint p;
p.y = [[theData objectAtIndex:i] floatValue];
p.x = (i-minX)*xScale;
p.y = (p.y-minT)*yScale;
[pathForPlot lineToPoint:p];
NSLog(@"point: %0.1f, %0.1f", p.x, p.y);
}
}
[[NSColor blackColor] set];
[pathForPlot stroke];
[txtMaxX setStringValue:[NSString stringWithFormat:@"%0.0f",maxX]];
}
-(void)controlTextDidEndEditing:(NSNotification *)obj{
NSLog(@"controlTextDidEndEditing");
if([[obj object] isEqualTo:txtMaxT]){
maxT = [txtMaxT floatValue];
[txtMidT setStringValue:[NSString stringWithFormat:@"%0.1f",0.5*(maxT+minT)]];
}
else if([[obj object] isEqualTo:txtMinT]){
minT = [txtMinT floatValue];
[txtMidT setStringValue:[NSString stringWithFormat:@"%0.1f",0.5*(maxT+minT)]];
}
else if([[obj object] isEqualTo:txtMaxX]){
maxX = [txtMaxX floatValue];
}
else if([[obj object] isEqualTo:txtMinX]){
minX = [txtMinX floatValue];
}
else NSLog(@"How'd we get here?");
[[[obj object] window] makeFirstResponder:[[obj object] window].contentView];
[self setNeedsDisplay:YES];
[self display];
}
-(void)mouseDown:(NSEvent *)theEvent{
NSLog(@"mousedown");
[self setNeedsDisplay:YES];
}
@end