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
|
2007-11-05 23:44:36 +00:00
|
|
|
|
* the Free Software Foundation; either version 3 of the License, or
|
2000-01-07 06:47:08 +00:00
|
|
|
|
* (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
|
2005-05-26 03:37:38 +00:00
|
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111 USA.
|
2000-01-07 06:47:08 +00:00
|
|
|
|
*/
|
|
|
|
|
|
2003-05-29 05:40:28 +00:00
|
|
|
|
#include <AppKit/AppKit.h>
|
|
|
|
|
#include <InterfaceBuilder/InterfaceBuilder.h>
|
2005-03-31 03:01:36 +00:00
|
|
|
|
#include <GormCore/GormFunctions.h>
|
2000-01-07 06:47:08 +00:00
|
|
|
|
|
2003-05-29 05:40:28 +00:00
|
|
|
|
/*
|
2004-05-13 22:48:14 +00:00
|
|
|
|
* This method will allow us to check if the menu is
|
|
|
|
|
* open, so that it can be conditionally closed.
|
|
|
|
|
*/
|
|
|
|
|
@interface NSMenu (GormMenuEditorAdditions)
|
|
|
|
|
- (BOOL) isVisible;
|
|
|
|
|
@end
|
|
|
|
|
|
|
|
|
|
@implementation NSMenu (GormMenuEditorAdditions)
|
|
|
|
|
- (BOOL) isVisible
|
|
|
|
|
{
|
|
|
|
|
return [_aWindow isVisible];
|
|
|
|
|
}
|
2002-09-21 15:24:59 +00:00
|
|
|
|
@end
|
|
|
|
|
|
2000-01-07 06:47:08 +00:00
|
|
|
|
|
|
|
|
|
|
2002-08-14 00:01:42 +00:00
|
|
|
|
@interface GormMenuEditor : NSMenuView <IBEditors, IBSelectionOwners>
|
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
|
|
|
|
|
|
2003-01-04 00:17:43 +00:00
|
|
|
|
@interface GormMenuEditor (Private)
|
|
|
|
|
- (NSEvent *) editTextField: view withEvent: (NSEvent *)theEvent;
|
|
|
|
|
@end
|
|
|
|
|
|
2000-01-07 06:47:08 +00:00
|
|
|
|
@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
|
|
|
|
}
|
|
|
|
|
|
2002-04-07 22:02:41 +00:00
|
|
|
|
- (BOOL) resignFirstResponder
|
|
|
|
|
{
|
|
|
|
|
return NO;
|
|
|
|
|
}
|
|
|
|
|
|
2004-08-06 11:17:45 +00:00
|
|
|
|
- (void) rightMouseDown: (NSEvent*)theEvent
|
|
|
|
|
{
|
|
|
|
|
// Do nothing. We want to ignore when the right mouse button is pressed.
|
|
|
|
|
}
|
|
|
|
|
|
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];
|
2002-01-14 04:19:01 +00:00
|
|
|
|
|
2011-09-15 07:54:12 +00:00
|
|
|
|
[[self window] makeMainWindow];
|
2002-04-07 22:02:41 +00:00
|
|
|
|
[[self window] makeFirstResponder: self];
|
|
|
|
|
|
2009-02-11 14:14:26 +00:00
|
|
|
|
if (hit == rep)
|
2000-01-13 21:19:03 +00:00
|
|
|
|
{
|
2009-02-11 14:14:26 +00:00
|
|
|
|
int pos = [rep indexOfItemAtPoint: loc];
|
2000-01-07 06:47:08 +00:00
|
|
|
|
|
2009-02-11 14:14:26 +00:00
|
|
|
|
if (pos >= 0)
|
2000-01-07 06:47:08 +00:00
|
|
|
|
{
|
2009-02-11 14:14:26 +00:00
|
|
|
|
NSMenuItem *item = [edited itemAtIndex: pos];
|
|
|
|
|
|
|
|
|
|
if ([theEvent clickCount] == 2)
|
2000-01-07 06:47:08 +00:00
|
|
|
|
{
|
2009-02-11 14:14:26 +00:00
|
|
|
|
id cell;
|
|
|
|
|
NSTextField *tf;
|
|
|
|
|
NSRect frame;
|
2009-01-25 11:45:09 +00:00
|
|
|
|
[self makeSelectionVisible: NO];
|
2009-02-11 14:14:26 +00:00
|
|
|
|
[self selectObjects: [NSArray array]];
|
|
|
|
|
cell = [rep menuItemCellForItemAtIndex: pos];
|
|
|
|
|
tf = [[NSTextField alloc] initWithFrame: [self bounds]];
|
|
|
|
|
frame = (NSRect)[cell titleRectForBounds:
|
|
|
|
|
[rep rectOfItemAtIndex: pos]];
|
|
|
|
|
NSDebugLog(@"cell %@ (%@)", cell, [cell stringValue]);
|
|
|
|
|
frame.origin.y += 3;
|
|
|
|
|
frame.size.height -= 5;
|
|
|
|
|
frame.origin.x += 1;
|
|
|
|
|
frame.size.width += 3;
|
|
|
|
|
|
|
|
|
|
[tf setFrame: frame];
|
|
|
|
|
[tf setEditable: YES];
|
|
|
|
|
[tf setBezeled: NO];
|
|
|
|
|
[tf setBordered: NO];
|
|
|
|
|
[self addSubview: tf];
|
|
|
|
|
[tf setStringValue: [[cell menuItem] title]];
|
|
|
|
|
[self editTextField: tf
|
|
|
|
|
withEvent: theEvent];
|
|
|
|
|
[[cell menuItem] setTitle: [tf stringValue]];
|
|
|
|
|
[tf removeFromSuperview];
|
|
|
|
|
RELEASE(tf);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[self makeSelectionVisible: NO];
|
|
|
|
|
if ([theEvent modifierFlags] & NSShiftKeyMask)
|
|
|
|
|
{
|
|
|
|
|
NSMutableArray *array;
|
|
|
|
|
|
|
|
|
|
array = [NSMutableArray arrayWithArray: selection];
|
|
|
|
|
if ([array containsObject: item] == YES)
|
2000-01-07 06:47:08 +00:00
|
|
|
|
{
|
2009-02-11 14:14:26 +00:00
|
|
|
|
[array removeObject: item];
|
2000-01-07 06:47:08 +00:00
|
|
|
|
}
|
2009-02-11 14:14:26 +00:00
|
|
|
|
else
|
2009-01-25 11:45:09 +00:00
|
|
|
|
{
|
2009-02-11 14:14:26 +00:00
|
|
|
|
[array addObject: item];
|
2009-01-25 11:45:09 +00:00
|
|
|
|
}
|
2009-02-11 14:14:26 +00:00
|
|
|
|
[self selectObjects: array];
|
|
|
|
|
[self makeSelectionVisible: YES];
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[self selectObjects: [NSArray arrayWithObject: item]];
|
|
|
|
|
if ([theEvent modifierFlags] & NSControlKeyMask)
|
|
|
|
|
{
|
|
|
|
|
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];
|
|
|
|
|
[NSApp startConnecting];
|
|
|
|
|
|
|
|
|
|
isLinkSource = YES;
|
|
|
|
|
[self dragImage: [NSApp linkImage]
|
|
|
|
|
at: dragPoint
|
|
|
|
|
offset: NSZeroSize
|
|
|
|
|
event: theEvent
|
|
|
|
|
pasteboard: pb
|
|
|
|
|
source: self
|
|
|
|
|
slideBack: YES];
|
|
|
|
|
isLinkSource = NO;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
NSDate *future = [NSDate distantFuture];
|
|
|
|
|
unsigned eventMask;
|
|
|
|
|
NSEvent *e;
|
|
|
|
|
NSEventType eType;
|
|
|
|
|
BOOL acceptsMouseMoved;
|
|
|
|
|
NSRect frame = [rep innerRect];
|
|
|
|
|
float maxMouse = NSMaxY(frame);
|
|
|
|
|
float minMouse = NSMinY(frame);
|
|
|
|
|
NSPoint lastPoint = loc;
|
|
|
|
|
NSPoint point = loc;
|
|
|
|
|
NSRect lastRect = [rep rectOfItemAtIndex: pos];
|
|
|
|
|
id cell = [rep menuItemCellForItemAtIndex: pos];
|
|
|
|
|
int newPos;
|
|
|
|
|
|
|
|
|
|
eventMask = NSLeftMouseUpMask | NSLeftMouseDraggedMask
|
|
|
|
|
| NSMouseMovedMask | NSPeriodicMask;
|
|
|
|
|
[[self window] setAcceptsMouseMovedEvents: YES];
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Save window state info.
|
|
|
|
|
*/
|
|
|
|
|
acceptsMouseMoved = [[self window] acceptsMouseMovedEvents];
|
|
|
|
|
[rep lockFocus];
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Track mouse movements until left mouse up.
|
|
|
|
|
* While we keep track of all mouse movements,
|
|
|
|
|
* we only act on a movement when a periodic
|
|
|
|
|
* event arives (every 20th of a second)
|
|
|
|
|
* in order to avoid excessive amounts of drawing.
|
|
|
|
|
*/
|
|
|
|
|
[NSEvent startPeriodicEventsAfterDelay: 0.1 withPeriod: 0.05];
|
|
|
|
|
e = [NSApp nextEventMatchingMask: eventMask
|
|
|
|
|
untilDate: future
|
|
|
|
|
inMode: NSEventTrackingRunLoopMode
|
|
|
|
|
dequeue: YES];
|
|
|
|
|
eType = [e type];
|
|
|
|
|
while (eType != NSLeftMouseUp)
|
2000-01-07 06:47:08 +00:00
|
|
|
|
{
|
2009-02-11 14:14:26 +00:00
|
|
|
|
if (eType != NSPeriodic)
|
2000-01-14 10:19:57 +00:00
|
|
|
|
{
|
2009-02-11 14:14:26 +00:00
|
|
|
|
point = [e locationInWindow];
|
|
|
|
|
}
|
|
|
|
|
else if (NSEqualPoints(point, lastPoint) == NO)
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
* Limit mouse movement.
|
|
|
|
|
*/
|
|
|
|
|
point.x = NSMinX(frame);
|
|
|
|
|
if (point.y < minMouse)
|
|
|
|
|
point.y = minMouse;
|
|
|
|
|
if (point.y > maxMouse)
|
|
|
|
|
point.y = maxMouse;
|
|
|
|
|
|
|
|
|
|
if (NSEqualPoints(point, lastPoint) == NO)
|
2000-01-14 10:19:57 +00:00
|
|
|
|
{
|
2009-02-11 14:14:26 +00:00
|
|
|
|
[[self window] disableFlushWindow];
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Redraw cells under area being changed.
|
|
|
|
|
*/
|
|
|
|
|
[rep drawRect: lastRect];
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Update location.
|
|
|
|
|
*/
|
|
|
|
|
lastRect.origin.y += point.y - lastPoint.y;
|
|
|
|
|
lastPoint = point;
|
|
|
|
|
|
2000-01-14 10:19:57 +00:00
|
|
|
|
/*
|
2009-02-11 14:14:26 +00:00
|
|
|
|
* Draw highlighted item being moved.
|
2000-01-14 10:19:57 +00:00
|
|
|
|
*/
|
2009-02-11 14:14:26 +00:00
|
|
|
|
[cell highlight: YES withFrame: lastRect inView: rep];
|
|
|
|
|
[cell setHighlighted: NO];
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Flush any drawing performed for this event.
|
|
|
|
|
*/
|
|
|
|
|
[[self window] enableFlushWindow];
|
|
|
|
|
[[self window] flushWindow];
|
2000-01-14 10:19:57 +00:00
|
|
|
|
}
|
2009-01-25 11:45:09 +00:00
|
|
|
|
}
|
2009-02-11 14:14:26 +00:00
|
|
|
|
e = [NSApp nextEventMatchingMask: eventMask
|
|
|
|
|
untilDate: future
|
|
|
|
|
inMode: NSEventTrackingRunLoopMode
|
|
|
|
|
dequeue: YES];
|
|
|
|
|
eType = [e type];
|
2000-01-07 06:47:08 +00:00
|
|
|
|
}
|
2009-02-11 14:14:26 +00:00
|
|
|
|
[NSEvent stopPeriodicEvents];
|
|
|
|
|
|
|
|
|
|
[rep drawRect: lastRect];
|
|
|
|
|
[rep unlockFocus];
|
|
|
|
|
newPos = [rep indexOfItemAtPoint: point];
|
|
|
|
|
if (newPos < pos)
|
|
|
|
|
{
|
|
|
|
|
NSMenuItem *item = [edited itemAtIndex: pos];
|
|
|
|
|
|
|
|
|
|
RETAIN(item);
|
|
|
|
|
if (newPos < 0)
|
|
|
|
|
newPos = 0;
|
|
|
|
|
[edited removeItemAtIndex: pos];
|
|
|
|
|
[edited insertItem: item atIndex: newPos];
|
|
|
|
|
RELEASE(item);
|
|
|
|
|
}
|
|
|
|
|
else if (newPos > pos)
|
|
|
|
|
{
|
|
|
|
|
NSMenuItem *item = [edited itemAtIndex: pos];
|
|
|
|
|
|
|
|
|
|
RETAIN(item);
|
|
|
|
|
[edited removeItemAtIndex: pos];
|
|
|
|
|
[edited insertItem: item atIndex: newPos];
|
|
|
|
|
RELEASE(item);
|
|
|
|
|
}
|
|
|
|
|
[edited sizeToFit];
|
|
|
|
|
[edited display];
|
|
|
|
|
/*
|
|
|
|
|
* Restore state to what it was on entry.
|
|
|
|
|
*/
|
|
|
|
|
[[self window] setAcceptsMouseMovedEvents: acceptsMouseMoved];
|
2000-01-07 06:47:08 +00:00
|
|
|
|
}
|
2009-02-11 14:14:26 +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
|
2000-01-14 13:34:15 +00:00
|
|
|
|
* handle it - but make sure the menu is selected in the editor first.
|
2000-01-13 21:19:03 +00:00
|
|
|
|
*/
|
2000-01-14 13:34:15 +00:00
|
|
|
|
[[document parentEditorForEditor: self] selectObjects:
|
2002-08-14 00:01:42 +00:00
|
|
|
|
[NSArray arrayWithObject: edited]];
|
2009-02-11 14:14:26 +00:00
|
|
|
|
[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
|
|
|
|
|
{
|
|
|
|
|
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
|
|
|
|
|
2003-09-28 01:58:57 +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];
|
|
|
|
|
}
|
2003-09-28 01:58:57 +00:00
|
|
|
|
|
2000-01-13 21:19:03 +00:00
|
|
|
|
[w setContentView: self];
|
2000-01-13 23:34:12 +00:00
|
|
|
|
|
2003-09-28 01:58:57 +00:00
|
|
|
|
//
|
|
|
|
|
// Line up submenu with parent menu.
|
|
|
|
|
//
|
2000-01-13 23:34:12 +00:00
|
|
|
|
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;
|
2004-05-01 00:05:53 +00:00
|
|
|
|
|
|
|
|
|
// if it's the main menu, display it when activated, otherwise don't.
|
|
|
|
|
if([[document nameForObject: edited] isEqual: @"NSMenu"])
|
|
|
|
|
{
|
|
|
|
|
[edited sizeToFit];
|
|
|
|
|
[[[edited menuRepresentation] window] setFrameTopLeftPoint: tl];
|
|
|
|
|
}
|
|
|
|
|
}
|
2000-01-07 06:47:08 +00:00
|
|
|
|
return NO;
|
|
|
|
|
}
|
|
|
|
|
return YES;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void) close
|
|
|
|
|
{
|
|
|
|
|
isClosed = YES;
|
|
|
|
|
[[NSNotificationCenter defaultCenter] removeObserver: self];
|
|
|
|
|
|
|
|
|
|
if ([(id<IB>)NSApp selectionOwner] == self)
|
|
|
|
|
{
|
|
|
|
|
[document resignSelectionForEditor: self];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[self closeSubeditors];
|
|
|
|
|
[self deactivate];
|
2004-05-29 19:18:22 +00:00
|
|
|
|
|
|
|
|
|
// if it's visible, close it.
|
2004-05-13 22:48:14 +00:00
|
|
|
|
if([edited isVisible])
|
2004-05-29 19:18:22 +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.
|
|
|
|
|
*/
|
2002-04-07 22:02:41 +00:00
|
|
|
|
[self makeSelectionVisible: NO];
|
2000-01-07 06:47:08 +00:00
|
|
|
|
[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];
|
|
|
|
|
}
|
2004-05-13 22:48:14 +00:00
|
|
|
|
|
2004-07-21 01:49:07 +00:00
|
|
|
|
RELEASE(edited);
|
2000-01-07 06:47:08 +00:00
|
|
|
|
RELEASE(selection);
|
2000-01-13 21:19:03 +00:00
|
|
|
|
RELEASE(subeditor);
|
2000-01-07 06:47:08 +00:00
|
|
|
|
[super dealloc];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void) deleteSelection
|
|
|
|
|
{
|
2000-01-13 21:19:03 +00:00
|
|
|
|
if ([selection count] > 0)
|
2000-01-07 06:47:08 +00:00
|
|
|
|
{
|
2004-03-21 05:12:27 +00:00
|
|
|
|
NSArray *s = [NSArray arrayWithArray: selection];
|
2000-01-13 21:40:09 +00:00
|
|
|
|
NSEnumerator *e = [s objectEnumerator];
|
|
|
|
|
NSMenuItem *i;
|
2004-03-21 05:12:27 +00:00
|
|
|
|
NSArray *d = nil;
|
2004-12-28 02:25:18 +00:00
|
|
|
|
|
2000-01-13 21:19:03 +00:00
|
|
|
|
[self makeSelectionVisible: NO];
|
|
|
|
|
[self selectObjects: [NSArray array]];
|
2004-03-21 05:12:27 +00:00
|
|
|
|
|
2003-10-13 03:32:51 +00:00
|
|
|
|
// find all relavent objects. Remove them from the nameTable.
|
2004-01-30 04:19:11 +00:00
|
|
|
|
d = findAllSubmenus( s );
|
2003-10-13 03:32:51 +00:00
|
|
|
|
[document detachObjects: d];
|
2004-03-21 05:12:27 +00:00
|
|
|
|
|
2003-10-13 03:32:51 +00:00
|
|
|
|
// remove the items from the menu...
|
2009-03-24 22:02:41 +00:00
|
|
|
|
while ((i = [e nextObject]) != nil && [edited numberOfItems] > 0)
|
2000-01-13 21:40:09 +00:00
|
|
|
|
{
|
|
|
|
|
[edited removeItem: i];
|
|
|
|
|
}
|
2004-04-28 02:13:57 +00:00
|
|
|
|
[edited sizeToFit];
|
|
|
|
|
[edited display];
|
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;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2002-09-21 15:24:59 +00:00
|
|
|
|
- (void) draggingExited: (id<NSDraggingInfo>)sender
|
|
|
|
|
{
|
|
|
|
|
if (dragType == GormLinkPboardType)
|
|
|
|
|
{
|
|
|
|
|
[NSApp displayConnectionBetween: [NSApp connectSource]
|
|
|
|
|
and: nil];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2000-01-07 06:47:08 +00:00
|
|
|
|
- (void) drawSelection
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (id<IBDocuments>) document
|
|
|
|
|
{
|
|
|
|
|
return document;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (id) editedObject
|
|
|
|
|
{
|
|
|
|
|
return edited;
|
|
|
|
|
}
|
|
|
|
|
|
2004-03-24 03:08:02 +00:00
|
|
|
|
// find all subitems for the given items...
|
|
|
|
|
void _attachAllSubmenus(id menu, NSArray *items, id document)
|
|
|
|
|
{
|
|
|
|
|
NSEnumerator *e = [items objectEnumerator];
|
2004-05-01 00:05:53 +00:00
|
|
|
|
NSString *name = [document nameForObject: menu];
|
2004-03-24 03:08:02 +00:00
|
|
|
|
id i = nil;
|
|
|
|
|
|
2004-05-01 00:05:53 +00:00
|
|
|
|
// if it's the main menu, display it... otherwise..
|
|
|
|
|
if([name isEqual: @"NSMenu"])
|
|
|
|
|
{
|
|
|
|
|
[menu display];
|
|
|
|
|
}
|
|
|
|
|
|
2004-03-24 03:08:02 +00:00
|
|
|
|
while((i = [e nextObject]) != nil)
|
|
|
|
|
{
|
|
|
|
|
[document attachObject: i toParent: menu];
|
|
|
|
|
if([i hasSubmenu])
|
|
|
|
|
{
|
|
|
|
|
id submenu = [i submenu];
|
|
|
|
|
NSArray *submenuItems = [submenu itemArray];
|
|
|
|
|
|
2004-03-24 05:00:08 +00:00
|
|
|
|
[submenu setSupermenu: menu];
|
2004-03-24 03:08:02 +00:00
|
|
|
|
[document attachObject: submenu toParent: i];
|
|
|
|
|
_attachAllSubmenus(submenu, submenuItems, document);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void _attachAll(NSMenu *menu, id document)
|
|
|
|
|
{
|
|
|
|
|
NSArray *items = [menu itemArray];
|
|
|
|
|
_attachAllSubmenus(menu, items, document);
|
|
|
|
|
}
|
|
|
|
|
|
2000-01-07 06:47:08 +00:00
|
|
|
|
- (id) initWithObject: (id)anObject inDocument: (id<IBDocuments>)aDocument
|
|
|
|
|
{
|
2000-01-13 21:19:03 +00:00
|
|
|
|
self = [super init];
|
2004-05-13 05:13:36 +00:00
|
|
|
|
if(self != nil)
|
|
|
|
|
{
|
|
|
|
|
document = aDocument;
|
|
|
|
|
ASSIGN(edited, anObject);
|
2005-06-17 11:52:30 +00:00
|
|
|
|
selection = [[NSMutableArray alloc] init];
|
2004-05-13 05:13:36 +00:00
|
|
|
|
rep = [edited menuRepresentation];
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Permit views and connections to be dragged in to the window.
|
|
|
|
|
*/
|
|
|
|
|
[self registerForDraggedTypes: [NSArray arrayWithObjects:
|
|
|
|
|
IBMenuPboardType, GormLinkPboardType, nil]];
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Make sure that all our menu items are attached in the document.
|
|
|
|
|
*/
|
|
|
|
|
_attachAll(edited, document);
|
|
|
|
|
}
|
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)
|
|
|
|
|
{
|
2005-04-22 16:41:17 +00:00
|
|
|
|
if ([edited _ownedByPopUp])
|
2000-01-13 21:40:09 +00:00
|
|
|
|
{
|
2004-12-28 13:35:52 +00:00
|
|
|
|
[item setOnStateImage: nil];
|
|
|
|
|
[item setMixedStateImage: nil];
|
2000-01-13 21:40:09 +00:00
|
|
|
|
}
|
2004-12-28 13:35:52 +00:00
|
|
|
|
[edited addItem: item];
|
2000-01-13 21:40:09 +00:00
|
|
|
|
}
|
|
|
|
|
[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-14 13:34:15 +00:00
|
|
|
|
[self makeSelectionVisible: NO];
|
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];
|
2004-03-24 20:22:39 +00:00
|
|
|
|
|
|
|
|
|
// Test to see if the first item is a menu, if so reject the drag. If the
|
|
|
|
|
// first item is a menu item, accept it.
|
|
|
|
|
if([items count] > 0)
|
|
|
|
|
{
|
|
|
|
|
id itemZero = [items objectAtIndex: 0];
|
|
|
|
|
if([itemZero isKindOfClass: [NSMenu class]])
|
|
|
|
|
{
|
|
|
|
|
return NO;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// enumerate through the items and add them.
|
2000-01-13 21:19:03 +00:00
|
|
|
|
enumerator = [items objectEnumerator];
|
|
|
|
|
while ((item = [enumerator nextObject]) != nil)
|
2000-01-07 06:47:08 +00:00
|
|
|
|
{
|
2002-10-08 20:17:17 +00:00
|
|
|
|
if ([edited _ownedByPopUp])
|
|
|
|
|
{
|
2004-02-21 18:48:48 +00:00
|
|
|
|
NSDebugLog(@"owned by popup");
|
2002-10-08 20:17:17 +00:00
|
|
|
|
[item setOnStateImage: nil];
|
|
|
|
|
[item setMixedStateImage: nil];
|
2004-08-18 04:19:45 +00:00
|
|
|
|
|
|
|
|
|
// if the item has a submenu, reject the drag.
|
|
|
|
|
if([item hasSubmenu])
|
|
|
|
|
{
|
|
|
|
|
return NO;
|
|
|
|
|
}
|
2002-10-08 20:17:17 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
2004-02-21 18:48:48 +00:00
|
|
|
|
NSDebugLog(@"not owned by popup");
|
2002-10-08 20:17:17 +00:00
|
|
|
|
[edited insertItem: item atIndex: pos++];
|
2000-01-07 06:47:08 +00:00
|
|
|
|
}
|
2009-02-11 14:14:26 +00:00
|
|
|
|
[edited sizeToFit];
|
|
|
|
|
[edited display];
|
2000-01-14 13:34:15 +00:00
|
|
|
|
[self selectObjects: items];
|
|
|
|
|
[self makeSelectionVisible: YES];
|
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
|
|
|
|
|
2004-02-21 18:48:48 +00:00
|
|
|
|
NSDebugLog(@"Link at index: %d (%@)", pos, NSStringFromPoint(loc));
|
2000-01-13 21:19:03 +00:00
|
|
|
|
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
|
|
|
|
|
{
|
2004-02-21 18:48:48 +00:00
|
|
|
|
NSDebugLog(@"Drop with unrecognized type (%@)!", dragType);
|
2000-01-07 06:47:08 +00:00
|
|
|
|
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];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (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];
|
2003-01-01 17:50:17 +00:00
|
|
|
|
NSDebugLog(@"selectObjects %@ %@", selection, anArray);
|
2000-01-07 06:47:08 +00:00
|
|
|
|
[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];
|
|
|
|
|
}
|
2004-03-24 05:00:08 +00:00
|
|
|
|
[menu display];
|
|
|
|
|
[[item submenu] display];
|
2000-01-13 23:34:12 +00:00
|
|
|
|
[editor orderFront];
|
|
|
|
|
[editor activate];
|
|
|
|
|
ASSIGN(subeditor, editor);
|
|
|
|
|
}
|
2000-01-13 21:19:03 +00:00
|
|
|
|
}
|
2004-03-24 03:08:02 +00:00
|
|
|
|
|
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];
|
|
|
|
|
}
|
2003-05-29 05:40:28 +00:00
|
|
|
|
|
|
|
|
|
/*
|
2000-01-13 21:19:03 +00:00
|
|
|
|
else
|
|
|
|
|
{
|
2003-01-04 00:17:43 +00:00
|
|
|
|
id ed = nil;
|
|
|
|
|
//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
|
|
|
|
}
|
2003-05-29 05:40:28 +00:00
|
|
|
|
*/
|
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
|
2002-09-21 15:24:59 +00:00
|
|
|
|
|
|
|
|
|
static BOOL done_editing;
|
|
|
|
|
|
|
|
|
|
@implementation GormMenuEditor (EditingAdditions)
|
|
|
|
|
- (void) handleNotification: (NSNotification*)aNotification
|
|
|
|
|
{
|
|
|
|
|
NSString *name = [aNotification name];
|
|
|
|
|
if ([name isEqual: NSControlTextDidEndEditingNotification] == YES)
|
|
|
|
|
{
|
|
|
|
|
done_editing = YES;
|
2004-12-28 03:00:32 +00:00
|
|
|
|
[document setSelectionFromEditor: self]; // Correction for Bug#11410
|
|
|
|
|
// [self selectObjects: [NSArray arrayWithObject: edited]];
|
2002-09-21 15:24:59 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Edit a textfield. If it's not already editable, make it so, then
|
|
|
|
|
edit it */
|
|
|
|
|
- (NSEvent *) editTextField: view withEvent: (NSEvent *)theEvent
|
|
|
|
|
{
|
|
|
|
|
unsigned eventMask;
|
|
|
|
|
BOOL wasEditable;
|
|
|
|
|
BOOL didDrawBackground;
|
|
|
|
|
NSTextField *editField;
|
|
|
|
|
NSRect frame;
|
|
|
|
|
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
|
|
|
|
|
NSDate *future = [NSDate distantFuture];
|
|
|
|
|
NSEvent *e;
|
|
|
|
|
|
|
|
|
|
editField = view;
|
|
|
|
|
frame = [editField frame];
|
|
|
|
|
|
|
|
|
|
wasEditable = [editField isEditable];
|
|
|
|
|
[editField setEditable: YES];
|
|
|
|
|
didDrawBackground = [editField drawsBackground];
|
|
|
|
|
[editField setDrawsBackground: YES];
|
|
|
|
|
|
|
|
|
|
[nc addObserver: self
|
|
|
|
|
selector: @selector(handleNotification:)
|
|
|
|
|
name: NSControlTextDidEndEditingNotification
|
|
|
|
|
object: nil];
|
|
|
|
|
|
|
|
|
|
/* Do some modal editing */
|
|
|
|
|
[editField selectText: self];
|
|
|
|
|
eventMask = NSLeftMouseDownMask | NSLeftMouseUpMask |
|
|
|
|
|
NSKeyDownMask | NSKeyUpMask | NSFlagsChangedMask;
|
|
|
|
|
|
|
|
|
|
done_editing = NO;
|
|
|
|
|
while (!done_editing)
|
|
|
|
|
{
|
|
|
|
|
NSEventType eType;
|
|
|
|
|
e = [NSApp nextEventMatchingMask: eventMask
|
|
|
|
|
untilDate: future
|
|
|
|
|
inMode: NSEventTrackingRunLoopMode
|
|
|
|
|
dequeue: YES];
|
|
|
|
|
eType = [e type];
|
|
|
|
|
switch (eType)
|
|
|
|
|
{
|
|
|
|
|
case NSLeftMouseDown:
|
|
|
|
|
{
|
|
|
|
|
NSPoint dp = [self convertPoint: [e locationInWindow]
|
|
|
|
|
fromView: nil];
|
|
|
|
|
if (NSMouseInRect(dp, frame, NO) == NO)
|
|
|
|
|
{
|
|
|
|
|
done_editing = YES;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
[[editField currentEditor] mouseDown: e];
|
|
|
|
|
break;
|
|
|
|
|
case NSLeftMouseUp:
|
|
|
|
|
[[editField currentEditor] mouseUp: e];
|
|
|
|
|
break;
|
|
|
|
|
case NSLeftMouseDragged:
|
|
|
|
|
[[editField currentEditor] mouseDragged: e];
|
|
|
|
|
break;
|
|
|
|
|
case NSKeyDown:
|
|
|
|
|
[[editField currentEditor] keyDown: e];
|
|
|
|
|
break;
|
|
|
|
|
case NSKeyUp:
|
|
|
|
|
[[editField currentEditor] keyUp: e];
|
|
|
|
|
break;
|
|
|
|
|
case NSFlagsChanged:
|
|
|
|
|
[[editField currentEditor] flagsChanged: e];
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
NSLog(@"Internal Error: Unhandled event during editing: %@", e);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[editField setEditable: wasEditable];
|
|
|
|
|
[editField setDrawsBackground: didDrawBackground];
|
|
|
|
|
[nc removeObserver: self
|
|
|
|
|
name: NSControlTextDidEndEditingNotification
|
|
|
|
|
object: nil];
|
|
|
|
|
|
|
|
|
|
[[editField currentEditor] resignFirstResponder];
|
|
|
|
|
[self setNeedsDisplay: YES];
|
|
|
|
|
|
|
|
|
|
return e;
|
|
|
|
|
}
|
|
|
|
|
@end
|