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::UpdateCopySourceOverlay()
413 for (sal_uInt8 i
= 0; i
< 4; ++i
)
414 if (pGridWin
[i
] && pGridWin
[i
]->IsVisible())
415 pGridWin
[i
]->UpdateCopySourceOverlay();
418 void ScTabView::GetPageMoveEndPosition(SCsCOL nMovX
, SCsROW nMovY
, SCsCOL
& rPageX
, SCsROW
& rPageY
)
422 aViewData
.GetMoveCursor( nCurX
,nCurY
);
424 ScSplitPos eWhich
= aViewData
.GetActivePart();
425 ScHSplitPos eWhichX
= WhichH( eWhich
);
426 ScVSplitPos eWhichY
= WhichV( eWhich
);
431 nPageX
= ((SCsCOL
) aViewData
.CellsAtX( nCurX
, 1, eWhichX
)) * nMovX
;
433 nPageX
= ((SCsCOL
) aViewData
.CellsAtX( nCurX
, -1, eWhichX
)) * nMovX
;
436 nPageY
= ((SCsROW
) aViewData
.CellsAtY( nCurY
, 1, eWhichY
)) * nMovY
;
438 nPageY
= ((SCsROW
) aViewData
.CellsAtY( nCurY
, -1, eWhichY
)) * nMovY
;
440 if (nMovX
!= 0 && nPageX
== 0) nPageX
= (nMovX
>0) ? 1 : -1;
441 if (nMovY
!= 0 && nPageY
== 0) nPageY
= (nMovY
>0) ? 1 : -1;
447 void ScTabView::GetAreaMoveEndPosition(SCsCOL nMovX
, SCsROW nMovY
, ScFollowMode eMode
,
448 SCsCOL
& rAreaX
, SCsROW
& rAreaY
, ScFollowMode
& rMode
)
455 if (aViewData
.IsRefMode())
457 nNewX
= aViewData
.GetRefEndX();
458 nNewY
= aViewData
.GetRefEndY();
460 else if (IsBlockMode())
467 nNewX
= nCurX
= aViewData
.GetCurX();
468 nNewY
= nCurY
= aViewData
.GetCurY();
471 ScDocument
* pDoc
= aViewData
.GetDocument();
472 SCTAB nTab
= aViewData
.GetTabNo();
474 // FindAreaPos kennt nur -1 oder 1 als Richtung
478 for ( i
=0; i
<nMovX
; i
++ )
479 pDoc
->FindAreaPos( nNewX
, nNewY
, nTab
, 1, 0 );
481 for ( i
=0; i
<-nMovX
; i
++ )
482 pDoc
->FindAreaPos( nNewX
, nNewY
, nTab
, -1, 0 );
484 for ( i
=0; i
<nMovY
; i
++ )
485 pDoc
->FindAreaPos( nNewX
, nNewY
, nTab
, 0, 1 );
487 for ( i
=0; i
<-nMovY
; i
++ )
488 pDoc
->FindAreaPos( nNewX
, nNewY
, nTab
, 0, -1 );
490 if (eMode
==SC_FOLLOW_JUMP
) // unten/rechts nicht zuviel grau anzeigen
492 if (nMovX
!= 0 && nNewX
== MAXCOL
)
493 eMode
= SC_FOLLOW_LINE
;
494 if (nMovY
!= 0 && nNewY
== MAXROW
)
495 eMode
= SC_FOLLOW_LINE
;
498 if (aViewData
.IsRefMode())
500 rAreaX
= nNewX
- aViewData
.GetRefEndX();
501 rAreaY
= nNewY
- aViewData
.GetRefEndY();
503 else if (IsBlockMode())
505 rAreaX
= nNewX
- nBlockEndX
;
506 rAreaY
= nNewY
- nBlockEndY
;
510 rAreaX
= nNewX
- nCurX
;
511 rAreaY
= nNewY
- nCurY
;
518 bool lcl_isCellQualified(ScDocument
* pDoc
, SCCOL nCol
, SCROW nRow
, SCTAB nTab
, bool bSelectLocked
, bool bSelectUnlocked
)
520 bool bCellProtected
= pDoc
->HasAttrib(
521 nCol
, nRow
, nTab
, nCol
, nRow
, nTab
, HASATTR_PROTECTED
);
523 if (bCellProtected
&& !bSelectLocked
)
526 if (!bCellProtected
&& !bSelectUnlocked
)
532 void lcl_moveCursorByProtRule(
533 SCCOL
& rCol
, SCROW
& rRow
, SCsCOL nMovX
, SCsROW nMovY
, SCTAB nTab
, ScDocument
* pDoc
)
535 bool bSelectLocked
= true;
536 bool bSelectUnlocked
= true;
537 ScTableProtection
* pTabProtection
= pDoc
->GetTabProtection(nTab
);
538 if (pTabProtection
&& pTabProtection
->isProtected())
540 bSelectLocked
= pTabProtection
->isOptionEnabled(ScTableProtection::SELECT_LOCKED_CELLS
);
541 bSelectUnlocked
= pTabProtection
->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS
);
548 for (SCCOL i
= 0; i
< nMovX
; ++i
)
550 if (!lcl_isCellQualified(pDoc
, rCol
+1, rRow
, nTab
, bSelectLocked
, bSelectUnlocked
))
561 for (SCCOL i
= 0; i
< nMovX
; ++i
)
563 if (!lcl_isCellQualified(pDoc
, rCol
-1, rRow
, nTab
, bSelectLocked
, bSelectUnlocked
))
574 for (SCROW i
= 0; i
< nMovY
; ++i
)
576 if (!lcl_isCellQualified(pDoc
, rCol
, rRow
+1, nTab
, bSelectLocked
, bSelectUnlocked
))
587 for (SCROW i
= 0; i
< nMovY
; ++i
)
589 if (!lcl_isCellQualified(pDoc
, rCol
, rRow
-1, nTab
, bSelectLocked
, bSelectUnlocked
))
599 void ScTabView::ExpandBlock(SCsCOL nMovX
, SCsROW nMovY
, ScFollowMode eMode
)
601 if (!nMovX
&& !nMovY
)
602 // Nothing to do. Bail out.
605 ScTabViewShell
* pViewShell
= aViewData
.GetViewShell();
606 bool bRefInputMode
= pViewShell
&& pViewShell
->IsRefInputMode();
607 if (bRefInputMode
&& !aViewData
.IsRefMode())
608 // initialize formula reference mode if it hasn't already.
609 InitRefMode(aViewData
.GetCurX(), aViewData
.GetCurY(), aViewData
.GetTabNo(), SC_REFTYPE_REF
);
611 ScDocument
* pDoc
= aViewData
.GetDocument();
613 if (aViewData
.IsRefMode())
615 // formula reference mode
617 SCCOL nNewX
= aViewData
.GetRefEndX();
618 SCROW nNewY
= aViewData
.GetRefEndY();
619 SCTAB nRefTab
= aViewData
.GetRefEndZ();
621 bool bSelectLocked
= true;
622 bool bSelectUnlocked
= true;
623 ScTableProtection
* pTabProtection
= pDoc
->GetTabProtection(nRefTab
);
624 if (pTabProtection
&& pTabProtection
->isProtected())
626 bSelectLocked
= pTabProtection
->isOptionEnabled(ScTableProtection::SELECT_LOCKED_CELLS
);
627 bSelectUnlocked
= pTabProtection
->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS
);
630 lcl_moveCursorByProtRule(nNewX
, nNewY
, nMovX
, nMovY
, nRefTab
, pDoc
);
634 SCCOL nTempX
= nNewX
;
635 while (pDoc
->IsHorOverlapped(nTempX
, nNewY
, nRefTab
))
642 if (lcl_isCellQualified(pDoc
, nTempX
, nNewY
, nRefTab
, bSelectLocked
, bSelectUnlocked
))
648 SCROW nTempY
= nNewY
;
649 while (pDoc
->IsVerOverlapped(nNewX
, nTempY
, nRefTab
))
656 if (lcl_isCellQualified(pDoc
, nNewX
, nTempY
, nRefTab
, bSelectLocked
, bSelectUnlocked
))
660 pDoc
->SkipOverlapped(nNewX
, nNewY
, nRefTab
);
661 UpdateRef(nNewX
, nNewY
, nRefTab
);
662 AlignToCursor(nNewX
, nNewY
, eMode
);
666 // normal selection mode
668 SCTAB nTab
= aViewData
.GetTabNo();
671 InitBlockMode(aViewData
.GetCurX(), aViewData
.GetCurY(), nTab
, true);
673 lcl_moveCursorByProtRule(nBlockEndX
, nBlockEndY
, nMovX
, nMovY
, nTab
, pDoc
);
677 else if (nBlockEndX
> MAXCOL
)
682 else if (nBlockEndY
> MAXROW
)
685 pDoc
->SkipOverlapped(nBlockEndX
, nBlockEndY
, nTab
);
686 MarkCursor(nBlockEndX
, nBlockEndY
, nTab
, false, false, true);
688 // Check if the entire row(s) or column(s) are selected.
689 ScSplitPos eActive
= aViewData
.GetActivePart();
690 bool bRowSelected
= (nBlockStartX
== 0 && nBlockEndX
== MAXCOL
);
691 bool bColSelected
= (nBlockStartY
== 0 && nBlockEndY
== MAXROW
);
692 SCsCOL nAlignX
= bRowSelected
? aViewData
.GetPosX(WhichH(eActive
)) : nBlockEndX
;
693 SCsROW nAlignY
= bColSelected
? aViewData
.GetPosY(WhichV(eActive
)) : nBlockEndY
;
694 AlignToCursor(nAlignX
, nAlignY
, eMode
);
696 UpdateAutoFillMark();
700 void ScTabView::ExpandBlockPage(SCsCOL nMovX
, SCsROW nMovY
)
704 GetPageMoveEndPosition(nMovX
, nMovY
, nPageX
, nPageY
);
705 ExpandBlock(nPageX
, nPageY
, SC_FOLLOW_FIX
);
708 void ScTabView::ExpandBlockArea(SCsCOL nMovX
, SCsROW nMovY
)
713 GetAreaMoveEndPosition(nMovX
, nMovY
, SC_FOLLOW_JUMP
, nAreaX
, nAreaY
, eMode
);
714 ExpandBlock(nAreaX
, nAreaY
, eMode
);
717 void ScTabView::UpdateSelectionOverlay()
719 for (USHORT i
=0; i
<4; i
++)
720 if ( pGridWin
[i
] && pGridWin
[i
]->IsVisible() )
721 pGridWin
[i
]->UpdateSelectionOverlay();
724 void ScTabView::UpdateShrinkOverlay()
726 for (USHORT i
=0; i
<4; i
++)
727 if ( pGridWin
[i
] && pGridWin
[i
]->IsVisible() )
728 pGridWin
[i
]->UpdateShrinkOverlay();
731 void ScTabView::UpdateAllOverlays()
733 for (USHORT i
=0; i
<4; i
++)
734 if ( pGridWin
[i
] && pGridWin
[i
]->IsVisible() )
735 pGridWin
[i
]->UpdateAllOverlays();
739 //! PaintBlock in zwei Methoden aufteilen: RepaintBlock und RemoveBlock o.ae.
742 void ScTabView::PaintBlock( BOOL bReset
)
744 ScDocument
* pDoc
= aViewData
.GetDocument();
745 ScMarkData
& rMark
= aViewData
.GetMarkData();
746 SCTAB nTab
= aViewData
.GetTabNo();
747 BOOL bMark
= rMark
.IsMarked();
748 BOOL bMulti
= rMark
.IsMultiMarked();
755 BOOL bFlag
= rMark
.GetMarkingFlag();
756 rMark
.SetMarking(FALSE
);
758 rMark
.GetMultiMarkArea(aMarkRange
);
759 rMark
.MarkToSimple();
760 rMark
.SetMarking(bFlag
);
762 bMark
= rMark
.IsMarked();
763 bMulti
= rMark
.IsMultiMarked();
766 rMark
.GetMarkArea(aMarkRange
);
768 nBlockStartX
= aMarkRange
.aStart
.Col();
769 nBlockStartY
= aMarkRange
.aStart
.Row();
770 nBlockStartZ
= aMarkRange
.aStart
.Tab();
771 nBlockEndX
= aMarkRange
.aEnd
.Col();
772 nBlockEndY
= aMarkRange
.aEnd
.Row();
773 nBlockEndZ
= aMarkRange
.aEnd
.Tab();
775 BOOL bDidReset
= FALSE
;
777 if ( nTab
>=nBlockStartZ
&& nTab
<=nBlockEndZ
)
781 // Invertieren beim Loeschen nur auf aktiver View
782 if ( aViewData
.IsActive() )
787 #ifdef OLD_SELECTION_PAINT
789 if (pGridWin
[i
] && pGridWin
[i
]->IsVisible())
790 pGridWin
[i
]->InvertSimple( nBlockStartX
, nBlockStartY
,
791 nBlockEndX
, nBlockEndY
,
795 UpdateSelectionOverlay();
800 #ifdef OLD_SELECTION_PAINT
801 // (mis)use InvertBlockMark to remove all of the selection
802 // -> set bBlockNeg (like when removing parts of a selection)
803 // and convert everything to Multi
806 BOOL bOld
= bBlockNeg
;
808 // #73130# (negative) MarkArea must be set in case of repaint
809 rMark
.SetMarkArea( ScRange( nBlockStartX
,nBlockStartY
, nTab
,
810 nBlockEndX
,nBlockEndY
, nTab
) );
812 InvertBlockMark( nBlockStartX
, nBlockStartY
, nBlockEndX
, nBlockEndY
);
817 UpdateSelectionOverlay();
821 // repaint if controls are touched (#69680# in both cases)
822 // #i74768# Forms are rendered by DrawingLayer's EndDrawLayers()
823 static bool bSuppressControlExtraStuff(true);
825 if(!bSuppressControlExtraStuff
)
827 Rectangle aMMRect
= pDoc
->GetMMRect(nBlockStartX
,nBlockStartY
,nBlockEndX
,nBlockEndY
, nTab
);
828 if (pDoc
->HasControl( nTab
, aMMRect
))
832 if (pGridWin
[i
] && pGridWin
[i
]->IsVisible())
834 // MapMode muss logischer (1/100mm) sein !!!
835 pDoc
->InvalidateControls( pGridWin
[i
], nTab
, aMMRect
);
836 pGridWin
[i
]->Update();
844 PaintMarks( nBlockStartX
, nBlockStartY
, nBlockEndX
, nBlockEndY
);
847 if ( bReset
&& !bDidReset
)
854 void ScTabView::SelectAll( BOOL bContinue
)
856 ScMarkData
& rMark
= aViewData
.GetMarkData();
857 SCTAB nTab
= aViewData
.GetTabNo();
859 if (rMark
.IsMarked())
862 rMark
.GetMarkArea( aMarkRange
);
863 if ( aMarkRange
== ScRange( 0,0,nTab
, MAXCOL
,MAXROW
,nTab
) )
867 DoneBlockMode( bContinue
);
868 InitBlockMode( 0,0,nTab
);
869 MarkCursor( MAXCOL
,MAXROW
,nTab
);
874 void ScTabView::SelectAllTables()
876 ScDocument
* pDoc
= aViewData
.GetDocument();
877 ScMarkData
& rMark
= aViewData
.GetMarkData();
878 // SCTAB nTab = aViewData.GetTabNo();
879 SCTAB nCount
= pDoc
->GetTableCount();
883 for (SCTAB i
=0; i
<nCount
; i
++)
884 rMark
.SelectTable( i
, TRUE
);
886 // Markierungen werden per Default nicht pro Tabelle gehalten
887 // pDoc->ExtendMarksFromTable( nTab );
889 aViewData
.GetDocShell()->PostPaintExtras();
890 SfxBindings
& rBind
= aViewData
.GetBindings();
891 rBind
.Invalidate( FID_FILL_TAB
);
892 rBind
.Invalidate( FID_TAB_DESELECTALL
);
896 void ScTabView::DeselectAllTables()
898 ScDocument
* pDoc
= aViewData
.GetDocument();
899 ScMarkData
& rMark
= aViewData
.GetMarkData();
900 SCTAB nTab
= aViewData
.GetTabNo();
901 SCTAB nCount
= pDoc
->GetTableCount();
903 for (SCTAB i
=0; i
<nCount
; i
++)
904 rMark
.SelectTable( i
, ( i
== nTab
) );
906 aViewData
.GetDocShell()->PostPaintExtras();
907 SfxBindings
& rBind
= aViewData
.GetBindings();
908 rBind
.Invalidate( FID_FILL_TAB
);
909 rBind
.Invalidate( FID_TAB_DESELECTALL
);
912 BOOL
lcl_FitsInWindow( double fScaleX
, double fScaleY
, USHORT nZoom
,
913 long nWindowX
, long nWindowY
, ScDocument
* pDoc
, SCTAB nTab
,
914 SCCOL nStartCol
, SCROW nStartRow
, SCCOL nEndCol
, SCROW nEndRow
,
915 SCCOL nFixPosX
, SCROW nFixPosY
)
917 double fZoomFactor
= (double)Fraction(nZoom
,100);
918 fScaleX
*= fZoomFactor
;
919 fScaleY
*= fZoomFactor
;
923 for (nCol
=0; nCol
<nFixPosX
; nCol
++)
925 // for frozen panes, add both parts
926 USHORT nColTwips
= pDoc
->GetColWidth( nCol
, nTab
);
929 nBlockX
+= (long)(nColTwips
* fScaleX
);
930 if (nBlockX
> nWindowX
)
934 for (nCol
=nStartCol
; nCol
<=nEndCol
; nCol
++)
936 USHORT nColTwips
= pDoc
->GetColWidth( nCol
, nTab
);
939 nBlockX
+= (long)(nColTwips
* fScaleX
);
940 if (nBlockX
> nWindowX
)
946 for (SCROW nRow
= 0; nRow
<= nFixPosY
-1; ++nRow
)
948 if (pDoc
->RowHidden(nRow
, nTab
))
951 // for frozen panes, add both parts
952 USHORT nRowTwips
= pDoc
->GetRowHeight(nRow
, nTab
);
955 nBlockY
+= (long)(nRowTwips
* fScaleY
);
956 if (nBlockY
> nWindowY
)
960 for (SCROW nRow
= nStartRow
; nRow
<= nEndRow
; ++nRow
)
962 USHORT nRowTwips
= pDoc
->GetRowHeight(nRow
, nTab
);
965 nBlockY
+= (long)(nRowTwips
* fScaleY
);
966 if (nBlockY
> nWindowY
)
974 USHORT
ScTabView::CalcZoom( SvxZoomType eType
, USHORT nOldZoom
)
976 USHORT nZoom
= 0; // Ergebnis
980 case SVX_ZOOM_PERCENT
: // rZoom ist kein besonderer prozentualer Wert
984 case SVX_ZOOM_OPTIMAL
: // nZoom entspricht der optimalen Gr"o\se
986 ScMarkData
& rMark
= aViewData
.GetMarkData();
987 ScDocument
* pDoc
= aViewData
.GetDocument();
989 if (!rMark
.IsMarked() && !rMark
.IsMultiMarked())
990 nZoom
= 100; // nothing selected
993 SCTAB nTab
= aViewData
.GetTabNo();
995 if ( aViewData
.GetSimpleArea( aMarkRange
) != SC_MARK_SIMPLE
)
996 rMark
.GetMultiMarkArea( aMarkRange
);
998 SCCOL nStartCol
= aMarkRange
.aStart
.Col();
999 SCROW nStartRow
= aMarkRange
.aStart
.Row();
1000 SCTAB nStartTab
= aMarkRange
.aStart
.Tab();
1001 SCCOL nEndCol
= aMarkRange
.aEnd
.Col();
1002 SCROW nEndRow
= aMarkRange
.aEnd
.Row();
1003 SCTAB nEndTab
= aMarkRange
.aEnd
.Tab();
1005 if ( nTab
< nStartTab
&& nTab
> nEndTab
)
1008 ScSplitPos eUsedPart
= aViewData
.GetActivePart();
1012 if ( aViewData
.GetHSplitMode() == SC_SPLIT_FIX
)
1015 eUsedPart
= (WhichV(eUsedPart
)==SC_SPLIT_TOP
) ? SC_SPLIT_TOPRIGHT
: SC_SPLIT_BOTTOMRIGHT
;
1016 nFixPosX
= aViewData
.GetFixPosX();
1017 if ( nStartCol
< nFixPosX
)
1018 nStartCol
= nFixPosX
;
1020 if ( aViewData
.GetVSplitMode() == SC_SPLIT_FIX
)
1023 eUsedPart
= (WhichH(eUsedPart
)==SC_SPLIT_LEFT
) ? SC_SPLIT_BOTTOMLEFT
: SC_SPLIT_BOTTOMRIGHT
;
1024 nFixPosY
= aViewData
.GetFixPosY();
1025 if ( nStartRow
< nFixPosY
)
1026 nStartRow
= nFixPosY
;
1029 if (pGridWin
[eUsedPart
])
1031 // Because scale is rounded to pixels, the only reliable way to find
1032 // the right scale is to check if a zoom fits
1034 Size aWinSize
= pGridWin
[eUsedPart
]->GetOutputSizePixel();
1036 // for frozen panes, use sum of both parts for calculation
1038 if ( nFixPosX
!= 0 )
1039 aWinSize
.Width() += GetGridWidth( SC_SPLIT_LEFT
);
1040 if ( nFixPosY
!= 0 )
1041 aWinSize
.Height() += GetGridHeight( SC_SPLIT_TOP
);
1043 ScDocShell
* pDocSh
= aViewData
.GetDocShell();
1044 double nPPTX
= ScGlobal::nScreenPPTX
/ pDocSh
->GetOutputFactor();
1045 double nPPTY
= ScGlobal::nScreenPPTY
;
1047 USHORT nMin
= MINZOOM
;
1048 USHORT nMax
= MAXZOOM
;
1049 while ( nMax
> nMin
)
1051 USHORT nTest
= (nMin
+nMax
+1)/2;
1052 if ( lcl_FitsInWindow(
1053 nPPTX
, nPPTY
, nTest
, aWinSize
.Width(), aWinSize
.Height(),
1054 pDoc
, nTab
, nStartCol
, nStartRow
, nEndCol
, nEndRow
,
1055 nFixPosX
, nFixPosY
) )
1060 DBG_ASSERT( nMin
== nMax
, "Schachtelung ist falsch" );
1063 if ( nZoom
!= nOldZoom
)
1065 // scroll to block only in active split part
1066 // (the part for which the size was calculated)
1068 if ( nStartCol
<= nEndCol
)
1069 aViewData
.SetPosX( WhichH(eUsedPart
), nStartCol
);
1070 if ( nStartRow
<= nEndRow
)
1071 aViewData
.SetPosY( WhichV(eUsedPart
), nStartRow
);
1078 case SVX_ZOOM_WHOLEPAGE
: // nZoom entspricht der ganzen Seite oder
1079 case SVX_ZOOM_PAGEWIDTH
: // nZoom entspricht der Seitenbreite
1081 SCTAB nCurTab
= aViewData
.GetTabNo();
1082 ScDocument
* pDoc
= aViewData
.GetDocument();
1083 ScStyleSheetPool
* pStylePool
= pDoc
->GetStyleSheetPool();
1084 SfxStyleSheetBase
* pStyleSheet
=
1085 pStylePool
->Find( pDoc
->GetPageStyle( nCurTab
),
1086 SFX_STYLE_FAMILY_PAGE
);
1088 DBG_ASSERT( pStyleSheet
, "PageStyle not found :-/" );
1092 ScPrintFunc
aPrintFunc( aViewData
.GetDocShell(),
1093 aViewData
.GetViewShell()->GetPrinter(TRUE
),
1096 Size aPageSize
= aPrintFunc
.GetDataSize();
1098 // use the size of the largest GridWin for normal split,
1099 // or both combined for frozen panes, with the (document) size
1100 // of the frozen part added to the page size
1101 // (with frozen panes, the size of the individual parts
1102 // depends on the scale that is to be calculated)
1104 if ( !pGridWin
[SC_SPLIT_BOTTOMLEFT
] ) return 0;
1105 Size aWinSize
= pGridWin
[SC_SPLIT_BOTTOMLEFT
]->GetOutputSizePixel();
1106 ScSplitMode eHMode
= aViewData
.GetHSplitMode();
1107 if ( eHMode
!= SC_SPLIT_NONE
&& pGridWin
[SC_SPLIT_BOTTOMRIGHT
] )
1109 long nOtherWidth
= pGridWin
[SC_SPLIT_BOTTOMRIGHT
]->
1110 GetOutputSizePixel().Width();
1111 if ( eHMode
== SC_SPLIT_FIX
)
1113 aWinSize
.Width() += nOtherWidth
;
1114 for ( SCCOL nCol
= aViewData
.GetPosX(SC_SPLIT_LEFT
);
1115 nCol
< aViewData
.GetFixPosX(); nCol
++ )
1116 aPageSize
.Width() += pDoc
->GetColWidth( nCol
, nCurTab
);
1118 else if ( nOtherWidth
> aWinSize
.Width() )
1119 aWinSize
.Width() = nOtherWidth
;
1121 ScSplitMode eVMode
= aViewData
.GetVSplitMode();
1122 if ( eVMode
!= SC_SPLIT_NONE
&& pGridWin
[SC_SPLIT_TOPLEFT
] )
1124 long nOtherHeight
= pGridWin
[SC_SPLIT_TOPLEFT
]->
1125 GetOutputSizePixel().Height();
1126 if ( eVMode
== SC_SPLIT_FIX
)
1128 aWinSize
.Height() += nOtherHeight
;
1129 aPageSize
.Height() += pDoc
->GetRowHeight(
1130 aViewData
.GetPosY(SC_SPLIT_TOP
),
1131 aViewData
.GetFixPosY()-1, nCurTab
);
1133 else if ( nOtherHeight
> aWinSize
.Height() )
1134 aWinSize
.Height() = nOtherHeight
;
1137 double nPPTX
= ScGlobal::nScreenPPTX
/ aViewData
.GetDocShell()->GetOutputFactor();
1138 double nPPTY
= ScGlobal::nScreenPPTY
;
1140 long nZoomX
= (long) ( aWinSize
.Width() * 100 /
1141 ( aPageSize
.Width() * nPPTX
) );
1142 long nZoomY
= (long) ( aWinSize
.Height() * 100 /
1143 ( aPageSize
.Height() * nPPTY
) );
1146 if (eType
== SVX_ZOOM_WHOLEPAGE
&& nZoomY
< nNew
)
1149 nZoom
= (USHORT
) nNew
;
1155 DBG_ERROR("Unknown Zoom-Revision");
1162 // wird z.B. gerufen, wenn sich das View-Fenster verschiebt:
1164 void ScTabView::StopMarking()
1166 ScSplitPos eActive
= aViewData
.GetActivePart();
1167 if (pGridWin
[eActive
])
1168 pGridWin
[eActive
]->StopMarking();
1170 ScHSplitPos eH
= WhichH(eActive
);
1172 pColBar
[eH
]->StopMarking();
1174 ScVSplitPos eV
= WhichV(eActive
);
1176 pRowBar
[eV
]->StopMarking();
1179 void ScTabView::HideNoteMarker()
1181 for (USHORT i
=0; i
<4; i
++)
1182 if (pGridWin
[i
] && pGridWin
[i
]->IsVisible())
1183 pGridWin
[i
]->HideNoteMarker();
1186 void ScTabView::MakeDrawLayer()
1190 aViewData
.GetDocShell()->MakeDrawLayer();
1192 // pDrawView wird per Notify gesetzt
1193 DBG_ASSERT(pDrawView
,"ScTabView::MakeDrawLayer funktioniert nicht");
1196 for(sal_uInt16
a(0); a
< 4; a
++)
1200 pGridWin
[a
]->DrawLayerCreated();
1206 void ScTabView::ErrorMessage( USHORT nGlobStrId
)
1208 if ( SC_MOD()->IsInExecuteDrop() )
1210 // #i28468# don't show error message when called from Drag&Drop, silently abort instead
1214 StopMarking(); // falls per Focus aus MouseButtonDown aufgerufen
1216 Window
* pParent
= aViewData
.GetDialogParent();
1217 ScWaitCursorOff
aWaitOff( pParent
);
1218 BOOL bFocus
= pParent
&& pParent
->HasFocus();
1220 if(nGlobStrId
==STR_PROTECTIONERR
)
1222 if(aViewData
.GetDocShell()->IsReadOnly())
1224 nGlobStrId
=STR_READONLYERR
;
1228 InfoBox
aBox( pParent
, ScGlobal::GetRscString( nGlobStrId
) );
1231 pParent
->GrabFocus();
1234 Window
* ScTabView::GetParentOrChild( USHORT nChildId
)
1236 SfxViewFrame
* pViewFrm
= aViewData
.GetViewShell()->GetViewFrame();
1238 if ( pViewFrm
->HasChildWindow(nChildId
) )
1240 SfxChildWindow
* pChild
= pViewFrm
->GetChildWindow(nChildId
);
1243 Window
* pWin
= pChild
->GetWindow();
1244 if (pWin
&& pWin
->IsVisible())
1249 return aViewData
.GetDialogParent();
1252 void ScTabView::UpdatePageBreakData( BOOL bForcePaint
)
1254 ScPageBreakData
* pNewData
= NULL
;
1256 if (aViewData
.IsPagebreakMode())
1258 ScDocShell
* pDocSh
= aViewData
.GetDocShell();
1259 ScDocument
* pDoc
= pDocSh
->GetDocument();
1260 SCTAB nTab
= aViewData
.GetTabNo();
1262 USHORT nCount
= pDoc
->GetPrintRangeCount(nTab
);
1265 pNewData
= new ScPageBreakData(nCount
);
1267 ScPrintFunc
aPrintFunc( pDocSh
, pDocSh
->GetPrinter(), nTab
, 0,0,NULL
, NULL
, pNewData
);
1268 // ScPrintFunc fuellt im ctor die PageBreakData
1271 aPrintFunc
.ResetBreaks(nTab
);
1272 pNewData
->AddPages();
1275 // Druckbereiche veraendert?
1276 if ( bForcePaint
|| ( pPageBreakData
&& !pPageBreakData
->IsEqual( *pNewData
) ) )
1280 delete pPageBreakData
;
1281 pPageBreakData
= pNewData
;