update dev300-m58
[ooovba.git] / sc / source / ui / view / tabview2.cxx
blob999c952abdb2b3eafeb0575a58e02aaf85eb1eaf
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: tabview2.cxx,v $
10 * $Revision: 1.21 $
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>
49 #include "attrib.hxx"
50 #include "pagedata.hxx"
51 #include "tabview.hxx"
52 #include "tabvwsh.hxx"
53 #include "printfun.hxx"
54 #include "stlpool.hxx"
55 #include "docsh.hxx"
56 #include "gridwin.hxx"
57 #include "olinewin.hxx"
58 #include "uiitems.hxx"
59 #include "sc.hrc"
60 #include "viewutil.hxx"
61 #include "colrowba.hxx"
62 #include "waitoff.hxx"
63 #include "globstr.hrc"
64 #include "scmod.hxx"
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);
87 if (bLeft)
88 PaintLeftArea( nStartRow, nEndRow );
89 if (bTop)
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
99 return bIsBlockMode
100 && nBlockStartX == nCol
101 && nBlockStartY == nRow
102 && nBlockStartZ == nTab;
105 void ScTabView::InitOwnBlockMode()
107 if (!bIsBlockMode)
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!
117 nBlockStartX = 0;
118 nBlockStartY = 0;
119 nBlockStartZ = 0;
120 nBlockEndX = 0;
121 nBlockEndY = 0;
122 nBlockEndZ = 0;
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 )
131 if (!bIsBlockMode)
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?
140 if (bTestNeg)
142 if ( bCols )
143 bBlockNeg = rMark.IsColumnMarked( nCurX );
144 else if ( bRows )
145 bBlockNeg = rMark.IsRowMarked( nCurY );
146 else
147 bBlockNeg = rMark.IsCellMarked( nCurX, nCurY );
149 else
150 bBlockNeg = FALSE;
151 rMark.SetMarkNegative(bBlockNeg);
153 // bIsBlockMode = TRUE;
154 bIsBlockMode = SC_BLOCKMODE_NORMAL; //! Variable umbenennen!
155 bBlockCols = bCols;
156 bBlockRows = bRows;
157 nBlockStartX = nBlockStartXOrig = nCurX;
158 nBlockStartY = nBlockStartYOrig = nCurY;
159 nBlockStartZ = nCurZ;
160 nBlockEndX = nOldCurX = nBlockStartX;
161 nBlockEndY = nOldCurY = nBlockStartY;
162 nBlockEndZ = nBlockStartZ;
164 if (bBlockCols)
166 nBlockStartY = nBlockStartYOrig = 0;
167 nBlockEndY = MAXROW;
170 if (bBlockRows)
172 nBlockStartX = nBlockStartXOrig = 0;
173 nBlockEndX = MAXCOL;
176 rMark.SetMarkArea( ScRange( nBlockStartX,nBlockStartY, nTab, nBlockEndX,nBlockEndY, nTab ) );
178 #ifdef OLD_SELECTION_PAINT
179 InvertBlockMark( nBlockStartX,nBlockStartY,nBlockEndX,nBlockEndY );
180 #endif
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)
198 rMark.MarkToMulti();
200 if (bContinue)
201 rMark.MarkToMulti();
202 else
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
212 else
213 rMark.ResetMark();
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;
229 if (!bIsBlockMode)
231 DBG_ERROR( "MarkCursor nicht im BlockMode" );
232 InitBlockMode( nCurX, nCurY, nCurZ, FALSE, bCols, bRows );
235 if (bCols)
236 nCurY = MAXROW;
237 if (bRows)
238 nCurX = MAXCOL;
240 ScMarkData& rMark = aViewData.GetMarkData();
241 DBG_ASSERT(rMark.IsMarked() || rMark.IsMultiMarked(), "MarkCursor, !IsMarked()");
242 ScRange aMarkRange;
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
268 SCTAB nTab = nCurZ;
270 #ifdef OLD_SELECTION_PAINT
271 SCCOL nDrawStartCol;
272 SCROW nDrawStartRow;
273 SCCOL nDrawEndCol;
274 SCROW nDrawEndRow;
275 #endif
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;
352 else
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;
368 else
370 nBlockEndX = nCurX;
371 nBlockEndY = nCurY;
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
380 BOOL bCont;
381 BOOL bDraw = aRect.GetXorDiff( nDrawStartCol, nDrawStartRow,
382 nDrawEndCol, nDrawEndRow, bCont );
383 if ( bDraw )
385 //? PutInOrder( nDrawStartCol, nDrawEndCol );
386 //? PutInOrder( nDrawStartRow, nDrawEndRow );
388 HideAllCursors();
389 InvertBlockMark( nDrawStartCol, nDrawStartRow, nDrawEndCol, nDrawEndRow );
390 if (bCont)
392 aRect.GetContDiff( nDrawStartCol, nDrawStartRow, nDrawEndCol, nDrawEndRow );
393 InvertBlockMark( nDrawStartCol, nDrawStartRow, nDrawEndCol, nDrawEndRow );
395 ShowAllCursors();
397 #endif
398 UpdateSelectionOverlay();
400 nOldCurX = nCurX;
401 nOldCurY = nCurY;
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)
413 SCCOL nCurX;
414 SCROW nCurY;
415 aViewData.GetMoveCursor( nCurX,nCurY );
417 ScSplitPos eWhich = aViewData.GetActivePart();
418 ScHSplitPos eWhichX = WhichH( eWhich );
419 ScVSplitPos eWhichY = WhichV( eWhich );
421 SCsCOL nPageX;
422 SCsROW nPageY;
423 if (nMovX >= 0)
424 nPageX = ((SCsCOL) aViewData.CellsAtX( nCurX, 1, eWhichX )) * nMovX;
425 else
426 nPageX = ((SCsCOL) aViewData.CellsAtX( nCurX, -1, eWhichX )) * nMovX;
428 if (nMovY >= 0)
429 nPageY = ((SCsROW) aViewData.CellsAtY( nCurY, 1, eWhichY )) * nMovY;
430 else
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;
436 rPageX = nPageX;
437 rPageY = nPageY;
440 void ScTabView::GetAreaMoveEndPosition(SCsCOL nMovX, SCsROW nMovY, ScFollowMode eMode,
441 SCsCOL& rAreaX, SCsROW& rAreaY, ScFollowMode& rMode)
443 SCCOL nNewX = -1;
444 SCROW nNewY = -1;
445 SCCOL nCurX = -1;
446 SCROW nCurY = -1;
448 if (aViewData.IsRefMode())
450 nNewX = aViewData.GetRefEndX();
451 nNewY = aViewData.GetRefEndY();
453 else if (IsBlockMode())
455 nNewX = nBlockEndX;
456 nNewY = nBlockEndY;
458 else
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
469 SCsCOLROW i;
470 if ( nMovX > 0 )
471 for ( i=0; i<nMovX; i++ )
472 pDoc->FindAreaPos( nNewX, nNewY, nTab, 1, 0 );
473 if ( nMovX < 0 )
474 for ( i=0; i<-nMovX; i++ )
475 pDoc->FindAreaPos( nNewX, nNewY, nTab, -1, 0 );
476 if ( nMovY > 0 )
477 for ( i=0; i<nMovY; i++ )
478 pDoc->FindAreaPos( nNewX, nNewY, nTab, 0, 1 );
479 if ( nMovY < 0 )
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;
501 else
503 rAreaX = nNewX - nCurX;
504 rAreaY = nNewY - nCurY;
506 rMode = eMode;
509 namespace {
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)
517 return false;
519 if (!bCellProtected && !bSelectUnlocked)
520 return false;
522 return true;
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);
537 if (nMovX > 0)
539 if (rCol < MAXCOL)
541 for (SCCOL i = 0; i < nMovX; ++i)
543 if (!lcl_isCellQualified(pDoc, rCol+1, rRow, nTab, bSelectLocked, bSelectUnlocked))
544 break;
545 ++rCol;
549 else if (nMovX < 0)
551 if (rCol > 0)
553 nMovX = -nMovX;
554 for (SCCOL i = 0; i < nMovX; ++i)
556 if (!lcl_isCellQualified(pDoc, rCol-1, rRow, nTab, bSelectLocked, bSelectUnlocked))
557 break;
558 --rCol;
563 if (nMovY > 0)
565 if (rRow < MAXROW)
567 for (SCROW i = 0; i < nMovY; ++i)
569 if (!lcl_isCellQualified(pDoc, rCol, rRow+1, nTab, bSelectLocked, bSelectUnlocked))
570 break;
571 ++rRow;
575 else if (nMovY < 0)
577 if (rRow > 0)
579 nMovY = -nMovY;
580 for (SCROW i = 0; i < nMovY; ++i)
582 if (!lcl_isCellQualified(pDoc, rCol, rRow-1, nTab, bSelectLocked, bSelectUnlocked))
583 break;
584 --rRow;
592 void ScTabView::ExpandBlock(SCsCOL nMovX, SCsROW nMovY, ScFollowMode eMode)
594 if (!nMovX && !nMovY)
595 // Nothing to do. Bail out.
596 return;
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);
625 if (nMovX)
627 SCCOL nTempX = nNewX;
628 while (pDoc->IsHorOverlapped(nTempX, nNewY, nRefTab))
630 if (nMovX > 0)
631 ++nTempX;
632 else
633 --nTempX;
635 if (lcl_isCellQualified(pDoc, nTempX, nNewY, nRefTab, bSelectLocked, bSelectUnlocked))
636 nNewX = nTempX;
639 if (nMovY)
641 SCROW nTempY = nNewY;
642 while (pDoc->IsVerOverlapped(nNewX, nTempY, nRefTab))
644 if (nMovY > 0)
645 ++nTempY;
646 else
647 --nTempY;
649 if (lcl_isCellQualified(pDoc, nNewX, nTempY, nRefTab, bSelectLocked, bSelectUnlocked))
650 nNewY = nTempY;
653 pDoc->SkipOverlapped(nNewX, nNewY, nRefTab);
654 UpdateRef(nNewX, nNewY, nRefTab);
655 AlignToCursor(nNewX, nNewY, eMode);
657 else
659 // normal selection mode
661 SCTAB nTab = aViewData.GetTabNo();
663 if (!IsBlockMode())
664 InitBlockMode(aViewData.GetCurX(), aViewData.GetCurY(), nTab, true);
666 lcl_moveCursorByProtRule(nBlockEndX, nBlockEndY, nMovX, nMovY, nTab, pDoc);
668 if (nBlockEndX < 0)
669 nBlockEndX = 0;
670 else if (nBlockEndX > MAXCOL)
671 nBlockEndX = MAXCOL;
673 if (nBlockEndY < 0)
674 nBlockEndY = 0;
675 else if (nBlockEndY > MAXROW)
676 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)
695 SCsCOL nPageX;
696 SCsROW nPageY;
697 GetPageMoveEndPosition(nMovX, nMovY, nPageX, nPageY);
698 ExpandBlock(nPageX, nPageY, SC_FOLLOW_FIX);
701 void ScTabView::ExpandBlockArea(SCsCOL nMovX, SCsROW nMovY)
703 SCsCOL nAreaX;
704 SCsROW nAreaY;
705 ScFollowMode eMode;
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();
742 if (bMark || bMulti)
744 ScRange aMarkRange;
745 HideAllCursors();
746 if (bMulti)
748 BOOL bFlag = rMark.GetMarkingFlag();
749 rMark.SetMarking(FALSE);
750 rMark.MarkToMulti();
751 rMark.GetMultiMarkArea(aMarkRange);
752 rMark.MarkToSimple();
753 rMark.SetMarking(bFlag);
755 bMark = rMark.IsMarked();
756 bMulti = rMark.IsMultiMarked();
758 else
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 )
772 if ( bReset )
774 // Invertieren beim Loeschen nur auf aktiver View
775 if ( aViewData.IsActive() )
777 USHORT i;
778 if ( bMulti )
780 #ifdef OLD_SELECTION_PAINT
781 for (i=0; i<4; i++)
782 if (pGridWin[i] && pGridWin[i]->IsVisible())
783 pGridWin[i]->InvertSimple( nBlockStartX, nBlockStartY,
784 nBlockEndX, nBlockEndY,
785 TRUE, TRUE );
786 #endif
787 rMark.ResetMark();
788 UpdateSelectionOverlay();
789 bDidReset = TRUE;
791 else
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
798 rMark.MarkToMulti();
799 BOOL bOld = bBlockNeg;
800 bBlockNeg = TRUE;
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 );
807 bBlockNeg = bOld;
808 #endif
809 rMark.ResetMark();
810 UpdateSelectionOverlay();
811 bDidReset = TRUE;
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 ))
823 for (i=0; i<4; i++)
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();
836 else
837 PaintMarks( nBlockStartX, nBlockStartY, nBlockEndX, nBlockEndY );
840 if ( bReset && !bDidReset )
841 rMark.ResetMark();
843 ShowAllCursors();
847 void ScTabView::SelectAll( BOOL bContinue )
849 ScMarkData& rMark = aViewData.GetMarkData();
850 SCTAB nTab = aViewData.GetTabNo();
852 if (rMark.IsMarked())
854 ScRange aMarkRange;
855 rMark.GetMarkArea( aMarkRange );
856 if ( aMarkRange == ScRange( 0,0,nTab, MAXCOL,MAXROW,nTab ) )
857 return;
860 DoneBlockMode( bContinue );
861 InitBlockMode( 0,0,nTab );
862 MarkCursor( MAXCOL,MAXROW,nTab );
864 SelectionChanged();
867 void ScTabView::SelectAllTables()
869 ScDocument* pDoc = aViewData.GetDocument();
870 ScMarkData& rMark = aViewData.GetMarkData();
871 // SCTAB nTab = aViewData.GetTabNo();
872 SCTAB nCount = pDoc->GetTableCount();
874 if (nCount>1)
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;
914 long nBlockX = 0;
915 SCCOL nCol;
916 for (nCol=0; nCol<nFixPosX; nCol++)
918 // for frozen panes, add both parts
919 USHORT nColTwips = pDoc->GetColWidth( nCol, nTab );
920 if (nColTwips)
922 nBlockX += (long)(nColTwips * fScaleX);
923 if (nBlockX > nWindowX)
924 return FALSE;
927 for (nCol=nStartCol; nCol<=nEndCol; nCol++)
929 USHORT nColTwips = pDoc->GetColWidth( nCol, nTab );
930 if (nColTwips)
932 nBlockX += (long)(nColTwips * fScaleX);
933 if (nBlockX > nWindowX)
934 return FALSE;
938 long nBlockY = 0;
939 for (SCROW nRow = 0; nRow <= nFixPosY-1; ++nRow)
941 if (pDoc->RowHidden(nRow, nTab))
942 continue;
944 // for frozen panes, add both parts
945 USHORT nRowTwips = pDoc->GetRowHeight(nRow, nTab);
946 if (nRowTwips)
948 nBlockY += (long)(nRowTwips * fScaleY);
949 if (nBlockY > nWindowY)
950 return FALSE;
953 for (SCROW nRow = nStartRow; nRow <= nEndRow; ++nRow)
955 USHORT nRowTwips = pDoc->GetRowHeight(nRow, nTab);
956 if (nRowTwips)
958 nBlockY += (long)(nRowTwips * fScaleY);
959 if (nBlockY > nWindowY)
960 return FALSE;
964 return TRUE;
967 USHORT ScTabView::CalcZoom( SvxZoomType eType, USHORT nOldZoom )
969 USHORT nZoom = 0; // Ergebnis
971 switch ( eType )
973 case SVX_ZOOM_PERCENT: // rZoom ist kein besonderer prozentualer Wert
974 nZoom = nOldZoom;
975 break;
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
984 else
986 SCTAB nTab = aViewData.GetTabNo();
987 ScRange aMarkRange;
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 )
999 nTab = nStartTab;
1001 ScSplitPos eUsedPart = aViewData.GetActivePart();
1003 SCCOL nFixPosX = 0;
1004 SCROW nFixPosY = 0;
1005 if ( aViewData.GetHSplitMode() == SC_SPLIT_FIX )
1007 // use right part
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 )
1015 // use bottom part
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 ) )
1049 nMin = nTest;
1050 else
1051 nMax = nTest-1;
1053 DBG_ASSERT( nMin == nMax, "Schachtelung ist falsch" );
1054 nZoom = nMin;
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 );
1069 break;
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 :-/" );
1083 if ( pStyleSheet )
1085 ScPrintFunc aPrintFunc( aViewData.GetDocShell(),
1086 aViewData.GetViewShell()->GetPrinter(TRUE),
1087 nCurTab );
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 ) );
1137 long nNew = nZoomX;
1139 if (eType == SVX_ZOOM_WHOLEPAGE && nZoomY < nNew)
1140 nNew = nZoomY;
1142 nZoom = (USHORT) nNew;
1145 break;
1147 default:
1148 DBG_ERROR("Unknown Zoom-Revision");
1149 nZoom = 0;
1152 return nZoom;
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);
1164 if (pColBar[eH])
1165 pColBar[eH]->StopMarking();
1167 ScVSplitPos eV = WhichV(eActive);
1168 if (pRowBar[eV])
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()
1181 if (!pDrawView)
1183 aViewData.GetDocShell()->MakeDrawLayer();
1185 // pDrawView wird per Notify gesetzt
1186 DBG_ASSERT(pDrawView,"ScTabView::MakeDrawLayer funktioniert nicht");
1188 // #114409#
1189 for(sal_uInt16 a(0); a < 4; a++)
1191 if(pGridWin[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
1204 return;
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 ) );
1222 aBox.Execute();
1223 if (bFocus)
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);
1234 if (pChild)
1236 Window* pWin = pChild->GetWindow();
1237 if (pWin && pWin->IsVisible())
1238 return pWin;
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);
1256 if (!nCount)
1257 nCount = 1;
1258 pNewData = new ScPageBreakData(nCount);
1260 ScPrintFunc aPrintFunc( pDocSh, pDocSh->GetPrinter(), nTab, 0,0,NULL, NULL, pNewData );
1261 // ScPrintFunc fuellt im ctor die PageBreakData
1262 if ( nCount > 1 )
1264 aPrintFunc.ResetBreaks(nTab);
1265 pNewData->AddPages();
1268 // Druckbereiche veraendert?
1269 if ( bForcePaint || ( pPageBreakData && !pPageBreakData->IsEqual( *pNewData ) ) )
1270 PaintGrid();
1273 delete pPageBreakData;
1274 pPageBreakData = pNewData;