// @(#)Shape.h	3.8	7/28/92

#ifndef Shapes_First

#ifdef __GNUG__
#pragma interface
#endif

#define Shapes_First

#include "Command.h"
#include "Globals.h"
#include "View.h"
#include "StyledText.h"
#include "GeoPos.h"

extern Point HandleSize;
extern Point HandleSize2;
extern Point HandleSize3;
extern Point MinShapeSize;

enum ShapeProperties {
    eShapePattern,
    eShapePenPattern,
    eShapePensize,
    eShapeArrows,
    eShapeSmooth,
    eShapeAdjust,
    eShapeSpacing,
    eShapeTextSize,
    eShapeTextFont,
    eShapeTextFace
};


extern class Ink *InkPalette[];

int		NrInks();
class Ink	*GetInk(int i);
class Ink	*GetHlInk();

double deg2rad(double x);
double rad2deg(double x);
extern double Pi;


//---- DrawCommand -------------------------------------------------------------

class MapCommand : public Command {
    static GrCursor oldcursor;
protected:
    class MapView *mapview;
    bool moved;
    Point delta;
    
public:
    MetaDef(MapCommand);
    MapCommand(MapView *mv, int cmd= 0, char *cmdname= 0);

    Command *TrackMouse(TrackPhase, Point, Point, Point);
};

class DrawCommand : public MapCommand {
protected:
    class DrawView *view;
    class ObjList *saveselection, *saveselection2;

public:
    MetaDef(DrawCommand);
    DrawCommand(DrawView *dv, int cmd= 0, char *cmdname= 0);
    ~DrawCommand();

    void TrackConstrain(Point, Point, Point *);

    void DoIt();
    void RedoIt();
    void UndoIt();

    virtual void SaveDoIt();
    virtual void RestoreRedoIt();
    virtual void RestoreUndoIt();
};


//---- ShapeSketcher -----------------------------------------------------------

enum SketchModes { 
    eSMSquare       = BIT(0),
    eSMShowSizes    = BIT(1),
    eSMCenter       = BIT(2),
    eSMDefault      = 0
};

class ShapeSketcher: public DrawCommand {
    SketchModes mode;
protected:
    class Shape *proto, *newshape;
    
public:
    ShapeSketcher(DrawView*, class Shape *pro, SketchModes m= eSMDefault);
    void SaveDoIt();
    void RestoreRedoIt();
    void RestoreUndoIt();
    void TrackConstrain(Point, Point, Point *np);
    Command *TrackMouse(TrackPhase, Point, Point, Point);
    void TrackFeedback(Point, Point, bool);
};

//---- Shape -------------------------------------------------------------------

enum ShapeFlags {
    eShapeSplit    =   BIT(eObjLast+1),
    eShapeLast     =   eObjLast + 5
};


class Shape : public Object {
protected:
    static Point	spts[10];
    int			ink, penink;
    VObject		*container;
    short		pensize;
    GrLineCap		arrows;
    bool		isDeleted, isEnabled;
    float		longitude, latitude;
    char		*objname;
public:
    Rectangle		bbox;
    class GeoPos	bbox1, bbox2;
    
public:
    MetaDef(Shape);
    
    Shape();
    ~Shape();
    
    void Init1();
    virtual class Point	MinSize() const { return MinShapeSize; }

    void SetLong(float l) { longitude= l; }
    void SetLat(float l) { latitude= l; }
    float GetLong() const;
    float GetLat() const;
    virtual float GetLength() const { return 0; }
    void SetName(const char *n) {
	SafeDelete(objname);
	objname= new char[strlen(n)+1];
	strcpy(objname, n);
    }
    const char *GetName() const { return (const char*) objname; }

    virtual void AreaChanged();
    void SetGeoPos();

    View *GetView() const { return (View*) container; }
	
    VObject *GetContainer()
	{ return container; }
    virtual void SetContainer(VObject *vop);

    //---- sizes ---------------------------------------
    virtual void Init(Point p1, Point p2);
    virtual void SetSpan(Rectangle);
    virtual Rectangle GetSpan();
    virtual void Moveby(Point delta);
    virtual void Flip(int);
    
    //---- drawing -------------------------------------
    void DrawAll(Rectangle, int blink_col= 0, bool force= FALSE);
    virtual void Draw(Rectangle);
    virtual void Outline(Point, Point);
    virtual void Highlight(HighlightState);
    void Invalidate();
    virtual Rectangle InvalRect();
    bool IsInRect(Rectangle *r)
	{ return !isDeleted && InvalRect().Intersects(*r); }
    virtual GrCursor SketchCursor();
    
    //---- interaction ---------------------------------
    virtual ShapeSketcher *NewSketcher(DrawView*, SketchModes);
    virtual class ShapeStretcher *NewStretcher(DrawView*, int);
    virtual bool ContainsPoint1(Point);
    virtual bool ContainsPoint(Point);
    
    //---- handles -------------------------------------
    virtual Point *MakeHandles(int*);
    virtual void HighlightHandle(int);
    virtual int PointOnHandle(Point p);

    //---- properties ----------------------------------
    virtual short *GetImage();
    void SetSplit(bool b);
    bool GetSplit()
	{ return TestFlag(eShapeSplit); }
    virtual bool CanSplit();
    void SetDeleted(bool);
    bool GetDeleted()
	{ return isDeleted; }
    virtual bool IsGarbage();

    virtual void SetProperty(ShapeProperties, Object *op);
    virtual void ResetProperty(ShapeProperties, Object *op);
    virtual Object *GetProperty(ShapeProperties);

    virtual void SetSimpleProperty(ShapeProperties, int);
    virtual void ResetSimpleProperty(ShapeProperties, int);
    virtual int GetSimpleProperty(ShapeProperties);

    virtual Point GetConnectionPoint(Point);
    virtual Point Chop(Point);
    
    //---- text properties ----------------------------
    virtual Rectangle GetTextRect();        
    
    //---- input/output -------------------------------
#ifdef ET25
    virtual OStream& PrintOn(OStream&);
    virtual IStream& ReadFrom(IStream&);
#else
    virtual ostream& PrintOn(ostream&);
    virtual istream& ReadFrom(istream&);
#endif
};

double GeoDist(GeoPos &p1, GeoPos &p2);

//---- Change Property Command -------------------------------------------------

class ChangePropertyCommand: public DrawCommand {
protected:
    int cnt;
public:
    ChangePropertyCommand(DrawView*, int, char*);
    virtual void SaveProperty(Shape*, int);
    virtual void RestoreProperty(Shape*, int);
    virtual void SetProperty(Shape*, int);
    void SaveDoIt();
    void RestoreRedoIt();
    void RestoreUndoIt();
};

//---- Shape Stretcher ---------------------------------------------------------

class ShapeStretcher: public ChangePropertyCommand {
    Rectangle bbox, bbox1, bboxn, theBbox, allBbox;
    Point p1, p2;
    Rectangle *oldSpans;
    float sx, sy;
    int flip;

protected:
    class Shape *sp;
    int handle;

public:
    ShapeStretcher(DrawView *view, Shape*, int);
    ~ShapeStretcher();

    void SaveProperty(Shape*, int);
    void RestoreProperty(Shape*, int);
    void SetProperty(Shape*, int);
    Command *TrackMouse(TrackPhase, Point, Point, Point);
    void TrackConstrain(Point, Point, Point*);
    void TrackFeedback(Point, Point, bool);
};

#endif Shapes_First

