xref: /trunk/main/sc/source/ui/view/tabview2.cxx (revision 4d7c9de0)
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