/*
	File:		FocusLib.h

	Contains:	Library routines for focusing (setting up for drawing into a facet)

	Written by:	Jens Alfke

	Ported to Windows by: Lynn LeBaron

	Copyright:	© 1993 by Apple Computer, Inc., all rights reserved.

	Change History (most recent first):

		 <4>	 4/13/94	SS		changes for laserwriter printing support
		 <3>	  2/2/94	JA		Added CFocusWindow and PS calls.
		 <2>	11/23/93	VL		Made this work with ASLM.
		 <1>	11/23/93	JA		first checked in

	THEORY OF OPERATION:

		FocusLib sets up the drawing environment for a GDI-based part so that
		it can start drawing into a facet. It provides both a one-time change of
		focus (via the Focus call) and a way to set the focus but restore it later
		when the current scope exits (via the CFocus object.)

		Focus() and FocusWindow() are slightly different for offscreen facets. If the
		facet is in an offscreen canvas, Focus will set up to draw into that canvas;
		this is what one usually wants to do. On the other hand, FocusWindow will
		always focus onto an on-screen canvas, even for an off-screen facet. Use
		FocusWindow for things like rubber-banding where your drawing needs to show
		up immediately, even if the facet is offscreen.

		The CFocus object deserves an example:

		void DrawSomething( ODFacet *facet )
		{
			CFocus f(facet);		// Creates a CFocus object on the stack, which
									// changes the focus but stores the old state
			....drawing code...
		}

		Declaring the CFocus object calls its constructor, which sets the focus and
		stores the old state in the CFocus object itself (on the stack.) When its
		scope exists, the CFocus object's destructor is called, which restores the
		old focus.

		This can cause trouble with exceptions, because our exception package currently
		does NOT destruct objects when their scope disappears as a result of a Throw.
		You must do this manually:

		void DrawSomething( ODFacet *facet )
		{
			CFocus f(facet);
			TRY{
				...drawing code that might Throw an exception...
			}CATCH_ALL{
				f.Defocus();
			}ENDTRY
		}

		This example function catches any exception and manually restores the old focus
		before letting the exception continue.
*/


#ifndef _FOCUSLIB_
#define _FOCUSLIB_

class ODFacet;
class ODShape;

#define kCFocusID "appl:cfocus$class"

class CFocus {
	public:
	CFocus( ODFacet *facet, ODShape* invalShape, HDC *theHDC );
	~CFocus( )					{this->Defocus();}

	void Focus( ODFacet *facet, ODShape* invalShape, ODBoolean toWindow );
	void Defocus( );

	protected:
	CFocus( )	{ }
// Flag indicating whether we're drawing to a window or a canvas
	ODBoolean			fToWindow;
// The facet we're working on
	ODFacet		*fFacet;
// The HDC
	HDC				fHDC;
// If we're toWindow, the HWND
	HWND			fHWnd;
// For restoring DC state
	int				fOldMapMode;
	POINT			fOldWinOrg;
	SIZE			fOldVPExtent;
	SIZE			fOldWinExtent;
//	DWORD			fOldWinOrg;
//	DWORD			fOldVPExtent;
//	DWORD			fOldWinExtent;
	int				fSaveDC;
	HRGN			fOldClip;
	ODShape		*fclipShape;
};

class CFocusWindow :public CFocus {
	public:
	CFocusWindow( ODFacet *facet, ODShape* invalShape, HDC *theHDC, HWND *theHWnd );
};

#endif //_FOCUSLIB_
