Alguém sabe de um exemplo de baixo nível (sem frameworks) de uma lista de arrastar e soltar, reordenável?

Eu estou procurando código (qualquer idioma) de uma lista gráfica básica que pode ser reordenada por arrastar e soltar. Tão exatamente essa funcionalidade http://jqueryui.com/sortable/, mas escrita diretamente no buffer de frameworks / canvas sem qualquer estrutura (ou bibliotecas de baixo nível ‘colocar pixel’ no máximo) e provavelmente não em HTML / JS (a menos que seja apenas Canvas sem CSS).

Quanto mais simples melhor, como eu vou usá-lo no montador e não quero reinventar a roda se não for necessário.

heh eu odeio frameworks então isso é fácil como torta para mim …

isto é o que eu codifiquei para meus alunos durante minhas palestras há alguns anos atrás:

Este é o código do motor principal (projeto completo + exe está nesse zip acima):

//--------------------------------------------------------------------------- //--- 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;iCanvas,view); for (i=0;iCanvas,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=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=stvorcov; locked=true; } if (( q0)&&( q1)) { stvorec[sel_ix].x=x; stvorec[sel_ix].y=y; locked=true; } if (( q0)&&(!q1)) { stvorec[sel_ix].x=x; stvorec[sel_ix].y=y; } if ((!q0)&&(!q1)) { } redraw=true; } //--------------------------------------------------------------------------- void editor::del (bool q0,bool q1,int x,int y,int dx,int dy) { locked=false; if ((sel_ix<0)||(sel_tp==_atom_type_non)) return; if ((!q0)&&( q1)) { //++++ if (sel_tp==_atom_type_kruh) if (kruhov>0) { kruhov--; kruh[sel_ix]=kruh[kruhov]; } if (sel_tp==_atom_type_stvorec) if (stvorcov>0) { stvorcov--; stvorec[sel_ix]=stvorec[stvorcov]; } sel_ix=-1; sel_tp=_atom_type_non; } redraw=true; } //--------------------------------------------------------------------------- 

desculpe por isso não é inteiramente em Inglês

  • kruh significa círculo
  • stvorec significa quadrado

Este é o código para a janela (estilo BDS2006 VCL )

 //$$---- Form CPP ---- //--------------------------------------------------------------------------- #include  #pragma hdrstop #include "Unit1.h" #include "editor.h" //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1; editor edit; int x0,y0; //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- void draw() // redraw app screen { edit.draw(); Form1->Canvas->Draw(x0,y0,edit.bmp); // here just some info print outs int dy=16,x=x0,y=y0-dy; Form1->Canvas->Font->Color=clAqua; Form1->Canvas->Brush->Style=bsClear; Form1->Canvas->TextOutA(x,y+=dy,AnsiString().sprintf("locked: %i",edit.locked)); Form1->Canvas->TextOutA(x,y+=dy,AnsiString().sprintf("Key: %d",edit.key)); Form1->Canvas->TextOutA(x,y+=dy,AnsiString().sprintf("sel_tp: %i",edit.sel_tp)); Form1->Canvas->TextOutA(x,y+=dy,AnsiString().sprintf("sel_ix: %i",edit.sel_ix)); Form1->Canvas->TextOutA(x,y+=dy,AnsiString().sprintf("kruhov: %i",edit.kruhov)); Form1->Canvas->TextOutA(x,y+=dy,AnsiString().sprintf("stvorcov: %i",edit.stvorcov)); Form1->Canvas->Brush->Style=bsSolid; } //--------------------------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner):TForm(Owner) // init app { // select tool on app start bt_tool_kruhClick(this); } //--- window events: --------------------------------------------------------- void __fastcall TForm1::FormPaint(TObject *Sender) { draw(); } void __fastcall TForm1::FormResize(TObject *Sender) { x0=pan_top->Left; y0=pan_top->Height; edit.resize(ClientWidth-x0,ClientHeight-y0); draw(); } void __fastcall TForm1::FormActivate(TObject *Sender) { draw(); } //--------------------------------------------------------------------------- void __fastcall TForm1::FormKeyDown(TObject *Sender, WORD &Key, TShiftState Shift) { edit.keys(Key,Shift); draw(); } void __fastcall TForm1::FormMouseMove(TObject *Sender, TShiftState Shift, int X, int Y) { edit.mouse(X-x0,Y-y0,Shift); draw(); } void __fastcall TForm1::FormMouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y){ edit.mouse(X-x0,Y-y0,Shift); draw(); } void __fastcall TForm1::FormMouseUp(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y) { edit.mouse(X-x0,Y-y0,Shift); draw(); } //--------------------------------------------------------------------------- void __fastcall TForm1::bt_tool_kruhClick(TObject *Sender) // event on any tool button click { // select editor tool mode ... edit.edit_mode=_editor_edit_mode_non; if (bt_tool_kruh ->Down) edit.edit_mode=_editor_edit_mode_add_kruh; if (bt_tool_stvorec->Down) edit.edit_mode=_editor_edit_mode_add_stvorec; if (bt_tool_move ->Down) edit.edit_mode=_editor_edit_mode_mov; if (bt_tool_delete ->Down) edit.edit_mode=_editor_edit_mode_del; } //--------------------------------------------------------------------------- 

A janela tem apenas 4 botões de ferramentas (unidos pelo mesmo guia, de modo que somente um pode estar inativo por vez)

  • adicionar ferramenta de círculo
  • adicionar ferramenta quadrada
  • mover ferramenta
  • excluir ferramenta

Tudo é alocado estaticamente para simplicidade

[edit1] mais informações

  1. criar tipo / class de dados do object gfx ( atom_xxxx )

    ele deve manter o size,position,shape da representação gráfica visual do object. Adicione variables ​​de conexão ( type object e index objects ao que deve estar conectado). Adicione o object / dados reais dentro

  2. ID do object

    Eu estou usando int tp,ix;

    • tp significa tipo de object
    • ix significa índice na lista de objects do tipo tp
  3. motor de editor

    isso deve ser também class ou conjunto de variables ​​e funções. Deve conter todo o mundo editado (listas de objects):

    • variables ​​de visualização como bitmap de canvas / backbufer ou contexto de renderização, posição do mouse, lista de seleção
    • adicione funções / events como onmouse, onkey, draw,
    • adicionar function de edição deve ser capaz de select,add,del,move (arrastar e soltar) objects. Idealmente controlado por um conjunto de comandos para facilitar a operação de desfazer / refazer
    • adicionar undo/redo
    • adicionar save,load
    • adicione sua funcionalidade de simulação desejada

    e isso é tudo se eu não esqueci alguma coisa.

  4. criar interface GUI do aplicativo

    então crie janela, adicione painel com botões para cada ferramenta, menu e o que você precisar. Adicionar events para mouse, teclado, redesenhar, resize, arrastar e soltar, … Meu exemplo é assim:

    app editor

    Adicione editor edit; para ele globalmente ou como um membro dele. A opção de membro é melhor se você quiser ter o MDI mais tarde. Adicione interface de events entre edição e janela (o segundo código fonte).

[Notas]

  • ++++ marca parte do código onde você precisa adicionar mudanças se algum tipo de átomo é adicionado ao sistema
  • **** marca parte do código onde você precisa adicionar alterações se algum modo de edição for adicionado ao sistema

Desculpe por não adicionar mais código comentado, se você precisar esclarecer algo, me comente.

Espero que ajude um pouco …