1/* dvGrid.m 2 * Grid additions for Cenon DocView class 3 * 4 * Copyright (C) 1997-2012 by vhf interservice GmbH 5 * Author: Georg Fleischmann 6 * 7 * created: 1997-11-05 8 * modified: 2012-06-25 (display x10 grid even if x1 grid becomes too small) 9 * 2012-02-13 (thicker line every 10 thin lines) 10 * 2005-05-19 (line width set to 0.51) 11 * 12 * This program is free software; you can redistribute it and/or 13 * modify it under the terms of the vhf Public License as 14 * published by vhf interservice GmbH. Among other things, the 15 * License requires that the copyright notices and this notice 16 * be preserved on all copies. 17 * 18 * This program is distributed in the hope that it will be useful, 19 * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 21 * See the vhf Public License for more details. 22 * 23 * You should have received a copy of the vhf Public License along 24 * with this program; see the file LICENSE. If not, write to vhf. 25 * 26 * vhf interservice GmbH, Im Marxle 3, 72119 Altingen, Germany 27 * eMail: info@vhf.de 28 * http://www.vhf.de 29 */ 30 31#include <AppKit/AppKit.h> 32#include "App.h" 33#include "DocView.h" 34#include "DocWindow.h" 35#include "locations.h" 36#include "functions.h" 37 38 39@implementation DocView(Grid) 40 41/* Methods to modify the grid of the GraphicView. */ 42 43- (void)drawGrid 44{ VFloat trueGridSpacing = gridSpacing; 45 int n = 10; 46 47 if ( [self gridIsRelative] ) 48 trueGridSpacing = trueGridSpacing * [self resolution] * scale; 49 if ( [self gridIsEnabled] && numGridRectsX && trueGridSpacing >= 1 ) 50 { int i, offX, offY; 51 double bigGridSpacing = gridSpacing * [self resolution] * n; // larger grid (* 10) 52 NSPoint pStart; 53 54 /* fine grid */ 55 if ( trueGridSpacing >= 4 ) 56 { 57 [[NSColor lightGrayColor] set]; 58 //[[NSColor colorWithDeviceRed:0.91 green:0.95 blue:1.0 alpha:1.0] set]; // light blue 59 [NSBezierPath setDefaultLineWidth:(VHFIsDrawingToScreen() ? 1.0/scale : 0.1)]; 60 for ( i=0; i<numGridRectsX; i++ ) 61 [NSBezierPath strokeRect:gridListX[i]]; 62 for ( i=0; i<numGridRectsY; i++ ) 63 [NSBezierPath strokeRect:gridListY[i]]; 64 } 65 66 /* we draw every n'th line stronger (centered at crosshair origin) */ 67 pStart = [self pointAbsolute:NSZeroPoint]; // this is the crosshair position 68 pStart.x = pStart.x - floor(pStart.x / bigGridSpacing) * bigGridSpacing; 69 pStart.y = pStart.y - floor(pStart.y / bigGridSpacing) * bigGridSpacing; 70 for ( offX=0; offX < Min(n, numGridRectsX); offX++ ) 71 if ( gridListX[offX].origin.x + TOLERANCE >= pStart.x ) 72 break; 73 for ( offY=0; offY < Min(n, numGridRectsY); offY++ ) 74 if ( gridListY[offY].origin.y + TOLERANCE >= pStart.y ) 75 break; 76 [[NSColor grayColor] set]; 77 //[[NSColor colorWithDeviceRed:0.8 green:0.89 blue:1.0 alpha:1.0] set]; // light blue 78 [NSBezierPath setDefaultLineWidth:(VHFIsDrawingToScreen() ? 1.0/scale : 0.1)]; 79 for ( i = offX; i < numGridRectsX; i += n ) // X 80 [NSBezierPath strokeRect:gridListX[i]]; 81 for ( i = offY; i < numGridRectsY; i += n ) // Y 82 [NSBezierPath strokeRect:gridListY[i]]; 83 } 84} 85 86- (void)setGridSpacing:(float)spacing 87{ 88 if ( gridSpacing != spacing && spacing > 0 && spacing < 256 ) 89 { 90 gridSpacing = spacing; 91 gridIsEnabled = YES; 92 [self resetGrid]; 93 [self drawAndDisplay]; 94 [[self window] flushWindow]; 95 } 96} 97 98- (float)gridSpacing 99{ 100 return gridSpacing; 101} 102 103- (void)toggleGrid:sender 104{ 105 if ([sender respondsToSelector:@selector(tag)]) 106 [self setGridEnabled:[(NSMenuItem*)sender tag] ? YES : NO]; 107} 108 109- (void)setGridEnabled:(BOOL)flag 110{ 111 if (gridIsEnabled != flag) 112 { 113 gridIsEnabled = flag; 114 if (flag) 115 [self resetGrid]; 116 [self drawAndDisplay]; 117 [[self window] flushWindow]; 118 } 119} 120 121- (BOOL)gridIsEnabled 122{ 123 return gridIsEnabled; 124} 125 126- (void)setGridUnit:(int)value 127{ 128 if (gridUnit != value) 129 { 130 gridUnit = value; 131 [self resetGrid]; 132 [self drawAndDisplay]; 133 [[self window] flushWindow]; 134 } 135} 136 137- (int)gridUnit 138{ 139 return gridUnit; 140} 141 142/* relative unit (mm, inch, pt) 143 */ 144- (BOOL)gridIsRelative; 145{ 146 return (gridUnit > 3) ? NO : YES; 147} 148 149//#define GRID (gridIsEnabled ? (gridSpacing ? gridSpacing : 1.0) : 1.0) 150#define GRID (gridIsEnabled ? (([self gridIsRelative]) ? gridSpacing*[self resolution] \ 151 : gridSpacing/scale) : 1.0) 152/*#define grid(point) \ 153 { (point).x = floor(((point).x / GRID) + 0.5) * GRID; \ 154 (point).y = floor(((point).y / GRID) + 0.5) * GRID; }*/ 155 156/* grid spacing including scale 157 */ 158- (float)grid 159{ 160 return GRID; 161} 162 163/* return closest point on grid 164 */ 165- (NSPoint)grid:(NSPoint)p 166{ 167 if ( gridIsEnabled ) 168 { float grid = GRID; 169 170 p = [self pointRelativeOrigin:p]; 171 p.x = floor((p.x / grid) + 0.5) * grid; 172 p.y = floor((p.y / grid) + 0.5) * grid; 173 p = [self pointAbsolute:p]; 174 } 175 return p; 176} 177 178/* 179 * converts a value from internal unit to the current unit 180 */ 181- (float)resolution 182{ 183 switch ( gridUnit ) 184 { 185 case UNIT_MM: return 72.0/25.4; 186 case UNIT_INCH: return 72.0; 187 case UNIT_POINT: return 1.0; 188 } 189 return 1.0; 190} 191 192/* we maintain a list of rectangles representing the horicontal and vertical lines of the grid. 193 * We use Rectangles because they usually draw faster than lines 194 */ 195- (void)resetGrid 196{ int x, y, i; 197 float w, h, res = [self resolution], relGrid; 198 NSZone *zone = [self zone]; 199 NSRect bounds = [self bounds]; 200 NSPoint p, offset; // start offset for grid 201 BOOL gridIsRelative = [self gridIsRelative]; 202 203 if ( (!gridIsRelative && gridSpacing < 1) || (gridIsRelative && gridSpacing*res*scale < 1) ) 204 return; 205 206 relGrid = (gridIsRelative) ? gridSpacing*res : gridSpacing/scale; 207 208 x = (int)bounds.size.width / relGrid; 209 y = (int)bounds.size.height / relGrid; 210 numGridRectsX = x + 1; 211 numGridRectsY = y + 1; 212 if (gridListX) 213 { NSZoneFree(zone, gridListX); 214 NSZoneFree(zone, gridListY); 215 } 216 gridListX = NSZoneMalloc(zone, (numGridRectsX+2) * sizeof(NSRect)); 217 gridListY = NSZoneMalloc(zone, (numGridRectsY+2) * sizeof(NSRect)); 218 w = bounds.size.width; 219 h = bounds.size.height; 220 221 p = [self pointAbsolute:NSZeroPoint]; 222 offset.x = p.x - floor(p.x / relGrid) * relGrid; 223 offset.y = p.y - floor(p.y / relGrid) * relGrid; 224 225 for (i = 0; i <= y; i++) 226 { 227 gridListY[i].origin.x = 0.0; 228 gridListY[i].origin.y = offset.y + i * relGrid; 229 gridListY[i].size.width = w; 230 gridListY[i].size.height = 0.0; 231 } 232 for (i = 0; i <= x; i++) 233 { 234 gridListX[i].origin.x = offset.x + i * relGrid; 235 gridListX[i].origin.y = 0.0; 236 gridListX[i].size.width = 0.0; 237 gridListX[i].size.height = h; 238 } 239} 240 241@end 242