/****************************************************************************
 *   Copyright (C) 2004 by Arboretum Systems, Inc.                          *
 *   Technical administrator: Alain Mazy, hav@mazy.be                       *
 *   Lead program designer: Georges Jaroslaw, gjaro@arboretum.com           *
 *                                                                          *
 *   HyperEngine-AV is a video, audio and text editor that can be used to   *
 *   record, import, edit, process and arrange together video, sound and    *
 *   text. These are all achieved in the program's free-form document       *
 *   window, with no limitations to the number of tracks.                   *
 *   The purpose of this program is to provide to users at all levels of    *
 *   expertise a readily accessible tool enabling them to create movies,    *
 *   slide shows or presentations.                                          *
 *                                                                          *
 *   HyperEngine-AV itself is free software. However, plug-ins that can be  *
 *   used as add-ons to HyperEngine-AV may or may not be free software, at  *
 *   the discretion of each plug-in developer and as specified by these     *
 *   plug-ins' respective licenses.                                         *
 *   You can redistribute HyperEngine-AV itself 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.                                             *
 *                                                                          *
 *   HyperEngine-AV 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 all applicable details.                 *
 *                                                                          *
 *   You should have received a copy of the GNU General Public License      *
 *   along with this program; if not, write to:                             *
 *   Free Software Foundation, Inc.,                                        *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.              *
 ****************************************************************************/
#import "MIObjectRep.h"
#import "MIObject.h"
#import "MIMainViewController.h"
#import "MITopLevelContainerRep.h"
#import "MIImageController.h"
#import "MIMainViewTrackers.h"
#import "MIApplicationController.h"
#import "MIWSSelection.h"
#import "MIPreferences.h"
#import "MIResizeCommand.h"
#import "MIMoveCommand.h"
#import "MIAudioClipRep.h"
#import "MIVideoClipRep.h"

#ifndef Zz_GlobalDefines_h
#include "Zz_GlobalDefines.h"
#endif //Zz_GlobalDefines_h

#ifndef TArmeWSObj_h
#include "TArmeWSObj.h"
#endif //TArmeWSObj_h

#import "MIActiveCursor.h"

extern bool gNoObjectTitlesAtAll;

#ifdef SCALABLE_TITLEBAR
#ifdef SMALL_TITLEBAR
const MIVPos	kRepTitleHeight = _MIVPos(16);
const MIVPos	kRepTitleBarHeight = _MIVPos(16);
#else
const MIVPos	kRepTitleHeight = _MIVPos(25); // 27);
const MIVPos	kRepTitleBarHeight = _MIVPos(11);
#endif
#ifdef FOOTER_EXISTS
const MIVPos	kRepFooterHeight = _MIVPos(8);
const MIVPos	kRepHeaderHeight = _MIVPos(8);
#else
const MIVPos	kRepFooterHeight = _MIVPos(0);
const MIVPos	kRepHeaderHeight = _MIVPos(8);
#endif

#else 

#ifdef SMALL_TITLEBAR
const int	kRepTitleHeight = 20;
const int   kRepTitleBarHeight = 20;
#else
const int	kRepTitleHeight = 26;
const int   kRepTitleBarHeight = 10;
#endif
#ifdef FOOTER_EXISTS
const MIVPos	kRepFooterHeight = _MIVPos(6);
const MIVPos	kRepHeaderHeight = _MIVPos(8);
#else
const MIVPos	kRepFooterHeight = _MIVPos(6);
const MIVPos	kRepHeaderHeight = _MIVPos(8);
#endif
#endif

const int   kRepButtonHitTolerance = 0;
const MIVPos	kBetweenClipsHeight = _MIVPos(10);
const int	kRepDragZoneSize = 12;
#ifdef SMALL_TITLEBAR
const MIVPos	kDefaultClipRepresentationHeight = _MIVPos(44);
const MIVPos	kDefaultGroupRepresentationHeight = _MIVPos(55);
#else
const int	kDefaultClipRepresentationHeight = 55; //64;
const int	kDefaultGroupRepresentationHeight = 100;
#endif
bool		gMovingTitle = YES;
bool		gCurrentlyDrawingToImage = NO;

const MIVPos		kRepAutomationCurveHeight = _MIVPos(30);

@class MIAudioClipRep;
@class MIVideoClipRep;

@implementation MIObjectRep

- (id)initWithFrame:(NSRect)frame inTLC:(MITopLevelContainerRep*)tlc
{
    self = [super init];
    if (self)
	{
		fIsInvalid = YES;
		fHasTopBottomHandles = NO;
		fHasLeftRightHandles = NO;
		fHasCollapseButton = NO;
		fHasPropertiesButton = NO;
		fHasOnOffButton = NO;
        fCachedTitleImage = nil;
        fCachedBodyImage = nil;
		fCachedAutomationImage = nil;
        fBackgroundColor = [[NSColor yellowColor] retain];
		fFrame = frame;
		fTrackingRectTag = -1;
		fMouseIsOverMe = NO;
		[self setTopLevelContainerRep:tlc];
		[self setImagesAndColor];
    }
    return self;
}

- (void)setImagesAndColor
{
	// must be overriden
	ZzAssert(0);
}


#ifdef TEST_BENJA_ALLOW_CURSOR_RECTS_DISABLING
extern bool gEnableCursorRectsUpdate;
#endif //TEST_BENJA_ALLOW_CURSOR_RECTS_DISABLING

- (void)drawMutedStateInRect:(NSRect)rect lineLength:(unsigned)lineLength
{
	NSPoint 	diag1, diag2, p1, p2, p3, p4;
	unsigned	spaceBetweenMarks = 8;

	// put both points as the top left corner
	diag1.x = NSMinX(rect);
	diag1.y = NSMaxY(rect);
	diag2 = diag1;
	[[NSColor grayColor] set];

	while ( diag1.x < NSMaxX(rect) )
	{
		// p1 is the "bottom" point
		p1 = diag1;
		p2 = diag2;
		p3 = diag1;
		p4 = diag2;
		p2.y = min(diag2.y, (p1.y+lineLength));
		p2.x = min(diag2.x, (p1.x+lineLength));
		p3.y = max(diag1.y, (p4.y-lineLength));
		p3.x = max(diag1.x, (p4.x-lineLength));
		[NSBezierPath strokeLineFromPoint:p1 toPoint:p2];
		[NSBezierPath strokeLineFromPoint:p3 toPoint:p4];
		diag1.y -= spaceBetweenMarks;
		if ( diag1.y < NSMinY(rect) )
		{
			diag1.x += (NSMinY(rect) - diag1.y);
			diag1.y = NSMinY(rect);
		}
	
		diag2.x += spaceBetweenMarks;
		if ( diag2.x > NSMaxX(rect) )
		{
			diag2.y -= (diag2.x - NSMaxX(rect) );
			diag2.x = NSMaxX(rect);
		}
	}
}

- (void)dealloc
{

	[[fTLCRep window] invalidateCursorRectsForView:fTLCRep];

	[fBackgroundColor release];
/*
    [fCachedBodyImage release];
    [fCachedTitleImage release];
    [fCachedTitleStringImage release];
    [fCachedLeftTitleImage release];
    [fCachedRightTitleImage release];
    [fCachedStretchableTitleImage release];
*/
	[fTemporaryTracker release];
    [fRepresentedObject release];
	[super dealloc];
}

- (void)invalidate
{
	fIsInvalid = YES;
	[self recreateFrame];
	[self setNeedsDisplay];
}

- (void)setTopLevelContainerRep:(MITopLevelContainerRep*)newTLC
{
	if ( !newTLC )
	{
		verntl(interfaceStephan,0,"Null TLC passed to setTopLevelContainerRep");
		return;
	}
        [newTLC retain];
	[fTLCRep release];
	fTLCRep = newTLC;
}

- (MITopLevelContainerRep*)getTopLevelContainerRep
{
	return fTLCRep;
}

- (NSRect)getTLCFrame
{
    NSRect	tlcFrame;
    
    tlcFrame = fFrame;
    tlcFrame.origin = NSZeroPoint;
    tlcFrame = [self convertRectToTLCCoords:tlcFrame];
    
    return tlcFrame;
}

- (NSRect)frame
{
    return fFrame;
}

- (NSRect)frameIncludingShadow
{
	NSRect fr = fFrame;
	// include the shadow
	if ( [MIPreferences shadowsAroundObject] && [[fRepresentedObject parentObject] isTLC] )
	{
		fr.origin.x -= [mainImageController->fClipExternalShadowLeft size].width;
		fr.size.width += [mainImageController->fClipExternalShadowLeft size].width;
		fr.size.width += [mainImageController->fClipExternalShadowRight size].width;
		fr.origin.y -= [mainImageController->fClipExternalShadowBottomCenter size].height;
		fr.size.height += [mainImageController->fClipExternalShadowBottomCenter size].height;
	}
	
	return fr;
}

- (NSRect)getBodyRect
{
	NSRect br = fFrame;
	
#ifdef SCALABLE_TITLEBAR
	br.size.height -= [[self getTopLevelContainerRep] MIVPosToPixel:[fRepresentedObject getTitleHeight]];
#else
	br.size.height -= kRepTitleHeight;
#endif
	return br;
}

- (NSRect)getTitleRect
{
	NSRect tr = fFrame;
	NSRect	tmpRect;
	
	float titleHeight;
#ifdef SCALABLE_TITLEBAR
	titleHeight = [[self getTopLevelContainerRep] MIVPosToPixel:[fRepresentedObject getTitleHeight]];
#else
	titleHeight = kRepTitleHeight;
#endif
	
	NSDivideRect(tr, &tr, &tmpRect, titleHeight, NSMaxYEdge);
	
	return tr;
}

- (void)setFrame:(NSRect)aFrame
{
    if ( NSEqualRects(fFrame, aFrame) )
        return;
    
    if ( !NSEqualSizes(fFrame.size, aFrame.size) )
    {
        [self setFrameSize:aFrame.size];
    }

	if ( !NSEqualPoints(fFrame.origin, aFrame.origin) )
	{
		[self setFrameOrigin:aFrame.origin];
	}
/*	fFrame = aFrame;
    if ( USE_CACHED_IMAGES )
    {
        [self refreshCachedTitleImage:NO];
        [self refreshCachedBodyImage:NO];
    }*/
}

- (void)setFrameOrigin:(NSPoint)frameOrigin
{
    if ( NSEqualPoints(frameOrigin, fFrame.origin) )
        return;
	
#ifdef TEST_BENJA_ALLOW_CURSOR_RECTS_DISABLING
	if(gEnableCursorRectsUpdate)
	{
#endif //TEST_BENJA_ALLOW_CURSOR_RECTS_DISABLING



		[[fTLCRep window] invalidateCursorRectsForView:fTLCRep];




#ifdef TEST_BENJA_ALLOW_CURSOR_RECTS_DISABLING
	}
#endif //TEST_BENJA_ALLOW_CURSOR_RECTS_DISABLING

	fFrame.origin = frameOrigin;

	[self refreshTrackingRect];
	
	if ( fSelected )
		[[NSNotificationCenter defaultCenter] postNotificationName:MTGSelectionChangedNotification object:[[[fTLCRep window] windowController] selection]];
}

- (void)setTempFrameWithoutRegeneratingImages:(NSRect)frame
{
	fIsBeingTimeStretched = YES;
	fFrame = frame;
}

- (void)setFrameSize:(NSSize)frameSize
{
	fIsBeingTimeStretched = NO;
	
    if ( NSEqualSizes(frameSize, fFrame.size) )
        return;
	
#ifdef TEST_BENJA_ALLOW_CURSOR_RECTS_DISABLING
	if(gEnableCursorRectsUpdate)
	{
#endif //TEST_BENJA_ALLOW_CURSOR_RECTS_DISABLING





		[[fTLCRep window] invalidateCursorRectsForView:fTLCRep];





#ifdef TEST_BENJA_ALLOW_CURSOR_RECTS_DISABLING
	}
#endif //TEST_BENJA_ALLOW_CURSOR_RECTS_DISABLING


	fFrame.size = frameSize;

	[self refreshTrackingRect];

	// if the rep is selected, then if we modify its frame, it means the selection changes
	// thus we need to post a notification.
	if ( fSelected )
		[[NSNotificationCenter defaultCenter] postNotificationName:MTGSelectionChangedNotification object:[[[fTLCRep window] windowController] selection]];
	
    if ( USE_CACHED_IMAGES )
    {
        [self refreshCachedTitleImage:NO];
		[self refreshCachedAutomationImage:NO];
        [self refreshCachedBodyImage:NO];
    }
}

- (NSRect)minimalRectToFitContent
{
	return [fTLCRep MIRectToNSRect:[[self representedObject] minimalRectToFitContent]];
}

- (void)recreateFrame
{
	// the model frame is the part of the body that can hold children
	// the representation frame holds 2 more things
	// a kRepTitleHeight zone (part of the body) to hold the children title bar
	// a kRepTitleHeight zone (part of the title) to hold the objet's title bar
	// a kRepFooterHeight zone (part of the body) to hold the resize handle
    NSRect newFrame;

	fIsBeingTimeStretched = NO;

	newFrame =  [fTLCRep MIRectToNSRect:[[self representedObject] modelFrame]];
//	newFrame.size.height = [fTLCRep MIVPosToPixel:[fRepresentedObject getHeight]];

/*
 if ( [fRepresentedObject isCollapsed] )
    {
        newFrame.size.height = kRepTitleHeight;
    }
*/    
    [self setFrame:newFrame];
	[self refreshCachedTitleStringImage];
//	[self refreshGuides];
	
}

- (void)removeCursorRects
{
	return;
#ifdef TEST_BENJA_ALLOW_CURSOR_RECTS_DISABLING
	if(gEnableCursorRectsUpdate)
	{
#endif//TEST_BENJA_ALLOW_CURSOR_RECTS_DISABLING

		NSPoint 	frOrigin = [self getTLCFrame].origin;
	
		if ( fHasLeftRightHandles )
		{
			// add the left and right resize handles
			[fTLCRep removeCursorRect:[self rectForZone:MIObjectRepResizeLeftZone withObjectOrigin:frOrigin] cursor:mainImageController->fResizeLeftCursor];
			[fTLCRep removeCursorRect:[self rectForZone:MIObjectRepResizeRightZone withObjectOrigin:frOrigin] cursor:mainImageController->fResizeRightCursor];
		}
		
		if ( fHasTopBottomHandles && ![fRepresentedObject isCollapsed] )
		{
			// add the top and bottom resize handles
			[fTLCRep removeCursorRect:[self rectForZone:MIObjectRepResizeUpZone withObjectOrigin:frOrigin] cursor:mainImageController->fResizeUpCursor];
			[fTLCRep removeCursorRect:[self rectForZone:MIObjectRepResizeDownZone withObjectOrigin:frOrigin] cursor:mainImageController->fResizeDownCursor];
		}
	
		if ( fHasTopBottomHandles && fHasLeftRightHandles && ![fRepresentedObject isCollapsed])
		{
			// add the corners
			[fTLCRep removeCursorRect:[self rectForZone:MIObjectRepResizeDownLeftZone withObjectOrigin:frOrigin] cursor:mainImageController->fResizeDownLeftCursor];
			[fTLCRep removeCursorRect:[self rectForZone:MIObjectRepResizeDownRightZone withObjectOrigin:frOrigin] cursor:mainImageController->fResizeDownRightCursor];
	//		[fTLCRep removeCursorRect:[self rectForZone:MIObjectRepResizeUpLeftZone withObjectOrigin:frOrigin] cursor:mainImageController->fResizeUpLeftCursor];
	//		[fTLCRep removeCursorRect:[self rectForZone:MIObjectRepResizeUpRightZone withObjectOrigin:frOrigin] cursor:mainImageController->fResizeUpRightCursor];
		}
	
		// add the bar rectangle for move
		[fTLCRep removeCursorRect:[self rectForZone:MIObjectRepDragBarZone withObjectOrigin:frOrigin] cursor:mainImageController->fMoveOpenCursor];
#ifdef TEST_BENJA_ALLOW_CURSOR_RECTS_DISABLING
	}
#endif //TEST_BENJA_ALLOW_CURSOR_RECTS_DISABLING
}

- (void)addCursorRects
{
	if ( !fMouseIsOverMe )
		return;

#ifdef TEST_BENJA_ALLOW_CURSOR_RECTS_DISABLING
	if(gEnableCursorRectsUpdate)
	{
#endif //TEST_BENJA_ALLOW_CURSOR_RECTS_DISABLING
		NSPoint 	frOrigin = [self getTLCFrame].origin;
/*	
		if ( fHasLeftRightHandles )
		{
			// add the left and right resize handles
			[fTLCRep addCursorRect:[self rectForZone:MIObjectRepResizeLeftZone withObjectOrigin:frOrigin] cursor:mainImageController->fResizeLeftCursor];
			[fTLCRep addCursorRect:[self rectForZone:MIObjectRepResizeRightZone withObjectOrigin:frOrigin] cursor:mainImageController->fResizeRightCursor];
		}
		
		if ( fHasTopBottomHandles && ![fRepresentedObject isCollapsed] )
		{
			// add the top and bottom resize handles
			[fTLCRep addCursorRect:[self rectForZone:MIObjectRepResizeUpZone withObjectOrigin:frOrigin] cursor:mainImageController->fResizeUpCursor];
			[fTLCRep addCursorRect:[self rectForZone:MIObjectRepResizeDownZone withObjectOrigin:frOrigin] cursor:mainImageController->fResizeDownCursor];
		}
	
		if ( fHasTopBottomHandles && fHasLeftRightHandles && ![fRepresentedObject isCollapsed])
		{
			// add the corners
			[fTLCRep addCursorRect:[self rectForZone:MIObjectRepResizeDownLeftZone withObjectOrigin:frOrigin] cursor:mainImageController->fResizeDownLeftCursor];
			[fTLCRep addCursorRect:[self rectForZone:MIObjectRepResizeDownRightZone withObjectOrigin:frOrigin] cursor:mainImageController->fResizeDownRightCursor];
	//		[fTLCRep addCursorRect:[self rectForZone:MIObjectRepResizeUpLeftZone withObjectOrigin:frOrigin] cursor:mainImageController->fResizeUpLeftCursor];
	//		[fTLCRep addCursorRect:[self rectForZone:MIObjectRepResizeUpRightZone withObjectOrigin:frOrigin] cursor:mainImageController->fResizeUpRightCursor];
		}
*/		
		// add the bar rectangle for move
		[fTLCRep addCursorRect:[self rectForZone:MIObjectRepDragBarZone withObjectOrigin:frOrigin] cursor:mainImageController->fMoveOpenCursor];
		
//		[self resetActiveCursorRects];
#ifdef TEST_BENJA_ALLOW_CURSOR_RECTS_DISABLING
	}
#endif //TEST_BENJA_ALLOW_CURSOR_RECTS_DISABLING
}
/*
- (void)refreshGuides
{
	MIGuide	*aGuide;
	NSRect	fr;
	
	fr = [self getTLCFrame];
	
	if ( !fGuides[NSMinXEdge] )
	{
		aGuide = [fTLCRep addVerticalGuideAtTime:[fTLCRep pixelToArmeTime:NSMinX(fr)]];
		[aGuide setObject:self];
		fGuides[NSMinXEdge] = aGuide;
	}
	else
		[fGuides[NSMinXEdge] setTime:[fTLCRep pixelToArmeTime:NSMinX(fr)]];
	
	if ( !fGuides[NSMinYEdge] )
	{
		aGuide = [fTLCRep addHorizontalGuideAtPos:[fTLCRep pixelToMIVPos:NSMinY(fr)]];
		[aGuide setObject:self];
		fGuides[NSMinYEdge] = aGuide;
	}
	else
		[fGuides[NSMinYEdge] setVPos:[fTLCRep pixelToMIVPos:NSMinY(fr)]];
	
	if ( !fGuides[NSMaxXEdge] )
	{
		aGuide = [fTLCRep addVerticalGuideAtTime:[fTLCRep pixelToArmeTime:NSMaxX(fr)]];
		[aGuide setObject:self];
		fGuides[NSMaxXEdge] = aGuide;
	}
	else
		[fGuides[NSMaxXEdge] setTime:[fTLCRep pixelToArmeTime:NSMaxX(fr)]];

	if ( !fGuides[NSMaxYEdge] )
	{
		aGuide = [fTLCRep addHorizontalGuideAtPos:[fTLCRep pixelToMIVPos:NSMaxY(fr)]];
		[aGuide setObject:self];
		fGuides[NSMaxYEdge] = aGuide;
	}
	else
		[fGuides[NSMaxYEdge] setVPos:[fTLCRep pixelToMIVPos:NSMaxY(fr)]];
}
*/
- (void)setBackgroundColor:(NSColor*)color
{
    [color retain];
    [fBackgroundColor release];
    fBackgroundColor = color;
}

- (NSColor*)backgroundColor
{
	return fBackgroundColor;
}

- (void)setRepresentedObject:(MIObject*)object
{
/*    [object retain];
    [fRepresentedObject release];*/
	
	[fRepresentedObject release];
    fRepresentedObject = object;
	[fRepresentedObject retain];

}

- (MIObject*)representedObject
{
	return fRepresentedObject;
}


- (NSPoint)convertPointFromParent:(NSPoint)aPoint
{
	return NSMakePoint(aPoint.x - fFrame.origin.x, aPoint.y - fFrame.origin.y);
}

- (NSRect)convertRectFromParent:(NSRect)aRect
{
	NSRect	ret;
	
	ret = aRect;
	ret.origin = NSMakePoint(aRect.origin.x - fFrame.origin.x, aRect.origin.y - fFrame.origin.y);
	
	return ret;
}

- (NSPoint)convertPointToTLCCoords:(NSPoint)aPoint
{
	MIObject	*aParent;
	NSRect		pFrame;
/*	NSPoint		tPoint = aPoint;
	
	tPoint.x += [fTLCRep armeTimeToPixel:[fRepresentedObject WSObject]->GetAbsoluteStartTime()];
	tPoint.y += [fTLCRep MIVPosToPixel:[fRepresentedObject getAbsoluteVerticalPos]];

	return tPoint;
*/
	aParent = [self representedObject];
	
	do
	{
		pFrame = [[aParent findRepresentationInTLC:fTLCRep] frame];
		aPoint.x += pFrame.origin.x;
		aPoint.y += pFrame.origin.y;
	} while ( (aParent = [aParent parentObject]) && (aParent != [fTLCRep representedObject]) );

	return aPoint;
}

- (NSRect)convertRectToTLCCoords:(NSRect)aRect
{
	NSRect ret;
	
	ret = aRect;
	ret.origin = [self convertPointToTLCCoords:aRect.origin];
	
	return ret;
}

- (NSPoint)convertPointToParentCoords:(NSPoint)aPoint
{
	NSPoint ret;

	ret = aPoint;
	ret.x += fFrame.origin.x;
	ret.y += fFrame.origin.y;

	return ret;
}
- (NSRect)convertRectToParentCoords:(NSRect)aRect
{
	NSRect ret;

	ret = aRect;
	ret.origin = [self convertPointToParentCoords:ret.origin];

	return ret;
}

- (NSPoint)convertPointFromTLCCoords:(NSPoint)aPoint
{
	MIObject	*aParent;
	NSRect		pFrame;
/*	NSPoint		tPoint = aPoint;
	
	tPoint.x -= [fTLCRep armeTimeToPixel:[fRepresentedObject WSObject]->GetAbsoluteStartTime()];
	tPoint.y -= [fTLCRep MIVPosToPixel:[fRepresentedObject getAbsoluteVerticalPos]];

	return tPoint;
*/
	aParent = [self representedObject];
	
	do
	{
		pFrame = [[aParent findRepresentationInTLC:fTLCRep] frame];
		aPoint.x -= pFrame.origin.x;
		aPoint.y -= pFrame.origin.y;
	} while ( (aParent = [aParent parentObject]) && (aParent != [fTLCRep representedObject]) );

	return aPoint;
}

- (NSRect)convertRectFromTLCCoords:(NSRect)aRect
{
	NSRect ret;
	
	ret = aRect;
	ret.origin = [self convertPointFromTLCCoords:aRect.origin];
	
	return ret;	
}

- (void)drawRect:(NSRect)aRect withOffset:(NSPoint)offset
{
	if ( fTrackingRectTag == -1 )
	{
		[self refreshTrackingRect];
	}
		
	// we need to draw the intersection of :
	// - our rect in draw coords
	// - aRect which is in draw coords
	
	// and we need to draw this intersection rect at "offset" in
	// the current draw context.
	
	NSRect 			bodyRect;
	NSRect 			titleRect;
	NSRect			automationRect;
	NSRect			frameRect;
	NSPoint			clippedBodyOrigin;
	float			titleHeight;
	float			titleBarHeight;
	
#ifdef SCALABLE_TITLEBAR
	titleHeight = [[self getTopLevelContainerRep] MIVPosToPixel:[fRepresentedObject getTitleHeight]];
	titleBarHeight = [[self getTopLevelContainerRep] MIVPosToPixel:kRepTitleBarHeight];
#else
	titleHeight = kRepTitleHeight;
	titleBarHeight = kRepTitleBarHeight;
#endif

	/*
	   Children don't implement this, they override the drawBaseBodyToPoint method mainly
	
	   the rendering mechanism goes this way,
	   
	   first the 'general body' is drawn, either through a cached image if it exists or from the components
	   then the same goes for the title
	   
	   objects with different rendering can override the drawBaseTitle and drawBaseBody to change the base things
	*/
	
	frameRect = [self frame];
	frameRect.origin = offset;

	// now, frameRect is the whole object in TLC coords
	if ( NSEqualRects(aRect, NSZeroRect) )
		aRect = frameRect;

	if ( !NSContainsRect(aRect, frameRect) && !NSIntersectsRect(aRect, frameRect) )
		return;
		
	// let's split it into title and body
	NSDivideRect( frameRect, &titleRect, &bodyRect, titleHeight , NSMaxYEdge );
	
#ifdef SMALL_TITLEBAR
	titleRect = [self rectForZone:MIObjectRepDragBarZone withObjectOrigin:offset]; 
#else
	titleRect = [self rectForZone:MIObjectRepTitleZone withObjectOrigin:offset];
#endif
	automationRect = [self rectForZone:MIObjectRepAutomationZone withObjectOrigin:offset];
	bodyRect = [self rectForZone:MIObjectRepBodyZone withObjectOrigin:offset];
	
	
	NSRect clippedBodyRect = NSIntersectionRect(bodyRect, aRect);
	NSRect clippingRectForSelection = clippedBodyRect;
	NSRect clippedTitleRect = NSIntersectionRect(titleRect, aRect);
	NSRect clippedAutomationRect = NSIntersectionRect(automationRect, aRect);
	
	// if we have a cached image, use that one else draw it from the components
	// and then draw the extra information particular to the object
	if ( fCachedBodyImage /*&& !NSEqualRects(clippedBodyRect, NSZeroRect) */)
	{
		// this is the draw coordinates origin of where we need to draw
		clippedBodyOrigin = clippedBodyRect.origin;
		
		// this brings the clippedBodyRect in the IMAGE coordinates,
		// not in draw coordinates
		clippedBodyRect.origin.x -= bodyRect.origin.x;
		clippedBodyRect.origin.y -= bodyRect.origin.y;
//		printf( "origin: %f width:%f max:%f\n", clippedBodyRect.origin.x, clippedBodyRect.size.width, clippedBodyRect.origin.x + clippedBodyRect.size.width );
//		clippedBodyRect.size.width += 1;
		
		[self drawCachedBodyImageToPoint:clippedBodyOrigin fromRect:clippedBodyRect];
	}
	else
	{
		// otherwise, the point given is the origin of where we need to draw
		// our whole frame, but restricted to the clippedBodyRect zone, in 
		// draw coords.
		[self drawBaseBodyRect:bodyRect clippedTo:clippedBodyRect ];
	}

#ifdef AUTOMATION_DATA
	if ( fCachedAutomationImage && !NSEqualRects(clippedAutomationRect, NSZeroRect) )
	{
		NSPoint clippedAutomationOrigin = clippedAutomationRect.origin;
		
		clippedAutomationRect.origin.x -= NSMinX(automationRect);
		clippedAutomationRect.origin.y -= NSMinY(automationRect);
		
		[self drawCachedAutomationImageToPoint:clippedAutomationOrigin fromRect:clippedAutomationRect];
	}
	else
		[self drawBaseAutomationRect:automationRect clippedTo:clippedAutomationRect];
#endif

	if(!gNoObjectTitlesAtAll)
		[self drawTitleToPoint:titleRect.origin clippedTo:aRect];
/*	clippedTitleOrigin = clippedTitleRect.origin;
	clippedTitleRect.origin.x -= titleRect.origin.x;
	clippedTitleRect.origin.y -= titleRect.origin.y;

	[self drawCachedTitleImageToPoint:clippedTitleOrigin fromRect:clippedTitleRect];
*/

		// draw alpha on top if the object is selected.
/*
	if ( [[[fTLCRep mainViewController] selection] type] == kMIWSSelectionTypeObjects &&
		[[[fTLCRep mainViewController] selection] containsObject:self] )
	{
		// draw an alpha film over the whole thing
		[[NSColor blackColor] set];
		[NSBezierPath setDefaultLineWidth:2];
		[NSBezierPath strokeRect:NSInsetRect(frameRect,1,1)];
		[NSBezierPath setDefaultLineWidth:.0];

		// blue film above
//		[[NSColor colorWithCalibratedRed:0 green:0 blue:0.6 alpha:0.2] set];
//		[NSBezierPath fillRect:NSIntersectionRect(frameRect, aRect)];
	}
*/			
	[self drawSelection:clippingRectForSelection drawNow:NO];
	if ( [fRepresentedObject isMuted] )
	{
		NSDivideRect( frameRect, &titleRect, &bodyRect, titleHeight, NSMaxYEdge);
		titleRect.size.height -= titleBarHeight;
		
		[self drawMutedStateInRect:bodyRect lineLength:5];
		[self drawMutedStateInRect:titleRect lineLength:3];
	}

	// draw a layer on top of the solo object
	if ( [fRepresentedObject WSObject]->IsTheVideoSolo() || [fRepresentedObject WSObject]->IsTheAudioSolo())
	{
		[self drawSoloStateInRect:frameRect];
	}

// the commented following call draws the zones of the object	
//	[self drawZonesWithOrigin:offset];

}

- (void)drawSoloStateInRect:(NSRect)rect
{
	NSRect	titleRect, bodyRect;
	float	titleHeight, titleBarHeight;
	
#ifdef SCALABLE_TITLEBAR
	titleHeight = [[self getTopLevelContainerRep] MIVPosToPixel:[fRepresentedObject getTitleHeight]];
	titleBarHeight = [[self getTopLevelContainerRep] MIVPosToPixel:kRepTitleBarHeight];
#else
	titleHeight = kRepTitleHeight;
	titleBarHeight = kRepTitleBarHeight;
#endif
	NSDivideRect(rect, &titleRect, &bodyRect, titleHeight, NSMaxYEdge);

	[[NSColor colorWithCalibratedRed:0 green:0.8 blue:0 alpha:0.5] set];
	titleRect.size.height -= titleBarHeight;
	titleRect = NSInsetRect(titleRect, 1.5, 1.5);
	[NSBezierPath setDefaultLineWidth:3];
	[NSBezierPath strokeRect:titleRect];
	
	bodyRect = NSInsetRect(bodyRect, 2.5, 2.5);
	[NSBezierPath setDefaultLineWidth:5];
	[NSBezierPath strokeRect:bodyRect];

	[NSBezierPath setDefaultLineWidth:0];		
}


- (void)drawShadowClippedTo:(NSRect)clippingRect withObjectOrigin:(NSPoint)objOrigin
{
//    draw the shadow, slow painful process
    NSRect 	frameRect;
    NSRect 	imgRect;
    NSRect 	dstRect;
    NSRect	lastDstRect;
	NSRect	tmpRect;
    NSImage	*img;

    frameRect = [self frame];
    frameRect.origin = objOrigin;
    
    
    // top left 
    img = mainImageController->fClipExternalShadowTopLeft;

    imgRect.origin = NSZeroPoint;
    imgRect.size = [img size];

    dstRect = imgRect;
    dstRect.origin.x = NSMinX(frameRect) - NSWidth(imgRect);
    dstRect.origin.y = NSMaxY(frameRect) - NSHeight(imgRect);
    lastDstRect = dstRect;
    
    [img drawInRect:dstRect fromRect:imgRect operation:NSCompositeSourceAtop fraction:1];


    // left
    img = mainImageController->fClipExternalShadowLeft;

    imgRect.origin = NSZeroPoint;
    imgRect.size = [img size];

    dstRect.origin.x = NSMinX(frameRect) - NSWidth(imgRect);
    dstRect.origin.y = NSMinY(frameRect);
    dstRect.size.height = NSHeight(frameRect) - NSHeight(lastDstRect);
    dstRect.size.width = NSWidth(imgRect);
    
	// cap up and down
	tmpRect = clippingRect;
	tmpRect.origin.x = NSMinX(dstRect);
	tmpRect.size.width = NSWidth(dstRect);
	dstRect = NSIntersectionRect(tmpRect, dstRect);
    [img drawInRect:dstRect fromRect:imgRect operation:NSCompositeSourceAtop fraction:1];

    // bottom left corner
    img = mainImageController->fClipExternalShadowBottomLeftCorner;

    imgRect.origin = NSZeroPoint;
    imgRect.size = [img size];

    dstRect = imgRect;
    dstRect.origin.x = NSMinX(frameRect) - NSWidth(imgRect);
    dstRect.origin.y = NSMinY(frameRect) - NSHeight(imgRect);

	if ( dstRect.size.width > 0 )
		[img drawInRect:dstRect fromRect:imgRect operation:NSCompositeSourceAtop fraction:1];
    
    // bottom left
    img = mainImageController->fClipExternalShadowBottomLeft;

    imgRect.origin = NSZeroPoint;
    imgRect.size = [img size];

    dstRect = imgRect;
    dstRect.origin.x = NSMinX(frameRect);
    dstRect.origin.y = NSMinY(frameRect) - NSHeight(imgRect);
	if ( NSMaxX(dstRect) > NSMaxX(frameRect) )
		dstRect.size.width = 0;
    lastDstRect = dstRect;
    
	if ( dstRect.size.width > 0 )
		[img drawInRect:dstRect fromRect:imgRect operation:NSCompositeSourceAtop fraction:1];
    
    // bottom center
    img = mainImageController->fClipExternalShadowBottomCenter;

    imgRect.origin = NSZeroPoint;
    imgRect.size = [img size];

    dstRect.origin.x = NSMaxX(lastDstRect);
    dstRect.origin.y = NSMinY(frameRect) - NSHeight(imgRect);
    dstRect.size.width = NSWidth(frameRect) - 2*NSWidth(lastDstRect);
    dstRect.size.height = NSHeight(imgRect);
    
	// cap left and right
	tmpRect = clippingRect;
	tmpRect.origin.y = NSMinY(dstRect);
	tmpRect.size.height = NSHeight(dstRect);
	dstRect = NSIntersectionRect(tmpRect, dstRect);
	if ( dstRect.size.width > 0 )
		[img drawInRect:dstRect fromRect:imgRect operation:NSCompositeSourceAtop fraction:1];
	
    // bottom right
    img = mainImageController->fClipExternalShadowBottomRight;

    imgRect.origin = NSZeroPoint;
    imgRect.size = [img size];

    dstRect = imgRect;
    dstRect.origin.x = NSMaxX(frameRect) - NSWidth(imgRect);
    dstRect.origin.y = NSMinY(frameRect) - NSHeight(imgRect);
	if ( NSMinX(dstRect) < NSMinX(frameRect) )
		dstRect.size.width = 0;
	
	if ( dstRect.size.width > 0 )
		[img drawInRect:dstRect fromRect:imgRect operation:NSCompositeSourceAtop fraction:1];
    
    // bottom right corner
    img = mainImageController->fClipExternalShadowBottomRightCorner;

    imgRect.origin = NSZeroPoint;
    imgRect.size = [img size];

    dstRect = imgRect;
    dstRect.origin.x = NSMaxX(frameRect);
    dstRect.origin.y = NSMinY(frameRect) - NSHeight(imgRect);

	if ( dstRect.size.width > 0 )
		[img drawInRect:dstRect fromRect:imgRect operation:NSCompositeSourceAtop fraction:1];
    
    // top right
    img = mainImageController->fClipExternalShadowTopRight;

    imgRect.origin = NSZeroPoint;
    imgRect.size = [img size];

    dstRect = imgRect;
    dstRect.origin.x = NSMaxX(frameRect);
    dstRect.origin.y = NSMaxY(frameRect) - NSHeight(imgRect);
    lastDstRect = dstRect;
    [img drawInRect:dstRect fromRect:imgRect operation:NSCompositeSourceAtop fraction:1];
    
    // right
    img = mainImageController->fClipExternalShadowRight;

    imgRect.origin = NSZeroPoint;
    imgRect.size = [img size];

    dstRect = imgRect;
    dstRect.origin.x = NSMaxX(frameRect);
    dstRect.origin.y = NSMinY(frameRect);
    dstRect.size.height = NSHeight(frameRect) - NSHeight(lastDstRect);

	// cap up and down
	tmpRect = clippingRect;
	tmpRect.origin.x = NSMinX(dstRect);
	tmpRect.size.width = NSWidth(dstRect);
	dstRect = NSIntersectionRect(tmpRect, dstRect);
    [img drawInRect:dstRect fromRect:imgRect operation:NSCompositeSourceAtop fraction:1];
}


/*
- (BOOL)isCollapsed
{
    return [fRepresentedObject isCollapsed];
}

- (void)toggleCollapsed
{
    [self setCollapsed:![fRepresentedObject isCollapsed]];
}

- (void)setCollapsed:(BOOL)flag
{
    NSRect	newFrame;
    
    if ( flag == [fRepresentedObject isCollapsed] )
        return;
        
    [fRepresentedObject isCollapsed] = flag;
    
    if ( [fRepresentedObject isCollapsed] )
    {
        fOldFrameHeight = NSHeight(fFrame);
        newFrame = fFrame;
        newFrame.origin.y = NSMaxY(fFrame)-kRepTitleHeight;
        newFrame.size.height = kRepTitleHeight;
        [self setFrame:newFrame];
    }
    else
    {
        newFrame = fFrame;
        newFrame.origin.y += kRepTitleHeight;
        newFrame.origin.y -= fOldFrameHeight;
        newFrame.size.height = fOldFrameHeight;  
        [self setFrame:newFrame];
//		[[[self representedObject] parentObject] resizeFrameToFullyIncludeChildren];
    }
    
}
*/
- (BOOL)isOpaque
{
	return [fRepresentedObject isOpaque];
}

- (BOOL)isSelected
{
	return fSelected;
}

- (void)resetFrameWithHZoom:(float)hZoom
{
	NSRect	newFrame;
	
	newFrame = [self frame];
	newFrame.size.width /= hZoom;
	
	[self setFrame:newFrame];
}

- (void)resetFrameWithVZoom:(float)vZoom
{
	NSRect	newFrame;
	
	newFrame = [self frame];
	newFrame.size.height /= vZoom;
	
	[self setFrame:newFrame];
}

- (void)cacheImagesIfSizeSmallerThan:(NSSize)maxSize frameIsInRect:(NSRect)enclosingRect
{
	if(gNoObjectTitlesAtAll)
		return;

	NSRect			myTLCFrame;
	NSEnumerator	*childrenEnum;
	MIObject		*aChild;
	BOOL			conditionsMet = YES;
	
	/// children first
	
	childrenEnum = [[fRepresentedObject getChildren] objectEnumerator];
	
	while ( aChild = [childrenEnum nextObject] )
	{
		[[aChild findRepresentationInTLC:fTLCRep] cacheImagesIfSizeSmallerThan:maxSize frameIsInRect:enclosingRect];
	}
	
	// then self
	
	myTLCFrame = [self getTLCFrame];
	
	if ( conditionsMet && !NSEqualSizes(maxSize, NSZeroSize) &&
	     ( NSHeight(myTLCFrame) > maxSize.height ||
		   NSWidth(myTLCFrame)  > maxSize.width ) )
	{
		[self freeCachedImages];
		conditionsMet = NO;
	}
	
	if ( conditionsMet && !NSEqualRects(enclosingRect, NSZeroRect) &&
		 ( !NSIntersectsRect(enclosingRect, myTLCFrame) &&
		   !NSContainsRect(enclosingRect, myTLCFrame) ) )
	{
		[self freeCachedImages];
		conditionsMet = NO;
	}
	
	if ( !fCachedBodyImage && conditionsMet )
		[self refreshCachedBodyImage:YES];
	
	if ( !fCachedAutomationImage && conditionsMet )
		[self refreshCachedAutomationImage:YES];
		
	if ( !fCachedTitleImage )
		[self refreshCachedTitleImage:!conditionsMet];
}

- (void)freeCachedImages
{
	if ( fIsBeingTimeStretched )
		return;
		
	[fCachedBodyImage release];
	fCachedBodyImage = nil;
	
	[fCachedAutomationImage release];
	fCachedAutomationImage = nil;
	
	[fCachedTitleImage release];
	fCachedTitleImage = nil;
}

- (void)toggleOnOff
{
// $$$ REFINE
// default implementation sets the value on/off on the miobjet (not used for anything but display)
//	[fRepresentedObject toggleOnOff];
}

- (void)popUpMenu:(NSMenu*)menu atPos:(NSPoint)pos
{
    NSEvent 			*theEvent;

	/*    theEvent = [NSEvent mouseEventWithType:NSLeftMouseDown location:[[sender object] frame].origin
modifierFlags:0 timestamp:(NSTimeInterval)time windowNumber:(int)windowNum
context:(NSGraphicsContext *)context eventNumber:(int)eventNumber
clickCount:1 pressure:1];
[NSMenu popUpContextMenu:fGridMenu withEvent:theEvent forView:[sender object]];*/


    theEvent = [NSEvent mouseEventWithType:NSLeftMouseDown location:[fTLCRep convertPoint:pos toView:nil]
							 modifierFlags:0 timestamp:0 windowNumber:[[fTLCRep window] windowNumber]
								   context:[NSGraphicsContext currentContext] eventNumber:1
								clickCount:1 pressure:1];


    [NSMenu popUpContextMenu:menu withEvent:theEvent forView:fTLCRep];

}

- (NSRect)rectForZone:(MIObjectRepZone)zone withObjectOrigin:(NSPoint)origin
{
	/*
					+-------------------------------------------+
		grab bar	|                                           |
					+-------------------------------------------+
		title bar	|                                           |
					|                                           |
					+---+-----------------------------------+---+
		resize up	|   |                                   |   |
					+---+-----------------------------------+---+
					|   |                                   |   |
					|   |                                   |   |
					|   |                                   |   |
		body		|   |                                   |   |
					|   |                                   |   |
					|   |                                   |   |
					|   |                                   |   |
					+---+-----------------------------------+---+
		resize down	| 1 |                                   | 1 |
					+---+-----------------------------------+---+
	*/
	
	NSRect	myFrame = fFrame;
	NSRect	rectForZone = NSZeroRect;
	float	titleBarHeight = 0;
	float	titleHeight = 0;
	float	automationHeight = 0;
	NSRect	myTitle, myBody, myAutomationZone;
	NSRect  myGrabBar, myTitleBar;
	NSRect	myLeftEdge, myRightEdge, myBottomEdge, myTopEdge;
	NSRect	myUpLeftCorner, myUpRightCorner, myBottomLeftCorner, myBottomRightCorner;
	
	
#ifdef SCALABLE_TITLEBAR
	titleBarHeight = [[self getTopLevelContainerRep] MIVPosToPixel:kRepTitleBarHeight];
	titleHeight = [[self getTopLevelContainerRep] MIVPosToPixel:[fRepresentedObject getTitleHeight]];
#ifdef AUTOMATION_DATA
	automationHeight = [[self getTopLevelContainerRep] MIVPosToPixel:[fRepresentedObject getAutomationCurvesHeight]];
#endif
#else
	titleBarHeight = kRepTitleBarHeight;
	titleHeight = kRepTitleHeight;
	automationHeight = 0;
#endif

	myFrame.origin = NSZeroPoint;

	// create the rects for generic (big) title and generic (big) body 
	NSDivideRect(myFrame, &myTitle, &myBody, titleHeight, NSMaxYEdge);

	NSDivideRect(myBody, &myAutomationZone, &myBody, automationHeight, NSMaxYEdge);

	// divide the generic title into a grab bar and a title bar
	NSDivideRect(myTitle, &myGrabBar, &myTitleBar, titleBarHeight, NSMaxYEdge);

	// create the left and right edges
	if ( fHasLeftRightHandles )
	{
		NSDivideRect(myBody, &myRightEdge, &myLeftEdge, kRepDragZoneSize, NSMaxXEdge);
		myLeftEdge.size.width = kRepDragZoneSize;
	}

	// create the top and bottom edges
	if ( fHasTopBottomHandles )
	{
		NSDivideRect(myBody, &myTopEdge, &myBottomEdge, kRepDragZoneSize, NSMaxYEdge);
		myBottomEdge.size.height = kRepDragZoneSize;
	}
	
	// divide the edges into corners
	if ( fHasTopBottomHandles && fHasLeftRightHandles )
	{
		NSDivideRect(myLeftEdge, &myUpLeftCorner, &myLeftEdge, kRepDragZoneSize, NSMaxYEdge);
		NSDivideRect(myLeftEdge, &myBottomLeftCorner, &myLeftEdge, kRepDragZoneSize, NSMinYEdge );
		
		NSDivideRect(myRightEdge, &myUpRightCorner, &myRightEdge, kRepDragZoneSize, NSMaxYEdge );
		NSDivideRect(myRightEdge, &myBottomRightCorner, &myRightEdge, kRepDragZoneSize, NSMinYEdge );
		
		myTopEdge = NSInsetRect( myTopEdge, kRepDragZoneSize, 0);
		myBottomEdge = NSInsetRect( myBottomEdge, kRepDragZoneSize, 0);
	}
	
	switch( zone )
	{
		case MIObjectRepResizeUpZone:
			rectForZone = myTopEdge;
			break;
		case MIObjectRepResizeUpLeftZone:
			rectForZone = myUpLeftCorner;
			break;
		case MIObjectRepResizeLeftZone:
			rectForZone = myLeftEdge;
			break;
		case MIObjectRepResizeDownLeftZone:
			rectForZone = myBottomLeftCorner;
			break;
		case MIObjectRepResizeDownZone:
			rectForZone = myBottomEdge;
			break;
		case MIObjectRepResizeDownRightZone:
			rectForZone = myBottomRightCorner;
			break;
		case MIObjectRepResizeRightZone:
			rectForZone = myRightEdge;
			break;
		case MIObjectRepResizeUpRightZone:
			rectForZone = myUpRightCorner;
			break;
		case MIObjectRepDragBarZone:
			rectForZone = myGrabBar;
			break;
		case MIObjectRepTitleZone:
			rectForZone = myTitleBar;
			break;
		case MIObjectRepAutomationZone:
			rectForZone = myAutomationZone;
			break;
		case MIObjectRepBodyZone:
			rectForZone = myBody;
			break;
		case MIObjectRepBodySelectionZone:
			rectForZone = NSInsetRect(myBody, kRepDragZoneSize, 0);
			break;
		case MIObjectRepRightBodySelectionZone:
			rectForZone = myBody;
			rectForZone.origin.x = NSMaxX(myBody) - kRepDragZoneSize;
			rectForZone.size.width = kRepDragZoneSize;
			if ( [self isKindOfClass:[MIAudioClipRep class]] ||
			     [self isKindOfClass:[MIVideoClipRep class]] )
			{
				rectForZone.origin.y += kRepDragZoneSize;
				rectForZone.size.height -= kRepDragZoneSize;
			}
			break;
		case MIObjectRepLeftBodySelectionZone:
			rectForZone = myBody;
			rectForZone.size.width = kRepDragZoneSize;
			if ( [self isKindOfClass:[MIAudioClipRep class]] ||
			     [self isKindOfClass:[MIVideoClipRep class]] )
			{
				rectForZone.origin.y += kRepDragZoneSize;
				rectForZone.size.height -= kRepDragZoneSize;
			}
			break;
		case MIObjectRepCollapseButtonZone:
		case MIObjectRepPropertiesButtonZone:
		case MIObjectRepOnOffButtonZone:
			rectForZone = NSZeroRect;
			break;
		case MIObjectRepRightTimeStretchZone:
			rectForZone.origin.y = NSMinY(myBody);
			rectForZone.origin.x = NSMaxX(myBody) - kRepDragZoneSize;
			rectForZone.size.width = kRepDragZoneSize;
			rectForZone.size.height = kRepDragZoneSize;
			break;
		case MIObjectRepLeftTimeStretchZone:
			rectForZone.origin = myBody.origin;
			rectForZone.size.width = kRepDragZoneSize;
			rectForZone.size.height = kRepDragZoneSize;
			break;
	}
	if ( !NSContainsRect(myFrame, rectForZone) )
		rectForZone = NSIntersectionRect(myFrame, rectForZone);
		
	rectForZone.origin = TranslateNSPoint( rectForZone.origin, origin);
	
	return rectForZone;
}

- (NSRect)rectForZone:(MIObjectRepZone)zone
{
	return [self rectForZone:zone withObjectOrigin:NSZeroPoint];
}

- (void)drawZonesWithOrigin:(NSPoint)p
{
	[[NSColor colorWithCalibratedRed:0.5 green:1 blue:1 alpha:0.2] set]; // cyan
	[[NSColor cyanColor] set];
	[NSBezierPath fillRect:[self rectForZone:MIObjectRepDragBarZone withObjectOrigin:p]];

	[[NSColor colorWithCalibratedRed:1 green:0 blue:1 alpha:0.2] set]; // magenta
	[[NSColor magentaColor] set];
	[NSBezierPath fillRect:[self rectForZone:MIObjectRepTitleZone withObjectOrigin:p]];

	[[NSColor colorWithCalibratedRed:1 green:0 blue:0 alpha:0.2] set]; // red
	[[NSColor redColor] set]; 
	[NSBezierPath fillRect:[self rectForZone:MIObjectRepBodyZone withObjectOrigin:p]];

	[[NSColor colorWithCalibratedRed:0 green:0 blue:1 alpha:0.2] set]; // blue
	[[NSColor blueColor] set];
	[NSBezierPath fillRect:[self rectForZone:MIObjectRepResizeUpLeftZone withObjectOrigin:p]];
	[NSBezierPath fillRect:[self rectForZone:MIObjectRepResizeUpRightZone withObjectOrigin:p]];
	[NSBezierPath fillRect:[self rectForZone:MIObjectRepResizeDownLeftZone withObjectOrigin:p]];
	[NSBezierPath fillRect:[self rectForZone:MIObjectRepResizeDownRightZone withObjectOrigin:p]];

	[[NSColor colorWithCalibratedRed:0 green:1 blue:0 alpha:0.2] set]; // green
	[[NSColor greenColor] set];
	[NSBezierPath fillRect:[self rectForZone:MIObjectRepResizeLeftZone withObjectOrigin:p]];
	[NSBezierPath fillRect:[self rectForZone:MIObjectRepResizeRightZone withObjectOrigin:p]];
	[NSBezierPath fillRect:[self rectForZone:MIObjectRepResizeDownZone withObjectOrigin:p]];
	[NSBezierPath fillRect:[self rectForZone:MIObjectRepResizeUpZone withObjectOrigin:p]];

}

- (MIObjectMouseHandling)handleMoreMouseTracking:(NSPoint)mouseLoc modifier:(unsigned int)modifier type:(NSEventType)type
{
    NSRect						myFrame = [self frame];
    BOOL						bNeedsRedisplay = NO;
    MIObjectMouseHandling		status = MIContinueMouseHandling;
    NSRect						myTLCFrame = [self getTLCFrame];
/*
	float						titleHeight, titleBarHeight, footerHeight;
	
#ifdef SCALABLE_TITLEBAR
	titleHeight = [[self getTopLevelContainerRep] MIVPosToPixel:[fRepresentedObject getTitleHeight]];
	titleBarHeight = [[self getTopLevelContainerRep] MIVPosToPixel:kRepTitleBarHeight];
#else
	titleHeight = kRepTitleHeight;
	titleBarHeight = kRepTitleBarHeight;
#endif
	footerHeight = [[self getTopLevelContainerRep] MIVPosToPixel:kRepFooterHeight];
*/

	[self invalidateTheMouseTracker]; // au cas ou un tracker n'aurait pas ŽtŽ releasŽ

	// check for selection (only if it's about full objects)
	if ( [[[fTLCRep mainViewController] selection] type] == kMIWSSelectionTypeObjects )
	{
		if ([[fTLCRep mainViewController] isObjectInSelection:self])
		{
			// if the object is already in the selection and the COMMAND modifier is there, remove the object from the selection
			if ( modifier & NSCommandKeyMask ||
				 modifier & NSShiftKeyMask )
			{
				[[fTLCRep mainViewController] removeObjectFromSelection:self];
				status = MIStopMouseHandling;
			}
		}
		else
		{
			// the object is not in the selection, so we clear the selection, add this object
			if ( !modifier || ( modifier & NSControlKeyMask && NSPointInRect(mouseLoc, [self rectForZone:MIObjectRepDragBarZone]) ) )
				[[fTLCRep mainViewController] clearSelection];

			[[fTLCRep mainViewController] addObjectToSelection:self];
		}
	}
	else
	{
		if ( NSPointInRect(mouseLoc, [self rectForZone:MIObjectRepDragBarZone]) )
		{
			// if the select is not whole object selection, clear it before moving
			// the actual move tracker etc are created later on
			[[fTLCRep mainViewController] clearSelection];
			[[fTLCRep mainViewController] selectionSetObjectsType];
			[[fTLCRep mainViewController] addObjectToSelection:self];
		}
	}


	/*
	precedence:
		contextual menu
		buttons
		resize up, down, left, right
		resize corners
		move/copy/alias
	*/
		
// check for contextual menu
	if ( (type == NSRightMouseDown || (modifier & NSControlKeyMask )) &&
		 NSPointInRect(mouseLoc, [self rectForZone:MIObjectRepDragBarZone]) )
	{
			// bring up contextual menu
			status = MIStopMouseHandling;
			[self popUpMenu:[[MIApplicationController sharedApplicationController] localEditMenu] atPos:[self convertPointToTLCCoords:mouseLoc]];
	}
	
// check for collapse button
	if ( status == MIContinueMouseHandling && fHasCollapseButton )
	{
		if(NSPointInRect(mouseLoc, [self rectForZone:MIObjectRepCollapseButtonZone]) )
		{
			bNeedsRedisplay = YES;
			if ( [[self representedObject] isCollapsed] )
			{
				[[self representedObject] setCollapsed:NO];
				myTLCFrame = [self getTLCFrame];
			}
			else
			{
				myTLCFrame = [self getTLCFrame];
				[[self representedObject] setCollapsed:YES];
			}
			status = MIStopMouseHandling;
		}
	}
		
// check for properties button
	if ( status == MIContinueMouseHandling && fHasPropertiesButton )
	{
		if ( NSPointInRect(mouseLoc, [self rectForZone:MIObjectRepPropertiesButtonZone]) )
		{
			[self showProperties];
			status = MIStopMouseHandling;
		}
	}

// check for the On/Off (mute) button
	if ( status == MIContinueMouseHandling && fHasOnOffButton )
	{
		if ( NSPointInRect(mouseLoc, [self rectForZone:MIObjectRepOnOffButtonZone]) )
		{
			bNeedsRedisplay = YES;
			[self toggleOnOff];
			status = MIStopMouseHandling;
		}
	}

// check for resize up & down
	if ( status == MIContinueMouseHandling && fHasTopBottomHandles && [MIResizeCommand supportsSelection:[[fTLCRep mainViewController] selection]])
	{
		if ( NSPointInRect(mouseLoc, [self rectForZone:MIObjectRepResizeUpZone]) )
		{
			status = MIAskMeATracker;
			fTemporaryTracker = [[MIResizeObjectTracker alloc] initWithView:fTLCRep atPos:[self convertPointToTLCCoords:mouseLoc] withModifiers:nil] ;
			[fTemporaryTracker setEdge:NSMaxYEdge];			
		}
		
		if ( NSPointInRect(mouseLoc, [self rectForZone:MIObjectRepResizeDownZone]) )
		{
			status = MIAskMeATracker;
			fTemporaryTracker = [[MIResizeObjectTracker alloc] initWithView:fTLCRep atPos:[self convertPointToTLCCoords:mouseLoc] withModifiers:nil] ;
			[fTemporaryTracker setEdge:NSMinYEdge];			
		}
	}
	
// check for left and right
	if ( status == MIContinueMouseHandling && fHasLeftRightHandles && [MIResizeCommand supportsSelection:[[fTLCRep mainViewController] selection]])
	{
		if ( NSPointInRect(mouseLoc, [self rectForZone:MIObjectRepResizeLeftZone]) )
		{
			status = MIAskMeATracker;
			fTemporaryTracker = [[MIResizeObjectTracker alloc] initWithView:fTLCRep atPos:[self convertPointToTLCCoords:mouseLoc] withModifiers:nil] ;
			[fTemporaryTracker setEdge:NSMinXEdge];			
		}
		
		if ( NSPointInRect(mouseLoc, [self rectForZone:MIObjectRepResizeRightZone]) )
		{
			status = MIAskMeATracker;
			fTemporaryTracker = [[MIResizeObjectTracker alloc] initWithView:fTLCRep atPos:[self convertPointToTLCCoords:mouseLoc] withModifiers:nil] ;
			[fTemporaryTracker setEdge:NSMaxXEdge];			
		}
	}
	
// check for the corners
	if ( status == MIContinueMouseHandling && fHasLeftRightHandles && fHasTopBottomHandles && [MIResizeCommand supportsSelection:[[fTLCRep mainViewController] selection]])
	{
		// up left
		if ( NSPointInRect(mouseLoc, [self rectForZone:MIObjectRepResizeUpLeftZone]) )
		{
			status = MIAskMeATracker;
			fTemporaryTracker = [[MIResizeObjectTracker alloc] initWithView:fTLCRep atPos:[self convertPointToTLCCoords:mouseLoc] withModifiers:nil] ;
			[fTemporaryTracker setEdge:NSMinXEdge];	
			[fTemporaryTracker setEdge:NSMaxYEdge];		
		}

		// up right
		if ( NSPointInRect(mouseLoc, [self rectForZone:MIObjectRepResizeUpRightZone]) )
		{
			status = MIAskMeATracker;
			fTemporaryTracker = [[MIResizeObjectTracker alloc] initWithView:fTLCRep atPos:[self convertPointToTLCCoords:mouseLoc] withModifiers:nil] ;
			[fTemporaryTracker setEdge:NSMaxXEdge];	
			[fTemporaryTracker setEdge:NSMaxYEdge];		
		}

		// down left
		if ( NSPointInRect(mouseLoc, [self rectForZone:MIObjectRepResizeDownLeftZone]) )
		{
			status = MIAskMeATracker;
			fTemporaryTracker = [[MIResizeObjectTracker alloc] initWithView:fTLCRep atPos:[self convertPointToTLCCoords:mouseLoc] withModifiers:nil] ;
			[fTemporaryTracker setEdge:NSMinXEdge];	
			[fTemporaryTracker setEdge:NSMinYEdge];		
		}

		// down right
		if ( NSPointInRect(mouseLoc, [self rectForZone:MIObjectRepResizeDownRightZone]) )
		{
			status = MIAskMeATracker;
			fTemporaryTracker = [[MIResizeObjectTracker alloc] initWithView:fTLCRep atPos:[self convertPointToTLCCoords:mouseLoc] withModifiers:nil] ;
			[fTemporaryTracker setEdge:NSMaxXEdge];	
			[fTemporaryTracker setEdge:NSMinYEdge];		
		}
	}

// check for move/alias/copy
	// $$$TODO add a check for the object being locked
	// $$$TODO add aliasing and copying
	if ( status == MIContinueMouseHandling && [MIMoveCommand supportsSelection:[[fTLCRep mainViewController] selection]])
	{
		if ( NSPointInRect(mouseLoc, [self rectForZone:MIObjectRepDragBarZone]) )
		{
			status =  MIAskMeATracker;
			// if the select is not whole object selection, clear it before moving
			if ( [[[fTLCRep mainViewController] selection] type] != kMIWSSelectionTypeObjects )
			{
				[[fTLCRep mainViewController] clearSelection];
				[[fTLCRep mainViewController] selectionSetObjectsType];
				[[fTLCRep mainViewController] addObjectToSelection:self];
			}
			
			fTemporaryTracker = [[MIMoveSelectionTracker alloc] initWithView:fTLCRep atPos:[self convertPointToTLCCoords:mouseLoc] withModifiers:nil] ;
		}
	}

// check for selection
	
    if ( bNeedsRedisplay )
    {
        [self refreshCachedTitleImage:NO];
		[self setNeedsDisplay];
    }

    return status;
}

- (BOOL)doubleClick:(NSPoint)mouseLoc modifier:(unsigned int)modifier
{
	// NSBeep();
	return NO;
}

- (MIMouseTracker*)getTheMouseTracker:(NSPoint)mouseLoc
{
    return fTemporaryTracker;
}

- (void)invalidateTheMouseTracker
{
    [fTemporaryTracker release];
    fTemporaryTracker = nil;
}

- (void)drawBaseAutomationRect:(NSRect)zoneInDrawCoords clippedTo:(NSRect)clippingRect
{
	[[self backgroundColor] set];
	[NSBezierPath fillRect:zoneInDrawCoords];
}

- (void)drawBaseBodyRect:(NSRect)frameInDrawCoords clippedTo:(NSRect)clippingRect
{
	//MTGStartTimeLog
    NSRect			aRect;
	float			titleHeight;
	float			titleBarHeight;
	float			footerHeight;

#ifdef SCALABLE_TITLEBAR
	titleHeight = [[self getTopLevelContainerRep] MIVPosToPixel:[fRepresentedObject getTitleHeight]];
	titleBarHeight = [[self getTopLevelContainerRep] MIVPosToPixel:kRepTitleBarHeight];
#else
	titleHeight = kRepTitleHeight;
	titleBarHeight = kRepTitleBarHeight;
#endif
	footerHeight = [[self getTopLevelContainerRep] MIVPosToPixel:kRepFooterHeight];


	// $$$ TODO use the clippingRect
    
	// $$$TODO : please tell me why we're using the whole frame !
	
    aRect = [self frame];
    aRect.origin = frameInDrawCoords.origin;
    
    // draw the background color
	[[self backgroundColor] set];
    [NSBezierPath fillRect:aRect];

    // draw the surrounding gray line
	if ( [self isSelected] && [[[fTLCRep mainViewController] selection] type] == kMIWSSelectionTypeObjects )
		[[NSColor colorWithCalibratedRed:.301 green:.301 blue:.301 alpha:1.0f] set];
//		[[NSColor colorWithCalibratedRed:1 green:1 blue:1 alpha:0.5] set];
	else
		[[NSColor colorWithCalibratedRed:.699 green:.699 blue:.699 alpha:1.0f] set];
//		[[NSColor colorWithCalibratedRed:0 green:0 blue:0 alpha:0.5] set];
    [NSBezierPath strokeLineFromPoint:NSMakePoint(NSMinX(aRect),NSMinY(aRect)) toPoint:NSMakePoint(NSMinX(aRect), NSMaxY(aRect))];
    [NSBezierPath strokeLineFromPoint:NSMakePoint(NSMaxX(aRect),NSMinY(aRect)) toPoint:NSMakePoint(NSMaxX(aRect), NSMaxY(aRect))];
    [NSBezierPath strokeLineFromPoint:NSMakePoint(NSMinX(aRect),NSMinY(aRect)) toPoint:NSMakePoint(NSMaxX(aRect), NSMinY(aRect))];

#ifdef DRAW_HANDLES
	if ( fHasTopBottomHandles )
	{
		// draw the bottom handle
		curPoint = aRect.origin;
		curPoint.x = NSMidX(aRect)-([mainImageController->fClipHandleBottom size].width/2);
		curPoint.y += 2;
		[mainImageController->fClipHandleBottom compositeToPoint:curPoint operation:NSCompositeSourceAtop];
	}
	
	if ( fHasTopBottomHandles && fHasLeftRightHandles )
	{
		// draw the left and right resize handles
		if ( [self isSelected] && [[[fTLCRep mainViewController] selection] type] == kMIWSSelectionTypeObjects )
			[[NSColor whiteColor] set];
		else
			[[NSColor blackColor] set];
		[NSBezierPath strokeLineFromPoint:NSMakePoint(NSMinX(aRect)+1, NSMinY(aRect)+footerHeight-1) toPoint:NSMakePoint(NSMinX(aRect)+footerHeight-1,NSMinY(aRect)+1)];
		[NSBezierPath strokeLineFromPoint:NSMakePoint(NSMinX(aRect)+1, NSMinY(aRect)+footerHeight/2) toPoint:NSMakePoint(NSMinX(aRect)+footerHeight/2,NSMinY(aRect)+1)];
	
		maxX = NSMaxX(aRect);
		
		[NSBezierPath strokeLineFromPoint:NSMakePoint(maxX-1, NSMinY(aRect)+footerHeight-1) toPoint:NSMakePoint(maxX-(footerHeight-1),NSMinY(aRect)+1)];
		[NSBezierPath strokeLineFromPoint:NSMakePoint(maxX-1, NSMinY(aRect)+footerHeight/2) toPoint:NSMakePoint(maxX-(footerHeight/2),NSMinY(aRect)+1)];
	}
#endif
	//MTGEndTimeLog(@"MIObjectRep",@"drawBaseBodyRect:clippedTo:")
}

- (void)drawSelection:(NSRect)clippingRect drawNow:(BOOL)drawItNow;
{
	//MTGStartTimeLog
	// now let's draw the selection if there is any for this clip
	MIWSSelection* sel = [[[self getTopLevelContainerRep] mainViewController] selection];
	if(([sel type] == kMIWSSelectionTypeTimeSlice) && [sel containsObject:self])
	{
		if (!drawItNow) // just compute the selection rect
		{
			// 	kMIWSSelectionTypeTimeSlice,
			// kMIWSSelectionTypeObjects
			float start, endx;
			
			// if it's a slice selection, only draw a slice
			start = [[[self getTopLevelContainerRep] mainViewController] armeTimeToPixel:[sel startTime]];
			endx = [[[self getTopLevelContainerRep] mainViewController] armeTimeToPixel:[sel endxTime]];
			// maybe it's a zero length selection, which is still a selection
			if(start==endx)
				endx = start+1;
			if(start > endx)
			{
				float tmp = start;
				start = endx;
				endx = tmp;
			}
			NSRect tlcFrame = [self getTLCFrame];
			if ( start < NSMinX(tlcFrame) )
				start = NSMinX(tlcFrame);
			if ( endx > NSMaxX(tlcFrame) )
				endx = NSMaxX(tlcFrame);
				
			fSliceSelectionRect = NSMakeRect(start, clippingRect.origin.y, endx-start, clippingRect.size.height);
		}
		else // just draw the selection rect that has been computed before
		{
			[[NSColor colorWithCalibratedRed:0.0 green:0.0 blue:1.0 alpha:0.5] set];
			[NSBezierPath fillRect:fSliceSelectionRect];
		}
	}
	//MTGEndTimeLog(@"MIObjectRep",@"drawSelection:drawNow:")
}

- (void)drawTitleToPoint:(NSPoint)aPoint clippedTo:(NSRect)clippingRect
{
	if(gNoObjectTitlesAtAll)
		return;

	//MTGStartTimeLog
	NSPoint			curPoint;
	NSRect			tmpRect, tmpRect2;
	NSRect			aRect;
	NSRect			imgClipRect = NSZeroRect;
	NSImage			*img;
	float			titleHeight, titleBarHeight;
	
#ifdef SCALABLE_TITLEBAR
	titleHeight = [[self getTopLevelContainerRep] MIVPosToPixel:[fRepresentedObject getTitleHeight]];
	titleBarHeight = [[self getTopLevelContainerRep] MIVPosToPixel:kRepTitleBarHeight];
#else
	titleBarHeight = kRepTitleBarHeight;
	titleHeight = kRepTitleHeight;
#endif


	aRect = [self frame];
	aRect.origin = aPoint;
	aRect.size.height = titleHeight;


#ifndef SMALL_TITLEBAR
	[fBackgroundColor set];
	[NSBezierPath fillRect:NSIntersectionRect(aRect, clippingRect)];

	[[NSColor grayColor] set];
	[NSBezierPath strokeLineFromPoint:NSMakePoint(NSMinX(aRect), NSMinY(aRect)) toPoint:NSMakePoint(NSMaxX(aRect), NSMinY(aRect))];
	aRect.origin.y += (titleHeight - titleBarHeight);
	aRect.size.height = titleBarHeight;
#endif


	// take the left size of the image from aRect, draw it
	NSDivideRect(aRect, &tmpRect, &aRect, [fLeftTitleImage size].width, NSMinXEdge);
	[fLeftTitleImage drawInRect:tmpRect fromRect:NSMakeRect(0,0,[fLeftTitleImage size].width,[fLeftTitleImage size].height) operation:NSCompositeCopy fraction:1];

	// do the same for the right part
	NSDivideRect(aRect, &tmpRect, &tmpRect2, [fRightTitleImage size].width, NSMaxXEdge);
	// add some overlapping
	if ( tmpRect.size.width > 0 )
	{
		[fRightTitleImage drawInRect:tmpRect fromRect:NSMakeRect(0,0,[fRightTitleImage size].width,[fRightTitleImage size].height) operation:NSCompositeCopy fraction:1];
	}

	// draw the center image where in the remaining rect
	// extend tmpRect2 in both directions
	if ( NSWidth(tmpRect2) > 0 )
	{
		tmpRect2 = NSIntersectionRect(tmpRect2, clippingRect);
		tmpRect2.origin.x--;
		tmpRect2.size.width += 2;
		tmpRect2.origin.y = tmpRect.origin.y;
		tmpRect2.size.height = tmpRect.size.height;
		[fCenterTitleImage drawInRect:tmpRect2 fromRect:NSMakeRect(0,0,[fCenterTitleImage size].width, [fCenterTitleImage size].height) operation:NSCompositeCopy fraction:1];
	}
	
#ifdef DRAW_HANDLES
	if ( fHasTopBottomHandles )
	{
		// draw the top handle
		curPoint.x = NSMidX(aRect)- ([mainImageController->fClipHandleTop size].width/2);
		curPoint.y = NSMaxY(aRect) - ((titleBarHeight + [mainImageController->fClipHandleTop size].height)/2);
		[mainImageController->fClipHandleTop compositeToPoint:curPoint operation:NSCompositeSourceAtop];
	}

	curPoint.y = NSMinY(aRect) + 2;


	// draw the left and right handle
	if ( fHasLeftRightHandles )
	{
		curPoint.y += 2;
		curPoint.x = NSMinX(aRect)+2;

		[mainImageController->fClipHandleLeft compositeToPoint:curPoint operation:NSCompositeSourceAtop];

		curPoint.x = ( NSMaxX(aRect) - 2 ) - [mainImageController->fClipHandleRight size].width;

		[mainImageController->fClipHandleRight compositeToPoint:curPoint operation:NSCompositeSourceAtop];

		curPoint.x = aRect.origin.x + [mainImageController->fClipHandleLeft size].width;

		curPoint.x += 4;
		curPoint.y -= 2;
	}
#endif


	// draw the 'collapsed' button
	if ( fHasCollapseButton )
	{
		if ( [fRepresentedObject isCollapsed] )
			img = mainImageController->fContainerButtonArrowHorizontal;
		else
			img = mainImageController->fContainerButtonArrowVertical;

		curPoint = [self drawClippedImage:img atPoint:curPoint clippingRect:clippingRect];

		curPoint.x += 4;
	}



	// draw the 'properties' button
	if ( fHasPropertiesButton )
	{
		curPoint = [self drawClippedImage:mainImageController->fContainerButtonPropertiesOff atPoint:curPoint clippingRect:clippingRect];

		curPoint.x += 4;
	}



	// draw the 'ON/OFF' button
	if ( fHasOnOffButton )
	{
		if ( [fRepresentedObject isMuted] )
			img = mainImageController->fContainerButtonOn;
		else
			img = mainImageController->fContainerButtonOff;

		curPoint = [self drawClippedImage:img atPoint:curPoint clippingRect:clippingRect];
		curPoint.x += 4;
	}

	// draw the title at the beginning of the object

#ifndef SMALL_TITLEBAR
	aRect = [self frame];
	aRect.origin = aPoint;
	aRect.origin.y++;
	aRect.size.height = (titleHeight - titleBarHeight) - 1;
#endif

	[self drawScrollingTitleWithTitleRect:aRect];
	//MTGEndTimeLog(@"MIObjectRep",@"drawTitleToPoint:clippedTo:")
}

- (void)drawScrollingTitleWithTitleRect:(NSRect)titleRect
{
	
	if ( [[fTLCRep mainViewController] vZoomIndex] < [MIMainViewController getDefaultVZoomIndex] )
		return;

	//MTGStartTimeLog
	NSRect	stringRect;
	float	imgWidth = [fCachedTitleStringImage size].width;

	stringRect = titleRect;
#ifdef SMALL_TITLEBAR
	stringRect.size.height = [fCachedTitleStringImage size].height;
#endif
//	stringRect.origin.y += 2;
#ifdef DRAW_HANDLES
	if ( fHasLeftRightHandles )
		stringRect.origin.x += [mainImageController->fClipHandleLeft size].width + 4;
	if ( fHasCollapseButton )
		stringRect.origin.x += [mainImageController->fContainerButtonArrowHorizontal size].width + 4;
	if ( fHasPropertiesButton )
		stringRect.origin.x += [mainImageController->fContainerButtonPropertiesOff size].width + 4;
	if ( fHasOnOffButton )
		stringRect.origin.x += [mainImageController->fContainerButtonOff size].width + 4;
#endif
	stringRect.size.width = NSMaxX(titleRect) - NSMinX(stringRect);
#ifdef DRAW_HANDLES
	if ( fHasLeftRightHandles )
		stringRect.size.width -= ([mainImageController->fClipHandleLeft size].width + 4);
#endif
	// stringRect is the maximum rectangle we have

	if ( NSWidth(stringRect) <= imgWidth || gCurrentlyDrawingToImage )
	{
		[self drawClippedImage:fCachedTitleStringImage atPoint:stringRect.origin clippingRect:stringRect];
		fLastTitleImageRect = stringRect;
	}
	else
	{
		// we have some freedom to place it.
		NSRect visibleRect = [fTLCRep visibleRect];
		NSRect tmpRect;

		// check if it can be displayed to the left.
		tmpRect = stringRect;
		tmpRect.size.width = imgWidth;
		if ( NSContainsRect( visibleRect, tmpRect ) )
		{
			// the leftmost part of the clip is visible, put it there.
			stringRect = tmpRect;
			[self drawClippedImage:fCachedTitleStringImage atPoint:stringRect.origin clippingRect:stringRect];
			fLastTitleImageRect = stringRect;
		}
		else if ( [MIPreferences movingTitles] )
		{
			// put it at the leftmost part of the clip that is visible
			// tmpRect represents the visible portion of the object's free space to draw the string
			tmpRect = NSIntersectionRect( visibleRect, stringRect );
			tmpRect.size.height = NSHeight(stringRect);
			tmpRect.origin.y = NSMinY(stringRect);

			if ( !NSEqualPoints( tmpRect.origin, NSZeroPoint ) )
			{
				// if the intersection rect is too small to fit the string, draw it so that the end of
				// the clip matches the end of the max string rect
				if ( tmpRect.size.width < imgWidth && /*NSMinX(tmpRect) > (NSMinX(stringRect) + imgWidth )*/
					 NSMinX(titleRect) < NSMinX(visibleRect) )
				{
					tmpRect.origin.x = NSMaxX(tmpRect) - imgWidth;
				}
				tmpRect.size.width = imgWidth;			
				stringRect = tmpRect;
				[self drawClippedImage:fCachedTitleStringImage atPoint:stringRect.origin clippingRect:stringRect];
				fLastTitleImageRect = stringRect;
			}
		}
	}
	//MTGEndTimeLog(@"MIObjectRep",@"drawScrollingTitleWithTitleRect:")
}

- (NSPoint)drawClippedImage:(NSImage*)img atPoint:(NSPoint)aPoint clippingRect:(NSRect)clippingRect
{
	NSRect	imgClipRect = NSZeroRect;
	
	imgClipRect.size = [img size];
	
	if ( !NSEqualRects(NSZeroRect, clippingRect) )
	{
		if ( NSMaxX(clippingRect) < aPoint.x + [img size].width )
			imgClipRect.size.width = NSMaxX(clippingRect) - aPoint.x;
		if ( NSMaxY(clippingRect) < aPoint.y + [img size].height )
			imgClipRect.size.height = NSMaxY(clippingRect) - aPoint.y;
	}
	
	[img compositeToPoint:aPoint fromRect:imgClipRect operation:NSCompositeSourceAtop];

	aPoint.x += [img size].width;
	
	return aPoint;
}

- (void)refreshCachedTitleImage:(BOOL)createIfAbsent;
{
	if(gNoObjectTitlesAtAll)
		return;

	NSRect				aRect;
	static NSString		*title = nil;
	NSSize				titleSize;
	NSPoint				titleOrigin;
	NSRect				minRect = NSZeroRect;
	BOOL				bTitleImageNeedsRecreating = NO;
	float				titleHeight, titleBarHeight;
	
/*	if ( !createIfAbsent &&
	     !fCachedTitleImage )
		return;*/

#ifdef SCALABLE_TITLEBAR
	titleHeight = [[self getTopLevelContainerRep] MIVPosToPixel:[fRepresentedObject getTitleHeight]];
	titleBarHeight = [[self getTopLevelContainerRep] MIVPosToPixel:kRepTitleBarHeight];
#else
	titleHeight = kRepTitleHeight;
	titleBarHeight = kRepTitleBarHeight;
#endif

	aRect = [self frame];
	aRect.size.height = titleHeight;

	minRect.size.height = titleHeight;
#ifdef DRAW_HANDLES

	if ( fHasLeftRightHandles )
		minRect.size.width += [mainImageController->fClipHandleLeft size].width + 4;
	if ( fHasCollapseButton )
		minRect.size.width += [mainImageController->fContainerButtonArrowHorizontal size].width + 4;
	if ( fHasPropertiesButton )
		minRect.size.width += [mainImageController->fContainerButtonPropertiesOff size].width + 4;
	if ( fHasOnOffButton )
		minRect.size.width += [mainImageController->fContainerButtonOff size].width + 4;

	if ( minRect.size.width < [fLeftTitleImage size].width )
		minRect.size.width = [fLeftTitleImage size].width;
#endif
	// create the text
	if ( !title || ![[fRepresentedObject title] isEqualToString:title] )
		bTitleImageNeedsRecreating = YES;
	
	if ( !fCachedTitleStringImage || bTitleImageNeedsRecreating )
	{
		[title release];
		title = [[fRepresentedObject title] retain];

		[self refreshCachedTitleStringImage];
		titleOrigin.x = 1;
		titleOrigin.y = (titleHeight - titleBarHeight)/2 - titleSize.height/2;
	}
	
	if ( NSWidth(aRect) <= (kCacheingMinSize.width + kCacheingHorizontalExtra ) )
	{
		// check if a new image is to be allocated or if the old one suffices
		fCachedTitleImage = [self createOrRefreshImage:fCachedTitleImage ofSize:aRect.size];
		
		// lock the focus on the image to display things in it
		[fCachedTitleImage lockFocus];
		{
			gCurrentlyDrawingToImage = YES;
			[self drawTitleToPoint:NSZeroPoint clippedTo:NSZeroRect];
			[title drawAtPoint:NSMakePoint(NSMaxX(minRect),titleOrigin.y) withAttributes:nil];
			if ( fTLCRep->fDrawRedrawRects )
			{
				[[NSColor magentaColor] set];
				[NSBezierPath strokeLineFromPoint:NSZeroPoint toPoint:NSMakePoint(NSMaxX(aRect), NSMaxY(aRect))];
			}
			gCurrentlyDrawingToImage = NO;
		}
		[fCachedTitleImage unlockFocus];
	}
}

- (void)refreshCachedTitleStringImage
{
	if(gNoObjectTitlesAtAll)
		return;

	float 				titleHeight;
	NSMutableDictionary	*dic;
	NSSize				titleSize = NSZeroSize;
	NSFont				*theFont;
	NSSize				maxSize;
	float				lockOffset = 0;
	static NSFont		*lucidaGrande = [[NSFont fontWithName:@"Lucida Grande" size:10] retain];

    // $$$STEPHAN: no title for the object??? do we do something about it?c
	if ( ![fRepresentedObject title] )
        return;
        
#ifdef SCALABLE_TITLEBAR
	titleHeight = [[self getTopLevelContainerRep] MIVPosToPixel:[fRepresentedObject getTitleHeight]];
#else
	titleHeight = kRepTitleHeight;
#endif
	
#ifdef SMALL_TITLEBAR
	maxSize = [self rectForZone:MIObjectRepDragBarZone].size;
	float fs = 0;
	while ( /*titleSize.width < maxSize.width &&*/ titleSize.height < maxSize.height )
	{
		fs++;
//		theFont = [NSFont fontWithName:@"Verdana-Regular" size:fs];
		theFont = [NSFont fontWithName:@"Lucida Grande" size:fs];
		if ( theFont )
		{
			dic = [NSMutableDictionary dictionaryWithObject:theFont forKey:NSFontAttributeName];
			titleSize = [[fRepresentedObject title] sizeWithAttributes:dic];
		}
		else
		{
			dic = nil;
			titleSize = NSZeroSize;
		}
	}
	
	if ( theFont ) 
	{
		theFont = [NSFont fontWithName:@"Lucida Grande" size:fs-1];
		dic = [NSMutableDictionary dictionaryWithObject:theFont forKey:NSFontAttributeName];
		titleSize = [[fRepresentedObject title] sizeWithAttributes:dic];		
	}
#else
	maxSize = [self rectForZone:MIObjectRepTitleZone].size;
	theFont = lucidaGrande;
	dic = [NSMutableDictionary dictionaryWithObject:theFont forKey:NSFontAttributeName];
	if ( [self isSelected] && [[[fTLCRep mainViewController] selection] type] == kMIWSSelectionTypeObjects )
		[dic setObject:[NSColor whiteColor] forKey:NSForegroundColorAttributeName];
	else
		[dic setObject:[NSColor blackColor] forKey:NSForegroundColorAttributeName];
	
	titleSize = [[fRepresentedObject title] sizeWithAttributes:dic];
#endif







	if (	[fLastTitle isEqualToString:[fRepresentedObject title]]
		&&	fLastLockedStatus == [fRepresentedObject isLocked]
#ifdef SMALL_TITLEBAR
		&&	NSEqualSizes(NSMakeSize(titleSize.width + lockOffset,maxSize.height), [fCachedTitleStringImage size]) 
#endif
		&&	fLastSelectedStatus == [self isSelected] )
		return;
	else
	{
		[fLastTitle release];
		fLastTitle = [fRepresentedObject title];
		if([fLastTitle isEqualToString:@""])
			fLastTitle = [NSString stringWithString:@"Untitled"];
		[fLastTitle retain];
		fLastLockedStatus = [fRepresentedObject isLocked];
		fLastSelectedStatus = [self isSelected];
	}
		



	if ( [fRepresentedObject isLocked] )
		lockOffset = [mainImageController->fClipLock size].width + 3;
		
	/// $$$HACK title is too high, need to decrease it else shadow gets cropped
//	titleSize.height -= 2;
//	titleSize.height = maxSize.height;

	
	//$$HACK from Alain, I have seen the lockFocus crashing because an image was zero pixel high so ...
	if (maxSize.height < 1)
		return; //maxSize.height = 1;

	[fCachedTitleStringImage release];
	fCachedTitleStringImage = [[NSImage alloc] initWithSize:NSMakeSize(titleSize.width + lockOffset,maxSize.height)];

	[fCachedTitleStringImage lockFocus];
	{
		gCurrentlyDrawingToImage = YES;
#ifdef SMALL_TITLEBAR
		[fCenterTitleImage drawInRect:NSMakeRect(0,0,[fCachedTitleStringImage size].width,[fCachedTitleStringImage size].height) fromRect:NSMakeRect(0,0,[fCenterTitleImage size].width, [fCenterTitleImage size].height) operation:NSCompositeCopy fraction:1];
		if ( [fRepresentedObject isLocked] )
			[mainImageController->fClipLock compositeToPoint:NSZeroPoint operation:NSCompositeSourceAtop];

		[[fRepresentedObject title] drawAtPoint:NSMakePoint(lockOffset,(titleHeight/2)-(titleSize.height/2)) withAttributes:dic];
#else
		[[self backgroundColor] set];
		[NSBezierPath fillRect:NSMakeRect(0,0,[fCachedTitleStringImage size].width,[fCachedTitleStringImage size].height)];
		if ( [fRepresentedObject isLocked] )
			[mainImageController->fClipLock compositeToPoint:NSZeroPoint operation:NSCompositeSourceAtop];
		[[fRepresentedObject title] drawAtPoint:NSMakePoint(lockOffset,(((titleHeight-10)/2)-(titleSize.height/2))) withAttributes:dic];
#endif
		if ( fTLCRep->fDrawRedrawRects )
		{
			[[NSColor magentaColor] set];
			[NSBezierPath strokeLineFromPoint:NSZeroPoint toPoint:NSMakePoint(titleSize.width, maxSize.height)];
		}
	}
	gCurrentlyDrawingToImage = NO;
	[fCachedTitleStringImage unlockFocus];	
}

- (NSImage*)createOrRefreshImage:(NSImage*)image ofSize:(NSSize)size
{
	NSImage	*theImage = nil;
	
	theImage = image;
	
	if ( theImage )
	{
		if ( !NSEqualSizes([theImage size], size) )
		{
			[theImage release];
			theImage = [[NSImage alloc] initWithSize: size];
		}
	}
	else
	{
		theImage = [[NSImage alloc] initWithSize:size];
	}

	return theImage;
}

- (void)refreshCachedAutomationImage:(BOOL)createIfAbsent
{
    NSRect	zeroFrame;

	if ( !createIfAbsent &&
	     !fCachedAutomationImage )
		return;

	zeroFrame = [self rectForZone:MIObjectRepAutomationZone];
    zeroFrame.origin = NSZeroPoint;

	if ( NSEqualRects( zeroFrame, NSZeroRect) )
		return;

	fCachedAutomationImage = [self createOrRefreshImage:fCachedAutomationImage ofSize:zeroFrame.size];

		
    [fCachedAutomationImage lockFocus];
		gCurrentlyDrawingToImage = YES;
		[self drawBaseAutomationRect:zeroFrame clippedTo:zeroFrame];
		if ( fTLCRep->fDrawRedrawRects )
		{
			[[NSColor magentaColor] set];
			[NSBezierPath strokeLineFromPoint:NSZeroPoint toPoint:NSMakePoint(NSMaxX(zeroFrame), NSMaxY(zeroFrame))];
		}
		gCurrentlyDrawingToImage = NO;
    [fCachedAutomationImage unlockFocus];
}


- (void)refreshCachedBodyImage:(BOOL)createIfAbsent
{
//	NSRect		aRect;
//	float		titleHeight;
	if ( fIsBeingTimeStretched )
		return;
		
	if ( !createIfAbsent &&
	     !fCachedBodyImage )
		return;
/*
#ifdef SCALABLE_TITLEBAR
	titleHeight = [[self getTopLevelContainerRep] MIVPosToPixel:[fRepresentedObject getTitleHeight]];
#else
	titleHeight = kRepTitleHeight;
#endif


	aRect = [self frame];
	aRect.size.height -= titleHeight;
	
	if ( !NSHeight(aRect) )
		return; // if the frame is collapsed, there is no body to draw and thus no image to cache...
		
	// check if a new image is to be allocated or if the old one suffices
    
    
    // lock the focus on the image to display things in it
    zeroFrame = fFrame;
*/
    NSRect	zeroFrame;

	zeroFrame = [self rectForZone:MIObjectRepBodyZone];
    zeroFrame.origin = NSZeroPoint;

	if ( NSEqualRects( zeroFrame, NSZeroRect ) )
		return;
	
	if ( NSWidth(zeroFrame) >= 10000 )
	{
		[fCachedBodyImage release];
		fCachedBodyImage = nil;
		return;
	}
	fCachedBodyImage = [self createOrRefreshImage:fCachedBodyImage ofSize:zeroFrame.size];

    [fCachedBodyImage lockFocus];
		gCurrentlyDrawingToImage = YES;
		[self drawBaseBodyRect:zeroFrame clippedTo:zeroFrame];
		if ( fTLCRep->fDrawRedrawRects )
		{
			[[NSColor magentaColor] set];
			[NSBezierPath strokeLineFromPoint:NSZeroPoint toPoint:NSMakePoint(NSMaxX(zeroFrame), NSMaxY(zeroFrame))];
		}
		gCurrentlyDrawingToImage = NO;
    [fCachedBodyImage unlockFocus];
}

- (void)drawCachedAutomationImageToPoint:(NSPoint)aPoint fromRect:(NSRect)rect
{
    [fCachedAutomationImage compositeToPoint:aPoint fromRect:rect operation:NSCompositeCopy];
}

- (void)drawCachedBodyImageToPoint:(NSPoint)aPoint fromRect:(NSRect)rect
{
    [fCachedBodyImage compositeToPoint:aPoint fromRect:rect operation:NSCompositeCopy];
	
	if ( fIsBeingTimeStretched )
	{
		NSRect	tmpRect = fFrame;
		tmpRect.size.height = rect.size.height;
		[fCachedBodyImage drawInRect:tmpRect fromRect:NSMakeRect(0,0,[fCachedBodyImage size].width,[fCachedBodyImage size].height) operation:NSCompositeCopy fraction:1.0];
	}
}

- (void)drawCachedTitleImageToPoint:(NSPoint)aPoint fromRect:(NSRect)rect
{
	if(gNoObjectTitlesAtAll)
		return;

	NSRect		pseudoFrameRect;
	NSPoint		offset;
	
	/*
		rect is a rectangle representing the portion of the title to draw if the title had its origin at 0,0
		aPoint is the point where that portion is to be drawn (so, not the origin of the title's frame) 
	*/
	
	offset.x = aPoint.x - NSMinX(rect);
	offset.y = aPoint.y - NSMinY(rect); 
		
	pseudoFrameRect = [self frame];
	pseudoFrameRect.origin = offset;

	if ( fCachedTitleImage )
		[fCachedTitleImage compositeToPoint:aPoint fromRect:rect operation:NSCompositeCopy];
}

- (void)setNeedsDisplay
{
	NSRect fr = [self getTLCFrame];
	
	// include the shadow
	if ( [MIPreferences shadowsAroundObject] && [[fRepresentedObject parentObject] isTLC] )
	{
		fr.origin.x -= [mainImageController->fClipExternalShadowLeft size].width;
		fr.size.width += [mainImageController->fClipExternalShadowLeft size].width;
		fr.size.width += [mainImageController->fClipExternalShadowRight size].width;
		fr.origin.y -= [mainImageController->fClipExternalShadowBottomCenter size].height;
		fr.size.height += [mainImageController->fClipExternalShadowBottomCenter size].height;
		fr.size.height++;  // because anti aliasing effects of the pixel above may not be rendered correctly
	}
	else
		fr = NSInsetRect(fr, -1,-1); // because anti aliasing effects of the pixel above may not be rendered correctly
		
	[[self getTopLevelContainerRep] setNeedsDisplayInRect:fr];
	
	if ( fTrackingRectTag == -1 )
		[self refreshTrackingRect];

}

- (void)setDataNeedsDisplay
{
	[self setNeedsDisplay];
//	[[self getTopLevelContainerRep] setNeedsDisplayInRect:[self getTLCFrame]];
}

- (void)showProperties
{
}


- (void)setSelected:(BOOL)selected
{
	if ( selected == fSelected )
		return;
		
	fSelected = selected;
	[self setImagesAndColor];
	[self refreshCachedTitleImage:NO];
	[self refreshCachedAutomationImage:NO];
	[self refreshCachedBodyImage:NO];
	[self refreshCachedTitleStringImage];
	[self invalidateCachedImage];
}


- (TArmeDoc*)getDoc
{
	return [[self representedObject] WSObject]->GetDoc();
}

- (void)invalidateCachedImage
{
}

- (void)resetActiveCursorRects
{
	return;
	
	if ( fTrackingRectTagArray )
	{
		NSEnumerator *enumerator = [fTrackingRectTagArray objectEnumerator];
		MIActiveCursor *activeCursor;

		while (( activeCursor = [enumerator nextObject] )) {
			[fTLCRep removeTrackingRect:[activeCursor tag]];
		}
		
		[fTrackingRectTagArray release];
		fTrackingRectTagArray = nil;
		fActiveCursor = nil;
	}

	fTrackingRectTagArray = [[NSMutableArray alloc] initWithCapacity:10];
	[self addActiveCursors];
}

- (void)refreshTrackingRect
{
	if ( !gEnableCursorRectsUpdate )
		return;
	
	if ( fTrackingRectTag != -1 )
	{
		[fTLCRep removeTrackingRect:fTrackingRectTag];
		fTrackingRectTag = -1;
	}
		
	fTrackingRectTag = [fTLCRep addTrackingRect:NSInsetRect([self getTLCFrame],-1,-1) owner:self userData:nil assumeInside:NO];
}

- (void)addActiveCursors {
	// to be implemented by subclasses
}

- (void)addActiveCursor:(MIActiveCursor*)activeCursor
{

	return;

	NSPoint pt = [fTLCRep convertPoint:[[fTLCRep window] convertScreenToBase:[NSEvent mouseLocation]] fromView:nil];

	[activeCursor setTag:[fTLCRep addTrackingRect:[activeCursor activeRect] owner:self userData:nil assumeInside:NSPointInRect(pt, [activeCursor activeRect])]];

	[fTrackingRectTagArray addObject:activeCursor];
}

- (void)mouseEntered:(NSEvent *)theEvent
{
	[[[[self representedObject] parentObject] findRepresentationInTLC:fTLCRep] mouseExited:theEvent];
	fMouseIsOverMe = YES;
	[[fTLCRep window] invalidateCursorRectsForView:fTLCRep];
	[[fTLCRep window] resetCursorRects];


	return;

	

	NSEnumerator *enumerator = [fTrackingRectTagArray objectEnumerator];
	MIActiveCursor *activeCursor;
	
	while (( activeCursor = [enumerator nextObject] )) {
		if ( [activeCursor tag] == [theEvent trackingNumber] )
			fActiveCursor = activeCursor;
	}

	fTimer = [NSTimer scheduledTimerWithTimeInterval:0.25 target:self selector:@selector(trigger:) userInfo:nil repeats:YES];
	[self trigger:nil];
}

- (void)trigger:(NSTimer*)timer {
	
//	unsigned int modifiers = [NSEvent modifiers];
	unsigned int modifiers = 0; ///$$$TODO see bug 556

	if ( modifiers & NSCommandKeyMask ) {
		[[fActiveCursor commandCursor] set];
	} else if ( modifiers & NSControlKeyMask ) {
		[[fActiveCursor controlCursor] set];
	} else if ( modifiers & NSAlternateKeyMask ) {
		[[fActiveCursor alternateCursor] set];
	} else if ( modifiers & NSShiftKeyMask ) {
		[[fActiveCursor shiftCursor] set];
	} else {
		[[fActiveCursor plainCursor] set];
	}

}

- (void)mouseExited:(NSEvent *)theEvent
{
	fMouseIsOverMe = NO;
	[[[[self representedObject] parentObject] findRepresentationInTLC:fTLCRep] mouseEntered:theEvent];

	[fTimer invalidate];
	fTimer = nil;
	fActiveCursor = nil;
	[[NSCursor arrowCursor] set];
}

- (id)retain
{	
//	printf("about to [retain] MIObjectRep(%p,%s). Ref count will go from %d to %d\n",(void*)self,[[self representedObject] WSObject]->GetName(),[self retainCount],[self retainCount]+1);
	return [super retain];
}

- (void)release
{
//	printf("about to [release] MIObjectRep(%p,%s). Ref count will go from %d to %d\n",(void*)self,[[self representedObject] WSObject]->GetName(),[self retainCount],[self retainCount]-1);
	[super release];
}

- (id)autorelease
{
	return [super autorelease];
}
@end

