Permalink
Browse files

Various updates, sync back model changes from growth-charts app

  • Loading branch information...
1 parent 185fc63 commit b785d5f4984fd673e44ce8c6199f430a5f32a2ce @p2 committed Jan 9, 2013
@@ -30,28 +30,18 @@
/**
* A chart area represents an area on a PDF file to draw content into.
- *
- * Use one of its subclasses, they are more useful than this abstract superclass.
- *
- * You can use the chart area as a standard view, adding it to a superview and have it draw the items into its context when the area is drawn, or use it
- * manually by not adding it to a view hierarchy and calling its drawing methods with your own context. We do this with CHChartPlotAreas from CHChartPage so
- * the area can also display data points that lie outside its borders.
- *
- * @attention Override "drawLayer:inContext:" in subclasses, not "drawRect:"!
*/
@interface CHChartAreaView : CHClickableView
@property (nonatomic, weak) CHChartArea *area; ///< The area model that describes the receiver
-@property (nonatomic, assign) CGPathRef outline; ///< The outline of the area. We do *not* clip to this area, but you can use it to do so.
+@property (nonatomic, strong) NSBezierPath *outline; ///< The outline of the area
@property (nonatomic, assign) CGSize pageSize; ///< The size of the page we're currently displayed on, in screen pixels
@property (nonatomic, copy) NSArray *areas; ///< An area can have any number of subareas
@property (nonatomic, weak) CHChartPDFView *pageView; ///< The PDFView we're residing in
-- (void)setFromDictionary:(NSDictionary *)dict;
-
- (void)setup;
- (void)reset;
- (void)resetHighlight;
@@ -36,12 +36,6 @@ @interface CHChartAreaView () {
@implementation CHChartAreaView
-- (void)dealloc
-{
- CGPathRelease(_outline);
-}
-
-
- (id)initWithFrame:(CGRect)frame
{
if ((self = [super initWithFrame:frame])) {
@@ -55,46 +49,6 @@ - (void)setup
}
-/**
- * The chart area model keeps a dictionary around, subclasses of the view can override this method to receive more properties for its configuration.
- * Don't forget to call super, the base implementation assigns origin and size!
- */
-- (void)setFromDictionary:(NSDictionary *)dict
-{
- // outline path
- NSString *outlineString = [dict objectForKey:@"outline"];
- if ([outlineString isKindOfClass:[NSString class]]) {
- NSArray *points = [outlineString componentsSeparatedByCharactersInSet:[[self class] outlinePathSplitSet]];
-
- // at least 3 points are required
- if ([points count] > 2) {
- CGMutablePathRef outlinePath = nil;
- for (NSString *point in points) {
- NSPoint p = NSPointFromString(point);
- if (!outlinePath) {
- outlinePath = CGPathCreateMutable();
- CGPathMoveToPoint(outlinePath, NULL, p.x, p.y);
- }
- else {
- CGPathAddLineToPoint(outlinePath, NULL, p.x, p.y);
- }
- }
-
- // store in ivar and clean up
- CGPathCloseSubpath(outlinePath);
- self.outline = CGPathCreateCopy(outlinePath);
- CGPathRelease(outlinePath);
- }
- else {
- DLog(@"For \"outline\", at least 3 points must be defined, we only got this: %@", points);
- }
- }
- else if (outlineString) {
- DLog(@"\"outline\" must be a NSString, but I got a %@, discarding", NSStringFromClass([outlineString class]));
- }
-}
-
-
#pragma mark - Data Types
/**
* This method searches all areas and returns a set of all data types that are used on the receiver
@@ -265,6 +219,11 @@ - (void)setFrame:(NSRect)frameRect
if (!NSEqualRects(self.frame, frameRect)) {
[super setFrame:frameRect];
+ // make sure we have a parent rect
+ if (CGRectIsEmpty(inParentRect)) {
+ inParentRect = CGRectMake(0.f, 0.f, 1.f, 1.f);
+ }
+
// update relative frame
CGRect relFrame = CGRectZero;
relFrame.origin.x = frameRect.origin.x / inParentRect.size.width;
@@ -314,7 +273,7 @@ - (CGRect)framingBox
*/
- (CGRect)outlineBox
{
- if (_outline) {
+/* if (_outline) {
CGSize mySize = [self bounds].size;
CGRect scaledOutline = CGPathGetBoundingBox(_outline);
scaledOutline.origin.x *= mySize.width;
@@ -323,7 +282,7 @@ - (CGRect)outlineBox
scaledOutline.size.height *= mySize.height;
return scaledOutline;
- }
+ } // */
return self.bounds;
}
@@ -398,14 +357,54 @@ - (void)drawRect:(NSRect)dirtyRect
[NSGraphicsContext saveGraphicsState];
if (self.active) {
- [[NSColor colorWithDeviceRed:0.f green:1.f blue:0.f alpha:0.4f] setFill];
+ [[NSColor colorWithDeviceRed:0.f green:1.f blue:0.f alpha:0.5f] setFill];
}
else {
[[NSColor colorWithDeviceRed:0.f green:0.f blue:1.f alpha:0.25f] setFill];
}
[NSBezierPath fillRect:self.bounds];
[NSGraphicsContext restoreGraphicsState];
+
+ // the outline path
+ if (self.active && self.outline) {
+ [NSGraphicsContext saveGraphicsState];
+
+ // transform to current size
+ NSRect bnds = self.bounds;
+ NSAffineTransform *transform = [NSAffineTransform transform];
+ [transform scaleXBy:bnds.size.width yBy:bnds.size.height];
+ NSBezierPath *outlinePath = [_outline copy];
+ [outlinePath transformUsingAffineTransform:transform];
+
+ [outlinePath setClip];
+ [[NSColor colorWithDeviceRed:1.f green:0.f blue:0.f alpha:0.5f] setFill];
+ [NSBezierPath fillRect:bnds];
+
+ [NSGraphicsContext restoreGraphicsState];
+ }
+}
+
+- (NSBezierPath *)outline
+{
+ if (!_outline) {
+ if ([self.area.outlinePoints count] > 0) {
+ NSBezierPath *path = nil;
+ for (NSValue *pointValue in self.area.outlinePoints) {
+ if (!path) {
+ path = [NSBezierPath new];
+ [path moveToPoint:[pointValue pointValue]];
+ }
+ else {
+ [path lineToPoint:[pointValue pointValue]];
+ }
+ }
+
+ [path closePath];
+ self.outline = path;
+ }
+ }
+ return _outline;
}
@@ -66,7 +66,7 @@ - (void)drawPagePost:(PDFPage *)page
NSSet *areas = _chart.chartAreas;
if ([areas count] > 0) {
for (CHChartArea *area in areas) {
- if (pageNum == area.page) {
+ if (!area.page || pageNum == area.page) {
CHChartAreaView *areaView = [area viewForParent:self];
areaView.pageView = self;
[areaView positionInFrame:pageFrame onView:docView pageSize:origSize];
@@ -232,7 +232,7 @@ - (NSButton *)zoomOut
{
if (!_zoomOut) {
self.zoomOut = [[NSButton alloc] initWithFrame:NSMakeRect(0.f, 0.f, 39.f, 38.f)];
- //[_zoomIn setAutoresizingMask:NSViewMinXMargin];
+ //[_zoomOut setAutoresizingMask:NSViewMinXMargin];
[_zoomOut setButtonType:NSMomentaryPushInButton];
[_zoomOut setBezelStyle:NSCircularBezelStyle];
[_zoomOut setTitle:@"-"];
@@ -19,6 +19,7 @@
@property (nonatomic, strong) CHChart *chart;
- (NSURL *)pdfWithSameName;
+- (void)didLoadPDFAtURL:(NSURL *)pdfURL;
@end
@@ -26,12 +26,11 @@ - (void)makeWindowControllers
{
CHWindowController *controller = [[CHWindowController alloc] initWithWindowNibName:@"CHDocument"];
[self addWindowController:controller];
-}
-
-- (void)windowControllerDidLoadNib:(NSWindowController *)aController
-{
- [super windowControllerDidLoadNib:aController];
- // Add any code here that needs to be executed once the windowController has loaded the document's window.
+
+ // if we created a new document, we don't yet have a chart, create one
+ if (!_chart) {
+ self.chart = [CHChart new];
+ }
}
+ (BOOL)autosavesInPlace
@@ -42,6 +41,15 @@ + (BOOL)autosavesInPlace
#pragma mark - Chart Handling
+- (void)setChart:(CHChart *)chart
+{
+ if (chart != _chart) {
+ [self willChangeValueForKey:@"chart"];
+ _chart = chart;
+ [self didChangeValueForKey:@"chart"];
+ }
+}
+
/**
* When loading a JSON, looks if there is a PDF with the same name in that directory, and returns the URL.
*/
@@ -61,12 +69,34 @@ - (NSURL *)pdfWithSameName
return nil;
}
+/**
+ * We call this when we load a PDF; if the document does not yet have a name, we use the PDF name.
+ */
+- (void)didLoadPDFAtURL:(NSURL *)pdfURL
+{
+ if (!pdfURL || [self fileURL]) {
+ return;
+ }
+
+ // set the document URL
+ NSString *fileName = [[pdfURL lastPathComponent] stringByDeletingPathExtension];
+ NSString *jsonName = [fileName stringByAppendingString:@".json"];
+ NSString *jsonPath = [[[pdfURL path] stringByDeletingLastPathComponent] stringByAppendingPathComponent:jsonName];
+ NSFileManager *fm = [NSFileManager defaultManager];
+ if ([fm fileExistsAtPath:jsonPath]) {
+ DLog(@"There already exists a JSON with the same name as this PDF at %@", jsonPath);
+ }
+ else {
+ self.fileURL = [NSURL fileURLWithPath:jsonPath];
+ }
+}
+
#pragma mark - File Reading and Writing
- (NSData *)dataOfType:(NSString *)typeName error:(NSError **)outError
{
- if (![@"DocumentType" isEqualToString:typeName]) {
+ if (![@"Growth Chart JSON" isEqualToString:typeName]) {
if (NULL != outError) {
NSString *errorMessage = [NSString stringWithFormat:@"I don't know how to write data of type \"%@\"", typeName];
NSDictionary *info = @{NSLocalizedDescriptionKey: errorMessage};
@@ -93,7 +123,7 @@ - (NSData *)dataOfType:(NSString *)typeName error:(NSError **)outError
- (BOOL)readFromData:(NSData *)data ofType:(NSString *)typeName error:(NSError **)outError
{
- if (![@"DocumentType" isEqualToString:typeName]) {
+ if (![@"Growth Chart JSON" isEqualToString:typeName]) {
if (NULL != outError) {
NSString *errorMessage = [NSString stringWithFormat:@"I don't know how to read data of type \"%@\"", typeName];
NSDictionary *info = @{NSLocalizedDescriptionKey: errorMessage};
@@ -33,7 +33,6 @@
*/
@interface CHWindowController : NSWindowController <NSSplitViewDelegate>
-@property (nonatomic, readonly, weak) CHChart *chart;
@property (nonatomic, readonly, weak) CHChartArea *activeArea;
@property (nonatomic, readonly, strong) CHChartPDFView *pdf;
@@ -32,7 +32,6 @@ @interface CHWindowController () {
NSUInteger currentAreaIndex;
}
-@property (nonatomic, readwrite, weak) CHChart *chart;
@property (nonatomic, readwrite, weak) CHChartArea *activeArea;
@property (nonatomic, readwrite, strong) CHChartPDFView *pdf;
@@ -138,7 +137,7 @@ - (void)loadPDFAt:(NSURL *)url
PDFDocument *pdfDoc = [[PDFDocument alloc] initWithURL:url];
_pdf.document = pdfDoc;
- _pdf.chart = self.chart;
+ _pdf.chart = [self pdfDocument].chart;
// add as subview
_pdf.frame = _leftPane.bounds;
@@ -149,6 +148,9 @@ - (void)loadPDFAt:(NSURL *)url
// update button
_pdfFoundButton.title = @"Unload PDF";
[_pdfFoundButton setEnabled:YES];
+
+ // if we don't yet have a JSON document, use the PDF name as JSON name
+ [[self pdfDocument] didLoadPDFAtURL:url];
}
- (IBAction)handleFoundPDF:(id)sender
@@ -204,19 +206,15 @@ - (void)updateFoundPDFStatus
#pragma mark - Chart Handling
-- (void)setDocument:(NSDocument *)document
-{
- [super setDocument:document];
- self.chart = [self pdfDocument].chart;
-}
-
- (CHDocument *)pdfDocument
{
return (CHDocument *)self.document;
}
+
+
#pragma mark - Area Handling
/**
* We are observing _pdf.activeArea, so whenever that one changes we will also enter this method.
@@ -259,7 +257,7 @@ - (void)changeActiveArea:(NSButton *)sender
- (IBAction)addArea:(id)sender
{
- CHChartArea *newArea = [[self chart] newAreaInParentArea:_activeArea];
+ CHChartArea *newArea = [[self pdfDocument].chart newAreaInParentArea:_activeArea];
[self doAddArea:newArea];
}
@@ -286,7 +284,7 @@ - (void)doRemoveArea:(CHChartArea *)area
[self.undoManager registerUndoWithTarget:self selector:@selector(doAddArea:) object:area];
// remove
- [[self chart] removeArea:area];
+ [[self pdfDocument].chart removeArea:area];
[_pdf didRemoveArea:area];
}
@@ -55,21 +55,29 @@
@property (nonatomic, copy) NSString *sourceName; ///< The source name
@property (nonatomic, copy) NSString *sourceAcronym; ///< The acronym for the source
@property (nonatomic, copy) NSString *shortDescription; ///< A description of this chart
-@property (nonatomic, copy) NSString *resourceName; ///< The file name in our bundle, if available
@property (nonatomic, copy) NSString *source; ///< Where this chart comes from, usually a URL
@property (nonatomic, assign) CHGender gender; ///< The gender found on this chart
-@property (nonatomic, strong) PPRange *ageRange; ///< The age-range in months
@property (nonatomic, strong) NSSet *chartAreas; ///< The areas on the chart that can show data (CHChartArea objects)
-+ (NSArray *)bundledCharts;
+@property (nonatomic, strong) NSURL *resourceURL; ///< The URL to a file in our bundle, if available
+@property (nonatomic, copy) NSString *resourceName; ///< The file name in our bundle, if available
-- (NSURL *)resourceURL;
+@property (nonatomic, copy) PPRange *ageRangeMonths; ///< The age-range in months
+@property (nonatomic, copy) PPRange *weightRangeKilogram; ///< The weight-range in kilogram
+@property (nonatomic, copy) PPRange *lengthRangeCentimeter; ///< The length-range in centimeter
+@property (nonatomic, copy) PPRange *hcRangeCentimeter; ///< The headcircumference-range in centimeter
+
++ (NSArray *)bundledCharts;
- (NSUInteger)numAreas;
- (CHChartArea *)newAreaInParentArea:(CHChartArea *)parent;
- (void)addArea:(CHChartArea *)area;
- (void)removeArea:(CHChartArea *)area;
+- (NSSet *)plotDataTypes;
+- (BOOL)hasAreaWithDataType:(NSString *)dataType;
+- (BOOL)plotsAreaWithDataType:(NSString *)dataType;
+
@end
Oops, something went wrong.

0 comments on commit b785d5f

Please sign in to comment.