2000-01-07 06:47:08 +00:00
|
|
|
|
/* GormMenuEditor.m
|
|
|
|
|
*
|
|
|
|
|
* Copyright (C) 2000 Free Software Foundation, Inc.
|
|
|
|
|
*
|
|
|
|
|
* Author: Richard Frith-Macdonald <richard@brainstrom.co.uk>
|
|
|
|
|
* Date: 2000
|
|
|
|
|
*
|
|
|
|
|
* 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"
|
|
|
|
|
|
2000-01-13 21:19:03 +00:00
|
|
|
|
@implementation NSMenu (GormObjectAdditions)
|
|
|
|
|
- (NSString*) editorClassName
|
2000-01-07 06:47:08 +00:00
|
|
|
|
{
|
2000-01-13 21:19:03 +00:00
|
|
|
|
return @"GormMenuEditor";
|
|
|
|
|
}
|
|
|
|
|
/*
|
|
|
|
|
* Method to return the image that should be used to display menus within
|
|
|
|
|
* the matrix containing the objects in a document.
|
|
|
|
|
*/
|
|
|
|
|
- (NSImage*) imageForViewer
|
|
|
|
|
{
|
|
|
|
|
static NSImage *image = nil;
|
2000-01-07 06:47:08 +00:00
|
|
|
|
|
2000-01-13 21:19:03 +00:00
|
|
|
|
if (image == nil)
|
2000-01-07 06:47:08 +00:00
|
|
|
|
{
|
2000-01-13 21:19:03 +00:00
|
|
|
|
NSBundle *bundle = [NSBundle mainBundle];
|
|
|
|
|
NSString *path = [bundle pathForImageResource: @"GormMenu"];
|
|
|
|
|
|
|
|
|
|
image = [[NSImage alloc] initWithContentsOfFile: path];
|
2000-01-07 06:47:08 +00:00
|
|
|
|
}
|
2000-01-13 21:19:03 +00:00
|
|
|
|
return image;
|
2000-01-07 06:47:08 +00:00
|
|
|
|
}
|
2000-01-13 21:19:03 +00:00
|
|
|
|
@end
|
2000-01-07 06:47:08 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2000-01-13 21:19:03 +00:00
|
|
|
|
@interface GormMenuEditor : NSMenuView <IBEditors>
|
2000-01-07 06:47:08 +00:00
|
|
|
|
{
|
|
|
|
|
id<IBDocuments> document;
|
|
|
|
|
NSMenu *edited;
|
2000-01-13 21:19:03 +00:00
|
|
|
|
id original;
|
|
|
|
|
NSMenuView *rep;
|
2000-01-07 06:47:08 +00:00
|
|
|
|
NSMutableArray *selection;
|
2000-01-13 21:19:03 +00:00
|
|
|
|
id subeditor;
|
2000-01-07 06:47:08 +00:00
|
|
|
|
BOOL isLinkSource;
|
|
|
|
|
BOOL isClosed;
|
|
|
|
|
NSPasteboard *dragPb;
|
|
|
|
|
NSString *dragType;
|
|
|
|
|
}
|
|
|
|
|
- (BOOL) acceptsTypeFromArray: (NSArray*)types;
|
|
|
|
|
- (BOOL) activate;
|
|
|
|
|
- (id) initWithObject: (id)anObject inDocument: (id<IBDocuments>)aDocument;
|
|
|
|
|
- (void) close;
|
|
|
|
|
- (void) closeSubeditors;
|
|
|
|
|
- (void) copySelection;
|
|
|
|
|
- (void) deactivate;
|
|
|
|
|
- (void) deleteSelection;
|
|
|
|
|
- (id<IBDocuments>) document;
|
|
|
|
|
- (void) draggedImage: (NSImage*)i endedAt: (NSPoint)p deposited: (BOOL)f;
|
|
|
|
|
- (unsigned int) draggingSourceOperationMaskForLocal: (BOOL)flag;
|
|
|
|
|
- (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 GormMenuEditor
|
|
|
|
|
|
|
|
|
|
- (BOOL) acceptsFirstMouse: (NSEvent*)theEvent
|
|
|
|
|
{
|
|
|
|
|
return YES;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void) encodeWithCoder: (NSCoder*)aCoder
|
|
|
|
|
{
|
|
|
|
|
[NSException raise: NSInternalInconsistencyException
|
|
|
|
|
format: @"Argh - encoding menu editor"];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Intercepting events in the view and handling them
|
|
|
|
|
*/
|
|
|
|
|
- (NSView*) hitTest: (NSPoint)loc
|
|
|
|
|
{
|
2000-01-13 21:19:03 +00:00
|
|
|
|
/*
|
|
|
|
|
* We grab all events in the window.
|
|
|
|
|
*/
|
|
|
|
|
if ([super hitTest: loc] != nil)
|
2000-01-07 06:47:08 +00:00
|
|
|
|
{
|
2000-01-13 21:19:03 +00:00
|
|
|
|
return self;
|
2000-01-07 06:47:08 +00:00
|
|
|
|
}
|
2000-01-13 21:19:03 +00:00
|
|
|
|
return nil;
|
2000-01-07 06:47:08 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void) mouseDown: (NSEvent*)theEvent
|
|
|
|
|
{
|
2000-01-13 21:19:03 +00:00
|
|
|
|
NSPoint loc = [theEvent locationInWindow];
|
|
|
|
|
NSView *hit = [super hitTest: loc];
|
2000-01-07 06:47:08 +00:00
|
|
|
|
|
2000-01-13 21:19:03 +00:00
|
|
|
|
if (hit == rep)
|
|
|
|
|
{
|
|
|
|
|
int pos = [rep indexOfItemAtPoint: loc];
|
2000-01-07 06:47:08 +00:00
|
|
|
|
|
2000-01-13 21:19:03 +00:00
|
|
|
|
NSLog(@"Mouse down on item %d", pos);
|
|
|
|
|
if (pos >= 0)
|
2000-01-07 06:47:08 +00:00
|
|
|
|
{
|
2000-01-13 21:19:03 +00:00
|
|
|
|
NSMenuItem *item = [edited itemAtIndex: pos];
|
2000-01-07 06:47:08 +00:00
|
|
|
|
|
2000-01-13 21:19:03 +00:00
|
|
|
|
[self makeSelectionVisible: NO];
|
|
|
|
|
if ([theEvent modifierFlags] & NSShiftKeyMask)
|
2000-01-07 06:47:08 +00:00
|
|
|
|
{
|
2000-01-13 21:19:03 +00:00
|
|
|
|
NSMutableArray *array;
|
2000-01-07 06:47:08 +00:00
|
|
|
|
|
2000-01-13 21:19:03 +00:00
|
|
|
|
array = [NSMutableArray arrayWithArray: selection];
|
|
|
|
|
if ([array containsObject: item] == YES)
|
2000-01-07 06:47:08 +00:00
|
|
|
|
{
|
2000-01-13 21:19:03 +00:00
|
|
|
|
[array removeObject: item];
|
2000-01-07 06:47:08 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2000-01-13 21:19:03 +00:00
|
|
|
|
[array addObject: item];
|
2000-01-07 06:47:08 +00:00
|
|
|
|
}
|
2000-01-13 21:19:03 +00:00
|
|
|
|
[self selectObjects: array];
|
2000-01-07 06:47:08 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2000-01-13 21:19:03 +00:00
|
|
|
|
[self selectObjects: [NSArray arrayWithObject: item]];
|
|
|
|
|
if ([theEvent modifierFlags] & NSControlKeyMask)
|
2000-01-07 06:47:08 +00:00
|
|
|
|
{
|
2000-01-13 21:19:03 +00:00
|
|
|
|
NSPoint dragPoint = [theEvent locationInWindow];
|
|
|
|
|
NSPasteboard *pb;
|
|
|
|
|
NSString *name = [document nameForObject: item];
|
|
|
|
|
|
|
|
|
|
pb = [NSPasteboard pasteboardWithName: NSDragPboard];
|
|
|
|
|
[pb declareTypes:
|
|
|
|
|
[NSArray arrayWithObject: GormLinkPboardType]
|
|
|
|
|
owner: self];
|
|
|
|
|
[pb setString: name forType: GormLinkPboardType];
|
|
|
|
|
[NSApp displayConnectionBetween: item and: nil];
|
|
|
|
|
|
|
|
|
|
isLinkSource = YES;
|
|
|
|
|
[self dragImage: [NSApp linkImage]
|
|
|
|
|
at: dragPoint
|
|
|
|
|
offset: NSZeroSize
|
|
|
|
|
event: theEvent
|
|
|
|
|
pasteboard: pb
|
|
|
|
|
source: self
|
|
|
|
|
slideBack: YES];
|
|
|
|
|
isLinkSource = NO;
|
2000-01-07 06:47:08 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2000-01-13 21:19:03 +00:00
|
|
|
|
[self makeSelectionVisible: YES];
|
2000-01-07 06:47:08 +00:00
|
|
|
|
}
|
2000-01-13 21:19:03 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
* The mouse down wasn't over the menu items, so we just let the menu
|
|
|
|
|
* handle it.
|
|
|
|
|
*/
|
|
|
|
|
[hit mouseDown: theEvent];
|
2000-01-07 06:47:08 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (BOOL) acceptsTypeFromArray: (NSArray*)types
|
|
|
|
|
{
|
|
|
|
|
/*
|
2000-01-13 21:19:03 +00:00
|
|
|
|
* A menu editor can accept menu items pasted in to it.
|
2000-01-07 06:47:08 +00:00
|
|
|
|
*/
|
|
|
|
|
return [types containsObject: IBMenuPboardType];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (BOOL) activate
|
|
|
|
|
{
|
|
|
|
|
NSAssert(isClosed == NO, NSInternalInconsistencyException);
|
|
|
|
|
if (original == nil)
|
|
|
|
|
{
|
2000-01-13 21:19:03 +00:00
|
|
|
|
NSWindow *w;
|
2000-01-07 06:47:08 +00:00
|
|
|
|
NSEnumerator *enumerator;
|
|
|
|
|
NSView *sub;
|
2000-01-13 23:34:12 +00:00
|
|
|
|
NSMenuItem *item;
|
2000-01-07 06:47:08 +00:00
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Swap ourselves in as a replacement for the original window
|
|
|
|
|
* content view.
|
|
|
|
|
*/
|
2000-01-13 21:19:03 +00:00
|
|
|
|
w = [rep window];
|
|
|
|
|
original = RETAIN([w contentView]);
|
2000-01-07 06:47:08 +00:00
|
|
|
|
[self setFrame: [original frame]];
|
|
|
|
|
enumerator = [[original subviews] objectEnumerator];
|
|
|
|
|
while ((sub = [enumerator nextObject]) != nil)
|
|
|
|
|
{
|
|
|
|
|
[self addSubview: sub];
|
|
|
|
|
}
|
2000-01-13 21:19:03 +00:00
|
|
|
|
[w setContentView: self];
|
2000-01-13 23:34:12 +00:00
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Line up submenu with parent menu.
|
|
|
|
|
*/
|
|
|
|
|
item = [document parentOfObject: edited];
|
|
|
|
|
if (item != nil)
|
|
|
|
|
{
|
|
|
|
|
NSMenu *parent = [document parentOfObject: item];
|
|
|
|
|
NSRect frame = [[[parent menuRepresentation] window] frame];
|
|
|
|
|
NSPoint tl;
|
|
|
|
|
|
|
|
|
|
tl = frame.origin;
|
|
|
|
|
tl.x += frame.size.width;
|
|
|
|
|
tl.y += frame.size.height;
|
|
|
|
|
[edited sizeToFit];
|
|
|
|
|
[[[edited menuRepresentation] window] setFrameTopLeftPoint: tl];
|
|
|
|
|
}
|
|
|
|
|
|
2000-01-13 21:19:03 +00:00
|
|
|
|
[edited display];
|
2000-01-07 06:47:08 +00:00
|
|
|
|
return NO;
|
|
|
|
|
}
|
|
|
|
|
return YES;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void) close
|
|
|
|
|
{
|
|
|
|
|
NSAssert(isClosed == NO, NSInternalInconsistencyException);
|
|
|
|
|
isClosed = YES;
|
|
|
|
|
[[NSNotificationCenter defaultCenter] removeObserver: self];
|
|
|
|
|
|
|
|
|
|
[self makeSelectionVisible: NO];
|
|
|
|
|
if ([(id<IB>)NSApp selectionOwner] == self)
|
|
|
|
|
{
|
|
|
|
|
[document resignSelectionForEditor: self];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[self closeSubeditors];
|
|
|
|
|
|
|
|
|
|
[self deactivate];
|
|
|
|
|
|
2000-01-13 21:19:03 +00:00
|
|
|
|
[edited close];
|
|
|
|
|
|
2000-01-07 06:47:08 +00:00
|
|
|
|
[document editor: self didCloseForObject: edited];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void) closeSubeditors
|
|
|
|
|
{
|
2000-01-13 21:19:03 +00:00
|
|
|
|
if (subeditor != nil)
|
2000-01-07 06:47:08 +00:00
|
|
|
|
{
|
2000-01-13 21:19:03 +00:00
|
|
|
|
[subeditor close];
|
|
|
|
|
DESTROY(subeditor);
|
2000-01-07 06:47:08 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void) copySelection
|
|
|
|
|
{
|
|
|
|
|
if ([selection count] > 0)
|
|
|
|
|
{
|
|
|
|
|
[document copyObjects: selection
|
2000-01-13 21:19:03 +00:00
|
|
|
|
type: IBMenuPboardType
|
2000-01-07 06:47:08 +00:00
|
|
|
|
toPasteboard: [NSPasteboard generalPasteboard]];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void) deactivate
|
|
|
|
|
{
|
|
|
|
|
if (original != nil)
|
|
|
|
|
{
|
|
|
|
|
NSEnumerator *enumerator;
|
|
|
|
|
NSView *sub;
|
|
|
|
|
|
|
|
|
|
RETAIN(self);
|
|
|
|
|
/*
|
|
|
|
|
* Swap ourselves out and the original window content view in.
|
|
|
|
|
*/
|
|
|
|
|
[original setFrame: [self frame]];
|
2000-01-13 21:19:03 +00:00
|
|
|
|
[[rep window] setContentView: original];
|
2000-01-07 06:47:08 +00:00
|
|
|
|
enumerator = [[self subviews] objectEnumerator];
|
|
|
|
|
while ((sub = [enumerator nextObject]) != nil)
|
|
|
|
|
{
|
|
|
|
|
[original addSubview: sub];
|
|
|
|
|
}
|
|
|
|
|
DESTROY(original);
|
|
|
|
|
RELEASE(self);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void) dealloc
|
|
|
|
|
{
|
|
|
|
|
if (isClosed == NO)
|
|
|
|
|
{
|
|
|
|
|
[self close];
|
|
|
|
|
}
|
|
|
|
|
RELEASE(edited);
|
|
|
|
|
RELEASE(selection);
|
2000-01-13 21:19:03 +00:00
|
|
|
|
RELEASE(subeditor);
|
2000-01-07 06:47:08 +00:00
|
|
|
|
RELEASE(document);
|
|
|
|
|
[super dealloc];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void) deleteSelection
|
|
|
|
|
{
|
2000-01-13 21:19:03 +00:00
|
|
|
|
if ([selection count] > 0)
|
2000-01-07 06:47:08 +00:00
|
|
|
|
{
|
2000-01-13 21:40:09 +00:00
|
|
|
|
NSArray *s = [NSArray arrayWithArray: selection];
|
|
|
|
|
NSEnumerator *e = [s objectEnumerator];
|
|
|
|
|
NSMenuItem *i;
|
2000-01-07 06:47:08 +00:00
|
|
|
|
|
2000-01-13 21:19:03 +00:00
|
|
|
|
[self makeSelectionVisible: NO];
|
|
|
|
|
[self selectObjects: [NSArray array]];
|
2000-01-13 21:40:09 +00:00
|
|
|
|
while ((i = [e nextObject]) != nil)
|
|
|
|
|
{
|
|
|
|
|
[edited removeItem: i];
|
|
|
|
|
}
|
2000-01-13 21:19:03 +00:00
|
|
|
|
[document detachObjects: s];
|
2000-01-07 06:47:08 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Dragging source protocol implementation
|
|
|
|
|
*/
|
|
|
|
|
- (void) draggedImage: (NSImage*)i endedAt: (NSPoint)p deposited: (BOOL)f
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
* FIXME - handle this.
|
|
|
|
|
* Notification that a drag failed/succeeded.
|
|
|
|
|
*/
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (unsigned int) draggingSourceOperationMaskForLocal: (BOOL)flag
|
|
|
|
|
{
|
|
|
|
|
if (isLinkSource == YES)
|
|
|
|
|
return NSDragOperationLink;
|
|
|
|
|
else
|
|
|
|
|
return NSDragOperationCopy;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (unsigned) draggingEntered: (id<NSDraggingInfo>)sender
|
|
|
|
|
{
|
|
|
|
|
NSArray *types;
|
|
|
|
|
|
|
|
|
|
dragPb = [sender draggingPasteboard];
|
|
|
|
|
types = [dragPb types];
|
2000-01-13 21:19:03 +00:00
|
|
|
|
if ([types containsObject: IBMenuPboardType] == YES)
|
2000-01-07 06:47:08 +00:00
|
|
|
|
{
|
2000-01-13 21:19:03 +00:00
|
|
|
|
dragType = IBMenuPboardType;
|
2000-01-07 06:47:08 +00:00
|
|
|
|
}
|
|
|
|
|
else if ([types containsObject: GormLinkPboardType] == YES)
|
|
|
|
|
{
|
|
|
|
|
dragType = GormLinkPboardType;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
dragType = nil;
|
|
|
|
|
}
|
|
|
|
|
return [self draggingUpdated: sender];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (unsigned) draggingUpdated: (id<NSDraggingInfo>)sender
|
|
|
|
|
{
|
2000-01-13 21:19:03 +00:00
|
|
|
|
if (dragType == IBMenuPboardType)
|
2000-01-07 06:47:08 +00:00
|
|
|
|
{
|
|
|
|
|
return NSDragOperationCopy;
|
|
|
|
|
}
|
|
|
|
|
else if (dragType == GormLinkPboardType)
|
|
|
|
|
{
|
|
|
|
|
NSPoint loc = [sender draggingLocation];
|
2000-01-13 21:19:03 +00:00
|
|
|
|
int pos = [rep indexOfItemAtPoint: loc];
|
|
|
|
|
id item = nil;
|
2000-01-07 06:47:08 +00:00
|
|
|
|
|
2000-01-13 21:19:03 +00:00
|
|
|
|
if (pos >= 0)
|
2000-01-07 06:47:08 +00:00
|
|
|
|
{
|
2000-01-13 21:19:03 +00:00
|
|
|
|
item = [edited itemAtIndex: pos];
|
2000-01-07 06:47:08 +00:00
|
|
|
|
}
|
2000-01-13 21:19:03 +00:00
|
|
|
|
if (item == [NSApp connectSource])
|
2000-01-07 06:47:08 +00:00
|
|
|
|
{
|
2000-01-13 21:19:03 +00:00
|
|
|
|
item = nil;
|
2000-01-07 06:47:08 +00:00
|
|
|
|
}
|
2000-01-13 21:19:03 +00:00
|
|
|
|
[NSApp displayConnectionBetween: [NSApp connectSource] and: item];
|
2000-01-07 06:47:08 +00:00
|
|
|
|
return NSDragOperationLink;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void) drawSelection
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (id<IBDocuments>) document
|
|
|
|
|
{
|
|
|
|
|
return document;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (id) editedObject
|
|
|
|
|
{
|
|
|
|
|
return edited;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (id) initWithObject: (id)anObject inDocument: (id<IBDocuments>)aDocument
|
|
|
|
|
{
|
2000-01-13 21:19:03 +00:00
|
|
|
|
self = [super init];
|
2000-01-07 06:47:08 +00:00
|
|
|
|
ASSIGN(document, aDocument);
|
|
|
|
|
ASSIGN(edited, anObject);
|
|
|
|
|
selection = [NSMutableArray new];
|
2000-01-13 21:19:03 +00:00
|
|
|
|
rep = [edited menuRepresentation];
|
2000-01-07 06:47:08 +00:00
|
|
|
|
/*
|
|
|
|
|
* Permit views and connections to be dragged in to the window.
|
|
|
|
|
*/
|
|
|
|
|
[self registerForDraggedTypes: [NSArray arrayWithObjects:
|
2000-01-13 21:19:03 +00:00
|
|
|
|
IBMenuPboardType, GormLinkPboardType, nil]];
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Make sure that all our menu items are attached in the document.
|
|
|
|
|
*/
|
|
|
|
|
[document attachObjects: [edited itemArray] toParent: edited];
|
2000-01-07 06:47:08 +00:00
|
|
|
|
|
|
|
|
|
return self;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void) makeSelectionVisible: (BOOL)flag
|
|
|
|
|
{
|
|
|
|
|
if (flag == NO)
|
|
|
|
|
{
|
|
|
|
|
if ([selection count] > 0)
|
|
|
|
|
{
|
|
|
|
|
NSEnumerator *enumerator = [selection objectEnumerator];
|
2000-01-13 21:19:03 +00:00
|
|
|
|
NSMenuItem *item;
|
2000-01-07 06:47:08 +00:00
|
|
|
|
|
|
|
|
|
[[self window] disableFlushWindow];
|
2000-01-13 21:19:03 +00:00
|
|
|
|
[rep lockFocus];
|
|
|
|
|
while ((item = [enumerator nextObject]) != nil)
|
2000-01-07 06:47:08 +00:00
|
|
|
|
{
|
2000-01-13 21:19:03 +00:00
|
|
|
|
int pos = [edited indexOfItem: item];
|
|
|
|
|
id cell = [rep menuItemCellForItemAtIndex: pos];
|
|
|
|
|
NSRect rect = [rep rectOfItemAtIndex: pos];
|
|
|
|
|
|
|
|
|
|
[cell highlight: NO withFrame: rect inView: rep];
|
2000-01-07 06:47:08 +00:00
|
|
|
|
}
|
2000-01-13 21:19:03 +00:00
|
|
|
|
[rep unlockFocus];
|
2000-01-07 06:47:08 +00:00
|
|
|
|
[[self window] enableFlushWindow];
|
|
|
|
|
[[self window] flushWindowIfNeeded];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2000-01-13 21:19:03 +00:00
|
|
|
|
if ([selection count] > 0)
|
|
|
|
|
{
|
|
|
|
|
NSEnumerator *enumerator = [selection objectEnumerator];
|
|
|
|
|
NSMenuItem *item;
|
|
|
|
|
|
|
|
|
|
[[self window] disableFlushWindow];
|
|
|
|
|
[rep lockFocus];
|
|
|
|
|
while ((item = [enumerator nextObject]) != nil)
|
|
|
|
|
{
|
|
|
|
|
int pos = [edited indexOfItem: item];
|
|
|
|
|
id cell = [rep menuItemCellForItemAtIndex: pos];
|
|
|
|
|
NSRect rect = [rep rectOfItemAtIndex: pos];
|
|
|
|
|
|
|
|
|
|
[cell highlight: YES withFrame: rect inView: rep];
|
|
|
|
|
}
|
|
|
|
|
[rep unlockFocus];
|
|
|
|
|
[[self window] enableFlushWindow];
|
|
|
|
|
[[self window] flushWindowIfNeeded];
|
|
|
|
|
}
|
2000-01-07 06:47:08 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (id<IBEditors>) openSubeditorForObject: (id)anObject
|
|
|
|
|
{
|
2000-01-13 21:19:03 +00:00
|
|
|
|
return nil;
|
2000-01-07 06:47:08 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void) orderFront
|
|
|
|
|
{
|
2000-01-13 21:19:03 +00:00
|
|
|
|
[[edited window] orderFront: self];
|
2000-01-07 06:47:08 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void) pasteInSelection
|
|
|
|
|
{
|
|
|
|
|
NSPasteboard *pb = [NSPasteboard generalPasteboard];
|
2000-01-13 21:19:03 +00:00
|
|
|
|
NSArray *items;
|
2000-01-13 21:40:09 +00:00
|
|
|
|
NSEnumerator *enumerator;
|
|
|
|
|
NSMenuItem *item;
|
2000-01-07 06:47:08 +00:00
|
|
|
|
|
|
|
|
|
/*
|
2000-01-13 21:19:03 +00:00
|
|
|
|
* Ask the document to get the copied items from the pasteboard and add
|
2000-01-07 06:47:08 +00:00
|
|
|
|
* them to it's collection of known objects.
|
|
|
|
|
*/
|
2000-01-13 21:19:03 +00:00
|
|
|
|
items = [document pasteType: IBMenuPboardType
|
2000-01-07 06:47:08 +00:00
|
|
|
|
fromPasteboard: pb
|
|
|
|
|
parent: edited];
|
2000-01-13 21:40:09 +00:00
|
|
|
|
|
|
|
|
|
enumerator = [items objectEnumerator];
|
|
|
|
|
while ((item = [enumerator nextObject]) != nil)
|
|
|
|
|
{
|
|
|
|
|
NSString *title = [item title];
|
|
|
|
|
|
|
|
|
|
if ([edited indexOfItemWithTitle: title] > 0)
|
|
|
|
|
{
|
|
|
|
|
[document detachObject: item]; /* Already exists */
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
[edited addItem: item];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
[edited sizeToFit];
|
|
|
|
|
[edited display];
|
2000-01-07 06:47:08 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (BOOL) performDragOperation: (id<NSDraggingInfo>)sender
|
|
|
|
|
{
|
2000-01-13 21:19:03 +00:00
|
|
|
|
NSRect f = [rep frame];
|
|
|
|
|
|
|
|
|
|
if (dragType == IBMenuPboardType)
|
2000-01-07 06:47:08 +00:00
|
|
|
|
{
|
|
|
|
|
NSPoint loc = [sender draggedImageLocation];
|
2000-01-13 21:19:03 +00:00
|
|
|
|
NSArray *items;
|
2000-01-07 06:47:08 +00:00
|
|
|
|
NSEnumerator *enumerator;
|
2000-01-13 21:19:03 +00:00
|
|
|
|
NSMenuItem *item;
|
|
|
|
|
int pos;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Adjust location so that it lies within horizontal bounds, and so that
|
|
|
|
|
* it appears about half an item higher than it is. That way, we treat
|
|
|
|
|
* a drop in the lower half of an item as an insertion below it, and a
|
|
|
|
|
* drop in the upper half as an insertion above it.
|
|
|
|
|
*/
|
|
|
|
|
if (loc.x < NSMinX(f))
|
|
|
|
|
loc.x = NSMinX(f);
|
|
|
|
|
if (loc.x > NSMaxX(f))
|
|
|
|
|
loc.x = NSMaxX(f);
|
|
|
|
|
loc.y += 10;
|
|
|
|
|
pos = [rep indexOfItemAtPoint: loc] + 1;
|
2000-01-07 06:47:08 +00:00
|
|
|
|
|
2000-01-13 23:34:12 +00:00
|
|
|
|
NSLog(@"Drop at index: %d (%@)", pos, NSStringFromPoint(loc));
|
2000-01-07 06:47:08 +00:00
|
|
|
|
/*
|
|
|
|
|
* Ask the document to get the dragged views from the pasteboard and add
|
|
|
|
|
* them to it's collection of known objects.
|
|
|
|
|
*/
|
2000-01-13 21:19:03 +00:00
|
|
|
|
items = [document pasteType: IBMenuPboardType
|
2000-01-07 06:47:08 +00:00
|
|
|
|
fromPasteboard: dragPb
|
|
|
|
|
parent: edited];
|
2000-01-13 21:19:03 +00:00
|
|
|
|
enumerator = [items objectEnumerator];
|
|
|
|
|
while ((item = [enumerator nextObject]) != nil)
|
2000-01-07 06:47:08 +00:00
|
|
|
|
{
|
2000-01-13 21:19:03 +00:00
|
|
|
|
NSString *title = [item title];
|
2000-01-07 06:47:08 +00:00
|
|
|
|
|
2000-01-13 21:19:03 +00:00
|
|
|
|
if ([edited indexOfItemWithTitle: title] > 0)
|
|
|
|
|
{
|
|
|
|
|
[document detachObject: item]; /* Already exists */
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
[edited insertItem: item atIndex: pos++];
|
|
|
|
|
}
|
2000-01-07 06:47:08 +00:00
|
|
|
|
}
|
2000-01-13 21:19:03 +00:00
|
|
|
|
[edited sizeToFit];
|
|
|
|
|
[edited display];
|
2000-01-07 06:47:08 +00:00
|
|
|
|
}
|
|
|
|
|
else if (dragType == GormLinkPboardType)
|
|
|
|
|
{
|
|
|
|
|
NSPoint loc = [sender draggingLocation];
|
2000-01-13 21:19:03 +00:00
|
|
|
|
int pos = [rep indexOfItemAtPoint: loc];
|
2000-01-07 06:47:08 +00:00
|
|
|
|
|
2000-01-13 21:19:03 +00:00
|
|
|
|
NSLog(@"Link at index: %d (%@)", pos, NSStringFromPoint(loc));
|
|
|
|
|
if (pos >= 0)
|
|
|
|
|
{
|
|
|
|
|
id item = [edited itemAtIndex: pos];
|
|
|
|
|
|
|
|
|
|
[NSApp displayConnectionBetween: [NSApp connectSource] and: item];
|
|
|
|
|
[NSApp startConnecting];
|
|
|
|
|
}
|
2000-01-07 06:47:08 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
NSLog(@"Drop with unrecognized type (%@)!", dragType);
|
|
|
|
|
dragType = nil;
|
|
|
|
|
return NO;
|
|
|
|
|
}
|
|
|
|
|
dragType = nil;
|
|
|
|
|
return YES;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (BOOL) prepareForDragOperation: (id<NSDraggingInfo>)sender
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
* Tell the source that we will accept the drop if we can.
|
|
|
|
|
*/
|
2000-01-13 21:19:03 +00:00
|
|
|
|
if (dragType == IBMenuPboardType)
|
2000-01-07 06:47:08 +00:00
|
|
|
|
{
|
|
|
|
|
/*
|
2000-01-13 21:19:03 +00:00
|
|
|
|
* We can accept menus dropped anywhere.
|
2000-01-07 06:47:08 +00:00
|
|
|
|
*/
|
|
|
|
|
return YES;
|
|
|
|
|
}
|
|
|
|
|
else if (dragType == GormLinkPboardType)
|
|
|
|
|
{
|
|
|
|
|
/*
|
2000-01-13 21:19:03 +00:00
|
|
|
|
* We can accept a link dropped on any of our items.
|
2000-01-07 06:47:08 +00:00
|
|
|
|
*/
|
2000-01-13 21:19:03 +00:00
|
|
|
|
return YES;
|
2000-01-07 06:47:08 +00:00
|
|
|
|
}
|
|
|
|
|
return NO;
|
|
|
|
|
}
|
|
|
|
|
|
2000-01-13 21:19:03 +00:00
|
|
|
|
/*
|
2000-01-13 21:40:09 +00:00
|
|
|
|
* Return the rectangle in which an objects link status will be displayed.
|
2000-01-13 21:19:03 +00:00
|
|
|
|
*/
|
|
|
|
|
- (NSRect) rectForObject: (id)anObject
|
|
|
|
|
{
|
|
|
|
|
int pos = [edited indexOfItem: anObject];
|
|
|
|
|
NSRect rect;
|
|
|
|
|
|
|
|
|
|
if (pos >= 0)
|
|
|
|
|
{
|
|
|
|
|
rect = [rep rectOfItemAtIndex: pos];
|
|
|
|
|
rect = [rep convertRect: rect toView: nil];
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
rect = [self frame];
|
|
|
|
|
}
|
|
|
|
|
return rect;
|
|
|
|
|
}
|
|
|
|
|
|
2000-01-07 06:47:08 +00:00
|
|
|
|
- (void) resetObject: (id)anObject
|
|
|
|
|
{
|
|
|
|
|
[[self window] makeKeyAndOrderFront: self];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (id) selectAll: (id)sender
|
|
|
|
|
{
|
2000-01-13 21:19:03 +00:00
|
|
|
|
[self selectObjects: [edited itemArray]];
|
2000-01-07 06:47:08 +00:00
|
|
|
|
return self;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void) selectObjects: (NSArray*)anArray
|
|
|
|
|
{
|
2000-01-13 21:19:03 +00:00
|
|
|
|
if ([anArray isEqual: selection] == NO)
|
2000-01-07 06:47:08 +00:00
|
|
|
|
{
|
2000-01-13 23:34:12 +00:00
|
|
|
|
unsigned count;
|
|
|
|
|
NSMenuItem *item;
|
2000-01-07 06:47:08 +00:00
|
|
|
|
|
|
|
|
|
[selection removeAllObjects];
|
|
|
|
|
[selection addObjectsFromArray: anArray];
|
|
|
|
|
|
|
|
|
|
count = [selection count];
|
|
|
|
|
|
|
|
|
|
/*
|
2000-01-13 21:19:03 +00:00
|
|
|
|
* We can only select items in our menu - discard others.
|
2000-01-07 06:47:08 +00:00
|
|
|
|
*/
|
|
|
|
|
while (count-- > 0)
|
|
|
|
|
{
|
|
|
|
|
id o = [selection objectAtIndex: count];
|
|
|
|
|
|
2000-01-13 21:19:03 +00:00
|
|
|
|
if ([edited indexOfItem: o] == NSNotFound)
|
2000-01-07 06:47:08 +00:00
|
|
|
|
{
|
|
|
|
|
[selection removeObjectAtIndex: count];
|
|
|
|
|
}
|
|
|
|
|
}
|
2000-01-13 23:34:12 +00:00
|
|
|
|
item = [selection lastObject];
|
|
|
|
|
if ([selection count] != 1 || [item hasSubmenu] == NO)
|
|
|
|
|
{
|
|
|
|
|
[self closeSubeditors];
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
NSMenu *menu;
|
|
|
|
|
id editor;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* A single item with a submenu is selected -
|
|
|
|
|
* Make sure the submenu is registered in the document and
|
|
|
|
|
* open an editor for it Close any existing subeditor.
|
|
|
|
|
*/
|
|
|
|
|
menu = [item submenu];
|
|
|
|
|
if ([document containsObject: menu] == NO)
|
|
|
|
|
{
|
|
|
|
|
[document attachObject: menu toParent: item];
|
|
|
|
|
}
|
|
|
|
|
editor = [document editorForObject: menu create: YES];
|
|
|
|
|
if (subeditor != nil && subeditor != editor)
|
|
|
|
|
{
|
|
|
|
|
[self closeSubeditors];
|
|
|
|
|
}
|
|
|
|
|
[editor orderFront];
|
|
|
|
|
[editor activate];
|
|
|
|
|
ASSIGN(subeditor, editor);
|
|
|
|
|
}
|
2000-01-13 21:19:03 +00:00
|
|
|
|
}
|
|
|
|
|
/*
|
|
|
|
|
* Now we must let the document (and hence the rest of the app) know
|
|
|
|
|
* about our new selection. If there is nothing in it, make sure
|
|
|
|
|
* that our edited window is selected instead.
|
|
|
|
|
*/
|
|
|
|
|
if ([selection count] > 0)
|
|
|
|
|
{
|
|
|
|
|
[document setSelectionFromEditor: self];
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
GormObjectEditor *ed;
|
2000-01-07 06:47:08 +00:00
|
|
|
|
|
2000-01-13 21:19:03 +00:00
|
|
|
|
ed = [GormObjectEditor editorForDocument: document];
|
|
|
|
|
[ed selectObjects: [NSArray arrayWithObject: edited]];
|
2000-01-07 06:47:08 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (NSArray*) selection
|
|
|
|
|
{
|
|
|
|
|
return [NSArray arrayWithArray: selection];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (unsigned) selectionCount
|
|
|
|
|
{
|
|
|
|
|
return [selection count];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void) validateEditing
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (BOOL) wantsSelection
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
* 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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (NSWindow*) window
|
|
|
|
|
{
|
|
|
|
|
return [super window];
|
|
|
|
|
}
|
|
|
|
|
@end
|