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