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