1999-12-13 17:01:35 +00:00
|
|
|
|
/* GormWindowEditor.m
|
|
|
|
|
*
|
|
|
|
|
* Copyright (C) 1999 Free Software Foundation, Inc.
|
|
|
|
|
*
|
|
|
|
|
* Author: Richard Frith-Macdonald <richard@brainstrom.co.uk>
|
|
|
|
|
* Date: 1999
|
|
|
|
|
*
|
|
|
|
|
* This file is part of GNUstep.
|
|
|
|
|
*
|
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
|
* (at your option) any later version.
|
|
|
|
|
*
|
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
|
*
|
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include "GormPrivate.h"
|
|
|
|
|
|
1999-12-16 06:56:02 +00:00
|
|
|
|
static NSRect
|
|
|
|
|
NSRectFromPoints(NSPoint p0, NSPoint p1)
|
|
|
|
|
{
|
|
|
|
|
NSRect r;
|
|
|
|
|
|
|
|
|
|
if (p0.x < p1.x)
|
|
|
|
|
{
|
|
|
|
|
r.origin.x = p0.x;
|
|
|
|
|
r.size.width = p1.x - p0.x;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
r.origin.x = p1.x;
|
|
|
|
|
r.size.width = p0.x - p1.x;
|
|
|
|
|
}
|
|
|
|
|
if (p0.y < p1.y)
|
|
|
|
|
{
|
|
|
|
|
r.origin.y = p0.y;
|
|
|
|
|
r.size.height = p1.y - p0.y;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
r.origin.y = p1.y;
|
|
|
|
|
r.size.height = p0.y - p1.y;
|
|
|
|
|
}
|
|
|
|
|
return r;
|
|
|
|
|
}
|
|
|
|
|
|
1999-12-13 17:01:35 +00:00
|
|
|
|
/*
|
|
|
|
|
* Methods to return the images that should be used to display objects within
|
|
|
|
|
* the matrix containing the objects in a document.
|
|
|
|
|
*/
|
1999-12-14 17:38:17 +00:00
|
|
|
|
@implementation NSMenu (GormObjectAdditions)
|
1999-12-13 17:01:35 +00:00
|
|
|
|
- (NSImage*) imageForViewer
|
|
|
|
|
{
|
|
|
|
|
static NSImage *image = nil;
|
|
|
|
|
|
|
|
|
|
if (image == nil)
|
|
|
|
|
{
|
|
|
|
|
NSBundle *bundle = [NSBundle mainBundle];
|
|
|
|
|
NSString *path = [bundle pathForImageResource: @"GormMenu"];
|
|
|
|
|
|
|
|
|
|
image = [[NSImage alloc] initWithContentsOfFile: path];
|
|
|
|
|
}
|
|
|
|
|
return image;
|
|
|
|
|
}
|
|
|
|
|
@end
|
|
|
|
|
|
1999-12-14 17:38:17 +00:00
|
|
|
|
@implementation NSWindow (GormObjectAdditions)
|
|
|
|
|
- (NSString*) editorClassName
|
|
|
|
|
{
|
|
|
|
|
return @"GormWindowEditor";
|
|
|
|
|
}
|
1999-12-13 17:01:35 +00:00
|
|
|
|
- (NSImage*) imageForViewer
|
|
|
|
|
{
|
|
|
|
|
static NSImage *image = nil;
|
|
|
|
|
|
|
|
|
|
if (image == nil)
|
|
|
|
|
{
|
|
|
|
|
NSBundle *bundle = [NSBundle mainBundle];
|
|
|
|
|
NSString *path = [bundle pathForImageResource: @"GormWindow"];
|
|
|
|
|
|
|
|
|
|
image = [[NSImage alloc] initWithContentsOfFile: path];
|
|
|
|
|
}
|
|
|
|
|
return image;
|
|
|
|
|
}
|
|
|
|
|
@end
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Default implementations of methods used for updating a view by
|
|
|
|
|
* direct action through an editor.
|
|
|
|
|
*/
|
|
|
|
|
@implementation NSView (ViewAdditions)
|
|
|
|
|
|
|
|
|
|
- (BOOL) acceptsColor: (NSColor*)color atPoint: (NSPoint)point
|
|
|
|
|
{
|
|
|
|
|
return NO; /* Can the view accept a color drag-and-drop? */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (BOOL) allowsAltDragging
|
|
|
|
|
{
|
|
|
|
|
return NO; /* Can the view be dragged into a matrix? */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void) depositColor: (NSColor*)color atPoint: (NSPoint)point
|
|
|
|
|
{
|
|
|
|
|
/* Handle color drop in view. */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (NSSize) maximumSizeFromKnobPosition: (IBKnobPosition)knobPosition
|
|
|
|
|
{
|
|
|
|
|
NSView *s = [self superview];
|
|
|
|
|
NSRect r = (s != nil) ? [s bounds] : [self bounds];
|
|
|
|
|
|
|
|
|
|
return r.size; /* maximum resize permitted */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (NSSize) minimumSizeFromKnobPosition: (IBKnobPosition)position
|
|
|
|
|
{
|
|
|
|
|
return NSZeroSize; /* Minimum resize permitted */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void) placeView: (NSRect)newFrame
|
|
|
|
|
{
|
|
|
|
|
[self setFrame: newFrame]; /* View changed by editor. */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@interface GormWindowEditor : NSView <IBEditors>
|
|
|
|
|
{
|
|
|
|
|
id<IBDocuments> document;
|
1999-12-14 17:38:17 +00:00
|
|
|
|
NSWindow *edited;
|
|
|
|
|
NSView *original;
|
1999-12-13 17:01:35 +00:00
|
|
|
|
NSMutableArray *selection;
|
1999-12-14 17:38:17 +00:00
|
|
|
|
NSMutableArray *subeditors;
|
1999-12-13 17:01:35 +00:00
|
|
|
|
BOOL shouldBeginDrag;
|
1999-12-15 11:12:52 +00:00
|
|
|
|
BOOL isClosed;
|
1999-12-13 17:01:35 +00:00
|
|
|
|
NSPasteboard *dragPb;
|
|
|
|
|
}
|
|
|
|
|
- (BOOL) acceptsTypeFromArray: (NSArray*)types;
|
|
|
|
|
- (BOOL) activate;
|
|
|
|
|
- (id) initWithObject: (id)anObject inDocument: (id<IBDocuments>)aDocument;
|
|
|
|
|
- (void) close;
|
|
|
|
|
- (void) closeSubeditors;
|
|
|
|
|
- (void) copySelection;
|
|
|
|
|
- (void) deleteSelection;
|
|
|
|
|
- (id<IBDocuments>) document;
|
1999-12-14 17:38:17 +00:00
|
|
|
|
- (void) draggedImage: (NSImage*)i endedAt: (NSPoint)p deposited: (BOOL)f;
|
|
|
|
|
- (unsigned int) draggingSourceOperationMaskForLocal: (BOOL)flag;
|
1999-12-13 17:01:35 +00:00
|
|
|
|
- (id) editedObject;
|
|
|
|
|
- (void) makeSelectionVisible: (BOOL)flag;
|
|
|
|
|
- (id<IBEditors>) openSubeditorForObject: (id)anObject;
|
|
|
|
|
- (void) orderFront;
|
|
|
|
|
- (void) pasteInSelection;
|
|
|
|
|
- (void) resetObject: (id)anObject;
|
|
|
|
|
- (void) selectObjects: (NSArray*)objects;
|
|
|
|
|
- (void) validateEditing;
|
|
|
|
|
- (BOOL) wantsSelection;
|
|
|
|
|
- (NSWindow*) window;
|
|
|
|
|
@end
|
|
|
|
|
|
|
|
|
|
@implementation GormWindowEditor
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Intercepting events in the view and handling them
|
|
|
|
|
*/
|
|
|
|
|
- (NSView*) hitTest: (NSPoint)loc
|
|
|
|
|
{
|
1999-12-15 15:29:27 +00:00
|
|
|
|
if ([(id<IB>)NSApp isTestingInterface] == YES)
|
|
|
|
|
{
|
|
|
|
|
return [super hitTest: loc];
|
|
|
|
|
}
|
1999-12-15 21:43:57 +00:00
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
* Stop the subviews receiving events - we grab them all.
|
|
|
|
|
*/
|
|
|
|
|
if ([super hitTest: loc] != nil)
|
|
|
|
|
{
|
|
|
|
|
return self;
|
|
|
|
|
}
|
|
|
|
|
return nil;
|
|
|
|
|
}
|
1999-12-13 17:01:35 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void) mouseDown: (NSEvent*)theEvent
|
|
|
|
|
{
|
1999-12-15 15:29:27 +00:00
|
|
|
|
if ([(id<IB>)NSApp isTestingInterface] == YES)
|
|
|
|
|
{
|
|
|
|
|
[super mouseDown: theEvent];
|
|
|
|
|
return;
|
|
|
|
|
}
|
1999-12-13 17:01:35 +00:00
|
|
|
|
else
|
|
|
|
|
{
|
1999-12-15 21:43:57 +00:00
|
|
|
|
NSEnumerator *enumerator;
|
|
|
|
|
NSView *view = nil;
|
|
|
|
|
IBKnobPosition knob = IBNoneKnobPosition;
|
1999-12-16 06:56:02 +00:00
|
|
|
|
NSDate *future = [NSDate distantFuture];
|
|
|
|
|
BOOL acceptsMouseMoved;
|
|
|
|
|
NSPoint mouseDownPoint;
|
|
|
|
|
NSPoint lastPoint;
|
|
|
|
|
NSPoint point;
|
|
|
|
|
unsigned eventMask;
|
|
|
|
|
NSEvent *e;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Save window state info.
|
|
|
|
|
*/
|
|
|
|
|
acceptsMouseMoved = [[self window] acceptsMouseMovedEvents];
|
1999-12-15 21:43:57 +00:00
|
|
|
|
|
|
|
|
|
mouseDownPoint = [theEvent locationInWindow];
|
1999-12-16 06:56:02 +00:00
|
|
|
|
eventMask = NSLeftMouseDownMask | NSLeftMouseUpMask
|
|
|
|
|
| NSLeftMouseDraggedMask | NSMouseMovedMask | NSPeriodicMask;
|
|
|
|
|
[[self window] setAcceptsMouseMovedEvents: YES];
|
1999-12-15 21:43:57 +00:00
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* If our selection is not our window, it must be one or more
|
|
|
|
|
* subviews, so we need to check to see if the knob of any subview
|
|
|
|
|
* has been hit, or if a subview itsself has been hit.
|
|
|
|
|
*/
|
|
|
|
|
if ([selection lastObject] != edited)
|
|
|
|
|
{
|
|
|
|
|
enumerator = [selection objectEnumerator];
|
|
|
|
|
while ((view = [enumerator nextObject]) != nil)
|
|
|
|
|
{
|
|
|
|
|
knob = GormKnobHitInRect([view frame], mouseDownPoint);
|
|
|
|
|
if (knob != IBNoneKnobPosition)
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
* Clicked on the knob of a selected subview.
|
|
|
|
|
* If it's not the only selected view - make it so.
|
|
|
|
|
* We now expect to drag from this.
|
|
|
|
|
*/
|
|
|
|
|
if ([selection count] != 1)
|
|
|
|
|
{
|
|
|
|
|
[self selectObjects: [NSArray arrayWithObject: view]];
|
|
|
|
|
[self makeSelectionVisible: NO];
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (view == nil)
|
|
|
|
|
{
|
|
|
|
|
enumerator = [selection objectEnumerator];
|
|
|
|
|
while ((view = [enumerator nextObject]) != nil)
|
|
|
|
|
{
|
|
|
|
|
if (NSMouseInRect(mouseDownPoint, [view frame], NO) == YES)
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
* Clicked inside a selected subview.
|
|
|
|
|
*/
|
|
|
|
|
if ([theEvent modifierFlags] & NSShiftKeyMask)
|
|
|
|
|
{
|
|
|
|
|
NSMutableArray *array;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* remove this view from the selection.
|
|
|
|
|
*/
|
|
|
|
|
[self makeSelectionVisible: NO];
|
|
|
|
|
array = [NSMutableArray arrayWithArray: selection];
|
|
|
|
|
[array removeObjectIdenticalTo: view];
|
|
|
|
|
[self selectObjects: array];
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
[self makeSelectionVisible: YES];
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* If we haven't clicked in a selected subview - find out where we
|
|
|
|
|
* actually did click.
|
|
|
|
|
*/
|
|
|
|
|
if (view == nil)
|
|
|
|
|
{
|
|
|
|
|
view = [super hitTest: mouseDownPoint];
|
|
|
|
|
if (view != nil && view != self)
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
* Clicked on an unselected subview.
|
|
|
|
|
*/
|
|
|
|
|
if ([theEvent modifierFlags] & NSShiftKeyMask)
|
|
|
|
|
{
|
|
|
|
|
if ([selection lastObject] == edited
|
|
|
|
|
|| ([theEvent modifierFlags] & NSControlKeyMask))
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
* Can't extend the selection - change it to the subview.
|
|
|
|
|
*/
|
|
|
|
|
[self makeSelectionVisible: NO];
|
|
|
|
|
[self selectObjects: [NSArray arrayWithObject: view]];
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
NSMutableArray *array;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* extend the selection to include this subview.
|
|
|
|
|
*/
|
|
|
|
|
array = [NSMutableArray arrayWithArray: selection];
|
|
|
|
|
[array addObject: view];
|
|
|
|
|
[self selectObjects: array];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
* Select the new view (clear the old selection markings)
|
|
|
|
|
*/
|
|
|
|
|
[self makeSelectionVisible: NO];
|
|
|
|
|
[self selectObjects: [NSArray arrayWithObject: view]];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if ([selection indexOfObjectIdenticalTo: view] == NSNotFound)
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
* This view has just been deselected.
|
|
|
|
|
*/
|
|
|
|
|
view = nil;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (view == self)
|
|
|
|
|
{
|
1999-12-16 06:56:02 +00:00
|
|
|
|
NSGraphicsContext *ctxt = [NSGraphicsContext currentContext];
|
|
|
|
|
NSEnumerator *enumerator;
|
|
|
|
|
NSMutableArray *array;
|
|
|
|
|
NSEventType eType;
|
|
|
|
|
NSRect r;
|
|
|
|
|
|
1999-12-15 21:43:57 +00:00
|
|
|
|
/*
|
|
|
|
|
* Clicked on an window background - make window the selection.
|
|
|
|
|
*/
|
|
|
|
|
[self makeSelectionVisible: NO];
|
|
|
|
|
[self selectObjects: [NSArray arrayWithObject: edited]];
|
1999-12-16 06:56:02 +00:00
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Track mouse movements until left mouse up.
|
|
|
|
|
*/
|
|
|
|
|
lastPoint = mouseDownPoint;
|
|
|
|
|
[self lockFocus];
|
|
|
|
|
[NSEvent startPeriodicEventsAfterDelay: 0.1 withPeriod: 0.05];
|
|
|
|
|
e = [NSApp nextEventMatchingMask: eventMask
|
|
|
|
|
untilDate: future
|
|
|
|
|
inMode: NSEventTrackingRunLoopMode
|
|
|
|
|
dequeue: YES];
|
|
|
|
|
eType = [e type];
|
|
|
|
|
while (eType != NSLeftMouseUp)
|
|
|
|
|
{
|
|
|
|
|
if (eType != NSPeriodic)
|
|
|
|
|
{
|
|
|
|
|
point = [self convertPoint: [e locationInWindow]
|
|
|
|
|
fromView: nil];
|
|
|
|
|
}
|
|
|
|
|
if (eType == NSPeriodic && NSEqualPoints(point, lastPoint) == NO)
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
* Clear old box and draw new one.
|
|
|
|
|
* FIXME - there has to be a more efficient way to restore
|
|
|
|
|
* the display under the box.
|
|
|
|
|
*/
|
|
|
|
|
[[self window] disableFlushWindow];
|
|
|
|
|
r = NSRectFromPoints(lastPoint, mouseDownPoint);
|
|
|
|
|
r.origin.x--;
|
|
|
|
|
r.origin.y--;
|
|
|
|
|
r.size.width += 2;
|
|
|
|
|
r.size.height += 2;
|
|
|
|
|
[self displayRect: r];
|
|
|
|
|
r = NSRectFromPoints(point, mouseDownPoint);
|
|
|
|
|
DPSsetgray(ctxt, NSBlack);
|
|
|
|
|
DPSmoveto(ctxt, NSMinX(r), NSMinY(r));
|
|
|
|
|
DPSlineto(ctxt, NSMinX(r), NSMaxY(r));
|
|
|
|
|
DPSlineto(ctxt, NSMaxX(r), NSMaxY(r));
|
|
|
|
|
DPSlineto(ctxt, NSMaxX(r), NSMinY(r));
|
|
|
|
|
DPSlineto(ctxt, NSMinX(r), NSMinY(r));
|
|
|
|
|
DPSstroke(ctxt);
|
|
|
|
|
[[self window] enableFlushWindow];
|
|
|
|
|
[[self window] flushWindow];
|
|
|
|
|
lastPoint = point;
|
|
|
|
|
}
|
|
|
|
|
e = [NSApp nextEventMatchingMask: eventMask
|
|
|
|
|
untilDate: future
|
|
|
|
|
inMode: NSEventTrackingRunLoopMode
|
|
|
|
|
dequeue: YES];
|
|
|
|
|
eType = [e type];
|
|
|
|
|
}
|
|
|
|
|
[NSEvent stopPeriodicEvents];
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* restore the display
|
|
|
|
|
*/
|
|
|
|
|
r = NSRectFromPoints(lastPoint, mouseDownPoint);
|
|
|
|
|
r.origin.x--;
|
|
|
|
|
r.origin.y--;
|
|
|
|
|
r.size.width += 2;
|
|
|
|
|
r.size.height += 2;
|
|
|
|
|
[self displayRect: r];
|
|
|
|
|
[self unlockFocus];
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Now finally check the selected rectangle to find the views in it.
|
|
|
|
|
*/
|
|
|
|
|
point = [self convertPoint: [e locationInWindow]
|
|
|
|
|
fromView: nil];
|
|
|
|
|
r = NSRectFromPoints(point, mouseDownPoint);
|
|
|
|
|
array = [NSMutableArray arrayWithCapacity: 8];
|
|
|
|
|
enumerator = [[self subviews] objectEnumerator];
|
|
|
|
|
while ((view = [enumerator nextObject]) != nil)
|
|
|
|
|
{
|
|
|
|
|
if (NSIntersectsRect(r, [view frame]) == YES)
|
|
|
|
|
{
|
|
|
|
|
[array addObject: view];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if ([array count] > 0)
|
|
|
|
|
{
|
|
|
|
|
[self selectObjects: array];
|
|
|
|
|
}
|
1999-12-15 21:43:57 +00:00
|
|
|
|
}
|
|
|
|
|
else if (view != nil)
|
|
|
|
|
{
|
|
|
|
|
if (knob == IBNoneKnobPosition)
|
|
|
|
|
{
|
|
|
|
|
if ([theEvent modifierFlags] & NSControlKeyMask)
|
|
|
|
|
{
|
|
|
|
|
NSLog(@"Control key not yet supported");
|
|
|
|
|
/* FIXME */
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
[self makeSelectionVisible: YES];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
* Expecting to drag a handle.
|
|
|
|
|
*/
|
|
|
|
|
}
|
|
|
|
|
}
|
1999-12-16 06:56:02 +00:00
|
|
|
|
|
1999-12-15 21:43:57 +00:00
|
|
|
|
[self makeSelectionVisible: YES];
|
1999-12-16 06:56:02 +00:00
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Restore state to what it was on entry.
|
|
|
|
|
*/
|
|
|
|
|
[[self window] setAcceptsMouseMovedEvents: acceptsMouseMoved];
|
1999-12-13 17:01:35 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void) mouseDragged: (NSEvent*)theEvent
|
|
|
|
|
{
|
1999-12-15 15:29:27 +00:00
|
|
|
|
if ([(id<IB>)NSApp isTestingInterface] == YES)
|
|
|
|
|
{
|
|
|
|
|
[super mouseDown: theEvent];
|
|
|
|
|
return;
|
|
|
|
|
}
|
1999-12-13 17:01:35 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (BOOL) acceptsTypeFromArray: (NSArray*)types
|
|
|
|
|
{
|
1999-12-14 17:38:17 +00:00
|
|
|
|
/*
|
|
|
|
|
* A window editor can accept views dropped in to the window.
|
|
|
|
|
*/
|
|
|
|
|
return [types containsObject: IBViewPboardType];
|
1999-12-13 17:01:35 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (BOOL) activate
|
|
|
|
|
{
|
1999-12-14 17:38:17 +00:00
|
|
|
|
if (original == nil)
|
|
|
|
|
{
|
|
|
|
|
NSEnumerator *enumerator;
|
|
|
|
|
NSView *sub;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Swap ourselves in as a replacement for the original window
|
|
|
|
|
* content view.
|
|
|
|
|
*/
|
|
|
|
|
original = RETAIN([edited contentView]);
|
|
|
|
|
[self setFrame: [original frame]];
|
|
|
|
|
enumerator = [[original subviews] objectEnumerator];
|
|
|
|
|
while ((sub = [enumerator nextObject]) != nil)
|
|
|
|
|
{
|
|
|
|
|
[self addSubview: sub];
|
|
|
|
|
}
|
|
|
|
|
[edited setContentView: self];
|
|
|
|
|
}
|
|
|
|
|
if ([edited isKeyWindow] == NO)
|
|
|
|
|
{
|
|
|
|
|
[window makeKeyAndOrderFront: self];
|
|
|
|
|
}
|
|
|
|
|
if ([selection count] == 0)
|
|
|
|
|
{
|
|
|
|
|
[selection addObject: edited];
|
|
|
|
|
}
|
|
|
|
|
if ([(id<IB>)NSApp selectionOwner] != self)
|
|
|
|
|
{
|
|
|
|
|
[document setSelectionFromEditor: self];
|
|
|
|
|
}
|
1999-12-13 17:01:35 +00:00
|
|
|
|
return YES;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void) close
|
|
|
|
|
{
|
|
|
|
|
[self closeSubeditors];
|
1999-12-14 17:38:17 +00:00
|
|
|
|
|
|
|
|
|
if (original != nil)
|
|
|
|
|
{
|
|
|
|
|
NSEnumerator *enumerator;
|
|
|
|
|
NSView *sub;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Swap ourselves out and the original window content view in.
|
|
|
|
|
*/
|
|
|
|
|
[original setFrame: [self frame]];
|
|
|
|
|
enumerator = [[self subviews] objectEnumerator];
|
|
|
|
|
while ((sub = [enumerator nextObject]) != nil)
|
|
|
|
|
{
|
|
|
|
|
[original addSubview: sub];
|
|
|
|
|
}
|
|
|
|
|
[edited setContentView: original];
|
|
|
|
|
DESTROY(original);
|
|
|
|
|
}
|
|
|
|
|
if ([(id<IB>)NSApp selectionOwner] == self)
|
|
|
|
|
{
|
|
|
|
|
[document resignSelectionForEditor: self];
|
|
|
|
|
}
|
1999-12-15 11:12:52 +00:00
|
|
|
|
[document editor: self didCloseForObject: edited];
|
1999-12-13 17:01:35 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void) closeSubeditors
|
|
|
|
|
{
|
1999-12-14 17:38:17 +00:00
|
|
|
|
while ([subeditors count] > 0)
|
|
|
|
|
{
|
|
|
|
|
id<IBEditors> sub = [subeditors lastObject];
|
|
|
|
|
|
|
|
|
|
[sub close];
|
|
|
|
|
[subeditors removeObjectIdenticalTo: sub];
|
|
|
|
|
}
|
1999-12-13 17:01:35 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void) copySelection
|
|
|
|
|
{
|
1999-12-14 17:38:17 +00:00
|
|
|
|
switch ([selection count])
|
|
|
|
|
{
|
|
|
|
|
case 0:
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 1:
|
|
|
|
|
{
|
|
|
|
|
id obj = [selection lastObject];
|
|
|
|
|
|
|
|
|
|
if (obj == edited)
|
|
|
|
|
{
|
|
|
|
|
[document copyObject: selection
|
|
|
|
|
type: IBWindowPboardType
|
|
|
|
|
toPasteboard: [NSPasteboard generalPasteboard]];
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
[document copyObject: selection
|
|
|
|
|
type: IBViewPboardType
|
|
|
|
|
toPasteboard: [NSPasteboard generalPasteboard]];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
[document copyObjects: selection
|
|
|
|
|
type: IBViewPboardType
|
|
|
|
|
toPasteboard: [NSPasteboard generalPasteboard]];
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void) dealloc
|
|
|
|
|
{
|
1999-12-15 15:29:27 +00:00
|
|
|
|
[[NSNotificationCenter defaultCenter] removeObserver: self];
|
1999-12-14 17:38:17 +00:00
|
|
|
|
[self close];
|
|
|
|
|
RELEASE(edited);
|
|
|
|
|
RELEASE(selection);
|
|
|
|
|
RELEASE(subeditors);
|
|
|
|
|
RELEASE(document);
|
|
|
|
|
[super dealloc];
|
1999-12-13 17:01:35 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void) deleteSelection
|
|
|
|
|
{
|
1999-12-14 17:38:17 +00:00
|
|
|
|
NSArray *a = [NSArray arrayWithArray: selection];
|
|
|
|
|
unsigned c = [a count];
|
|
|
|
|
|
|
|
|
|
[selection removeAllObjects];
|
|
|
|
|
[document resignSelectionForEditor: self];
|
|
|
|
|
while (c-- > 0)
|
|
|
|
|
{
|
|
|
|
|
id obj = [a objectAtIndex: c];
|
|
|
|
|
|
|
|
|
|
[document detachObject: obj];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Dragging source protocol implementation
|
|
|
|
|
*/
|
|
|
|
|
- (void) draggedImage: (NSImage*)i endedAt: (NSPoint)p deposited: (BOOL)f
|
|
|
|
|
{
|
|
|
|
|
NSString *type = [[dragPb types] lastObject];
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Windows are an exception to the normal DnD mechanism - we create them
|
|
|
|
|
* if they are dropped anywhere except back in the pallettes view -
|
|
|
|
|
* ie. if they are dragged, but the drop fails.
|
|
|
|
|
*/
|
|
|
|
|
if (f == NO && [type isEqual: IBWindowPboardType] == YES)
|
|
|
|
|
{
|
|
|
|
|
id<IBDocuments> active = [(id<IB>)NSApp activeDocument];
|
|
|
|
|
|
|
|
|
|
if (active != nil)
|
|
|
|
|
{
|
|
|
|
|
[active pasteType: type fromPasteboard: dragPb parent: nil];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (unsigned int) draggingSourceOperationMaskForLocal: (BOOL)flag
|
|
|
|
|
{
|
|
|
|
|
return NSDragOperationCopy;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (unsigned) draggingEntered: (id<NSDraggingInfo>)sender
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
* Let the dragging source know we will copy the dragged object.
|
|
|
|
|
*/
|
|
|
|
|
return NSDragOperationCopy;;
|
1999-12-13 17:01:35 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void) drawSelection
|
|
|
|
|
{
|
1999-12-15 21:43:57 +00:00
|
|
|
|
if ([selection count] > 0 && [selection lastObject] != edited)
|
|
|
|
|
{
|
|
|
|
|
NSEnumerator *enumerator = [selection objectEnumerator];
|
|
|
|
|
NSView *view;
|
|
|
|
|
|
|
|
|
|
[self lockFocus];
|
|
|
|
|
while ((view = [enumerator nextObject]) != nil)
|
|
|
|
|
{
|
|
|
|
|
GormDrawKnobsForRect([view frame]);
|
|
|
|
|
}
|
|
|
|
|
GormShowFastKnobFills();
|
|
|
|
|
[self unlockFocus];
|
|
|
|
|
}
|
1999-12-13 17:01:35 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (id<IBDocuments>) document
|
|
|
|
|
{
|
|
|
|
|
return document;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (id) editedObject
|
|
|
|
|
{
|
|
|
|
|
return edited;
|
|
|
|
|
}
|
|
|
|
|
|
1999-12-14 17:38:17 +00:00
|
|
|
|
- (id) initWithObject: (id)anObject inDocument: (id<IBDocuments>)aDocument
|
|
|
|
|
{
|
|
|
|
|
NSWindow *win = (NSWindow*)anObject;
|
|
|
|
|
NSView *cv = [win contentView];
|
|
|
|
|
NSView *sub;
|
|
|
|
|
NSEnumerator *enumerator;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Initialize with current window content frame, move window subviews to
|
|
|
|
|
* self, and replace window content view with self.
|
|
|
|
|
*/
|
|
|
|
|
if ((self = [super initWithFrame: [cv frame]]) == nil)
|
|
|
|
|
return nil;
|
|
|
|
|
original = RETAIN(cv);
|
|
|
|
|
enumerator = [[original subviews] objectEnumerator];
|
|
|
|
|
while ((sub = [enumerator nextObject]) != nil)
|
|
|
|
|
{
|
|
|
|
|
[self addSubview: sub];
|
|
|
|
|
}
|
|
|
|
|
[win setContentView: self];
|
|
|
|
|
|
|
|
|
|
ASSIGN(document, aDocument);
|
|
|
|
|
ASSIGN(edited, anObject);
|
|
|
|
|
selection = [NSMutableArray new];
|
|
|
|
|
[selection addObject: edited];
|
|
|
|
|
subeditors = [NSMutableArray new];
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Permit views to be dragged in to the window.
|
|
|
|
|
*/
|
|
|
|
|
[self registerForDraggedTypes: [NSArray arrayWithObjects:
|
|
|
|
|
IBViewPboardType, nil]];
|
|
|
|
|
|
|
|
|
|
return self;
|
|
|
|
|
}
|
|
|
|
|
|
1999-12-13 17:01:35 +00:00
|
|
|
|
- (void) makeSelectionVisible: (BOOL)flag
|
|
|
|
|
{
|
1999-12-15 21:43:57 +00:00
|
|
|
|
if (flag == NO)
|
|
|
|
|
{
|
|
|
|
|
if ([selection count] > 0 && [selection lastObject] != edited)
|
|
|
|
|
{
|
|
|
|
|
NSEnumerator *enumerator = [selection objectEnumerator];
|
1999-12-16 06:56:02 +00:00
|
|
|
|
NSView *view;
|
1999-12-15 21:43:57 +00:00
|
|
|
|
|
|
|
|
|
[[self window] disableFlushWindow];
|
|
|
|
|
while ((view = [enumerator nextObject]) != nil)
|
|
|
|
|
{
|
|
|
|
|
NSRect rect = GormExtBoundsForRect([view frame]);
|
|
|
|
|
|
|
|
|
|
[self displayRect: rect];
|
|
|
|
|
}
|
|
|
|
|
[[self window] enableFlushWindow];
|
1999-12-16 06:56:02 +00:00
|
|
|
|
[[self window] flushWindowIfNeeded];
|
1999-12-15 21:43:57 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
[self drawSelection];
|
|
|
|
|
[[self window] flushWindow];
|
|
|
|
|
}
|
1999-12-13 17:01:35 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (id<IBEditors>) openSubeditorForObject: (id)anObject
|
|
|
|
|
{
|
1999-12-14 17:38:17 +00:00
|
|
|
|
id<IBEditors> sub;
|
|
|
|
|
|
|
|
|
|
sub = [document editorForObject: anObject inEditor: self create: YES];
|
|
|
|
|
/*
|
|
|
|
|
* If we don't already have this subeditor, make a note of it so we
|
|
|
|
|
* can close it later.
|
|
|
|
|
*/
|
|
|
|
|
if ([subeditors indexOfObjectIdenticalTo: sub] == NSNotFound)
|
|
|
|
|
{
|
|
|
|
|
[subeditors addObject: sub];
|
|
|
|
|
}
|
|
|
|
|
return sub;
|
1999-12-13 17:01:35 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void) orderFront
|
|
|
|
|
{
|
1999-12-14 17:38:17 +00:00
|
|
|
|
[edited orderFront: self];
|
1999-12-13 17:01:35 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void) pasteInSelection
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
1999-12-14 17:38:17 +00:00
|
|
|
|
- (BOOL) performDragOperation: (id<NSDraggingInfo>)sender
|
|
|
|
|
{
|
1999-12-14 20:20:41 +00:00
|
|
|
|
NSPoint loc = [sender draggedImageLocation];
|
1999-12-14 17:38:17 +00:00
|
|
|
|
NSPasteboard *pb = [sender draggingPasteboard];
|
|
|
|
|
NSArray *views;
|
|
|
|
|
NSEnumerator *enumerator;
|
|
|
|
|
NSView *sub;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Ask the document to get the dragged views from the pasteboard and add
|
|
|
|
|
* them to it's collection of known objects.
|
|
|
|
|
*/
|
|
|
|
|
views = [document pasteType: IBViewPboardType
|
|
|
|
|
fromPasteboard: pb
|
|
|
|
|
parent: edited];
|
|
|
|
|
/*
|
|
|
|
|
* Now make all the views subviews of ourself, setting their origin to be
|
1999-12-14 20:20:41 +00:00
|
|
|
|
* the point at which they were dropped (converted from window coordinates
|
|
|
|
|
* to our own coordinates).
|
1999-12-14 17:38:17 +00:00
|
|
|
|
*/
|
|
|
|
|
loc = [self convertPoint: loc fromView: nil];
|
|
|
|
|
enumerator = [views objectEnumerator];
|
|
|
|
|
while ((sub = [enumerator nextObject]) != nil)
|
|
|
|
|
{
|
|
|
|
|
NSRect rect = [sub frame];
|
|
|
|
|
|
|
|
|
|
rect.origin = loc;
|
|
|
|
|
[sub setFrame: rect];
|
|
|
|
|
[self addSubview: sub];
|
|
|
|
|
}
|
|
|
|
|
return YES;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (BOOL) prepareForDragOperation: (id<NSDraggingInfo>)sender
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
* Tell the source that we will accept the drop.
|
|
|
|
|
*/
|
|
|
|
|
return YES;
|
|
|
|
|
}
|
|
|
|
|
|
1999-12-13 17:01:35 +00:00
|
|
|
|
- (void) resetObject: (id)anObject
|
|
|
|
|
{
|
1999-12-15 21:43:57 +00:00
|
|
|
|
[self display];
|
1999-12-13 17:01:35 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void) selectObjects: (NSArray*)anArray
|
|
|
|
|
{
|
1999-12-14 17:38:17 +00:00
|
|
|
|
if (anArray != selection)
|
|
|
|
|
{
|
|
|
|
|
[selection removeAllObjects];
|
|
|
|
|
[selection addObjectsFromArray: anArray];
|
|
|
|
|
if ([selection indexOfObjectIdenticalTo: edited] != NSNotFound)
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
* we have selected our edited window ... we can't have anything
|
|
|
|
|
* else selected at the same time.
|
|
|
|
|
*/
|
|
|
|
|
if ([selection count] > 0)
|
|
|
|
|
{
|
|
|
|
|
[selection removeAllObjects];
|
|
|
|
|
[selection addObject: edited];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
unsigned count = [selection count];
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* We can only select views that are direct subviews - discard others.
|
|
|
|
|
*/
|
|
|
|
|
while (count-- > 0)
|
|
|
|
|
{
|
|
|
|
|
id o = [selection objectAtIndex: count];
|
|
|
|
|
|
|
|
|
|
if ([[self subviews] indexOfObjectIdenticalTo: o] == NSNotFound)
|
|
|
|
|
{
|
|
|
|
|
[selection removeObjectAtIndex: count];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/*
|
|
|
|
|
* Now we must let the document (and hence the rest of the app) know about
|
|
|
|
|
* our new selection.
|
|
|
|
|
*/
|
|
|
|
|
[document setSelectionFromEditor: self];
|
1999-12-13 17:01:35 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (NSArray*) selection
|
|
|
|
|
{
|
1999-12-14 17:38:17 +00:00
|
|
|
|
return [NSArray arrayWithArray: selection];
|
1999-12-13 17:01:35 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (unsigned) selectionCount
|
|
|
|
|
{
|
|
|
|
|
return [selection count];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void) validateEditing
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (BOOL) wantsSelection
|
|
|
|
|
{
|
1999-12-14 17:38:17 +00:00
|
|
|
|
/*
|
|
|
|
|
* We only want to be the selection owner if we are active (have been
|
|
|
|
|
* swapped for the windows original content view) and if we have some
|
|
|
|
|
* object selected.
|
|
|
|
|
*/
|
|
|
|
|
if (original == nil)
|
|
|
|
|
return NO;
|
|
|
|
|
if ([selection count] == 0)
|
|
|
|
|
return NO;
|
|
|
|
|
return YES;
|
1999-12-13 17:01:35 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (NSWindow*) window
|
|
|
|
|
{
|
1999-12-14 17:38:17 +00:00
|
|
|
|
return [super window];
|
1999-12-13 17:01:35 +00:00
|
|
|
|
}
|
|
|
|
|
@end
|