1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: tabview2.cxx,v $
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_sc.hxx"
36 // INCLUDE ---------------------------------------------------------------
38 #include "scitems.hxx"
39 #include <svx/eeitem.hxx>
42 #include <vcl/timer.hxx>
43 #include <vcl/msgbox.hxx>
44 #include <sfx2/app.hxx>
45 #include <sfx2/viewfrm.hxx>
46 #include <sfx2/bindings.hxx>
47 #include <sfx2/childwin.hxx>
50 #include "pagedata.hxx"
51 #include "tabview.hxx"
52 #include "tabvwsh.hxx"
53 #include "printfun.hxx"
54 #include "stlpool.hxx"
56 #include "gridwin.hxx"
57 #include "olinewin.hxx"
58 #include "uiitems.hxx"
60 #include "viewutil.hxx"
61 #include "colrowba.hxx"
62 #include "waitoff.hxx"
63 #include "globstr.hrc"
65 #include "tabprotection.hxx"
67 #define SC_BLOCKMODE_NONE 0
68 #define SC_BLOCKMODE_NORMAL 1
69 #define SC_BLOCKMODE_OWN 2
74 // Markier - Funktionen
77 void ScTabView::PaintMarks(SCCOL nStartCol
, SCROW nStartRow
, SCCOL nEndCol
, SCROW nEndRow
)
79 if (!ValidCol(nStartCol
)) nStartCol
= MAXCOL
;
80 if (!ValidRow(nStartRow
)) nStartRow
= MAXROW
;
81 if (!ValidCol(nEndCol
)) nEndCol
= MAXCOL
;
82 if (!ValidRow(nEndRow
)) nEndRow
= MAXROW
;
84 BOOL bLeft
= (nStartCol
==0 && nEndCol
==MAXCOL
);
85 BOOL bTop
= (nStartRow
==0 && nEndRow
==MAXROW
);
88 PaintLeftArea( nStartRow
, nEndRow
);
90 PaintTopArea( nStartCol
, nEndCol
);
92 aViewData
.GetDocument()->ExtendMerge( nStartCol
, nStartRow
, nEndCol
, nEndRow
,
93 aViewData
.GetTabNo() );
94 PaintArea( nStartCol
, nStartRow
, nEndCol
, nEndRow
, SC_UPDATE_MARKS
);
97 BOOL
ScTabView::IsMarking( SCCOL nCol
, SCROW nRow
, SCTAB nTab
) const
100 && nBlockStartX
== nCol
101 && nBlockStartY
== nRow
102 && nBlockStartZ
== nTab
;
105 void ScTabView::InitOwnBlockMode()
109 // Wenn keine (alte) Markierung mehr da ist, Anker in SelectionEngine loeschen:
111 ScMarkData
& rMark
= aViewData
.GetMarkData();
112 if (!rMark
.IsMarked() && !rMark
.IsMultiMarked())
113 GetSelEngine()->CursorPosChanging( FALSE
, FALSE
);
115 // bIsBlockMode = TRUE;
116 bIsBlockMode
= SC_BLOCKMODE_OWN
; //! Variable umbenennen!
124 SelectionChanged(); // Status wird mit gesetzer Markierung abgefragt
128 void ScTabView::InitBlockMode( SCCOL nCurX
, SCROW nCurY
, SCTAB nCurZ
,
129 BOOL bTestNeg
, BOOL bCols
, BOOL bRows
)
133 if (!ValidCol(nCurX
)) nCurX
= MAXCOL
;
134 if (!ValidRow(nCurY
)) nCurY
= MAXROW
;
136 ScMarkData
& rMark
= aViewData
.GetMarkData();
137 SCTAB nTab
= aViewData
.GetTabNo();
139 // Teil von Markierung aufheben?
143 bBlockNeg
= rMark
.IsColumnMarked( nCurX
);
145 bBlockNeg
= rMark
.IsRowMarked( nCurY
);
147 bBlockNeg
= rMark
.IsCellMarked( nCurX
, nCurY
);
151 rMark
.SetMarkNegative(bBlockNeg
);
153 // bIsBlockMode = TRUE;
154 bIsBlockMode
= SC_BLOCKMODE_NORMAL
; //! Variable umbenennen!
157 nBlockStartX
= nBlockStartXOrig
= nCurX
;
158 nBlockStartY
= nBlockStartYOrig
= nCurY
;
159 nBlockStartZ
= nCurZ
;
160 nBlockEndX
= nOldCurX
= nBlockStartX
;
161 nBlockEndY
= nOldCurY
= nBlockStartY
;
162 nBlockEndZ
= nBlockStartZ
;
166 nBlockStartY
= nBlockStartYOrig
= 0;
172 nBlockStartX
= nBlockStartXOrig
= 0;
176 rMark
.SetMarkArea( ScRange( nBlockStartX
,nBlockStartY
, nTab
, nBlockEndX
,nBlockEndY
, nTab
) );
178 #ifdef OLD_SELECTION_PAINT
179 InvertBlockMark( nBlockStartX
,nBlockStartY
,nBlockEndX
,nBlockEndY
);
181 UpdateSelectionOverlay();
185 void ScTabView::DoneBlockMode( BOOL bContinue
) // Default FALSE
187 // Wenn zwischen Tabellen- und Header SelectionEngine gewechselt wird,
188 // wird evtl. DeselectAll gerufen, weil die andere Engine keinen Anker hat.
189 // Mit bMoveIsShift wird verhindert, dass dann die Selektion aufgehoben wird.
191 if (bIsBlockMode
&& !bMoveIsShift
)
193 ScMarkData
& rMark
= aViewData
.GetMarkData();
194 BOOL bFlag
= rMark
.GetMarkingFlag();
195 rMark
.SetMarking(FALSE
);
197 if (bBlockNeg
&& !bContinue
)
204 // Die Tabelle kann an dieser Stelle ungueltig sein, weil DoneBlockMode
205 // aus SetTabNo aufgerufen wird
206 // (z.B. wenn die aktuelle Tabelle von einer anderen View aus geloescht wird)
208 SCTAB nTab
= aViewData
.GetTabNo();
209 ScDocument
* pDoc
= aViewData
.GetDocument();
210 if ( pDoc
->HasTable(nTab
) )
211 PaintBlock( TRUE
); // TRUE -> Block loeschen
215 // bIsBlockMode = FALSE;
216 bIsBlockMode
= SC_BLOCKMODE_NONE
; //! Variable umbenennen!
218 rMark
.SetMarking(bFlag
);
219 rMark
.SetMarkNegative(FALSE
);
223 void ScTabView::MarkCursor( SCCOL nCurX
, SCROW nCurY
, SCTAB nCurZ
,
224 BOOL bCols
, BOOL bRows
, BOOL bCellSelection
)
226 if (!ValidCol(nCurX
)) nCurX
= MAXCOL
;
227 if (!ValidRow(nCurY
)) nCurY
= MAXROW
;
231 DBG_ERROR( "MarkCursor nicht im BlockMode" );
232 InitBlockMode( nCurX
, nCurY
, nCurZ
, FALSE
, bCols
, bRows
);
240 ScMarkData
& rMark
= aViewData
.GetMarkData();
241 DBG_ASSERT(rMark
.IsMarked() || rMark
.IsMultiMarked(), "MarkCursor, !IsMarked()");
243 rMark
.GetMarkArea(aMarkRange
);
244 if (( aMarkRange
.aStart
.Col() != nBlockStartX
&& aMarkRange
.aEnd
.Col() != nBlockStartX
) ||
245 ( aMarkRange
.aStart
.Row() != nBlockStartY
&& aMarkRange
.aEnd
.Row() != nBlockStartY
) ||
246 ( bIsBlockMode
== SC_BLOCKMODE_OWN
))
248 // Markierung ist veraendert worden
249 // (z.B. MarkToSimple, wenn per negativ alles bis auf ein Rechteck geloescht wurde)
250 // oder nach InitOwnBlockMode wird mit Shift-Klick weitermarkiert...
252 BOOL bOldShift
= bMoveIsShift
;
253 bMoveIsShift
= FALSE
; // wirklich umsetzen
254 DoneBlockMode(FALSE
); //! direkt Variablen setzen? (-> kein Geflacker)
255 bMoveIsShift
= bOldShift
;
257 InitBlockMode( aMarkRange
.aStart
.Col(), aMarkRange
.aStart
.Row(),
258 nBlockStartZ
, rMark
.IsMarkNegative(), bCols
, bRows
);
261 SCCOL nOldBlockEndX
= nBlockEndX
;
262 SCROW nOldBlockEndY
= nBlockEndY
;
264 if ( nCurX
!= nOldCurX
|| nCurY
!= nOldCurY
)
266 // Current cursor has moved
270 #ifdef OLD_SELECTION_PAINT
277 // Set old selection area
278 ScUpdateRect
aRect( nBlockStartX
, nBlockStartY
, nOldBlockEndX
, nOldBlockEndY
);
280 if ( bCellSelection
)
282 // Expand selection area accordingly when the current selection ends
283 // with a merged cell.
284 SCsCOL nCurXOffset
= 0;
285 SCsCOL nBlockStartXOffset
= 0;
286 SCsROW nCurYOffset
= 0;
287 SCsROW nBlockStartYOffset
= 0;
288 BOOL bBlockStartMerged
= FALSE
;
289 const ScMergeAttr
* pMergeAttr
= NULL
;
290 ScDocument
* pDocument
= aViewData
.GetDocument();
292 // The following block checks whether or not the "BlockStart" (anchor)
293 // cell is merged. If it's merged, it'll then move the position of the
294 // anchor cell to the corner that's diagonally opposite of the
295 // direction of a current selection area. For instance, if a current
296 // selection is moving in the upperleft direction, the anchor cell will
297 // move to the lower-right corner of the merged anchor cell, and so on.
299 pMergeAttr
= static_cast<const ScMergeAttr
*>(
300 pDocument
->GetAttr( nBlockStartXOrig
, nBlockStartYOrig
, nTab
, ATTR_MERGE
) );
301 if ( pMergeAttr
->IsMerged() )
303 SCsCOL nColSpan
= pMergeAttr
->GetColMerge();
304 SCsROW nRowSpan
= pMergeAttr
->GetRowMerge();
306 if ( !( nCurX
>= nBlockStartXOrig
+ nColSpan
- 1 && nCurY
>= nBlockStartYOrig
+ nRowSpan
- 1 ) )
308 nBlockStartX
= nCurX
>= nBlockStartXOrig
? nBlockStartXOrig
: nBlockStartXOrig
+ nColSpan
- 1;
309 nBlockStartY
= nCurY
>= nBlockStartYOrig
? nBlockStartYOrig
: nBlockStartYOrig
+ nRowSpan
- 1;
310 nCurXOffset
= nCurX
>= nBlockStartXOrig
&& nCurX
< nBlockStartXOrig
+ nColSpan
- 1 ?
311 nBlockStartXOrig
- nCurX
+ nColSpan
- 1 : 0;
312 nCurYOffset
= nCurY
>= nBlockStartYOrig
&& nCurY
< nBlockStartYOrig
+ nRowSpan
- 1 ?
313 nBlockStartYOrig
- nCurY
+ nRowSpan
- 1 : 0;
314 bBlockStartMerged
= TRUE
;
318 // The following block checks whether or not the current cell is
319 // merged. If it is, it'll then set the appropriate X & Y offset
320 // values (nCurXOffset & nCurYOffset) such that the selection area will
321 // grow by those specified offset amounts. Note that the values of
322 // nCurXOffset/nCurYOffset may also be specified in the previous code
323 // block, in which case whichever value is greater will take on.
325 pMergeAttr
= static_cast<const ScMergeAttr
*>(
326 pDocument
->GetAttr( nCurX
, nCurY
, nTab
, ATTR_MERGE
) );
327 if ( pMergeAttr
->IsMerged() )
329 SCsCOL nColSpan
= pMergeAttr
->GetColMerge();
330 SCsROW nRowSpan
= pMergeAttr
->GetRowMerge();
332 if ( !( nBlockStartX
>= nCurX
+ nColSpan
- 1 && nBlockStartY
>= nCurY
+ nRowSpan
- 1 ) )
334 if ( nBlockStartX
<= nCurX
+ nColSpan
- 1 )
336 SCsCOL nCurXOffsetTemp
= nCurX
< nCurX
+ nColSpan
- 1 ? nColSpan
- 1 : 0;
337 nCurXOffset
= nCurXOffset
> nCurXOffsetTemp
? nCurXOffset
: nCurXOffsetTemp
;
339 if ( nBlockStartY
<= nCurY
+ nRowSpan
- 1 )
341 SCsROW nCurYOffsetTemp
= nCurY
< nCurY
+ nRowSpan
- 1 ? nRowSpan
- 1 : 0;
342 nCurYOffset
= nCurYOffset
> nCurYOffsetTemp
? nCurYOffset
: nCurYOffsetTemp
;
344 if ( !( nBlockStartX
<= nCurX
&& nBlockStartY
<= nCurY
) &&
345 !( nBlockStartX
> nCurX
+ nColSpan
- 1 && nBlockStartY
> nCurY
+ nRowSpan
- 1 ) )
347 nBlockStartXOffset
= nBlockStartX
> nCurX
&& nBlockStartX
<= nCurX
+ nColSpan
- 1 ? nCurX
- nBlockStartX
: 0;
348 nBlockStartYOffset
= nBlockStartY
> nCurY
&& nBlockStartY
<= nCurY
+ nRowSpan
- 1 ? nCurY
- nBlockStartY
: 0;
354 // The current cell is not merged. Move the anchor cell to its
355 // original position.
356 if ( !bBlockStartMerged
)
358 nBlockStartX
= nBlockStartXOrig
;
359 nBlockStartY
= nBlockStartYOrig
;
363 nBlockStartX
= nBlockStartX
+ nBlockStartXOffset
>= 0 ? nBlockStartX
+ nBlockStartXOffset
: 0;
364 nBlockStartY
= nBlockStartY
+ nBlockStartYOffset
>= 0 ? nBlockStartY
+ nBlockStartYOffset
: 0;
365 nBlockEndX
= nCurX
+ nCurXOffset
> MAXCOL
? MAXCOL
: nCurX
+ nCurXOffset
;
366 nBlockEndY
= nCurY
+ nCurYOffset
> MAXROW
? MAXROW
: nCurY
+ nCurYOffset
;
373 // end of "if ( bCellSelection )"
375 // Set new selection area
376 aRect
.SetNew( nBlockStartX
, nBlockStartY
, nBlockEndX
, nBlockEndY
);
377 rMark
.SetMarkArea( ScRange( nBlockStartX
, nBlockStartY
, nTab
, nBlockEndX
, nBlockEndY
, nTab
) );
379 #ifdef OLD_SELECTION_PAINT
381 BOOL bDraw
= aRect
.GetXorDiff( nDrawStartCol
, nDrawStartRow
,
382 nDrawEndCol
, nDrawEndRow
, bCont
);
385 //? PutInOrder( nDrawStartCol, nDrawEndCol );
386 //? PutInOrder( nDrawStartRow, nDrawEndRow );
389 InvertBlockMark( nDrawStartCol
, nDrawStartRow
, nDrawEndCol
, nDrawEndRow
);
392 aRect
.GetContDiff( nDrawStartCol
, nDrawStartRow
, nDrawEndCol
, nDrawEndRow
);
393 InvertBlockMark( nDrawStartCol
, nDrawStartRow
, nDrawEndCol
, nDrawEndRow
);
398 UpdateSelectionOverlay();
403 aViewData
.GetViewShell()->UpdateInputHandler();
404 // InvalidateAttribs();
407 if ( !bCols
&& !bRows
)
408 aHdrFunc
.SetAnchorFlag( FALSE
);
411 void ScTabView::GetPageMoveEndPosition(SCsCOL nMovX
, SCsROW nMovY
, SCsCOL
& rPageX
, SCsROW
& rPageY
)
415 aViewData
.GetMoveCursor( nCurX
,nCurY
);
417 ScSplitPos eWhich
= aViewData
.GetActivePart();
418 ScHSplitPos eWhichX
= WhichH( eWhich
);
419 ScVSplitPos eWhichY
= WhichV( eWhich
);
424 nPageX
= ((SCsCOL
) aViewData
.CellsAtX( nCurX
, 1, eWhichX
)) * nMovX
;
426 nPageX
= ((SCsCOL
) aViewData
.CellsAtX( nCurX
, -1, eWhichX
)) * nMovX
;
429 nPageY
= ((SCsROW
) aViewData
.CellsAtY( nCurY
, 1, eWhichY
)) * nMovY
;
431 nPageY
= ((SCsROW
) aViewData
.CellsAtY( nCurY
, -1, eWhichY
)) * nMovY
;
433 if (nMovX
!= 0 && nPageX
== 0) nPageX
= (nMovX
>0) ? 1 : -1;
434 if (nMovY
!= 0 && nPageY
== 0) nPageY
= (nMovY
>0) ? 1 : -1;
440 void ScTabView::GetAreaMoveEndPosition(SCsCOL nMovX
, SCsROW nMovY
, ScFollowMode eMode
,
441 SCsCOL
& rAreaX
, SCsROW
& rAreaY
, ScFollowMode
& rMode
)
448 if (aViewData
.IsRefMode())
450 nNewX
= aViewData
.GetRefEndX();
451 nNewY
= aViewData
.GetRefEndY();
453 else if (IsBlockMode())
460 nNewX
= nCurX
= aViewData
.GetCurX();
461 nNewY
= nCurY
= aViewData
.GetCurY();
464 ScDocument
* pDoc
= aViewData
.GetDocument();
465 SCTAB nTab
= aViewData
.GetTabNo();
467 // FindAreaPos kennt nur -1 oder 1 als Richtung
471 for ( i
=0; i
<nMovX
; i
++ )
472 pDoc
->FindAreaPos( nNewX
, nNewY
, nTab
, 1, 0 );
474 for ( i
=0; i
<-nMovX
; i
++ )
475 pDoc
->FindAreaPos( nNewX
, nNewY
, nTab
, -1, 0 );
477 for ( i
=0; i
<nMovY
; i
++ )
478 pDoc
->FindAreaPos( nNewX
, nNewY
, nTab
, 0, 1 );
480 for ( i
=0; i
<-nMovY
; i
++ )
481 pDoc
->FindAreaPos( nNewX
, nNewY
, nTab
, 0, -1 );
483 if (eMode
==SC_FOLLOW_JUMP
) // unten/rechts nicht zuviel grau anzeigen
485 if (nMovX
!= 0 && nNewX
== MAXCOL
)
486 eMode
= SC_FOLLOW_LINE
;
487 if (nMovY
!= 0 && nNewY
== MAXROW
)
488 eMode
= SC_FOLLOW_LINE
;
491 if (aViewData
.IsRefMode())
493 rAreaX
= nNewX
- aViewData
.GetRefEndX();
494 rAreaY
= nNewY
- aViewData
.GetRefEndY();
496 else if (IsBlockMode())
498 rAreaX
= nNewX
- nBlockEndX
;
499 rAreaY
= nNewY
- nBlockEndY
;
503 rAreaX
= nNewX
- nCurX
;
504 rAreaY
= nNewY
- nCurY
;
511 bool lcl_isCellQualified(ScDocument
* pDoc
, SCCOL nCol
, SCROW nRow
, SCTAB nTab
, bool bSelectLocked
, bool bSelectUnlocked
)
513 bool bCellProtected
= pDoc
->HasAttrib(
514 nCol
, nRow
, nTab
, nCol
, nRow
, nTab
, HASATTR_PROTECTED
);
516 if (bCellProtected
&& !bSelectLocked
)
519 if (!bCellProtected
&& !bSelectUnlocked
)
525 void lcl_moveCursorByProtRule(
526 SCCOL
& rCol
, SCROW
& rRow
, SCsCOL nMovX
, SCsROW nMovY
, SCTAB nTab
, ScDocument
* pDoc
)
528 bool bSelectLocked
= true;
529 bool bSelectUnlocked
= true;
530 ScTableProtection
* pTabProtection
= pDoc
->GetTabProtection(nTab
);
531 if (pTabProtection
&& pTabProtection
->isProtected())
533 bSelectLocked
= pTabProtection
->isOptionEnabled(ScTableProtection::SELECT_LOCKED_CELLS
);
534 bSelectUnlocked
= pTabProtection
->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS
);
541 for (SCCOL i
= 0; i
< nMovX
; ++i
)
543 if (!lcl_isCellQualified(pDoc
, rCol
+1, rRow
, nTab
, bSelectLocked
, bSelectUnlocked
))
554 for (SCCOL i
= 0; i
< nMovX
; ++i
)
556 if (!lcl_isCellQualified(pDoc
, rCol
-1, rRow
, nTab
, bSelectLocked
, bSelectUnlocked
))
567 for (SCROW i
= 0; i
< nMovY
; ++i
)
569 if (!lcl_isCellQualified(pDoc
, rCol
, rRow
+1, nTab
, bSelectLocked
, bSelectUnlocked
))
580 for (SCROW i
= 0; i
< nMovY
; ++i
)
582 if (!lcl_isCellQualified(pDoc
, rCol
, rRow
-1, nTab
, bSelectLocked
, bSelectUnlocked
))
592 void ScTabView::ExpandBlock(SCsCOL nMovX
, SCsROW nMovY
, ScFollowMode eMode
)
594 if (!nMovX
&& !nMovY
)
595 // Nothing to do. Bail out.
598 ScTabViewShell
* pViewShell
= aViewData
.GetViewShell();
599 bool bRefInputMode
= pViewShell
&& pViewShell
->IsRefInputMode();
600 if (bRefInputMode
&& !aViewData
.IsRefMode())
601 // initialize formula reference mode if it hasn't already.
602 InitRefMode(aViewData
.GetCurX(), aViewData
.GetCurY(), aViewData
.GetTabNo(), SC_REFTYPE_REF
);
604 ScDocument
* pDoc
= aViewData
.GetDocument();
606 if (aViewData
.IsRefMode())
608 // formula reference mode
610 SCCOL nNewX
= aViewData
.GetRefEndX();
611 SCROW nNewY
= aViewData
.GetRefEndY();
612 SCTAB nRefTab
= aViewData
.GetRefEndZ();
614 bool bSelectLocked
= true;
615 bool bSelectUnlocked
= true;
616 ScTableProtection
* pTabProtection
= pDoc
->GetTabProtection(nRefTab
);
617 if (pTabProtection
&& pTabProtection
->isProtected())
619 bSelectLocked
= pTabProtection
->isOptionEnabled(ScTableProtection::SELECT_LOCKED_CELLS
);
620 bSelectUnlocked
= pTabProtection
->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS
);
623 lcl_moveCursorByProtRule(nNewX
, nNewY
, nMovX
, nMovY
, nRefTab
, pDoc
);
627 SCCOL nTempX
= nNewX
;
628 while (pDoc
->IsHorOverlapped(nTempX
, nNewY
, nRefTab
))
635 if (lcl_isCellQualified(pDoc
, nTempX
, nNewY
, nRefTab
, bSelectLocked
, bSelectUnlocked
))
641 SCROW nTempY
= nNewY
;
642 while (pDoc
->IsVerOverlapped(nNewX
, nTempY
, nRefTab
))
649 if (lcl_isCellQualified(pDoc
, nNewX
, nTempY
, nRefTab
, bSelectLocked
, bSelectUnlocked
))
653 pDoc
->SkipOverlapped(nNewX
, nNewY
, nRefTab
);
654 UpdateRef(nNewX
, nNewY
, nRefTab
);
655 AlignToCursor(nNewX
, nNewY
, eMode
);
659 // normal selection mode
661 SCTAB nTab
= aViewData
.GetTabNo();
664 InitBlockMode(aViewData
.GetCurX(), aViewData
.GetCurY(), nTab
, true);
666 lcl_moveCursorByProtRule(nBlockEndX
, nBlockEndY
, nMovX
, nMovY
, nTab
, pDoc
);
670 else if (nBlockEndX
> MAXCOL
)
675 else if (nBlockEndY
> MAXROW
)
678 pDoc
->SkipOverlapped(nBlockEndX
, nBlockEndY
, nTab
);
679 MarkCursor(nBlockEndX
, nBlockEndY
, nTab
, false, false, true);
681 // Check if the entire row(s) or column(s) are selected.
682 ScSplitPos eActive
= aViewData
.GetActivePart();
683 bool bRowSelected
= (nBlockStartX
== 0 && nBlockEndX
== MAXCOL
);
684 bool bColSelected
= (nBlockStartY
== 0 && nBlockEndY
== MAXROW
);
685 SCsCOL nAlignX
= bRowSelected
? aViewData
.GetPosX(WhichH(eActive
)) : nBlockEndX
;
686 SCsROW nAlignY
= bColSelected
? aViewData
.GetPosY(WhichV(eActive
)) : nBlockEndY
;
687 AlignToCursor(nAlignX
, nAlignY
, eMode
);
689 UpdateAutoFillMark();
693 void ScTabView::ExpandBlockPage(SCsCOL nMovX
, SCsROW nMovY
)
697 GetPageMoveEndPosition(nMovX
, nMovY
, nPageX
, nPageY
);
698 ExpandBlock(nPageX
, nPageY
, SC_FOLLOW_FIX
);
701 void ScTabView::ExpandBlockArea(SCsCOL nMovX
, SCsROW nMovY
)
706 GetAreaMoveEndPosition(nMovX
, nMovY
, SC_FOLLOW_JUMP
, nAreaX
, nAreaY
, eMode
);
707 ExpandBlock(nAreaX
, nAreaY
, eMode
);
710 void ScTabView::UpdateSelectionOverlay()
712 for (USHORT i
=0; i
<4; i
++)
713 if ( pGridWin
[i
] && pGridWin
[i
]->IsVisible() )
714 pGridWin
[i
]->UpdateSelectionOverlay();
717 void ScTabView::UpdateShrinkOverlay()
719 for (USHORT i
=0; i
<4; i
++)
720 if ( pGridWin
[i
] && pGridWin
[i
]->IsVisible() )
721 pGridWin
[i
]->UpdateShrinkOverlay();
724 void ScTabView::UpdateAllOverlays()
726 for (USHORT i
=0; i
<4; i
++)
727 if ( pGridWin
[i
] && pGridWin
[i
]->IsVisible() )
728 pGridWin
[i
]->UpdateAllOverlays();
732 //! PaintBlock in zwei Methoden aufteilen: RepaintBlock und RemoveBlock o.ae.
735 void ScTabView::PaintBlock( BOOL bReset
)
737 ScDocument
* pDoc
= aViewData
.GetDocument();
738 ScMarkData
& rMark
= aViewData
.GetMarkData();
739 SCTAB nTab
= aViewData
.GetTabNo();
740 BOOL bMark
= rMark
.IsMarked();
741 BOOL bMulti
= rMark
.IsMultiMarked();
748 BOOL bFlag
= rMark
.GetMarkingFlag();
749 rMark
.SetMarking(FALSE
);
751 rMark
.GetMultiMarkArea(aMarkRange
);
752 rMark
.MarkToSimple();
753 rMark
.SetMarking(bFlag
);
755 bMark
= rMark
.IsMarked();
756 bMulti
= rMark
.IsMultiMarked();
759 rMark
.GetMarkArea(aMarkRange
);
761 nBlockStartX
= aMarkRange
.aStart
.Col();
762 nBlockStartY
= aMarkRange
.aStart
.Row();
763 nBlockStartZ
= aMarkRange
.aStart
.Tab();
764 nBlockEndX
= aMarkRange
.aEnd
.Col();
765 nBlockEndY
= aMarkRange
.aEnd
.Row();
766 nBlockEndZ
= aMarkRange
.aEnd
.Tab();
768 BOOL bDidReset
= FALSE
;
770 if ( nTab
>=nBlockStartZ
&& nTab
<=nBlockEndZ
)
774 // Invertieren beim Loeschen nur auf aktiver View
775 if ( aViewData
.IsActive() )
780 #ifdef OLD_SELECTION_PAINT
782 if (pGridWin
[i
] && pGridWin
[i
]->IsVisible())
783 pGridWin
[i
]->InvertSimple( nBlockStartX
, nBlockStartY
,
784 nBlockEndX
, nBlockEndY
,
788 UpdateSelectionOverlay();
793 #ifdef OLD_SELECTION_PAINT
794 // (mis)use InvertBlockMark to remove all of the selection
795 // -> set bBlockNeg (like when removing parts of a selection)
796 // and convert everything to Multi
799 BOOL bOld
= bBlockNeg
;
801 // #73130# (negative) MarkArea must be set in case of repaint
802 rMark
.SetMarkArea( ScRange( nBlockStartX
,nBlockStartY
, nTab
,
803 nBlockEndX
,nBlockEndY
, nTab
) );
805 InvertBlockMark( nBlockStartX
, nBlockStartY
, nBlockEndX
, nBlockEndY
);
810 UpdateSelectionOverlay();
814 // repaint if controls are touched (#69680# in both cases)
815 // #i74768# Forms are rendered by DrawingLayer's EndDrawLayers()
816 static bool bSuppressControlExtraStuff(true);
818 if(!bSuppressControlExtraStuff
)
820 Rectangle aMMRect
= pDoc
->GetMMRect(nBlockStartX
,nBlockStartY
,nBlockEndX
,nBlockEndY
, nTab
);
821 if (pDoc
->HasControl( nTab
, aMMRect
))
825 if (pGridWin
[i
] && pGridWin
[i
]->IsVisible())
827 // MapMode muss logischer (1/100mm) sein !!!
828 pDoc
->InvalidateControls( pGridWin
[i
], nTab
, aMMRect
);
829 pGridWin
[i
]->Update();
837 PaintMarks( nBlockStartX
, nBlockStartY
, nBlockEndX
, nBlockEndY
);
840 if ( bReset
&& !bDidReset
)
847 void ScTabView::SelectAll( BOOL bContinue
)
849 ScMarkData
& rMark
= aViewData
.GetMarkData();
850 SCTAB nTab
= aViewData
.GetTabNo();
852 if (rMark
.IsMarked())
855 rMark
.GetMarkArea( aMarkRange
);
856 if ( aMarkRange
== ScRange( 0,0,nTab
, MAXCOL
,MAXROW
,nTab
) )
860 DoneBlockMode( bContinue
);
861 InitBlockMode( 0,0,nTab
);
862 MarkCursor( MAXCOL
,MAXROW
,nTab
);
867 void ScTabView::SelectAllTables()
869 ScDocument
* pDoc
= aViewData
.GetDocument();
870 ScMarkData
& rMark
= aViewData
.GetMarkData();
871 // SCTAB nTab = aViewData.GetTabNo();
872 SCTAB nCount
= pDoc
->GetTableCount();
876 for (SCTAB i
=0; i
<nCount
; i
++)
877 rMark
.SelectTable( i
, TRUE
);
879 // Markierungen werden per Default nicht pro Tabelle gehalten
880 // pDoc->ExtendMarksFromTable( nTab );
882 aViewData
.GetDocShell()->PostPaintExtras();
883 SfxBindings
& rBind
= aViewData
.GetBindings();
884 rBind
.Invalidate( FID_FILL_TAB
);
885 rBind
.Invalidate( FID_TAB_DESELECTALL
);
889 void ScTabView::DeselectAllTables()
891 ScDocument
* pDoc
= aViewData
.GetDocument();
892 ScMarkData
& rMark
= aViewData
.GetMarkData();
893 SCTAB nTab
= aViewData
.GetTabNo();
894 SCTAB nCount
= pDoc
->GetTableCount();
896 for (SCTAB i
=0; i
<nCount
; i
++)
897 rMark
.SelectTable( i
, ( i
== nTab
) );
899 aViewData
.GetDocShell()->PostPaintExtras();
900 SfxBindings
& rBind
= aViewData
.GetBindings();
901 rBind
.Invalidate( FID_FILL_TAB
);
902 rBind
.Invalidate( FID_TAB_DESELECTALL
);
905 BOOL
lcl_FitsInWindow( double fScaleX
, double fScaleY
, USHORT nZoom
,
906 long nWindowX
, long nWindowY
, ScDocument
* pDoc
, SCTAB nTab
,
907 SCCOL nStartCol
, SCROW nStartRow
, SCCOL nEndCol
, SCROW nEndRow
,
908 SCCOL nFixPosX
, SCROW nFixPosY
)
910 double fZoomFactor
= (double)Fraction(nZoom
,100);
911 fScaleX
*= fZoomFactor
;
912 fScaleY
*= fZoomFactor
;
916 for (nCol
=0; nCol
<nFixPosX
; nCol
++)
918 // for frozen panes, add both parts
919 USHORT nColTwips
= pDoc
->GetColWidth( nCol
, nTab
);
922 nBlockX
+= (long)(nColTwips
* fScaleX
);
923 if (nBlockX
> nWindowX
)
927 for (nCol
=nStartCol
; nCol
<=nEndCol
; nCol
++)
929 USHORT nColTwips
= pDoc
->GetColWidth( nCol
, nTab
);
932 nBlockX
+= (long)(nColTwips
* fScaleX
);
933 if (nBlockX
> nWindowX
)
939 for (SCROW nRow
= 0; nRow
<= nFixPosY
-1; ++nRow
)
941 if (pDoc
->RowHidden(nRow
, nTab
))
944 // for frozen panes, add both parts
945 USHORT nRowTwips
= pDoc
->GetRowHeight(nRow
, nTab
);
948 nBlockY
+= (long)(nRowTwips
* fScaleY
);
949 if (nBlockY
> nWindowY
)
953 for (SCROW nRow
= nStartRow
; nRow
<= nEndRow
; ++nRow
)
955 USHORT nRowTwips
= pDoc
->GetRowHeight(nRow
, nTab
);
958 nBlockY
+= (long)(nRowTwips
* fScaleY
);
959 if (nBlockY
> nWindowY
)
967 USHORT
ScTabView::CalcZoom( SvxZoomType eType
, USHORT nOldZoom
)
969 USHORT nZoom
= 0; // Ergebnis
973 case SVX_ZOOM_PERCENT
: // rZoom ist kein besonderer prozentualer Wert
977 case SVX_ZOOM_OPTIMAL
: // nZoom entspricht der optimalen Gr"o\se
979 ScMarkData
& rMark
= aViewData
.GetMarkData();
980 ScDocument
* pDoc
= aViewData
.GetDocument();
982 if (!rMark
.IsMarked() && !rMark
.IsMultiMarked())
983 nZoom
= 100; // nothing selected
986 SCTAB nTab
= aViewData
.GetTabNo();
988 if ( aViewData
.GetSimpleArea( aMarkRange
) != SC_MARK_SIMPLE
)
989 rMark
.GetMultiMarkArea( aMarkRange
);
991 SCCOL nStartCol
= aMarkRange
.aStart
.Col();
992 SCROW nStartRow
= aMarkRange
.aStart
.Row();
993 SCTAB nStartTab
= aMarkRange
.aStart
.Tab();
994 SCCOL nEndCol
= aMarkRange
.aEnd
.Col();
995 SCROW nEndRow
= aMarkRange
.aEnd
.Row();
996 SCTAB nEndTab
= aMarkRange
.aEnd
.Tab();
998 if ( nTab
< nStartTab
&& nTab
> nEndTab
)
1001 ScSplitPos eUsedPart
= aViewData
.GetActivePart();
1005 if ( aViewData
.GetHSplitMode() == SC_SPLIT_FIX
)
1008 eUsedPart
= (WhichV(eUsedPart
)==SC_SPLIT_TOP
) ? SC_SPLIT_TOPRIGHT
: SC_SPLIT_BOTTOMRIGHT
;
1009 nFixPosX
= aViewData
.GetFixPosX();
1010 if ( nStartCol
< nFixPosX
)
1011 nStartCol
= nFixPosX
;
1013 if ( aViewData
.GetVSplitMode() == SC_SPLIT_FIX
)
1016 eUsedPart
= (WhichH(eUsedPart
)==SC_SPLIT_LEFT
) ? SC_SPLIT_BOTTOMLEFT
: SC_SPLIT_BOTTOMRIGHT
;
1017 nFixPosY
= aViewData
.GetFixPosY();
1018 if ( nStartRow
< nFixPosY
)
1019 nStartRow
= nFixPosY
;
1022 if (pGridWin
[eUsedPart
])
1024 // Because scale is rounded to pixels, the only reliable way to find
1025 // the right scale is to check if a zoom fits
1027 Size aWinSize
= pGridWin
[eUsedPart
]->GetOutputSizePixel();
1029 // for frozen panes, use sum of both parts for calculation
1031 if ( nFixPosX
!= 0 )
1032 aWinSize
.Width() += GetGridWidth( SC_SPLIT_LEFT
);
1033 if ( nFixPosY
!= 0 )
1034 aWinSize
.Height() += GetGridHeight( SC_SPLIT_TOP
);
1036 ScDocShell
* pDocSh
= aViewData
.GetDocShell();
1037 double nPPTX
= ScGlobal::nScreenPPTX
/ pDocSh
->GetOutputFactor();
1038 double nPPTY
= ScGlobal::nScreenPPTY
;
1040 USHORT nMin
= MINZOOM
;
1041 USHORT nMax
= MAXZOOM
;
1042 while ( nMax
> nMin
)
1044 USHORT nTest
= (nMin
+nMax
+1)/2;
1045 if ( lcl_FitsInWindow(
1046 nPPTX
, nPPTY
, nTest
, aWinSize
.Width(), aWinSize
.Height(),
1047 pDoc
, nTab
, nStartCol
, nStartRow
, nEndCol
, nEndRow
,
1048 nFixPosX
, nFixPosY
) )
1053 DBG_ASSERT( nMin
== nMax
, "Schachtelung ist falsch" );
1056 if ( nZoom
!= nOldZoom
)
1058 // scroll to block only in active split part
1059 // (the part for which the size was calculated)
1061 if ( nStartCol
<= nEndCol
)
1062 aViewData
.SetPosX( WhichH(eUsedPart
), nStartCol
);
1063 if ( nStartRow
<= nEndRow
)
1064 aViewData
.SetPosY( WhichV(eUsedPart
), nStartRow
);
1071 case SVX_ZOOM_WHOLEPAGE
: // nZoom entspricht der ganzen Seite oder
1072 case SVX_ZOOM_PAGEWIDTH
: // nZoom entspricht der Seitenbreite
1074 SCTAB nCurTab
= aViewData
.GetTabNo();
1075 ScDocument
* pDoc
= aViewData
.GetDocument();
1076 ScStyleSheetPool
* pStylePool
= pDoc
->GetStyleSheetPool();
1077 SfxStyleSheetBase
* pStyleSheet
=
1078 pStylePool
->Find( pDoc
->GetPageStyle( nCurTab
),
1079 SFX_STYLE_FAMILY_PAGE
);
1081 DBG_ASSERT( pStyleSheet
, "PageStyle not found :-/" );
1085 ScPrintFunc
aPrintFunc( aViewData
.GetDocShell(),
1086 aViewData
.GetViewShell()->GetPrinter(TRUE
),
1089 Size aPageSize
= aPrintFunc
.GetDataSize();
1091 // use the size of the largest GridWin for normal split,
1092 // or both combined for frozen panes, with the (document) size
1093 // of the frozen part added to the page size
1094 // (with frozen panes, the size of the individual parts
1095 // depends on the scale that is to be calculated)
1097 if ( !pGridWin
[SC_SPLIT_BOTTOMLEFT
] ) return 0;
1098 Size aWinSize
= pGridWin
[SC_SPLIT_BOTTOMLEFT
]->GetOutputSizePixel();
1099 ScSplitMode eHMode
= aViewData
.GetHSplitMode();
1100 if ( eHMode
!= SC_SPLIT_NONE
&& pGridWin
[SC_SPLIT_BOTTOMRIGHT
] )
1102 long nOtherWidth
= pGridWin
[SC_SPLIT_BOTTOMRIGHT
]->
1103 GetOutputSizePixel().Width();
1104 if ( eHMode
== SC_SPLIT_FIX
)
1106 aWinSize
.Width() += nOtherWidth
;
1107 for ( SCCOL nCol
= aViewData
.GetPosX(SC_SPLIT_LEFT
);
1108 nCol
< aViewData
.GetFixPosX(); nCol
++ )
1109 aPageSize
.Width() += pDoc
->GetColWidth( nCol
, nCurTab
);
1111 else if ( nOtherWidth
> aWinSize
.Width() )
1112 aWinSize
.Width() = nOtherWidth
;
1114 ScSplitMode eVMode
= aViewData
.GetVSplitMode();
1115 if ( eVMode
!= SC_SPLIT_NONE
&& pGridWin
[SC_SPLIT_TOPLEFT
] )
1117 long nOtherHeight
= pGridWin
[SC_SPLIT_TOPLEFT
]->
1118 GetOutputSizePixel().Height();
1119 if ( eVMode
== SC_SPLIT_FIX
)
1121 aWinSize
.Height() += nOtherHeight
;
1122 aPageSize
.Height() += pDoc
->GetRowHeight(
1123 aViewData
.GetPosY(SC_SPLIT_TOP
),
1124 aViewData
.GetFixPosY()-1, nCurTab
);
1126 else if ( nOtherHeight
> aWinSize
.Height() )
1127 aWinSize
.Height() = nOtherHeight
;
1130 double nPPTX
= ScGlobal::nScreenPPTX
/ aViewData
.GetDocShell()->GetOutputFactor();
1131 double nPPTY
= ScGlobal::nScreenPPTY
;
1133 long nZoomX
= (long) ( aWinSize
.Width() * 100 /
1134 ( aPageSize
.Width() * nPPTX
) );
1135 long nZoomY
= (long) ( aWinSize
.Height() * 100 /
1136 ( aPageSize
.Height() * nPPTY
) );
1139 if (eType
== SVX_ZOOM_WHOLEPAGE
&& nZoomY
< nNew
)
1142 nZoom
= (USHORT
) nNew
;
1148 DBG_ERROR("Unknown Zoom-Revision");
1155 // wird z.B. gerufen, wenn sich das View-Fenster verschiebt:
1157 void ScTabView::StopMarking()
1159 ScSplitPos eActive
= aViewData
.GetActivePart();
1160 if (pGridWin
[eActive
])
1161 pGridWin
[eActive
]->StopMarking();
1163 ScHSplitPos eH
= WhichH(eActive
);
1165 pColBar
[eH
]->StopMarking();
1167 ScVSplitPos eV
= WhichV(eActive
);
1169 pRowBar
[eV
]->StopMarking();
1172 void ScTabView::HideNoteMarker()
1174 for (USHORT i
=0; i
<4; i
++)
1175 if (pGridWin
[i
] && pGridWin
[i
]->IsVisible())
1176 pGridWin
[i
]->HideNoteMarker();
1179 void ScTabView::MakeDrawLayer()
1183 aViewData
.GetDocShell()->MakeDrawLayer();
1185 // pDrawView wird per Notify gesetzt
1186 DBG_ASSERT(pDrawView
,"ScTabView::MakeDrawLayer funktioniert nicht");
1189 for(sal_uInt16
a(0); a
< 4; a
++)
1193 pGridWin
[a
]->DrawLayerCreated();
1199 void ScTabView::ErrorMessage( USHORT nGlobStrId
)
1201 if ( SC_MOD()->IsInExecuteDrop() )
1203 // #i28468# don't show error message when called from Drag&Drop, silently abort instead
1207 StopMarking(); // falls per Focus aus MouseButtonDown aufgerufen
1209 Window
* pParent
= aViewData
.GetDialogParent();
1210 ScWaitCursorOff
aWaitOff( pParent
);
1211 BOOL bFocus
= pParent
&& pParent
->HasFocus();
1213 if(nGlobStrId
==STR_PROTECTIONERR
)
1215 if(aViewData
.GetDocShell()->IsReadOnly())
1217 nGlobStrId
=STR_READONLYERR
;
1221 InfoBox
aBox( pParent
, ScGlobal::GetRscString( nGlobStrId
) );
1224 pParent
->GrabFocus();
1227 Window
* ScTabView::GetParentOrChild( USHORT nChildId
)
1229 SfxViewFrame
* pViewFrm
= aViewData
.GetViewShell()->GetViewFrame();
1231 if ( pViewFrm
->HasChildWindow(nChildId
) )
1233 SfxChildWindow
* pChild
= pViewFrm
->GetChildWindow(nChildId
);
1236 Window
* pWin
= pChild
->GetWindow();
1237 if (pWin
&& pWin
->IsVisible())
1242 return aViewData
.GetDialogParent();
1245 void ScTabView::UpdatePageBreakData( BOOL bForcePaint
)
1247 ScPageBreakData
* pNewData
= NULL
;
1249 if (aViewData
.IsPagebreakMode())
1251 ScDocShell
* pDocSh
= aViewData
.GetDocShell();
1252 ScDocument
* pDoc
= pDocSh
->GetDocument();
1253 SCTAB nTab
= aViewData
.GetTabNo();
1255 USHORT nCount
= pDoc
->GetPrintRangeCount(nTab
);
1258 pNewData
= new ScPageBreakData(nCount
);
1260 ScPrintFunc
aPrintFunc( pDocSh
, pDocSh
->GetPrinter(), nTab
, 0,0,NULL
, NULL
, pNewData
);
1261 // ScPrintFunc fuellt im ctor die PageBreakData
1264 aPrintFunc
.ResetBreaks(nTab
);
1265 pNewData
->AddPages();
1268 // Druckbereiche veraendert?
1269 if ( bForcePaint
|| ( pPageBreakData
&& !pPageBreakData
->IsEqual( *pNewData
) ) )
1273 delete pPageBreakData
;
1274 pPageBreakData
= pNewData
;