- BORLAND/: Borland C++ 4.52 (chosen over 4.5 by byte-match: CODE/RP/CW32.LIB
is identical to 4.52's install lib). BCC32/TLINK32/TLIB/MAKE run natively on
Win11; CODE/BT/OPT.MAK is the shipped BTL4OPT.EXE's exact flag recipe
(extender = Borland PowerPack DPMI32, not Phar Lap TNT).
- restoration/source410/: the literal 1995-form reconstruction of the missing
BT game source (never mixed into CODE/). Round 1-3 state:
* 6 of 10 surviving original TUs COMPILE CLEAN under the period toolchain
(BTMSSN, BTCNSL, BTSCNRL, BTTEAM, BTL4MODE, BTL4ARND) - first builds
since 1996.
* BT_L4/BTL4APP.CPP pilot reconstruction: 12/12 functions, Fail() lands on
its binary-recorded line 400 exactly.
* BT/BTCNSL.HPP: console wire IDs recovered from the binary's ctors
(Killed=9, Damaged=10, ScoreUpdate=13, DeathWithoutHonor=15 [T1];
TeamScore=12 flagged [T4]).
* MUNGA/: 8 engine-header backfills back-dated from the BT412 WinTesla tree
(VDATA numbering decomp-verified; AUDREND's OpenAL-era virtual removed -
the period compiler is the drift detector).
* Tooling: backdate.py (WinTesla->1995 header transform), compile410.sh
(per-TU verification sweep under authentic OPT.MAK flags).
* README: corrected roadmap - MECH.HPP is the capstone grown with the mech
TU reconstructions; BTREG.CPP green = the header-family milestone.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1844 lines
71 KiB
C++
1844 lines
71 KiB
C++
/*------------------------------------------------------------------------*/
|
|
/* */
|
|
/* STREAM2.CPP */
|
|
/* */
|
|
/* Copyright Borland International, 1993 */
|
|
/* */
|
|
/* Streaming example, version 2 */
|
|
/* */
|
|
/* Streams enhanced objects but stays compatible with streams created */
|
|
/* with version 1. */
|
|
/* */
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
#include <owl\owlpch.h>
|
|
|
|
#include <new.h>
|
|
#include <cstring.h>
|
|
|
|
#include <classlib\sets.h>
|
|
#include <classlib\objstrm.h>
|
|
|
|
#include <owl\point.h>
|
|
#include <owl\window.h>
|
|
#include <owl\dc.h>
|
|
#include <owl\applicat.h>
|
|
#include <owl\framewin.h>
|
|
#include <owl\dialog.h>
|
|
#include <owl\opensave.h>
|
|
|
|
#include "streams.h"
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
/* */
|
|
/* class GraphicalObject */
|
|
/* */
|
|
/* class GraphicalObject provides the abstract interface */
|
|
/* to all of the graphical objects that can be displayed */
|
|
/* by this graphical system. It should be a virtual base */
|
|
/* of any class derived from it. */
|
|
/* */
|
|
/* Member functions: */
|
|
/* */
|
|
/* GraphicalObject(); */
|
|
/* */
|
|
/* Creates a GraphicalObject with undefined initial */
|
|
/* coordinates. Needed only in multiple inheritance when */
|
|
/* we know that GraphicalObject(const TRect&) will be used */
|
|
/* by derived classes. */
|
|
/* */
|
|
/* GraphicalObject( TPoint p1, TPoint p2 ); */
|
|
/* */
|
|
/* Creates a GraphicalObject with the location and size */
|
|
/* specified by p1 and p2. */
|
|
/* */
|
|
/* virtual ~GraphicalObject(); */
|
|
/* */
|
|
/* Destructor. */
|
|
/* */
|
|
/* void Draw( TDC& ); */
|
|
/* */
|
|
/* Does some preliminary setup of the device context, then */
|
|
/* calls DoDraw() to draw the object. */
|
|
/* */
|
|
/* virtual void DoDraw( TDC& ) = 0; */
|
|
/* */
|
|
/* Draws the object. In GraphicalObject this does */
|
|
/* nothing. It should be overridden in any class */
|
|
/* that will be displayed on the screen. */
|
|
/* */
|
|
/* int operator == ( const GraphicalObject& ) const; */
|
|
/* */
|
|
/* This operator must exist so that we can put GraphicalObjects */
|
|
/* into the Set that is used in TGraphWindow. */
|
|
/* */
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
class GraphicalObject : public TStreamableBase
|
|
{
|
|
|
|
public:
|
|
|
|
GraphicalObject();
|
|
GraphicalObject( TPoint p1, TPoint p2 );
|
|
virtual ~GraphicalObject();
|
|
|
|
void Draw( TDC& );
|
|
int operator == ( const GraphicalObject& obj ) const;
|
|
|
|
protected:
|
|
|
|
TRect bbox;
|
|
|
|
void SetFill(); // Changed
|
|
|
|
private:
|
|
|
|
int Filled; // Changed
|
|
virtual void DoDraw( TDC& ) = 0;
|
|
|
|
class GraphicalObjectDC
|
|
{
|
|
public:
|
|
GraphicalObjectDC( TDC& dc, int filled ); // Changed
|
|
~GraphicalObjectDC();
|
|
operator TDC&() const;
|
|
private:
|
|
TDC& DC;
|
|
};
|
|
|
|
DECLARE_ABSTRACT_STREAMABLE( , GraphicalObject, 2 );// Changed
|
|
|
|
};
|
|
|
|
inline GraphicalObject::GraphicalObject() : Filled(0) // Changed
|
|
{
|
|
}
|
|
|
|
inline GraphicalObject::GraphicalObject( TPoint p1, TPoint p2 ) :
|
|
bbox( p1, p2 ), Filled(0)
|
|
{
|
|
}
|
|
|
|
inline GraphicalObject::~GraphicalObject()
|
|
{
|
|
}
|
|
|
|
void GraphicalObject::Draw( TDC& dc )
|
|
{
|
|
GraphicalObjectDC gdc( dc, Filled ); // Changed
|
|
DoDraw( gdc );
|
|
}
|
|
|
|
inline int GraphicalObject::operator == ( const GraphicalObject& obj ) const
|
|
{
|
|
return this == &obj;
|
|
}
|
|
|
|
// Changed
|
|
void GraphicalObject::SetFill()
|
|
{
|
|
Filled = 1;
|
|
}
|
|
|
|
GraphicalObject::GraphicalObjectDC::GraphicalObjectDC( TDC& dc, int filled ) :
|
|
DC(dc)
|
|
{
|
|
if( filled ) // Changed
|
|
DC.SelectStockObject( BLACK_BRUSH );
|
|
else
|
|
DC.SelectStockObject( NULL_BRUSH );
|
|
}
|
|
|
|
GraphicalObject::GraphicalObjectDC::~GraphicalObjectDC()
|
|
{
|
|
}
|
|
|
|
GraphicalObject::GraphicalObjectDC::operator TDC&() const
|
|
{
|
|
return DC;
|
|
}
|
|
|
|
IMPLEMENT_CASTABLE( GraphicalObject );
|
|
IMPLEMENT_ABSTRACT_STREAMABLE( GraphicalObject );
|
|
|
|
// Changed
|
|
void *GraphicalObject::Streamer::Read( ipstream& in, uint32 ver ) const
|
|
{
|
|
in >> GetObject()->bbox;
|
|
if( ver > 1 )
|
|
in >> GetObject()->Filled;
|
|
else
|
|
GetObject()->Filled = 0; // old objects didn't write this field
|
|
return GetObject();
|
|
}
|
|
|
|
void GraphicalObject::Streamer::Write( opstream& out ) const
|
|
{
|
|
out << GetObject()->bbox << GetObject()->Filled; // Changed
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
/* */
|
|
/* class Line */
|
|
/* */
|
|
/* class Line draws a line between two specified points. */
|
|
/* */
|
|
/* Member functions: */
|
|
/* */
|
|
/* Line( TPoint p1, TPoint p2 ); */
|
|
/* */
|
|
/* Creates a line between the points p1 and p2. */
|
|
/* */
|
|
/* void ImplementDraw( TDC& ); */
|
|
/* */
|
|
/* Draws the line. */
|
|
/* */
|
|
/* virtual void DoDraw( TDC& ); */
|
|
/* */
|
|
/* Overrides GraphicalObject::DoDraw and draws the line by */
|
|
/* calling ImplementDraw(). */
|
|
/* */
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
class Line : public virtual GraphicalObject
|
|
{
|
|
|
|
public:
|
|
|
|
Line( TPoint p1, TPoint p2 );
|
|
|
|
protected:
|
|
|
|
void ImplementDraw( TDC& );
|
|
|
|
private:
|
|
|
|
virtual void DoDraw( TDC& );
|
|
|
|
DECLARE_STREAMABLE_FROM_BASE( , Line, GraphicalObject );
|
|
|
|
};
|
|
|
|
inline Line::Line( TPoint p1, TPoint p2 ) : GraphicalObject( p1, p2 )
|
|
{
|
|
}
|
|
|
|
void Line::ImplementDraw( TDC& dc )
|
|
{
|
|
dc.MoveTo( bbox.left, bbox.top );
|
|
dc.LineTo( bbox.right, bbox.bottom );
|
|
}
|
|
|
|
void Line::DoDraw( TDC& dc )
|
|
{
|
|
ImplementDraw( dc );
|
|
}
|
|
|
|
IMPLEMENT_CASTABLE1( Line, GraphicalObject );
|
|
IMPLEMENT_STREAMABLE_FROM_BASE( Line, GraphicalObject );
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
/* */
|
|
/* class TRectangle */
|
|
/* */
|
|
/* class TRectangle draws a rectangle. */
|
|
/* */
|
|
/* Member functions: */
|
|
/* */
|
|
/* TRectangle( TPoint p1, TPoint p2 ); */
|
|
/* */
|
|
/* Creates a TRectangle whose upper left corner is at p1 */
|
|
/* and whose lower right corner is at p2. */
|
|
/* */
|
|
/* void ImplementDraw( TDC& ); */
|
|
/* */
|
|
/* Draws the rectangle. */
|
|
/* */
|
|
/* virtual void DoDraw( TDC& ); */
|
|
/* */
|
|
/* Overrides GraphicalObject::DoDraw and draws the rectangle by */
|
|
/* calling ImplementDraw(). */
|
|
/* */
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
class TRectangle : public virtual GraphicalObject
|
|
{
|
|
|
|
public:
|
|
|
|
TRectangle( TPoint p1, TPoint p2 );
|
|
|
|
protected:
|
|
|
|
void ImplementDraw( TDC& );
|
|
|
|
private:
|
|
|
|
virtual void DoDraw( TDC& );
|
|
|
|
DECLARE_STREAMABLE_FROM_BASE( , TRectangle, GraphicalObject );
|
|
|
|
};
|
|
|
|
inline TRectangle::TRectangle( TPoint p1, TPoint p2 ) :
|
|
GraphicalObject( p1, p2 )
|
|
{
|
|
}
|
|
|
|
void TRectangle::ImplementDraw( TDC& dc )
|
|
{
|
|
dc.Rectangle( bbox );
|
|
}
|
|
|
|
void TRectangle::DoDraw( TDC& dc )
|
|
{
|
|
ImplementDraw( dc );
|
|
}
|
|
|
|
IMPLEMENT_CASTABLE1( TRectangle, GraphicalObject );
|
|
IMPLEMENT_STREAMABLE_FROM_BASE( TRectangle, GraphicalObject );
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
/* */
|
|
/* class TEllipse */
|
|
/* */
|
|
/* class TEllipse draws an ellipse. */
|
|
/* */
|
|
/* Member functions: */
|
|
/* */
|
|
/* TEllipse( TPoint p1, TPoint p2 ); */
|
|
/* */
|
|
/* Creates a TEllipse whose bounding box is defined by p1 and p2 */
|
|
/* */
|
|
/* void ImplementDraw( TDC& ); */
|
|
/* */
|
|
/* Draws the ellipse. */
|
|
/* */
|
|
/* virtual void DoDraw( TDC& ); */
|
|
/* */
|
|
/* Overrides GraphicalObject::DoDraw and draws the ellipse by */
|
|
/* calling ImplementDraw(). */
|
|
/* */
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
class TEllipse : public virtual GraphicalObject
|
|
{
|
|
|
|
public:
|
|
|
|
TEllipse( TPoint p1, TPoint p2 );
|
|
|
|
protected:
|
|
|
|
void ImplementDraw( TDC& );
|
|
|
|
private:
|
|
|
|
virtual void DoDraw( TDC& );
|
|
|
|
DECLARE_STREAMABLE_FROM_BASE( , TEllipse, GraphicalObject );
|
|
|
|
};
|
|
|
|
TEllipse::TEllipse( TPoint p1, TPoint p2 ) :
|
|
GraphicalObject( p1, p2 )
|
|
{
|
|
}
|
|
|
|
void TEllipse::ImplementDraw( TDC& dc )
|
|
{
|
|
dc.Ellipse( bbox );
|
|
}
|
|
|
|
void TEllipse::DoDraw( TDC& dc )
|
|
{
|
|
ImplementDraw( dc );
|
|
}
|
|
|
|
IMPLEMENT_CASTABLE1( TEllipse, GraphicalObject );
|
|
IMPLEMENT_STREAMABLE_FROM_BASE( TEllipse, GraphicalObject );
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
/* */
|
|
/* class Caption */
|
|
/* */
|
|
/* class Caption draws its text on the screen. */
|
|
/* Note that Caption is an abstract class. It */
|
|
/* must have a bounding box, but it does not */
|
|
/* have a constructor that takes any coordinates. */
|
|
/* Each class derived from Caption will provide */
|
|
/* a bounding box in the virtual base GraphicalObject. */
|
|
/* */
|
|
/* Type definitions: */
|
|
/* */
|
|
/* TextLoc */
|
|
/* */
|
|
/* An enum used to specify how y-coordinate values */
|
|
/* should be interpreted when displaying text. */
|
|
/* */
|
|
/* Member functions: */
|
|
/* */
|
|
/* Caption( const string& txt, TextLoc where ); */
|
|
/* */
|
|
/* Creates a Caption with the specified text, */
|
|
/* which will be drawn in its bounding box */
|
|
/* at the top, center, or bottom, depending */
|
|
/* on the value of its argument 'where'. */
|
|
/* */
|
|
/* virtual void ImplementDraw( TDC& ); */
|
|
/* */
|
|
/* Draws the caption. */
|
|
/* */
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
class Caption : public virtual GraphicalObject
|
|
{
|
|
|
|
public:
|
|
|
|
enum TextLoc{ T_TOP, T_CENTER, T_BOTTOM };
|
|
|
|
Caption( const string& txt, TextLoc where );
|
|
|
|
protected:
|
|
|
|
void ImplementDraw( TDC& );
|
|
|
|
private:
|
|
|
|
string Text;
|
|
TextLoc Where;
|
|
|
|
DECLARE_ABSTRACT_STREAMABLE( , Caption, 1 );
|
|
|
|
};
|
|
|
|
Caption::Caption( const string& text, TextLoc where ) :
|
|
Text( text ), Where(where)
|
|
{
|
|
}
|
|
|
|
#pragma warn -def
|
|
void Caption::ImplementDraw( TDC& dc )
|
|
{
|
|
TEXTMETRIC tm;
|
|
dc.GetTextMetrics(tm);
|
|
int textHeight = tm.tmHeight+tm.tmExternalLeading;
|
|
|
|
int yDelta;
|
|
switch( Where )
|
|
{
|
|
case T_TOP:
|
|
yDelta = textHeight/2;
|
|
break;
|
|
case T_CENTER:
|
|
yDelta = (bbox.Height()-textHeight)/2;
|
|
break;
|
|
case T_BOTTOM:
|
|
yDelta = bbox.Height()-3*textHeight/2;
|
|
break;
|
|
}
|
|
dc.TextOut( bbox.left+bbox.Width()/2,
|
|
bbox.top+yDelta,
|
|
Text.c_str(), Text.length() );
|
|
}
|
|
#pragma warn .def
|
|
|
|
IMPLEMENT_CASTABLE1( Caption, GraphicalObject );
|
|
IMPLEMENT_ABSTRACT_STREAMABLE1( Caption, GraphicalObject );
|
|
|
|
void *Caption::Streamer::Read( ipstream& in, uint32 ) const
|
|
{
|
|
ReadVirtualBase( STATIC_CAST(GraphicalObject *,GetObject()), in );
|
|
int temp;
|
|
in >> GetObject()->Text >> temp;
|
|
GetObject()->Where = TextLoc(temp);
|
|
return GetObject();
|
|
}
|
|
|
|
void Caption::Streamer::Write( opstream& out ) const
|
|
{
|
|
WriteVirtualBase( STATIC_CAST(GraphicalObject *,GetObject()), out );
|
|
out << GetObject()->Text << int(GetObject()->Where);
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
/* */
|
|
/* class CaptionedRectangle */
|
|
/* */
|
|
/* class CaptionedRectangle draws a rectangle on the */
|
|
/* screen, with a caption horizontally centered at the */
|
|
/* top, in the center, or at the bottom. */
|
|
/* */
|
|
/* Member functions: */
|
|
/* */
|
|
/* CaptionedRectangle( TPoint p1, TPoint p2, */
|
|
/* const string& txt, */
|
|
/* TextLoc loc = T_TOP ) */
|
|
/* */
|
|
/* Creates a CaptionedRectangle with the specified */
|
|
/* location, size, and text. */
|
|
/* */
|
|
/* void ImplementDraw( TDC& ); */
|
|
/* */
|
|
/* Draws the rectangle and its text. */
|
|
/* */
|
|
/* virtual void DoDraw( TDC& ); */
|
|
/* */
|
|
/* Overrides GraphicalObject::DoDraw and draws the rectangle by */
|
|
/* calling ImplementDraw(). */
|
|
/* */
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
class CaptionedRectangle : public TRectangle, public Caption
|
|
{
|
|
|
|
public:
|
|
|
|
CaptionedRectangle( TPoint p1, TPoint p2,
|
|
const string& txt,
|
|
TextLoc loc = T_TOP );
|
|
|
|
protected:
|
|
|
|
void ImplementDraw( TDC& );
|
|
|
|
private:
|
|
|
|
virtual void DoDraw( TDC& );
|
|
|
|
DECLARE_STREAMABLE( , CaptionedRectangle, 1 );
|
|
|
|
};
|
|
|
|
CaptionedRectangle::CaptionedRectangle( TPoint p1, TPoint p2,
|
|
const string& txt,
|
|
TextLoc loc ) :
|
|
GraphicalObject( p1, p2 ),
|
|
TRectangle( p1, p2 ),
|
|
Caption( txt, loc )
|
|
{
|
|
}
|
|
|
|
void CaptionedRectangle::ImplementDraw( TDC& dc )
|
|
{
|
|
TRectangle::ImplementDraw( dc );
|
|
Caption::ImplementDraw( dc );
|
|
}
|
|
|
|
void CaptionedRectangle::DoDraw( TDC& dc )
|
|
{
|
|
ImplementDraw( dc );
|
|
}
|
|
|
|
IMPLEMENT_CASTABLE2( CaptionedRectangle, TRectangle, Caption );
|
|
IMPLEMENT_STREAMABLE3( CaptionedRectangle, TRectangle, Caption, GraphicalObject );
|
|
|
|
void *CaptionedRectangle::Streamer::Read( ipstream& in, uint32 ) const
|
|
{
|
|
ReadBaseObject( STATIC_CAST(TRectangle *,GetObject()), in );
|
|
ReadBaseObject( STATIC_CAST(Caption *,GetObject()), in );
|
|
return GetObject();
|
|
}
|
|
|
|
void CaptionedRectangle::Streamer::Write( opstream& out ) const
|
|
{
|
|
WriteBaseObject( STATIC_CAST(TRectangle *,GetObject()), out );
|
|
WriteBaseObject( STATIC_CAST(Caption *,GetObject()), out );
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
/* */
|
|
/* class CaptionedEllipse */
|
|
/* */
|
|
/* class CaptionedEllipse draws an ellipse on the */
|
|
/* screen, with a caption centered in the ellipse. */
|
|
/* */
|
|
/* Member functions: */
|
|
/* */
|
|
/* CaptionedEllipse( TPoint p1, TPoint p2, */
|
|
/* const string& txt ) */
|
|
/* */
|
|
/* Creates a CaptionedEllipse with the specified */
|
|
/* bounding box and text. */
|
|
/* */
|
|
/* void ImplementDraw( TDC& ); */
|
|
/* */
|
|
/* Draws the ellipse and its text. */
|
|
/* */
|
|
/* virtual void DoDraw( TDC& ); */
|
|
/* */
|
|
/* Overrides GraphicalObject::DoDraw and draws the ellipse by */
|
|
/* calling ImplementDraw(). */
|
|
/* */
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
class CaptionedEllipse : public TEllipse, public Caption
|
|
{
|
|
|
|
public:
|
|
|
|
CaptionedEllipse( TPoint p1, TPoint p2, const string& txt );
|
|
|
|
protected:
|
|
|
|
void ImplementDraw( TDC& );
|
|
|
|
private:
|
|
|
|
virtual void DoDraw( TDC& );
|
|
|
|
DECLARE_STREAMABLE( , CaptionedEllipse, 1 );
|
|
|
|
};
|
|
|
|
CaptionedEllipse::CaptionedEllipse( TPoint p1, TPoint p2, const string& txt ) :
|
|
GraphicalObject( p1, p2 ),
|
|
TEllipse( p1, p2 ),
|
|
Caption( txt, T_CENTER )
|
|
{
|
|
}
|
|
|
|
void CaptionedEllipse::ImplementDraw( TDC& dc )
|
|
{
|
|
TEllipse::ImplementDraw( dc );
|
|
Caption::ImplementDraw( dc );
|
|
}
|
|
|
|
void CaptionedEllipse::DoDraw( TDC& dc )
|
|
{
|
|
ImplementDraw( dc );
|
|
}
|
|
|
|
IMPLEMENT_CASTABLE2( CaptionedEllipse, TEllipse, Caption );
|
|
IMPLEMENT_STREAMABLE3( CaptionedEllipse, TEllipse, Caption, GraphicalObject );
|
|
|
|
void *CaptionedEllipse::Streamer::Read( ipstream& in, uint32 ) const
|
|
{
|
|
ReadBaseObject( STATIC_CAST(TEllipse *,GetObject()), in );
|
|
ReadBaseObject( STATIC_CAST(Caption *,GetObject()), in );
|
|
return GetObject();
|
|
}
|
|
|
|
void CaptionedEllipse::Streamer::Write( opstream& out ) const
|
|
{
|
|
WriteBaseObject( STATIC_CAST(TEllipse *,GetObject()), out );
|
|
WriteBaseObject( STATIC_CAST(Caption *,GetObject()), out );
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
/* */
|
|
/* class TFilledRectangle */
|
|
/* */
|
|
/* class TFilledRectangle draws a black rectangle on the screen. */
|
|
/* */
|
|
/* Member functions: */
|
|
/* */
|
|
/* TFilledRectangle( TPoint p1, TPoint p2 ); */
|
|
/* */
|
|
/* Creates a TFilledRectangle whose upper left corner is at p1 */
|
|
/* and whose lower right corner is at p2. */
|
|
/* */
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
class TFilledRectangle : public TRectangle
|
|
{
|
|
|
|
public:
|
|
|
|
TFilledRectangle::TFilledRectangle( TPoint p1, TPoint p2 );
|
|
|
|
DECLARE_STREAMABLE_FROM_BASE( , TFilledRectangle, TRectangle );
|
|
};
|
|
|
|
TFilledRectangle::TFilledRectangle( TPoint p1, TPoint p2 ) :
|
|
TRectangle( p1, p2 ), GraphicalObject( p1, p2 )
|
|
{
|
|
SetFill();
|
|
}
|
|
|
|
IMPLEMENT_CASTABLE1( TFilledRectangle, TRectangle );
|
|
IMPLEMENT_STREAMABLE_FROM_BASE( TFilledRectangle, TRectangle );
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
/* */
|
|
/* class TFilledEllipse */
|
|
/* */
|
|
/* class TFilledEllipse draws a black ellipse on the screen. */
|
|
/* */
|
|
/* Member functions: */
|
|
/* */
|
|
/* TFilledEllipse( TPoint p1, TPoint p2 ); */
|
|
/* */
|
|
/* Creates a TFilledEllipse whose bounding box is defined by */
|
|
/* p1 and p2 */
|
|
/* */
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
class TFilledEllipse : public TEllipse
|
|
{
|
|
|
|
public:
|
|
|
|
TFilledEllipse::TFilledEllipse( TPoint p1, TPoint p2 );
|
|
|
|
DECLARE_STREAMABLE_FROM_BASE( , TFilledEllipse, TEllipse );
|
|
};
|
|
|
|
TFilledEllipse::TFilledEllipse( TPoint p1, TPoint p2 ) :
|
|
TEllipse( p1, p2 ), GraphicalObject( p1, p2 )
|
|
{
|
|
SetFill();
|
|
}
|
|
|
|
IMPLEMENT_CASTABLE1( TFilledEllipse, TEllipse );
|
|
IMPLEMENT_STREAMABLE_FROM_BASE( TFilledEllipse, TEllipse );
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
/* */
|
|
/* class TObjectBuilder */
|
|
/* */
|
|
/* class TObjectBuilder provides the core functionality for */
|
|
/* building objects derived from GraphicalObject in a Windows */
|
|
/* environment. It handles changing the cursor to one that */
|
|
/* indicates the type of object being built, clipping the cursor */
|
|
/* so that it stays within the application's client area, */
|
|
/* handles anchoring the object's bounding box and dragging the */
|
|
/* unanchored corner of the bounding box. */
|
|
/* */
|
|
/* Public member functions: */
|
|
/* */
|
|
/* TObjectBuilder( TWindow& owner, int cursorId ); */
|
|
/* */
|
|
/* Clips the cursor so that it stays within the owner's */
|
|
/* client area and replaces the default cursor with the */
|
|
/* cursor contained in the resource identified by cursorId. */
|
|
/* */
|
|
/* ~TObjectBuilder(); */
|
|
/* */
|
|
/* Restores the default cursor and ends the clipping. */
|
|
/* */
|
|
/* */
|
|
/* void SetAnchor( TPoint pos ); */
|
|
/* */
|
|
/* Sets the anchor point of the bounding box to the point pos. */
|
|
/* */
|
|
/* void Drag( TPoint pos ); */
|
|
/* */
|
|
/* Moves the unanchored corner of the bounding box to the */
|
|
/* point pos, drawing the object's skeleton as appropriate. */
|
|
/* See DrawSkeleton(). */
|
|
/* */
|
|
/* GraphicalObject *CreateObject(); */
|
|
/* */
|
|
/* Returns a pointer to the newly created object derived */
|
|
/* from GraphicalObject and contained within the bounding box */
|
|
/* delimited by the anchor point and the unanchored corner as */
|
|
/* set up by SetAnchor() and Drag() and cleans up whatever */
|
|
/* needs to be cleaned up. See BuildObject(). */
|
|
/* */
|
|
/* void Cancel() */
|
|
/* */
|
|
/* Cleans up whatever needs to be cleaned up when the object is */
|
|
/* not wanted. */
|
|
/* */
|
|
/* Protected member functions: */
|
|
/* */
|
|
/* const TWindow& GetOwner() const; */
|
|
/* */
|
|
/* Returns a reference to the TWindow that owns the client */
|
|
/* area that we're drawing to. */
|
|
/* */
|
|
/* Virtual functions: */
|
|
/* */
|
|
/* void DrawSkeleton( TDC& dc, TPoint p1, TPoint p2 ) const = 0; */
|
|
/* */
|
|
/* This must be overridden by the derived class. It is called */
|
|
/* from Drag() to erase the previously drawn skeleton which */
|
|
/* was drawn at p1 and p2, and it is called again to draw the */
|
|
/* new skeleton at positions p1 and p2. The skeleton should be */
|
|
/* some sort of simple line representation of the object being */
|
|
/* built. */
|
|
/* */
|
|
/* GraphicalObject *BuildObject( TPoint p1, TPoint p2 ) = 0; */
|
|
/* */
|
|
/* Called from CreateObject() to actually build the desired */
|
|
/* object, with its bounding box defined by p1 and p2. Typically */
|
|
/* this just calls a constructor for the desired object. */
|
|
/* */
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
class TObjectBuilder
|
|
{
|
|
|
|
public:
|
|
|
|
TObjectBuilder( TWindow& owner, int cursorId );
|
|
virtual ~TObjectBuilder();
|
|
|
|
void SetAnchor( TPoint pos );
|
|
void Drag( TPoint pos );
|
|
GraphicalObject *CreateObject();
|
|
void Cancel() const;
|
|
|
|
protected:
|
|
|
|
const TWindow& GetOwner() const { return Owner; }
|
|
|
|
|
|
private:
|
|
|
|
class BuilderDC : public TClientDC
|
|
{
|
|
public:
|
|
BuilderDC( HWND wnd );
|
|
~BuilderDC();
|
|
};
|
|
|
|
virtual void DrawSkeleton( TDC& dc, TPoint p1, TPoint p2 ) const = 0;
|
|
virtual GraphicalObject *BuildObject( TPoint p1, TPoint p2 ) = 0;
|
|
|
|
TPoint Anchor;
|
|
TPoint Current;
|
|
int Anchored;
|
|
|
|
HCURSOR OldCursor;
|
|
TWindow& Owner;
|
|
|
|
TObjectBuilder( const TObjectBuilder& );
|
|
const TObjectBuilder& operator = ( const TObjectBuilder& );
|
|
|
|
};
|
|
|
|
TObjectBuilder::TObjectBuilder( TWindow& owner, int cursorId ) :
|
|
Owner(owner),
|
|
Anchored(0)
|
|
{
|
|
TRect Rect;
|
|
Owner.GetWindowRect( Rect );
|
|
ClipCursor( &Rect );
|
|
Owner.SetCursor( Owner.GetApplication(), cursorId );
|
|
}
|
|
|
|
TObjectBuilder::~TObjectBuilder()
|
|
{
|
|
Owner.SetCursor( 0, IDC_ARROW );
|
|
ClipCursor(0);
|
|
}
|
|
|
|
void TObjectBuilder::SetAnchor( TPoint point )
|
|
{
|
|
Anchor = Current = point;
|
|
BuilderDC dc( Owner );
|
|
DrawSkeleton( dc, Anchor, Current );
|
|
Anchored = 1;
|
|
}
|
|
|
|
void TObjectBuilder::Drag( TPoint point )
|
|
{
|
|
if( Anchored )
|
|
{
|
|
BuilderDC dc( Owner );
|
|
DrawSkeleton( dc, Anchor, Current );
|
|
Current = point;
|
|
DrawSkeleton( dc, Anchor, Current );
|
|
}
|
|
}
|
|
|
|
GraphicalObject *TObjectBuilder::CreateObject()
|
|
{
|
|
return BuildObject( Anchor, Current );
|
|
}
|
|
|
|
void TObjectBuilder::Cancel() const
|
|
{
|
|
if( Anchored )
|
|
{
|
|
BuilderDC dc( Owner );
|
|
DrawSkeleton( dc, Anchor, Current );
|
|
}
|
|
}
|
|
|
|
TObjectBuilder::BuilderDC::BuilderDC( HWND wnd ) : TClientDC( wnd )
|
|
{
|
|
SelectStockObject(WHITE_PEN);
|
|
SetROP2( R2_XORPEN );
|
|
SelectStockObject(NULL_BRUSH);
|
|
}
|
|
|
|
TObjectBuilder::BuilderDC::~BuilderDC()
|
|
{
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
/* */
|
|
/* class LineBuilder */
|
|
/* */
|
|
/* class LineBuilder builds a Line object using the mechanisms */
|
|
/* provided by TObjectBuilder. */
|
|
/* */
|
|
/* Member functions: */
|
|
/* */
|
|
/* LineBuilder( TWindow& owner ); */
|
|
/* */
|
|
/* Initializes a LineBuilder that will draw its skeleton inside */
|
|
/* the client area of owner. */
|
|
/* */
|
|
/* void DrawSkeleton( TDC& dc, TPoint p1, TPoint p2 ) const; */
|
|
/* */
|
|
/* Overrides TObjectBuilder::DrawSkeleton to draw the skeleton */
|
|
/* for a line, which is just a line from p1 to p2. */
|
|
/* */
|
|
/* GraphicalObject *BuildObject( TPoint p1, TPoint p2 ); */
|
|
/* */
|
|
/* Overrides TObjectBuilder::BuildObject to build a Line */
|
|
/* object with its endpoints at p1 and p2. */
|
|
/* */
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
class LineBuilder : public TObjectBuilder
|
|
{
|
|
|
|
public:
|
|
|
|
LineBuilder( TWindow& owner );
|
|
|
|
private:
|
|
|
|
virtual void DrawSkeleton( TDC& dc, TPoint p1, TPoint p2 ) const;
|
|
virtual GraphicalObject *BuildObject( TPoint p1, TPoint p2 );
|
|
|
|
};
|
|
|
|
LineBuilder::LineBuilder( TWindow& owner ) :
|
|
TObjectBuilder( owner, LINE_CURSOR )
|
|
{
|
|
}
|
|
|
|
void LineBuilder::DrawSkeleton( TDC& dc, TPoint p1, TPoint p2 ) const
|
|
{
|
|
dc.MoveTo( p1.x, p1.y );
|
|
dc.LineTo( p2.x, p2.y );
|
|
}
|
|
|
|
GraphicalObject *LineBuilder::BuildObject( TPoint p1, TPoint p2 )
|
|
{
|
|
return new Line( p1, p2 );
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
/* */
|
|
/* class RectangleBuilder */
|
|
/* */
|
|
/* class RectangleBuilder builds a TRectangle object using the */
|
|
/* mechanisms provided by TObjectBuilder. */
|
|
/* */
|
|
/* Member functions: */
|
|
/* */
|
|
/* RectangleBuilder( TWindow& owner ); */
|
|
/* */
|
|
/* Initializes a RectangleBuilder that will draw its skeleton */
|
|
/* inside the client area of owner. */
|
|
/* */
|
|
/* void DrawSkeleton( TDC& dc, TPoint p1, TPoint p2 ) const; */
|
|
/* */
|
|
/* Overrides TObjectBuilder::DrawSkeleton to draw the skeleton */
|
|
/* for a TRectangle, which is a rectangle whose upper left */
|
|
/* corner is at p1 and whose lower right corner is at p2. */
|
|
/* */
|
|
/* GraphicalObject *BuildObject( TPoint p1, TPoint p2 ); */
|
|
/* */
|
|
/* Overrides TObjectBuilder::BuildObject to build a TRectangle */
|
|
/* object with its upper left corner at p1 and its lower right */
|
|
/* corner at p2. */
|
|
/* */
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
class RectangleBuilder : public TObjectBuilder
|
|
{
|
|
|
|
public:
|
|
|
|
RectangleBuilder( TWindow& owner );
|
|
|
|
private:
|
|
|
|
virtual void DrawSkeleton( TDC& dc, TPoint p1, TPoint p2 ) const;
|
|
virtual GraphicalObject *BuildObject( TPoint p1, TPoint p2 );
|
|
|
|
};
|
|
|
|
RectangleBuilder::RectangleBuilder( TWindow& owner ) :
|
|
TObjectBuilder( owner, RECT_CURSOR )
|
|
{
|
|
}
|
|
|
|
void RectangleBuilder::DrawSkeleton( TDC& dc, TPoint p1, TPoint p2 ) const
|
|
{
|
|
dc.Rectangle( p1, p2 );
|
|
}
|
|
|
|
GraphicalObject *RectangleBuilder::BuildObject( TPoint p1, TPoint p2 )
|
|
{
|
|
return new TRectangle( p1, p2 );
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
/* */
|
|
/* class EllipseBuilder */
|
|
/* */
|
|
/* class EllipseBuilder builds a TEllipse object using the */
|
|
/* mechanisms provided by TObjectBuilder. */
|
|
/* */
|
|
/* Member functions: */
|
|
/* */
|
|
/* EllipseBuilder( TWindow& owner ); */
|
|
/* */
|
|
/* Initializes an EllipseBuilder that will draw its skeleton */
|
|
/* inside the client area of owner. */
|
|
/* */
|
|
/* void DrawSkeleton( TDC& dc, TPoint p1, TPoint p2 ) const; */
|
|
/* */
|
|
/* Overrides TObjectBuilder::DrawSkeleton to draw the skeleton */
|
|
/* for a TEllipse, which is an ellipse with a bounding box whose */
|
|
/* upper left corner is at p1 and whose lower right corner is */
|
|
/* at p2. */
|
|
/* */
|
|
/* GraphicalObject *BuildObject( TPoint p1, TPoint p2 ); */
|
|
/* */
|
|
/* Overrides TObjectBuilder::BuildObject to build a TEllipse */
|
|
/* object with a bounding box whose upper left corner is at p1 */
|
|
/* and whose lower right corner is at p2. */
|
|
/* */
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
class EllipseBuilder : public TObjectBuilder
|
|
{
|
|
|
|
public:
|
|
|
|
EllipseBuilder( TWindow& owner );
|
|
|
|
private:
|
|
|
|
virtual void DrawSkeleton( TDC& dc, TPoint p1, TPoint p2 ) const;
|
|
virtual GraphicalObject *BuildObject( TPoint p1, TPoint p2 );
|
|
|
|
};
|
|
|
|
EllipseBuilder::EllipseBuilder( TWindow& owner ) :
|
|
TObjectBuilder( owner, ELLIPSE_CURSOR )
|
|
{
|
|
}
|
|
|
|
void EllipseBuilder::DrawSkeleton( TDC& dc, TPoint p1, TPoint p2 ) const
|
|
|
|
{
|
|
dc.Ellipse( p1, p2 );
|
|
}
|
|
|
|
GraphicalObject *EllipseBuilder::BuildObject( TPoint p1, TPoint p2 )
|
|
{
|
|
return new TEllipse( p1, p2 );
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
/* */
|
|
/* class CaptionBuilder */
|
|
/* */
|
|
/* class CaptionBuilder provides a base class for use by builders */
|
|
/* of captioned objects. It does not inherit from TObjectBuilder. */
|
|
/* It is expected that this class will be mixed in with a class */
|
|
/* that does inherit from TObjectBuilder. See, for example, */
|
|
/* CaptionedRectangleBuilder. */
|
|
/* */
|
|
/* Member functions: */
|
|
/* */
|
|
/* CaptionBuilder( TWindow& owner, int allowPosition ); */
|
|
/* */
|
|
/* Initializes a CaptionBuilder that will belong to the TWindow */
|
|
/* owner. allowPosition is a flag that indicates whether the */
|
|
/* user should be allowed to specify the placement of the */
|
|
/* caption. If allowPosition is non-zero, the dialog box that */
|
|
/* prompts for the caption also allows the user to specify */
|
|
/* whether the caption should be at the top, in the center, or */
|
|
/* at the bottom of the object. If allowPosition is 0 this */
|
|
/* part of the dialog box is grayed out. */
|
|
/* */
|
|
/* string GetCaption(); */
|
|
/* */
|
|
/* Retrieves the text of the caption specified by the user. If */
|
|
/* the user hasn't been asked for the caption yet GetCaption() */
|
|
/* puts up a dialog box requesting input from the user. */
|
|
/* */
|
|
/* Caption::TextLoc GetLocation(); */
|
|
/* */
|
|
/* Retrieves the location for the caption specified by the user. */
|
|
/* If the user hasn't been asked for the caption yet */
|
|
/* GetLocation() puts up a dialog box requesting input from the */
|
|
/* user. If allowPosition was 0 GetLocation() returns T_TOP. */
|
|
/* */
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
class CaptionBuilder
|
|
{
|
|
|
|
public:
|
|
|
|
CaptionBuilder( TWindow& owner, int allowPosition = 1 );
|
|
string GetCaption();
|
|
Caption::TextLoc GetLocation();
|
|
|
|
private:
|
|
|
|
void GetData();
|
|
int HaveData;
|
|
string Caption;
|
|
Caption::TextLoc Location;
|
|
TWindow& Owner;
|
|
int AllowPosition;
|
|
|
|
class CaptionDialog : public TDialog
|
|
{
|
|
public:
|
|
CaptionDialog( TWindow& parent, CaptionBuilder& builder );
|
|
BOOL CanClose();
|
|
void SetupWindow();
|
|
private:
|
|
void TopClicked();
|
|
void CenterClicked();
|
|
void BottomClicked();
|
|
CaptionBuilder& Builder;
|
|
DECLARE_RESPONSE_TABLE( CaptionDialog );
|
|
};
|
|
|
|
friend CaptionDialog;
|
|
|
|
};
|
|
|
|
CaptionBuilder::CaptionBuilder( TWindow& owner, int allowPosition ) :
|
|
HaveData(0),
|
|
Location(Caption::T_TOP),
|
|
Owner(owner),
|
|
AllowPosition(allowPosition)
|
|
{
|
|
}
|
|
|
|
void CaptionBuilder::GetData()
|
|
{
|
|
if( !HaveData )
|
|
{
|
|
CaptionDialog dialog( Owner, *this );
|
|
dialog.Execute();
|
|
HaveData = 1;
|
|
}
|
|
}
|
|
|
|
string CaptionBuilder::GetCaption()
|
|
{
|
|
GetData();
|
|
return Caption;
|
|
}
|
|
|
|
Caption::TextLoc CaptionBuilder::GetLocation()
|
|
{
|
|
GetData();
|
|
return Location;
|
|
}
|
|
|
|
DEFINE_RESPONSE_TABLE1( CaptionBuilder::CaptionDialog, TDialog )
|
|
EV_CHILD_NOTIFY( IDD_TOP, BN_CLICKED, TopClicked ),
|
|
EV_CHILD_NOTIFY( IDD_CENTER, BN_CLICKED, CenterClicked ),
|
|
EV_CHILD_NOTIFY( IDD_BOTTOM, BN_CLICKED, BottomClicked ),
|
|
END_RESPONSE_TABLE;
|
|
|
|
CaptionBuilder::CaptionDialog::CaptionDialog( TWindow& parent, CaptionBuilder& builder ) :
|
|
TDialog( &parent, "CaptionDlg" ),
|
|
Builder(builder)
|
|
{
|
|
}
|
|
|
|
void CaptionBuilder::CaptionDialog::SetupWindow()
|
|
{
|
|
if( Builder.AllowPosition )
|
|
SendDlgItemMessage( IDD_TOP, BM_SETCHECK, 1, 0L );
|
|
else
|
|
{
|
|
::EnableWindow( GetDlgItem( IDD_TOP ), 0 );
|
|
::EnableWindow( GetDlgItem( IDD_CENTER ), 0 );
|
|
::EnableWindow( GetDlgItem( IDD_BOTTOM ), 0 );
|
|
::EnableWindow( GetDlgItem( IDD_POSITIONBOX ), 0 );
|
|
}
|
|
}
|
|
|
|
BOOL CaptionBuilder::CaptionDialog::CanClose()
|
|
{
|
|
char buf[256];
|
|
GetDlgItemText( IDD_INPUTEDITBOX, buf, sizeof(buf) );
|
|
Builder.Caption = buf;
|
|
return TRUE;
|
|
}
|
|
|
|
void CaptionBuilder::CaptionDialog::TopClicked()
|
|
{
|
|
Builder.Location = Caption::T_TOP;
|
|
}
|
|
|
|
void CaptionBuilder::CaptionDialog::CenterClicked()
|
|
{
|
|
Builder.Location = Caption::T_CENTER;
|
|
}
|
|
|
|
void CaptionBuilder::CaptionDialog::BottomClicked()
|
|
{
|
|
Builder.Location = Caption::T_BOTTOM;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
/* */
|
|
/* class CaptionedRectangleBuilder */
|
|
/* */
|
|
/* class CaptionedRectangleBuilder builds a CaptionedRectangle */
|
|
/* object using the mechanisms provided by TObjectBuilder. */
|
|
/* */
|
|
/* Member functions: */
|
|
/* */
|
|
/* CaptionedRectangleBuilder( TWindow& owner ); */
|
|
/* */
|
|
/* Initializes a CaptionedRectangleBuilder that will draw its */
|
|
/* skeleton inside the client area of owner and prompt for the */
|
|
/* caption after the bounding box has been defined. */
|
|
/* */
|
|
/* void DrawSkeleton( TDC& dc, TPoint p1, TPoint p2 ) const; */
|
|
/* */
|
|
/* Overrides TObjectBuilder::DrawSkeleton to draw the skeleton */
|
|
/* for a CaptionedRectangle, which is a rectangle whose upper */
|
|
/* left corner is at p1 and whose lower right corner is at p2. */
|
|
/* */
|
|
/* GraphicalObject *BuildObject( TPoint p1, TPoint p2 ); */
|
|
/* */
|
|
/* Overrides TObjectBuilder::BuildObject to build a */
|
|
/* CaptionedRectangle object with its upper left corner at p1 */
|
|
/* and its lower right corner at p2. */
|
|
/* */
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
class CaptionedRectangleBuilder : public RectangleBuilder, private CaptionBuilder
|
|
{
|
|
|
|
public:
|
|
|
|
CaptionedRectangleBuilder( TWindow& owner );
|
|
|
|
private:
|
|
|
|
virtual GraphicalObject *BuildObject( TPoint p1, TPoint p2 );
|
|
|
|
};
|
|
|
|
CaptionedRectangleBuilder::CaptionedRectangleBuilder( TWindow& owner ) :
|
|
RectangleBuilder( owner ),
|
|
CaptionBuilder( owner )
|
|
{
|
|
}
|
|
|
|
GraphicalObject *CaptionedRectangleBuilder::BuildObject( TPoint p1, TPoint p2 )
|
|
{
|
|
return new CaptionedRectangle( p1, p2, GetCaption(), GetLocation() );
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
/* */
|
|
/* class CaptionedEllipseBuilder */
|
|
/* */
|
|
/* class CaptionedEllipseBuilder builds a CaptionedEllipse */
|
|
/* object using the mechanisms provided by TObjectBuilder. */
|
|
/* */
|
|
/* Member functions: */
|
|
/* */
|
|
/* CaptionedEllipseBuilder( TWindow& owner ); */
|
|
/* */
|
|
/* Initializes a CaptionedRectangleBuilder that will draw its */
|
|
/* skeleton inside the client area of owner and prompt for the */
|
|
/* caption after the bounding box has been defined. */
|
|
/* */
|
|
/* void DrawSkeleton( TDC& dc, TPoint p1, TPoint p2 ) const; */
|
|
/* */
|
|
/* Overrides TObjectBuilder::DrawSkeleton to draw the skeleton */
|
|
/* for a CaptionedEllipse, which is an ellipse with a bounding */
|
|
/* box whose upper left corner is at p1 and whose lower right */
|
|
/* corner is at p2. */
|
|
/* */
|
|
/* GraphicalObject *BuildObject( TPoint p1, TPoint p2 ); */
|
|
/* */
|
|
/* Overrides TObjectBuilder::BuildObject to build a */
|
|
/* CaptionedEllipse object with a bounding box whose upper left */
|
|
/* corner is at p1 and whose lower right corner is at p2. */
|
|
/* */
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
class CaptionedEllipseBuilder : public EllipseBuilder, public CaptionBuilder
|
|
{
|
|
|
|
public:
|
|
|
|
CaptionedEllipseBuilder( TWindow& owner );
|
|
|
|
private:
|
|
|
|
virtual GraphicalObject *BuildObject( TPoint p1, TPoint p2 );
|
|
|
|
};
|
|
|
|
CaptionedEllipseBuilder::CaptionedEllipseBuilder( TWindow& owner ) :
|
|
EllipseBuilder( owner ),
|
|
CaptionBuilder( owner, 0 )
|
|
{
|
|
}
|
|
|
|
GraphicalObject *CaptionedEllipseBuilder::BuildObject( TPoint p1, TPoint p2 )
|
|
{
|
|
return new CaptionedEllipse( p1, p2, GetCaption() );
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
/* */
|
|
/* class FilledRectangleBuilder */
|
|
/* */
|
|
/* class FilledRectangleBuilder builds a TFilledRectangle object. */
|
|
/* */
|
|
/* Member functions: */
|
|
/* */
|
|
/* FilledRectangleBuilder( TWindow& owner ); */
|
|
/* */
|
|
/* Initializes a FilledRectangleBuilder. */
|
|
/* */
|
|
/* GraphicalObject *BuildObject( TPoint p1, TPoint p2 ); */
|
|
/* */
|
|
/* Overrides RectangleBuilder::BuildObject to build a */
|
|
/* TFilledRectangle object with its upper left corner at p1 and */
|
|
/* its lower right corner at p2. */
|
|
/* */
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
class FilledRectangleBuilder : public RectangleBuilder
|
|
{
|
|
|
|
public:
|
|
|
|
FilledRectangleBuilder( TWindow& owner );
|
|
|
|
private:
|
|
|
|
virtual GraphicalObject *BuildObject( TPoint p1, TPoint p2 );
|
|
|
|
};
|
|
|
|
FilledRectangleBuilder::FilledRectangleBuilder( TWindow& owner ) :
|
|
RectangleBuilder( owner )
|
|
{
|
|
}
|
|
|
|
GraphicalObject *FilledRectangleBuilder::BuildObject( TPoint p1, TPoint p2 )
|
|
{
|
|
return new TFilledRectangle( p1, p2 );
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
/* */
|
|
/* class FilledEllipseBuilder */
|
|
/* */
|
|
/* class FilledEllipseBuilder builds a TFilledEllipse object. */
|
|
/* */
|
|
/* Member functions: */
|
|
/* */
|
|
/* FilledEllipseBuilder( TWindow& owner ); */
|
|
/* */
|
|
/* Initializes a FilledEllipseBuilder. */
|
|
/* */
|
|
/* GraphicalObject *BuildObject( TPoint p1, TPoint p2 ); */
|
|
/* */
|
|
/* Overrides EllipseBuilder::BuildObject to build a */
|
|
/* TFilledEllipse object with its bounding box defined by */
|
|
/* p1 and p2. */
|
|
/* */
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
class FilledEllipseBuilder : public EllipseBuilder
|
|
{
|
|
|
|
public:
|
|
|
|
FilledEllipseBuilder( TWindow& owner );
|
|
|
|
private:
|
|
|
|
virtual GraphicalObject *BuildObject( TPoint p1, TPoint p2 );
|
|
|
|
};
|
|
|
|
FilledEllipseBuilder::FilledEllipseBuilder( TWindow& owner ) :
|
|
EllipseBuilder( owner )
|
|
{
|
|
}
|
|
|
|
GraphicalObject *FilledEllipseBuilder::BuildObject( TPoint p1, TPoint p2 )
|
|
{
|
|
return new TFilledEllipse( p1, p2 );
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
/* */
|
|
/* class TGraphWindow */
|
|
/* */
|
|
/* class TGraphWindow pulls all of the forgoing together into a */
|
|
/* rather limited shape editor. It uses a TISetAsVector to hold */
|
|
/* the various objects that are in the current drawing. */
|
|
/* */
|
|
/* Member functions: */
|
|
/* */
|
|
/* TGraphWindow(); */
|
|
/* */
|
|
/* Initializes the window. */
|
|
/* */
|
|
/* void Paint( TDC&, BOOL, TRect& ); */
|
|
/* */
|
|
/* Called whenever the window receives a WM_PAINT message. Draws */
|
|
/* the objects by calling each of their Draw() functions. */
|
|
/* */
|
|
/* void CmNew(); */
|
|
/* */
|
|
/* Called when the user selects File/New from the menu. Removes */
|
|
/* all objects from the current drawing. */
|
|
/* */
|
|
/* void CmLine(); */
|
|
/* */
|
|
/* Called when the user selects Edit/Line from the menu. Adds */
|
|
/* a line to the drawing. */
|
|
/* */
|
|
/* void CmRectangle(); */
|
|
/* */
|
|
/* Called when the user selects Edit/Rectangle from the menu. */
|
|
/* Adds a rectangle to the drawing. */
|
|
/* */
|
|
/* void CmCaptionedRectangle(); */
|
|
/* */
|
|
/* Called when the user selects Edit/CaptionedRectangle from the */
|
|
/* menu. Adds a captioned rectangle to the drawing. */
|
|
/* */
|
|
/* void CmEllipse(); */
|
|
/* */
|
|
/* Called when the user selects Edit/Ellipse from the menu. */
|
|
/* Adds an ellipse to the drawing. */
|
|
/* */
|
|
/* void CmCaptionedEllipse(); */
|
|
/* */
|
|
/* Called when the user selects Edit/CaptionedEllipse from the */
|
|
/* menu. Adds a captioned ellipse to the drawing. */
|
|
/* */
|
|
/* void CmAbout(); */
|
|
/* */
|
|
/* Called when the user selects Help/About from the menu. */
|
|
/* Displays the About box. */
|
|
/* */
|
|
/* void EvLButtonDown(); */
|
|
/* */
|
|
/* Called when the user presses the left mouse button. During */
|
|
/* building of an object, this anchors the object's bounding */
|
|
/* box at the current position of the mouse. */
|
|
/* */
|
|
/* void EvLButtonUp(); */
|
|
/* */
|
|
/* Called when the user releases the left mouse button. During */
|
|
/* building of an object, this creates the actual object with */
|
|
/* its bounding box defined by the previous anchor position and */
|
|
/* the current position of the mouse. */
|
|
/* */
|
|
/* void EvRButtonDown(); */
|
|
/* */
|
|
/* Called when the user presses the right mouse button. During */
|
|
/* building of an object, this terminates building. */
|
|
/* */
|
|
/* void EvMouseMove(); */
|
|
/* */
|
|
/* Called when the user moves the mouse. During building of an */
|
|
/* object, if the object's bounding box has been anchored, this */
|
|
/* drags the free corner of the bounding box. */
|
|
/* */
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
class TGraphWindow : public TWindow
|
|
{
|
|
|
|
public:
|
|
|
|
TGraphWindow();
|
|
|
|
void Paint(TDC&, BOOL, TRect&);
|
|
|
|
void CmNew();
|
|
void CmLine();
|
|
void CmRectangle();
|
|
void CmCaptionedRectangle();
|
|
void CmFilledRectangle(); // Changed
|
|
void CmEllipse();
|
|
void CmCaptionedEllipse();
|
|
void CmFilledEllipse(); // Changed
|
|
void CmAbout();
|
|
|
|
void CmFileOpen();
|
|
void CmFileSave();
|
|
void CmFileSaveAs();
|
|
|
|
void EvLButtonDown( UINT modKeys, TPoint& point );
|
|
void EvLButtonUp( UINT modKeys, TPoint& point );
|
|
void EvRButtonDown( UINT modKeys, TPoint& point );
|
|
void EvMouseMove( UINT modKeys, TPoint& point );
|
|
|
|
BOOL CanClose();
|
|
|
|
TOpenSaveDialog::TData FileData;
|
|
|
|
private:
|
|
|
|
int SaveFile();
|
|
int SaveFileAs();
|
|
void ReadObjects();
|
|
void WriteObjects();
|
|
int CheckAndClear();
|
|
int OkToClear();
|
|
static void WriteObject( GraphicalObject &obj, void * );
|
|
|
|
TObjectBuilder *Builder;
|
|
|
|
void FlushObjects();
|
|
void AddObject( GraphicalObject *obj );
|
|
static void DrawObject( GraphicalObject &obj, void * );
|
|
TISetAsVector<GraphicalObject> Objects;
|
|
|
|
int WindowIsDirty;
|
|
|
|
class GraphWindowDC
|
|
{
|
|
public:
|
|
GraphWindowDC( TDC& );
|
|
~GraphWindowDC();
|
|
operator TDC&() const;
|
|
private:
|
|
TDC& DC;
|
|
uint OldFlags;
|
|
TPen Pen;
|
|
};
|
|
|
|
DECLARE_RESPONSE_TABLE(TGraphWindow);
|
|
|
|
};
|
|
|
|
DEFINE_RESPONSE_TABLE1( TGraphWindow, TWindow )
|
|
EV_COMMAND( CM_FILENEW, CmNew ),
|
|
EV_COMMAND( CM_FILEOPEN, CmFileOpen ),
|
|
EV_COMMAND( CM_FILESAVE, CmFileSave ),
|
|
EV_COMMAND( CM_FILESAVEAS, CmFileSaveAs ),
|
|
EV_COMMAND( CM_EDITLINE, CmLine ),
|
|
EV_COMMAND( CM_EDITRECTANGLE, CmRectangle ),
|
|
EV_COMMAND( CM_EDITCAPTIONEDRECTANGLE, CmCaptionedRectangle ),
|
|
EV_COMMAND( CM_EDITFILLEDRECTANGLE, CmFilledRectangle ), // Changed
|
|
EV_COMMAND( CM_EDITELLIPSE, CmEllipse ),
|
|
EV_COMMAND( CM_EDITCAPTIONEDELLIPSE, CmCaptionedEllipse ),
|
|
EV_COMMAND( CM_EDITFILLEDELLIPSE, CmFilledEllipse ), // Changed
|
|
EV_COMMAND( CM_HELPABOUT, CmAbout ),
|
|
EV_WM_LBUTTONDOWN,
|
|
EV_WM_LBUTTONUP,
|
|
EV_WM_RBUTTONDOWN,
|
|
EV_WM_MOUSEMOVE,
|
|
END_RESPONSE_TABLE;
|
|
|
|
TGraphWindow::GraphWindowDC::GraphWindowDC( TDC& dc ) :
|
|
DC(dc),
|
|
Pen(::GetSysColor(COLOR_WINDOWTEXT))
|
|
{
|
|
OldFlags = DC.SetTextAlign( TA_CENTER );
|
|
DC.SelectObject( Pen );
|
|
DC.SetBkColor( ::GetSysColor( COLOR_WINDOW ) );
|
|
}
|
|
|
|
TGraphWindow::GraphWindowDC::~GraphWindowDC()
|
|
{
|
|
DC.RestorePen();
|
|
DC.SetTextAlign( OldFlags );
|
|
}
|
|
|
|
TGraphWindow::GraphWindowDC::operator TDC&() const
|
|
{
|
|
return DC;
|
|
}
|
|
|
|
TGraphWindow::TGraphWindow() :
|
|
TWindow( 0, 0, 0 ),
|
|
Builder(0),
|
|
FileData(OFN_FILEMUSTEXIST|OFN_HIDEREADONLY|OFN_PATHMUSTEXIST,
|
|
"Stream Files (*.stm)|*.stm|All Files (*.*)|*.*|",
|
|
0, "", "*"),
|
|
WindowIsDirty(0)
|
|
{
|
|
}
|
|
|
|
void TGraphWindow::DrawObject( GraphicalObject &obj, void *ptr )
|
|
{
|
|
obj.Draw( *(GraphWindowDC *)ptr );
|
|
}
|
|
|
|
void TGraphWindow::Paint( TDC& dc, BOOL, TRect& )
|
|
{
|
|
GraphWindowDC gdc(dc);
|
|
Objects.ForEach( DrawObject, &gdc );
|
|
}
|
|
|
|
void TGraphWindow::CmNew()
|
|
{
|
|
if( CheckAndClear() )
|
|
Invalidate();
|
|
}
|
|
|
|
void TGraphWindow::CmFileOpen()
|
|
{
|
|
if( CheckAndClear() )
|
|
{
|
|
*FileData.FileName = 0;
|
|
TFileOpenDialog dlg( this, FileData );
|
|
if( dlg.Execute() == IDOK )
|
|
{
|
|
ReadObjects();
|
|
Invalidate();
|
|
}
|
|
}
|
|
}
|
|
|
|
void TGraphWindow::CmFileSave()
|
|
{
|
|
SaveFile();
|
|
}
|
|
|
|
int TGraphWindow::SaveFile()
|
|
{
|
|
if( *FileData.FileName == '\0' )
|
|
return SaveFileAs();
|
|
else
|
|
{
|
|
WriteObjects();
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
void TGraphWindow::CmFileSaveAs()
|
|
{
|
|
SaveFileAs();
|
|
}
|
|
|
|
int TGraphWindow::SaveFileAs()
|
|
{
|
|
*FileData.FileName = '\0';
|
|
TFileSaveDialog dlg( this, FileData );
|
|
if( dlg.Execute() == IDOK )
|
|
{
|
|
WriteObjects();
|
|
return 1;
|
|
}
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
void TGraphWindow::ReadObjects()
|
|
{
|
|
ifpstream in( FileData.FileName );
|
|
int count;
|
|
in >> count;
|
|
while( count-- != 0 )
|
|
{
|
|
GraphicalObject *object;
|
|
in >> object;
|
|
AddObject( object );
|
|
}
|
|
WindowIsDirty = 0;
|
|
}
|
|
|
|
void TGraphWindow::WriteObject( GraphicalObject& obj, void *data )
|
|
{
|
|
*(ofpstream *)data << &obj;
|
|
}
|
|
|
|
void TGraphWindow::WriteObjects()
|
|
{
|
|
ofpstream out( FileData.FileName );
|
|
out << Objects.GetItemsInContainer();
|
|
Objects.ForEach( WriteObject, &out );
|
|
WindowIsDirty = 0;
|
|
}
|
|
|
|
int TGraphWindow::CheckAndClear()
|
|
{
|
|
if( OkToClear() )
|
|
{
|
|
FlushObjects();
|
|
return 1;
|
|
}
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
int TGraphWindow::OkToClear()
|
|
{
|
|
if( !WindowIsDirty )
|
|
return 1;
|
|
else
|
|
{
|
|
string msg;
|
|
if( *FileData.FileName == 0 )
|
|
msg = "<untitled>";
|
|
else
|
|
msg = FileData.FileName;
|
|
msg += " has not been saved. Save before closing?";
|
|
int res = MessageBox( msg.c_str(), GetApplication()->GetName(),
|
|
MB_ICONEXCLAMATION | MB_YESNOCANCEL );
|
|
switch( res )
|
|
{
|
|
case IDYES:
|
|
return SaveFile();
|
|
case IDNO:
|
|
return 1;
|
|
case IDCANCEL:
|
|
return 0;
|
|
}
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
void TGraphWindow::CmLine()
|
|
{
|
|
Builder = new LineBuilder( *this );
|
|
}
|
|
|
|
void TGraphWindow::CmRectangle()
|
|
{
|
|
Builder = new RectangleBuilder( *this );
|
|
}
|
|
|
|
void TGraphWindow::CmCaptionedRectangle()
|
|
{
|
|
Builder = new CaptionedRectangleBuilder( *this );
|
|
}
|
|
|
|
// Changed
|
|
void TGraphWindow::CmFilledRectangle()
|
|
{
|
|
Builder = new FilledRectangleBuilder( *this );
|
|
}
|
|
|
|
void TGraphWindow::CmEllipse()
|
|
{
|
|
Builder = new EllipseBuilder( *this );
|
|
}
|
|
|
|
void TGraphWindow::CmCaptionedEllipse()
|
|
{
|
|
Builder = new CaptionedEllipseBuilder( *this );
|
|
}
|
|
|
|
// Changed
|
|
void TGraphWindow::CmFilledEllipse()
|
|
{
|
|
Builder = new FilledEllipseBuilder( *this );
|
|
}
|
|
|
|
void TGraphWindow::CmAbout()
|
|
{
|
|
TDialog dlg( this, "About" );
|
|
dlg.Execute();
|
|
}
|
|
|
|
BOOL TGraphWindow::CanClose()
|
|
{
|
|
return CheckAndClear();
|
|
}
|
|
|
|
void TGraphWindow::AddObject( GraphicalObject *object )
|
|
{
|
|
Objects.Add( object );
|
|
WindowIsDirty = 1;
|
|
}
|
|
|
|
void TGraphWindow::FlushObjects()
|
|
{
|
|
Objects.Flush();
|
|
WindowIsDirty = 0;
|
|
}
|
|
|
|
void TGraphWindow::EvLButtonDown( UINT modKeys, TPoint& point )
|
|
{
|
|
if( Builder == 0 )
|
|
TWindow::EvLButtonDown( modKeys, point );
|
|
else
|
|
Builder->SetAnchor(point);
|
|
}
|
|
|
|
void TGraphWindow::EvLButtonUp( UINT modKeys, TPoint& point )
|
|
{
|
|
if( Builder == 0 )
|
|
TWindow::EvLButtonUp( modKeys, point );
|
|
else
|
|
{
|
|
AddObject( Builder->CreateObject() );
|
|
delete Builder;
|
|
Builder = 0;
|
|
Invalidate();
|
|
}
|
|
}
|
|
|
|
void TGraphWindow::EvRButtonDown( UINT modKeys, TPoint& point )
|
|
{
|
|
if( Builder == 0 )
|
|
TWindow::EvRButtonDown( modKeys, point );
|
|
else
|
|
{
|
|
Builder->Cancel();
|
|
delete Builder;
|
|
Builder = 0;
|
|
}
|
|
}
|
|
|
|
void TGraphWindow::EvMouseMove( UINT modKeys, TPoint& point )
|
|
{
|
|
if( Builder == 0 )
|
|
TWindow::EvMouseMove( modKeys, point );
|
|
else
|
|
Builder->Drag( point );
|
|
}
|
|
|
|
class TStreamApp : public TApplication
|
|
{
|
|
|
|
public:
|
|
|
|
TStreamApp() : TApplication() {}
|
|
|
|
void InitMainWindow();
|
|
|
|
};
|
|
|
|
void TStreamApp::InitMainWindow()
|
|
{
|
|
MainWindow = new TFrameWindow( 0, "Streaming Example, version 2",
|
|
new TGraphWindow );
|
|
MainWindow->AssignMenu("COMMANDS");
|
|
|
|
}
|
|
|
|
int OwlMain( int, char ** )
|
|
{
|
|
TStreamApp app;
|
|
return app.Run();
|
|
}
|
|
|
|
|