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.
426 lines
16 KiB
426 lines
16 KiB
/* This file is part of the KOffice project
|
|
* Copyright (C) 2005 Thomas Zander <zander@kde.org>
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Library General Public
|
|
* License as published by the Free Software Foundation; version 2.
|
|
|
|
* This library 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
|
|
* Library General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Library General Public License
|
|
* along with this library; see the file COPYING.LIB. If not, write to
|
|
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
* Boston, MA 02110-1301, USA.
|
|
*/
|
|
#include "KWDocument.h"
|
|
#include "KWFrameViewManager.h"
|
|
#include <KWFrameView.h>
|
|
#include <KWFrame.h>
|
|
#include <KWFrameSet.h>
|
|
|
|
#include <kdebug.h>
|
|
#include <kcursor.h>
|
|
#include <tqcursor.h>
|
|
#include <tqtimer.h>
|
|
#include "tqpopupmenu.h"
|
|
#include <algorithm>
|
|
|
|
KWFrameViewManager::KWFrameViewManager() : TQObject() {
|
|
setName("KWFrameViewManager");
|
|
m_queueRequested = false;
|
|
m_blockEvents = false;
|
|
}
|
|
|
|
KWFrameViewManager::KWFrameViewManager(KWDocument *doc) {
|
|
m_queueRequested = false;
|
|
m_blockEvents = true;
|
|
TQPtrListIterator<KWFrameSet> frameSets = doc->framesetsIterator();
|
|
while(frameSets.current()) {
|
|
slotFrameSetAdded(*frameSets);
|
|
++frameSets;
|
|
}
|
|
m_blockEvents = false;
|
|
connect(doc, TQT_SIGNAL( sigFrameSetAdded(KWFrameSet*)), TQT_SLOT( slotFrameSetAdded(KWFrameSet*)));
|
|
connect(doc, TQT_SIGNAL( sigFrameSetRemoved(KWFrameSet*)), TQT_SLOT( slotFrameSetRemoved(KWFrameSet*)));
|
|
recalculateFrameCache();
|
|
}
|
|
|
|
KWFrameViewManager::~KWFrameViewManager() {
|
|
TQValueListIterator<FrameEvent *> events = m_frameEvents.begin();
|
|
while(events != m_frameEvents.end()) {
|
|
delete (*events);
|
|
++events;
|
|
}
|
|
}
|
|
|
|
void KWFrameViewManager::addKWFramesListener(KWFramesListener *listener) {
|
|
m_framesListener.append(listener);
|
|
}
|
|
void KWFrameViewManager::removeKWFramesListener(KWFramesListener *listener) {
|
|
m_framesListener.remove(listener);
|
|
}
|
|
|
|
void KWFrameViewManager::slotFrameSetAdded(KWFrameSet *fs) {
|
|
if(! m_blockEvents)
|
|
m_frameEvents.append(new FrameEvent(FrameEvent::FrameSetAdded, fs));
|
|
connect(fs, TQT_SIGNAL( sigFrameAdded(KWFrame*)), TQT_SLOT( slotFrameAdded(KWFrame *)));
|
|
connect(fs, TQT_SIGNAL( sigFrameRemoved(KWFrame*)), TQT_SLOT( slotFrameRemoved(KWFrame *)));
|
|
connect(fs, TQT_SIGNAL( sigNameChanged(KWFrameSet*)), TQT_SLOT( slotFrameSetRenamed(KWFrameSet *)));
|
|
TQPtrListIterator<KWFrame> frames = fs->frameIterator();
|
|
while(frames.current()) {
|
|
KWFrame *f = frames.current();
|
|
slotFrameAdded(f);
|
|
++frames;
|
|
}
|
|
requestFireEvents();
|
|
}
|
|
void KWFrameViewManager::slotFrameSetRemoved(KWFrameSet *fs) {
|
|
if(! m_blockEvents)
|
|
m_frameEvents.append(new FrameEvent(FrameEvent::FrameSetRemoved, fs));
|
|
disconnect(fs, TQT_SIGNAL( sigFrameAdded(KWFrame*)), this, TQT_SLOT( slotFrameAdded(KWFrame *)));
|
|
disconnect(fs, TQT_SIGNAL( sigFrameRemoved(KWFrame*)), this, TQT_SLOT( slotFrameRemoved(KWFrame *)));
|
|
disconnect(fs, TQT_SIGNAL( sigNameChanged(KWFrameSet*)), this, TQT_SLOT( slotFrameSetRenamed(KWFrameSet *)));
|
|
TQPtrListIterator<KWFrame> frames = fs->frameIterator();
|
|
while(frames.current()) {
|
|
KWFrame *f = frames.current();
|
|
slotFrameRemoved(f);
|
|
++frames;
|
|
}
|
|
requestFireEvents();
|
|
}
|
|
void KWFrameViewManager::slotFrameAdded(KWFrame *f) {
|
|
if(! m_blockEvents)
|
|
m_frameEvents.append(new FrameEvent(FrameEvent::FrameAdded, f));
|
|
m_frames.append(new KWFrameView(this, f));
|
|
requestFireEvents();
|
|
}
|
|
void KWFrameViewManager::slotFrameRemoved(KWFrame *f) {
|
|
if(! m_blockEvents)
|
|
m_frameEvents.append(new FrameEvent(FrameEvent::FrameRemoved, f));
|
|
TQValueListIterator<KWFrameView *> frames = m_frames.begin();
|
|
while(frames != m_frames.end()) {
|
|
KWFrameView *fv = *frames;
|
|
if(fv->frame() == f) {
|
|
if(fv->selected())
|
|
m_frameEvents.append(new FrameEvent(FrameEvent::FrameSelectionChanged));
|
|
m_frames.remove(frames);
|
|
delete fv;
|
|
break;
|
|
}
|
|
++frames;
|
|
}
|
|
requestFireEvents();
|
|
}
|
|
void KWFrameViewManager::slotFrameMoved(KWFrame *f, double previousYPosition) {
|
|
Q_UNUSED(previousYPosition); // to be used for the page caches to mark them dirty
|
|
if(! m_blockEvents)
|
|
m_frameEvents.append(new FrameEvent(FrameEvent::FrameMoved, f));
|
|
// TODO; KWFrameList update??
|
|
// update our caches..
|
|
requestFireEvents();
|
|
}
|
|
void KWFrameViewManager::slotFrameResized(KWFrame *f) {
|
|
if(! m_blockEvents)
|
|
m_frameEvents.append(new FrameEvent(FrameEvent::FrameResized, f));
|
|
// update our caches..
|
|
requestFireEvents();
|
|
}
|
|
void KWFrameViewManager::slotFrameSelectionChanged() {
|
|
if(! m_blockEvents)
|
|
m_frameEvents.append(new FrameEvent(FrameEvent::FrameSelectionChanged));
|
|
// update our caches..
|
|
requestFireEvents();
|
|
}
|
|
|
|
void KWFrameViewManager::slotFrameSetRenamed(KWFrameSet *fs) {
|
|
if(! m_blockEvents)
|
|
m_frameEvents.append(new FrameEvent(FrameEvent::FrameSetRenamed, fs));
|
|
requestFireEvents();
|
|
}
|
|
|
|
void KWFrameViewManager::requestFireEvents() {
|
|
if(m_queueRequested && !m_blockEvents)
|
|
return;
|
|
m_queueRequested = true;
|
|
TQTimer::singleShot ( 0, this, TQT_SLOT(fireEvents()) );
|
|
}
|
|
|
|
void KWFrameViewManager::fireEvents() {
|
|
m_queueRequested = false;
|
|
if(m_frameEvents.isEmpty())
|
|
return;
|
|
recalculateFrameCache();
|
|
|
|
TQValueList<FrameEvent *> copy(m_frameEvents);
|
|
m_frameEvents.clear();
|
|
|
|
TQValueList<KWFrame*> resizedFrames;
|
|
TQValueList<KWFrame*> movedFrames;
|
|
TQValueList<KWFramesListener *> listenersCopy(m_framesListener);
|
|
bool selectionChangedFired=false;
|
|
|
|
TQValueListIterator<FrameEvent *> events = copy.begin();
|
|
while(events != copy.end()) {
|
|
FrameEvent *event = *events;
|
|
|
|
// emit based.
|
|
if(!selectionChangedFired && event->m_action == FrameEvent::FrameSelectionChanged) {
|
|
emit sigFrameSelectionChanged();
|
|
selectionChangedFired = true; // only fire ones.
|
|
} else if(event->m_action == FrameEvent::FrameSetRenamed) {
|
|
TQPtrListIterator<KWFrame> frames = event->m_frameSet->frameIterator();
|
|
for(;frames.current();++frames) {
|
|
if(view(frames.current())->selected()) {
|
|
emit sigFrameSetRenamed();
|
|
break;
|
|
}
|
|
}
|
|
} else if(event->m_action == FrameEvent::FrameResized) {
|
|
resizedFrames.append(event->m_frame);
|
|
} else if(event->m_action == FrameEvent::FrameMoved) {
|
|
movedFrames.append(event->m_frame);
|
|
}
|
|
|
|
// listener based
|
|
TQValueListIterator<KWFramesListener *> listeners = listenersCopy.begin();
|
|
while(listeners != listenersCopy.end()) {
|
|
if(event->m_action == FrameEvent::FrameRemoved)
|
|
(*listeners)->frameRemoved(event->m_frame);
|
|
else if(event->m_action == FrameEvent::FrameAdded)
|
|
(*listeners)->frameAdded(event->m_frame);
|
|
else if(event->m_action == FrameEvent::FrameSetRemoved)
|
|
(*listeners)->frameSetRemoved(event->m_frameSet);
|
|
else if(event->m_action == FrameEvent::FrameSetAdded)
|
|
(*listeners)->frameSetAdded(event->m_frameSet);
|
|
++listeners;
|
|
}
|
|
|
|
delete event;
|
|
events = copy.remove(events);
|
|
}
|
|
if(resizedFrames.count() > 0)
|
|
emit sigFrameResized(resizedFrames);
|
|
if(movedFrames.count() > 0)
|
|
emit sigFrameMoved(movedFrames);
|
|
}
|
|
|
|
void KWFrameViewManager::recalculateFrameCache() {
|
|
// TODO :) design and implement a cache...
|
|
// list of frames sorted on y-coord, with an additional list containing a jump-index
|
|
kdDebug(31001) << "recalculateFrameCache " << m_frames.count() << " frames are currently registred" << endl;
|
|
}
|
|
|
|
KWFrameView *KWFrameViewManager::view(const KoPoint &point, SelectionType selected, bool borderOnly) const {
|
|
TQValueVector<KWFrameView*> framesThatAreHit = framesAt(point, borderOnly);
|
|
bool foundCycleFrame = false;
|
|
TQValueVector<KWFrameView*>::iterator sortedFrames = framesThatAreHit.begin();
|
|
while(sortedFrames != framesThatAreHit.end()) {
|
|
if(selected == nextUnselected) {
|
|
if((*sortedFrames)->selected() )
|
|
foundCycleFrame = true;
|
|
else if(foundCycleFrame && !(*sortedFrames)->selected() )
|
|
return *sortedFrames;
|
|
}
|
|
else if(selected == frameOnTop)
|
|
return *sortedFrames;
|
|
else { // not cycle, so simply a selected check.
|
|
if((*sortedFrames)->selected() == (selected == KWFrameViewManager::selected ))
|
|
return *sortedFrames;
|
|
}
|
|
++sortedFrames;
|
|
}
|
|
if(selected == nextUnselected && framesThatAreHit.count() > 0)
|
|
return framesThatAreHit[0];
|
|
return 0;
|
|
}
|
|
|
|
TQValueVector<KWFrameView*> KWFrameViewManager::framesAt(const KoPoint &point, bool borderOnly) const {
|
|
TQValueVector<KWFrameView*> framesThatAreHit;
|
|
// This is probably the slowest and worst way to do it, mark this for optimalisation!
|
|
for(TQValueListConstIterator<KWFrameView*> frames = m_frames.begin();
|
|
frames != m_frames.end(); ++frames) {
|
|
if(! (*frames)->frame()->frameSet()->isVisible())
|
|
continue;
|
|
if(borderOnly && (*frames)->isBorderHit(point) ||
|
|
!borderOnly && (*frames)->contains(point))
|
|
framesThatAreHit.append(*frames);
|
|
}
|
|
// sort on z-ordering; top on first
|
|
std::sort(framesThatAreHit.begin(), framesThatAreHit.end(), compareFrameViewZOrder);
|
|
return framesThatAreHit;
|
|
}
|
|
|
|
KWFrameView *KWFrameViewManager::view(const KWFrame *frame) const {
|
|
// This is probably the slowest and worst way to do it, mark this for optimalisation!
|
|
TQValueListConstIterator<KWFrameView*> frames = m_frames.begin();
|
|
while(frames != m_frames.end()) {
|
|
if((*frames)->frame() == frame)
|
|
return *frames;
|
|
++frames;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
bool KWFrameViewManager::compareFrameViewZOrder(KWFrameView *f1, KWFrameView *f2) {
|
|
return f1->frame()->zOrder() >= f2->frame()->zOrder();
|
|
}
|
|
|
|
TQCursor KWFrameViewManager::mouseCursor( const KoPoint &point, int keyState ) const {
|
|
KWFrameView *view = 0;
|
|
TQValueVector<KWFrameView*> framesThatAreHit = framesAt(point);
|
|
TQValueVector<KWFrameView*>::iterator sortedFrames = framesThatAreHit.begin();
|
|
MouseMeaning meaning;
|
|
while(sortedFrames != framesThatAreHit.end()) {
|
|
meaning = (*sortedFrames)->mouseMeaning(point, keyState);
|
|
if(meaning != MEANING_NONE) {
|
|
view = (*sortedFrames);
|
|
break;
|
|
}
|
|
++sortedFrames;
|
|
}
|
|
|
|
if(view == 0)
|
|
return TQCursor(); // default arrow shape
|
|
|
|
KWFrameSet*frameSet = view->frame()->frameSet();
|
|
switch ( meaning ) {
|
|
case MEANING_NONE:
|
|
return TQt::ibeamCursor; // default cursor in margins
|
|
case MEANING_MOUSE_INSIDE:
|
|
return TQCursor(); // default arrow shape
|
|
case MEANING_MOUSE_INSIDE_TEXT:
|
|
return TQt::ibeamCursor;
|
|
case MEANING_MOUSE_OVER_LINK:
|
|
return TQt::PointingHandCursor;
|
|
case MEANING_MOUSE_OVER_FOOTNOTE:
|
|
return TQt::PointingHandCursor;
|
|
case MEANING_MOUSE_MOVE:
|
|
return TQt::sizeAllCursor;
|
|
case MEANING_MOUSE_SELECT:
|
|
return KCursor::handCursor();
|
|
case MEANING_ACTIVATE_PART:
|
|
return KCursor::handCursor();
|
|
case MEANING_TOPLEFT:
|
|
case MEANING_BOTTOMRIGHT:
|
|
return TQt::sizeFDiagCursor;
|
|
case MEANING_LEFT:
|
|
case MEANING_RIGHT:
|
|
return TQt::sizeHorCursor;
|
|
case MEANING_BOTTOMLEFT:
|
|
case MEANING_TOPRIGHT:
|
|
return TQt::sizeBDiagCursor;
|
|
case MEANING_TOP:
|
|
case MEANING_BOTTOM:
|
|
if ( frameSet->isProtectSize() || frameSet->isMainFrameset())
|
|
return TQt::forbiddenCursor;
|
|
return TQt::sizeVerCursor;
|
|
case MEANING_RESIZE_COLUMN:
|
|
return TQt::splitHCursor;
|
|
case MEANING_RESIZE_ROW:
|
|
return TQt::splitVCursor;
|
|
case MEANING_SELECT_RANGE:
|
|
case MEANING_SELECT_COLUMN:
|
|
case MEANING_SELECT_ROW:
|
|
case MEANING_FORBIDDEN:
|
|
return KCursor::handCursor();
|
|
}
|
|
return TQCursor(); // default arrow shape
|
|
}
|
|
|
|
MouseMeaning KWFrameViewManager::mouseMeaning( const KoPoint &point, int keyState) const {
|
|
TQValueVector<KWFrameView*> framesThatAreHit = framesAt(point);
|
|
TQValueVector<KWFrameView*>::iterator sortedFrames = framesThatAreHit.begin();
|
|
while(sortedFrames != framesThatAreHit.end()) {
|
|
MouseMeaning answer = (*sortedFrames)->mouseMeaning(point, keyState);
|
|
if(answer != MEANING_NONE) {
|
|
//kdDebug() << "mouseMeaning at " << point << " is " << answer << endl;
|
|
return answer;
|
|
}
|
|
++sortedFrames;
|
|
}
|
|
return MEANING_NONE;
|
|
}
|
|
|
|
TQValueList<KWFrameView*> KWFrameViewManager::selectedFrames() const {
|
|
TQValueList<KWFrameView*> selectedFrames;
|
|
|
|
TQValueList<KWFrameView*>::const_iterator frames = m_frames.begin();
|
|
for(; frames != m_frames.end(); ++frames )
|
|
if( (*frames)->selected() )
|
|
selectedFrames.append( *frames );
|
|
return selectedFrames;
|
|
}
|
|
|
|
KWFrameView* KWFrameViewManager::selectedFrame() const {
|
|
TQValueList<KWFrameView*>::const_iterator frames = m_frames.begin();
|
|
for(; frames != m_frames.end(); ++frames )
|
|
if( (*frames)->selected() )
|
|
return *frames;
|
|
return 0;
|
|
}
|
|
|
|
void KWFrameViewManager::showPopup( const KoPoint &point, KWView *view, int keyState, const TQPoint &popupPoint) const {
|
|
TQValueVector<KWFrameView*> framesThatAreHit = framesAt(point);
|
|
if(framesThatAreHit.count() == 0) {
|
|
view->popupMenu("action_popup")->popup(popupPoint);
|
|
return;
|
|
}
|
|
if(keyState == TQt::ControlButton) {
|
|
// show the border popup of the top most frame.
|
|
framesThatAreHit[0]->showPopup(framesThatAreHit[0]->frame()->topLeft(), view, popupPoint);
|
|
return;
|
|
}
|
|
TQValueVector<KWFrameView*>::iterator iter = framesThatAreHit.begin();
|
|
while(iter != framesThatAreHit.end()) {
|
|
if( (*iter)->selected() && keyState == TQt::ControlButton ) {
|
|
(*iter)->showPopup(point, view, popupPoint);
|
|
return;
|
|
}
|
|
++iter;
|
|
}
|
|
framesThatAreHit[0]->showPopup(point, view, popupPoint);
|
|
}
|
|
|
|
void KWFrameViewManager::selectFrames(const KoPoint &point, int keyState, bool leftClick) {
|
|
MouseMeaning mm = mouseMeaning(point, keyState);
|
|
bool multiSelect = mm == MEANING_MOUSE_SELECT || ( keyState & TQt::ControlButton );
|
|
SelectionType se = frameOnTop;
|
|
if(leftClick && multiSelect)
|
|
se = nextUnselected;
|
|
KWFrameView *toBeSelected = view(point, se, !multiSelect);
|
|
//kdDebug() << "KWFrameViewManager::selectFrames" << point << " got: " << toBeSelected << endl;
|
|
if(toBeSelected == 0 || (keyState & TQt::ControlButton) == 0 || ( keyState & TQt::ShiftButton ) &&
|
|
!(leftClick && (mm == MEANING_TOPLEFT || mm == MEANING_TOPRIGHT || mm == MEANING_TOP ||
|
|
mm == MEANING_LEFT || mm == MEANING_RIGHT || mm == MEANING_MOUSE_MOVE ||
|
|
mm == MEANING_BOTTOMLEFT || mm == MEANING_BOTTOM || mm == MEANING_BOTTOMRIGHT))) {
|
|
// unselect all
|
|
for(TQValueListConstIterator<KWFrameView*> frames = m_frames.begin();
|
|
frames != m_frames.end(); ++frames) {
|
|
(*frames)->setSelected(false);
|
|
}
|
|
}
|
|
if(toBeSelected == 0)
|
|
return;
|
|
toBeSelected->setSelected(true, mm);
|
|
slotFrameSelectionChanged();
|
|
}
|
|
|
|
// ********** FrameEvent **** */
|
|
KWFrameViewManager::FrameEvent::FrameEvent (ActionType action) {
|
|
m_action = action;
|
|
}
|
|
KWFrameViewManager::FrameEvent::FrameEvent (ActionType action, KWFrame *frame) {
|
|
m_action = action;
|
|
m_frame = frame;
|
|
}
|
|
KWFrameViewManager::FrameEvent::FrameEvent (ActionType action, KWFrameSet *frameSet) {
|
|
m_action = action;
|
|
m_frameSet = frameSet;
|
|
}
|
|
|
|
|
|
#include "KWFrameViewManager.moc"
|