Forum > LCL

[SOLVED] Inserting button by dragging

(1/1)

egsuh:
I have four tbuttons on a TFlowPanel (or TPanel). All of them are same sizes, aligned as alTop, and widths match the width of the parent panel. So, then are in a row from top to bottom (let's say button1, button2, button3, and button4).

Is there any way that I can move the position of buttons, by dragging one button over and dropping it on another button? Form example, if I drag & drop Button3 on button1 then the order would be buttons 3,1,2,4.  And from here, if I drag and drop button4 on to button1 then the order would be 3,4,1,2. 

Is this possible?

egsuh:
Or not necessarily drag & drop. By any other event (e.g. buy clicking other buttons), I'd like to move them.

dje:
This is the simplest method I've found. It works for most control types which are aligned to top in a TPanel. The main code is:

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---procedure TFormMain.Button1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: integer);var LControl: TControl;begin  LControl := Sender as TControl;  if LControl.Parent = PanelButtons then begin    LControl.ControlStyle := LControl.ControlStyle + [csCaptureMouse];    if csLButtonDown in LControl.ControlState then begin      LControl.Top := LControl.Top + (Y - LControl.Height div 2);    end;  end;end;
An up/down style re-order (as used in Lazarus's menu editor, TListView items editor) requires a way to select an item. So, your buttons would have to be TToggleButton's or some other method. The problem with the above, is, the control list order is not changed. So, you would have to find another way to extract the ordering. ie: Sorting controls by Y.

I do recommend you look at other interfaces which are more suited to re-ordering by the user. eg TListView.

wp:
Is this question about designtime or about runtime?

If I understand correctly, the buttons are filling a panel, arranged from top to bottom, all having the same size. This can be achieved most easily with the ChildSizing property of the panel: Set panel.ChildSizing.ControlsPerLine=1, .EnlargeHorizontal=crsHomogenousChildResize, .Layout=cclLeftToRightThenTopToBottom, and .ShrinkVertical=crsHomogenousChildResize. Then add the buttons - they will be added from top to bottom and exanded over the entire panel width (and if you had set ChildSizing.EnlargeVertical and .ShrinkVertical to crsHomogenousChildResize, too, they will also fill the panel vertically).

If you want to rearrange buttons at designtime, right-click the button that you want to move and select "Z-order" > (one of the items in that context menu) to change the button's z-order index.

If you want to do this at runtime find out the z index of the destination button by calling Panel.GetControlIndex(button) and change the z index of the dropped button by calling Panel.SetControlIndex(dropped_button, destination_button_index). This can be incorporated in a short drag-and-drop code:

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---procedure TForm1.ButtonDragOver(Sender, Source: TObject; X, Y: Integer;  State: TDragState; var Accept: Boolean);begin  if (Source is TButton) and (TButton(Source).Parent = Panel1) then    Accept := true;end; // Source = button dragged// Sender = button on which Source is droppedprocedure TForm1.ButtonDragDrop(Sender, Source: TObject; X, Y: Integer);var  pos: Integer;begin  // Find position of "Sender" in the panel's Z-order.  pos := Panel1.GetControlIndex(TControl(Sender));   // Move "Source" to position of "Sender" in the panel's Z-order.  Panel1.SetControlIndex(TControl(Source), pos);   // Update the childsizing  Panel1.Realign;end;

egsuh:
Thank you wp.

I had been almost neat to your example, except that I missed Panel1. in

           Panel1.getControlIndex and Panel1.setControlIndex,

and Panel1.Realign;.   All the buttons' DragMode must be dmAutomatic to work only with the codes.

And thank you for other advises --- they are much helpful.

Navigation

[0] Message Index

Go to full version