// -*-C++-*- 

/*  inc/platform/Wq.hpp  */

/*
 * Author: Philogelos A. <Philogelos@yahoo.com>
 * Maintainer: Philogelos A.
 * Keywords: C++, library, containers
 *
 * Copyright (C) 1999 Philogelos A.
 *
 * This file is part of Quercus Robusta.
 *
 * Quercus Robusta is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Library General Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version.
 *
 * This software 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 Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this software; see the file COPYING.LIB.  If not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 *
 */



#ifndef __WQ_HPP__
#define __WQ_HPP__

/* $Id$ */

/* #define USE_WQ */

#if defined( WANT_USE_WQ )
#define USE_WQ
#elif defined( UNWANT_USE_WQ )
#if defined( USE_WQ )
#undef USE_WQ
#endif
#endif

#if defined( USE_WQ )

#include "Top.hpp"
#include "defines.h"

#include "Win32Platform.hpp"
#if !defined( USE_WIN32 )
#error "USE_WQ implies USE_WIN32"
#endif

#include "platform/threads/Win32Thread.hpp"
#if !defined( USE_WIN32THREADS )
#error "USE_WQ implies USE_WIN32THREADS"
#endif

#include "String.hpp"
#include "platform/threads/Runnable.hpp"
#include "observe/ObservableAdapter.hpp"
#include "Condition.hpp"
#include "iter/enumerations/TypedEnumeration.hpp"
#include "iter/iterators/Iterator.hpp"
#include "platform/Aq.hpp"
#include "Guard.hpp"

/**

   @author Philogelos
   @created
*/
class Wq : public virtual Top
{
public: class Window;
public: class WqEvent;
public: class WqEventSource;
public: class WindowEventSource;
public: class Drawable;
public: class GC;
public: class DC;
public: class WPainter;

public: class Bitmap;
public: class Brush;
public: class Pen;
public: class Font;
public: class Cursor;

public: class KeyEvent;
public: class ButtonEvent;
public: class MouseMotionEvent;
public: class FocusEvent;
public: class WindowEvent;
public: class DestroyEvent;
public: class ResizeEvent;
public: class SelectionEvent;

public: class MSWindowSystem : public Aq::GUISystem,
		public virtual Object
{
public: virtual Aq::Painter *createPainter( Aq::GraphicContext *aContext, 
											Aq::Drawable *aDrawable ) const;
public: static MSWindowSystem *msWindowSystem;
};

public: class WqEventSource : public Aq::EventSource
		{
		public: WqEventSource();
		public: virtual Aq::AqEvent *getNextTypedElement() = 0;
		public: virtual void  processEvent( Aq::AqEvent *anEvent );
		};

public: class Drawable : public Aq::Drawable
		{
		public: Drawable();

		public: virtual DC *getDC() const = 0;
		public: virtual void ungetDC( DC *aDC ) const = 0;
		};

public: class Window : public virtual Win32Object,
		public Aq::Window,
		public Drawable
		{
			friend WindowEventSource;

		public: Window( HANDLE aHandle );
		public: virtual ~Window();

		public: void show() const;
		public: virtual Aq::EventSource *getEventSource() const;
		public: WindowEventSource *getWEventSource() const;

		public: void move( Aq::CoordX aX, Aq::CoordY aY );
		public: void setSize( Aq::Size aWidth, 
						Aq::Size aHeight );
		public: void setTitle( String aTitle );

		public: void makeForeground();

		public: void setCursor( Cursor *aCursor );
		public: void showCursor( boolean toShow );

		public: virtual DC *getDC() const;
		public: virtual void ungetDC( DC *aDC ) const;

		public: virtual boolean isCursorWithin() const;

		public: static String getDefaultClassName();
		public: static Window *create();
		public: static UINT  terminateMessage;
		public: static UINT  wakeUpMessage;

		protected: Thread *eventLoop;
		protected: WindowEventSource *events;
		protected: List *triggers;
		protected: Cursor *cursor;

		protected: static boolean defaultClassRegistered;
		protected: static LRESULT CALLBACK defWinProc
					   ( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
		protected: static void *winLoop( void * );
		};

public: class CloseWindowException : public virtual Exception
		{
		public: CloseWindowException();
		public: virtual ~CloseWindowException();
		};

public: class GC : public Aq::GraphicContext,
		public virtual Object
		{
		  friend WPainter;

		public: GC( COLORREF aFore, COLORREF aBack, 
					Pen *aPen, Brush *aBrush, Font *aFont );
		public: virtual ~GC();

		public: void flushTo( DC *aDC );

		protected: COLORREF fg;
		protected: COLORREF bg;
		protected: Pen *pen;
		protected: Brush *brush;
		protected: Font *font;

		protected: Brush *cleanBrush;
		};

public: class WPainter : public Aq::Painter,
		public virtual Object
		{
		public: WPainter( GC *aGC, Drawable *aWindow );
		public: virtual ~WPainter();

		public: virtual void init();
		public: virtual void done();

		public: virtual void drawLine( Aq::CoordX aStartX, 
									   Aq::CoordY aStartY, 
									   Aq::CoordX anEndX, 
									   Aq::CoordY anEndY ) const;
		public: virtual void drawPoint( Aq::CoordX aX, Aq::CoordY aY ) const;
		public: virtual void drawCString( Aq::CoordX aX, Aq::CoordY aY, 
										  char *aString ) const;

		public: virtual void fillRectangle( Aq::CoordX aX, 
											Aq::CoordY aY,
											Aq::Size aWidth, 
											Aq::Size aHeight ) const;
		public: virtual void clearRectangle( Aq::CoordX aX, 
											 Aq::CoordY aY,
											 Aq::Size aWidth, 
											 Aq::Size aHeight ) const;

		public: virtual void copyFrom( Aq::CoordX aSourceX, 
									   Aq::CoordY aSourceY, 
									   Aq::Size aWidth, Aq::Size aHeight,
									   Aq::Drawable *aDrawable,
									   Aq::CoordX aDestX, 
									   Aq::CoordY aDestY ) const;

		public: virtual void setDrawable( Aq::Drawable *aDrawable );
		
		public: virtual void setWDrawable( Drawable *aDrawable );
		public: Drawable *getWDrawable() const;
		public: GC *getGC() const;

		protected: Drawable *arena;
		protected: mutable DC *dc;
		};

public: class WindowEventSource : public WqEventSource
		{
		public: WindowEventSource();
		public: virtual boolean init();
		public: virtual void done();
		public: virtual Aq::AqEvent *getNextTypedElement();
		public: void selectMouseMotion( boolean isSelected );
		public: virtual boolean ignorableEvent( MSG *aMsg ) const;

		protected: Window *hostWindow;
		protected: boolean generateMouseMotionEvents;
		};

public: class WqEvent : public Aq::AqEvent,
		  public virtual Object
		{
		public: WqEvent( MSG *anEvent );

		public: static WqEvent *create( MSG *anEvent );
		public: static String getEventName( unsigned anId );

		public: virtual String toString() const;
		public: virtual String getClassName() const;

		public: MSG event;

		public: typedef enum 
		{ 
		  key = ( 1<< 0 ), 
		  button = ( 1<< 1 ), 
		  mouse = ( 1<< 2 ), 
		  focus = ( 1<< 3 ), 
		  window = ( 1<< 4 ), 
		  destroy = ( 1<< 5 ), 
		  resize = ( 1<< 6 ),
		  selection = ( 1<< 7 ), 
		  other = ( 1<< 8 ) 
		} EventType;

		public: typedef struct
		{
		  Index type;
		  char *name;
		} MessageType;

		public: static void initTypes();
		public: static MessageType *types;
		};


public: class KeyEvent : public virtual WqEvent,
		public virtual Aq::KeyEvent
{
public: KeyEvent( MSG *anEvent );
public: virtual String getClassName() const;
};

public: class ButtonEvent : public virtual WqEvent,
		public virtual Aq::KeyEvent

{
public: ButtonEvent( MSG *anEvent );
public: virtual String getClassName() const;
};

public: class MouseMotionEvent : public virtual WqEvent,
		public virtual Aq::KeyEvent

{
public: MouseMotionEvent( MSG *anEvent );
public: virtual String getClassName() const;
};

public: class FocusEvent : public virtual WqEvent,
		public virtual Aq::KeyEvent

{
public: FocusEvent( MSG *anEvent );
public: virtual String getClassName() const;
};

public: class WindowEvent : public virtual WqEvent,
		public virtual Aq::KeyEvent

{
public: WindowEvent( MSG *anEvent );
public: virtual String getClassName() const;
};

public: class DestroyEvent : public virtual WqEvent,
		public virtual Aq::KeyEvent

{
public: DestroyEvent( MSG *anEvent );
public: virtual String getClassName() const;
};

public: class ResizeEvent : public virtual WqEvent,
		public virtual Aq::KeyEvent

{
public: ResizeEvent( MSG *anEvent );
public: virtual String getClassName() const;
};

public: class SelectionEvent : public virtual WqEvent,
		public virtual Aq::KeyEvent

{
public: SelectionEvent( MSG *anEvent );
public: virtual String getClassName() const;
};

public: class DC : public Win32Object
		{
		public: DC( HANDLE aHandle );
		public: virtual ~DC();

		public: void drawString( Aq::CoordX aX, Aq::CoordY aY, String aString );
		public: void drawCString( Aq::CoordX aX, Aq::CoordY aY, char *aString );

		public: void fillRectangle( Aq::CoordX aX, Aq::CoordY aY, 
									Aq::Size aWidth, 
									Aq::Size aHeight, Brush *aBrush );

		public: void copyTo( Aq::CoordX aSourceX, Aq::CoordY aSourceY,
							 Aq::Size aWidth, Aq::Size aHeight,
							 DC *aDC, 
							 Aq::CoordX aDestX, Aq::CoordY aDestY,
							 DWORD anOp );

		public: void setFont( Font *aFont );
		public: void setBitmap( Bitmap *aBitmap );
		public: void setBrush( Brush *aBrush );
		public: void setPen( Pen *aPen );

		public: Font   *getFont() const;
		public: Bitmap *getBitmap() const;
		public: Brush  *getBrush() const;
		public: Pen    *getPen() const;

		public: void setTextForeground( COLORREF aColor );
		public: void setTextBackground( COLORREF aColor );

		public: COLORREF getTextForeground() const;
		public: COLORREF getTextBackground() const;

		public: void selectObject( Win32Object *anObject );
		public: HANDLE  getObject( UINT anObjType ) const;

		public: static DC *create( Window *aWindow );
		public: static DC *createInMemory( HANDLE aHandle );
		};

public: class Bitmap : public Win32Object,
		public Drawable
		{
		public: Bitmap( HANDLE aHandle );
		public: virtual ~Bitmap();

		public: Aq::Size getWidth() const;
		public: Aq::Size getHeight() const;

		public: void setSize( Aq::Size aWidth, Aq::Size aHeight );

		public: virtual void setDC( DC *aDC );
		public: virtual DC *getDC() const;
		public: virtual void ungetDC( DC *aDC ) const;

		public: static Bitmap *create( DC *aDC, Aq::Size aWidth,
									   Aq::Size aHeight );
		public: static Bitmap *load( int aResource );

		protected: DC *dc;
		};

public: class Brush : public Win32Object
		{
		public: Brush( HANDLE aHandle );
		public: virtual ~Brush();

		public: static Brush *createSolid( COLORREF aColor );
		public: static Brush *createStock( int aStockBrush );
		};

public: class FontIterator : public virtual Iterator,
			public virtual Object
		{
		public: FontIterator( DC *aDC );
		public: virtual ~FontIterator();

		public: virtual void iterate( Iterable *aBlock );

		protected: DC *dc;
		};

public: class Font : public Win32Object
		{
		public: Font( HANDLE handle );
		public: virtual ~Font();

		public: static Font *create( 
					int aHeight, 
					int aWidth, 
					int anEscapement, 
					int anOrientation, 
					int aWeight, 
					DWORD anItalic, 
					DWORD anUnderline, 
					DWORD aStrikeOut, 
					DWORD aCharSet, 
					DWORD anOutputPrecision, 
					DWORD anwClipPrecision, 
					DWORD aQuality, 
					DWORD aPitchAndFamily, 
					LPCTSTR aFace ); 
 
		public: static Font *createDefault();
		};

public: class Cursor : public Win32Object
		{
		public: Cursor( HANDLE aHandle );
		public: virtual ~Cursor();

		public: static Cursor *load( char *aResource );
		public: static Cursor *loadGlobal( HANDLE aModule, char *aResource );
		public: static Cursor *create( Aq::Size aWidth, Aq::Size aHeight, 
					Aq::CoordX aHotSpotX, Aq::CoordY aHotSpotY, 
					void *anANDMask, void *aXORMask );
		};

public: class Pen : public Win32Object
		{
		public: Pen( HANDLE aHandle );
		public: virtual ~Pen();

		public: static Pen *create( int aStyle, int aWidth, COLORREF aColor );
		};

public: static void initClass();

#if defined( TESTING )
public: static boolean tester( int );
#endif
};

/* USE_WQ */
#endif

/* $Log$ */

/* __WQ_HPP__ */
#endif
