From a9bd3b4784e0355c14d867e89a1d46b902841617 Mon Sep 17 00:00:00 2001 From: Richard Frith-MacDonald Date: Thu, 16 Dec 1999 18:06:22 +0000 Subject: [PATCH] Loads of stuff! git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/apps/gorm/trunk@5538 72102866-910b-0410-8b05-ffd578937521 --- ChangeLog | 6 + Gorm.m | 275 ++++++++++++++++------ GormDocument.h | 1 + GormDocument.m | 4 +- GormPalettesManager.m | 12 +- GormPrivate.h | 33 ++- GormViewKnobs.m | 99 ++++++++ GormWindowEditor.m | 534 ++++++++++++++++++++++++++++-------------- 8 files changed, 713 insertions(+), 251 deletions(-) diff --git a/ChangeLog b/ChangeLog index f28f4737..f7d10978 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +Thu Dec 16 15:45:00 1999 Richard Frith-Macdonald + + * GormWindowEditor.m: Implemented support for moving and resizing + subviews within a window. + * Gorm.m: Implemented edit menu (mostly) with cut and paste. + Thu Dec 16 6:54:00 1999 Richard Frith-Macdonald * GormWindowEditor.m: Implemented selection mechanism including diff --git a/Gorm.m b/Gorm.m index 38cee815..4a4d338d 100644 --- a/Gorm.m +++ b/Gorm.m @@ -80,27 +80,24 @@ NSString *IBDidEndTestingInterfaceNotification return YES; } -- (id) beginTesting: (id)sender +- (id) copy: (id)sender { - if (isTesting == YES) - { - return nil; - } - else - { - NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; + if ([[selectionOwner selection] count] == 0 + || [selectionOwner respondsToSelector: @selector(copySelection)] == NO) + return nil; + [selectionOwner copySelection]; + return self; +} - [nc postNotificationName: IBWillBeginTestingInterfaceNotification - object: self]; - isTesting = YES; - if ([selectionOwner conformsToProtocol: @protocol(IBEditors)] == YES) - { - [(id)selectionOwner makeSelectionVisible: NO]; - } - [nc postNotificationName: IBDidBeginTestingInterfaceNotification - object: self]; - return self; - } +- (id) cut: (id)sender +{ + if ([[selectionOwner selection] count] == 0 + || [selectionOwner respondsToSelector: @selector(copySelection)] == NO + || [selectionOwner respondsToSelector: @selector(deleteSelection)] == NO) + return nil; + [selectionOwner copySelection]; + [selectionOwner deleteSelection]; + return self; } - (void) dealloc @@ -108,7 +105,6 @@ NSString *IBDidEndTestingInterfaceNotification NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; [nc removeObserver: self]; - RELEASE(gormMenu); RELEASE(infoPanel); RELEASE(inspectorsManager); RELEASE(palettesManager); @@ -116,6 +112,15 @@ NSString *IBDidEndTestingInterfaceNotification [super dealloc]; } +- (id) delete: (id)sender +{ + if ([[selectionOwner selection] count] == 0 + || [selectionOwner respondsToSelector: @selector(deleteSelection)] == NO) + return nil; + [selectionOwner deleteSelection]; + return self; +} + - (id) endTesting: (id)sender { if (isTesting == NO) @@ -139,11 +144,6 @@ NSString *IBDidEndTestingInterfaceNotification } } -- (NSMenu*) gormMenu -{ - return gormMenu; -} - - (void) handleNotification: (NSNotification*)notification { NSString *name = [notification name]; @@ -166,6 +166,16 @@ NSString *IBDidEndTestingInterfaceNotification } } +- (id) infoPanel: (id) sender +{ + if (infoPanel == nil) + { + infoPanel = [InfoPanel new]; + } + [infoPanel orderFront: nil]; + return self; +} + - (id) init { self = [super init]; @@ -183,8 +193,6 @@ NSString *IBDidEndTestingInterfaceNotification name: IBWillCloseDocumentNotification object: nil]; - gormMenu = [[NSMenu alloc] initWithTitle: @"Gorm"]; - /* * Make sure the palettes manager exists, so that the editors and * inspectors provided in the standard palettes are available. @@ -194,6 +202,12 @@ NSString *IBDidEndTestingInterfaceNotification return self; } +- (id) inspector: (id) sender +{ + [[[self inspectorsManager] panel] orderFront: nil]; + return self; +} + - (GormInspectorsManager*) inspectorsManager { if (inspectorsManager == nil) @@ -208,7 +222,12 @@ NSString *IBDidEndTestingInterfaceNotification return isTesting; } -- (id) makeNewDocument: (id) sender +- (id) loadPalette: (id) sender +{ + return [[self palettesManager] openPalette: sender]; +} + +- (id) newApplication: (id) sender { id doc = [GormDocument new]; @@ -219,7 +238,7 @@ NSString *IBDidEndTestingInterfaceNotification return doc; } -- (id) openDocument: (id) sender +- (id) open: (id) sender { GormDocument *doc = [GormDocument new]; @@ -238,11 +257,6 @@ NSString *IBDidEndTestingInterfaceNotification return doc; } -- (id) openPalette: (id) sender -{ - return [[self palettesManager] openPalette: sender]; -} - - (GormPalettesManager*) palettesManager { if (palettesManager == nil) @@ -252,34 +266,31 @@ NSString *IBDidEndTestingInterfaceNotification return palettesManager; } -- (id) runInfoPanel: (id) sender -{ - if (infoPanel == nil) - { - infoPanel = [InfoPanel new]; - } - [infoPanel orderFront: nil]; - return self; -} - -- (id) runGormInspectors: (id) sender -{ - [[[self inspectorsManager] panel] orderFront: nil]; - return self; -} - -- (id) runGormPalettes: (id) sender +- (id) palettes: (id) sender { [[[self palettesManager] panel] orderFront: self]; return self; } +- (id) paste: (id)sender +{ + if ([selectionOwner respondsToSelector: @selector(pasteInSelection)] == NO) + return nil; + [selectionOwner pasteInSelection]; + return self; +} + - (id) revertToSaved: (id)sender { NSLog(@"Revert to save not yet implemented"); return nil; } +- (id) save: (id)sender +{ + return [(id)activeDocument save: sender]; +} + - (id) saveAll: (id)sender { NSEnumerator *e = [documents objectEnumerator]; @@ -289,20 +300,21 @@ NSString *IBDidEndTestingInterfaceNotification { if ([[doc window] isDocumentEdited] == YES) { - [doc saveDocument: sender]; + [doc save: sender]; } } return self; } -- (id) saveAsDocument: (id)sender +- (id) saveAs: (id)sender { - return [(id)activeDocument saveAsDocument: sender]; + return [(id)activeDocument saveAs: sender]; } -- (id) saveDocument: (id)sender +- (id) selectAll: (id)sender { - return [(id)activeDocument saveDocument: sender]; + /* FIXME */ + return nil; } - (id) selectionOwner @@ -314,6 +326,95 @@ NSString *IBDidEndTestingInterfaceNotification { return [[selectionOwner selection] lastObject]; } + +- (id) setName: (id)sender +{ + /* FIXME */ + return nil; +} + +- (id) testInterface: (id)sender +{ + if (isTesting == YES) + { + return nil; + } + else + { + NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; + + [nc postNotificationName: IBWillBeginTestingInterfaceNotification + object: self]; + isTesting = YES; + if ([selectionOwner conformsToProtocol: @protocol(IBEditors)] == YES) + { + [(id)selectionOwner makeSelectionVisible: NO]; + } + [nc postNotificationName: IBDidBeginTestingInterfaceNotification + object: self]; + return self; + } +} + +- (BOOL) validateMenuItem: (NSMenuItem*)item +{ + SEL action = [item action]; + + if (sel_eq(action, @selector(save:)) + || sel_eq(action, @selector(saveAs:)) + || sel_eq(action, @selector(saveAll:))) + { + if (activeDocument == nil) + return NO; + } + + if (sel_eq(action, @selector(revertToSaved:))) + { + if (activeDocument == nil) + return NO; + } + + if (sel_eq(action, @selector(testInterface:))) + { + if (activeDocument == nil) + return NO; + } + + if (sel_eq(action, @selector(copy:))) + { + if ([[selectionOwner selection] count] == 0) + return NO; + return [selectionOwner respondsToSelector: @selector(copySelection)]; + } + + if (sel_eq(action, @selector(cut:))) + { + if ([[selectionOwner selection] count] == 0) + return NO; + return ([selectionOwner respondsToSelector: @selector(copySelection)] + && [selectionOwner respondsToSelector: @selector(deleteSelection)]); + } + + if (sel_eq(action, @selector(delete:))) + { + if ([[selectionOwner selection] count] == 0) + return NO; + return [selectionOwner respondsToSelector: @selector(deleteSelection)]; + } + + if (sel_eq(action, @selector(paste:))) + { + return [selectionOwner respondsToSelector: @selector(pasteInSelection)]; + } + + if (sel_eq(action, @selector(setName:))) + { + if ([[selectionOwner selection] count] != 1) + return NO; + } + + return YES; +} @end int @@ -335,14 +436,14 @@ main(void) */ NSApp = theApp = [Gorm new]; - mainMenu = [theApp gormMenu]; + mainMenu = [[NSMenu alloc] initWithTitle: @"Gorm"]; /* * Set up info menu. */ aMenu = [NSMenu new]; [aMenu addItemWithTitle: @"Info Panel..." - action: @selector(runInfoPanel:) + action: @selector(infoPanel:) keyEquivalent: @""]; [aMenu addItemWithTitle: @"Help..." action: NULL @@ -358,16 +459,16 @@ main(void) */ aMenu = [NSMenu new]; [aMenu addItemWithTitle: @"Open..." - action: @selector(openDocument:) + action: @selector(open:) keyEquivalent: @"o"]; [aMenu addItemWithTitle: @"New Application" - action: @selector(makeNewDocument:) + action: @selector(newApplication:) keyEquivalent: @"n"]; [aMenu addItemWithTitle: @"Save" - action: @selector(saveDocument:) + action: @selector(save:) keyEquivalent: @"s"]; [aMenu addItemWithTitle: @"Save As..." - action: @selector(saveAsDocument:) + action: @selector(saveAs:) keyEquivalent: @"S"]; [aMenu addItemWithTitle: @"Save All" action: @selector(saveAll:) @@ -376,7 +477,7 @@ main(void) action: @selector(revertToSaved:) keyEquivalent: @"u"]; [aMenu addItemWithTitle: @"Test Interface" - action: @selector(beginTesting:) + action: @selector(testInterface:) keyEquivalent: @"r"]; menuItem = [mainMenu addItemWithTitle: @"Document" action: NULL @@ -384,18 +485,46 @@ main(void) [mainMenu setSubmenu: aMenu forItem: menuItem]; RELEASE(aMenu); + /* + * Set up edit menu. + */ + aMenu = [NSMenu new]; + [aMenu addItemWithTitle: @"Cut" + action: @selector(cut:) + keyEquivalent: @"x"]; + [aMenu addItemWithTitle: @"Copy" + action: @selector(copy:) + keyEquivalent: @"c"]; + [aMenu addItemWithTitle: @"Paste" + action: @selector(paste:) + keyEquivalent: @"v"]; + [aMenu addItemWithTitle: @"Delete" + action: @selector(delete:) + keyEquivalent: @""]; + [aMenu addItemWithTitle: @"Select All" + action: @selector(selectAll:) + keyEquivalent: @"a"]; + [aMenu addItemWithTitle: @"Set Name..." + action: @selector(setName:) + keyEquivalent: @""]; + menuItem = [mainMenu addItemWithTitle: @"Edit" + action: NULL + keyEquivalent: @""]; + [mainMenu setSubmenu: aMenu forItem: menuItem]; + RELEASE(aMenu); + /* * Set up tools menu. */ aMenu = [NSMenu new]; [aMenu addItemWithTitle: @"Inspector..." - action: @selector(runGormInspectors:) + action: @selector(inspector:) keyEquivalent: @""]; [aMenu addItemWithTitle: @"Palettes..." - action: @selector(runGormPalettes:) + action: @selector(palettes:) keyEquivalent: @""]; [aMenu addItemWithTitle: @"Load Palette..." - action: @selector(openPalette:) + action: @selector(loadPalette:) keyEquivalent: @""]; menuItem = [mainMenu addItemWithTitle: @"Tools" action: NULL @@ -422,6 +551,20 @@ main(void) [mainMenu setSubmenu: windowsMenu forItem: menuItem]; RELEASE(windowsMenu); + /* + * Set up Services menu + */ + aMenu = [NSMenu new]; + menuItem = [mainMenu addItemWithTitle: @"Services" + action: NULL + keyEquivalent: @""]; + [mainMenu setSubmenu: aMenu forItem: menuItem]; + RELEASE(aMenu); + + [mainMenu addItemWithTitle: @"Hide" + action: @selector(hide:) + keyEquivalent: @"h"]; + [mainMenu addItemWithTitle: @"Quit" action: @selector(terminate:) keyEquivalent: @"q"]; diff --git a/GormDocument.h b/GormDocument.h index 33d21df9..6b2a4768 100644 --- a/GormDocument.h +++ b/GormDocument.h @@ -31,6 +31,7 @@ NSScrollView *scrollView; id objectsView; BOOL hiddenDuringTest; + NSMenu *savedMenu; NSMenuItem *quitItem; /* Replaced during test */ } - (void) addConnector: (id)aConnector; diff --git a/GormDocument.m b/GormDocument.m index 966aa659..3fc04a93 100644 --- a/GormDocument.m +++ b/GormDocument.m @@ -459,6 +459,7 @@ static NSImage *classesImage = nil; [testMenu addItemWithTitle: @"Quit" action: @selector(endTesting:) keyEquivalent: @"q"]; + savedMenu = RETAIN([NSApp mainMenu]); [NSApp setMainMenu: testMenu]; [keyWindow makeKeyAndOrderFront: self]; RELEASE(testMenu); @@ -489,7 +490,8 @@ static NSImage *classesImage = nil; /* * restore the main menu. */ - [NSApp setMainMenu: [(Gorm*)NSApp gormMenu]]; + [NSApp setMainMenu: savedMenu]; + DESTROY(savedMenu); } [window orderFront: self]; [window setExcludedFromWindowsMenu: NO]; diff --git a/GormPalettesManager.m b/GormPalettesManager.m index 8631c1cb..38dbb81c 100644 --- a/GormPalettesManager.m +++ b/GormPalettesManager.m @@ -1,4 +1,4 @@ -/* GormPalettesPanager.m +/* GormPalettesManager.m * * Copyright (C) 1999 Free Software Foundation, Inc. * @@ -24,6 +24,16 @@ #include "GormPrivate.h" +@interface GormPalettePanel : NSPanel +@end + +@implementation GormPalettePanel +- (BOOL) canBecomeKey +{ + return NO; +} +@end + @interface GormPaletteView : NSView { NSPoint mouseDownPoint; diff --git a/GormPrivate.h b/GormPrivate.h index e170a415..7c13801f 100644 --- a/GormPrivate.h +++ b/GormPrivate.h @@ -16,24 +16,34 @@ id infoPanel; GormInspectorsManager *inspectorsManager; GormPalettesManager *palettesManager; - id selectionOwner; - id activeDocument; + id selectionOwner; + id activeDocument; NSMutableArray *documents; - NSMenu *gormMenu; BOOL isTesting; } - (id) activeDocument; -- (id) beginTesting: (id)sender; -- (id) endTesting: (id)sender; -- (NSMenu*) gormMenu; - (void) handleNotification: (NSNotification*)aNotification; - (GormInspectorsManager*) inspectorsManager; -- (id) makeNewDocument: (id) sender; -- (id) openPalette: (id) sender; - (GormPalettesManager*) palettesManager; -- (id) runInfoPanel: (id) sender; -- (id) runGormInspectors: (id) sender; -- (id) runGormPalettes: (id) sender; + +- (id) copy: (id)sender; +- (id) cut: (id)sender; +- (id) delete: (id)sender; +- (id) endTesting: (id)sender; +- (id) infoPanel: (id) sender; +- (id) inspector: (id) sender; +- (id) newApplication: (id) sender; +- (id) loadPalette: (id) sender; +- (id) open: (id)sender; +- (id) palettes: (id) sender; +- (id) paste: (id)sender; +- (id) revertToSaved: (id)sender; +- (id) save: (id)sender; +- (id) saveAll: (id)sender; +- (id) saveAs: (id)sender; +- (id) selectAll: (id)sender; +- (id) setName: (id)sender; +- (id) testInterface: (id)sender; @end /* @@ -43,5 +53,6 @@ void GormDrawKnobsForRect(NSRect aFrame); NSRect GormExtBoundsForRect(NSRect aFrame); IBKnobPosition GormKnobHitInRect(NSRect aFrame, NSPoint p); void GormShowFastKnobFills(void); +void GormShowFrameWithKnob(NSRect aRect, IBKnobPosition aKnob); #endif diff --git a/GormViewKnobs.m b/GormViewKnobs.m index a4c6a68c..78fc5baf 100644 --- a/GormViewKnobs.m +++ b/GormViewKnobs.m @@ -5,6 +5,7 @@ Author: Gerrit van Dyk Date: 1999 + Modified and extended by: Richard Frith-Macdonald This file is part of the GNUstep Interface Modeller Application. @@ -82,6 +83,104 @@ GormShowFastKnobFills(void) dkgrayRectCount = 0; } +static void +_showLitKnobForRect(NSGraphicsContext *ctxt, NSRect frame, IBKnobPosition aKnob) +{ + float dx, dy; + BOOL oddx, oddy; + NSRect r; + + if (!KNOB_WIDTH) + { + calcKnobSize(); + } + dx = NSWidth(frame) / 2.0; + dy = NSHeight(frame) / 2.0; + oddx = (floor(dx) != dx); + oddy = (floor(dy) != dy); + frame.size.width = KNOB_WIDTH; + frame.size.height = KNOB_HEIGHT; + frame.origin.x -= ((KNOB_WIDTH - 1.0) / 2.0); + frame.origin.y -= ((KNOB_HEIGHT - 1.0) / 2.0); + + if (aKnob == IBBottomLeftKnobPosition) + r = frame; + frame.origin.y += dy; + if (oddy) + frame.origin.y -= 0.5; + if (aKnob == IBMiddleLeftKnobPosition) + r = frame; + frame.origin.y += dy; + if (oddy) + frame.origin.y += 0.5; + if (aKnob == IBTopLeftKnobPosition) + r = frame; + frame.origin.x += dx; + if (oddx) + frame.origin.x -= 0.5; + if (aKnob == IBTopMiddleKnobPosition) + r = frame; + frame.origin.x += dx; + if (oddx) + frame.origin.x += 0.5; + if (aKnob == IBTopRightKnobPosition) + r = frame; + frame.origin.y -= dy; + if (oddy) + frame.origin.y -= 0.5; + if (aKnob == IBMiddleRightKnobPosition) + r = frame; + frame.origin.y -= dy; + if (oddy) + frame.origin.y += 0.5; + if (aKnob == IBBottomRightKnobPosition) + r = frame; + frame.origin.x -= dx; + if (oddx) + frame.origin.x += 0.5; + if (aKnob == IBBottomMiddleKnobPosition) + r = frame; + + r.origin.x += 1.0; + r.origin.y -= 1.0; + DPSsetgray(ctxt, NSBlack); + DPSrectfill(ctxt, NSMinX(r), NSMinY(r), NSWidth(r), NSHeight(r)); + r.origin.x -= 1.0; + r.origin.y += 1.0; + DPSsetgray(ctxt, NSWhite); + DPSrectfill(ctxt, NSMinX(r), NSMinY(r), NSWidth(r), NSHeight(r)); +} + +void +GormShowFrameWithKnob(NSRect aRect, IBKnobPosition aKnob) +{ + NSGraphicsContext *ctxt = [NSGraphicsContext currentContext]; + NSRect r = aRect; + + /* + * We draw a wire-frame around the rectangle. + */ + r.origin.x -= 0.5; + r.origin.y -= 0.5; + r.size.width += 1.0; + r.size.height += 1.0; + 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); + + if (aKnob != IBNoneKnobPosition) + { + /* + * NB. we use the internal rectangle for calculating the knob position. + */ + _showLitKnobForRect(ctxt, aRect, aKnob); + } +} + void GormDrawKnobsForRect(NSRect aRect) { diff --git a/GormWindowEditor.m b/GormWindowEditor.m index f133a450..b321ba4d 100644 --- a/GormWindowEditor.m +++ b/GormWindowEditor.m @@ -123,7 +123,7 @@ NSRectFromPoints(NSPoint p0, NSPoint p1) - (NSSize) minimumSizeFromKnobPosition: (IBKnobPosition)position { - return NSZeroSize; /* Minimum resize permitted */ + return NSMakeSize(5, 5); /* Minimum resize permitted */ } - (void) placeView: (NSRect)newFrame @@ -204,30 +204,16 @@ NSRectFromPoints(NSPoint p0, NSPoint p1) NSEnumerator *enumerator; NSView *view = nil; IBKnobPosition knob = IBNoneKnobPosition; - NSDate *future = [NSDate distantFuture]; - BOOL acceptsMouseMoved; NSPoint mouseDownPoint; - NSPoint lastPoint; - NSPoint point; - unsigned eventMask; - NSEvent *e; - - /* - * Save window state info. - */ - acceptsMouseMoved = [[self window] acceptsMouseMovedEvents]; + NSMutableArray *array; mouseDownPoint = [theEvent locationInWindow]; - eventMask = NSLeftMouseDownMask | NSLeftMouseUpMask - | NSLeftMouseDraggedMask | NSMouseMovedMask | NSPeriodicMask; - [[self window] setAcceptsMouseMovedEvents: YES]; /* - * 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 we have any subviews selected, 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) + if ([selection count] != 0) { enumerator = [selection objectEnumerator]; while ((view = [enumerator nextObject]) != nil) @@ -243,8 +229,12 @@ NSRectFromPoints(NSPoint p0, NSPoint p1) if ([selection count] != 1) { [self selectObjects: [NSArray arrayWithObject: view]]; - [self makeSelectionVisible: NO]; } + [self makeSelectionVisible: NO]; + [self lockFocus]; + GormShowFrameWithKnob([view frame], knob); + [self unlockFocus]; + [[self window] flushWindow]; break; } } @@ -260,8 +250,6 @@ NSRectFromPoints(NSPoint p0, NSPoint p1) */ if ([theEvent modifierFlags] & NSShiftKeyMask) { - NSMutableArray *array; - /* * remove this view from the selection. */ @@ -287,7 +275,15 @@ NSRectFromPoints(NSPoint p0, NSPoint p1) if (view == nil) { view = [super hitTest: mouseDownPoint]; - if (view != nil && view != self) + if (view == self) + { + /* + * Clicked on an window background - empty the selection. + */ + [self makeSelectionVisible: NO]; + [self selectObjects: [NSArray array]]; + } + else if (view != nil) { /* * Clicked on an unselected subview. @@ -305,8 +301,6 @@ NSRectFromPoints(NSPoint p0, NSPoint p1) } else { - NSMutableArray *array; - /* * extend the selection to include this subview. */ @@ -333,19 +327,103 @@ NSRectFromPoints(NSPoint p0, NSPoint p1) view = nil; } - if (view == self) + /* + * Having determined the current selection, we now handle events. + */ + if (view != nil) { - NSGraphicsContext *ctxt = [NSGraphicsContext currentContext]; - NSEnumerator *enumerator; - NSMutableArray *array; + NSDate *future = [NSDate distantFuture]; + NSView *subview; + BOOL acceptsMouseMoved; + BOOL dragStarted = NO; + unsigned eventMask; + NSEvent *e; NSEventType eType; NSRect r; + NSPoint maxMouse; + NSPoint minMouse; + NSRect lastRect = [view frame]; + NSPoint lastPoint = mouseDownPoint; + NSPoint point = mouseDownPoint; + + eventMask = NSLeftMouseDownMask | NSLeftMouseUpMask + | NSLeftMouseDraggedMask | NSMouseMovedMask | NSPeriodicMask; + [[self window] setAcceptsMouseMovedEvents: YES]; /* - * Clicked on an window background - make window the selection. + * Save window state info. */ - [self makeSelectionVisible: NO]; - [self selectObjects: [NSArray arrayWithObject: edited]]; + acceptsMouseMoved = [[self window] acceptsMouseMovedEvents]; + [self lockFocus]; + + /* + * Get size limits for resizing subview and calculate maximum + * and minimum mouse positions that won't cause us to exceed + * those limits. + */ + if (view != self && knob != IBNoneKnobPosition) + { + NSSize max = [view maximumSizeFromKnobPosition: knob]; + NSSize min = [view minimumSizeFromKnobPosition: knob]; + + r = [self bounds]; + minMouse = NSMakePoint(NSMinX(r), NSMinY(r)); + maxMouse = NSMakePoint(NSMaxX(r), NSMaxY(r)); + r = [view frame]; + switch (knob) + { + case IBBottomLeftKnobPosition: + maxMouse.x = NSMaxX(r) - min.width; + minMouse.x = NSMaxX(r) - max.width; + maxMouse.y = NSMaxY(r) - min.height; + minMouse.y = NSMaxY(r) - max.height; + break; + + case IBMiddleLeftKnobPosition: + maxMouse.x = NSMaxX(r) - min.width; + minMouse.x = NSMaxX(r) - max.width; + break; + + case IBTopLeftKnobPosition: + maxMouse.x = NSMaxX(r) - min.width; + minMouse.x = NSMaxX(r) - max.width; + maxMouse.y = NSMinY(r) + max.height; + minMouse.y = NSMinY(r) + min.height; + break; + + case IBTopMiddleKnobPosition: + maxMouse.y = NSMinY(r) + max.height; + minMouse.y = NSMinY(r) + min.height; + break; + + case IBTopRightKnobPosition: + maxMouse.x = NSMinX(r) + max.width; + minMouse.x = NSMinX(r) + min.width; + maxMouse.y = NSMinY(r) + max.height; + minMouse.y = NSMinY(r) + min.height; + break; + + case IBMiddleRightKnobPosition: + maxMouse.x = NSMinX(r) + max.width; + minMouse.x = NSMinX(r) + min.width; + break; + + case IBBottomRightKnobPosition: + maxMouse.x = NSMinX(r) + max.width; + minMouse.x = NSMinX(r) + min.width; + maxMouse.y = NSMaxY(r) - min.height; + minMouse.y = NSMaxY(r) - max.height; + break; + + case IBBottomMiddleKnobPosition: + maxMouse.y = NSMaxY(r) - min.height; + minMouse.y = NSMaxY(r) - max.height; + break; + + case IBNoneKnobPosition: + break; /* NOT REACHED */ + } + } /* * Track mouse movements until left mouse up. @@ -353,8 +431,6 @@ NSRectFromPoints(NSPoint p0, NSPoint p1) * movement when a periodic event arives (every 20th of a second) * in order to avoid excessive amounts of drawing. */ - lastPoint = mouseDownPoint; - [self lockFocus]; [NSEvent startPeriodicEventsAfterDelay: 0.1 withPeriod: 0.05]; e = [NSApp nextEventMatchingMask: eventMask untilDate: future @@ -368,34 +444,147 @@ NSRectFromPoints(NSPoint p0, NSPoint p1) point = [self convertPoint: [e locationInWindow] fromView: nil]; } - if (eType == NSPeriodic && NSEqualPoints(point, lastPoint) == NO) + else if (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. - * FIXME - does the fact that we need to redisplay a - * rectangle slightly larger than the one we drew mean that - * there is a drawing bug? - */ [[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); + + if (view == self) + { + /* + * Handle wire-frame for selecting contents of window. + * + * FIXME - there has to be a more efficient way to + * restore the display under the box. + * FIXME - does the fact that we need to redisplay a + * rectangle slightly larger than the one we drew mean + * that there is a drawing bug? + */ + r = NSRectFromPoints(lastPoint, mouseDownPoint); + lastPoint = point; + r.origin.x--; + r.origin.y--; + r.size.width += 2; + r.size.height += 2; + [self displayRect: r]; + r = NSRectFromPoints(point, mouseDownPoint); + GormShowFrameWithKnob(r, IBNoneKnobPosition); + } + else if (knob == IBNoneKnobPosition) + { + float xDiff = point.x - lastPoint.x; + float yDiff = point.y - lastPoint.y; + + lastPoint = point; + if (dragStarted == NO) + { + /* + * Remove selection knobs before moving selection. + */ + dragStarted = YES; + [self makeSelectionVisible: NO]; + } + if ([theEvent modifierFlags] & NSControlKeyMask) + { + NSLog(@"Control key not yet supported"); + /* FIXME */ + } + else + { + enumerator = [selection objectEnumerator]; + while ((subview = [enumerator nextObject]) != nil) + { + NSRect oldFrame = [subview frame]; + + r = oldFrame; + r.origin.x += xDiff; + r.origin.y += yDiff; + [subview setFrame: r]; + [self displayRect: oldFrame]; + [subview display]; + } + } + } + else + { + float xDiff; + float yDiff; + + if (point.x < minMouse.x) + point.x = minMouse.x; + if (point.y < minMouse.y) + point.y = minMouse.y; + if (point.x > maxMouse.x) + point.x = maxMouse.x; + if (point.y > maxMouse.y) + point.y = maxMouse.y; + + xDiff = point.x - lastPoint.x; + yDiff = point.y - lastPoint.y; + lastPoint = point; + + r = GormExtBoundsForRect(lastRect); + r.origin.x--; + r.origin.y--; + r.size.width += 2; + r.size.height += 2; + [self displayRect: r]; + r = lastRect; + switch (knob) + { + case IBBottomLeftKnobPosition: + r.origin.x += xDiff; + r.origin.y += yDiff; + r.size.width -= xDiff; + r.size.height -= yDiff; + break; + + case IBMiddleLeftKnobPosition: + r.origin.x += xDiff; + r.size.width -= xDiff; + break; + + case IBTopLeftKnobPosition: + r.origin.x += xDiff; + r.size.width -= xDiff; + r.size.height += yDiff; + break; + + case IBTopMiddleKnobPosition: + r.size.height += yDiff; + break; + + case IBTopRightKnobPosition: + r.size.width += xDiff; + r.size.height += yDiff; + break; + + case IBMiddleRightKnobPosition: + r.size.width += xDiff; + break; + + case IBBottomRightKnobPosition: + r.origin.y += yDiff; + r.size.width += xDiff; + r.size.height -= yDiff; + break; + + case IBBottomMiddleKnobPosition: + r.origin.y += yDiff; + r.size.height -= yDiff; + break; + + case IBNoneKnobPosition: + break; /* NOT REACHED */ + } + lastRect = r; + GormShowFrameWithKnob(lastRect, knob); + } + + /* + * Flush any drawing performed for this event. + */ [[self window] enableFlushWindow]; [[self window] flushWindow]; - lastPoint = point; } e = [NSApp nextEventMatchingMask: eventMask untilDate: future @@ -406,65 +595,73 @@ NSRectFromPoints(NSPoint p0, NSPoint p1) [NSEvent stopPeriodicEvents]; /* - * restore the display + * Perform any necessary cleanup. */ - 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 - * and make them (if any) into our current selection. - */ - 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]; - } - } - else if (view != nil) - { - if (knob == IBNoneKnobPosition) - { - if ([theEvent modifierFlags] & NSControlKeyMask) - { - NSLog(@"Control key not yet supported"); - /* FIXME */ - } - else - { - [self makeSelectionVisible: YES]; - } - } - else + if (view == self) { /* - * Expecting to drag a handle. + * restore the display */ + r = NSRectFromPoints(lastPoint, mouseDownPoint); + r.origin.x--; + r.origin.y--; + r.size.width += 2; + r.size.height += 2; + [self displayRect: r]; + + /* + * Now finally check the selected rectangle to find the views in + * it and make them (if any) into our current selection. + */ + point = [self convertPoint: [e locationInWindow] + fromView: nil]; + r = NSRectFromPoints(point, mouseDownPoint); + array = [NSMutableArray arrayWithCapacity: 8]; + enumerator = [[self subviews] objectEnumerator]; + while ((subview = [enumerator nextObject]) != nil) + { + if (NSIntersectsRect(r, [subview frame]) == YES) + { + [array addObject: subview]; + } + } + if ([array count] > 0) + { + [self selectObjects: array]; + } } + else if (knob != IBNoneKnobPosition) + { + NSRect redrawRect; + + /* + * This was a subview resize, so we must clean up by removing + * the highlighted knob and the wireframe around the view. + */ + r = GormExtBoundsForRect([view frame]); + r.origin.x--; + r.origin.y--; + r.size.width += 2; + r.size.height += 2; + redrawRect = r; + [view setFrame: lastRect]; + r = GormExtBoundsForRect([view frame]); + r.origin.x--; + r.origin.y--; + r.size.width += 2; + r.size.height += 2; + redrawRect = NSUnionRect(r, redrawRect); + [self displayRect: redrawRect]; + [self makeSelectionVisible: YES]; + } + + [self unlockFocus]; + /* + * Restore state to what it was on entry. + */ + [[self window] setAcceptsMouseMovedEvents: acceptsMouseMoved]; } - [self makeSelectionVisible: YES]; - - /* - * Restore state to what it was on entry. - */ - [[self window] setAcceptsMouseMovedEvents: acceptsMouseMoved]; } } @@ -561,35 +758,11 @@ NSRectFromPoints(NSPoint p0, NSPoint p1) - (void) copySelection { - switch ([selection count]) + if ([selection count] > 0) { - 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; + [document copyObjects: selection + type: IBViewPboardType + toPasteboard: [NSPasteboard generalPasteboard]]; } } @@ -609,13 +782,15 @@ NSRectFromPoints(NSPoint p0, NSPoint p1) NSArray *a = [NSArray arrayWithArray: selection]; unsigned c = [a count]; - [selection removeAllObjects]; - [document resignSelectionForEditor: self]; + [self makeSelectionVisible: NO]; + [self selectObjects: [NSArray array]]; while (c-- > 0) { id obj = [a objectAtIndex: c]; [document detachObject: obj]; + [self setNeedsDisplayInRect: [obj frame]]; + [obj removeFromSuperview]; } } @@ -706,7 +881,6 @@ NSRectFromPoints(NSPoint p0, NSPoint p1) ASSIGN(document, aDocument); ASSIGN(edited, anObject); selection = [NSMutableArray new]; - [selection addObject: edited]; subeditors = [NSMutableArray new]; /* @@ -722,7 +896,7 @@ NSRectFromPoints(NSPoint p0, NSPoint p1) { if (flag == NO) { - if ([selection count] > 0 && [selection lastObject] != edited) + if ([selection count] > 0) { NSEnumerator *enumerator = [selection objectEnumerator]; NSView *view; @@ -768,6 +942,34 @@ NSRectFromPoints(NSPoint p0, NSPoint p1) - (void) pasteInSelection { + NSPasteboard *pb = [NSPasteboard generalPasteboard]; + NSMutableArray *array = [NSMutableArray arrayWithArray: selection]; + NSArray *views; + NSEnumerator *enumerator; + NSView *sub; + + /* + * Ask the document to get the copied 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. + */ + enumerator = [views objectEnumerator]; + while ((sub = [enumerator nextObject]) != nil) + { + if ([sub isKindOfClass: [NSView class]] == YES) + { + [self addSubview: sub]; + [array addObject: sub]; + } + } + [self makeSelectionVisible: NO]; + [self selectObjects: array]; + [self makeSelectionVisible: YES]; } - (BOOL) performDragOperation: (id)sender @@ -820,43 +1022,31 @@ NSRectFromPoints(NSPoint p0, NSPoint p1) { if (anArray != selection) { + unsigned count; + [selection removeAllObjects]; [selection addObjectsFromArray: anArray]; - if ([selection indexOfObjectIdenticalTo: edited] != NSNotFound) + + count = [selection count]; + + /* + * We can only select views that are direct subviews - discard others. + */ + while (count-- > 0) { - /* - * we have selected our edited window ... we can't have anything - * else selected at the same time. - */ - if ([selection count] > 0) + id o = [selection objectAtIndex: count]; + + if ([[self subviews] indexOfObjectIdenticalTo: o] == NSNotFound) { - [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]; - } + [selection removeObjectAtIndex: count]; } } + /* + * Now we must let the document (and hence the rest of the app) know + * about our new selection. + */ + [document setSelectionFromEditor: self]; } - /* - * Now we must let the document (and hence the rest of the app) know about - * our new selection. - */ - [document setSelectionFromEditor: self]; } - (NSArray*) selection