/* 
   IMModelWindow.m

   Model window used for moving, sizing, and editing of visual components.

   Copyright (C) 1996, 1997 Free Software Foundation, Inc.

   Author:	Scott Christley <scottc@net-community.com>
   Date: 	August 1996
   Author:  Felipe A. Rodriguez <far@ix.netcom.com>
   Date:	Sept 1998
   
   This file is part of the mySTEP Library and is provided
   under the terms of the GNU Library General Public License.
*/ 

#include <AppKit/AppKit.h>

#include "IMModelWindow.h"
#include "IMModelView.h"
#include "Controller.h"


@implementation IMModelWindow

- (id) initWithContentRect:(NSRect)contentRect
				 styleMask:(unsigned int)aStyle
				 backing:(NSBackingStoreType)bufferingType
				 defer:(BOOL)flag
				 screen:aScreen
{
	selection = [[NSMutableSet alloc] init];

	return [super initWithContentRect: contentRect
				  styleMask: aStyle
				  backing: bufferingType
				  defer: flag
				  screen: aScreen];
}

- (NSMutableSet *) selectedElements
{
	return selection;
}

- (void) sendEvent:(NSEvent *)event
{
NSRect h = {{0,0},{6,6}}, oh = {{-999,0},{6,6}};
NSRect oldRect = {{0,0},{0,0}};	
										// intercept NSWindow's sendEvent: so
										// that controls within this window do
    									// not behave like controls while in
										// modelling mode
	if([(Controller *)[NSApp delegate] testInterface])
		{
		[super sendEvent:event];						// user has selected
		return;											// test interface mode
		}
										// intercept NSWindow's sendEvent: so
	switch ([event type])				// that controls within this window
    	{								// do not behave like controls
    	case NSLeftMouseDown:				
			{												// Left mouse down
			IMHandleType handle;
			NSPoint p = [event locationInWindow];
			NSView *v = [_contentView hitTestForHandle: &handle atPoint: p];

			if (v)									// if a handle was grabbed
	  			{									// do size tracking
				BOOL done, mouseUp;
				NSEvent *e;
				NSRect newf, old_frame = [v frame];
				NSPoint newp, diff, newd;
				NSSize old_size;
				unsigned int event_mask = NSLeftMouseDownMask | 
										NSLeftMouseUpMask | NSMouseMovedMask | 
										NSLeftMouseDraggedMask | 
										NSRightMouseDraggedMask;

				done = NO;
				newf = old_frame;
				diff.x = old_frame.origin.x - p.x;
				diff.y = old_frame.origin.y - p.y;	
				[[self contentView] lockFocus];
													// begin a modal loop in
			while (!done)							// order to track the mouse
				{
				e = [NSApp nextEventMatchingMask:event_mask 
						   untilDate:nil
						   inMode:nil 
						   dequeue:YES];
	
				if ([e type] == NSLeftMouseUp)			// If mouse went up
					done = YES;							// then we are done
				else	
					{
					newp = [e locationInWindow];

					switch (handle)
						{								// x origin is fixed
						case IMBottomRightHandle:		
							newd.x = newp.x - p.x;
							newd.y = newp.y - p.y;
							newf.origin.y = old_frame.origin.y + newd.y;
							newf.size.width = old_frame.size.width + newd.x;
							newf.size.height = old_frame.size.height - newd.y;
 
							h.origin = newf.origin;		// calc handle origin
							h.origin.x += newf.size.width;
							h.origin.y -= 6;
							break;

		     			case IMBottomMiddleHandle:			// width is fixed
							newd.y = newp.y - p.y;
							newf.origin.y = old_frame.origin.y + newd.y;
							newf.size.height = old_frame.size.height - newd.y;

							h.origin = newf.origin;		// calc handle origin
							h.origin.x += ((newf.size.width/2) - 2);
							h.origin.y -= 6;
							break;

		      			case IMBottomLeftHandle:
							newd.x = newp.x - p.x;
							newd.y = newp.y - p.y;
							newf.origin.x = old_frame.origin.x + newd.x;
							newf.origin.y = old_frame.origin.y + newd.y;
							newf.size.width = old_frame.size.width - newd.x;
							newf.size.height = old_frame.size.height - newd.y;

							h.origin = newf.origin;		// calc handle origin
							h.origin.x -= 6;
							h.origin.y -= 6;
							break;
														// origin is fixed
		      			case IMTopRightHandle:
							newf.size.width = newp.x - newf.origin.x;
							newf.size.height = newp.y - newf.origin.y;

							h.origin = newf.origin;		// calc handle origin
							h.origin.x += newf.size.width;
							h.origin.y += newf.size.height;
							break;

		     	 		case IMTopMiddleHandle:
							newd.y = newp.y - p.y;
							newf.size.height = old_frame.size.height + newd.y;

							h.origin = newf.origin;		// calc handle origin
							h.origin.x += ((newf.size.width/2) - 2);
							h.origin.y += newf.size.height;
							break;

		      			case IMTopLeftHandle:
							newd.x = newp.x - p.x;
							newd.y = newp.y - p.y;
							newf.origin.x = old_frame.origin.x + newd.x;
							newf.size.width = old_frame.size.width - newd.x;
							newf.size.height = old_frame.size.height + newd.y;

							h.origin = newf.origin;		// calc handle origin
							h.origin.x -= 6;
							h.origin.y += newf.size.height;
							break;

		      			case IMRightMiddleHandle:
							newd.x = newp.x - p.x;
							newf.size.width = old_frame.size.width + newd.x;

							h.origin = newf.origin;		// calc handle origin
							h.origin.x += newf.size.width;
							h.origin.y += ((newf.size.height/2) - 3);
							break;

		      			case IMLeftMiddleHandle:
							newd.x = newp.x - p.x;
							newf.origin.x = old_frame.origin.x + newd.x;
							newf.size.width = old_frame.size.width - newd.x;

							h.origin = newf.origin;		// calc handle origin
							h.origin.x -= 6;
							h.origin.y += ((newf.size.height/2) - 3);
							break;

		      		default:
						   NSLog(@"IMWindow internal error: unknown handle\n");
		      		}
														// highlight the handle 
														// which was grabbed
				[[NSColor darkGrayColor] set];
				if(oh.origin.x != -999)		
					NSRectFillUsingOperation(oh, NSCompositeXOR);
				NSRectFillUsingOperation(h, NSCompositeXOR);
				oh = h;										// save old rect
				[[NSColor lightGrayColor] set];

				if (newf.size.width < 0)
		      		newf.size.width = 0;
		    	if (newf.size.height < 0)
		      		newf.size.height = 0;
		    	[v setFrame: newf];
				}

//fprintf(stderr, " tracking loop\n");

			if(oldRect.size.width != 0)
				NSFrameRectWithWidthUsingOperation(oldRect,1., NSCompositeXOR);
								
			NSFrameRectWithWidthUsingOperation(newf,1., NSCompositeXOR);
			oldRect = newf;
			}

	    [[self contentView] unlockFocus];

	    [self display];
	    [v display];
	    break;
		}

	if (!v)
		v = [_contentView hitTest: p];

	NSLog(@"IMModelWindow");

	if (v && v != _contentView)							// Do movement tracking
		{
	    BOOL done, mouseUp;
	    NSEvent *e;
	    NSRect new_frame, old_frame = [v frame];
	    NSPoint new_point, diff;
	    unsigned int event_mask = NSLeftMouseDownMask | NSLeftMouseUpMask |
	      							NSMouseMovedMask | NSLeftMouseDraggedMask 
	      							| NSRightMouseDraggedMask;

						// Determine the distance between the view's frame
						// and the mouse location, this will be used to 
						// determine the new view's frame when moving the mouse
	    diff.x = old_frame.origin.x - p.x;
	    diff.y = old_frame.origin.y - p.y;

	    [selection addObject: v];						// change the selection

	    done = NO;
	    new_frame = old_frame;
	    while (!done)
			{
			e = [NSApp nextEventMatchingMask:event_mask 
					   untilDate:nil
					   inMode:nil 
					   dequeue:YES];
		
			if ([e type] == NSLeftMouseUp)					// If mouse went up
		  		done = YES;									// we are done
			else
		  		{
				new_point = [e locationInWindow];
				new_frame.origin.x = new_point.x + diff.x;
				new_frame.origin.y = new_point.y + diff.y;
				[v setFrame: new_frame];
				[v display];
		  		}
			}

	    [self display];
//	    [v display];
	    [[self contentView] display];
		}
	else
		NSLog(@"IMModelWindow no v :");

			break;
			}					// catch but don't handle these in model mode
		case NSLeftMouseUp:								// Left mouse up
		case NSRightMouseDown:							// Right mouse down
		case NSRightMouseUp:							// Right mouse up
		case NSMouseMoved:								// Mouse moved
		case NSLeftMouseDragged:						// Left mouse dragged
		case NSRightMouseDragged:						// Right mouse dragged
		case NSMouseEntered:							// Mouse entered
		case NSMouseExited:								// Mouse exited
		case NSKeyDown:									// Key down
		case NSKeyUp:									// Key up
		case NSFlagsChanged:							// Flags changed
		case NSPeriodic:
			break;
		}
}

@end
