static char *sccs_id= (sccs_id, "@(#)Army.c	3.7 7/28/92");

/*

    GEO, Postgres GIS (Geografic Information System) frontend

    Copyright (C) 1991  TNO Institute for Perception, The Netherlands
			Written by: Tom Vijlbrief

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 1, or (at your option)
    any later version.

    This program 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 more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.


Note that parts of this distribution are taken from the ET++
distribution. See the et2.2/ subdirectories for details.

===============================================================================
Tom Vijlbrief
TNO Institute for Perception		Phone: +31 34 63 562 11
P.O. Box 23				Fax:   +31 34 63 539 77
3769 ZG  Soesterberg			E-mail: tom@izf.tno.nl
The Netherlands				or: uunet!hp4nl.nluug.nl!tnosoes!tom
===============================================================================

*/

#include "Class.h"
#include "Application.h"
#include "Document.h"
#include "Window.h"
#include "View.h"
#include "Menu.h"
#include "DialogItems.h"
#ifdef ET25
#include "Fields.h"
#include "Stream.h"
#else
#include "RestrTView.h"
#endif
#include "RegularExp.h"
#include "CheapText.h"
#include "ImageItem.h"
#include "Army.h"

#include "DrawView.h"

//---- ArmyShape Methods -------------------------------------------------------

static short ArmyImage[]= {
#   include  "army_images/army.img"
};

MetaImpl(ArmyShape,
	(T(el),T(wl),T(nl),T(sl), T(h),
	 TP(es),TP(ws),TP(ns),TP(ss),
	 TP(font), 0
	));

Font	*ArmyShape::font;
int	ArmyShape::h;


ArmyShape::ArmyShape()
{
  if (!font) {
    font= new_Font(eFontHelvetica, 12, eFaceBold);
    h= 2 * ArmyShape::font->BBox((byte*)"").extent.y;
  }

  bbox= gRect0;
  ink= 0;
}

ArmyShape::~ArmyShape()
{
    // SafeDelete(bm);
    // SafeDelete(sbm);
}


void ArmyShape::Moveby(Point delta)
{
    center= center + delta;
    Shape::Moveby(delta);
}


short *ArmyShape::GetImage()
{
    return ArmyImage;
}

void ArmyShape::Init(Point pp1, Point pp2)
{
    ArmySymbolDialog *d;

    bm= (d= ((DrawView*)GetView())->GetArmyDialog())->GetType();
    sbm= d->GetStrength();
    ns= (byte*) strsave(d->north_str());
    ss= (byte*) strsave(d->south_str());
    es= (byte*) strsave(d->east_str());
    ws= (byte*) strsave(d->west_str());
    nl= font->BBox(ns).extent.x+margin;
    sl= font->BBox(ss).extent.x+margin;
    el= font->BBox(es).extent.x+margin;
    wl= font->BBox(ws).extent.x+margin;
    center= GeoPos(this,pp1);
    Point pc= center;
    Shape::Init(pc-Point(wl+im_w/2,h+im_h/2+10),
	pc+Point(el+im_w/2-1,h+im_h/2-1));
}

void ArmyShape::AreaChanged()
{
  bbox.origin= center - Point(wl+im_w/2,h+im_h/2+10);
}

void ArmyShape::DrawCenterStr(Point p, byte *s, Font *font)
{
  Rectangle rec= font->BBox(s);
  Point pos(p.x - rec.extent.x/2, p.y + rec.extent.y/2);
  GrTextMoveto(pos);
  GrSetTextNormal();
  GrSetFont(font);
  GrDrawString(s);
}


void ArmyShape::Draw(Rectangle r)
{
  bool no_text= bbox.extent.x < wl+el || bbox.extent.y < 2*h;

  Rectangle im_box(bbox.origin + (no_text ? gPoint0: Point(wl,h)),
	bbox.extent- (no_text ? gPoint0: Point(el+wl,2*h)));
  Rectangle str_box(im_box.origin, Point(im_box.extent.x, im_box.extent.y/5));
  GrPaintBitMap(str_box, sbm, GetInk(penink));
  Rectangle sym_box(im_box.origin+Point(0,str_box.extent.y),
	im_box.extent-Point(0,str_box.extent.y));
  GrFillRect(sym_box);
  GrPaintBitMap(sym_box, bm, GetInk(penink));
  if (no_text)
	return;
  DrawCenterStr(im_box.origin+Point(im_box.extent.x/2,-h/2), ns);
  DrawCenterStr(im_box.origin+Point(im_box.extent.x/2,im_box.extent.y+h/2), ss);
  DrawCenterStr(im_box.origin+Point(-wl/2,im_box.extent.y/2), ws);
  DrawCenterStr(im_box.origin+Point(im_box.extent.x+el/2,im_box.extent.y/2), es);
}


#ifdef ET25
OStream& ArmyShape::PrintOn(OStream& s)
#else
ostream& ArmyShape::PrintOn(ostream& s)
#endif
{
    Shape::PrintOn(s);
    center.Save(s);
#ifdef ET25
    s.PrintString(ns); s SP << nl << "\n";
    s.PrintString(ss); s SP << sl << "\n";
    s.PrintString(es); s SP << el << "\n";
    s.PrintString(ws); s SP << wl << "\n";
#else
    PrintString(s, ns); s SP << nl << "\n";
    PrintString(s, ss); s SP << sl << "\n";
    PrintString(s, es); s SP << el << "\n";
    PrintString(s, ws); s SP << wl << "\n";
#endif
    return s << bm << sbm;
}

#ifdef ET25
IStream& ArmyShape::ReadFrom(IStream& s)
#else
istream& ArmyShape::ReadFrom(istream& s)
#endif
{
    Shape::ReadFrom(s);
    center.Load(s);
#ifdef ET25
    s.ReadString(&ns) >> nl;
    s.ReadString(&ss) >> sl;
    s.ReadString(&es) >> el;
    s.ReadString(&ws) >> wl;
#else
    ReadString(s, &ns) >> nl;
    ReadString(s, &ss) >> sl;
    ReadString(s, &es) >> el;
    ReadString(s, &ws) >> wl;
#endif
    SafeDelete(bm);
    SafeDelete(sbm);
    return s >> bm >> sbm;
}

static char    *strength_string[] = {
	"Leeg",
	"Onbekend",
	"Divisie",
	"Brigade",
	"Bataljon",
	"Compagnie",
	"Peloton",
	"Groep"
};

const int STRENGTH_SIZE= sizeof(strength_string) / sizeof(strength_string[0]);

static char    *type_string[] = {
	"Blanko",
	"Infanterie",
	"Painf",
	"Artillerie",
	"Genie",
	"PaGenie",
	"Tank",
	"Verkenners",
	"Verbindingen"
};

const int TYPE_SIZE= sizeof(type_string) / sizeof(type_string[0]);

// IMAGES
static short TypeImage[][ArmyShape::im_w/sizeof(short)/8 * ArmyShape::im_h] = {
#   include "army_images/blanko.img"
#   include "army_images/inf.img"
#   include "army_images/painf.img"
#   include "army_images/art.img"
#   include "army_images/gen.img"
#   include "army_images/pagn.img"
#   include "army_images/tank.img"
#   include "army_images/verk.img" 
#   include "army_images/verb.img"
};

static short StrengthImage[][ArmyShape::im_w/sizeof(short)/8 * 10] = {
#    include "army_images/leeg.img"
#    include "army_images/onbekend.img"
#    include "army_images/divisie.img"
#    include "army_images/brigade.img"
#    include "army_images/bataljon.img"
#    include "army_images/compagnie.img"
#    include "army_images/peloton.img"
#    include "army_images/groep.img"
};

//---- MyImageItem      --------------------------------------------------------

class MyImageItem: public ImageItem {
public:
    MetaDef(MyImageItem);
    MyImageItem( Bitmap* b ) : (b)
        { }
    void ChangeBitmap( Bitmap* );
    Bitmap *GetBitmap()
        { return bmp; }
};

MetaImpl0(MyImageItem);

void MyImageItem::ChangeBitmap(Bitmap *newbmp)
{
    bmp = newbmp;
    ForceRedraw();
}

//---- ArmySymbolDialog --------------------------------------------------------
#ifdef __GNUG__
static
#endif
const int   cIdSize    =    cIdFirstUser + 200,
            cIdType    =    cIdFirstUser + 201,
            cIdStrength=    cIdFirstUser + 202,
            cIdNorth   =    cIdFirstUser + 203,
            cIdEast    =    cIdFirstUser + 204,
            cIdWest    =    cIdFirstUser + 205,
            cIdSouth   =    cIdFirstUser + 206,
            cIdMENU    =    cIdFirstUser + 210;


#ifdef ET23
MetaImpl(ArmySymbolDialog, (TP(size), TP(type), TP(strength), 
			    T(oldsize), T(oldtype), T(oldstrength),
			    TP(north), TP(south), TP(east), TP(west),
			    TP(oldnorth), TP(oldsouth),
			    TP(oldeast), TP(oldwest),
			    TP(typeimageitem), TP(strengthimageitem), 
			    TAP(typebmp),
			    TAP(strengthbmp), 0));
#else
MetaImpl(ArmySymbolDialog, (TP(size), TP(type), TP(strength), 
			    T(oldsize), T(oldtype), T(oldstrength),
			    TP(north), TP(south), TP(east), TP(west),
			    TP(oldnorth), TP(oldsouth),
			    TP(oldeast), TP(oldwest),
			    TP(typeimageitem), TP(strengthimageitem), 
			    0));
#endif

#ifdef ET25
ArmySymbolDialog::ArmySymbolDialog() : ("Define Symbol")
#else
ArmySymbolDialog::ArmySymbolDialog() : ("Define Symbol", eBWinBlock)
#endif
{
    unsigned i;

    strengthbmp= new Bitmap*[STRENGTH_SIZE];
    for (i=0 ; i < STRENGTH_SIZE ; i++)
        strengthbmp[i] = new Bitmap(Point(ArmyShape::im_w,10), StrengthImage[i]);

    typebmp= new Bitmap*[TYPE_SIZE];
    for (i=0 ; i < TYPE_SIZE ; i++)
        typebmp[i] = new Bitmap(Point(ArmyShape::im_w,ArmyShape::im_h), TypeImage[i]);
        // typebmp[i] = new Bitmap(Point(44,32), TypeImage[i]);
    valid = FALSE;
};

ArmySymbolDialog::~ArmySymbolDialog()
{
    unsigned i;

    for (i=0 ; i < STRENGTH_SIZE ; i++)
        SafeDelete(strengthbmp[i]);
    SafeDelete(strengthbmp);
    for (i=0 ; i < TYPE_SIZE ; i++)
        SafeDelete(typebmp[i]);
    SafeDelete(typebmp);
}

VObject* ArmySymbolDialog::DoCreateDialog()
{
    RegularExp *regularexp = new RegularExp(".?.?.?.?.?.?.?.?.?.?");
    int textwidth = gSysFont->Size() * (ETI_SIZE-1);
        
    // joep@tnosoes: due to a bug we have to create a Centered item this way...
#ifdef ET25
    north = new RegExpField(cIdNorth, regularexp);
    south = new RegExpField(cIdSouth, regularexp);
    west = new RegExpField(cIdWest, regularexp);
    east = new RegExpField(cIdEast, regularexp);
#else
    north = new EditTextItem(cIdNorth, 
                new RestrTextView(this,
                    regularexp,
                    Rectangle(gPoint0, Point(textwidth, cFit)),
                    new CheapText((byte*)"", ETI_SIZE),
                    eCenter
                )
            );

    south = new EditTextItem(cIdSouth, 
                new RestrTextView(this,
                    regularexp,
                    Rectangle(gPoint0, Point(textwidth, cFit)),
                    new CheapText((byte*)"", ETI_SIZE),
                    eCenter
                )
            );

    west = new EditTextItem(cIdWest, 
                new RestrTextView(this,
                    regularexp,
                    Rectangle(gPoint0, Point(textwidth, cFit)),
                    new CheapText((byte*)"", ETI_SIZE),
                    eRight
                )
            );

    east = new RestrTextItem(cIdEast, regularexp, "");
#endif

    VObject *SymbolText=
        new BorderItem("Symbol", 
            new Cluster(cIdNone, eVObjHCenter, 10,
                north,
                new Cluster(cIdNone, eVObjVCenter, 10,
                    west,
                    new Cluster(cIdNone, eVObjHCenter, 10,
                        strengthimageitem = new MyImageItem( strengthbmp[0] ),
                        typeimageitem = new MyImageItem( typebmp[0] ),
                        0
                    ),
                    east,
                    0
                ),
                south,
                0
            )
        );

    strength=
        new OneOfCluster(cIdStrength, eVObjHLeft, 10,
            strength_string[0],
            strength_string[1],
            strength_string[2],
            strength_string[3],
            strength_string[4],
            strength_string[5],
            strength_string[6],
            strength_string[7],
            0
        );
                
    type=
        new OneOfCluster(cIdType, eVObjHLeft, 10,
            type_string[0],
            type_string[1],
            type_string[2],
            type_string[3],
            type_string[4],
            type_string[5],
            type_string[6],
            type_string[7],
            type_string[8],
            0
        );

#if 0
    size= new OneOfCluster(cIdSize, eVObjHLeft, 10,
            "Klein",
            "Medium",
            "Groot",
            0
        );
#endif

    VObject *Actions=
        new Cluster(cIdNone, eVObjVCenter, 20,
            new ActionButton(cIdYes,     "OK", TRUE),
            new ActionButton(cIdCancel,  "Cancel"),
            new ActionButton(cIdDefault, "Default"),
            0
        );
    BorderItem *asdialog =
        new BorderItem(
            new Cluster(cIdNone, eVObjHCenter, 20, 
                SymbolText,
                new Cluster(cIdNone, eVObjVTop, 10,
                    new BorderItem("Sterkte", 
                        strength
                    ),
                    new BorderItem("Type",
                        type
                    ),
#if 0
                    new BorderItem("Grootte", 
                        size
                    ),
#endif
                    0
                ),
                Actions,
                0
            )
        );

    return asdialog;
}

int ArmySymbolDialog::ShowArmySymbolDialog(VObject *v)
{
    if (v)
        return ShowOnWindow(v->GetWindow());
    return -1;
}

void    ArmySymbolDialog::Control(int id, int p, void *v)
{
    switch (id) {
    case cIdYes:
	valid = TRUE;
	break;
    case cIdStrength:
        strengthimageitem->ChangeBitmap(strengthbmp[p-id]);
        break;
    case cIdType:
        typeimageitem->ChangeBitmap(typebmp[p-id]);
        break;
    case cIdCancel:
	valid= FALSE;
    }
    Dialog::Control(id, p, v);
}

void    ArmySymbolDialog::DoSetDefaults()
{
    /* Called once and when 'default'-button is selected */
    strength->SetItemOn(cIdStrength);
    strengthimageitem->ChangeBitmap(strengthbmp[0]);
    
    type->SetItemOn(cIdType);
    typeimageitem->ChangeBitmap(typebmp[0]);

#if 0
    size->SetItemOn(cIdSize+eASMedium);
#endif

    north->SetString((byte *)"Noord");
    south->SetString((byte *)"Zuid");
    east->SetString((byte *)"Oost");
    west->SetString((byte *)"West");
}

#ifdef ET25
#else
class MyLabeledButton: public LabeledButton {
public:
  VObject *Left() { return left; }
  VObject *Right() { return right; }
};

//=========================================================
int GetOneOfCluster(OneOfCluster *c)
{
    if (c->Size() <= 0)
        return 0;
    Iter next(c->GetList());
    MyLabeledButton *dip;

    while (dip = (MyLabeledButton*) next()) {
        if (((OnOffItem*)dip->Left())->GetValue())
            return dip->GetId();
    }
    return 0;
}
#endif

//=======================================================

void    ArmySymbolDialog::DoSave()
{
#ifdef ET25
    strcpy(oldnorth, north->AsString());
    strcpy(oldsouth, south->AsString());
    strcpy(oldeast, east->AsString());
    strcpy(oldwest, west->AsString());
#else
    oldstrength = GetOneOfCluster(strength);
    oldtype = GetOneOfCluster(type);
    strcpy(oldnorth, north->GetText()->AsString());
    strcpy(oldsouth, south->GetText()->AsString());
    strcpy(oldeast, east->GetText()->AsString());
    strcpy(oldwest, west->GetText()->AsString());
#endif
}

void    ArmySymbolDialog::DoRestore()
{
    strength->SetItemOn(oldstrength);
    strengthimageitem->ChangeBitmap(strengthbmp[oldstrength-cIdStrength]);

    type->SetItemOn(oldtype);
    typeimageitem->ChangeBitmap(typebmp[oldtype-cIdType]);

#if 0
    size->Set(oldsize);
#endif
 
    north->SetString((byte *)oldnorth);
    south->SetString((byte *)oldsouth);
    east->SetString((byte *)oldeast);
    west->SetString((byte *)oldwest);
}

void    ArmySymbolDialog::DoSetup()
{
    valid = FALSE;
}

Bitmap* ArmySymbolDialog::GetType()
{
    return typeimageitem->GetBitmap();
}

Bitmap* ArmySymbolDialog::GetStrength()
{
    return strengthimageitem->GetBitmap();
}

ArmySymbolSize ArmySymbolDialog::GetSize()
{
    return 0;
}

bool ArmySymbolDialog::Valid()
{
    return valid;
}

const char *ArmySymbolDialog::north_str()
{
#ifdef ET25
  return north->AsString();
#else
  return north->GetText()->AsString();
#endif
}

const char *ArmySymbolDialog::south_str()
{
#ifdef ET25
  return south->AsString();
#else
  return south->GetText()->AsString();
#endif
}

const char *ArmySymbolDialog::east_str()
{
#ifdef ET25
  return east->AsString();
#else
  return east->GetText()->AsString();
#endif
}

const char *ArmySymbolDialog::west_str()
{
#ifdef ET25
  return west->AsString();
#else
  return west->GetText()->AsString();
#endif
}
