/* This file is part of KDDockWidgets. SPDX-FileCopyrightText: 2019 Klarälvdalens Datakonsult AB, a KDAB Group company Author: Sérgio Martins SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only Contact KDAB at for commercial licensing options. */ /** * @file * @brief A MultiSplitter with support for drop indicators when hovering over. * * @author Sérgio Martins \ */ #ifndef KD_DROP_AREA_P_H #define KD_DROP_AREA_P_H #pragma once #include "kddockwidgets/docks_export.h" #include "kddockwidgets/KDDockWidgets.h" #include "kddockwidgets/core/Layout.h" class TestQtWidgets; class TestDocks; namespace KDDockWidgets { namespace Core { class Group; class Draggable; class DockWidget; class Separator; class DropIndicatorOverlay; class LayoutingSeparator; struct WindowBeingDragged; /** * MultiSplitter is simply a wrapper around Core::Item in which the hosted widgets are * of class KDDockWidgets::Frame. The stuff in Core:: being agnostic and generic, not specific * to KDDW. * * A MultiSplitter is like a QSplitter but supports mixing vertical and horizontal splitters in * any combination. * * It supports adding a widget to the left/top/bottom/right of the whole MultiSplitter or adding * relative to a single widget. */ class DOCKS_EXPORT DropArea : public Layout { Q_OBJECT public: explicit DropArea(View *parent, MainWindowOptions options, bool isMDIWrapper = false); ~DropArea(); void removeHover(); DropLocation hover(WindowBeingDragged *draggedWindow, Point globalPos); ///@brief Called when a user drops a widget via DND bool drop(WindowBeingDragged *droppedWindow, Point globalPos); Vector groups() const; Core::Item *centralFrame() const; DropIndicatorOverlay *dropIndicatorOverlay() const; void addDockWidget(DockWidget *dw, KDDockWidgets::Location location, DockWidget *relativeTo, const InitialOption &initialOption = {}); void _addDockWidget(DockWidget *dw, KDDockWidgets::Location location, Item *relativeTo, const InitialOption &initialOption); bool containsDockWidget(DockWidget *) const; /// Returns whether this layout has a single dock widget which is floating /// Implies it's in a FloatingWindow and that it has only one dock widget bool hasSingleFloatingGroup() const; /// Returns whether this drop area has only 1 group. /// See further explanation in FloatingWindow::hasSingleGroup() bool hasSingleGroup() const; Vector affinities() const; void layoutParentContainerEqually(DockWidget *); /// When DockWidgetOption_MDINestable is used, docked MDI dock widgets will be wrapped inside /// a DropArea, so they accept drops This DropArea is created implicitly while docking, and this /// function will return true bool isMDIWrapper() const; /// Returns the helper dock widget for implementing DockWidgetOption_MDINestable. Core::DockWidget *mdiDockWidgetWrapper() const; static Core::Group *createCentralGroup(MainWindowOptions options); /** * @brief Adds a widget to this MultiSplitter. */ void addWidget(View *widget, KDDockWidgets::Location location, Core::Item *relativeToItem = nullptr, const InitialOption &option = DefaultSizeMode::Fair); /** * Adds an entire MultiSplitter into this layout. The donor MultiSplitter will be deleted * after all its Frames are stolen. All added Frames will preserve their original layout, so, * if widgetFoo was at the left of widgetBar when in the donor splitter, then it will still be * at left of widgetBar when the whole splitter is dropped into this one. */ void addMultiSplitter(Core::DropArea *sourceMultiSplitter, KDDockWidgets::Location location, Core::Group *relativeToGroup = nullptr, const InitialOption &option = DefaultSizeMode::Fair); /** * Called by the indicators, so they draw the drop rubber band at the correct place. * The rect for the rubberband when dropping a widget at the specified location. * Excludes the Separator thickness, result is actually smaller than what needed. In other * words, the result will be exactly the same as the geometry the widget will get. */ Rect rectForDrop(const WindowBeingDragged *wbd, KDDockWidgets::Location location, const Core::Item *relativeTo) const; bool deserialize(const LayoutSaver::MultiSplitter &) override; ///@brief returns the list of separators Vector separators() const; /// @brief See docs for MainWindowBase::layoutEqually() void layoutEqually(); /// @brief overload that just resizes widgets within a sub-tree void layoutEqually(Core::ItemBoxContainer *); /// @brief Returns the number of items layed-out horizontally or vertically /// But honours nesting int numSideBySide_recursive(Qt::Orientation) const; Core::ItemBoxContainer *rootItem() const; /// Returns the current drop location /// The user needs to be dragging a window and be over a drop indicator, otherwise DropLocation_None is returned DropLocation currentDropLocation() const; Core::Group *centralGroup() const; #if defined(DOCKS_DEVELOPER_MODE) public: #else private: #endif KDDW_DELETE_COPY_CTOR(DropArea) friend class Core::MainWindow; friend class Core::Group; friend class Core::FloatingWindow; friend class DropIndicatorOverlay; friend class AnimatedIndicators; // For debug/hardening bool validateInputs(View *widget, KDDockWidgets::Location location, const Core::Item *relativeToItem, const InitialOption &option) const; void setRootItem(Core::ItemBoxContainer *); /** * @brief Like @ref availableLengthForDrop but just returns the total available width or height * (depending on @p orientation) So no need to receive any location. * @param orientation If Qt::Vertical then returns the available height. Width otherwise. */ int availableLengthForOrientation(Qt::Orientation orientation) const; /** * @brief Equivalent to @ref availableLengthForOrientation but returns for both orientations. * width is for Qt::Vertical. */ Size availableSize() const; template bool validateAffinity(T *, Core::Group *acceptingGroup = nullptr) const; bool drop(WindowBeingDragged *draggedWindow, Core::Group *acceptingGroup, DropLocation); bool drop(View *droppedwindow, KDDockWidgets::Location location, Core::Group *relativeTo); Core::Group *groupContainingPos(Point globalPos) const; void updateFloatingActions(); class Private; Private *const d; }; } } #endif