heh I hate frameworks so this is easy as pie for me...
this is what I coded for my students during my lectures few years back:
This is the main engine code (complete project + exe is in that zip above):
//---------------------------------------------------------------------------
//--- Constants: ------------------------------------------------------------
//---------------------------------------------------------------------------
const int _select_max_l=16;
const int _select_max_ll=_select_max_l*_select_max_l;
const int _half_size=10;
const int _atoms_max=32;
//---------------------------------------------------------------------------
enum _atom_type_enum //++++
{
_atom_type_non=0,
_atom_type_kruh,
_atom_type_stvorec,
_atom_type_enum_end
};
//---------------------------------------------------------------------------
enum _editor_edit_mode_enum //****
{
_editor_edit_mode_non=0,
_editor_edit_mode_move,
_editor_edit_mode_mov,
_editor_edit_mode_add_kruh,
_editor_edit_mode_add_stvorec,
_editor_edit_mode_del,
_editor_edit_mode_enum_end
};
//---------------------------------------------------------------------------
//--- viewer: ---------------------------------------------------------------
//---------------------------------------------------------------------------
class viewer
{
public: int x0,y0;
viewer() { x0=0; y0=0; }
void world2screen(int &sx,int &sy,int wx,int wy) { sx=wx-x0; sy=wy-y0; }
void screen2world(int &wx,int &wy,int sx,int sy) { wx=sx+x0; wy=sy+y0; }
void world2screen(int &sl,int wl) { sl=wl; }
void screen2world(int &wl,int sl) { wl=sl; }
};
//---------------------------------------------------------------------------
//--- atom kruh: ------------------------------------------------------------
//---------------------------------------------------------------------------
class atom_kruh
{
public: int x,y,r; // world coordinates
TColor col0,col1,col2;
AnsiString str;
atom_kruh() { x=0; y=0; r=_half_size; str=""; col0=clBlue; col1=clAqua; col2=clWhite; }
void draw(TCanvas *scr,const viewer &view)
{
int xx,yy,rr;
view.world2screen(xx,yy,x,y);
view.world2screen(rr,r);
scr->Brush->Color=col0;
scr->Pen ->Color=col1;
scr->Font ->Color=col2;
scr->Ellipse(xx-rr,yy-rr,xx+rr,yy+rr);
scr->Brush->Style=bsClear;
xx-=scr->TextWidth(str)>>1;
yy-=scr->TextHeight(str)>>1;
scr->TextOutA(xx,yy,str);
scr->Brush->Style=bsSolid;
}
bool select(int &ll,int wx,int wy)
{
int qq,xx,yy;
xx=wx-x; xx*=xx;
yy=wy-y; yy*=yy;
qq=xx+yy;
if ((qq<=_select_max_ll)&&((qq<=ll)||(ll<0))) { ll=qq; return true; }
return false;
}
};
//---------------------------------------------------------------------------
//--- atom kruh: ------------------------------------------------------------
//---------------------------------------------------------------------------
class atom_stvorec
{
public: int x,y,r; // world coordinates
TColor col0,col1,col2;
AnsiString str;
atom_stvorec() { x=0; y=0; r=_half_size; str=""; col0=clBlue; col1=clAqua; col2=clWhite; }
void draw(TCanvas *scr,const viewer &view)
{
int xx,yy,rr;
view.world2screen(xx,yy,x,y);
view.world2screen(rr,r);
scr->Brush->Color=col0;
scr->Pen ->Color=col1;
scr->Font ->Color=col2;
scr->Rectangle(xx-rr,yy-rr,xx+rr,yy+rr);
scr->Brush->Style=bsClear;
xx-=scr->TextWidth(str)>>1;
yy-=scr->TextHeight(str)>>1;
scr->TextOutA(xx,yy,str);
scr->Brush->Style=bsSolid;
}
bool select(int &ll,int wx,int wy)
{
int qq,xx,yy;
xx=wx-x; xx*=xx;
yy=wy-y; yy*=yy;
qq=xx+yy;
if ((qq<=_select_max_ll)&&((qq<=ll)||(ll<0))) { ll=qq; return true; }
return false;
}
};
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
class editor
{
public: Graphics::TBitmap *bmp; // back buffer
int xs,ys;
int sel_ix,sel_tp; // actual mouse selected item
int edit_mode; // selected edit tool
viewer view; // view
bool redraw; // redraw needed?
bool locked; // edit in progress?
WORD key,key0;
int mx,my,mx0,my0;
TShiftState sh,sh0;
atom_kruh kruh[_atoms_max]; // all object lists
atom_stvorec stvorec[_atoms_max];
int kruhov;
int stvorcov;
editor();
~editor();
void resize(int _xs,int _ys); // interface with window
void draw();
void mouse(int x,int y,TShiftState s) { mx0=mx; my0=my; sh0=sh; mx=x; my=y; sh=s; edit(); }
void keys(WORD k,TShiftState s) { key0=key; sh0=sh; key=k; sh=s; edit(); }
void select(); // helper functions
void edit();
void move (bool q0,bool q1,int x,int y,int dx,int dy);
void mov (bool q0,bool q1,int x,int y,int dx,int dy);
void add_kruh (bool q0,bool q1,int x,int y,int dx,int dy);
void add_stvorec(bool q0,bool q1,int x,int y,int dx,int dy);
void del (bool q0,bool q1,int x,int y,int dx,int dy);
};
//---------------------------------------------------------------------------
editor::editor()
{
bmp=new Graphics::TBitmap;
resize(1,1);
sel_ix=-1;
sel_tp=_atom_type_non;
edit_mode=_editor_edit_mode_non;
key=0; key0=0;
mx=0; mx0=0;
my=0; my0=0;
locked=false;
kruhov=0;
stvorcov=0;
}
//---------------------------------------------------------------------------
editor::~editor()
{
delete bmp;
}
//---------------------------------------------------------------------------
void editor::resize(int _xs,int _ys)
{
bmp->Width=_xs;
bmp->Height=_ys;
xs=bmp->Width;
ys=bmp->Height;
redraw=true;
}
//---------------------------------------------------------------------------
void editor::draw()
{
int i;
if (!redraw) return;
redraw=false;
bmp->Canvas->Brush->Color=clBlack;
bmp->Canvas->FillRect(Rect(0,0,xs,ys));
//++++
for (i=0;i<kruhov ;i++) kruh[i] .draw(bmp->Canvas,view);
for (i=0;i<stvorcov;i++) stvorec[i].draw(bmp->Canvas,view);
}
//---------------------------------------------------------------------------
void editor::select()
{
int i,wx,wy,ll;
int sel_tp0=sel_tp; sel_tp=_atom_type_non;
int sel_ix0=sel_ix; sel_ix=-1;
view.screen2world(wx,wy,mx,my);
//++++
ll=-1;
for (i=0;i<kruhov ;i++) if (kruh[i] .select(ll,wx,wy)) { sel_tp=_atom_type_kruh; sel_ix=i; };
for (i=0;i<stvorcov;i++) if (stvorec[i].select(ll,wx,wy)) { sel_tp=_atom_type_stvorec; sel_ix=i; };
if (sel_tp!=sel_tp0) redraw=true;
if (sel_ix!=sel_ix0) redraw=true;
}
//---------------------------------------------------------------------------
void editor::edit()
{
bool q0,q1;
int x,y,dx,dy;
x=mx; dx=mx-mx0;
y=my; dy=my-my0;
view.screen2world( x, y, x, y);
view.screen2world(dx,dx);
view.screen2world(dy,dy);
q0=sh0.Contains(ssLeft);
q1=sh .Contains(ssLeft);
if (!locked) select();
//****
if(edit_mode==_editor_edit_mode_mov) mov (q0,q1,x,y,dx,dy);
if(edit_mode==_editor_edit_mode_add_kruh) add_kruh (q0,q1,x,y,dx,dy);
if(edit_mode==_editor_edit_mode_add_stvorec)add_stvorec (q0,q1,x,y,dx,dy);
if(edit_mode==_editor_edit_mode_del) del (q0,q1,x,y,dx,dy);
q0=sh0.Contains(ssRight);
q1=sh .Contains(ssRight);
if (!locked) move(q0,q1,x,y,dx,dy);
}
//---------------------------------------------------------------------------
void editor::move (bool q0,bool q1,int x,int y,int dx,int dy)
{
if ((sel_ix>=0)&&(sel_tp!=_atom_type_non)) return;
if (q1)
{
view.x0-=dx;
view.y0-=dy;
redraw=true;
}
}
//---------------------------------------------------------------------------
void editor::mov (bool q0,bool q1,int x,int y,int dx,int dy)
{
if ((!locked)&&((sel_ix<0)||(sel_tp==_atom_type_non))) return;
locked=false;
if ((q1)||((q0)&&(!q1)))
{
//++++
if (sel_tp==_atom_type_kruh)
{
kruh[sel_ix].x=x;
kruh[sel_ix].y=y;
}
if (sel_tp==_atom_type_stvorec)
{
stvorec[sel_ix].x=x;
stvorec[sel_ix].y=y;
}
locked=true;
}
if (!q1) locked=false;
redraw=true;
}
//---------------------------------------------------------------------------
void editor::add_kruh (bool q0,bool q1,int x,int y,int dx,int dy)
{
if ((!locked)&&(sel_ix>=0)&&(sel_tp!=_atom_type_non)) return;
locked=false;
if (kruhov>=_atoms_max) return;
if ((!q0)&&( q1))
{
sel_tp=_atom_type_kruh;
sel_ix=kruhov;
kruhov++;
kruh[sel_ix].x=x;
kruh[sel_ix].y=y;
kruh[sel_ix].str=kruhov;
locked=true;
}
if (( q0)&&( q1))
{
kruh[sel_ix].x=x;
kruh[sel_ix].y=y;
locked=true;
}
if (( q0)&&(!q1))
{
kruh[sel_ix].x=x;
kruh[sel_ix].y=y;
}
if ((!q0)&&(!q1))
{
}
redraw=true;
}
//---------------------------------------------------------------------------
void editor::add_stvorec(bool q0,bool q1,int x,int y,int dx,int dy)
{
if ((!locked)&&(sel_ix>=0)&&(sel_tp!=_atom_type_non)) return;
locked=false;
if (stvorcov>=_atoms_max) return;
if ((!q0)&&( q1))
{
sel_tp=_atom_type_stvorec;
sel_ix=stvorcov;
stvorcov++;
stvorec[sel_ix].x=x;
stvorec[sel_ix].y=y;
stvorec[sel_ix].str=s