update dev300-m58
[ooovba.git] / sw / source / core / view / scrrect.cxx
blob87b718425dac17263141ffe2ea8f9aab7b5f2d18
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: scrrect.cxx,v $
10 * $Revision: 1.23 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
35 #include <viewimp.hxx>
36 #include <viewsh.hxx>
37 #include <viewopt.hxx>
38 #include <vcl/window.hxx>
39 #include <scrrect.hxx> // SwScrollRect, SwScrollRects
40 // OD 18.02.2003 #107562# - <SwAlignRect> for <ViewShell::Scroll()>
41 #include <frmtool.hxx>
42 #ifndef _CURSOR_HXX //autogen
43 #include <vcl/cursor.hxx>
44 #endif
45 #include <vcl/virdev.hxx>
46 #ifndef _APP_HXX //autogen
47 #include <vcl/svapp.hxx>
48 #endif
49 #include <txtfrm.hxx>
50 #include "crsrsh.hxx"
51 #include "rootfrm.hxx"
52 #include "pagefrm.hxx"
54 // OD 12.11.2002 #96272# - include declaration for <SetMappingForVirtDev>
55 #include "setmapvirtdev.hxx"
56 #include <IDocumentDrawModelAccess.hxx>
58 // #i75172#
59 #include "dview.hxx"
61 DBG_NAME(RefreshTimer)
63 SV_IMPL_VARARR(SwStripeArr,SwStripe);
64 SV_IMPL_OP_PTRARR_SORT(SwScrollStripes, SwStripesPtr);
65 SV_IMPL_OP_PTRARR_SORT(SScrAreas, SwScrollAreaPtr);
67 /*****************************************************************************
69 |* ViewShell::AddScrollRect()
71 |* Creation MA 07. Mar. 94
72 |* Last change AMA 20. July 00
74 |* Description
75 |* ViewShell::AddScrollRect(..) passes a registration from a scrolling frame or
76 |* rectangle to all ViewShells and SwViewImps respectively.
78 ******************************************************************************/
80 void ViewShell::AddScrollRect( const SwFrm *pFrm, const SwRect &rRect,
81 long nOfs )
83 ASSERT( pFrm, "Where is my friend, the frame?" );
84 BOOL bScrollOn = TRUE;
86 #ifdef NOSCROLL
87 //Auch im Product per speziellem Compilat abschaltbar.
88 bScrollOn = FALSE;
89 #endif
91 if( bScrollOn && Imp()->IsScroll() && nOfs <= SHRT_MAX && nOfs >= SHRT_MIN )
93 ViewShell *pSh = this;
96 pSh->Imp()->AddScrollRect( pFrm, rRect, nOfs );
97 pSh = (ViewShell*)pSh->GetNext();
98 } while ( pSh != this );
100 else
101 AddPaintRect( rRect );
104 /******************************************************************************
106 |* ViewShell::Scroll()
108 |* Ersterstellung MA 07. Mar. 94
109 |* Last change AMA 21. July 00
111 |* Description
112 |* ViewShell::Scroll() scrolls all rectangles in the pScrollRects-list and
113 |* transfers the critical lines by calling SwViewImp::MoveScrollArea(..).
115 ******************************************************************************/
116 #include <svx/sdrpaintwindow.hxx>
117 #include <svx/sdr/overlay/overlaymanager.hxx>
119 void ViewShell::Scroll()
121 SwScrollAreas *pScrollRects = Imp()->GetScrollRects();
122 if ( pScrollRects )
124 bPaintWorks = FALSE;
125 ASSERT( pScrollRects->Count(), "ScrollRects ohne ScrollRects." );
127 //Abgleichen der Region mit den Scroll-Bereichen!!!
128 //Wenn eines der Scroll-Rechtecke ungueltig wird, so muss
129 //der PaintMode wahrscheinlich auf PAINT_BACKGROUND umgeschaltet
130 //werden.
132 //Auf die Richtung kommt es an:
133 //- Bei einem pos. Ofst muss von hinten nach vorn gescrollt werden.
134 //- Bei einem neg. Ofst muss von vorn nach hinten gescrollt werden.
135 BOOL bPositive = (*pScrollRects)[0]->GetOffs() > 0;
136 if( (*pScrollRects)[0]->IsVertical() )
137 bPositive = !bPositive;
138 int i = bPositive ? pScrollRects->Count()-1 : 0;
140 for ( ; bPositive ?
141 i >= 0 :
142 i < (int)pScrollRects->Count();
143 bPositive ?
144 --i :
145 ++i )
147 const SwScrollArea &rScroll = *(*pScrollRects)[ sal::static_int_cast<USHORT>(i) ];
148 if( rScroll.Count() )
150 int j = bPositive ? rScroll.Count()-1 : 0;
151 for ( ; bPositive ? j >= 0 : j < (int)rScroll.Count();
152 bPositive ? --j : ++j )
154 const SwStripes& rStripes = *rScroll[ sal::static_int_cast<USHORT>(j) ];
155 if( rScroll.IsVertical() )
157 Rectangle aRectangle( rStripes.GetY() -
158 rStripes.GetHeight() + rScroll.GetOffs(),
159 rStripes.GetMin(),
160 rStripes.GetY() + rScroll.GetOffs(),
161 rStripes.GetMax() );
162 // OD 18.02.2003 #107562# - align rectangle for scrolling
163 SwRect aAlignedScrollRect( aRectangle );
164 ::SwAlignRect( aAlignedScrollRect, this );
166 // #i68597# when scrolling, let DrawingLayer know about refreshed areas,
167 // even when no DL objects are in the area. This is needed to allow
168 // fully buffered overlay.
169 const Rectangle aSourceRect(aAlignedScrollRect.SVRect());
170 const Rectangle aTargetRect(
171 aSourceRect.Left() - rScroll.GetOffs(), aSourceRect.Top(),
172 aSourceRect.Right() - rScroll.GetOffs(), aSourceRect.Bottom());
174 if(GetWin())
176 // SCROLL_NOWINDOWINVALIDATE okay since AddPaintRect below adds the to-be-invalidated region
177 GetWin()->Scroll( -rScroll.GetOffs(), 0, aSourceRect, SCROLL_CHILDREN | SCROLL_NOWINDOWINVALIDATE );
180 // #i68597# if buffered overlay, the buffered content needs to be scrolled directly
182 SdrPaintWindow* pPaintWindow = GetDrawView()->GetPaintWindow(0);
184 if(pPaintWindow)
186 sdr::overlay::OverlayManager* pOverlayManager = pPaintWindow->GetOverlayManager();
188 if(pOverlayManager)
190 pOverlayManager->copyArea(aTargetRect.TopLeft(), aSourceRect.TopLeft(), aSourceRect.GetSize());
195 SwRect aRect( aRectangle );
196 Imp()->ScrolledRect( aRect, -rScroll.GetOffs() );
197 if ( bPositive )
198 aRect.Right( aRect.Left() + rScroll.GetOffs()-1 );
199 else
200 aRect.Left( aRect.Right() - rScroll.GetOffs() );
201 Imp()->AddPaintRect( aRect );
203 else
205 Rectangle aRectangle( rStripes.GetMin(),
206 rStripes.GetY() - rScroll.GetOffs(),
207 rStripes.GetRight(),
208 rStripes.GetBottom() - rScroll.GetOffs() );
209 // OD 18.02.2003 #107562# - use aligned rectangle for scrolling
210 SwRect aAlignedScrollRect( aRectangle );
211 ::SwAlignRect( aAlignedScrollRect, this );
213 // #i68597# when scrolling, let DrawingLayer know about refreshed areas,
214 // even when no DL objects are in the area. This is needed to allow
215 // fully buffered overlay.
216 const Rectangle aSourceRect(aAlignedScrollRect.SVRect());
217 const Rectangle aTargetRect(
218 aSourceRect.Left(), aSourceRect.Top() + rScroll.GetOffs(),
219 aSourceRect.Right(), aSourceRect.Bottom() + rScroll.GetOffs());
221 if(GetWin())
223 // SCROLL_NOWINDOWINVALIDATE okay since AddPaintRect below adds the to-be-invalidated region
224 GetWin()->Scroll( 0, rScroll.GetOffs(), aSourceRect, SCROLL_CHILDREN | SCROLL_NOWINDOWINVALIDATE );
227 // #i68597# if buffered overlay, the buffered content needs to be scrolled directly
229 SdrPaintWindow* pPaintWindow = GetDrawView()->GetPaintWindow(0);
231 if(pPaintWindow)
233 sdr::overlay::OverlayManager* pOverlayManager = pPaintWindow->GetOverlayManager();
235 if(pOverlayManager)
237 pOverlayManager->copyArea(aTargetRect.TopLeft(), aSourceRect.TopLeft(), aSourceRect.GetSize());
242 SwRect aRect( aRectangle );
243 Imp()->ScrolledRect( aRect, rScroll.GetOffs() );
244 if ( bPositive )
245 aRect.Bottom( aRect.Top() + rScroll.GetOffs()-1 );
246 else
247 aRect.Top( aRect.Bottom() + rScroll.GetOffs() );
248 Imp()->AddPaintRect( aRect );
253 if ( !Imp()->IsScrolled() )
254 Imp()->SetScrolled();
256 Imp()->MoveScrollArea();
257 bPaintWorks = TRUE;
261 /******************************************************************************
263 |* ViewShell::SetNoNextScroll()
265 |* Ersterstellung MA 08. Mar. 94
266 |* Letzte Aenderung MA 08. Mar. 94
268 ******************************************************************************/
270 void ViewShell::SetNoNextScroll()
272 ViewShell *pSh = this;
274 { pSh->Imp()->ResetNextScroll();
275 pSh = (ViewShell*)pSh->GetNext();
277 } while ( pSh != this );
280 /******************************************************************************
282 |* SwViewImp::AddScrollRect()
284 |* Ersterstellung MA 07. Mar. 94
285 |* Last change AMA 21. July 00
287 |* Adds a scrollable rectangle and his critical lines to the list.
289 ******************************************************************************/
291 void SwViewImp::AddScrollRect( const SwFrm *pFrm, const SwRect &rRect,
292 long nOffs )
294 ASSERT( nOffs != 0, "Scrollen ohne Ofst." );
295 SwRect aRect( rRect );
296 BOOL bVert = pFrm->IsVertical();
297 if( bVert )
298 aRect.Pos().X() += nOffs;
299 else
300 aRect.Pos().Y() -= nOffs;
301 if( aRect.IsOver( pSh->VisArea() ) )
303 ASSERT( pSh->GetWin(), "Scrolling without outputdevice" );
304 aRect._Intersection( pSh->VisArea() );
305 SwStripes *pStr;
306 if ( !pScrollRects )
307 pScrollRects = new SwScrollAreas;
308 if( bVert )
310 aRect.Pos().X() -= nOffs;
311 pStr = new SwStripes( aRect.Right(), aRect.Width(),
312 aRect.Top(), aRect.Bottom() );
313 if( pFrm->IsTxtFrm() )
314 ((SwTxtFrm*)pFrm)->CriticalLines(*pSh->GetWin(), *pStr, nOffs );
315 else
316 pStr->Insert( SwStripe( aRect.Right(), aRect.Width() ), 0 );
317 pScrollRects->InsertCol( SwScrollColumn( pFrm->Frm().Top(),
318 pFrm->Frm().Height(), nOffs, bVert ), pStr);
320 else
322 aRect.Pos().Y() += nOffs;
323 pStr = new SwStripes( aRect.Top(), aRect.Height(),
324 aRect.Left(), aRect.Right() );
325 if( pFrm->IsTxtFrm() )
326 ((SwTxtFrm*)pFrm)->CriticalLines(*pSh->GetWin(), *pStr, nOffs );
327 else
328 pStr->Insert( SwStripe( aRect.Top(), aRect.Height() ), 0 );
329 pScrollRects->InsertCol( SwScrollColumn( pFrm->Frm().Left(),
330 pFrm->Frm().Width(), nOffs, bVert ), pStr );
333 else
334 AddPaintRect( rRect );
337 /******************************************************************************
339 |* SwViewImp::MoveScrollArea()
341 |* Creation AMA 10. July 00
342 |* Last change AMA 21. July 00
344 |* Transfers the areas after scrolling to the scrolled list, but only those
345 |* parts with critical lines.
347 ******************************************************************************/
349 void SwViewImp::MoveScrollArea()
351 if( !pScrolledArea )
352 pScrolledArea = new SwScrollAreas;
353 for( USHORT nIdx = 0; nIdx < pScrollRects->Count(); ++nIdx )
355 SwScrollArea *pScr = (*pScrollRects)[ nIdx ];
356 if( pScr->Compress() )
357 delete pScr;
358 else
360 USHORT nIndx;
361 if( pScrolledArea->Seek_Entry( pScr, &nIndx ) )
362 pScrolledArea->GetObject(nIndx)->Add( pScr );
363 else
364 pScrolledArea->Insert( pScr );
367 delete pScrollRects;
368 pScrollRects = NULL;
371 /******************************************************************************
373 |* SwViewImp::FlushScrolledArea()
375 |* Creation AMA 10. July 00
376 |* Last change AMA 21. July 00
378 |* Flushes the scrolled critical lines, that is transfer them to AddPaintRect()
379 |* and remove them from the list.
381 ******************************************************************************/
383 void SwViewImp::FlushScrolledArea()
385 USHORT nCount = pScrolledArea->Count();
386 while( nCount )
388 SwScrollArea* pScroll = (*pScrolledArea)[--nCount];
389 USHORT nCnt = pScroll->Count();
390 while( nCnt )
392 SwStripes* pStripes = (*pScroll)[--nCnt];
393 if( pScroll->IsVertical() )
395 SwRect aRect( 0, pStripes->GetMin(), 0, pStripes->GetWidth() );
396 for( USHORT i = 0; i < pStripes->Count(); ++i )
398 long nWidth = (*pStripes)[i].GetHeight();
399 aRect.Left( (*pStripes)[i].GetY() - nWidth + 1 );
400 aRect.Width( nWidth );
401 AddPaintRect( aRect );
405 SwRect aRect( pStripes->GetMin(), 0, pStripes->GetWidth(), 0 );
406 for( USHORT i = 0; i < pStripes->Count(); ++i )
408 aRect.Top( (*pStripes)[i].GetY() );
409 aRect.Height( (*pStripes)[i].GetHeight() );
410 AddPaintRect( aRect );
413 pScroll->Remove( nCnt );
414 delete pStripes;
416 pScrolledArea->Remove( nCount );
417 delete pScroll;
419 delete pScrolledArea;
420 pScrolledArea = NULL;
423 /******************************************************************************
425 |* SwViewImp::_FlushScrolledArea(..)
427 |* Creation AMA 10. July 00
428 |* Last change AMA 21. July 00
430 |* The critical lines, which overlaps with the given rectangle, will be united
431 |* with the rectangle and removed from the list.
433 ******************************************************************************/
435 BOOL SwViewImp::_FlushScrolledArea( SwRect& rRect )
437 BOOL bRet = FALSE;
438 for( USHORT i = pScrolledArea->Count(); i; )
440 SwScrollArea* pScroll = (*pScrolledArea)[--i];
441 for( USHORT j = pScroll->Count(); j; )
443 SwStripes* pStripes = (*pScroll)[--j];
444 if( pStripes->Count() )
446 if( pScroll->IsVertical() )
448 SwRect aRect( pStripes->GetY() - pStripes->GetHeight(),
449 pStripes->GetMin(), pStripes->GetHeight(),
450 pStripes->GetWidth() );
451 if( rRect.IsOver( aRect ) )
453 for( USHORT nI = pStripes->Count(); nI; )
455 long nWidth = (*pStripes)[--nI].GetHeight();
456 aRect.Left( (*pStripes)[nI].GetY() - nWidth + 1 );
457 aRect.Width( nWidth );
458 if( rRect.IsOver( aRect ) )
460 rRect.Union( aRect );
461 bRet = TRUE;
462 pStripes->Remove( nI );
463 nI = pStripes->Count();
468 else
470 SwRect aRect( pStripes->GetMin(), pStripes->GetY(),
471 pStripes->GetWidth(), pStripes->GetHeight() );
472 if( rRect.IsOver( aRect ) )
474 for( USHORT nI = pStripes->Count(); nI; )
476 aRect.Top( (*pStripes)[--nI].GetY() );
477 aRect.Height( (*pStripes)[nI].GetHeight() );
478 if( rRect.IsOver( aRect ) )
480 rRect.Union( aRect );
481 bRet = TRUE;
482 pStripes->Remove( nI );
483 nI = pStripes->Count();
489 if( !pStripes->Count() )
491 pScroll->Remove( j );
492 delete pStripes;
495 if( !pScroll->Count() )
497 pScrolledArea->Remove( pScroll );
498 delete pScroll;
501 if( !pScrolledArea->Count() )
503 DELETEZ( pScrolledArea );
504 SetNextScroll();
506 return bRet;
509 /******************************************************************************
511 |* SwViewImp::RefreshScrolledHdl(..)
513 |* Creation MA 06. Oct. 94
514 |* Last change AMA 21. July 00
516 |* Every timerstop one of the critical lines will be painted.
518 ******************************************************************************/
520 IMPL_LINK( SwViewImp, RefreshScrolledHdl, Timer *, EMPTYARG )
522 DBG_PROFSTART( RefreshTimer );
524 if ( !IsScrolled() )
525 { DBG_PROFSTOP( RefreshTimer );
526 return 0;
529 SET_CURR_SHELL( GetShell() );
531 //Kein Refresh wenn eine Selektion besteht.
532 if ( GetShell()->IsA( TYPE(SwCrsrShell) ) &&
533 (((SwCrsrShell*)GetShell())->HasSelection() ||
534 ((SwCrsrShell*)GetShell())->GetCrsrCnt() > 1))
536 DBG_PROFSTOP( RefreshTimer );
537 return 0;
540 if( pScrolledArea )
542 const SwRect aRect( GetShell()->VisArea() );
543 BOOL bNoRefresh = GetShell()->IsA( TYPE(SwCrsrShell) ) &&
544 ( ((SwCrsrShell*)GetShell())->HasSelection() ||
545 ((SwCrsrShell*)GetShell())->GetCrsrCnt() > 1 );
546 if( pScrolledArea->Count() )
548 SwScrollArea* pScroll = pScrolledArea->GetObject(0);
549 ASSERT( pScroll->Count(), "Empty scrollarea" );
550 // OD 21.10.2003 #112616# - for savety reason:
551 // react, if precondition named in assertion isn't hold
552 if ( pScroll->Count() )
554 SwStripes* pStripes = pScroll->GetObject(0);
555 // OD 20.10.2003 #112616# - consider also first stripe
556 ASSERT( pStripes->Count(), "Empty scrollstripes" );
557 // OD 21.10.2003 #112616# - for savety reason:
558 // react, if precondition named in assertion isn't hold
559 if ( pStripes->Count() )
561 const SwStripe &rStripe = pStripes->GetObject(0);
562 SwRect aTmpRect = pScroll->IsVertical() ?
563 SwRect( rStripe.GetY() - rStripe.GetHeight(), pScroll->GetX(),
564 rStripe.GetHeight(), pScroll->GetWidth() ) :
565 SwRect( pScroll->GetX(), rStripe.GetY(),
566 pScroll->GetWidth(), rStripe.GetHeight() );
567 if( aTmpRect.IsOver( aRect ) )
569 // SwSaveHdl aSaveHdl( this );
570 if( !bNoRefresh )
571 _RefreshScrolledArea( aTmpRect );
573 // OD 20.10.2003 #112616# - consider also first stripe
574 pStripes->Remove( 0 );
576 if( pStripes->Count() < 1 )
578 pScroll->Remove( USHORT(0) );
579 delete pStripes;
582 if( !pScroll->Count() )
584 pScrolledArea->Remove( pScroll );
585 delete pScroll;
588 if( !pScrolledArea->Count() )
590 delete pScrolledArea;
591 pScrolledArea = 0;
595 //All done?
596 if( !pScrolledArea || !pScrolledArea->Count()
599 ResetScrolled();
600 SetNextScroll();
601 aScrollTimer.Stop();
604 DBG_PROFSTOP( RefreshTimer );
605 return 0;
608 /******************************************************************************
610 |* SwViewImp::_ScrolledRect(..)
612 |* Creation AMA 20. July 00
613 |* Last change AMA 21. July 00
615 |* handles the problem of scrolled criticals lines, when they are a part of
616 |* a scrolling area again. In this case, their rectangle has to move to the
617 |* right position.
619 ******************************************************************************/
621 void SwViewImp::_ScrolledRect( const SwRect& rRect, long nOffs )
623 for( USHORT i = pScrolledArea->Count(); i; )
625 SwScrollArea* pScroll = (*pScrolledArea)[--i];
626 ASSERT( pScroll->Count() == 1, "Missing scrollarea compression 1" );
627 SwStripes* pStripes = (*pScroll)[0];
628 if( pStripes->Count() )
630 SwRect aRect = pScroll->IsVertical() ?
631 SwRect( pStripes->GetY() - pStripes->GetHeight(),
632 pStripes->GetMin(), pStripes->GetHeight(),
633 pStripes->GetWidth() ) :
634 SwRect( pStripes->GetMin(), pStripes->GetY(),
635 pStripes->GetWidth(), pStripes->GetHeight() );
637 if( rRect.IsOver( aRect ) )
639 BOOL bRecalc = FALSE;
640 for( USHORT nI = pStripes->Count(); nI; )
642 if( pScroll->IsVertical() )
644 long nWidth = (*pStripes)[--nI].GetHeight();
645 aRect.Left( (*pStripes)[nI].GetY() - nWidth + 1 );
646 aRect.Width( nWidth );
648 else
650 aRect.Top( (*pStripes)[--nI].GetY() );
651 aRect.Height( (*pStripes)[nI].GetHeight() );
653 if( rRect.IsInside( aRect ) )
655 (*pStripes)[nI].Y() += nOffs;
656 bRecalc = TRUE;
659 if( bRecalc )
660 pStripes->Recalc( pScroll->IsVertical() );
666 /******************************************************************************
668 |* SwViewImp::_RefreshScrolledArea()
670 ******************************************************************************/
672 //Berechnen der Hoehe fuer das virtuelle Device, Breite und maximaler
673 //Speicherbedarf sind vorgegeben.
674 #define MAXKB 180L
676 static void lcl_CalcVirtHeight( OutputDevice *pOut, Size &rSz )
678 char nBytes;
679 const ULONG nColorCount = pOut->GetColorCount();
680 if( 256 >= nColorCount ) // 2^8
681 nBytes = 1;
682 else
683 if( USHRT_MAX >= nColorCount ) // 2^16
684 nBytes = 2;
685 else
686 if( 16777216 >= nColorCount ) // 2^24
687 nBytes = 3;
688 else
689 nBytes = 4; // 2^n
691 rSz = pOut->LogicToPixel( rSz );
693 long nKB = MAXKB * 1000;
694 nKB /= nBytes;
695 if ( rSz.Width() > 0 )
696 rSz.Height() = nKB / rSz.Width();
697 else
698 rSz.Height() = nKB;
700 rSz = pOut->PixelToLogic( rSz );
703 void SwViewImp::_RefreshScrolledArea( const SwRect &rRect )
705 SwRect aScRect( rRect );
706 aScRect.Intersection( GetShell()->VisArea() );
708 if( aScRect.IsEmpty() )
709 return;
711 BOOL bShowCrsr = FALSE;
712 Window *pWin = GetShell()->GetWin();
713 if ( pWin && pWin->GetCursor() && pWin->GetCursor()->IsVisible() )
715 bShowCrsr = TRUE;
716 pWin->GetCursor()->Hide();
719 //Virtuelles Device erzeugen und einstellen.
720 // --> OD 2007-08-16 #i80720#
721 // rename variable <pOld> to <pCurrentOut>
722 OutputDevice* pCurrentOut = GetShell()->GetOut();
723 VirtualDevice *pVout = new VirtualDevice( *pCurrentOut );
724 MapMode aMapMode( pCurrentOut->GetMapMode() );
725 pVout->SetMapMode( aMapMode );
726 Size aSize( aScRect.Width(), 0 );
727 lcl_CalcVirtHeight( pCurrentOut, aSize );
728 if ( aSize.Height() > aScRect.Height() )
729 aSize.Height() = aScRect.Height() + 50;
731 //unten in der Schleife lassen wir die Rechtecke ein wenig ueberlappen,
732 //das muss auch bei der Groesse beruecksichtigt werden.
733 aSize = pCurrentOut->LogicToPixel( aSize );
734 aSize.Width() += 4; aSize.Height() += 4;
735 aSize = pCurrentOut->PixelToLogic( aSize );
736 // <--
738 const SwRootFrm* pLayout = GetShell()->GetLayout();
740 // #i75172# Avoid VDev if PreRendering is active
741 static bool bDoNotUseVDev(GetDrawView()->IsBufferedOutputAllowed());
743 // --> OD 2007-08-16 #i80720#
744 // Enlarge paint rectangle also in case that "own" virtual device <pVout>
745 // isn't used. Refactor code a little bit to achieve this.
746 const bool bApplyVDev = !bDoNotUseVDev && pVout->SetOutputSize( aSize );
749 if ( bApplyVDev )
751 // --> OD 2007-08-16 #i80720#
752 // rename variable <pOld> to <pCurrentOut>
753 pVout->SetLineColor( pCurrentOut->GetLineColor() );
754 pVout->SetFillColor( pCurrentOut->GetFillColor() );
755 // <--
758 // #i72754# start Pre/PostPaint encapsulation before pOut is changed to the buffering VDev
759 const Region aRepaintRegion(aScRect.SVRect());
760 GetShell()->DLPrePaint2(aRepaintRegion);
762 //Virtuelles Device in die ViewShell 'selektieren'
763 // --> OD 2007-08-16 #i80720#
764 // remember current output device at this place
765 OutputDevice* pOldOut = GetShell()->GetOut();
766 // <--
767 if ( bApplyVDev )
769 GetShell()->pOut = pVout;
772 const SwFrm *pPg = GetFirstVisPage();
775 SwRect aRect( pPg->Frm() );
776 if ( aRect.IsOver( aScRect ) )
778 aRect._Intersection( aScRect );
781 Rectangle aTmp( aRect.SVRect() );
782 long nTmp = aTmp.Top() + aSize.Height();
783 if ( aTmp.Bottom() > nTmp )
784 aTmp.Bottom() = nTmp;
786 aTmp = pOldOut->LogicToPixel( aTmp );
787 if( aRect.Top() > pPg->Frm().Top() )
788 aTmp.Top() -= 2;
789 if( aRect.Top() + aRect.Height() < pPg->Frm().Top()
790 + pPg->Frm().Height() )
791 aTmp.Bottom() += 2;
792 if( aRect.Left() > pPg->Frm().Left() )
793 aTmp.Left() -= 2;
794 if( aRect.Left() + aRect.Width() < pPg->Frm().Left()
795 + pPg->Frm().Width() )
796 aTmp.Right() += 2;
797 aTmp = pOldOut->PixelToLogic( aTmp );
798 SwRect aTmp2( aTmp );
800 if ( bApplyVDev )
802 // OD 12.11.2002 #96272# - use method to set mapping
803 //Point aOrigin( aTmp2.Pos() );
804 //aOrigin.X() = -aOrigin.X(); aOrigin.Y() = -aOrigin.Y();
805 //aMapMode.SetOrigin( aOrigin );
806 ::SetMappingForVirtDev( aTmp2.Pos(), &aMapMode, pOldOut, pVout );
807 pVout->SetMapMode( aMapMode );
810 pLayout->Paint( aTmp2 );
811 if ( bApplyVDev )
813 pOldOut->DrawOutDev( aTmp2.Pos(), aTmp2.SSize(),
814 aTmp2.Pos(), aTmp2.SSize(), *pVout );
817 aRect.Top( aRect.Top() + aSize.Height() );
818 aScRect.Top( aRect.Top() );
820 } while ( aRect.Height() > 0 );
822 pPg = pPg->GetNext();
824 } while ( pPg && pPg->Frm().IsOver( GetShell()->VisArea() ) );
826 if ( bApplyVDev )
828 GetShell()->pOut = pOldOut;
830 delete pVout;
832 // #i72754# end Pre/PostPaint encapsulation when pOut is back and content is painted
833 GetShell()->DLPostPaint2(true);
835 // <--
837 if ( bShowCrsr )
838 pWin->GetCursor()->Show();
841 /******************************************************************************
843 |* SwViewImp::RefreshScrolledArea()
845 |* Ersterstellung MA 06. Oct. 94
846 |* Letzte Aenderung MA 19. Apr. 95
848 ******************************************************************************/
850 void SwViewImp::RefreshScrolledArea( SwRect &rRect )
852 // --> OD 2007-07-24 #123003# - make code robust
853 // avoid recursive call
854 static bool bRunning( false );
856 if ( bRunning )
858 ASSERT( false, "<SwViewImp::RefreshScrolledArea(..)> - recursive method call - please inform OD" );
859 return;
861 // <--
863 //1. Wird auch von der CrsrShell gerufen, um ggf. den Bereich, in den der
864 //Crsr gesetzt wird (Absatz, ganze Zeile bei einer Tabelle) aufzufrischen.
865 //Allerdings kann es dann natuerlich sein, dass das Rechteck ueberhaupt
866 //nicht mit aufzufrischenden Bereichen ueberlappt.
867 //2. Kein Refresh wenn eine Selektion besteht.
868 if( (GetShell()->IsA( TYPE(SwCrsrShell) ) &&
869 (((SwCrsrShell*)GetShell())->HasSelection() ||
870 ((SwCrsrShell*)GetShell())->GetCrsrCnt() > 1)))
872 return;
875 // --> OD 2007-07-27 #123003#
876 bRunning = true;
877 // <--
879 if( pScrolledArea && pScrolledArea->Count() &&
880 !( ( GetShell()->IsA( TYPE(SwCrsrShell) ) &&
881 ( ((SwCrsrShell*)GetShell())->HasSelection() ||
882 ((SwCrsrShell*)GetShell())->GetCrsrCnt() > 1) ) ) )
884 for( USHORT i = pScrolledArea->Count(); i; )
886 SwScrollArea* pScroll = (*pScrolledArea)[--i];
887 for( USHORT j = pScroll->Count(); j; )
889 SwStripes* pStripes = (*pScroll)[--j];
890 if( pStripes->Count() )
892 SwRect aRect = pScroll->IsVertical() ?
893 SwRect( pStripes->GetY() - pStripes->GetHeight(),
894 pStripes->GetMin(), pStripes->GetHeight(),
895 pStripes->GetWidth() ) :
896 SwRect( pStripes->GetMin(), pStripes->GetY(),
897 pStripes->GetWidth(), pStripes->GetHeight() );
898 if( rRect.IsOver( aRect ) )
900 for( USHORT nI = pStripes->Count(); nI; )
902 if( pScroll->IsVertical() )
904 long nWidth = (*pStripes)[--nI].GetHeight();
905 aRect.Left( (*pStripes)[nI].GetY() -nWidth +1 );
906 aRect.Width( nWidth );
908 else
910 aRect.Top( (*pStripes)[--nI].GetY() );
911 aRect.Height( (*pStripes)[nI].GetHeight() );
913 if( rRect.IsOver( aRect ) )
915 pStripes->Remove( nI );
916 _RefreshScrolledArea( aRect );
921 if( !pStripes->Count() )
923 pScroll->Remove( j );
924 delete pStripes;
927 if( !pScroll->Count() )
929 pScrolledArea->Remove( pScroll );
930 delete pScroll;
932 //Ist da jemand ungeduldig?
933 //Nur Mouse und Keyboard, weil wir sonst von jeder billigen
934 //Uhr unterbrochen werden.
935 if( GetpApp()->AnyInput( INPUT_MOUSEANDKEYBOARD ) )
936 break;
940 //All done?
941 if( !pScrolledArea || !pScrolledArea->Count() )
943 ResetScrolled();
944 SetNextScroll();
945 aScrollTimer.Stop();
948 // --> OD 2007-07-24 #123003#
949 bRunning = false;
950 // <--
953 SwStripes& SwStripes::Plus( const SwStripes& rOther, BOOL bVert )
955 if( !Count() )
957 Insert( &rOther, 0 );
958 SetMin( rOther.GetMin() );
959 SetMax( rOther.GetMax() );
960 return *this;
963 long nCnt = rOther.Count();
964 if( nCnt )
966 ChkMin( rOther.GetMin() );
967 ChkMax( rOther.GetMax() );
968 USHORT nStart = 0;
969 if( bVert )
970 for( USHORT nIdx = 0; nIdx < nCnt; ++nIdx )
972 const SwStripe& rAdd = rOther[ nIdx ];
973 long nBottom = rAdd.GetY() - rAdd.GetHeight();
974 USHORT nCount = Count();
975 USHORT nTmpY = nStart;
976 while( nTmpY < nCount )
978 SwStripe& rChk = GetObject( nTmpY );
979 if( rChk.GetY() - rChk.GetHeight() < rAdd.GetY() )
980 break;
981 else
982 ++nTmpY;
984 USHORT nB = nTmpY;
985 while( nB < nCount )
987 const SwStripe& rChk = GetObject( nB );
988 if( rChk.GetY() <= nBottom )
989 break;
990 else
991 ++nB;
993 nStart = nTmpY;
994 if( nTmpY == nB )
995 Insert( rAdd, nTmpY );
996 else
998 long nChkBottom = rAdd.GetY() - rAdd.GetHeight();;
999 const SwStripe& rChkB = GetObject( nB - 1 );
1000 long nTmp = rChkB.GetY() - rChkB.GetHeight();
1001 if( nTmp < nChkBottom )
1002 nChkBottom = nTmp;
1003 SwStripe& rChk = GetObject( nTmpY );
1004 if( rAdd.GetY() > rChk.GetY() )
1005 rChk.Y() = rAdd.GetY();
1006 rChk.Height() = rChk.GetY() - nChkBottom;
1007 nChkBottom = nB - nTmpY - 1;
1008 if( nChkBottom )
1009 Remove( nTmpY + 1, (USHORT)nChkBottom );
1012 else
1014 for( USHORT nIdx = 0; nIdx < nCnt; ++nIdx )
1016 const SwStripe& rAdd = rOther[ nIdx ];
1017 long nBottom = rAdd.GetY() + rAdd.GetHeight();
1018 USHORT nCount = Count();
1019 USHORT nTmpY = nStart;
1020 while( nTmpY < nCount )
1022 SwStripe& rChk = GetObject( nTmpY );
1023 if( rChk.GetY() + rChk.GetHeight() > rAdd.GetY() )
1024 break;
1025 else
1026 ++nTmpY;
1028 USHORT nB = nTmpY;
1029 while( nB < nCount )
1031 const SwStripe& rChk = GetObject( nB );
1032 if( rChk.GetY() >= nBottom )
1033 break;
1034 else
1035 ++nB;
1037 nStart = nTmpY;
1038 if( nTmpY == nB )
1039 Insert( rAdd, nTmpY );
1040 else
1042 long nChkBottom = rAdd.GetY() + rAdd.GetHeight();;
1043 const SwStripe& rChkB = GetObject( nB - 1 );
1044 long nTmp = rChkB.GetY() + rChkB.GetHeight();
1045 if( nTmp > nChkBottom )
1046 nChkBottom = nTmp;
1047 SwStripe& rChk = GetObject( nTmpY );
1048 if( rAdd.GetY() < rChk.GetY() )
1049 rChk.Y() = rAdd.GetY();
1050 rChk.Height() = nChkBottom - rChk.GetY();
1051 nChkBottom = nB - nTmpY - 1;
1052 if( nChkBottom )
1053 Remove( nTmpY + 1, (USHORT)nChkBottom );
1058 return *this;
1061 BOOL SwStripes::Recalc( BOOL bVert )
1063 if( !Count() )
1064 return TRUE;
1065 Y() = GetObject(0).GetY();
1066 if( bVert )
1068 long nTmpMin = GetObject(0).GetY() - GetObject(0).Height();
1069 for( USHORT nIdx = 1; nIdx < Count(); )
1071 const SwStripe& rStr = GetObject(nIdx++);
1072 if( GetY() < rStr.GetY() )
1073 Y() = rStr.GetY();
1074 if( nTmpMin > rStr.GetY() - rStr.GetHeight() )
1075 nTmpMin = rStr.GetY() - rStr.GetHeight();
1077 Height() = GetY() - nTmpMin;
1079 else
1081 long nTmpMax = GetObject(0).GetY() + GetObject(0).Height();
1082 for( USHORT nIdx = 1; nIdx < Count(); )
1084 const SwStripe& rStr = GetObject(nIdx++);
1085 if( GetY() > rStr.GetY() )
1086 Y() = rStr.GetY();
1087 if( nTmpMax < rStr.GetY() + rStr.GetHeight() )
1088 nTmpMax = rStr.GetY() + rStr.GetHeight();
1090 Height() = nTmpMax - GetY();
1092 return FALSE;
1095 BOOL SwScrollArea::Compress()
1097 if( !Count() )
1098 return TRUE;
1099 for( USHORT nIdx = Count() - 1; nIdx > 0; --nIdx )
1101 GetObject(0)->Plus( *GetObject(nIdx), IsVertical() );
1102 delete GetObject( nIdx );
1103 Remove( nIdx, 1 );
1105 ClrOffs();
1106 return GetObject(0)->Recalc( IsVertical() );
1109 void SwScrollArea::Add( SwScrollArea *pScroll )
1111 ASSERT( pScroll->Count() == 1, "Missing scrollarea compression 2" );
1112 ASSERT( Count() == 1, "Missing scrollarea compression 3" );
1113 GetObject(0)->Plus( *pScroll->GetObject(0), IsVertical() );
1114 GetObject(0)->Recalc( IsVertical() );
1115 delete pScroll->GetObject( 0 );
1116 pScroll->Remove( (USHORT)0, 1 );
1117 delete pScroll;
1120 /******************************************************************************
1122 |* SwScrollAreas::Insert(..)
1124 ******************************************************************************/
1126 void SwScrollAreas::InsertCol( const SwScrollColumn &rCol,
1127 SwStripes *pStripes )
1129 SwScrollArea *pTmp = new SwScrollArea( rCol, pStripes );
1130 USHORT nIdx;
1131 if( Seek_Entry( pTmp, &nIdx ) )
1133 GetObject( nIdx )->SmartInsert( pStripes );
1134 delete pTmp;
1136 else
1137 Insert( pTmp );
1141 void SwScrollArea::SmartInsert( SwStripes* pStripes )
1143 ASSERT( pStripes, "Insert empty scrollstripe?" );
1144 BOOL bNotInserted = TRUE;
1145 if( IsVertical() )
1146 for( USHORT nIdx = 0; nIdx < Count() && bNotInserted; )
1148 SwStripes* pTmp = GetObject( nIdx++ );
1149 if( pTmp->GetY() - pTmp->GetHeight() == pStripes->GetY() )
1151 pTmp->Height() += pStripes->GetHeight();
1152 pTmp->ChkMin( pStripes->GetMin() );
1153 pTmp->ChkMax( pStripes->GetMax() );
1154 if( pStripes->Count() )
1155 pTmp->Insert( (SwStripeArr*)pStripes, pTmp->Count(), 0 );
1156 bNotInserted = FALSE;
1158 else if( pTmp->GetY() == pStripes->GetY() - pStripes->GetHeight() )
1160 pTmp->Height() += pStripes->GetHeight();
1161 pTmp->Y() = pStripes->GetY();
1162 pTmp->ChkMin( pStripes->GetMin() );
1163 pTmp->ChkMax( pStripes->GetMax() );
1164 if( pStripes->Count() )
1165 pTmp->Insert( (SwStripeArr*)pStripes, 0, 0 );
1166 bNotInserted = FALSE;
1169 else
1170 for( USHORT nIdx = 0; nIdx < Count() && bNotInserted; )
1172 SwStripes* pTmp = GetObject( nIdx++ );
1173 if( pTmp->GetY() + pTmp->GetHeight() == pStripes->GetY() )
1175 pTmp->Height() += pStripes->GetHeight();
1176 pTmp->ChkMin( pStripes->GetMin() );
1177 pTmp->ChkMax( pStripes->GetMax() );
1178 if( pStripes->Count() )
1179 pTmp->Insert( (SwStripeArr*)pStripes, pTmp->Count(), 0 );
1180 bNotInserted = FALSE;
1182 else if( pTmp->GetY() == pStripes->GetY() + pStripes->GetHeight() )
1184 pTmp->Height() += pStripes->GetHeight();
1185 pTmp->Y() = pStripes->GetY();
1186 pTmp->ChkMin( pStripes->GetMin() );
1187 pTmp->ChkMax( pStripes->GetMax() );
1188 if( pStripes->Count() )
1189 pTmp->Insert( (SwStripeArr*)pStripes, 0, 0 );
1190 bNotInserted = FALSE;
1193 if( !bNotInserted || !Insert( pStripes ) )
1194 delete pStripes;