Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzQt includes
Toshihiro Shimizu 890ddd
#include "toonzqt/menubarcommand.h"
Toshihiro Shimizu 890ddd
#include "docklayout.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// Qt includes
Toshihiro Shimizu 890ddd
#include <qevent></qevent>
Toshihiro Shimizu 890ddd
#include <qmouseevent></qmouseevent>
Toshihiro Shimizu 890ddd
#include <qapplication></qapplication>
Toshihiro Shimizu 890ddd
#include <qdesktopwidget></qdesktopwidget>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// STD includes
Toshihiro Shimizu 890ddd
#include <assert.h></assert.h>
Toshihiro Shimizu 890ddd
#include <math.h></math.h>
Toshihiro Shimizu 890ddd
#include <algorithm></algorithm>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//========================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------
Toshihiro Shimizu 890ddd
//    Dock Lock Check
Toshihiro Shimizu 890ddd
//-----------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
DockingCheck *DockingCheck::instance() {
Shinya Kitaoka 120a6e
  static DockingCheck _instance;
Shinya Kitaoka 120a6e
  return &_instance;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void DockingCheck::setToggle(QAction *toggle) { m_toggle = toggle; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void DockingCheck::setIsEnabled(bool on) {
Shinya Kitaoka 120a6e
  m_enabled = on;
Shinya Kitaoka 120a6e
  if (m_toggle) m_toggle->setChecked(on);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//========================================================
Toshihiro Shimizu 890ddd
Shinya Kitaoka d1f6c4
class DockingToggleCommand final : public MenuItemHandler {
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  DockingToggleCommand() : MenuItemHandler("MI_DockingCheck") {}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 473e70
  void execute() override {
Shinya Kitaoka 120a6e
    DockingCheck *dc = DockingCheck::instance();
Shinya Kitaoka 120a6e
    dc->setIsEnabled(!dc->isEnabled());
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
} dockingToggleCommand;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//========================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------
Toshihiro Shimizu 890ddd
//    Geometry inlines
Toshihiro Shimizu 890ddd
//------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
//! Calculates infinite-norm distance between points \b a and \b b.
Shinya Kitaoka 120a6e
inline int absoluteDistance(const QPoint &a, const QPoint &b) {
Shinya Kitaoka 120a6e
  return std::max(abs(a.x() - b.x()), abs(a.y() - b.y()));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
// Il metodo QRectF::toRect pare che faccia la cosa commentata. Ovviamente non
Shinya Kitaoka 120a6e
// e' la cosa piu' simpatica - considera
Shinya Kitaoka 120a6e
// che in questo modo i bordi del rect di input *non vengono approssimati alle
Shinya Kitaoka 120a6e
// piu' vicine coordinate intere*!
Shinya Kitaoka 120a6e
//  es:   topLeft= (1/3, 1/3); width= 4/3, height= 4/3 => left= top= right=
Shinya Kitaoka 120a6e
//  bottom= 0.
Shinya Kitaoka 120a6e
inline QRect toRect(const QRectF &rect) {
Shinya Kitaoka 120a6e
  // return QRect(qRound(rect.left()), qRound(rect.top()), qRound(rect.width()),
Shinya Kitaoka 120a6e
  // qRound(rect.height()));
Shinya Kitaoka 120a6e
  return QRect(rect.topLeft().toPoint(),
Shinya Kitaoka 120a6e
               rect.bottomRight().toPoint() -= QPoint(1, 1));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//========================================================
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
// Forward declaration
Shinya Kitaoka 120a6e
namespace {
Toshihiro Shimizu 890ddd
QDesktopWidget *desktop;
Toshihiro Shimizu 890ddd
void getClosestAvailableMousePosition(QPoint &globalPos);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//========================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------
Toshihiro Shimizu 890ddd
//    Layout inlines
Toshihiro Shimizu 890ddd
//----------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
inline void DockLayout::update() {
Shinya Kitaoka 120a6e
  // E' necessario?
Shinya Kitaoka 120a6e
  applyGeometry();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//========================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------
Toshihiro Shimizu 890ddd
//    My Dock Widget Methods
Toshihiro Shimizu 890ddd
//------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
//! Constructs a dock Widget; every newly constructed dock widget is floating
Shinya Kitaoka 120a6e
//! (i.e. not docked
Shinya Kitaoka 120a6e
//! into the layout).
Toshihiro Shimizu 890ddd
DockWidget::DockWidget(QWidget *parent, Qt::WindowFlags flags)
Jeremy Bullock 3a998e
    : QFrame(parent, flags)
Shinya Kitaoka 120a6e
    , m_dragging(false)
Shinya Kitaoka 120a6e
    , m_resizing(false)
Shinya Kitaoka 120a6e
    , m_floating(true)
Shinya Kitaoka 120a6e
    , m_undocking(false)
Shinya Kitaoka 120a6e
    , m_parentLayout(0)
Shinya Kitaoka 120a6e
    , m_selectedPlace(0)
Shinya Kitaoka 120a6e
    , m_maximized(0) {
Shinya Kitaoka 120a6e
  // Don't let this widget inherit the parent's backround color
Shinya Kitaoka 120a6e
  // setAutoFillBackground(true);
Shinya Kitaoka 120a6e
  // setBackgroundRole(QPalette::Background);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // setAttribute(Qt::WA_DeleteOnClose);   //Since Toonz just hides panels...
Shinya Kitaoka 120a6e
  setAttribute(Qt::WA_Hover);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Set default minimum and maximum sizes.
Shinya Kitaoka 120a6e
  setMinimumSize(QSize(50, 50));
Shinya Kitaoka 120a6e
  setMaximumSize(QSize(10000, 10000));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_decoAllocator = new DockDecoAllocator;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Make sure the desktop is initialized and known
Shinya Kitaoka 120a6e
  desktop = qApp->desktop();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
DockWidget::~DockWidget() {
Shinya Kitaoka 120a6e
  // Since close button lies on the title bar, make sure mouse is released if
Shinya Kitaoka 120a6e
  // that is pressed.
Shinya Kitaoka 120a6e
  if (QWidget::mouseGrabber() == this) releaseMouse();
Shinya Kitaoka 120a6e
  clearDockPlaceholders();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Delete deco allocator
Shinya Kitaoka 120a6e
  delete m_decoAllocator;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
//! Clears dock placeholders for this dockwidget. This is automatically called
Shinya Kitaoka 120a6e
//! at drag ends.
Shinya Kitaoka 120a6e
void DockWidget::clearDockPlaceholders() {
Shinya Kitaoka 120a6e
  unsigned int i;
Shinya Kitaoka 120a6e
  for (i = 0; i < m_placeholders.size(); ++i) delete m_placeholders[i];
Shinya Kitaoka 120a6e
  m_placeholders.clear();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
//! Shows dock widget in docked mode.
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
//! Returns true or false whether input \b QPoint is inside the dragging grip
Shinya Kitaoka 120a6e
//! for \b this DockWidget, or not.
Shinya Kitaoka 120a6e
//! Typically (and by default), true is returned whenever p lies inside the
Shinya Kitaoka 120a6e
//! widget's title bar when floating;
Shinya Kitaoka 120a6e
//! however, you are free to place the drag grip anywhere reimplementing this
Shinya Kitaoka 120a6e
//! method in custom dockwidgets.
Shinya Kitaoka 120a6e
bool DockWidget::isDragGrip(QPoint p) {
Shinya Kitaoka 120a6e
  if (isFloating()) {
Shinya Kitaoka 120a6e
    QRect frame        = frameGeometry();
Shinya Kitaoka 120a6e
    QRect conts        = geometry();
Shinya Kitaoka 120a6e
    int margin         = conts.left() - frame.left();
Shinya Kitaoka 120a6e
    int titleBarHeight = conts.top() - frame.top();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    QRect titleArea(QPoint(0, margin - titleBarHeight),
Shinya Kitaoka 120a6e
                    QPoint(width() - 1, -1));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    return titleArea.contains(p);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return 0;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool DockWidget::event(QEvent *e) {
Shinya Kitaoka 120a6e
  // qDebug("Dock Widget - Event type: %d", e->type());
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Little deviation or type specifications for received events
Shinya Kitaoka 120a6e
  switch (e->type()) {
Shinya Kitaoka 120a6e
  // Dock widgets are hover widgets - since their cursor may change on resize
Shinya Kitaoka 120a6e
  // grips.
Shinya Kitaoka 120a6e
  case QEvent::HoverMove:
Shinya Kitaoka 120a6e
    hoverMoveEvent(static_cast<qhoverevent *="">(e));</qhoverevent>
Shinya Kitaoka 120a6e
    return true;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Native titlebar press events must be redirected to common ones
Shinya Kitaoka 120a6e
  // - and, in this case mouse has to grabbed
Shinya Kitaoka 120a6e
  case QEvent::NonClientAreaMouseButtonPress:
Shinya Kitaoka 120a6e
    // grabMouse();  //Cannot not go here or resizes cannot be natively handled
Shinya Kitaoka 120a6e
    mousePressEvent(static_cast<qmouseevent *="">(e));</qmouseevent>
Shinya Kitaoka 120a6e
    return true;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Titlebars are not natively handled in this raw class - their responsibility
Shinya Kitaoka 120a6e
  // falls
Shinya Kitaoka 120a6e
  // to user implementation of DockWidget class
Shinya Kitaoka 120a6e
  case QEvent::WindowTitleChange:
Shinya Kitaoka 120a6e
    windowTitleEvent(e);
Shinya Kitaoka 120a6e
    return true;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  default:
Shinya Kitaoka 120a6e
    return QWidget::event(e);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
//! Adjusts widget cursor depending on \b isResizeGrip()
Shinya Kitaoka 120a6e
// NOTA: Da migliorare: ricordare il cursor settato o se era unset e riapplicare
Shinya Kitaoka 120a6e
// quando fuori dal resize grip.
Shinya Kitaoka 120a6e
void DockWidget::hoverMoveEvent(QHoverEvent *he) {
Shinya Kitaoka 120a6e
  if (m_floating && !m_resizing && !m_undocking) {
Shinya Kitaoka 120a6e
    QCursor newCursor = Qt::ArrowCursor;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if ((m_marginType = isResizeGrip(he->pos()))) {
Shinya Kitaoka 120a6e
      // Hovering a margin - update cursor shape
Shinya Kitaoka 120a6e
      if (m_marginType & leftMargin) {
Shinya Kitaoka 120a6e
        if (m_marginType & topMargin)
Shinya Kitaoka 120a6e
          newCursor = Qt::SizeFDiagCursor;
Shinya Kitaoka 120a6e
        else if (m_marginType & bottomMargin)
Shinya Kitaoka 120a6e
          newCursor = Qt::SizeBDiagCursor;
Shinya Kitaoka 120a6e
        else
Shinya Kitaoka 120a6e
          newCursor = Qt::SizeHorCursor;
Shinya Kitaoka 120a6e
      } else if (m_marginType & rightMargin) {
Shinya Kitaoka 120a6e
        if (m_marginType & topMargin)
Shinya Kitaoka 120a6e
          newCursor = Qt::SizeBDiagCursor;
Shinya Kitaoka 120a6e
        else if (m_marginType & bottomMargin)
Shinya Kitaoka 120a6e
          newCursor = Qt::SizeFDiagCursor;
Shinya Kitaoka 120a6e
        else
Shinya Kitaoka 120a6e
          newCursor = Qt::SizeHorCursor;
Shinya Kitaoka 120a6e
      } else
Shinya Kitaoka 120a6e
        newCursor = Qt::SizeVerCursor;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (newCursor.shape() != cursor().shape()) setCursor(newCursor);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
//! Dispatches mouse presses for particular purposes...
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
//! a)  Trigger a window resize (or none with native deco)
Toshihiro Shimizu 890ddd
//!    if press is over a resize grip
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
//! b)  Trigger a window drag if press is over a drag grip
Shinya Kitaoka 120a6e
void DockWidget::mousePressEvent(QMouseEvent *me) {
Shinya Kitaoka 120a6e
  if ((m_marginType = m_floating ? isResizeGrip(me->pos()) : 0)) {
Shinya Kitaoka 120a6e
    // Resize begins
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // NOTE: It is better to assume that resize grips dominate over drag grips:
Shinya Kitaoka 120a6e
    // this ensures
Shinya Kitaoka 120a6e
    // that mouse cursor changes are always consistent with resize events.
Shinya Kitaoka 120a6e
Shinya Kitaoka 38fd86
    m_resizing            = true;
Shinya Kitaoka 120a6e
    m_dragMouseInitialPos = me->globalPos();  // Re-used as old position
Shinya Kitaoka 120a6e
  } else if (isDragGrip(me->pos())) {
Shinya Kitaoka 120a6e
    // Dragging begins
Shinya Kitaoka 120a6e
    DockingCheck *lock = DockingCheck::instance();  // Docking system lock
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    m_dragMouseInitialPos = me->globalPos();
Shinya Kitaoka 120a6e
    m_dragInitialPos      = pos();
Shinya Kitaoka 120a6e
    // Grab mouse inputs - useful if widget gets under placeholders
Shinya Kitaoka 120a6e
    if (me->type() == QEvent::NonClientAreaMouseButtonPress)
Shinya Kitaoka 120a6e
      // If can receive double-clicks, avoid grabbing mouse
Shinya Kitaoka 120a6e
      grabMouse();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (m_floating) {
Shinya Kitaoka 120a6e
      m_dragging = true;
Shinya Kitaoka 120a6e
      // Do not allow docking if there is a maximized widget or the layout is
Shinya Kitaoka 120a6e
      // locked
Shinya Kitaoka 120a6e
      if (m_parentLayout && !m_parentLayout->getMaximized() &&
Shinya Kitaoka 120a6e
          !lock->isEnabled())
Shinya Kitaoka 120a6e
        m_parentLayout->calculateDockPlaceholders(this);
Shinya Kitaoka 120a6e
    } else {
Shinya Kitaoka 120a6e
      if (!lock->isEnabled()) m_undocking = true;
Shinya Kitaoka 120a6e
      m_dragInitialPos = parentWidget()->mapToGlobal(m_dragInitialPos);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void DockWidget::mouseMoveEvent(QMouseEvent *me) {
Shinya Kitaoka 120a6e
  QPoint correctedGlobalPos(me->globalPos());
Shinya Kitaoka 120a6e
  getClosestAvailableMousePosition(correctedGlobalPos);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (m_resizing) {
Shinya Kitaoka 120a6e
    // m_dragMouseInitialPos re-used as old position
Shinya Kitaoka 120a6e
    int dx = correctedGlobalPos.x() - m_dragMouseInitialPos.x();
Shinya Kitaoka 120a6e
    int dy = correctedGlobalPos.y() - m_dragMouseInitialPos.y();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    QRect geom = geometry();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (m_marginType & leftMargin) {
Shinya Kitaoka 120a6e
      int newWidth = geom.width() - dx;
Shinya Kitaoka 120a6e
      if (newWidth >= minimumWidth() && newWidth <= maximumWidth())
Shinya Kitaoka 120a6e
        geom.setLeft(geom.left() + dx);
Shinya Kitaoka 120a6e
    } else if (m_marginType & rightMargin)
Shinya Kitaoka 120a6e
      geom.setRight(geom.right() + dx);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (m_marginType & topMargin) {
Shinya Kitaoka 120a6e
      int newHeight = geom.height() - dy;
Shinya Kitaoka 120a6e
      if (newHeight >= minimumHeight() && newHeight <= maximumHeight())
Shinya Kitaoka 120a6e
        geom.setTop(geom.top() + dy);
Shinya Kitaoka 120a6e
    } else if (m_marginType & bottomMargin)
Shinya Kitaoka 120a6e
      geom.setBottom(geom.bottom() + dy);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    setGeometry(geom);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    m_dragMouseInitialPos = correctedGlobalPos;
Shinya Kitaoka 120a6e
  } else if (m_dragging) {
Shinya Kitaoka 120a6e
    move(m_dragInitialPos + correctedGlobalPos - m_dragMouseInitialPos);
Shinya Kitaoka 120a6e
    selectDockPlaceholder(me);
Shinya Kitaoka 120a6e
  } else if (m_undocking) {
Shinya Kitaoka 120a6e
    int distance = absoluteDistance(me->globalPos(), m_dragMouseInitialPos);
Shinya Kitaoka 120a6e
    if (distance > 8) {
Shinya Kitaoka 120a6e
      m_undocking = false;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      // Attempt undocking
Shinya Kitaoka 120a6e
      if (m_parentLayout->undockItem(this)) {
Shinya Kitaoka 120a6e
        m_dragging = true;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        // Then, move dock widget under cursor, as if drag actually begun at
Shinya Kitaoka 120a6e
        // button press.
Shinya Kitaoka 120a6e
        move(m_dragInitialPos + correctedGlobalPos - m_dragMouseInitialPos);
Shinya Kitaoka 120a6e
        show();  // Dock widget is not automatically shown after undock.
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        // Re-grab mouse inputs. Seems that making the window float (i.e.:
Shinya Kitaoka 120a6e
        // reparenting) breaks old grab.
Shinya Kitaoka 120a6e
        // NOTE: mouse *must* be grabbed only when visible - see Qt manual.
Shinya Kitaoka 120a6e
        grabMouse();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        // After undocking takes place, docking possibilities have to be
Shinya Kitaoka 120a6e
        // recalculated
Shinya Kitaoka 120a6e
        m_parentLayout->calculateDockPlaceholders(this);
Shinya Kitaoka 120a6e
        selectDockPlaceholder(me);
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void DockWidget::mouseReleaseEvent(QMouseEvent *me) {
Shinya Kitaoka 120a6e
  // Ensure mouse is released
Shinya Kitaoka 120a6e
  releaseMouse();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (m_dragging) {
Shinya Kitaoka 120a6e
    m_dragging = false;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    if (m_floating && m_selectedPlace) {
Shinya Kitaoka 120a6e
      m_parentLayout->dockItem(this, m_selectedPlace);
Shinya Kitaoka 120a6e
    } else {
Shinya Kitaoka 120a6e
      // qDebug("Dock failed");
Shinya Kitaoka 120a6e
    }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    // Clear dock placeholders
Shinya Kitaoka 120a6e
    clearDockPlaceholders();
Shinya Kitaoka 120a6e
    m_selectedPlace = 0;
Shinya Kitaoka 120a6e
  } else if (m_undocking) {
Shinya Kitaoka 120a6e
    // qDebug("Undock failed");
Shinya Kitaoka 120a6e
    m_undocking = false;
Shinya Kitaoka 120a6e
  } else if (m_resizing) {
Shinya Kitaoka 120a6e
    m_resizing = false;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
//! DockWidgets respond to title bar double clicks maximizing the widget in
Shinya Kitaoka 120a6e
//! layout's contents rect.
Shinya Kitaoka 120a6e
void DockWidget::mouseDoubleClickEvent(QMouseEvent *me) {
Shinya Kitaoka 120a6e
  if (!m_floating && isDragGrip(me->pos())) {
Shinya Kitaoka 120a6e
    parentLayout()->setMaximized(this, !m_maximized);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------
Toshihiro Shimizu 890ddd
shun_iwasawa 01efa1
void DockWidget::maximizeDock() {
shun_iwasawa 01efa1
  if (!m_floating) {
shun_iwasawa 01efa1
    parentLayout()->setMaximized(this, !m_maximized);
shun_iwasawa 01efa1
  }
Jeremy Bullock d07b20
}
Jeremy Bullock d07b20
Jeremy Bullock d07b20
//-------------------------------------
Shinya Kitaoka 120a6e
//! Switch in selected dock placeholder's hierarchy.
Shinya Kitaoka 120a6e
void DockWidget::wheelEvent(QWheelEvent *we) {
Shinya Kitaoka 120a6e
  if (m_dragging) {
Shinya Kitaoka 120a6e
    if (m_selectedPlace) {
Shinya Kitaoka 120a6e
      DockPlaceholder *newSelected =
Shinya Kitaoka 120a6e
          (we->delta() > 0)
Shinya Kitaoka 120a6e
              ? m_selectedPlace->parentPlaceholder()
Shinya Kitaoka 120a6e
              : m_selectedPlace->childPlaceholder(
Shinya Kitaoka 120a6e
                    parentWidget()->mapFromGlobal(we->globalPos()));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      if (newSelected != m_selectedPlace) {
Shinya Kitaoka 120a6e
        m_selectedPlace->hide();
Shinya Kitaoka 120a6e
        newSelected->show();
Shinya Kitaoka 120a6e
        m_selectedPlace = newSelected;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
//! Returns widget (separator or docked widget) containing input \point, or 0 if
Shinya Kitaoka 120a6e
//! none.
Shinya Kitaoka 120a6e
//! Convenience function combining parentLayout() and containerOf(\b point).
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
//!\b NOTE: Observe that, in any case, the use of QEnterEvents is discouraged
Shinya Kitaoka 38fd86
//! for this purpose:
Shinya Kitaoka 120a6e
//! remember that we forcedly remain within its boundaries when dragging a dock
Shinya Kitaoka 120a6e
//! widget;
Shinya Kitaoka 120a6e
//! instead, we are rather interested about entering the dock widgets *below*.
Shinya Kitaoka 120a6e
QWidget *DockWidget::hoveredWidget(QMouseEvent *me) {
Shinya Kitaoka 120a6e
  if (!m_parentLayout) return 0;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  QPoint point = parentWidget()->mapFromGlobal(me->globalPos());
Shinya Kitaoka 120a6e
  return m_parentLayout->containerOf(point);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
//! Returns adjacent placeholders to hovered widget. If hovered is a separator,
Shinya Kitaoka 120a6e
//! just return associated placeholder.
Shinya Kitaoka 120a6e
DockPlaceholder *DockWidget::placeAdjacentTo(DockWidget *dockWidget,
Shinya Kitaoka 120a6e
                                             int boundary) {
Shinya Kitaoka 120a6e
  Region *r = parentLayout()->find(dockWidget);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (((boundary == DockPlaceholder::left ||
Shinya Kitaoka 120a6e
        boundary == DockPlaceholder::right) &&
Shinya Kitaoka 120a6e
       r->getOrientation() == Region::horizontal) ||
Shinya Kitaoka 120a6e
      ((boundary == DockPlaceholder::top ||
Shinya Kitaoka 120a6e
        boundary == DockPlaceholder::bottom) &&
Shinya Kitaoka 120a6e
       r->getOrientation() == Region::vertical)) {
Shinya Kitaoka 120a6e
    // Placeholder is coherent with region orientation
Shinya Kitaoka 120a6e
    return r->placeholders().size() ? r->placeholder(boundary % 2) : 0;
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    // Search in parent region
Shinya Kitaoka 120a6e
    Region *parent = r->getParent();
Shinya Kitaoka 120a6e
    if (parent) {
Shinya Kitaoka 120a6e
      unsigned int i = parent->find(r);
Shinya Kitaoka 120a6e
      return parent->placeholders().size()
Shinya Kitaoka 120a6e
                 ? parent->placeholder(i + (boundary % 2))
Shinya Kitaoka 120a6e
                 : 0;
Shinya Kitaoka 120a6e
    } else {
Shinya Kitaoka 120a6e
      // No parent region - dockWidget is the only widget of the whole layout;
Shinya Kitaoka 120a6e
      // Then check the first 2 elements of placeholders vector.
Shinya Kitaoka 120a6e
      if (!m_placeholders[boundary % 2]->getParentRegion()) {
Shinya Kitaoka 120a6e
        return m_placeholders.size() ? m_placeholders[boundary % 2] : 0;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  return 0;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
//! Returns placeholder associated with input separator.
Shinya Kitaoka 120a6e
DockPlaceholder *DockWidget::placeOfSeparator(DockSeparator *sep) {
Shinya Kitaoka 120a6e
  Region *r = sep->getParentRegion();
Shinya Kitaoka 120a6e
  int idx   = sep->getIndex();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return r->placeholders().size() ? r->placeholder(idx + 1) : 0;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
//! Processes an input mouse event to select the active placeholder among the
Shinya Kitaoka 120a6e
//! possible ones
Shinya Kitaoka 120a6e
//! for \b this dock widget. The selected placeholder is also evidenced with
Shinya Kitaoka 120a6e
//! respect to the
Shinya Kitaoka 120a6e
//! other (or these are kept hidden) according to the body of this function.
Shinya Kitaoka 120a6e
void DockWidget::selectDockPlaceholder(QMouseEvent *me) {
Shinya Kitaoka 120a6e
  // const int inf= 1000000;
Shinya Kitaoka 120a6e
  DockPlaceholder *selected = 0;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Search placeholders cotaining muose position
Shinya Kitaoka 120a6e
  unsigned int i;
Shinya Kitaoka 120a6e
  for (i = 0; i < m_placeholders.size(); ++i) {
Shinya Kitaoka 120a6e
    if (m_placeholders[i]->geometry().contains(me->globalPos())) {
Shinya Kitaoka 120a6e
      selected = m_placeholders[i];
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // In order to avoid flickering
Shinya Kitaoka 120a6e
  if (m_selectedPlace != selected) {
Shinya Kitaoka 120a6e
    if (m_selectedPlace) m_selectedPlace->hide();
Shinya Kitaoka 120a6e
    if (selected) selected->show();
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  m_selectedPlace = selected;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//========================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------
Toshihiro Shimizu 890ddd
//    Dock Placeholders
Toshihiro Shimizu 890ddd
//-------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
inline QRect DockPlaceholder::parentGeometry() const {
Shinya Kitaoka 120a6e
  return m_region ? toRect(m_region->getGeometry())
Shinya Kitaoka 120a6e
                  : m_owner->parentLayout()->contentsRect();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
//! Assigns the geometry of \b this placeholder.
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
//! Once a placeholder is created, in response to a user window drag,
Shinya Kitaoka 120a6e
//! dock placeholders are calculated. After a placeholder is created,
Shinya Kitaoka 120a6e
//! its geometry is built according to this function. It is possible to
Shinya Kitaoka 120a6e
//! reimplement it in order to build custom placeholder styles.
Shinya Kitaoka 120a6e
inline void DockPlaceholder::buildGeometry() {
Shinya Kitaoka 120a6e
  QRect relativeToMainRect;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (m_separator)
Shinya Kitaoka 120a6e
    relativeToMainRect = m_separator->geometry();
Shinya Kitaoka 120a6e
  else {
Shinya Kitaoka 120a6e
    QRect parentRect   = parentGeometry();
Shinya Kitaoka 120a6e
    DockLayout *layout = m_owner->parentLayout();
Shinya Kitaoka 120a6e
    QRect mainRect     = layout->contentsRect();
Shinya Kitaoka 120a6e
    int sepWidth       = layout->spacing();
Shinya Kitaoka 38fd86
    int margin = 6;  // layout->margin();   //Purtroppo questa info e' assegnata
Shinya Kitaoka 120a6e
                     // prima delle Room...
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (isRoot()) {
Shinya Kitaoka 120a6e
      // Set the whole contents rect
Shinya Kitaoka 120a6e
      relativeToMainRect = parentRect;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      // Set a square at middle of parent geometry
Shinya Kitaoka 120a6e
      // QPoint center= parentRect.center();
Shinya Kitaoka 120a6e
      // relativeToMainRect= QRect(center - QPoint(50,50), center +
Shinya Kitaoka 120a6e
      // QPoint(50,50));
Shinya Kitaoka 120a6e
    } else if (getParentRegion() == 0 ||
Shinya Kitaoka 120a6e
               getParentRegion() == layout->rootRegion()) {
Shinya Kitaoka 120a6e
      // Outer insertion case
Shinya Kitaoka 120a6e
      switch (getAttribute()) {
Shinya Kitaoka 120a6e
        int leftBound, upperBound;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      case left:
Shinya Kitaoka 120a6e
        leftBound = parentRect.left() - margin;
Shinya Kitaoka 120a6e
        relativeToMainRect =
Shinya Kitaoka 120a6e
            QRect(leftBound, parentRect.top(), margin, parentRect.height());
Shinya Kitaoka 120a6e
        break;
Shinya Kitaoka 120a6e
      case right:
Shinya Kitaoka 120a6e
        leftBound = parentRect.right() + 1;
Shinya Kitaoka 120a6e
        relativeToMainRect =
Shinya Kitaoka 120a6e
            QRect(leftBound, parentRect.top(), margin, parentRect.height());
Shinya Kitaoka 120a6e
        break;
Shinya Kitaoka 120a6e
      case top:
Shinya Kitaoka 120a6e
        upperBound = parentRect.top() - margin;
Shinya Kitaoka 120a6e
        relativeToMainRect =
Shinya Kitaoka 120a6e
            QRect(parentRect.left(), upperBound, parentRect.width(), margin);
Shinya Kitaoka 120a6e
        break;
Shinya Kitaoka 120a6e
      default:
Shinya Kitaoka 120a6e
        upperBound = parentRect.bottom() + 1;
Shinya Kitaoka 120a6e
        relativeToMainRect =
Shinya Kitaoka 120a6e
            QRect(parentRect.left(), upperBound, parentRect.width(), margin);
Shinya Kitaoka 120a6e
        break;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    } else
Shinya Kitaoka 120a6e
      switch (getAttribute()) {
Shinya Kitaoka 120a6e
        int leftBound, upperBound;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      case left:
Shinya Kitaoka 120a6e
        leftBound = parentRect.left();
Shinya Kitaoka 120a6e
        relativeToMainRect =
Shinya Kitaoka 120a6e
            QRect(leftBound, parentRect.top(), sepWidth, parentRect.height());
Shinya Kitaoka 120a6e
        break;
Shinya Kitaoka 120a6e
      case right:
Shinya Kitaoka 120a6e
        leftBound = parentRect.right() - sepWidth + 1;
Shinya Kitaoka 120a6e
        relativeToMainRect =
Shinya Kitaoka 120a6e
            QRect(leftBound, parentRect.top(), sepWidth, parentRect.height());
Shinya Kitaoka 120a6e
        break;
Shinya Kitaoka 120a6e
      case top:
Shinya Kitaoka 120a6e
        upperBound = parentRect.top();
Shinya Kitaoka 120a6e
        relativeToMainRect =
Shinya Kitaoka 120a6e
            QRect(parentRect.left(), upperBound, parentRect.width(), sepWidth);
Shinya Kitaoka 120a6e
        break;
Shinya Kitaoka 120a6e
      default:
Shinya Kitaoka 120a6e
        upperBound = parentRect.bottom() - sepWidth + 1;
Shinya Kitaoka 120a6e
        relativeToMainRect =
Shinya Kitaoka 120a6e
            QRect(parentRect.left(), upperBound, parentRect.width(), sepWidth);
Shinya Kitaoka 120a6e
        break;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  QPoint topLeft =
Shinya Kitaoka 120a6e
      m_owner->parentWidget()->mapToGlobal(relativeToMainRect.topLeft());
Shinya Kitaoka 120a6e
  QPoint bottomRight =
Shinya Kitaoka 120a6e
      m_owner->parentWidget()->mapToGlobal(relativeToMainRect.bottomRight());
Shinya Kitaoka 120a6e
  setGeometry(QRect(topLeft, bottomRight));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
DockPlaceholder::DockPlaceholder(DockWidget *owner, Region *r, int idx,
Shinya Kitaoka 120a6e
                                 int attributes)
Shinya Kitaoka 120a6e
    : QWidget(owner)
Shinya Kitaoka 120a6e
    , m_owner(owner)
Shinya Kitaoka 120a6e
    , m_separator(0)
Shinya Kitaoka 120a6e
    , m_region(r)
Shinya Kitaoka 120a6e
    , m_idx(idx)
Shinya Kitaoka 120a6e
    , m_attributes(attributes) {
Shinya Kitaoka 120a6e
  setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Set separators
Shinya Kitaoka 120a6e
  if (r && idx && idx < (int)r->getChildList().size()) {
Shinya Kitaoka 120a6e
    m_separator = r->separators()[idx - 1];
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
inline DockSeparator *DockPlaceholder::getSeparator() const {
Shinya Kitaoka 120a6e
  return m_separator;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
//! Find the 'parent' of this placeholder (same side/orientation, on grandParent
Shinya Kitaoka 120a6e
//! region)
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
//! NOTE: If no grandParent exists \b this is the root, which is then returned.
Shinya Kitaoka 120a6e
DockPlaceholder *DockPlaceholder::parentPlaceholder() {
Shinya Kitaoka 120a6e
  // Placeholders covering a whole separator or roots have no parent (return
Shinya Kitaoka 120a6e
  // itself)
Shinya Kitaoka 120a6e
  if (m_attributes == sepHor || m_attributes == sepVert || isRoot())
Shinya Kitaoka 120a6e
    return this;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Now, check if owner Region has a parent.
Shinya Kitaoka 120a6e
  Region *grandParent;
Shinya Kitaoka 120a6e
  if (!m_region || !m_region->getParent()) return this;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if ((grandParent = m_region->getParent()->getParent())) {
Shinya Kitaoka 120a6e
    // Good, we finally have to search in grandParent's region our direct
Shinya Kitaoka 120a6e
    // parent.
Shinya Kitaoka 120a6e
    unsigned int idx = grandParent->find(m_region->getParent());
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // Since placeholders are built ordered, just use the found idx.
Shinya Kitaoka 120a6e
    if (m_attributes == left || m_attributes == top)
Shinya Kitaoka 120a6e
      return grandParent->placeholders().size() ? grandParent->placeholder(idx)
Shinya Kitaoka 120a6e
                                                : this;
Shinya Kitaoka 120a6e
    else
Shinya Kitaoka 120a6e
      return grandParent->placeholders().size()
Shinya Kitaoka 120a6e
                 ? grandParent->placeholder(idx + 1)
Shinya Kitaoka 120a6e
                 : this;
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    // GrandParent would be a new root. Then, take the first two possible
Shinya Kitaoka 120a6e
    // placeholders
Shinya Kitaoka 120a6e
    // of the entire dockWidget.
Shinya Kitaoka 120a6e
    if (m_owner->m_placeholders.size()) {
Shinya Kitaoka 120a6e
      DockPlaceholder *result = m_owner->m_placeholders[m_attributes % 2];
Shinya Kitaoka 120a6e
      if (!result->m_region) return result;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    return this;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
//! The opposite of parentPlaceholder() - but a point belonging to the child
Shinya Kitaoka 120a6e
//! region to be selected is requested as univoque key among all children.
Shinya Kitaoka 120a6e
DockPlaceholder *DockPlaceholder::childPlaceholder(QPoint p) {
Shinya Kitaoka 120a6e
  // Ensure this is not a root placeholder
Shinya Kitaoka 120a6e
  if (m_attributes == root) return this;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Define children list and ensure it is not void.
Shinya Kitaoka 120a6e
  Region *r;
Shinya Kitaoka 120a6e
  unsigned int i;
Shinya Kitaoka 120a6e
  bool lastExtremity;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (m_region) {
Shinya Kitaoka 120a6e
    if (!m_region->getChildList().size()) return this;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    // Search the subregion containing p
Shinya Kitaoka 120a6e
    for (i = 0; i < m_region->getChildList().size(); ++i)
Shinya Kitaoka 120a6e
      if (m_region->childRegion(i)->getGeometry().contains(p)) break;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    if (i == m_region->getChildList().size())
Shinya Kitaoka 120a6e
      return this;  // No subregion found...
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    lastExtremity = (m_idx > (int)i);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    // Ensure it has subRegions.
Shinya Kitaoka 120a6e
    r = m_region->childRegion(i);
Shinya Kitaoka 120a6e
    if (!r->getChildList().size()) return this;
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    r             = m_owner->parentLayout()->rootRegion();
Shinya Kitaoka 120a6e
    lastExtremity = m_attributes % 2;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Now, take the 'grandson' region as above.
Shinya Kitaoka 120a6e
  for (i = 0; i < r->getChildList().size(); ++i)
Shinya Kitaoka 120a6e
    if (r->childRegion(i)->getGeometry().contains(p)) break;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (i == r->getChildList().size()) return this;  // No subregion found...
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  r = r->childRegion(i);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Finally, return child placeholder found.
Shinya Kitaoka 120a6e
  return r->placeholders().size()
Shinya Kitaoka 120a6e
             ? lastExtremity ? r->placeholders().back()
Shinya Kitaoka 120a6e
                             : r->placeholders().front()
Shinya Kitaoka 120a6e
             : this;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
//! Returns greatest placeholder which contains this one.
Shinya Kitaoka 120a6e
inline DockPlaceholder *DockPlaceholder::greatestPlaceholder() {
Shinya Kitaoka 120a6e
  DockPlaceholder *old = this, *current = parentPlaceholder();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  while (current != old) {
Shinya Kitaoka 120a6e
    old     = current;
Shinya Kitaoka 120a6e
    current = old->parentPlaceholder();
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return current;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
//! Returns smallest placeholder contained by this one - a point belonging to
Shinya Kitaoka 120a6e
//! the child
Shinya Kitaoka 120a6e
//! region to be selected is requested as univoque key among all children.
Shinya Kitaoka 120a6e
inline DockPlaceholder *DockPlaceholder::smallestPlaceholder(QPoint p) {
Shinya Kitaoka 120a6e
  DockPlaceholder *old = this, *current = childPlaceholder(p);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  while (current != old) {
Shinya Kitaoka 120a6e
    old     = current;
Shinya Kitaoka 120a6e
    current = old->childPlaceholder(p);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return current;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//========================================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------
Toshihiro Shimizu 890ddd
//    Separators
Toshihiro Shimizu 890ddd
//------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
DockSeparator::DockSeparator(DockLayout *owner, bool orientation,
Shinya Kitaoka 120a6e
                             Region *parentRegion)
Shinya Kitaoka 120a6e
    : QWidget(owner->parentWidget())
Shinya Kitaoka 120a6e
    , m_owner(owner)
Shinya Kitaoka 120a6e
    , m_orientation(orientation)
Shinya Kitaoka 120a6e
    , m_parentRegion(parentRegion)
Shinya Kitaoka 120a6e
    , m_pressed(false) {
Shinya Kitaoka 120a6e
  setObjectName("DockSeparator");
Shinya Kitaoka 120a6e
  setWindowFlags(Qt::SubWindow);
Shinya Kitaoka 120a6e
  setAutoFillBackground(false);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Set appropriate widget cursor
Shinya Kitaoka 120a6e
  if (m_orientation == Region::horizontal)
Shinya Kitaoka 120a6e
    setCursor(Qt::SplitHCursor);
Shinya Kitaoka 120a6e
  else
Shinya Kitaoka 120a6e
    setCursor(Qt::SplitVCursor);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  show();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void DockSeparator::mousePressEvent(QMouseEvent *me) {
Shinya Kitaoka 120a6e
  m_pressed = true;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_oldPos = me->globalPos();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  const std::deque<dockseparator *=""> &sepList = m_parentRegion->separators();</dockseparator>
Shinya Kitaoka 120a6e
  const std::deque<region *=""> &childList      = m_parentRegion->getChildList();</region>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Find separated Regions (separator index)
Shinya Kitaoka 120a6e
  unsigned int i;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  for (i = 0; i < sepList.size(); ++i)
Shinya Kitaoka 120a6e
    if (sepList[i] == this) break;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Calculate bounds for separator shift
Shinya Kitaoka 120a6e
  // First ensure extremal sizes are recalculated
Shinya Kitaoka 120a6e
  m_parentRegion->calculateExtremalSizes();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  int sepWidth = m_owner->spacing();
Shinya Kitaoka 120a6e
  Region *r    = getParentRegion();
Shinya Kitaoka 120a6e
  double parentLeft, parentRight;
Shinya Kitaoka 120a6e
  int leftSepCount = m_index;
Shinya Kitaoka 120a6e
  int rightSepCount =
Shinya Kitaoka 120a6e
      r->separators().size() - leftSepCount;  // This sep included
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (m_orientation == Region::horizontal) {
Shinya Kitaoka 120a6e
    parentLeft  = r->getGeometry().left();
Shinya Kitaoka 120a6e
    parentRight = r->getGeometry().right();
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    parentLeft  = r->getGeometry().top();
Shinya Kitaoka 120a6e
    parentRight = r->getGeometry().bottom();
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Calculate left and right extremal sizes
Shinya Kitaoka 120a6e
  int j, leftMinSize = 0, rightMinSize = 0, leftMaxSize = 0, rightMaxSize = 0;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  for (j = 0; j <= m_index; ++j) {
Shinya Kitaoka 120a6e
    leftMinSize += r->childRegion(j)->getMinimumSize(m_orientation);
Shinya Kitaoka 120a6e
    leftMaxSize += r->childRegion(j)->getMaximumSize(m_orientation);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  int size = r->getChildList().size();
Shinya Kitaoka 120a6e
  for (j = m_index + 1; j < size; ++j) {
Shinya Kitaoka 120a6e
    rightMinSize += r->childRegion(j)->getMinimumSize(m_orientation);
Shinya Kitaoka 120a6e
    rightMaxSize += r->childRegion(j)->getMaximumSize(m_orientation);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Sull'intera regione padre
Shinya Kitaoka 120a6e
  m_leftBound = std::max(parentLeft + leftMinSize + leftSepCount * sepWidth,
Shinya Kitaoka 120a6e
                         parentRight - rightMaxSize - rightSepCount * sepWidth);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_rightBound =
Shinya Kitaoka 120a6e
      std::min(parentLeft + leftMaxSize + leftSepCount * sepWidth,
Shinya Kitaoka 120a6e
               parentRight - rightMinSize - rightSepCount * sepWidth);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
inline void DockSeparator::mouseReleaseEvent(QMouseEvent *me) {
Shinya Kitaoka 120a6e
  m_pressed = false;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void DockSeparator::mouseMoveEvent(QMouseEvent *me) {
Shinya Kitaoka 120a6e
  if (m_pressed) {
Shinya Kitaoka 120a6e
    double movedPosition, newPosition;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (m_orientation == Region::horizontal) {
Shinya Kitaoka 120a6e
      double dx = me->globalX() - m_oldPos.x();
Shinya Kitaoka 120a6e
      movedPosition =
Shinya Kitaoka 120a6e
          getParentRegion()->childRegion(m_index)->getGeometry().right() + dx;
Shinya Kitaoka 120a6e
      newPosition =
Shinya Kitaoka 120a6e
          std::min(std::max(movedPosition, m_leftBound), m_rightBound);
Shinya Kitaoka 120a6e
      dx += newPosition - movedPosition;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      if (dx) {
Shinya Kitaoka 120a6e
        Region *r;
Shinya Kitaoka 120a6e
        QRectF newGeometry;
Shinya Kitaoka 120a6e
        double newWidth, dxTemp = dx;
Shinya Kitaoka 120a6e
        int i;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        // Propagate dx in left-adjacent regions
Shinya Kitaoka 120a6e
        for (i = m_index; dx != 0 && i >= 0; --i) {
Shinya Kitaoka 120a6e
          r           = getParentRegion()->childRegion(i);
Shinya Kitaoka 120a6e
          newGeometry = r->getGeometry();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
          // Right margin is shifted by dx
Shinya Kitaoka 120a6e
          newGeometry.adjust(0, 0, dx, 0);
Shinya Kitaoka 120a6e
          newWidth = newGeometry.width();
Shinya Kitaoka 120a6e
          // New width absorbs part of dx according to constraints
Shinya Kitaoka 120a6e
          newWidth = std::min(
Shinya Kitaoka 120a6e
              std::max(newWidth, (double)r->getMinimumSize(Region::horizontal)),
Shinya Kitaoka 120a6e
              (double)r->getMaximumSize(Region::horizontal));
Shinya Kitaoka 120a6e
          newGeometry.adjust(dx = newGeometry.width() - newWidth, 0, 0, 0);
Shinya Kitaoka 120a6e
          r->setGeometry(newGeometry);
Shinya Kitaoka 120a6e
          r->redistribute();
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        dx       = dxTemp;
Shinya Kitaoka 120a6e
        int size = getParentRegion()->getChildList().size();
Shinya Kitaoka 120a6e
        // Propagate dx in right-adjacent regions
Shinya Kitaoka 120a6e
        for (i = m_index + 1; dx != 0 && i < size; ++i) {
Shinya Kitaoka 120a6e
          r           = getParentRegion()->childRegion(i);
Shinya Kitaoka 120a6e
          newGeometry = r->getGeometry();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
          newGeometry.adjust(dx, 0, 0, 0);
Shinya Kitaoka 120a6e
          newWidth = newGeometry.width();
Shinya Kitaoka 120a6e
          newWidth = std::min(
Shinya Kitaoka 120a6e
              std::max(newWidth, (double)r->getMinimumSize(Region::horizontal)),
Shinya Kitaoka 120a6e
              (double)r->getMaximumSize(Region::horizontal));
Shinya Kitaoka 120a6e
          newGeometry.adjust(0, 0, dx = newWidth - newGeometry.width(), 0);
Shinya Kitaoka 120a6e
          r->setGeometry(newGeometry);
Shinya Kitaoka 120a6e
          r->redistribute();
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        m_owner->update();
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    } else {
Shinya Kitaoka 120a6e
      double dy = me->globalY() - m_oldPos.y();
Shinya Kitaoka 120a6e
      movedPosition =
Shinya Kitaoka 120a6e
          getParentRegion()->childRegion(m_index)->getGeometry().bottom() + dy;
Shinya Kitaoka 120a6e
      newPosition =
Shinya Kitaoka 120a6e
          std::min(std::max(movedPosition, m_leftBound), m_rightBound);
Shinya Kitaoka 120a6e
      dy += newPosition - movedPosition;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      if (dy) {
Shinya Kitaoka 120a6e
        Region *r;
Shinya Kitaoka 120a6e
        QRectF newGeometry;
Shinya Kitaoka 120a6e
        double newHeight, dyTemp = dy;
Shinya Kitaoka 120a6e
        int i;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        for (i = m_index; dy != 0 && i >= 0; --i) {
Shinya Kitaoka 120a6e
          r                  = getParentRegion()->childRegion(i);
Shinya Kitaoka 120a6e
          newGeometry        = r->getGeometry();
Shinya Kitaoka 120a6e
          QRectF oldGeometry = newGeometry;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
          newGeometry.adjust(0, 0, 0, dy);
Shinya Kitaoka 120a6e
          newHeight = newGeometry.height();
Shinya Kitaoka 120a6e
          newHeight = std::min(
Shinya Kitaoka 120a6e
              std::max(newHeight, (double)r->getMinimumSize(Region::vertical)),
Shinya Kitaoka 120a6e
              (double)r->getMaximumSize(Region::vertical));
Shinya Kitaoka 120a6e
          newGeometry.adjust(0, dy = newGeometry.height() - newHeight, 0, 0);
Shinya Kitaoka 120a6e
          r->setGeometry(newGeometry);
Shinya Kitaoka 120a6e
          r->redistribute();
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        dy       = dyTemp;
Shinya Kitaoka 120a6e
        int size = getParentRegion()->getChildList().size();
Shinya Kitaoka 120a6e
        for (i = m_index + 1; dy != 0 && i < size; ++i) {
Shinya Kitaoka 120a6e
          r           = getParentRegion()->childRegion(i);
Shinya Kitaoka 120a6e
          newGeometry = r->getGeometry();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
          newGeometry.adjust(0, dy, 0, 0);
Shinya Kitaoka 120a6e
          newHeight = newGeometry.height();
Shinya Kitaoka 120a6e
          newHeight = std::min(
Shinya Kitaoka 120a6e
              std::max(newHeight, (double)r->getMinimumSize(Region::vertical)),
Shinya Kitaoka 120a6e
              (double)r->getMaximumSize(Region::vertical));
Shinya Kitaoka 120a6e
          newGeometry.adjust(0, 0, 0, dy = newHeight - newGeometry.height());
Shinya Kitaoka 120a6e
          r->setGeometry(newGeometry);
Shinya Kitaoka 120a6e
          r->redistribute();
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        m_owner->update();
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    m_oldPos = QPoint(me->globalX(), me->globalY());
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//========================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------
Toshihiro Shimizu 890ddd
//    Available geometries code
Toshihiro Shimizu 890ddd
//----------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
namespace {
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
// Finds the closest mouse point belonging to some available geometry.
Shinya Kitaoka 120a6e
void getClosestAvailableMousePosition(QPoint &globalPos) {
Shinya Kitaoka 120a6e
  // Search the screen rect containing the mouse position
Shinya Kitaoka 120a6e
  int i, screens = desktop->numScreens();
Shinya Kitaoka 120a6e
  for (i = 0; i < screens; ++i)
Shinya Kitaoka 120a6e
    if (desktop->screenGeometry(i).contains(globalPos)) break;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Find the closest point to the corresponding available region
Shinya Kitaoka 120a6e
  QRect rect(desktop->availableGeometry(i));
Shinya Kitaoka 120a6e
  if (rect.contains(globalPos)) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Return the closest point to the available geometry
Shinya Kitaoka 120a6e
  QPoint result;
Shinya Kitaoka 120a6e
  if (globalPos.x() < rect.left())
Shinya Kitaoka 120a6e
    globalPos.setX(rect.left());
Shinya Kitaoka 120a6e
  else if (globalPos.x() > rect.right())
Shinya Kitaoka 120a6e
    globalPos.setX(rect.right());
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (globalPos.y() < rect.top())
Shinya Kitaoka 120a6e
    globalPos.setY(rect.top());
Shinya Kitaoka 120a6e
  else if (globalPos.y() > rect.bottom())
Shinya Kitaoka 120a6e
    globalPos.setY(rect.bottom());
Shinya Kitaoka 120a6e
}
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
}  // Local namespace