1/* dvTile.m
2 * DocView addition for batch production
3 *
4 * Copyright (C) 1996-2011 by vhf interservice GmbH
5 * Author:   Georg Fleischmann
6 *
7 * created:  1996-05-10
8 * modified: 2011-09-08 (-setTileWithLimits:, -buildTileCopies: sort sequence from down to up to down)
9 *           2008-07-24 (Prefs_IncrementSerial removed in -incrementSerialNumbers)
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the vhf Public License as
13 * published by vhf interservice GmbH. Among other things, the
14 * License requires that the copyright notices and this notice
15 * be preserved on all copies.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
20 * See the vhf Public License for more details.
21 *
22 * You should have received a copy of the vhf Public License along
23 * with this program; see the file LICENSE. If not, write to vhf.
24 *
25 * vhf interservice GmbH, Im Marxle 3, 72119 Altingen, Germany
26 * eMail: info@vhf.de
27 * http://www.vhf.de
28 */
29
30#include <AppKit/AppKit.h>
31#include "DocView.h"
32#include "TilePanel.h"
33#include "TileObject.h"
34#include "PreferencesMacros.h"
35
36@implementation DocView(Tile)
37
38- (NSMutableArray*)tileOriginList	{ return tileOriginList; }
39- (BOOL)tileLimitSize			{ return tileLimitSize; }
40- (NSPoint)tileDistance			{ return tileDistance; }
41//- (NSPoint)useAbsoluteDistance		{ return useAbsoluteDistance; }
42- (NSPoint)tileLimits			{ return tileLimits; }
43//- (BOOL)mustMoveMasterToOrigin	{ return moveMasterToOrigin; }
44
45- (int)numberOfTiles
46{   int	xCnt, yCnt;
47
48    if (tileLimitSize)
49    {   NSRect	rect = [self tileBounds];
50
51        xCnt = tileLimits.x / (rect.size.width  + tileDistance.x);
52        yCnt = tileLimits.y / (rect.size.height + tileDistance.y);
53    }
54    else
55    {
56        xCnt = tileLimits.x;
57        yCnt = tileLimits.y;
58    }
59    return xCnt * yCnt;
60}
61
62
63/*
64 * limits    the size or number of items in x/y direction
65 * distance  the distance between tiles
66 *
67 * modified: 2005-10-15
68 */
69- (void)setTileWithLimits:(NSPoint)limits
70                limitSize:(BOOL)limitSize
71                 distance:(NSPoint)dist
72             moveToOrigin:(BOOL)moveToOrigin
73{   NSRect	rect;
74    int		l, x, xCnt, y, yCnt;
75    BOOL	setDirty = NO;
76    NSPoint	pOrigin = [origin pointWithNum:0], pMaster;
77
78    if (tileDistance.x != dist.x || tileDistance.y != dist.y)
79    {   setDirty = YES;
80        tileDistance = dist;
81    }
82    if (tileLimits.x != limits.x || tileLimits.y != limits.y)
83    {   setDirty = YES;
84        tileLimits = limits;
85    }
86    if (tileLimitSize != limitSize)
87    {   setDirty = YES;
88        tileLimitSize = limitSize;
89    }
90    [self serialNumber];	// determine serial number
91    rect = [self tileBounds];
92
93    if (!tileLimits.x || !tileLimits.y)
94    {
95        [tileOriginList release];
96        tileOriginList = nil;
97        return;
98    }
99
100    [tileOriginList release];
101    tileOriginList = [[NSMutableArray allocWithZone:[self zone]] init];
102
103    /* move master to lower/left position
104     */
105    if ( moveToOrigin &&
106         (rect.origin.x != tileDistance.x || rect.origin.y != tileDistance.y) )
107    {	NSPoint	p;
108        int	i;
109
110        p.x = pOrigin.x - rect.origin.x;
111        p.y = pOrigin.y - rect.origin.y;
112        //p.x = tileDistance.x - rect.origin.x;
113        //p.y = tileDistance.y - rect.origin.y;
114        for (l=[layerList count]-1; l>=0; l--)
115        {   NSMutableArray	*list = [[layerList objectAtIndex:l] list];
116
117            if ( ![[layerList objectAtIndex:l] useForTile] )
118                continue;
119            for (i=[list count]-1; i>=0; i--)
120                [[list objectAtIndex:i] moveBy:p];
121        }
122    }
123
124    if (setDirty)
125    {
126        for ( l=[layerList count]-1; l>=0; l-- )
127            if ( [[layerList objectAtIndex:l] useForTile] )
128                [[layerList objectAtIndex:l] setDirty:YES];
129        [document setDirty:YES];
130    }
131
132    /* create tileOriginList */
133    pMaster = [self tileBounds].origin;
134    xCnt = (int)(tileLimitSize) ? (limits.x/(rect.size.width  + tileDistance.x)) : limits.x;
135    yCnt = (int)(tileLimitSize) ? (limits.y/(rect.size.height + tileDistance.y)) : limits.y;
136    for ( x=0; x<xCnt; x++)
137    {
138        //for (y=0; y<yCnt; y++)
139        for ( (Even(x)) ? (y=0) : (y=yCnt-1); (Even(x)) ? (y<yCnt) : (y>=0); (Even(x)) ? (y++) : (y--) )
140        {   TileObject	*obj;
141            NSPoint	p;
142
143            obj = [[TileObject allocWithZone:[self zone]] autorelease];
144            p.x = pMaster.x/*tileDistance.x*/ + x * (rect.size.width +tileDistance.x);
145            p.y = pMaster.y/*tileDistance.y*/ + y * (rect.size.height+tileDistance.y);
146            [obj setPosition:p];
147            [tileOriginList addObject:obj];
148        }
149    }
150
151    /* increase working area, if necessary */
152    {   NSSize	size, frameSize = [self frame].size;
153
154        size = NSMakeSize(xCnt*(rect.size.width +tileDistance.x), yCnt*(rect.size.height+tileDistance.y));
155        [self setFrameSize:NSMakeSize(Max(frameSize.width,  size.width*scale),
156                                      Max(frameSize.height, size.height*scale))];
157    }
158
159    [self drawAndDisplay];
160}
161
162- (void)removeTiles
163{   int	l;
164
165    for ( l=[layerList count]-1; l>=0; l-- )
166        if ( [[layerList objectAtIndex:l] useForTile] )
167            [[layerList objectAtIndex:l] setDirty:YES];
168    [document setDirty:YES];
169
170    [tileOriginList removeAllObjects];
171    [tileOriginList release];
172    tileOriginList = nil;
173
174    [self drawAndDisplay];
175}
176
177/* modified: 2005-10-15
178 */
179- (void)buildTileCopies:(NSPoint)limits
180              limitSize:(BOOL)limitSize
181               distance:(NSPoint)dist
182           moveToOrigin:(BOOL)moveToOrigin
183{   NSRect		rect;
184    int			i, iCnt, l, x, xCnt, y, yCnt, copyCnt = 1;
185    NSMutableArray	*masterIndexes = [NSMutableArray array];
186    NSPoint		pOrigin = [origin pointWithNum:0];
187
188    tileDistance           = dist;
189    //tileAbsoluteDistance   = absoluteDistance;
190    tileLimits             = limits;
191    tileLimitSize          = limitSize;
192    //tileMoveMasterToOrigin = moveToOrigin;
193    [self serialNumber];
194    rect = [self tileBounds];
195
196    [tileOriginList release];
197    tileOriginList = nil;
198
199    /* move master to lower/left position (crosshair origin)
200     */
201    if ( moveToOrigin &&
202         (rect.origin.x != tileDistance.x || rect.origin.y != tileDistance.y) )
203    {	NSPoint	p;
204
205        p.x = pOrigin.x - rect.origin.x;
206        p.y = pOrigin.y - rect.origin.y;
207        //p.x = tileDistance.x - rect.origin.x;
208        //p.y = tileDistance.y - rect.origin.y;
209        for (l=[layerList count]-1; l>=0; l--)
210        {   NSMutableArray	*list = [[layerList objectAtIndex:l] list];
211
212            if ( ![[layerList objectAtIndex:l] useForTile] )
213                continue;
214            for (i=[list count]-1; i>=0; i--)
215                [[list objectAtIndex:i] moveBy:p];
216        }
217    }
218
219    [document setDirty:YES];
220
221    /* remember master indexes */
222    for (l=0; l<(int)[layerList count]; l++)
223        [masterIndexes addObject:[NSNumber numberWithInt:[[[layerList objectAtIndex:l] list] count]]];
224
225    xCnt = (int)(tileLimitSize) ? (limits.x/(rect.size.width  + tileDistance.x)) : limits.x;
226    yCnt = (int)(tileLimitSize) ? (limits.y/(rect.size.height + tileDistance.y)) : limits.y;
227    for ( x=0; x<xCnt; x++ )
228    {
229        //for ( y=0; y<yCnt; y++ )
230        for ( (Even(x)) ? (y=0) : (y=yCnt-1); (Even(x)) ? (y<yCnt) : (y>=0); (Even(x)) ? (y++) : (y--) )
231        {   NSPoint	p;
232
233            if ( !x && !y )
234                continue;
235            p.x = x * (rect.size.width +tileDistance.x);
236            p.y = y * (rect.size.height+tileDistance.y);
237            for (l=[layerList count]-1; l>=0; l--)
238            {   LayerObject	*layer = [layerList objectAtIndex:l];
239                NSMutableArray	*slist = [slayList objectAtIndex:l];
240
241                if ( ![[layerList objectAtIndex:l] useForTile] )
242                    continue;
243                for (i=0, iCnt=[[masterIndexes objectAtIndex:l] intValue]; i<iCnt; i++)
244                {   id	g = [[[[layer list] objectAtIndex:i] copy] autorelease];
245
246                    if ( [g respondsToSelector:@selector(isSerialNumber)] && [g isSerialNumber] )
247                        [g incrementSerialNumberBy:copyCnt];
248                    [g moveBy:p];
249                    [layer addObjectWithoutCheck:g];	// faster
250                    if ( [g isSelected] )
251                        [slist addObject:g];
252                }
253            }
254            copyCnt++;
255        }
256    }
257
258    /* increase working area, if necessary */
259    {   NSSize	size, frameSize = [self frame].size;
260
261        size = NSMakeSize(xCnt*(rect.size.width +tileDistance.x), yCnt*(rect.size.height+tileDistance.y));
262        [self setFrameSize:NSMakeSize(Max(frameSize.width,  size.width*scale),
263                                      Max(frameSize.height, size.height*scale))];
264    }
265
266    if ( [self window] && [[self window] windowNumber] >= 0 )
267        [self drawAndDisplay];
268}
269
270/* get the serial number
271 */
272- (id)serialNumber
273{   int	l, i;
274
275    serialNumber = nil;
276    for (l=[layerList count]-1; l>=0; l--)
277    {	NSMutableArray	*list = [[layerList objectAtIndex:l] list];
278
279        if ( ![[layerList objectAtIndex:l] useForTile] )
280            continue;
281        for (i=[list count]-1; i>=0; i--)
282        {   id	g = [list objectAtIndex:i];
283
284            if ( [g respondsToSelector:@selector(isSerialNumber)] && [g isSerialNumber] )
285            {	serialNumber = g;
286                l = 0;
287                break;
288            }
289        }
290    }
291    return serialNumber;
292}
293
294- (void)incrementSerialNumbers
295{   int	cnt = 1;
296
297    if (tileOriginList)
298        cnt = [self numberOfTiles];
299
300    [[self serialNumber] incrementSerialNumberBy:cnt];
301
302    [document setDirty:YES];
303    [self drawAndDisplay];
304}
305
306- (NSRect)tileBounds
307{   int		l;
308    NSRect	bRect = NSZeroRect, rect;
309
310    tileSize.width = tileSize.height = 0.0;
311    for (l=[layerList count]-1; l>=0; l--)
312    {	NSMutableArray	*list = [[layerList objectAtIndex:l] list];
313
314        if ( ![[layerList objectAtIndex:l] useForTile] )
315            continue;
316        rect = [self coordBoundsOfArray:list];
317        if (rect.origin.x || rect.origin.y || rect.size.width || rect.size.height)
318            bRect = (!bRect.size.width && !bRect.size.height) ? rect : VHFUnionRect(rect, bRect);
319    }
320
321    tileSize = bRect.size;
322    return bRect;
323}
324
325@end
326