@@ -367,17 +367,59 @@ void LayoutManipulator::dropEvent(QGraphicsSceneDragDropEvent* event)
367367 widgetPaths.append (name);
368368 }
369369
370+ CEGUIUtils::removeNestedPaths (widgetPaths);
371+
370372 if (event->dropAction () == Qt::MoveAction)
371373 {
372- _visualMode.moveWidgetsInHierarchy (std::move (widgetPaths), this , getWidget ()->getChildCount ());
373- event->acceptProposedAction ();
374+ // Remember desired offsets before reparenting:
375+ // - Dragged item is always the first (only for visual mode dragging for now, not from the tree)
376+ // - The first dragged item from each parent is dropped at a cursor position, with a small cascade offset
377+ // - All subsequent items from the same parent keep relative position to the first item
378+ std::map<LayoutManipulator*, QPointF> offsetByParent;
379+ std::map<CEGUI ::Window*, CEGUI ::UVector2> newPositions;
380+ const auto dropOffset = event->scenePos () - scenePos ();
381+
382+ for (const QString& widgetPath : widgetPaths)
383+ {
384+ auto manipulator = _visualMode.getScene ()->getManipulatorByPath (widgetPath);
385+ if (!manipulator) continue ;
386+
387+ auto oldParentManipulator = dynamic_cast <LayoutManipulator*>(manipulator->parentItem ());
388+ if (!oldParentManipulator) continue ;
389+
390+ auto it = offsetByParent.find (oldParentManipulator);
391+ if (it == offsetByParent.cend ())
392+ {
393+ const qreal cascadeOffset = offsetByParent.size () * 10.0 ;
394+ const QPointF offset = dropOffset - manipulator->pos () + QPointF (cascadeOffset, cascadeOffset);
395+ it = offsetByParent.emplace (oldParentManipulator, offset).first ;
396+ }
397+
398+ if (it->second .manhattanLength () > 0.0 )
399+ {
400+ auto newPos = manipulator->getWidget ()->getPosition ();
401+ newPos.d_x .d_offset += static_cast <float >(it->second .x ());
402+ newPos.d_y .d_offset += static_cast <float >(it->second .y ());
403+ newPositions.emplace (manipulator->getWidget (), newPos);
404+ }
405+ }
406+
407+ // First reparent widgets to the new parent
408+ _visualMode.moveWidgetsInHierarchy (widgetPaths, this , getWidget ()->getChildCount ());
374409
375- // calc offset
376- // get pos of the widget in old parent (need widget that we started to drag, or always first? or drag start pos, if more than one widget?)
377- // get pos of the drop inside this
378- // event->scenePos() - scenePos();
379- // Add move command
410+ // Then move widgets using the drop position with a separate command
411+ std::vector<LayoutMoveCommand::Record> records;
412+ LayoutMoveCommand::Record rec;
413+ for (const auto & pair : newPositions)
414+ {
415+ rec.path = CEGUIUtils::stringToQString (pair.first ->getNamePath ());
416+ rec.oldPos = pair.first ->getPosition ();
417+ rec.newPos = pair.second ;
418+ records.push_back (std::move (rec));
419+ }
420+ _visualMode.getEditor ().getUndoStack ()->push (new LayoutMoveCommand (_visualMode, std::move (records)));
380421
422+ event->acceptProposedAction ();
381423 return ;
382424 }
383425 }
@@ -397,24 +439,25 @@ void LayoutManipulator::mouseMoveEvent(QGraphicsSceneMouseEvent* event)
397439 setCursor (Qt::ClosedHandCursor);
398440
399441 std::set<LayoutManipulator*> selectedWidgets;
400- _visualMode.getScene ()->collectSelectedWidgets (selectedWidgets);
401442
402443 /* UX: not sure what is better, move all selection or only a Ctrl-dragged item
403- if (selectedWidgets.find(this) == selectedWidgets.end ())
444+ if (!isSelected() && !isAnyHandleSelected ())
404445 {
405446 _visualMode.getScene()->clearSelection();
406- selectedWidgets.clear();
407- selectedWidgets.insert(this);
408447 }
409448 else
410449 */
411450 {
412- selectedWidgets. insert ( this );
451+ _visualMode. getScene ()-> collectSelectedWidgets (selectedWidgets );
413452 LayoutVisualMode::removeNestedManipulators (selectedWidgets);
453+ selectedWidgets.erase (this ); // Will add to stream manually
414454 }
415455
416456 QByteArray bytes;
417457 QDataStream stream (&bytes, QIODevice::WriteOnly);
458+
459+ // Add dragged widget first, then the rest of selection
460+ stream << getWidgetPath ();
418461 for (LayoutManipulator* manipulator : selectedWidgets)
419462 stream << manipulator->getWidgetPath ();
420463
0 commit comments