You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
kvirc/src/kvirc/ui/kvi_mdimanager.cpp

1127 lines
32 KiB

//=============================================================================
//
// File : kvi_mdimanager.cpp
// Creation date : Wed Jun 21 2000 17:28:04 by Szymon Stefanek
//
// This file is part of the KVirc irc client distribution
// Copyright (C) 2000-2003 Szymon Stefanek (pragma at kvirc dot net)
//
// 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 opinion) 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. ,51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
//=============================================================================
#define __KVIRC__
#include "kvi_debug.h"
#include "kvi_settings.h"
#include "kvi_mdimanager.h"
#include "kvi_mdichild.h"
#include "kvi_locale.h"
#include "kvi_options.h"
#include "kvi_iconmanager.h"
#include "kvi_frame.h"
#include "kvi_menubar.h"
#include "kvi_mdicaption.h"
#include "kvi_app.h"
#include "kvi_tal_popupmenu.h"
#include <tqmenubar.h>
#include <tqlayout.h>
#include <tqpainter.h>
#include <math.h>
#include <tqcursor.h>
#include <tqdrawutil.h>
#include <tqevent.h>
#ifdef COMPILE_USE_QT4
#include "kvi_tal_hbox.h"
#endif
#ifdef COMPILE_PSEUDO_TRANSPARENCY
#include <tqpixmap.h>
extern TQPixmap * g_pShadedParentGlobalDesktopBackground;
#endif
KviMdiManager::KviMdiManager(TQWidget * parent,KviFrame * pFrm,const char * name)
: KviTalScrollView(parent)
{
setFrameShape(NoFrame);
m_pZ = new KviPointerList<KviMdiChild>;
m_pZ->setAutoDelete(true);
m_pFrm = pFrm;
m_iSdiIconItemId = 0;
m_iSdiCloseItemId = 0;
m_iSdiRestoreItemId = 0;
m_iSdiMinimizeItemId = 0;
m_pSdiIconButton = 0;
m_pSdiCloseButton = 0;
m_pSdiRestoreButton = 0;
m_pSdiMinimizeButton = 0;
#ifdef COMPILE_USE_QT4
m_pSdiControls = 0;
#endif
m_pWindowPopup = new KviTalPopupMenu(this);
connect(m_pWindowPopup,TQT_SIGNAL(activated(int)),this,TQT_SLOT(menuActivated(int)));
connect(m_pWindowPopup,TQT_SIGNAL(aboutToShow()),this,TQT_SLOT(fillWindowPopup()));
m_pTileMethodPopup = new KviTalPopupMenu(this);
connect(m_pTileMethodPopup,TQT_SIGNAL(activated(int)),this,TQT_SLOT(tileMethodMenuActivated(int)));
#ifdef COMPILE_USE_QT4
viewport()->setAutoFillBackground(false);
#else
viewport()->setBackgroundMode(TQWidget::NoBackground);
#endif
setStaticBackground(true);
resizeContents(width(),height());
#ifdef COMPILE_USE_QT4
setFocusPolicy(TQ_NoFocus);
viewport()->setFocusPolicy(TQ_NoFocus);
#else
setFocusPolicy(TQ_NoFocus);
viewport()->setFocusPolicy(TQ_NoFocus);
#endif
connect(g_pApp,TQT_SIGNAL(reloadImages()),this,TQT_SLOT(reloadImages()));
}
KviMdiManager::~KviMdiManager()
{
delete m_pZ;
}
void KviMdiManager::reloadImages()
{
for(KviMdiChild * c = m_pZ->first();c;c = m_pZ->next())
{
c->reloadImages();
}
}
bool KviMdiManager::focusNextPrevChild(bool bNext)
{
//bug("FFFFFF");
// this is a TQScrollView bug... it doesn't pass this
// event to the toplevel window
return m_pFrm->focusNextPrevChild(bNext);
}
void KviMdiManager::drawContents(TQPainter *p,int x,int y,int w,int h)
{
//tqDebug("MY DRAW CONTENTS (%d,%d,%d,%d)",x,y,w,h);
TQRect r(x,y,w,h);
#ifdef COMPILE_PSEUDO_TRANSPARENCY
if(g_pShadedParentGlobalDesktopBackground)
{
TQPoint pnt = viewport()->mapToGlobal(contentsToViewport(r.topLeft()));
p->drawTiledPixmap(r,*(g_pShadedParentGlobalDesktopBackground),pnt);
return;
}
#endif
if(KVI_OPTION_PIXMAP(KviOption_pixmapMdiBackground).pixmap())
{
p->drawTiledPixmap(r,*(KVI_OPTION_PIXMAP(KviOption_pixmapMdiBackground).pixmap()));
} else {
p->fillRect(r,KVI_OPTION_COLOR(KviOption_colorMdiBackground));
}
}
void KviMdiManager::manageChild(KviMdiChild * lpC,bool bCascade,TQRect *setGeom)
{
__range_valid(lpC);
m_pZ->insert(0,lpC); //hidden -> last in the Z order
if(bCascade)
{
TQPoint p = getCascadePoint(m_pZ->count()-1);
addChild(lpC,p.x(),p.y());
} else {
// FIXME: is this right ?
TQPoint p = lpC->pos();
if(p.x() < 0)p.setX(0);
if(p.y() < 0)p.setY(0);
addChild(lpC,p.x(),p.y());
if(setGeom)
{
if(setGeom->left() < 0)setGeom->setLeft(0);
if(setGeom->top() < 0)setGeom->setTop(0);
moveChild(lpC,setGeom->x(),setGeom->y());
lpC->setGeometry(*setGeom);
}
}
if(KVI_OPTION_BOOL(KviOption_boolAutoTileWindows))tile();
}
void KviMdiManager::showAndActivate(KviMdiChild * lpC)
{
lpC->show();
setTopChild(lpC,true);
if(KVI_OPTION_BOOL(KviOption_boolAutoTileWindows))tile();
}
void KviMdiManager::setTopChild(KviMdiChild *lpC,bool bSetFocus)
{
__range_valid(lpC);
// The following check fails safely at startup....
// __range_valid(lpC->isVisible() || lpC->testWState(WState_ForceHide));
KviMdiChild * pOldTop = m_pZ->last();
if(pOldTop != lpC)
{
m_pZ->setAutoDelete(false);
if(!m_pZ->removeRef(lpC))
{
m_pZ->setAutoDelete(true);
return; // no such child ?
}
// disable the labels of all the other children
//for(KviMdiChild *pC=m_pZ->first();pC;pC=m_pZ->next())
//{
// pC->captionLabel()->setActive(false);
//}
KviMdiChild * pMaximizedChild = pOldTop;
if(pOldTop)
{
pOldTop->captionLabel()->setActive(false);
if(pOldTop->m_state != KviMdiChild::Maximized)pMaximizedChild=0;
}
m_pZ->setAutoDelete(true);
m_pZ->append(lpC);
if(pMaximizedChild)lpC->maximize(); //do not animate the change
lpC->raise();
if(pMaximizedChild)pMaximizedChild->restore();
}
if(bSetFocus)
{
if(!lpC->hasFocus())
{
lpC->setFocus();
/*
if(topLevelWidget()->isActiveWindow())
{
}
*/
}
}
}
void KviMdiManager::focusInEvent(TQFocusEvent *)
{
focusTopChild();
}
void KviMdiManager::destroyChild(KviMdiChild *lpC,bool bFocusTopChild)
{
bool bWasMaximized = lpC->state() == KviMdiChild::Maximized;
disconnect(lpC);
lpC->blockSignals(true);
#ifdef _KVI_DEBUG_CHECK_RANGE_
//Report invalid results in a debug session
__range_valid(m_pZ->removeRef(lpC));
#else
m_pZ->removeRef(lpC);
#endif
if(bWasMaximized)
{
KviMdiChild * c=topChild();
if(c)
{
if(c->state() != KviMdiChild::Minimized)c->maximize();
else {
// minimized top child...the last one
leaveSDIMode();
}
} else {
// SDI state change
leaveSDIMode();
}
}
if(bFocusTopChild)focusTopChild();
if(KVI_OPTION_BOOL(KviOption_boolAutoTileWindows))tile();
updateContentsSize();
}
KviMdiChild * KviMdiManager::highestChildExcluding(KviMdiChild * pChild)
{
KviMdiChild * c = m_pZ->last();
while(c && (c == pChild))c = m_pZ->prev();
return c;
}
TQPoint KviMdiManager::getCascadePoint(int indexOfWindow)
{
TQPoint pnt(0,0);
if(indexOfWindow==0)return pnt;
KviMdiChild *lpC=m_pZ->first();
int step=(lpC ? (lpC->captionLabel()->heightHint()+KVI_MDICHILD_BORDER) : 20);
int availableHeight=viewport()->height()-(lpC ? lpC->minimumSize().height() : KVI_MDICHILD_MIN_HEIGHT);
int availableWidth=viewport()->width()-(lpC ? lpC->minimumSize().width() : KVI_MDICHILD_MIN_WIDTH);
int ax=0;
int ay=0;
for(int i=0;i<indexOfWindow;i++)
{
ax+=step;
ay+=step;
if(ax>availableWidth)ax=0;
if(ay>availableHeight)ay=0;
}
pnt.setX(ax);
pnt.setY(ay);
return pnt;
}
void KviMdiManager::mousePressEvent(TQMouseEvent *e)
{
//Popup the window menu
if(e->button() & Qt::RightButton)m_pWindowPopup->popup(mapToGlobal(e->pos()));
}
void KviMdiManager::childMoved(KviMdiChild *)
{
updateContentsSize();
}
void KviMdiManager::maximizeChild(KviMdiChild * lpC)
{
// the children must be moved once by the means of TQScrollView::moveChild()
// so the TQScrollView internal structures get updated with the negative
// position of the widget, otherwise, when restoring with moveChild()
// it will refuse to move it back to the original position
resizeContents(visibleWidth(),visibleHeight());
updateScrollBars();
g_pApp->sendPostedEvents();
if(g_pApp->closingDown())return;
moveChild(lpC,-KVI_MDICHILD_HIDDEN_EDGE,
-(KVI_MDICHILD_HIDDEN_EDGE + KVI_MDICHILD_SPACING + lpC->m_pCaption->heightHint()));
lpC->setGeometry(
-KVI_MDICHILD_HIDDEN_EDGE,
-(KVI_MDICHILD_HIDDEN_EDGE + KVI_MDICHILD_SPACING + lpC->m_pCaption->heightHint()),
viewport()->width() + (KVI_MDICHILD_HIDDEN_EDGE * 2), //KVI_MDICHILD_DOUBLE_HIDDEN_EDGE,
viewport()->height() + (KVI_MDICHILD_HIDDEN_EDGE * 2) + lpC->m_pCaption->heightHint() + KVI_MDICHILD_SPACING);
if(isInSDIMode())updateSDIMode();
else {
enterSDIMode(lpC);
// make sure that the child is focused
lpC->setFocus();
}
// fixme: we could hide all the other children now!
}
void KviMdiManager::resizeEvent(TQResizeEvent *e)
{
//If we have a maximized children at the top , adjust its size
KviTalScrollView::resizeEvent(e);
KviMdiChild *lpC=m_pZ->last();
if(lpC)
{
if(lpC->state()==KviMdiChild::Maximized)
{
// SDI mode
lpC->resize(viewport()->width() + (KVI_MDICHILD_HIDDEN_EDGE * 2),
viewport()->height() + lpC->m_pCaption->heightHint() + (KVI_MDICHILD_HIDDEN_EDGE * 2) + KVI_MDICHILD_SPACING);
return;
} else {
if(KVI_OPTION_BOOL(KviOption_boolAutoTileWindows))tile();
}
}
updateContentsSize();
}
/*
void KviMdiManager::childMaximized(KviMdiChild * lpC)
{
if(lpC == m_pZ->last())
{
enterSDIMode(lpC);
}
updateContentsSize();
}
*/
void KviMdiManager::childMinimized(KviMdiChild * lpC,bool bWasMaximized)
{
__range_valid(lpC);
if(m_pZ->findRef(lpC) == -1)return;
if(m_pZ->count() > 1)
{
m_pZ->setAutoDelete(false);
#ifdef _KVI_DEBUG_CHECK_RANGE_
//Report invalid results in a debug session
__range_valid(m_pZ->removeRef(lpC));
#else
m_pZ->removeRef(lpC);
#endif
m_pZ->setAutoDelete(true);
m_pZ->insert(0,lpC);
if(bWasMaximized)
{
// Need to maximize the top child
lpC = m_pZ->last();
if(!lpC)return; //??
if(lpC->state()==KviMdiChild::Minimized)
{
if(bWasMaximized)leaveSDIMode();
return;
}
lpC->maximize(); //do nrot animate the change
} else {
if(KVI_OPTION_BOOL(KviOption_boolAutoTileWindows))tile();
}
focusTopChild();
} else {
// Unique window minimized...it won't loose the focus...!!
setFocus(); //Remove focus from the child
if(bWasMaximized)leaveSDIMode();
}
updateContentsSize();
}
void KviMdiManager::childRestored(KviMdiChild * lpC,bool bWasMaximized)
{
if(bWasMaximized)
{
if(lpC != m_pZ->last())return; // do nothing in this case
leaveSDIMode();
updateContentsSize();
}
if(KVI_OPTION_BOOL(KviOption_boolAutoTileWindows))tile();
}
void KviMdiManager::focusTopChild()
{
KviMdiChild *lpC=m_pZ->last();
if(!lpC)return;
if(!lpC->isVisible())return;
// if(lpC->state()==KviMdiChild::Minimized)return;
// tqDebug("Focusing top child %s",lpC->name());
//disable the labels of all the other children
for(KviMdiChild *pC=m_pZ->first();pC;pC=m_pZ->next())
{
if(pC != lpC)
pC->captionLabel()->setActive(false);
}
lpC->raise();
if(!lpC->hasFocus())lpC->setFocus();
}
void KviMdiManager::minimizeActiveChild()
{
KviMdiChild * lpC = m_pZ->last();
if(!lpC)return;
if(lpC->state() != KviMdiChild::Minimized)lpC->minimize();
}
void KviMdiManager::restoreActiveChild()
{
KviMdiChild * lpC = m_pZ->last();
if(!lpC)return;
if(lpC->state() == KviMdiChild::Maximized)lpC->restore();
}
void KviMdiManager::closeActiveChild()
{
KviMdiChild * lpC = m_pZ->last();
if(!lpC)return;
lpC->closeRequest();
}
void KviMdiManager::updateContentsSize()
{
KviMdiChild * c = m_pZ->last();
if(c)
{
if(c->state() == KviMdiChild::Maximized)
{
return;
}
}
int fw = frameWidth() * 2;
int mx = width() - fw;
int my = height() - fw;
for(c = m_pZ->first();c;c = m_pZ->next())
{
if(c->isVisible())
{
int x = childX(c) + c->width();
if(x > mx)mx = x;
int y = childY(c) + c->height();
if(y > my)my = y;
}
}
resizeContents(mx,my);
}
void KviMdiManager::updateSDIMode()
{
KviMdiChild * lpC = m_pZ->last();
if(m_pSdiCloseButton)
m_pSdiCloseButton->setEnabled(lpC ? lpC->closeEnabled() : false);
// This would result in an addictional main menu bar entry on MacOSX which would trigger a popup menu and not
// a submenu. Due to the optical reasons it is removed here.
// The same popup is triggered by right clicking on the window name in the channel window list.
#ifndef Q_OS_MACX
KviMenuBar * b = m_pFrm->mainMenuBar();
const TQPixmap * pix = lpC ? lpC->icon() : 0;
if(!pix)pix = g_pIconManager->getSmallIcon(KVI_SMALLICON_NONE);
else if(pix->isNull())pix = g_pIconManager->getSmallIcon(KVI_SMALLICON_NONE);
if(!m_pSdiIconButton)
{
m_pSdiIconButton = new KviMenuBarToolButton(b,*pix,"nonne");
connect(m_pSdiIconButton,TQT_SIGNAL(clicked()),this,TQT_SLOT(activeChildSystemPopup()));
#ifdef COMPILE_USE_QT4
// This is an obscure, undocumented and internal function in QT4 TQMenuBar
// I won't be surprised if this disappears....
b->setCornerWidget(m_pSdiIconButton,TQt::TopLeftCorner);
m_pSdiIconButton->show();
#else
m_iSdiIconItemId = b->insertItem(m_pSdiIconButton,-1,0);
#endif
connect(m_pSdiIconButton,TQT_SIGNAL(destroyed()),this,TQT_SLOT(sdiIconButtonDestroyed()));
} else {
m_pSdiIconButton->setPixmap(*pix);
}
#endif //Q_OS_MACX
}
void KviMdiManager::activeChildSystemPopup()
{
KviMdiChild * lpC = m_pZ->last();
if(!lpC)return;
TQPoint pnt;
if(m_pSdiIconButton)
{
pnt = m_pSdiIconButton->mapToGlobal(TQPoint(0,m_pSdiIconButton->height()));
} else {
pnt = TQCursor::pos();
}
lpC->emitSystemPopupRequest(pnt);
}
bool KviMdiManager::isInSDIMode()
{
return (m_pSdiCloseButton != 0);
}
void KviMdiManager::enterSDIMode(KviMdiChild *lpC)
{
if(!m_pSdiCloseButton)
{
KviMenuBar * b = m_pFrm->mainMenuBar();
TQWidget * pButtonParent;
#ifdef COMPILE_USE_QT4
m_pSdiControls = new KviTalHBox(b);
m_pSdiControls->setMargin(0);
m_pSdiControls->setSpacing(2);
m_pSdiControls->setAutoFillBackground(false);
pButtonParent = m_pSdiControls;
#else
pButtonParent = b;
#endif
m_pSdiMinimizeButton = new KviMenuBarToolButton(pButtonParent,*(g_pIconManager->getSmallIcon(KVI_SMALLICON_MINIMIZE)),"btnminimize");
connect(m_pSdiMinimizeButton,TQT_SIGNAL(clicked()),this,TQT_SLOT(minimizeActiveChild()));
#ifndef COMPILE_USE_QT4
m_iSdiMinimizeItemId = b->insertItem(m_pSdiMinimizeButton,-1,b->count());
#endif
connect(m_pSdiMinimizeButton,TQT_SIGNAL(destroyed()),this,TQT_SLOT(sdiMinimizeButtonDestroyed()));
m_pSdiRestoreButton = new KviMenuBarToolButton(pButtonParent,*(g_pIconManager->getSmallIcon(KVI_SMALLICON_RESTORE)),"btnrestore");
connect(m_pSdiRestoreButton,TQT_SIGNAL(clicked()),this,TQT_SLOT(restoreActiveChild()));
#ifndef COMPILE_USE_QT4
m_iSdiRestoreItemId = b->insertItem(m_pSdiRestoreButton,-1,b->count());
#endif
connect(m_pSdiRestoreButton,TQT_SIGNAL(destroyed()),this,TQT_SLOT(sdiRestoreButtonDestroyed()));
m_pSdiCloseButton = new KviMenuBarToolButton(pButtonParent,*(g_pIconManager->getSmallIcon(KVI_SMALLICON_CLOSE)),"btnclose");
connect(m_pSdiCloseButton,TQT_SIGNAL(clicked()),this,TQT_SLOT(closeActiveChild()));
#ifndef COMPILE_USE_QT4
m_iSdiCloseItemId = b->insertItem(m_pSdiCloseButton,-1,b->count());
#endif
connect(m_pSdiCloseButton,TQT_SIGNAL(destroyed()),this,TQT_SLOT(sdiCloseButtonDestroyed()));
#ifdef COMPILE_USE_QT4
// This is an obscure, undocumented and internal function in QT4 TQMenuBar
// I won't be surprised if this disappears....
b->setCornerWidget(m_pSdiControls,TQt::TopRightCorner);
// The show below SHOULD force a re-layout of the menubar..
// but it doesn't work when the KviFrame is still hidden (at startup)
// We handle this BUG in showEvent()
m_pSdiControls->show();
#else
m_pSdiRestoreButton->show();
m_pSdiMinimizeButton->show();
m_pSdiCloseButton->show();
#endif
emit enteredSdiMode();
setVScrollBarMode(KviTalScrollView::AlwaysOff);
setHScrollBarMode(KviTalScrollView::AlwaysOff);
}
updateSDIMode();
}
void KviMdiManager::relayoutMenuButtons()
{
#ifdef COMPILE_USE_QT4
// force a re-layout of the menubar in TQt4 (see the note in enterSDIMode())
// by resetting the corner widget
if(m_pSdiControls)
{
m_pFrm->mainMenuBar()->setCornerWidget(0,TQt::TopRightCorner);
m_pFrm->mainMenuBar()->setCornerWidget(m_pSdiControls,TQt::TopRightCorner);
}
// also force an activation of the top MdiChild since it probably didn't get it yet
KviMdiChild * c = topChild();
if(c)
c->activate(false);
#endif
}
void KviMdiManager::sdiIconButtonDestroyed()
{
m_iSdiIconItemId = 0;
m_pSdiIconButton = 0;
}
void KviMdiManager::sdiMinimizeButtonDestroyed()
{
m_iSdiMinimizeItemId = 0;
m_pSdiMinimizeButton = 0;
}
void KviMdiManager::sdiRestoreButtonDestroyed()
{
m_iSdiRestoreItemId = 0;
m_pSdiRestoreButton = 0;
}
void KviMdiManager::sdiCloseButtonDestroyed()
{
m_iSdiCloseItemId = 0;
m_pSdiCloseButton = 0;
}
void KviMdiManager::leaveSDIMode()
{
__range_valid(m_pSdiCloseButton);
#ifdef COMPILE_USE_QT4
if(m_pSdiControls)
{
delete m_pSdiControls;
m_pSdiControls = 0;
}
if(m_pSdiIconButton)
{
m_pSdiIconButton->hide(); // this will force a TQMenuBar relayout
delete m_pSdiIconButton;
m_pSdiIconButton = 0;
}
#else
if(m_iSdiIconItemId != 0)m_pFrm->mainMenuBar()->removeItem(m_iSdiIconItemId);
if(m_iSdiCloseItemId != 0)m_pFrm->mainMenuBar()->removeItem(m_iSdiCloseItemId);
if(m_iSdiRestoreItemId != 0)m_pFrm->mainMenuBar()->removeItem(m_iSdiRestoreItemId);
if(m_iSdiMinimizeItemId != 0)m_pFrm->mainMenuBar()->removeItem(m_iSdiMinimizeItemId);
#endif
setVScrollBarMode(KviTalScrollView::Auto);
setHScrollBarMode(KviTalScrollView::Auto);
emit leftSdiMode();
}
#define KVI_TILE_METHOD_ANODINE 0
#define KVI_TILE_METHOD_PRAGMA4HOR 1
#define KVI_TILE_METHOD_PRAGMA4VER 2
#define KVI_TILE_METHOD_PRAGMA6HOR 3
#define KVI_TILE_METHOD_PRAGMA6VER 4
#define KVI_TILE_METHOD_PRAGMA9HOR 5
#define KVI_TILE_METHOD_PRAGMA9VER 6
#define KVI_NUM_TILE_METHODS 7
void KviMdiManager::fillWindowPopup()
{
m_pWindowPopup->clear();
m_pWindowPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_CASCADEWINDOWS)),(__tr2qs("&Cascade Windows")),this,TQT_SLOT(cascadeWindows()));
m_pWindowPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_CASCADEWINDOWS)),(__tr2qs("Cascade &Maximized")),this,TQT_SLOT(cascadeMaximized()));
m_pWindowPopup->insertSeparator();
m_pWindowPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_TILEWINDOWS)),(__tr2qs("&Tile Windows")),this,TQT_SLOT(tile()));
m_pTileMethodPopup->clear();
int id = m_pTileMethodPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_AUTOTILEWINDOWS)),(__tr2qs("&Auto Tile")),this,TQT_SLOT(toggleAutoTile()));
m_pTileMethodPopup->setItemChecked(id,KVI_OPTION_BOOL(KviOption_boolAutoTileWindows));
m_pTileMethodPopup->setItemParameter(id,-1);
m_pTileMethodPopup->insertSeparator();
int ids[KVI_NUM_TILE_METHODS];
ids[KVI_TILE_METHOD_ANODINE] = m_pTileMethodPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_TILEWINDOWS)),(__tr2qs("Anodine's Full Grid")));
m_pTileMethodPopup->setItemParameter(ids[KVI_TILE_METHOD_ANODINE],KVI_TILE_METHOD_ANODINE);
ids[KVI_TILE_METHOD_PRAGMA4HOR] = m_pTileMethodPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_TILEWINDOWS)),(__tr2qs("Pragma's Horizontal 4-Grid")));
m_pTileMethodPopup->setItemParameter(ids[KVI_TILE_METHOD_PRAGMA4HOR],KVI_TILE_METHOD_PRAGMA4HOR);
ids[KVI_TILE_METHOD_PRAGMA4VER] = m_pTileMethodPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_TILEWINDOWS)),(__tr2qs("Pragma's Vertical 4-Grid")));
m_pTileMethodPopup->setItemParameter(ids[KVI_TILE_METHOD_PRAGMA4VER],KVI_TILE_METHOD_PRAGMA4VER);
ids[KVI_TILE_METHOD_PRAGMA6HOR] = m_pTileMethodPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_TILEWINDOWS)),(__tr2qs("Pragma's Horizontal 6-Grid")));
m_pTileMethodPopup->setItemParameter(ids[KVI_TILE_METHOD_PRAGMA6HOR],KVI_TILE_METHOD_PRAGMA6HOR);
ids[KVI_TILE_METHOD_PRAGMA6VER] = m_pTileMethodPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_TILEWINDOWS)),(__tr2qs("Pragma's Vertical 6-Grid")));
m_pTileMethodPopup->setItemParameter(ids[KVI_TILE_METHOD_PRAGMA6VER],KVI_TILE_METHOD_PRAGMA6VER);
ids[KVI_TILE_METHOD_PRAGMA9HOR] = m_pTileMethodPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_TILEWINDOWS)),(__tr2qs("Pragma's Horizontal 9-Grid")));
m_pTileMethodPopup->setItemParameter(ids[KVI_TILE_METHOD_PRAGMA9HOR],KVI_TILE_METHOD_PRAGMA9HOR);
ids[KVI_TILE_METHOD_PRAGMA9VER] = m_pTileMethodPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_TILEWINDOWS)),(__tr2qs("Pragma's Vertical 9-Grid")));
m_pTileMethodPopup->setItemParameter(ids[KVI_TILE_METHOD_PRAGMA9VER],KVI_TILE_METHOD_PRAGMA9VER);
if(KVI_OPTION_UINT(KviOption_uintTileMethod) >= KVI_NUM_TILE_METHODS)KVI_OPTION_UINT(KviOption_uintTileMethod) = KVI_TILE_METHOD_PRAGMA9HOR;
m_pTileMethodPopup->setItemChecked(ids[KVI_OPTION_UINT(KviOption_uintTileMethod)],true);
m_pWindowPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_TILEWINDOWS)),(__tr2qs("Tile Met&hod")),m_pTileMethodPopup);
m_pWindowPopup->insertSeparator();
m_pWindowPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_MAXVERTICAL)),(__tr2qs("Expand &Vertically")),this,TQT_SLOT(expandVertical()));
m_pWindowPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_MAXHORIZONTAL)),(__tr2qs("Expand &Horizontally")),this,TQT_SLOT(expandHorizontal()));
m_pWindowPopup->insertSeparator();
m_pWindowPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_MINIMIZE)),(__tr2qs("Mi&nimize All")),this,TQT_SLOT(minimizeAll()));
// m_pWindowPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_RESTORE)),(__tr2qs("&Restore all")),this,TQT_SLOT(restoreAll()));
//
m_pWindowPopup->insertSeparator();
int i=100;
TQString szItem;
TQString szCaption;
for(KviMdiChild *lpC=m_pZ->first();lpC;lpC=m_pZ->next())
{
szItem.setNum(((uint)i)-99);
szItem+=". ";
szCaption = lpC->plainCaption();
if(szCaption.length() > 30)
{
TQString trail = szCaption.right(12);
szCaption.truncate(12);
szCaption+="...";
szCaption+=trail;
}
if(lpC->state()==KviMdiChild::Minimized)
{
szItem+="(";
szItem+=szCaption;
szItem+=")";
} else szItem+=szCaption;
const TQPixmap * pix = lpC->icon();
if(pix && !(pix->isNull()))m_pWindowPopup->insertItem(*pix,szItem,i);
else m_pWindowPopup->insertItem(szItem,i);
m_pWindowPopup->setItemChecked(i,((uint)i)==(m_pZ->count()+99));
i++;
}
}
void KviMdiManager::menuActivated(int id)
{
if(id<100)return;
id-=100;
__range_valid(((uint)id) < m_pZ->count());
KviMdiChild *lpC=m_pZ->at(id);
if(!lpC)return;
if(lpC->state()==KviMdiChild::Minimized)lpC->restore();
setTopChild(lpC,true);
}
void KviMdiManager::ensureNoMaximized()
{
KviMdiChild * lpC;
for(lpC=m_pZ->first();lpC;lpC=m_pZ->next())
{
if(lpC->state()==KviMdiChild::Maximized)lpC->restore();
}
}
void KviMdiManager::tileMethodMenuActivated(int id)
{
int idx = m_pTileMethodPopup->itemParameter(id);
if(idx < 0)idx = 0;
if(idx >= KVI_NUM_TILE_METHODS)idx = KVI_TILE_METHOD_PRAGMA9VER;
KVI_OPTION_UINT(KviOption_uintTileMethod) = idx;
if(KVI_OPTION_BOOL(KviOption_boolAutoTileWindows))tile();
}
void KviMdiManager::cascadeWindows()
{
ensureNoMaximized();
// this hack is needed to ensure that the scrollbars are hidden and the viewport()->width() and height() are correct
resizeContents(visibleWidth(),visibleHeight());
updateScrollBars();
g_pApp->sendPostedEvents();
if(g_pApp->closingDown())return;
int idx=0;
KviPointerList<KviMdiChild> list(*m_pZ);
list.setAutoDelete(false);
while(!list.isEmpty())
{
KviMdiChild *lpC=list.first();
if(lpC->state() != KviMdiChild::Minimized)
{
TQPoint p = getCascadePoint(idx);
moveChild(lpC,p.x(),p.y());
lpC->resize(lpC->sizeHint());
idx++;
}
list.removeFirst();
}
focusTopChild();
updateContentsSize();
}
void KviMdiManager::cascadeMaximized()
{
ensureNoMaximized();
// this hack is needed to ensure that the scrollbars are hidden and the viewport()->width() and height() are correct
resizeContents(visibleWidth(),visibleHeight());
updateScrollBars();
g_pApp->sendPostedEvents();
if(g_pApp->closingDown())return;
int idx=0;
KviPointerList<KviMdiChild> list(*m_pZ);
list.setAutoDelete(false);
while(!list.isEmpty())
{
KviMdiChild *lpC=list.first();
if(lpC->state() != KviMdiChild::Minimized)
{
TQPoint pnt(getCascadePoint(idx));
moveChild(lpC,pnt.x(),pnt.y());
TQSize curSize(viewport()->width() - pnt.x(),viewport()->height() - pnt.y());
if((lpC->minimumSize().width() > curSize.width()) ||
(lpC->minimumSize().height() > curSize.height()))lpC->resize(lpC->minimumSize());
else lpC->resize(curSize);
idx++;
}
list.removeFirst();
}
focusTopChild();
updateContentsSize();
}
void KviMdiManager::expandVertical()
{
ensureNoMaximized();
// this hack is needed to ensure that the scrollbars are hidden and the viewport()->width() and height() are correct
resizeContents(visibleWidth(),visibleHeight());
updateScrollBars();
g_pApp->sendPostedEvents();
if(g_pApp->closingDown())return;
KviPointerList<KviMdiChild> list(*m_pZ);
list.setAutoDelete(false);
while(!list.isEmpty())
{
KviMdiChild *lpC=list.first();
if(lpC->state() != KviMdiChild::Minimized)
{
moveChild(lpC,lpC->x(),0);
lpC->resize(lpC->width(),viewport()->height());
}
list.removeFirst();
}
focusTopChild();
updateContentsSize();
}
void KviMdiManager::expandHorizontal()
{
ensureNoMaximized();
// this hack is needed to ensure that the scrollbars are hidden and the viewport()->width() and height() are correct
resizeContents(visibleWidth(),visibleHeight());
updateScrollBars();
g_pApp->sendPostedEvents();
if(g_pApp->closingDown())return;
KviPointerList<KviMdiChild> list(*m_pZ);
list.setAutoDelete(false);
while(!list.isEmpty())
{
KviMdiChild *lpC=list.first();
if(lpC->state() != KviMdiChild::Minimized)
{
moveChild(lpC,0,lpC->y());
lpC->resize(viewport()->width(),lpC->height());
}
list.removeFirst();
}
focusTopChild();
updateContentsSize();
}
void KviMdiManager::minimizeAll()
{
KviPointerList<KviMdiChild> list(*m_pZ);
list.setAutoDelete(false);
m_pFrm->setActiveWindow((KviWindow*)m_pFrm->firstConsole());
while(!list.isEmpty())
{
KviMdiChild *lpC=list.first();
if(lpC->state() != KviMdiChild::Minimized)lpC->minimize();
list.removeFirst();
}
focusTopChild();
updateContentsSize();
}
/*
void KviMdiManager::restoreAll()
{
int idx=0;
KviPointerList<KviMdiChild> list(*m_pZ);
list.setAutoDelete(false);
while(!list.isEmpty())
{
KviMdiChild *lpC=list.first();
if(lpC->state() != KviMdiChild::Normal && (!(lpC->plainCaption()).contains("CONSOLE") ))
lpC->restore();
list.removeFirst();
}
focusTopChild();
updateContentsSize();
}
*/
int KviMdiManager::getVisibleChildCount()
{
int cnt=0;
for(KviMdiChild *lpC=m_pZ->first();lpC;lpC=m_pZ->next())
{
if(lpC->state() != KviMdiChild::Minimized)cnt++;
}
return cnt;
}
void KviMdiManager::tile()
{
switch(KVI_OPTION_UINT(KviOption_uintTileMethod))
{
case KVI_TILE_METHOD_ANODINE: tileAnodine(); break;
case KVI_TILE_METHOD_PRAGMA4HOR: tileAllInternal(4,true); break;
case KVI_TILE_METHOD_PRAGMA4VER: tileAllInternal(4,false); break;
case KVI_TILE_METHOD_PRAGMA6HOR: tileAllInternal(6,true); break;
case KVI_TILE_METHOD_PRAGMA6VER: tileAllInternal(6,false); break;
case KVI_TILE_METHOD_PRAGMA9HOR: tileAllInternal(9,true); break;
case KVI_TILE_METHOD_PRAGMA9VER: tileAllInternal(9,false); break;
default:
KVI_OPTION_UINT(KviOption_uintTileMethod) = KVI_TILE_METHOD_PRAGMA9HOR;
tileAllInternal(9,true);
break;
}
}
void KviMdiManager::toggleAutoTile()
{
if(KVI_OPTION_BOOL(KviOption_boolAutoTileWindows))
{
KVI_OPTION_BOOL(KviOption_boolAutoTileWindows) = false;
} else {
KVI_OPTION_BOOL(KviOption_boolAutoTileWindows) = true;
tile();
}
}
void KviMdiManager::tileAllInternal(int maxWnds,bool bHorizontal)
{
//NUM WINDOWS = 1,2,3,4,5,6,7,8,9
static int colstable[9]={ 1,1,1,2,2,2,3,3,3 }; //num columns
static int rowstable[9]={ 1,2,3,2,3,3,3,3,3 }; //num rows
static int lastwindw[9]={ 1,1,1,1,2,1,3,2,1 }; //last window multiplier
static int colrecall[9]={ 0,0,0,3,3,3,6,6,6 }; //adjust self
static int rowrecall[9]={ 0,0,0,0,4,4,4,4,4 }; //adjust self
int * pColstable = bHorizontal ? colstable : rowstable;
int * pRowstable = bHorizontal ? rowstable : colstable;
int * pColrecall = bHorizontal ? colrecall : rowrecall;
int * pRowrecall = bHorizontal ? rowrecall : colrecall;
ensureNoMaximized();
// this hack is needed to ensure that the scrollbars are hidden and the viewport()->width() and height() are correct
resizeContents(visibleWidth(),visibleHeight());
updateScrollBars();
g_pApp->sendPostedEvents();
if(g_pApp->closingDown())return;
KviMdiChild *lpTop=topChild();
int numVisible=getVisibleChildCount();
if(numVisible<1)return;
int numToHandle=((numVisible > maxWnds) ? maxWnds : numVisible);
int xQuantum=viewport()->width()/pColstable[numToHandle-1];
if(xQuantum < ((lpTop->minimumSize().width() > KVI_MDICHILD_MIN_WIDTH) ? lpTop->minimumSize().width() : KVI_MDICHILD_MIN_WIDTH)){
if(pColrecall[numToHandle-1]==0)tqDebug("Tile : Not enouh space");
else tileAllInternal(pColrecall[numToHandle-1],bHorizontal);
return;
}
int yQuantum=viewport()->height()/pRowstable[numToHandle-1];
if(yQuantum < ((lpTop->minimumSize().height() > KVI_MDICHILD_MIN_HEIGHT) ? lpTop->minimumSize().height() : KVI_MDICHILD_MIN_HEIGHT)){
if(pRowrecall[numToHandle-1]==0)tqDebug("Tile : Not enough space");
else tileAllInternal(pRowrecall[numToHandle-1],bHorizontal);
return;
}
int curX=0;
int curY=0;
int curRow=1;
int curCol=1;
int curWin=1;
for(KviMdiChild * lpC=m_pZ->first();lpC;lpC=m_pZ->next())
{
if(lpC->state()!=KviMdiChild::Minimized)
{
if((curWin%numToHandle)==0)
{
moveChild(lpC,curX,curY);
lpC->resize(xQuantum * lastwindw[numToHandle-1],yQuantum);
} else {
moveChild(lpC,curX,curY);
lpC->resize(xQuantum,yQuantum);
}
//example : 12 windows : 3 cols 3 rows
if(curCol<pColstable[numToHandle-1])
{ //curCol<3
curX+=xQuantum; //add a column in the same row
curCol++; //increase current column
} else {
curX=0; //new row
curCol=1; //column 1
if(curRow<pRowstable[numToHandle-1])
{ //curRow<3
curY+=yQuantum; //add a row
curRow++; //
} else {
curY=0; //restart from beginning
curRow=1; //
}
}
curWin++;
}
}
if(lpTop)lpTop->setFocus();
updateContentsSize();
}
void KviMdiManager::tileAnodine()
{
ensureNoMaximized();
// this hack is needed to ensure that the scrollbars are hidden and the viewport()->width() and height() are correct
resizeContents(visibleWidth(),visibleHeight());
updateScrollBars();
g_pApp->sendPostedEvents();
if(g_pApp->closingDown())return;
KviMdiChild *lpTop=topChild();
int numVisible=getVisibleChildCount(); // count visible windows
if(numVisible<1)return;
int numCols=int(sqrt((double)numVisible)); // set columns to square root of visible count
// create an array to form grid layout
int *numRows=new int[numCols];
int numCurCol=0;
while(numCurCol<numCols)
{
numRows[numCurCol]=numCols; // create primary grid values
numCurCol++;
}
int numDiff=numVisible-(numCols*numCols); // count extra rows
int numCurDiffCol=numCols; // set column limiting for grid updates
while(numDiff>0)
{
numCurDiffCol--;
numRows[numCurDiffCol]++; // add extra rows to column grid
if(numCurDiffCol<1)numCurDiffCol=numCols; // rotate through the grid
numDiff--;
}
numCurCol=0;
int numCurRow=0;
int curX=0;
int curY=0;
// the following code will size everything based on my grid above
// there is no limit to the number of windows it will handle
// it's great when a kick-ass theory works!!! // Pragma :)
int xQuantum=viewport()->width()/numCols;
int yQuantum=viewport()->height()/numRows[numCurCol];
for(KviMdiChild * lpC=m_pZ->first();lpC;lpC=m_pZ->next())
{
if(lpC->state() != KviMdiChild::Minimized)
{
moveChild(lpC,curX,curY);
lpC->resize(xQuantum,yQuantum);
numCurRow++;
curY+=yQuantum;
if(numCurRow==numRows[numCurCol])
{
numCurRow=0;
numCurCol++;
curY=0;
curX+=xQuantum;
if(numCurCol!=numCols)yQuantum=viewport()->height()/numRows[numCurCol];
}
}
}
delete[] numRows;
if(lpTop)lpTop->setFocus();
updateContentsSize();
}