aboutsummaryrefslogblamecommitdiff
path: root/src/dock.cpp
blob: 2dc06463927afa1dd9b537fd5c9e94adbd20e012 (plain) (tree)














































































































































































































































                                                                                                         





                                                                
/***************************************************************************
 *   Copyright (C) 2006 by Ilya Kotov                                      *
 *   forkotov02@hotmail.ru                                                 *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

#include <QAction>

#include "dock.h"


Dock *Dock::pointer = 0;

Dock *Dock::getPointer()
{
   if ( !pointer )
      pointer = new Dock();
   return pointer;
}

Dock::Dock ( QObject *parent )
      : QObject ( parent )
{
   pointer = this;
   m_mainWidget = 0;
}

Dock::~Dock()
{}

void Dock::setMainWidget ( QWidget *widget )
{
   m_mainWidget = widget;
   m_widgetList.prepend ( widget );
   m_dockedList.prepend ( FALSE );
}


QPoint Dock::snap ( QPoint npos, QWidget* mv, QWidget* st )
{
   int nx = npos.x() - st->x();
   int ny = abs ( npos.y() - st->y() + mv->height() );

   if ( abs ( nx ) < 15 && ny < 15 ) //above
      npos.rx() = st->x();
   if ( ny < 15 && nx > -mv->width() && nx < st->width() )
      npos.ry() = st->y() - mv->height();
   nx = abs ( npos.x() + mv->width() - st->x() - st->width() );
   if ( nx < 15 && ny < 15 )
      npos.rx() = st->x() + st->width() - mv->width();

   /***********/
   nx = npos.x() - st->x();
   ny = abs ( npos.y() - st->y() - st->height() );

   if ( abs ( nx ) < 15 && ny < 15 ) //near
      npos.rx() = st->x();
   if ( ny < 15 && nx > -mv->width() && nx < st->width() )
      npos.ry() = st->y() + st->height();
   nx = abs ( npos.x() + mv->width() - st->x() - st->width() );
   if ( nx < 15 && ny < 15 )
      npos.rx() = st->x() + st->width() - mv->width();
   /**************/
   nx = abs ( npos.x() - st->x() + mv->width() );
   ny = npos.y() - st->y();

   if ( nx < 15 && abs ( ny ) < 15 ) //left
      npos.ry() = st->y();
   if ( nx < 15 && ny > -mv->height() && ny < st->height() )
      npos.rx() = st->x() - mv->width();

   ny = abs ( npos.y() + mv->height() - st->y() - st->height() );
   if ( nx < 15 && ny < 15 )
      npos.ry() = st->y() + st->height() - mv->height();
   /*****************/
   nx = abs ( npos.x() - st->x() - st->width() );
   ny = npos.y() - st->y();

   if ( nx < 15 && abs ( ny ) < 15 ) //right
      npos.ry() = st->y();
   if ( nx < 15 && ny > -mv->height() && ny < st->height() )
      npos.rx() = st->x() + st->width();

   ny = abs ( npos.y() + mv->height() - st->y() - st->height() );
   if ( nx < 15 && ny < 15 )
      npos.ry() = st->y() + st->height() - mv->height();

   return ( npos );
}

void Dock::addWidget ( QWidget *widget )
{
   m_widgetList.append ( widget );
   m_dockedList.append ( FALSE );
   widget->addActions(m_actions);

}

void Dock::move ( QWidget* mv, QPoint npos )
{
   if ( mv == m_mainWidget )
   {

      for ( int i = 1; i<m_widgetList.size(); ++i )
      {
         if ( !m_dockedList.at ( i ) )
         {
            if ( m_widgetList.at ( i )->isVisible() )
               npos = snap ( npos, mv, m_widgetList.at ( i ) );

         }
         else
         {
            QPoint pos = QPoint ( npos.x() + x_list.at ( i ),
                                  npos.y() + y_list.at ( i ) );
            for ( int j = 1; j<m_widgetList.size(); ++j )
            {
               if ( !m_dockedList.at ( j ) && m_widgetList.at ( j )->isVisible() )
               {
                  pos = snap ( pos, m_widgetList.at ( i ), m_widgetList.at ( j ) );
                  npos = QPoint ( pos.x() - x_list.at ( i ),
                                  pos.y() - y_list.at ( i ) );
               }
            }
         }
      }
      mv->move ( npos );
      for ( int i = 1; i<m_widgetList.size(); ++i )
      {
         if ( m_dockedList.at ( i ) )
            m_widgetList.at ( i )->move ( npos.x() + x_list.at ( i ),
                                          npos.y() + y_list.at ( i ) );
      }
   }
   else
   {
      for ( int i = 0; i<m_widgetList.size(); ++i )
      {
         m_dockedList[i] = FALSE;
         if ( mv!=m_widgetList.at ( i ) && !m_dockedList.at ( i ) && m_widgetList.at ( i )->isVisible() )
         {
            npos = snap ( npos, mv, m_widgetList.at ( i ) );
         }
      }
      mv->move ( npos );
   }
}

void Dock::calculateDistances()
{
   x_list.clear();
   y_list.clear();
   foreach ( QWidget *w, m_widgetList )
   {
      if ( w!=m_mainWidget )
      {
         x_list.append ( - m_mainWidget->x() + w->x() );
         y_list.append ( - m_mainWidget->y() + w->y() );
      }
      else
      {
         x_list.prepend ( 0 );
         y_list.prepend ( 0 );
      }
   }
}

void Dock::updateDock()
{
   QWidget *mv = m_widgetList.at ( 0 );
   for ( int j = 1; j<m_widgetList.size(); ++j )
   {
      QWidget *st = m_widgetList.at ( j );
      m_dockedList[j] = isDocked ( mv, st );
   }
   for ( int j = 1; j<m_widgetList.size(); ++j )
   {
      if ( m_dockedList[j] )
         for ( int i = 1; i<m_widgetList.size(); ++i )
         {
            if ( !m_dockedList[i] )
            {
               mv = m_widgetList.at ( j );
               QWidget *st = m_widgetList.at ( i );
               m_dockedList[i] = isDocked ( mv, st );
            }
         }
   }

}

bool Dock::isDocked ( QWidget* mv, QWidget* st )
{
   int nx = mv->x() - st->x();
   int ny = abs ( mv->y() - st->y() + mv->height() );
   if ( ny < 2 && nx > -mv->width() && nx < st->width() ) //above
      return TRUE;

   /***********/
   nx = mv->x() - st->x();
   ny = abs ( mv->y() - st->y() - st->height() );
   if ( ny < 2 && nx > -mv->width() && nx < st->width() ) //near
      return TRUE;

   /**************/
   nx = abs ( mv->x() - st->x() + mv->width() );
   ny = mv->y() - st->y();
   if ( nx < 2 && ny > -mv->height() && ny < st->height() )   //left
      return TRUE;

   /*****************/
   nx = abs ( mv->x() - st->x() - st->width() );
   ny = mv->y() - st->y();
   if ( nx < 2 && ny > -mv->height() && ny < st->height() )   //right
      return TRUE;
   return FALSE;
}

void Dock::addActions ( QList<QAction *> actions )
{
   m_actions << actions;
   for ( int i = 0; i<m_widgetList.size(); ++i )
      m_widgetList.at ( i )->addActions ( actions );
}

bool Dock::isUnder(QWidget* upper, QWidget* nether)
{
    if (!isDocked(upper, nether))
        return FALSE;
    return abs (upper->y() + upper->height() - nether->y()) < 2;
}