kword

KWFrameViewManager.cpp
1/* This file is part of the KOffice project
2 * Copyright (C) 2005 Thomas Zander <zander@kde.org>
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; version 2.
7
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Library General Public License for more details.
12 *
13 * You should have received a copy of the GNU Library General Public License
14 * along with this library; see the file COPYING.LIB. If not, write to
15 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
16 * Boston, MA 02110-1301, USA.
17 */
18#include "KWDocument.h"
19#include "KWFrameViewManager.h"
20#include <KWFrameView.h>
21#include <KWFrame.h>
22#include <KWFrameSet.h>
23
24#include <kdebug.h>
25#include <kcursor.h>
26#include <tqcursor.h>
27#include <tqtimer.h>
28#include "tqpopupmenu.h"
29#include <algorithm>
30
31KWFrameViewManager::KWFrameViewManager() : TQObject() {
32 setName("KWFrameViewManager");
33 m_queueRequested = false;
34 m_blockEvents = false;
35}
36
37KWFrameViewManager::KWFrameViewManager(KWDocument *doc) {
38 m_queueRequested = false;
39 m_blockEvents = true;
40 TQPtrListIterator<KWFrameSet> frameSets = doc->framesetsIterator();
41 while(frameSets.current()) {
42 slotFrameSetAdded(*frameSets);
43 ++frameSets;
44 }
45 m_blockEvents = false;
46 connect(doc, TQ_SIGNAL( sigFrameSetAdded(KWFrameSet*)), TQ_SLOT( slotFrameSetAdded(KWFrameSet*)));
47 connect(doc, TQ_SIGNAL( sigFrameSetRemoved(KWFrameSet*)), TQ_SLOT( slotFrameSetRemoved(KWFrameSet*)));
48 recalculateFrameCache();
49}
50
51KWFrameViewManager::~KWFrameViewManager() {
52 TQValueListIterator<FrameEvent *> events = m_frameEvents.begin();
53 while(events != m_frameEvents.end()) {
54 delete (*events);
55 ++events;
56 }
57}
58
59void KWFrameViewManager::addKWFramesListener(KWFramesListener *listener) {
60 m_framesListener.append(listener);
61}
62void KWFrameViewManager::removeKWFramesListener(KWFramesListener *listener) {
63 m_framesListener.remove(listener);
64}
65
67 if(! m_blockEvents)
68 m_frameEvents.append(new FrameEvent(FrameEvent::FrameSetAdded, fs));
69 connect(fs, TQ_SIGNAL( sigFrameAdded(KWFrame*)), TQ_SLOT( slotFrameAdded(KWFrame *)));
70 connect(fs, TQ_SIGNAL( sigFrameRemoved(KWFrame*)), TQ_SLOT( slotFrameRemoved(KWFrame *)));
71 connect(fs, TQ_SIGNAL( sigNameChanged(KWFrameSet*)), TQ_SLOT( slotFrameSetRenamed(KWFrameSet *)));
72 TQPtrListIterator<KWFrame> frames = fs->frameIterator();
73 while(frames.current()) {
74 KWFrame *f = frames.current();
76 ++frames;
77 }
79}
81 if(! m_blockEvents)
82 m_frameEvents.append(new FrameEvent(FrameEvent::FrameSetRemoved, fs));
83 disconnect(fs, TQ_SIGNAL( sigFrameAdded(KWFrame*)), this, TQ_SLOT( slotFrameAdded(KWFrame *)));
84 disconnect(fs, TQ_SIGNAL( sigFrameRemoved(KWFrame*)), this, TQ_SLOT( slotFrameRemoved(KWFrame *)));
85 disconnect(fs, TQ_SIGNAL( sigNameChanged(KWFrameSet*)), this, TQ_SLOT( slotFrameSetRenamed(KWFrameSet *)));
86 TQPtrListIterator<KWFrame> frames = fs->frameIterator();
87 while(frames.current()) {
88 KWFrame *f = frames.current();
90 ++frames;
91 }
93}
95 if(! m_blockEvents)
96 m_frameEvents.append(new FrameEvent(FrameEvent::FrameAdded, f));
97 m_frames.append(new KWFrameView(this, f));
99}
101 if(! m_blockEvents)
102 m_frameEvents.append(new FrameEvent(FrameEvent::FrameRemoved, f));
103 TQValueListIterator<KWFrameView *> frames = m_frames.begin();
104 while(frames != m_frames.end()) {
105 KWFrameView *fv = *frames;
106 if(fv->frame() == f) {
107 if(fv->selected())
108 m_frameEvents.append(new FrameEvent(FrameEvent::FrameSelectionChanged));
109 m_frames.remove(frames);
110 delete fv;
111 break;
112 }
113 ++frames;
114 }
116}
117void KWFrameViewManager::slotFrameMoved(KWFrame *f, double previousYPosition) {
118 Q_UNUSED(previousYPosition); // to be used for the page caches to mark them dirty
119 if(! m_blockEvents)
120 m_frameEvents.append(new FrameEvent(FrameEvent::FrameMoved, f));
121 // TODO; KWFrameList update??
122 // update our caches..
124}
126 if(! m_blockEvents)
127 m_frameEvents.append(new FrameEvent(FrameEvent::FrameResized, f));
128 // update our caches..
130}
132 if(! m_blockEvents)
133 m_frameEvents.append(new FrameEvent(FrameEvent::FrameSelectionChanged));
134 // update our caches..
136}
137
139 if(! m_blockEvents)
140 m_frameEvents.append(new FrameEvent(FrameEvent::FrameSetRenamed, fs));
142}
143
145 if(m_queueRequested && !m_blockEvents)
146 return;
147 m_queueRequested = true;
148 TQTimer::singleShot ( 0, this, TQ_SLOT(fireEvents()) );
149}
150
152 m_queueRequested = false;
153 if(m_frameEvents.isEmpty())
154 return;
155 recalculateFrameCache();
156
157 TQValueList<FrameEvent *> copy(m_frameEvents);
158 m_frameEvents.clear();
159
160 TQValueList<KWFrame*> resizedFrames;
161 TQValueList<KWFrame*> movedFrames;
162 TQValueList<KWFramesListener *> listenersCopy(m_framesListener);
163 bool selectionChangedFired=false;
164
165 TQValueListIterator<FrameEvent *> events = copy.begin();
166 while(events != copy.end()) {
167 FrameEvent *event = *events;
168
169 // emit based.
170 if(!selectionChangedFired && event->m_action == FrameEvent::FrameSelectionChanged) {
172 selectionChangedFired = true; // only fire ones.
173 } else if(event->m_action == FrameEvent::FrameSetRenamed) {
174 TQPtrListIterator<KWFrame> frames = event->m_frameSet->frameIterator();
175 for(;frames.current();++frames) {
176 if(view(frames.current())->selected()) {
177 emit sigFrameSetRenamed();
178 break;
179 }
180 }
181 } else if(event->m_action == FrameEvent::FrameResized) {
182 resizedFrames.append(event->m_frame);
183 } else if(event->m_action == FrameEvent::FrameMoved) {
184 movedFrames.append(event->m_frame);
185 }
186
187 // listener based
188 TQValueListIterator<KWFramesListener *> listeners = listenersCopy.begin();
189 while(listeners != listenersCopy.end()) {
190 if(event->m_action == FrameEvent::FrameRemoved)
191 (*listeners)->frameRemoved(event->m_frame);
192 else if(event->m_action == FrameEvent::FrameAdded)
193 (*listeners)->frameAdded(event->m_frame);
194 else if(event->m_action == FrameEvent::FrameSetRemoved)
195 (*listeners)->frameSetRemoved(event->m_frameSet);
196 else if(event->m_action == FrameEvent::FrameSetAdded)
197 (*listeners)->frameSetAdded(event->m_frameSet);
198 ++listeners;
199 }
200
201 delete event;
202 events = copy.remove(events);
203 }
204 if(resizedFrames.count() > 0)
205 emit sigFrameResized(resizedFrames);
206 if(movedFrames.count() > 0)
207 emit sigFrameMoved(movedFrames);
208}
209
210void KWFrameViewManager::recalculateFrameCache() {
211 // TODO :) design and implement a cache...
212 // list of frames sorted on y-coord, with an additional list containing a jump-index
213 kdDebug(31001) << "recalculateFrameCache " << m_frames.count() << " frames are currently registred" << endl;
214}
215
216KWFrameView *KWFrameViewManager::view(const KoPoint &point, SelectionType selected, bool borderOnly) const {
217 TQValueVector<KWFrameView*> framesThatAreHit = framesAt(point, borderOnly);
218 bool foundCycleFrame = false;
219 TQValueVector<KWFrameView*>::iterator sortedFrames = framesThatAreHit.begin();
220 while(sortedFrames != framesThatAreHit.end()) {
221 if(selected == nextUnselected) {
222 if((*sortedFrames)->selected() )
223 foundCycleFrame = true;
224 else if(foundCycleFrame && !(*sortedFrames)->selected() )
225 return *sortedFrames;
226 }
227 else if(selected == frameOnTop)
228 return *sortedFrames;
229 else { // not cycle, so simply a selected check.
230 if((*sortedFrames)->selected() == (selected == KWFrameViewManager::selected ))
231 return *sortedFrames;
232 }
233 ++sortedFrames;
234 }
235 if(selected == nextUnselected && framesThatAreHit.count() > 0)
236 return framesThatAreHit[0];
237 return 0;
238}
239
240TQValueVector<KWFrameView*> KWFrameViewManager::framesAt(const KoPoint &point, bool borderOnly) const {
241 TQValueVector<KWFrameView*> framesThatAreHit;
242 // This is probably the slowest and worst way to do it, mark this for optimalisation!
243 for(TQValueListConstIterator<KWFrameView*> frames = m_frames.begin();
244 frames != m_frames.end(); ++frames) {
245 if(! (*frames)->frame()->frameSet()->isVisible())
246 continue;
247 if(borderOnly && (*frames)->isBorderHit(point) ||
248 !borderOnly && (*frames)->contains(point))
249 framesThatAreHit.append(*frames);
250 }
251 // sort on z-ordering; top on first
252 std::sort(framesThatAreHit.begin(), framesThatAreHit.end(), compareFrameViewZOrder);
253 return framesThatAreHit;
254}
255
257 // This is probably the slowest and worst way to do it, mark this for optimalisation!
258 TQValueListConstIterator<KWFrameView*> frames = m_frames.begin();
259 while(frames != m_frames.end()) {
260 if((*frames)->frame() == frame)
261 return *frames;
262 ++frames;
263 }
264 return 0;
265}
266
267bool KWFrameViewManager::compareFrameViewZOrder(KWFrameView *f1, KWFrameView *f2) {
268 return f1->frame()->zOrder() >= f2->frame()->zOrder();
269}
270
271TQCursor KWFrameViewManager::mouseCursor( const KoPoint &point, int keyState ) const {
272 KWFrameView *view = 0;
273 TQValueVector<KWFrameView*> framesThatAreHit = framesAt(point);
274 TQValueVector<KWFrameView*>::iterator sortedFrames = framesThatAreHit.begin();
275 MouseMeaning meaning;
276 while(sortedFrames != framesThatAreHit.end()) {
277 meaning = (*sortedFrames)->mouseMeaning(point, keyState);
278 if(meaning != MEANING_NONE) {
279 view = (*sortedFrames);
280 break;
281 }
282 ++sortedFrames;
283 }
284
285 if(view == 0)
286 return TQCursor(); // default arrow shape
287
288 KWFrameSet*frameSet = view->frame()->frameSet();
289 switch ( meaning ) {
290 case MEANING_NONE:
291 return TQt::ibeamCursor; // default cursor in margins
292 case MEANING_MOUSE_INSIDE:
293 return TQCursor(); // default arrow shape
294 case MEANING_MOUSE_INSIDE_TEXT:
295 return TQt::ibeamCursor;
296 case MEANING_MOUSE_OVER_LINK:
297 return TQt::PointingHandCursor;
298 case MEANING_MOUSE_OVER_FOOTNOTE:
299 return TQt::PointingHandCursor;
300 case MEANING_MOUSE_MOVE:
301 return TQt::sizeAllCursor;
302 case MEANING_MOUSE_SELECT:
303 return KCursor::handCursor();
304 case MEANING_ACTIVATE_PART:
305 return KCursor::handCursor();
306 case MEANING_TOPLEFT:
307 case MEANING_BOTTOMRIGHT:
308 return TQt::sizeFDiagCursor;
309 case MEANING_LEFT:
310 case MEANING_RIGHT:
311 return TQt::sizeHorCursor;
312 case MEANING_BOTTOMLEFT:
313 case MEANING_TOPRIGHT:
314 return TQt::sizeBDiagCursor;
315 case MEANING_TOP:
316 case MEANING_BOTTOM:
317 if ( frameSet->isProtectSize() || frameSet->isMainFrameset())
318 return TQt::forbiddenCursor;
319 return TQt::sizeVerCursor;
320 case MEANING_RESIZE_COLUMN:
321 return TQt::splitHCursor;
322 case MEANING_RESIZE_ROW:
323 return TQt::splitVCursor;
324 case MEANING_SELECT_RANGE:
325 case MEANING_SELECT_COLUMN:
326 case MEANING_SELECT_ROW:
327 case MEANING_FORBIDDEN:
328 return KCursor::handCursor();
329 }
330 return TQCursor(); // default arrow shape
331}
332
333MouseMeaning KWFrameViewManager::mouseMeaning( const KoPoint &point, int keyState) const {
334 TQValueVector<KWFrameView*> framesThatAreHit = framesAt(point);
335 TQValueVector<KWFrameView*>::iterator sortedFrames = framesThatAreHit.begin();
336 while(sortedFrames != framesThatAreHit.end()) {
337 MouseMeaning answer = (*sortedFrames)->mouseMeaning(point, keyState);
338 if(answer != MEANING_NONE) {
339 //kdDebug() << "mouseMeaning at " << point << " is " << answer << endl;
340 return answer;
341 }
342 ++sortedFrames;
343 }
344 return MEANING_NONE;
345}
346
347TQValueList<KWFrameView*> KWFrameViewManager::selectedFrames() const {
348 TQValueList<KWFrameView*> selectedFrames;
349
350 TQValueList<KWFrameView*>::const_iterator frames = m_frames.begin();
351 for(; frames != m_frames.end(); ++frames )
352 if( (*frames)->selected() )
353 selectedFrames.append( *frames );
354 return selectedFrames;
355}
356
358 TQValueList<KWFrameView*>::const_iterator frames = m_frames.begin();
359 for(; frames != m_frames.end(); ++frames )
360 if( (*frames)->selected() )
361 return *frames;
362 return 0;
363}
364
365void KWFrameViewManager::showPopup( const KoPoint &point, KWView *view, int keyState, const TQPoint &popupPoint) const {
366 TQValueVector<KWFrameView*> framesThatAreHit = framesAt(point);
367 if(framesThatAreHit.count() == 0) {
368 view->popupMenu("action_popup")->popup(popupPoint);
369 return;
370 }
371 if(keyState == TQt::ControlButton) {
372 // show the border popup of the top most frame.
373 framesThatAreHit[0]->showPopup(framesThatAreHit[0]->frame()->topLeft(), view, popupPoint);
374 return;
375 }
376 TQValueVector<KWFrameView*>::iterator iter = framesThatAreHit.begin();
377 while(iter != framesThatAreHit.end()) {
378 if( (*iter)->selected() && keyState == TQt::ControlButton ) {
379 (*iter)->showPopup(point, view, popupPoint);
380 return;
381 }
382 ++iter;
383 }
384 framesThatAreHit[0]->showPopup(point, view, popupPoint);
385}
386
387void KWFrameViewManager::selectFrames(const KoPoint &point, int keyState, bool leftClick) {
388 MouseMeaning mm = mouseMeaning(point, keyState);
389 bool multiSelect = mm == MEANING_MOUSE_SELECT || ( keyState & TQt::ControlButton );
390 SelectionType se = frameOnTop;
391 if(leftClick && multiSelect)
392 se = nextUnselected;
393 KWFrameView *toBeSelected = view(point, se, !multiSelect);
394 //kdDebug() << "KWFrameViewManager::selectFrames" << point << " got: " << toBeSelected << endl;
395 if(toBeSelected == 0 || (keyState & TQt::ControlButton) == 0 || ( keyState & TQt::ShiftButton ) &&
396 !(leftClick && (mm == MEANING_TOPLEFT || mm == MEANING_TOPRIGHT || mm == MEANING_TOP ||
397 mm == MEANING_LEFT || mm == MEANING_RIGHT || mm == MEANING_MOUSE_MOVE ||
398 mm == MEANING_BOTTOMLEFT || mm == MEANING_BOTTOM || mm == MEANING_BOTTOMRIGHT))) {
399 // unselect all
400 for(TQValueListConstIterator<KWFrameView*> frames = m_frames.begin();
401 frames != m_frames.end(); ++frames) {
402 (*frames)->setSelected(false);
403 }
404 }
405 if(toBeSelected == 0)
406 return;
407 toBeSelected->setSelected(true, mm);
409}
410
411// ********** FrameEvent **** */
412KWFrameViewManager::FrameEvent::FrameEvent (ActionType action) {
413 m_action = action;
414}
415KWFrameViewManager::FrameEvent::FrameEvent (ActionType action, KWFrame *frame) {
416 m_action = action;
417 m_frame = frame;
418}
419KWFrameViewManager::FrameEvent::FrameEvent (ActionType action, KWFrameSet *frameSet) {
420 m_action = action;
421 m_frameSet = frameSet;
422}
423
424
425#include "KWFrameViewManager.moc"
Class: KWFrameSet Base type, a frameset holds content as well as frames to show that content.
Definition KWFrameSet.h:62
const TQPtrList< KWFrame > & frameIterator() const
Iterator over the child frames.
Definition KWFrameSet.h:159
SelectionType
Used to change the behavior of view()
void slotFrameResized(KWFrame *f)
notify this slot if a Frame has been resized
KWFrameView * selectedFrame() const
Returns the first selected frame.
void showPopup(const KoPoint &point, KWView *view, int keyState, const TQPoint &popupPoint) const
Show a context-sensitive popup menu based on the location of 'point'.
void sigFrameMoved(const TQValueList< KWFrame * > &)
emitted after frames were moved
void slotFrameAdded(KWFrame *f)
notify this slot if a Frame has been created and should become visible.
void sigFrameSelectionChanged()
emitted after one or more incoming slotFrameSelectionChanged events.
MouseMeaning mouseMeaning(const KoPoint &point, int keyState) const
Return the MouseMeaning of what a click of the mouse would do at the point.
TQValueList< KWFrameView * > selectedFrames() const
Return all currently selected frames.
KWFrameView * view(const KoPoint &point, SelectionType select, bool borderOnly=false) const
Returns a frameView representing a frame positioned at point, or 0 when no match found.
void slotFrameSetRemoved(KWFrameSet *fs)
notify this slot if a FrameSet has been removed
void sigFrameSetRenamed()
emitted after a frameset that had at least one selected frame was renamed.
void slotFrameSetRenamed(KWFrameSet *fs)
notify this slot if a frameset was renamed
void selectFrames(const KoPoint &point, int keyState, bool leftClick)
Select frames based on a mouse click at point using keystate.
void slotFrameSetAdded(KWFrameSet *fs)
notify this slot if a FrameSet has been created and should become visible.
void sigFrameResized(const TQValueList< KWFrame * > &)
emitted after frames were resized
TQCursor mouseCursor(const KoPoint &point, int keyState) const
Similar to mouseMeaning(), but instead of returning the meaning this will return a mouse cursor to re...
void slotFrameMoved(KWFrame *f, double previousYPosition)
notify this slot if a Frame has been moved
virtual void requestFireEvents()
prepare or update the singleshot timer to fire events.
void fireEvents()
This method will propagate all the events saved up to the listeners.
void slotFrameRemoved(KWFrame *f)
notify this slot if a Frame has been removed
void slotFrameSelectionChanged()
notify this slot if one or more frames have been selected or unselected.
an instance of a KWFrameView represents the view in the MVC model of a frame; there can be multiple K...
Definition KWFrameView.h:82
void setSelected(bool selected, MouseMeaning selectPolicy=MEANING_MOUSE_SELECT)
Set the selected state of this frameView.
KWFrame * frame() const
returns the frame this frameView represents
bool selected() const
returns if this frameView is selected. A selected frame is shown differently on screen.
Definition KWFrameView.h:93
void showPopup(const KoPoint &point, KWView *view, const TQPoint &popupPoint) const
Show a context-sensitive popup menu based on the location of 'point'.
This class represents a single frame.
Definition KWFrame.h:68
KWFrameSet * frameSet() const
Data stucture methods.
Definition KWFrame.h:143