Need help with Drag and Drop for Wiki how-to

For help with anything that CEGUI doesn't offer straight out-of-the-box, e.g.:
- Implementation of new features, such as new Core classes, widgets, WindowRenderers, etc. ...
- Modification of any existing features for specific purposes
- Integration of CEGUI in new engines or frameworks and writing of new plugins (Renderer, Parser, ...) or modules

Moderators: CEGUI MVP, CEGUI Team

Rackle
CEGUI Team (Retired)
Posts: 534
Joined: Mon Jan 16, 2006 11:59
Location: Montréal

Postby Rackle » Thu Nov 16, 2006 13:43

>>I have no idea how a wiki page would be written differently from a manual page

I think the main difference is that the wiki entries are standalone topics whereas a manual would show a progression of topics. In a way the manual could go through the source code to explain the basic widgets and then go through the wiki to show what could be built from these basic widgets. This is sort of what I'm doing with the drag and drop thing (and what I've apparently done with nearly everything I've contributed so far). From basic widgets I'm building something bigger. It should cover most situations but if it does not then hopefully that programmer can modify the wiki to let everyone benefit.

Rackle
CEGUI Team (Retired)
Posts: 534
Joined: Mon Jan 16, 2006 11:59
Location: Montréal

Postby Rackle » Thu Nov 16, 2006 16:19

CrazyEddie wrote:new setting that I'll be putting in to allow a window to 'opt out' of getting those events.


I'm not sure if that's the answer. Let's say that (for whatever reason) I have a DropTarget with 4 children arranged in a 2x2 grid that entirely covers the DropTarget window. These 4 children will opt out and not receive the events but would the DropTarget receive them? That window is the one that's really interested the drag and drop events, not its children.

Or maybe you meant that the children would not trigger the EventDragDropTargetChanged, which is what I've resorted to in my code. Hrm, I'll try to post an alpha version very soon. Hopefully it can provide some idea of what I'm working on / talking about. Here's a preview.

This is within the DragItem class:

Code: Select all

    // Register events to override their behavior
    Window* dragWindow = WindowManager::getSingleton().getWindow(mWindow);
   dragWindow->subscribeEvent(DragContainer::EventDragDropTargetChanged, Event::Subscriber(&DragItem::handleDropTargetChanged, this));
    dragWindow->subscribeEvent(DragContainer::EventDragEnded,             Event::Subscriber(&DragItem::handleDragEnded,         this));

//---------------------------------------------------------------------------
bool DragItem::handleDropTargetChanged(const CEGUI::EventArgs& args)
{
    // This code ensures that the "enter" and "leave" events are generated only
    // once even when dragging over the children of a drag item
    // We only care if our target is a drop target or if we are over a drag item
    // slotted into a drop target.
    using namespace CEGUI;
    const DragDropEventArgs& ddea = static_cast<const DragDropEventArgs&>(args);

    // Check if we're over a drop target
    DropTarget* newDropTarget = DropTarget::findDropTarget(ddea.window->getName());
    if(!newDropTarget)
    {
        // Not over a drop target so check if we're over a drag item slotted into a DropTarget
        Window* parent = ddea.window;
        while(parent)
        {
            if(parent->testClassName(CEGUI::DragContainer::WidgetTypeName))
            {
                // We found a drag item
                //newDropTarget = DropTarget::findDropTarget(parent->getName());
            DragItem* dragItem = findDragItem(parent->getName());
            if(dragItem)
               newDropTarget = dragItem->getDropTarget();
                break;
            }
            parent = parent->getParent();
        }
    }

    // Trigger the "leaves" and "enter" events to the appropriate windows
    if( !(mHoveringDropTarget
          && newDropTarget
          && mHoveringDropTarget->getWindow().compare(newDropTarget->getWindow()) == 0) )
    {
        if(mHoveringDropTarget)
            mHoveringDropTarget->onDragItemLeave(this);
        if(newDropTarget)
            newDropTarget->onDragItemEnter(this, newDropTarget->isValid(this));
        mHoveringDropTarget = newDropTarget;
    }

    return true;
}

//---------------------------------------------------------------------------
bool DragItem::handleDragEnded(const CEGUI::EventArgs& args)
{
   using namespace CEGUI;
    if(mHoveringDropTarget && mHoveringDropTarget->isValid(this))
    {
        //mHoveringDropTarget->onDragItemDropped(this);
      DragDropConfig::getSingleton().processDrop(getDropTarget(), this, mHoveringDropTarget);
    }

    return true;
}


DragDropConfig is my latest addition, to handle the cases I've mentioned recently, moving a DragItem from spellbook to spellbook, spellbook to toolbar, and toolbar to toolbar.

I have tested the case of a DropTarget containing 1 child, which does not interfere with my processing. Next test would be a DropTarget with multiple children.

User avatar
CrazyEddie
CEGUI Project Lead
Posts: 6760
Joined: Wed Jan 12, 2005 12:06
Location: England
Contact:

Postby CrazyEddie » Fri Nov 17, 2006 12:21

Rackle wrote:
CrazyEddie wrote:new setting that I'll be putting in to allow a window to 'opt out' of getting those events.


I'm not sure if that's the answer. Let's say that (for whatever reason) I have a DropTarget with 4 children arranged in a 2x2 grid that entirely covers the DropTarget window. These 4 children will opt out and not receive the events but would the DropTarget receive them? That window is the one that's really interested the drag and drop events, not its children.


If the drop target (i.e. the one that want's the events) has the option enabled, and all the child 'items' do not, even if the entire drop target is obscured by it's children it will be the drop target that gets the events. Also, it's not some hack whereby the children "pass it on", it's all done properly :P The only event generated is by the window that ultimately wanted the drop notification.

I actually implemented this yesterday (for inclusion in future releases). If you want to try it out (not for the tutorial, but to check the behaviour), then you could try the latest code in "cegui_mk2/branches/v0-5" - the members are called isDragDropTarget / setDragDropTarget, and the property is "DragDropTarget" - all are booleans.

CE.

Rackle
CEGUI Team (Retired)
Posts: 534
Joined: Mon Jan 16, 2006 11:59
Location: Montréal

Postby Rackle » Fri Nov 17, 2006 13:54

>> it's all done properly

I don't doubt it.

>> isDragDropTarget() and setDragDropTarget()

Sounds like any window can become a DropTarget, including a listbox, which allows items to be dropped onto the listbox to add entries...fun possibilities.

>> try the latest code

I've looked at onDragPositionChanged() which compares the window under the DragItem to the old d_dropTarget. Seems like there would be multiple enter/leave events fired for a single DropTarget composed of multiple items.

Code: Select all

if ((d_dropTarget != 0) && !d_dropTarget->isDragDropTarget())
    d_dropTarget = d_dropTarget->getParent();


This would not handle the case of a DropTarget having multiple child windows stacked one on top of the other.

Grr, I'm going to be late for work...

User avatar
CrazyEddie
CEGUI Project Lead
Posts: 6760
Joined: Wed Jan 12, 2005 12:06
Location: England
Contact:

Postby CrazyEddie » Fri Nov 17, 2006 14:02

Rackle wrote:

Code: Select all

if ((d_dropTarget != 0) && !d_dropTarget->isDragDropTarget())
    d_dropTarget = d_dropTarget->getParent();


This would not handle the case of a DropTarget having multiple child windows stacked one on top of the other.

Gah! Thanks for that - the 'if' should be a 'while'. :oops:

CE.

Rackle
CEGUI Team (Retired)
Posts: 534
Joined: Mon Jan 16, 2006 11:59
Location: Montréal

Postby Rackle » Fri Nov 17, 2006 16:00

I finally came up with a scenario where the number of enter and leave events is important (I can't seem to let go of that point). If I play a sound when a drag item enters a drop target and another when it leaves that drop target then I would play those sounds too often.

I would modify the code within onDragPositionChanged to something like this:

Code: Select all

Window* eventWindow = root->getChildAtPosition(MouseCursor::getSingleton().getPosition());
d_enabled = wasEnabled;

if (eventWindow)
{
    while((eventWindow != 0) && !eventWindow->isDragDropTarget())
        eventWindow = eventWindow->getParent();
    if (eventWindow && eventWindow != d_dropTarget)
    {
      DragDropEventArgs args(eventWindow);
      args.dragDropItem = this;
      onDragDropTargetChanged(args);
    }
}


However it does not handle dropping a DragItem into emptiness/emptyness, such as when removing a slotted DragItem from a DropTarget/toolbar. Maybe something along the lines of:

Code: Select all

    if (!eventWindow || eventWindow && eventWindow != d_dropTarget)
    {
     if(!eventWindow)
       eventWindow = System::getSingleton().getGUISheet(); // root

would work (this is a revised version of the IF after the WHILE)..

User avatar
CrazyEddie
CEGUI Project Lead
Posts: 6760
Joined: Wed Jan 12, 2005 12:06
Location: England
Contact:

Postby CrazyEddie » Fri Nov 17, 2006 17:59

Well, to be honest I can't see how there can be multiple events fired for attached item windows if they have the DragDropTarget setting at False.

As it stands now (fixed with the while, of course), notifyDragDropItemEnters is only ever called for a window that has DragDropTarget set to true, and therefore such windows are also the only ones to ever have notifyDragDropItemLeaves on them. Thus, if all "items" attached to a target have this setting disabled, you will only ever get the notifications, and therefore the events fired, on the parent window which is enabled as a drop target window.

You actually have me doubting myself a little, so I will test the scenario you describe tomorrow - just to be sure!

CE.

User avatar
steven
Not too shy to talk
Not too shy to talk
Posts: 26
Joined: Mon Jul 04, 2005 18:38

Postby steven » Sun Jan 07, 2007 12:34

Was the wiki howto created ?
I couldn't find it.

Thanks

Rackle
CEGUI Team (Retired)
Posts: 534
Joined: Mon Jan 16, 2006 11:59
Location: Montréal

Postby Rackle » Sun Jan 07, 2007 12:46

No, not yet. I've been having trouble coding a solution that is sufficiently generic to handle every possible case. And I've been slacking off because of the holidays...

uelkfr
Not too shy to talk
Not too shy to talk
Posts: 34
Joined: Tue Dec 14, 2010 16:57

Re: Need help with Drag and Drop for Wiki how-to

Postby uelkfr » Sun Jan 02, 2011 06:56

Draging from toolbar and dropping to workspace window in Lua

Code: Select all

function handleDragDropped(args)
    local dragContainer = CEGUI.toDragDropEventArgs(args).dragDropItem;
    local staticWindow = CEGUI.toDragDropEventArgs(args).window;
    local clonedWindow = dragContainer:getChildAtIdx(1):clone("root/Workspace/Operator"..tostring(G_wndId), false);
    G_wndId = G_wndId + 1;
    clonedWindow:setVisible(true);
    local pos = CEGUI.CoordConverter:screenToWindow(staticWindow, dragContainer:getPosition());
    local parentSize = dragContainer:getParentPixelSize();
    local parentPos = dragContainer:getParent():getPosition():asAbsolute(parentSize);
    clonedWindow:setPosition(CEGUI.UVector2(CEGUI.UDim(0,pos.x+parentPos.x),CEGUI.UDim(0,pos.y+parentPos.y)));
    clonedWindow:setSize(CEGUI.UVector2(CEGUI.UDim(0,64),CEGUI.UDim(0,18)));
    staticWindow:addChildWindow(clonedWindow);
end

...
winMgr:getWindow("root/Workspace"):subscribeEvent("DragDropItemDropped", "handleDragDropped");
G_wndId = 0;


I use getChildAtIdx(1), because I have two windows attached to DragContainer. One of which is visible only when dragging, and second is visible when showing on toolbar.
helper to newbies

"i help you, dear newbie
but nobody helps me!"


Return to “Modifications / Integrations / Customisations”

Who is online

Users browsing this forum: No registered users and 16 guests