xref: /AOO41X/main/sc/source/ui/view/tabview2.cxx (revision 4d7c9de063a797b8b4f3d45e3561e82ad1f8ef1f)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sc.hxx"
26 
27 
28 
29 // INCLUDE ---------------------------------------------------------------
30 
31 #include "scitems.hxx"
32 #include <editeng/eeitem.hxx>
33 
34 
35 #include <vcl/timer.hxx>
36 #include <vcl/msgbox.hxx>
37 #include <sfx2/app.hxx>
38 #include <sfx2/viewfrm.hxx>
39 #include <sfx2/bindings.hxx>
40 #include <sfx2/childwin.hxx>
41 
42 #include "attrib.hxx"
43 #include "pagedata.hxx"
44 #include "tabview.hxx"
45 #include "tabvwsh.hxx"
46 #include "printfun.hxx"
47 #include "stlpool.hxx"
48 #include "docsh.hxx"
49 #include "gridwin.hxx"
50 #include "olinewin.hxx"
51 #include "uiitems.hxx"
52 #include "sc.hrc"
53 #include "viewutil.hxx"
54 #include "colrowba.hxx"
55 #include "waitoff.hxx"
56 #include "globstr.hrc"
57 #include "scmod.hxx"
58 
59 #define SC_BLOCKMODE_NONE       0
60 #define SC_BLOCKMODE_NORMAL     1
61 #define SC_BLOCKMODE_OWN        2
62 
63 
64 
65 //
66 //          Markier - Funktionen
67 //
68 
PaintMarks(SCCOL nStartCol,SCROW nStartRow,SCCOL nEndCol,SCROW nEndRow)69 void ScTabView::PaintMarks(SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow )
70 {
71     if (!ValidCol(nStartCol)) nStartCol = MAXCOL;
72     if (!ValidRow(nStartRow)) nStartRow = MAXROW;
73     if (!ValidCol(nEndCol)) nEndCol = MAXCOL;
74     if (!ValidRow(nEndRow)) nEndRow = MAXROW;
75 
76     sal_Bool bLeft = (nStartCol==0 && nEndCol==MAXCOL);
77     sal_Bool bTop = (nStartRow==0 && nEndRow==MAXROW);
78 
79     if (bLeft)
80         PaintLeftArea( nStartRow, nEndRow );
81     if (bTop)
82         PaintTopArea( nStartCol, nEndCol );
83 
84     aViewData.GetDocument()->ExtendMerge( nStartCol, nStartRow, nEndCol, nEndRow,
85                                             aViewData.GetTabNo() );
86     PaintArea( nStartCol, nStartRow, nEndCol, nEndRow, SC_UPDATE_MARKS );
87 }
88 
IsMarking(SCCOL nCol,SCROW nRow,SCTAB nTab) const89 sal_Bool ScTabView::IsMarking( SCCOL nCol, SCROW nRow, SCTAB nTab ) const
90 {
91     return bIsBlockMode
92         && nBlockStartX == nCol
93         && nBlockStartY == nRow
94         && nBlockStartZ == nTab;
95 }
96 
InitOwnBlockMode()97 void ScTabView::InitOwnBlockMode()
98 {
99     if (!bIsBlockMode)
100     {
101         //  Wenn keine (alte) Markierung mehr da ist, Anker in SelectionEngine loeschen:
102 
103         ScMarkData& rMark = aViewData.GetMarkData();
104         if (!rMark.IsMarked() && !rMark.IsMultiMarked())
105             GetSelEngine()->CursorPosChanging( sal_False, sal_False );
106 
107 //      bIsBlockMode = sal_True;
108         bIsBlockMode = SC_BLOCKMODE_OWN;            //! Variable umbenennen!
109         nBlockStartX = 0;
110         nBlockStartY = 0;
111         nBlockStartZ = 0;
112         nBlockEndX = 0;
113         nBlockEndY = 0;
114         nBlockEndZ = 0;
115 
116         SelectionChanged();     // Status wird mit gesetzer Markierung abgefragt
117     }
118 }
119 
InitBlockMode(SCCOL nCurX,SCROW nCurY,SCTAB nCurZ,sal_Bool bTestNeg,sal_Bool bCols,sal_Bool bRows,sal_Bool bForceNeg)120 void ScTabView::InitBlockMode( SCCOL nCurX, SCROW nCurY, SCTAB nCurZ,
121                                 sal_Bool bTestNeg, sal_Bool bCols, sal_Bool bRows, sal_Bool bForceNeg )
122 {
123     if (!bIsBlockMode)
124     {
125         if (!ValidCol(nCurX)) nCurX = MAXCOL;
126         if (!ValidRow(nCurY)) nCurY = MAXROW;
127 
128         ScMarkData& rMark = aViewData.GetMarkData();
129         SCTAB nTab = aViewData.GetTabNo();
130 
131         //  Teil von Markierung aufheben?
132         if (bForceNeg)
133             bBlockNeg = sal_True;
134         else if (bTestNeg)
135         {
136             if ( bCols )
137                 bBlockNeg = rMark.IsColumnMarked( nCurX );
138             else if ( bRows )
139                 bBlockNeg = rMark.IsRowMarked( nCurY );
140             else
141                 bBlockNeg = rMark.IsCellMarked( nCurX, nCurY );
142         }
143         else
144             bBlockNeg = sal_False;
145         rMark.SetMarkNegative(bBlockNeg);
146 
147 //      bIsBlockMode = sal_True;
148         bIsBlockMode = SC_BLOCKMODE_NORMAL;         //! Variable umbenennen!
149         bBlockCols = bCols;
150         bBlockRows = bRows;
151         nBlockStartX = nBlockStartXOrig = nCurX;
152         nBlockStartY = nBlockStartYOrig = nCurY;
153         nBlockStartZ = nCurZ;
154         nBlockEndX = nOldCurX = nBlockStartX;
155         nBlockEndY = nOldCurY = nBlockStartY;
156         nBlockEndZ = nBlockStartZ;
157 
158         if (bBlockCols)
159         {
160             nBlockStartY = nBlockStartYOrig = 0;
161             nBlockEndY = MAXROW;
162         }
163 
164         if (bBlockRows)
165         {
166             nBlockStartX = nBlockStartXOrig = 0;
167             nBlockEndX = MAXCOL;
168         }
169 
170         rMark.SetMarkArea( ScRange( nBlockStartX,nBlockStartY, nTab, nBlockEndX,nBlockEndY, nTab ) );
171 
172 #ifdef OLD_SELECTION_PAINT
173         InvertBlockMark( nBlockStartX,nBlockStartY,nBlockEndX,nBlockEndY );
174 #endif
175         UpdateSelectionOverlay();
176 
177         bNewStartIfMarking = sal_False;     // use only once
178     }
179 }
180 
SetNewStartIfMarking()181 void ScTabView::SetNewStartIfMarking()
182 {
183     bNewStartIfMarking = sal_True;
184 }
185 
DoneBlockMode(sal_Bool bContinue)186 void ScTabView::DoneBlockMode( sal_Bool bContinue )            // Default FALSE
187 {
188     //  Wenn zwischen Tabellen- und Header SelectionEngine gewechselt wird,
189     //  wird evtl. DeselectAll gerufen, weil die andere Engine keinen Anker hat.
190     //  Mit bMoveIsShift wird verhindert, dass dann die Selektion aufgehoben wird.
191 
192     if (bIsBlockMode && !bMoveIsShift)
193     {
194         ScMarkData& rMark = aViewData.GetMarkData();
195         sal_Bool bFlag = rMark.GetMarkingFlag();
196         rMark.SetMarking(sal_False);
197 
198         if (bBlockNeg && !bContinue)
199             rMark.MarkToMulti();
200 
201         if (bContinue)
202             rMark.MarkToMulti();
203         else
204         {
205             //  Die Tabelle kann an dieser Stelle ungueltig sein, weil DoneBlockMode
206             //  aus SetTabNo aufgerufen wird
207             //  (z.B. wenn die aktuelle Tabelle von einer anderen View aus geloescht wird)
208 
209             SCTAB nTab = aViewData.GetTabNo();
210             ScDocument* pDoc = aViewData.GetDocument();
211             if ( pDoc->HasTable(nTab) )
212                 PaintBlock( sal_True );                             // sal_True -> Block loeschen
213             else
214                 rMark.ResetMark();
215         }
216 //      bIsBlockMode = sal_False;
217         bIsBlockMode = SC_BLOCKMODE_NONE;           //! Variable umbenennen!
218 
219         rMark.SetMarking(bFlag);
220         rMark.SetMarkNegative(sal_False);
221     }
222 }
223 
MarkCursor(SCCOL nCurX,SCROW nCurY,SCTAB nCurZ,sal_Bool bCols,sal_Bool bRows,sal_Bool bCellSelection)224 void ScTabView::MarkCursor( SCCOL nCurX, SCROW nCurY, SCTAB nCurZ,
225                             sal_Bool bCols, sal_Bool bRows, sal_Bool bCellSelection )
226 {
227     if (!ValidCol(nCurX)) nCurX = MAXCOL;
228     if (!ValidRow(nCurY)) nCurY = MAXROW;
229 
230     if (!bIsBlockMode)
231     {
232         DBG_ERROR( "MarkCursor nicht im BlockMode" );
233         InitBlockMode( nCurX, nCurY, nCurZ, sal_False, bCols, bRows );
234     }
235 
236     if (bCols)
237         nCurY = MAXROW;
238     if (bRows)
239         nCurX = MAXCOL;
240 
241     ScMarkData& rMark = aViewData.GetMarkData();
242     DBG_ASSERT(rMark.IsMarked() || rMark.IsMultiMarked(), "MarkCursor, !IsMarked()");
243     ScRange aMarkRange;
244     rMark.GetMarkArea(aMarkRange);
245     if (( aMarkRange.aStart.Col() != nBlockStartX && aMarkRange.aEnd.Col() != nBlockStartX ) ||
246         ( aMarkRange.aStart.Row() != nBlockStartY && aMarkRange.aEnd.Row() != nBlockStartY ) ||
247         ( bIsBlockMode == SC_BLOCKMODE_OWN ))
248     {
249         //  Markierung ist veraendert worden
250         //  (z.B. MarkToSimple, wenn per negativ alles bis auf ein Rechteck geloescht wurde)
251         //  oder nach InitOwnBlockMode wird mit Shift-Klick weitermarkiert...
252 
253         sal_Bool bOldShift = bMoveIsShift;
254         bMoveIsShift = sal_False;               //  wirklich umsetzen
255         DoneBlockMode(sal_False);               //! direkt Variablen setzen? (-> kein Geflacker)
256         bMoveIsShift = bOldShift;
257 
258         InitBlockMode( aMarkRange.aStart.Col(), aMarkRange.aStart.Row(),
259                         nBlockStartZ, rMark.IsMarkNegative(), bCols, bRows );
260     }
261 
262     SCCOL nOldBlockEndX = nBlockEndX;
263     SCROW nOldBlockEndY = nBlockEndY;
264 
265     if ( nCurX != nOldCurX || nCurY != nOldCurY )
266     {
267         // Current cursor has moved
268 
269         SCTAB       nTab = nCurZ;
270 
271 #ifdef OLD_SELECTION_PAINT
272         SCCOL       nDrawStartCol;
273         SCROW       nDrawStartRow;
274         SCCOL       nDrawEndCol;
275         SCROW       nDrawEndRow;
276 #endif
277 
278         // Set old selection area
279         ScUpdateRect aRect( nBlockStartX, nBlockStartY, nOldBlockEndX, nOldBlockEndY );
280 
281         if ( bCellSelection )
282         {
283             // Expand selection area accordingly when the current selection ends
284             // with a merged cell.
285             SCsCOL nCurXOffset = 0;
286             SCsCOL nBlockStartXOffset = 0;
287             SCsROW nCurYOffset = 0;
288             SCsROW nBlockStartYOffset = 0;
289             sal_Bool bBlockStartMerged = sal_False;
290             const ScMergeAttr* pMergeAttr = NULL;
291             ScDocument* pDocument = aViewData.GetDocument();
292 
293             // The following block checks whether or not the "BlockStart" (anchor)
294             // cell is merged.  If it's merged, it'll then move the position of the
295             // anchor cell to the corner that's diagonally opposite of the
296             // direction of a current selection area.  For instance, if a current
297             // selection is moving in the upperleft direction, the anchor cell will
298             // move to the lower-right corner of the merged anchor cell, and so on.
299 
300             pMergeAttr = static_cast<const ScMergeAttr*>(
301                 pDocument->GetAttr( nBlockStartXOrig, nBlockStartYOrig, nTab, ATTR_MERGE ) );
302             if ( pMergeAttr->IsMerged() )
303             {
304                 SCsCOL nColSpan = pMergeAttr->GetColMerge();
305                 SCsROW nRowSpan = pMergeAttr->GetRowMerge();
306 
307                 if ( !( nCurX >= nBlockStartXOrig + nColSpan - 1 && nCurY >= nBlockStartYOrig + nRowSpan - 1 ) )
308                 {
309                     nBlockStartX = nCurX >= nBlockStartXOrig ? nBlockStartXOrig : nBlockStartXOrig + nColSpan - 1;
310                     nBlockStartY = nCurY >= nBlockStartYOrig ? nBlockStartYOrig : nBlockStartYOrig + nRowSpan - 1;
311                     nCurXOffset  = nCurX >= nBlockStartXOrig && nCurX < nBlockStartXOrig + nColSpan - 1 ?
312                         nBlockStartXOrig - nCurX + nColSpan - 1 : 0;
313                     nCurYOffset  = nCurY >= nBlockStartYOrig && nCurY < nBlockStartYOrig + nRowSpan - 1 ?
314                         nBlockStartYOrig - nCurY + nRowSpan - 1 : 0;
315                     bBlockStartMerged = sal_True;
316                 }
317             }
318 
319             // The following block checks whether or not the current cell is
320             // merged.  If it is, it'll then set the appropriate X & Y offset
321             // values (nCurXOffset & nCurYOffset) such that the selection area will
322             // grow by those specified offset amounts.  Note that the values of
323             // nCurXOffset/nCurYOffset may also be specified in the previous code
324             // block, in which case whichever value is greater will take on.
325 
326             pMergeAttr = static_cast<const ScMergeAttr*>(
327                 pDocument->GetAttr( nCurX, nCurY, nTab, ATTR_MERGE ) );
328             if ( pMergeAttr->IsMerged() )
329             {
330                 SCsCOL nColSpan = pMergeAttr->GetColMerge();
331                 SCsROW nRowSpan = pMergeAttr->GetRowMerge();
332 
333                 if ( !( nBlockStartX >= nCurX + nColSpan - 1 && nBlockStartY >= nCurY + nRowSpan - 1 ) )
334                 {
335                     if ( nBlockStartX <= nCurX + nColSpan - 1 )
336                     {
337                         SCsCOL nCurXOffsetTemp = nCurX < nCurX + nColSpan - 1 ? nColSpan - 1 : 0;
338                         nCurXOffset = nCurXOffset > nCurXOffsetTemp ? nCurXOffset : nCurXOffsetTemp;
339                     }
340                     if ( nBlockStartY <= nCurY + nRowSpan - 1 )
341                     {
342                         SCsROW nCurYOffsetTemp = nCurY < nCurY + nRowSpan - 1 ? nRowSpan - 1 : 0;
343                         nCurYOffset = nCurYOffset > nCurYOffsetTemp ? nCurYOffset : nCurYOffsetTemp;
344                     }
345                     if ( !( nBlockStartX <= nCurX && nBlockStartY <= nCurY ) &&
346                          !( nBlockStartX > nCurX + nColSpan - 1 && nBlockStartY > nCurY + nRowSpan - 1 ) )
347                     {
348                         nBlockStartXOffset = nBlockStartX > nCurX && nBlockStartX <= nCurX + nColSpan - 1 ? nCurX - nBlockStartX : 0;
349                         nBlockStartYOffset = nBlockStartY > nCurY && nBlockStartY <= nCurY + nRowSpan - 1 ? nCurY - nBlockStartY : 0;
350                     }
351                 }
352             }
353             else
354             {
355                 // The current cell is not merged.  Move the anchor cell to its
356                 // original position.
357                 if ( !bBlockStartMerged )
358                 {
359                     nBlockStartX = nBlockStartXOrig;
360                     nBlockStartY = nBlockStartYOrig;
361                 }
362             }
363 
364             nBlockStartX = nBlockStartX + nBlockStartXOffset >= 0 ? nBlockStartX + nBlockStartXOffset : 0;
365             nBlockStartY = nBlockStartY + nBlockStartYOffset >= 0 ? nBlockStartY + nBlockStartYOffset : 0;
366             nBlockEndX = nCurX + nCurXOffset > MAXCOL ? MAXCOL : nCurX + nCurXOffset;
367             nBlockEndY = nCurY + nCurYOffset > MAXROW ? MAXROW : nCurY + nCurYOffset;
368         }
369         else
370         {
371             nBlockEndX = nCurX;
372             nBlockEndY = nCurY;
373         }
374         // end of "if ( bCellSelection )"
375 
376         // Set new selection area
377         aRect.SetNew( nBlockStartX, nBlockStartY, nBlockEndX, nBlockEndY );
378         rMark.SetMarkArea( ScRange( nBlockStartX, nBlockStartY, nTab, nBlockEndX, nBlockEndY, nTab ) );
379 
380 #ifdef OLD_SELECTION_PAINT
381         sal_Bool bCont;
382         sal_Bool bDraw = aRect.GetXorDiff( nDrawStartCol, nDrawStartRow,
383                                         nDrawEndCol, nDrawEndRow, bCont );
384         if ( bDraw )
385         {
386 //?         PutInOrder( nDrawStartCol, nDrawEndCol );
387 //?         PutInOrder( nDrawStartRow, nDrawEndRow );
388 
389             HideAllCursors();
390             InvertBlockMark( nDrawStartCol, nDrawStartRow, nDrawEndCol, nDrawEndRow );
391             if (bCont)
392             {
393                 aRect.GetContDiff( nDrawStartCol, nDrawStartRow, nDrawEndCol, nDrawEndRow );
394                 InvertBlockMark( nDrawStartCol, nDrawStartRow, nDrawEndCol, nDrawEndRow );
395             }
396             ShowAllCursors();
397         }
398 #endif
399         UpdateSelectionOverlay();
400 
401         nOldCurX = nCurX;
402         nOldCurY = nCurY;
403 
404         aViewData.GetViewShell()->UpdateInputHandler();
405 //      InvalidateAttribs();
406     }
407 
408     if ( !bCols && !bRows )
409         aHdrFunc.SetAnchorFlag( sal_False );
410 }
411 
UpdateSelectionOverlay()412 void ScTabView::UpdateSelectionOverlay()
413 {
414     for (sal_uInt16 i=0; i<4; i++)
415         if ( pGridWin[i] && pGridWin[i]->IsVisible() )
416             pGridWin[i]->UpdateSelectionOverlay();
417 }
418 
UpdateShrinkOverlay()419 void ScTabView::UpdateShrinkOverlay()
420 {
421     for (sal_uInt16 i=0; i<4; i++)
422         if ( pGridWin[i] && pGridWin[i]->IsVisible() )
423             pGridWin[i]->UpdateShrinkOverlay();
424 }
425 
UpdateAllOverlays()426 void ScTabView::UpdateAllOverlays()
427 {
428     for (sal_uInt16 i=0; i<4; i++)
429         if ( pGridWin[i] && pGridWin[i]->IsVisible() )
430             pGridWin[i]->UpdateAllOverlays();
431 }
432 
433 //!
434 //! PaintBlock in zwei Methoden aufteilen: RepaintBlock und RemoveBlock o.ae.
435 //!
436 
PaintBlock(sal_Bool bReset)437 void ScTabView::PaintBlock( sal_Bool bReset )
438 {
439     ScDocument* pDoc = aViewData.GetDocument();
440     ScMarkData& rMark = aViewData.GetMarkData();
441     SCTAB nTab = aViewData.GetTabNo();
442     sal_Bool bMark = rMark.IsMarked();
443     sal_Bool bMulti = rMark.IsMultiMarked();
444     if (bMark || bMulti)
445     {
446         ScRange aMarkRange;
447         HideAllCursors();
448         if (bMulti)
449         {
450             sal_Bool bFlag = rMark.GetMarkingFlag();
451             rMark.SetMarking(sal_False);
452             rMark.MarkToMulti();
453             rMark.GetMultiMarkArea(aMarkRange);
454             rMark.MarkToSimple();
455             rMark.SetMarking(bFlag);
456 
457             bMark = rMark.IsMarked();
458             bMulti = rMark.IsMultiMarked();
459         }
460         else
461             rMark.GetMarkArea(aMarkRange);
462 
463         nBlockStartX = aMarkRange.aStart.Col();
464         nBlockStartY = aMarkRange.aStart.Row();
465         nBlockStartZ = aMarkRange.aStart.Tab();
466         nBlockEndX = aMarkRange.aEnd.Col();
467         nBlockEndY = aMarkRange.aEnd.Row();
468         nBlockEndZ = aMarkRange.aEnd.Tab();
469 
470         sal_Bool bDidReset = sal_False;
471 
472         if ( nTab>=nBlockStartZ && nTab<=nBlockEndZ )
473         {
474             if ( bReset )
475             {
476                 // Invertieren beim Loeschen nur auf aktiver View
477                 if ( aViewData.IsActive() )
478                 {
479                     sal_uInt16 i;
480                     if ( bMulti )
481                     {
482 #ifdef OLD_SELECTION_PAINT
483                         for (i=0; i<4; i++)
484                             if (pGridWin[i] && pGridWin[i]->IsVisible())
485                                 pGridWin[i]->InvertSimple( nBlockStartX, nBlockStartY,
486                                                             nBlockEndX, nBlockEndY,
487                                                             sal_True, sal_True );
488 #endif
489                         rMark.ResetMark();
490                         UpdateSelectionOverlay();
491                         bDidReset = sal_True;
492                     }
493                     else
494                     {
495 #ifdef OLD_SELECTION_PAINT
496                         // (mis)use InvertBlockMark to remove all of the selection
497                         // -> set bBlockNeg (like when removing parts of a selection)
498                         //    and convert everything to Multi
499 
500                         rMark.MarkToMulti();
501                         sal_Bool bOld = bBlockNeg;
502                         bBlockNeg = sal_True;
503                         // #73130# (negative) MarkArea must be set in case of repaint
504                         rMark.SetMarkArea( ScRange( nBlockStartX,nBlockStartY, nTab,
505                                                     nBlockEndX,nBlockEndY, nTab ) );
506 
507                         InvertBlockMark( nBlockStartX, nBlockStartY, nBlockEndX, nBlockEndY );
508 
509                         bBlockNeg = bOld;
510 #endif
511                         rMark.ResetMark();
512                         UpdateSelectionOverlay();
513                         bDidReset = sal_True;
514                     }
515 
516                     //  repaint if controls are touched (#69680# in both cases)
517                     // #i74768# Forms are rendered by DrawingLayer's EndDrawLayers()
518                     static bool bSuppressControlExtraStuff(true);
519 
520                     if(!bSuppressControlExtraStuff)
521                     {
522                         Rectangle aMMRect = pDoc->GetMMRect(nBlockStartX,nBlockStartY,nBlockEndX,nBlockEndY, nTab);
523                         if (pDoc->HasControl( nTab, aMMRect ))
524                         {
525                             for (i=0; i<4; i++)
526                             {
527                                 if (pGridWin[i] && pGridWin[i]->IsVisible())
528                                 {
529                                     //  MapMode muss logischer (1/100mm) sein !!!
530                                     pDoc->InvalidateControls( pGridWin[i], nTab, aMMRect );
531                                     pGridWin[i]->Update();
532                                 }
533                             }
534                         }
535                     }
536                 }
537             }
538             else
539                 PaintMarks( nBlockStartX, nBlockStartY, nBlockEndX, nBlockEndY );
540         }
541 
542         if ( bReset && !bDidReset )
543             rMark.ResetMark();
544 
545         ShowAllCursors();
546     }
547 }
548 
SelectAll(sal_Bool bContinue)549 void ScTabView::SelectAll( sal_Bool bContinue )
550 {
551     ScMarkData& rMark = aViewData.GetMarkData();
552     SCTAB nTab = aViewData.GetTabNo();
553 
554     if (rMark.IsMarked())
555     {
556         ScRange aMarkRange;
557         rMark.GetMarkArea( aMarkRange );
558         if ( aMarkRange == ScRange( 0,0,nTab, MAXCOL,MAXROW,nTab ) )
559             return;
560     }
561 
562     DoneBlockMode( bContinue );
563     InitBlockMode( 0,0,nTab );
564     MarkCursor( MAXCOL,MAXROW,nTab );
565 
566     SelectionChanged();
567 }
568 
SelectAllTables()569 void ScTabView::SelectAllTables()
570 {
571     ScDocument* pDoc = aViewData.GetDocument();
572     ScMarkData& rMark = aViewData.GetMarkData();
573 //    SCTAB nTab = aViewData.GetTabNo();
574     SCTAB nCount = pDoc->GetTableCount();
575 
576     if (nCount>1)
577     {
578         for (SCTAB i=0; i<nCount; i++)
579             rMark.SelectTable( i, sal_True );
580 
581         //      Markierungen werden per Default nicht pro Tabelle gehalten
582 //      pDoc->ExtendMarksFromTable( nTab );
583 
584         aViewData.GetDocShell()->PostPaintExtras();
585         SfxBindings& rBind = aViewData.GetBindings();
586         rBind.Invalidate( FID_FILL_TAB );
587         rBind.Invalidate( FID_TAB_DESELECTALL );
588     }
589 }
590 
DeselectAllTables()591 void ScTabView::DeselectAllTables()
592 {
593     ScDocument* pDoc = aViewData.GetDocument();
594     ScMarkData& rMark = aViewData.GetMarkData();
595     SCTAB nTab = aViewData.GetTabNo();
596     SCTAB nCount = pDoc->GetTableCount();
597 
598     for (SCTAB i=0; i<nCount; i++)
599         rMark.SelectTable( i, ( i == nTab ) );
600 
601     aViewData.GetDocShell()->PostPaintExtras();
602     SfxBindings& rBind = aViewData.GetBindings();
603     rBind.Invalidate( FID_FILL_TAB );
604     rBind.Invalidate( FID_TAB_DESELECTALL );
605 }
606 
lcl_FitsInWindow(double fScaleX,double fScaleY,sal_uInt16 nZoom,long nWindowX,long nWindowY,ScDocument * pDoc,SCTAB nTab,SCCOL nStartCol,SCROW nStartRow,SCCOL nEndCol,SCROW nEndRow,SCCOL nFixPosX,SCROW nFixPosY)607 sal_Bool lcl_FitsInWindow( double fScaleX, double fScaleY, sal_uInt16 nZoom,
608                         long nWindowX, long nWindowY, ScDocument* pDoc, SCTAB nTab,
609                         SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow,
610                         SCCOL nFixPosX, SCROW nFixPosY )
611 {
612     double fZoomFactor = (double)Fraction(nZoom,100);
613     fScaleX *= fZoomFactor;
614     fScaleY *= fZoomFactor;
615 
616     long nBlockX = 0;
617     SCCOL nCol;
618     for (nCol=0; nCol<nFixPosX; nCol++)
619     {
620         //  for frozen panes, add both parts
621         sal_uInt16 nColTwips = pDoc->GetColWidth( nCol, nTab );
622         if (nColTwips)
623         {
624             nBlockX += (long)(nColTwips * fScaleX);
625             if (nBlockX > nWindowX)
626                 return sal_False;
627         }
628     }
629     for (nCol=nStartCol; nCol<=nEndCol; nCol++)
630     {
631         sal_uInt16 nColTwips = pDoc->GetColWidth( nCol, nTab );
632         if (nColTwips)
633         {
634             nBlockX += (long)(nColTwips * fScaleX);
635             if (nBlockX > nWindowX)
636                 return sal_False;
637         }
638     }
639 
640     long nBlockY = 0;
641     for (SCROW nRow = 0; nRow <= nFixPosY-1; ++nRow)
642     {
643         if (pDoc->RowHidden(nRow, nTab))
644             continue;
645 
646         //  for frozen panes, add both parts
647         sal_uInt16 nRowTwips = pDoc->GetRowHeight(nRow, nTab);
648         if (nRowTwips)
649         {
650             nBlockY += (long)(nRowTwips * fScaleY);
651             if (nBlockY > nWindowY)
652                 return sal_False;
653         }
654     }
655     for (SCROW nRow = nStartRow; nRow <= nEndRow; ++nRow)
656     {
657         sal_uInt16 nRowTwips = pDoc->GetRowHeight(nRow, nTab);
658         if (nRowTwips)
659         {
660             nBlockY += (long)(nRowTwips * fScaleY);
661             if (nBlockY > nWindowY)
662                 return sal_False;
663         }
664     }
665 
666     return sal_True;
667 }
668 
CalcZoom(SvxZoomType eType,sal_uInt16 nOldZoom)669 sal_uInt16 ScTabView::CalcZoom( SvxZoomType eType, sal_uInt16 nOldZoom )
670 {
671     sal_uInt16 nZoom = 0; // Ergebnis
672 
673     switch ( eType )
674     {
675         case SVX_ZOOM_PERCENT: // rZoom ist kein besonderer prozentualer Wert
676             nZoom = nOldZoom;
677             break;
678 
679         case SVX_ZOOM_OPTIMAL:  // nZoom entspricht der optimalen Gr"o\se
680             {
681                 ScMarkData& rMark = aViewData.GetMarkData();
682                 ScDocument* pDoc = aViewData.GetDocument();
683 
684                 if (!rMark.IsMarked() && !rMark.IsMultiMarked())
685                     nZoom = 100;                // nothing selected
686                 else
687                 {
688                     SCTAB   nTab = aViewData.GetTabNo();
689                     ScRange aMarkRange;
690                     if ( aViewData.GetSimpleArea( aMarkRange ) != SC_MARK_SIMPLE )
691                         rMark.GetMultiMarkArea( aMarkRange );
692 
693                     SCCOL   nStartCol = aMarkRange.aStart.Col();
694                     SCROW   nStartRow = aMarkRange.aStart.Row();
695                     SCTAB   nStartTab = aMarkRange.aStart.Tab();
696                     SCCOL   nEndCol = aMarkRange.aEnd.Col();
697                     SCROW   nEndRow = aMarkRange.aEnd.Row();
698                     SCTAB   nEndTab = aMarkRange.aEnd.Tab();
699 
700                     if ( nTab < nStartTab && nTab > nEndTab )
701                         nTab = nStartTab;
702 
703                     ScSplitPos eUsedPart = aViewData.GetActivePart();
704 
705                     SCCOL nFixPosX = 0;
706                     SCROW nFixPosY = 0;
707                     if ( aViewData.GetHSplitMode() == SC_SPLIT_FIX )
708                     {
709                         //  use right part
710                         eUsedPart = (WhichV(eUsedPart)==SC_SPLIT_TOP) ? SC_SPLIT_TOPRIGHT : SC_SPLIT_BOTTOMRIGHT;
711                         nFixPosX = aViewData.GetFixPosX();
712                         if ( nStartCol < nFixPosX )
713                             nStartCol = nFixPosX;
714                     }
715                     if ( aViewData.GetVSplitMode() == SC_SPLIT_FIX )
716                     {
717                         //  use bottom part
718                         eUsedPart = (WhichH(eUsedPart)==SC_SPLIT_LEFT) ? SC_SPLIT_BOTTOMLEFT : SC_SPLIT_BOTTOMRIGHT;
719                         nFixPosY = aViewData.GetFixPosY();
720                         if ( nStartRow < nFixPosY )
721                             nStartRow = nFixPosY;
722                     }
723 
724                     if (pGridWin[eUsedPart])
725                     {
726                         //  Because scale is rounded to pixels, the only reliable way to find
727                         //  the right scale is to check if a zoom fits
728 
729                         Size aWinSize = pGridWin[eUsedPart]->GetOutputSizePixel();
730 
731                         //  for frozen panes, use sum of both parts for calculation
732 
733                         if ( nFixPosX != 0 )
734                             aWinSize.Width() += GetGridWidth( SC_SPLIT_LEFT );
735                         if ( nFixPosY != 0 )
736                             aWinSize.Height() += GetGridHeight( SC_SPLIT_TOP );
737 
738                         ScDocShell* pDocSh = aViewData.GetDocShell();
739                         double nPPTX = ScGlobal::nScreenPPTX / pDocSh->GetOutputFactor();
740                         double nPPTY = ScGlobal::nScreenPPTY;
741 
742                         sal_uInt16 nMin = MINZOOM;
743                         sal_uInt16 nMax = MAXZOOM;
744                         while ( nMax > nMin )
745                         {
746                             sal_uInt16 nTest = (nMin+nMax+1)/2;
747                             if ( lcl_FitsInWindow(
748                                         nPPTX, nPPTY, nTest, aWinSize.Width(), aWinSize.Height(),
749                                         pDoc, nTab, nStartCol, nStartRow, nEndCol, nEndRow,
750                                         nFixPosX, nFixPosY ) )
751                                 nMin = nTest;
752                             else
753                                 nMax = nTest-1;
754                         }
755                         DBG_ASSERT( nMin == nMax, "Schachtelung ist falsch" );
756                         nZoom = nMin;
757 
758                         if ( nZoom != nOldZoom )
759                         {
760                             // scroll to block only in active split part
761                             // (the part for which the size was calculated)
762 
763                             if ( nStartCol <= nEndCol )
764                                 aViewData.SetPosX( WhichH(eUsedPart), nStartCol );
765                             if ( nStartRow <= nEndRow )
766                                 aViewData.SetPosY( WhichV(eUsedPart), nStartRow );
767                         }
768                     }
769                 }
770             }
771             break;
772 
773             case SVX_ZOOM_WHOLEPAGE:    // nZoom entspricht der ganzen Seite oder
774             case SVX_ZOOM_PAGEWIDTH:    // nZoom entspricht der Seitenbreite
775                 {
776                     SCTAB               nCurTab     = aViewData.GetTabNo();
777                     ScDocument*         pDoc        = aViewData.GetDocument();
778                     ScStyleSheetPool*   pStylePool  = pDoc->GetStyleSheetPool();
779                     SfxStyleSheetBase*  pStyleSheet =
780                                             pStylePool->Find( pDoc->GetPageStyle( nCurTab ),
781                                                               SFX_STYLE_FAMILY_PAGE );
782 
783                     DBG_ASSERT( pStyleSheet, "PageStyle not found :-/" );
784 
785                     if ( pStyleSheet )
786                     {
787                         ScPrintFunc aPrintFunc( aViewData.GetDocShell(),
788                                                 aViewData.GetViewShell()->GetPrinter(sal_True),
789                                                 nCurTab );
790 
791                         Size aPageSize = aPrintFunc.GetDataSize();
792 
793                         //  use the size of the largest GridWin for normal split,
794                         //  or both combined for frozen panes, with the (document) size
795                         //  of the frozen part added to the page size
796                         //  (with frozen panes, the size of the individual parts
797                         //  depends on the scale that is to be calculated)
798 
799                         if ( !pGridWin[SC_SPLIT_BOTTOMLEFT] ) return 0;
800                         Size aWinSize = pGridWin[SC_SPLIT_BOTTOMLEFT]->GetOutputSizePixel();
801                         ScSplitMode eHMode = aViewData.GetHSplitMode();
802                         if ( eHMode != SC_SPLIT_NONE && pGridWin[SC_SPLIT_BOTTOMRIGHT] )
803                         {
804                             long nOtherWidth = pGridWin[SC_SPLIT_BOTTOMRIGHT]->
805                                                         GetOutputSizePixel().Width();
806                             if ( eHMode == SC_SPLIT_FIX )
807                             {
808                                 aWinSize.Width() += nOtherWidth;
809                                 for ( SCCOL nCol = aViewData.GetPosX(SC_SPLIT_LEFT);
810                                         nCol < aViewData.GetFixPosX(); nCol++ )
811                                     aPageSize.Width() += pDoc->GetColWidth( nCol, nCurTab );
812                             }
813                             else if ( nOtherWidth > aWinSize.Width() )
814                                 aWinSize.Width() = nOtherWidth;
815                         }
816                         ScSplitMode eVMode = aViewData.GetVSplitMode();
817                         if ( eVMode != SC_SPLIT_NONE && pGridWin[SC_SPLIT_TOPLEFT] )
818                         {
819                             long nOtherHeight = pGridWin[SC_SPLIT_TOPLEFT]->
820                                                         GetOutputSizePixel().Height();
821                             if ( eVMode == SC_SPLIT_FIX )
822                             {
823                                 aWinSize.Height() += nOtherHeight;
824                                 aPageSize.Height() += pDoc->GetRowHeight(
825                                         aViewData.GetPosY(SC_SPLIT_TOP),
826                                         aViewData.GetFixPosY()-1, nCurTab);
827                             }
828                             else if ( nOtherHeight > aWinSize.Height() )
829                                 aWinSize.Height() = nOtherHeight;
830                         }
831 
832                         double nPPTX = ScGlobal::nScreenPPTX / aViewData.GetDocShell()->GetOutputFactor();
833                         double nPPTY = ScGlobal::nScreenPPTY;
834 
835                         long nZoomX = (long) ( aWinSize.Width() * 100 /
836                                                ( aPageSize.Width() * nPPTX ) );
837                         long nZoomY = (long) ( aWinSize.Height() * 100 /
838                                                ( aPageSize.Height() * nPPTY ) );
839                         long nNew = nZoomX;
840 
841                         if (eType == SVX_ZOOM_WHOLEPAGE && nZoomY < nNew)
842                             nNew = nZoomY;
843 
844                         nZoom = (sal_uInt16) nNew;
845                     }
846                 }
847                 break;
848 
849         default:
850             DBG_ERROR("Unknown Zoom-Revision");
851             nZoom = 0;
852     }
853 
854     return nZoom;
855 }
856 
857 //  wird z.B. gerufen, wenn sich das View-Fenster verschiebt:
858 
StopMarking()859 void ScTabView::StopMarking()
860 {
861     ScSplitPos eActive = aViewData.GetActivePart();
862     if (pGridWin[eActive])
863         pGridWin[eActive]->StopMarking();
864 
865     ScHSplitPos eH = WhichH(eActive);
866     if (pColBar[eH])
867         pColBar[eH]->StopMarking();
868 
869     ScVSplitPos eV = WhichV(eActive);
870     if (pRowBar[eV])
871         pRowBar[eV]->StopMarking();
872 }
873 
HideNoteMarker()874 void ScTabView::HideNoteMarker()
875 {
876     for (sal_uInt16 i=0; i<4; i++)
877         if (pGridWin[i] && pGridWin[i]->IsVisible())
878             pGridWin[i]->HideNoteMarker();
879 }
880 
MakeDrawLayer()881 void ScTabView::MakeDrawLayer()
882 {
883     if (!pDrawView)
884     {
885         aViewData.GetDocShell()->MakeDrawLayer();
886 
887         //  pDrawView wird per Notify gesetzt
888         DBG_ASSERT(pDrawView,"ScTabView::MakeDrawLayer funktioniert nicht");
889 
890         // #114409#
891         for(sal_uInt16 a(0); a < 4; a++)
892         {
893             if(pGridWin[a])
894             {
895                 pGridWin[a]->DrawLayerCreated();
896             }
897         }
898     }
899 }
900 
ErrorMessage(sal_uInt16 nGlobStrId)901 void ScTabView::ErrorMessage( sal_uInt16 nGlobStrId )
902 {
903     if ( SC_MOD()->IsInExecuteDrop() )
904     {
905         // #i28468# don't show error message when called from Drag&Drop, silently abort instead
906         return;
907     }
908 
909     StopMarking();      // falls per Focus aus MouseButtonDown aufgerufen
910 
911     Window* pParent = aViewData.GetDialogParent();
912     ScWaitCursorOff aWaitOff( pParent );
913     sal_Bool bFocus = pParent && pParent->HasFocus();
914 
915     if(nGlobStrId==STR_PROTECTIONERR)
916     {
917         if(aViewData.GetDocShell()->IsReadOnly())
918         {
919             nGlobStrId=STR_READONLYERR;
920         }
921     }
922 
923     InfoBox aBox( pParent, ScGlobal::GetRscString( nGlobStrId ) );
924     aBox.Execute();
925     if (bFocus)
926         pParent->GrabFocus();
927 }
928 
GetParentOrChild(sal_uInt16 nChildId)929 Window* ScTabView::GetParentOrChild( sal_uInt16 nChildId )
930 {
931     SfxViewFrame* pViewFrm = aViewData.GetViewShell()->GetViewFrame();
932 
933     if ( pViewFrm->HasChildWindow(nChildId) )
934     {
935         SfxChildWindow* pChild = pViewFrm->GetChildWindow(nChildId);
936         if (pChild)
937         {
938             Window* pWin = pChild->GetWindow();
939             if (pWin && pWin->IsVisible())
940                 return pWin;
941         }
942     }
943 
944     return aViewData.GetDialogParent();
945 }
946 
UpdatePageBreakData(sal_Bool bForcePaint)947 void ScTabView::UpdatePageBreakData( sal_Bool bForcePaint )
948 {
949     ScPageBreakData* pNewData = NULL;
950 
951     if (aViewData.IsPagebreakMode())
952     {
953         ScDocShell* pDocSh = aViewData.GetDocShell();
954         ScDocument* pDoc = pDocSh->GetDocument();
955         SCTAB nTab = aViewData.GetTabNo();
956 
957         sal_uInt16 nCount = pDoc->GetPrintRangeCount(nTab);
958         if (!nCount)
959             nCount = 1;
960         pNewData = new ScPageBreakData(nCount);
961 
962         ScPrintFunc aPrintFunc( pDocSh, pDocSh->GetPrinter(), nTab, 0,0,NULL, NULL, pNewData );
963         //  ScPrintFunc fuellt im ctor die PageBreakData
964         if ( nCount > 1 )
965         {
966             aPrintFunc.ResetBreaks(nTab);
967             pNewData->AddPages();
968         }
969 
970         //  Druckbereiche veraendert?
971         if ( bForcePaint || ( pPageBreakData && !pPageBreakData->IsEqual( *pNewData ) ) )
972             PaintGrid();
973     }
974 
975     delete pPageBreakData;
976     pPageBreakData = pNewData;
977 }
978 
979 
980 
981