Garry's Mod Wiki

Revision Difference

Drag_and_Drop_for_VGUI#562994

<cat>Dev.UI</cat>⤶ # Drag 'N' Drop This is a drag n drop tutorial since it barely documented. ⤶ It's very easy, all you need to have is have two panels; receiver and droppable panel. ⤶ ```⤶ local receiver = vgui.Create('DPanel')⤶ receiver:SetSize( ScrW() / 2, ScrH() / 2 )⤶ ⤶ local droppable = vgui.Create('DPanel')⤶ droppable:SetSize( 100, 100 )⤶ This is a drag n drop tutorial since it's barely documented. It's very easy, all you need to have is two panels: a receiver and a droppable panel. ⤶ ## How it Works⤶ ⤶ [Panel:Droppable( string name )](https://wiki.facepunch.com/gmod/Panel:Droppable) takes 1 argument:⤶ * Name - Must match receiver's name to allow dropping⤶ ⤶ [Panel:Receiver( string name, function callback, table menu = nil )](https://wiki.facepunch.com/gmod/Panel:Receiver) takes 3 arguments:⤶ * Name - Identifier to match droppable panels⤶ * Callback - Function called when dragging/dropping occurs⤶ * Menu Options - Table of strings for right-click menu (optional)⤶ ⤶ The callback receives:⤶ * self - The receiving panel⤶ * panels - Table of panels being dropped⤶ * dropped - True when actually dropped, false while dragging over⤶ * menuIndex - Index if using right-click menu⤶ * x,y - Drop coordinates relative to receiver⤶ ⤶ In the example below:⤶ * Red panel can only be dropped on right frame⤶ * Green panel can be dropped on either frame⤶ * When dropped, panels become children of the receiving frame⤶ ⤶ ## Basic Example⤶ Here's a complete example showing one-way and two-way drag and drop:⤶ ⤶ ```lua⤶ -- Create two frames side by side⤶ local left_dframe = vgui.Create("DFrame")⤶ local right_dframe = vgui.Create("DFrame")⤶ ⤶ local w, h = 200, 300⤶ local screen_w, screen_h = ScrW(), ScrH()⤶ local x = screen_w / 2 - w - 10⤶ local y = screen_h / 2 - h / 2⤶ ⤶ left_dframe:SetSize(w, h)⤶ right_dframe:SetSize(w, h)⤶ left_dframe:SetPos(x, y)⤶ right_dframe:SetPos(x + w + 20, y)⤶ left_dframe:SetTitle("Source")⤶ right_dframe:SetTitle("Target")⤶ left_dframe:MakePopup()⤶ right_dframe:MakePopup()⤶ ⤶ local red = vgui.Create("DPanel", left_dframe)⤶ local green = vgui.Create("DPanel", left_dframe)⤶ red:SetSize(50, 50)⤶ green:SetSize(50, 50)⤶ red:SetPos(20, 50)⤶ green:SetPos(20, 120)⤶ ⤶ red.Paint = function(s, w, h)⤶ surface.SetDrawColor(120, 0, 0)⤶ surface.DrawRect(0, 0, w, h)⤶ draw.DrawText("One-way", "DermaDefault", w / 2, h / 2, color_white, TEXT_ALIGN_CENTER)⤶ end⤶ ⤶ green.Paint = function(s, w, h)⤶ surface.SetDrawColor(0, 120, 0)⤶ surface.DrawRect(0, 0, w, h)⤶ draw.DrawText("Two-way", "DermaDefault", w / 2, h / 2, color_white, TEXT_ALIGN_CENTER)⤶ end⤶ ⤶ -- Make panels draggable⤶ red:Droppable("one-way")⤶ green:Droppable("two-way")⤶ ⤶ -- Make only right dframe receive one-way drops⤶ right_dframe:Receiver("one-way", function(self, panels, dropped, _, x, y)⤶ if dropped then⤶ panels[1]:SetParent(self)⤶ panels[1]:SetPos(x - 25, y - 25)⤶ end⤶ end)⤶ ⤶ -- Make both dframes receive two-way drops⤶ right_dframe:Receiver("two-way", function(self, panels, dropped, _, x, y)⤶ if dropped then⤶ panels[1]:SetParent(self)⤶ panels[1]:SetPos(x - 25, y - 25)⤶ end⤶ end)⤶ ⤶ left_dframe:Receiver("two-way", function(self, panels, dropped, _, x, y)⤶ if dropped then⤶ panels[1]:SetParent(self)⤶ panels[1]:SetPos(x - 25, y - 25)⤶ end⤶ end)⤶ ``` ⤶ ⤶ Now we need to assign receiver and droppable functions for the panels⤶ ⤶ ```⤶ receiver:Receiver( 'name', function( receiver, tableOfDroppedPanels, isDropped, menuIndex, mouseX, mouseY ) end, {} )⤶ droppable:Droppable( 'name' )⤶ ```⤶ ⤶ Receiver metamethod takes three arguments, first one being the name of the DnD so it can receiver all droppable panels that have the same name as the receiver, callback function which gets executed as soon as a droppable panel is hovered over the receiver (if you want to detect it as soon as it was dropped, use isDropped argument) and last one is a table of strings that will act as a menu if drag'n'drop was performed with a right click.⤶ ⤶ Use the callback function for your stuff, setting position of the dropped panel or whatever you wanted to do.⤶ ⤶ Check <page>Panel:Receiver</page> for more information about the receiver metamethod.⤶ ⤶ The droppable method only takes one argument and it's the name of the receiver you want to drop it on.⤶ ⤶ More information at <page>Panel:Droppable</page>⤶ ⤶ Now you're able to drop droppable onto receiver.⤶ ⤶ ⤶ ⤶ <upload src="b5453/8dd0e1a9b8d45b1.gif" size="4926499" name="ezgif-2-7f57a61ca1.gif" />