Version 4.0.2.1, tag libreoffice-4.0.2.1
[LibreOffice.git] / sc / source / ui / view / tabview4.cxx
blob07f96f2fee301f99356ad429eaaba811a56fd59e
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <vcl/help.hxx>
21 #include <vcl/svapp.hxx>
23 #include "tabview.hxx"
24 #include "document.hxx"
25 #include "docsh.hxx"
26 #include "scmod.hxx"
27 #include "gridwin.hxx"
28 #include "globstr.hrc"
29 #include "cell.hxx"
30 #include "dociter.hxx"
32 extern sal_uInt16 nScFillModeMouseModifier; // global.cxx
34 // STATIC DATA -----------------------------------------------------------
36 //==================================================================
39 // --- Referenz-Eingabe / Fill-Cursor
42 void ScTabView::HideTip()
44 if ( nTipVisible )
46 Help::HideTip( nTipVisible );
47 nTipVisible = 0;
51 void ScTabView::ShowRefTip()
53 sal_Bool bDone = false;
54 if ( aViewData.GetRefType() == SC_REFTYPE_REF && Help::IsQuickHelpEnabled() )
56 SCCOL nStartX = aViewData.GetRefStartX();
57 SCROW nStartY = aViewData.GetRefStartY();
58 SCCOL nEndX = aViewData.GetRefEndX();
59 SCROW nEndY = aViewData.GetRefEndY();
60 if ( nEndX != nStartX || nEndY != nStartY ) // nicht fuer einzelne Zelle
62 sal_Bool bLeft = ( nEndX < nStartX );
63 sal_Bool bTop = ( nEndY < nStartY );
64 PutInOrder( nStartX, nEndX );
65 PutInOrder( nStartY, nEndY );
66 SCCOL nCols = nEndX+1-nStartX;
67 SCROW nRows = nEndY+1-nStartY;
69 String aHelp = ScGlobal::GetRscString( STR_QUICKHELP_REF );
70 aHelp.SearchAndReplace( rtl::OUString("%1"),
71 String::CreateFromInt32(nRows) );
72 aHelp.SearchAndReplace( rtl::OUString("%2"),
73 String::CreateFromInt32(nCols) );
75 ScSplitPos eWhich = aViewData.GetActivePart();
76 Window* pWin = pGridWin[eWhich];
77 if ( pWin )
79 Point aStart = aViewData.GetScrPos( nStartX, nStartY, eWhich );
80 Point aEnd = aViewData.GetScrPos( nEndX+1, nEndY+1, eWhich );
82 Point aPos( bLeft ? aStart.X() : ( aEnd.X() + 3 ),
83 bTop ? aStart.Y() : ( aEnd.Y() + 3 ) );
84 sal_uInt16 nFlags = ( bLeft ? QUICKHELP_RIGHT : QUICKHELP_LEFT ) |
85 ( bTop ? QUICKHELP_BOTTOM : QUICKHELP_TOP );
87 // nicht ueber die editierte Formel
88 if ( !bTop && aViewData.HasEditView( eWhich ) &&
89 nEndY+1 == aViewData.GetEditViewRow() )
91 // dann an der oberen Kante der editierten Zelle ausrichten
92 aPos.Y() -= 2; // die 3 von oben
93 nFlags = ( nFlags & ~QUICKHELP_TOP ) | QUICKHELP_BOTTOM;
96 Rectangle aRect( pWin->OutputToScreenPixel( aPos ), Size(1,1) );
98 //! Test, ob geaendert ??
100 HideTip();
101 nTipVisible = Help::ShowTip( pWin, aRect, aHelp, nFlags );
102 bDone = sal_True;
107 if (!bDone)
108 HideTip();
111 void ScTabView::StopRefMode()
113 if (aViewData.IsRefMode())
115 aViewData.SetRefMode( false, SC_REFTYPE_NONE );
117 HideTip();
118 UpdateShrinkOverlay();
120 if ( aViewData.GetTabNo() >= aViewData.GetRefStartZ() &&
121 aViewData.GetTabNo() <= aViewData.GetRefEndZ() )
123 ScDocument* pDoc = aViewData.GetDocument();
124 SCCOL nStartX = aViewData.GetRefStartX();
125 SCROW nStartY = aViewData.GetRefStartY();
126 SCCOL nEndX = aViewData.GetRefEndX();
127 SCROW nEndY = aViewData.GetRefEndY();
128 if ( nStartX == nEndX && nStartY == nEndY )
129 pDoc->ExtendMerge( nStartX, nStartY, nEndX, nEndY, aViewData.GetTabNo() );
131 PaintArea( nStartX,nStartY,nEndX,nEndY, SC_UPDATE_MARKS );
134 pSelEngine->Reset();
135 pSelEngine->SetAddMode( false ); //! sollte das nicht bei Reset passieren?
137 ScSplitPos eOld = pSelEngine->GetWhich();
138 ScSplitPos eNew = aViewData.GetActivePart();
139 if ( eNew != eOld )
141 pSelEngine->SetWindow( pGridWin[ eNew ] );
142 pSelEngine->SetWhich( eNew );
143 pSelEngine->SetVisibleArea( Rectangle(Point(),
144 pGridWin[eNew]->GetOutputSizePixel()) );
145 pGridWin[eOld]->MoveMouseStatus(*pGridWin[eNew]);
149 // AlignToCursor(SC_FOLLOW_NONE): Only switch active part.
150 // This must also be done if no RefMode was active (for RangeFinder dragging),
151 // but if RefMode was set, AlignToCursor must be after SelectionEngine reset,
152 // so the SelectionEngine SetWindow call from AlignToCursor doesn't capture
153 // the mouse again when called from Tracking/MouseButtonUp (#94562#).
154 AlignToCursor( aViewData.GetCurX(), aViewData.GetCurY(), SC_FOLLOW_NONE );
157 void ScTabView::DoneRefMode( bool bContinue )
159 ScDocument* pDoc = aViewData.GetDocument();
160 if ( aViewData.GetRefType() == SC_REFTYPE_REF && bContinue )
161 SC_MOD()->AddRefEntry();
163 sal_Bool bWasRef = aViewData.IsRefMode();
164 aViewData.SetRefMode( false, SC_REFTYPE_NONE );
166 HideTip();
167 UpdateShrinkOverlay();
169 // Paint:
170 if ( bWasRef && aViewData.GetTabNo() >= aViewData.GetRefStartZ() &&
171 aViewData.GetTabNo() <= aViewData.GetRefEndZ() )
173 SCCOL nStartX = aViewData.GetRefStartX();
174 SCROW nStartY = aViewData.GetRefStartY();
175 SCCOL nEndX = aViewData.GetRefEndX();
176 SCROW nEndY = aViewData.GetRefEndY();
177 if ( nStartX == nEndX && nStartY == nEndY )
178 pDoc->ExtendMerge( nStartX, nStartY, nEndX, nEndY, aViewData.GetTabNo() );
180 PaintArea( nStartX,nStartY,nEndX,nEndY, SC_UPDATE_MARKS );
184 void ScTabView::UpdateRef( SCCOL nCurX, SCROW nCurY, SCTAB nCurZ )
186 ScDocument* pDoc = aViewData.GetDocument();
188 if (!aViewData.IsRefMode())
190 // Das kommt vor, wenn bei einem Referenz-Dialog als erstes mit Control in die
191 // die Tabelle geklickt wird. Dann die neue Referenz an den alten Inhalt anhaengen:
193 ScModule* pScMod = SC_MOD();
194 if (pScMod->IsFormulaMode())
195 pScMod->AddRefEntry();
197 InitRefMode( nCurX, nCurY, nCurZ, SC_REFTYPE_REF );
200 if ( nCurX != aViewData.GetRefEndX() || nCurY != aViewData.GetRefEndY() ||
201 nCurZ != aViewData.GetRefEndZ() )
203 ScMarkData& rMark = aViewData.GetMarkData();
204 SCTAB nTab = aViewData.GetTabNo();
206 SCCOL nStartX = aViewData.GetRefStartX();
207 SCROW nStartY = aViewData.GetRefStartY();
208 SCCOL nEndX = aViewData.GetRefEndX();
209 SCROW nEndY = aViewData.GetRefEndY();
210 if ( nStartX == nEndX && nStartY == nEndY )
211 pDoc->ExtendMerge( nStartX, nStartY, nEndX, nEndY, nTab );
212 ScUpdateRect aRect( nStartX, nStartY, nEndX, nEndY );
214 aViewData.SetRefEnd( nCurX, nCurY, nCurZ );
216 nStartX = aViewData.GetRefStartX();
217 nStartY = aViewData.GetRefStartY();
218 nEndX = aViewData.GetRefEndX();
219 nEndY = aViewData.GetRefEndY();
220 if ( nStartX == nEndX && nStartY == nEndY )
221 pDoc->ExtendMerge( nStartX, nStartY, nEndX, nEndY, nTab );
222 aRect.SetNew( nStartX, nStartY, nEndX, nEndY );
224 ScRefType eType = aViewData.GetRefType();
225 if ( eType == SC_REFTYPE_REF )
227 ScRange aRef(
228 aViewData.GetRefStartX(), aViewData.GetRefStartY(), aViewData.GetRefStartZ(),
229 aViewData.GetRefEndX(), aViewData.GetRefEndY(), aViewData.GetRefEndZ() );
230 SC_MOD()->SetReference( aRef, pDoc, &rMark );
231 ShowRefTip();
233 else if ( eType == SC_REFTYPE_EMBED_LT || eType == SC_REFTYPE_EMBED_RB )
235 PutInOrder(nStartX,nEndX);
236 PutInOrder(nStartY,nEndY);
237 pDoc->SetEmbedded( ScRange(nStartX,nStartY,nTab, nEndX,nEndY,nTab) );
238 ScDocShell* pDocSh = aViewData.GetDocShell();
239 pDocSh->UpdateOle( &aViewData, sal_True );
240 pDocSh->SetDocumentModified();
243 SCCOL nPaintStartX;
244 SCROW nPaintStartY;
245 SCCOL nPaintEndX;
246 SCROW nPaintEndY;
247 if (aRect.GetDiff( nPaintStartX, nPaintStartY, nPaintEndX, nPaintEndY ))
248 PaintArea( nPaintStartX, nPaintStartY, nPaintEndX, nPaintEndY, SC_UPDATE_MARKS );
251 // Tip-Hilfe fuer Auto-Fill
253 if ( aViewData.GetRefType() == SC_REFTYPE_FILL && Help::IsQuickHelpEnabled() )
255 String aHelpStr;
256 ScRange aMarkRange;
257 aViewData.GetSimpleArea( aMarkRange );
258 SCCOL nEndX = aViewData.GetRefEndX();
259 SCROW nEndY = aViewData.GetRefEndY();
260 ScRange aDelRange;
261 if ( aViewData.GetFillMode() == SC_FILL_MATRIX && !(nScFillModeMouseModifier & KEY_MOD1) )
263 aHelpStr = ScGlobal::GetRscString( STR_TIP_RESIZEMATRIX );
264 SCCOL nCols = nEndX + 1 - aViewData.GetRefStartX(); // Reihenfolge ist richtig
265 SCROW nRows = nEndY + 1 - aViewData.GetRefStartY();
266 aHelpStr.SearchAndReplace( rtl::OUString("%1"),
267 String::CreateFromInt32(nRows) );
268 aHelpStr.SearchAndReplace( rtl::OUString("%2"),
269 String::CreateFromInt32(nCols) );
271 else if ( aViewData.GetDelMark( aDelRange ) )
272 aHelpStr = ScGlobal::GetRscString( STR_QUICKHELP_DELETE );
273 else if ( nEndX != aMarkRange.aEnd.Col() || nEndY != aMarkRange.aEnd.Row() )
274 aHelpStr = pDoc->GetAutoFillPreview( aMarkRange, nEndX, nEndY );
276 // je nach Richtung die obere oder untere Ecke:
277 SCCOL nAddX = ( nEndX >= aMarkRange.aEnd.Col() ) ? 1 : 0;
278 SCROW nAddY = ( nEndY >= aMarkRange.aEnd.Row() ) ? 1 : 0;
279 Point aPos = aViewData.GetScrPos( nEndX+nAddX, nEndY+nAddY, aViewData.GetActivePart() );
280 aPos.X() += 8;
281 aPos.Y() += 4;
282 Window* pWin = GetActiveWin();
283 if ( pWin )
284 aPos = pWin->OutputToScreenPixel( aPos );
285 Rectangle aRect( aPos, aPos );
286 sal_uInt16 nAlign = QUICKHELP_LEFT|QUICKHELP_TOP;
287 Help::ShowQuickHelp(pWin, aRect, aHelpStr, nAlign);
291 void ScTabView::InitRefMode( SCCOL nCurX, SCROW nCurY, SCTAB nCurZ, ScRefType eType, bool bPaint )
293 ScDocument* pDoc = aViewData.GetDocument();
294 ScMarkData& rMark = aViewData.GetMarkData();
295 if (!aViewData.IsRefMode())
297 aViewData.SetRefMode( sal_True, eType );
298 aViewData.SetRefStart( nCurX, nCurY, nCurZ );
299 aViewData.SetRefEnd( nCurX, nCurY, nCurZ );
301 if (nCurZ == aViewData.GetTabNo() && bPaint)
303 SCCOL nStartX = nCurX;
304 SCROW nStartY = nCurY;
305 SCCOL nEndX = nCurX;
306 SCROW nEndY = nCurY;
307 pDoc->ExtendMerge( nStartX, nStartY, nEndX, nEndY, aViewData.GetTabNo() );
309 //! nur Markierung ueber Inhalte zeichnen!
310 PaintArea( nStartX,nStartY,nEndX,nEndY, SC_UPDATE_MARKS );
312 // SetReference ohne Merge-Anpassung
313 ScRange aRef( nCurX,nCurY,nCurZ, nCurX,nCurY,nCurZ );
314 SC_MOD()->SetReference( aRef, pDoc, &rMark );
319 void ScTabView::SetScrollBar( ScrollBar& rScroll, long nRangeMax, long nVisible, long nPos, bool bLayoutRTL )
321 if ( nVisible == 0 )
322 nVisible = 1; // #i59893# don't use visible size 0
324 rScroll.SetRange( Range( 0, nRangeMax ) );
325 rScroll.SetVisibleSize( nVisible );
326 rScroll.SetThumbPos( nPos );
328 rScroll.EnableRTL( bLayoutRTL );
331 long ScTabView::GetScrollBarPos( ScrollBar& rScroll )
333 return rScroll.GetThumbPos();
336 // UpdateScrollBars - sichtbaren Bereich und Scrollweite der Scrollbars einstellen
338 static long lcl_UpdateBar( ScrollBar& rScroll, SCCOLROW nSize ) // Size = (komplette) Zellen
340 long nOldPos;
341 long nNewPos;
343 nOldPos = rScroll.GetThumbPos();
344 rScroll.SetPageSize( static_cast<long>(nSize) );
345 nNewPos = rScroll.GetThumbPos();
346 #ifndef UNX
347 rScroll.SetPageSize( 1 ); // immer moeglich !
348 #endif
350 return nNewPos - nOldPos;
353 static long lcl_GetScrollRange( SCCOLROW nDocEnd, SCCOLROW nPos, SCCOLROW nVis, SCCOLROW nMax, SCCOLROW nStart )
355 // get the end (positive) of a scroll bar range that always starts at 0
357 ++nVis;
358 ++nMax; // for partially visible cells
359 SCCOLROW nEnd = Max(nDocEnd, (SCCOLROW)(nPos+nVis)) + nVis;
360 if (nEnd > nMax)
361 nEnd = nMax;
363 return ( nEnd - nStart ); // for range starting at 0
366 void ScTabView::UpdateScrollBars()
368 long nDiff;
369 sal_Bool bTop = ( aViewData.GetVSplitMode() != SC_SPLIT_NONE );
370 sal_Bool bRight = ( aViewData.GetHSplitMode() != SC_SPLIT_NONE );
371 ScDocument* pDoc = aViewData.GetDocument();
372 SCTAB nTab = aViewData.GetTabNo();
373 bool bLayoutRTL = pDoc->IsLayoutRTL( nTab );
374 SCCOL nUsedX;
375 SCROW nUsedY;
376 pDoc->GetTableArea( nTab, nUsedX, nUsedY ); //! cachen !!!!!!!!!!!!!!!
378 SCCOL nVisXL = 0;
379 SCCOL nVisXR = 0;
380 SCROW nVisYB = 0;
381 SCROW nVisYT = 0;
383 SCCOL nStartX = 0;
384 SCROW nStartY = 0;
385 if (aViewData.GetHSplitMode()==SC_SPLIT_FIX)
386 nStartX = aViewData.GetFixPosX();
387 if (aViewData.GetVSplitMode()==SC_SPLIT_FIX)
388 nStartY = aViewData.GetFixPosY();
390 nVisXL = aViewData.VisibleCellsX( SC_SPLIT_LEFT );
391 long nMaxXL = lcl_GetScrollRange( nUsedX, aViewData.GetPosX(SC_SPLIT_LEFT), nVisXL, MAXCOL, 0 );
392 SetScrollBar( aHScrollLeft, nMaxXL, nVisXL, aViewData.GetPosX( SC_SPLIT_LEFT ), bLayoutRTL );
394 nVisYB = aViewData.VisibleCellsY( SC_SPLIT_BOTTOM );
395 long nMaxYB = lcl_GetScrollRange( nUsedY, aViewData.GetPosY(SC_SPLIT_BOTTOM), nVisYB, MAXROW, nStartY );
396 SetScrollBar( aVScrollBottom, nMaxYB, nVisYB, aViewData.GetPosY( SC_SPLIT_BOTTOM ) - nStartY, bLayoutRTL );
398 if (bRight)
400 nVisXR = aViewData.VisibleCellsX( SC_SPLIT_RIGHT );
401 long nMaxXR = lcl_GetScrollRange( nUsedX, aViewData.GetPosX(SC_SPLIT_RIGHT), nVisXR, MAXCOL, nStartX );
402 SetScrollBar( aHScrollRight, nMaxXR, nVisXR, aViewData.GetPosX( SC_SPLIT_RIGHT ) - nStartX, bLayoutRTL );
405 if (bTop)
407 nVisYT = aViewData.VisibleCellsY( SC_SPLIT_TOP );
408 long nMaxYT = lcl_GetScrollRange( nUsedY, aViewData.GetPosY(SC_SPLIT_TOP), nVisYT, MAXROW, 0 );
409 SetScrollBar( aVScrollTop, nMaxYT, nVisYT, aViewData.GetPosY( SC_SPLIT_TOP ), bLayoutRTL );
412 // Bereich testen
414 nDiff = lcl_UpdateBar( aHScrollLeft, nVisXL );
415 if (nDiff) ScrollX( nDiff, SC_SPLIT_LEFT );
416 if (bRight)
418 nDiff = lcl_UpdateBar( aHScrollRight, nVisXR );
419 if (nDiff) ScrollX( nDiff, SC_SPLIT_RIGHT );
422 nDiff = lcl_UpdateBar( aVScrollBottom, nVisYB );
423 if (nDiff) ScrollY( nDiff, SC_SPLIT_BOTTOM );
424 if (bTop)
426 nDiff = lcl_UpdateBar( aVScrollTop, nVisYT );
427 if (nDiff) ScrollY( nDiff, SC_SPLIT_TOP );
430 // set visible area for online spelling
432 if ( aViewData.IsActive() )
434 ScSplitPos eActive = aViewData.GetActivePart();
435 ScHSplitPos eHWhich = WhichH( eActive );
436 ScVSplitPos eVWhich = WhichV( eActive );
437 SCCOL nPosX = aViewData.GetPosX(eHWhich);
438 SCROW nPosY = aViewData.GetPosY(eVWhich);
439 SCCOL nEndX = nPosX + ( ( eHWhich == SC_SPLIT_LEFT ) ? nVisXL : nVisXR );
440 SCROW nEndY = nPosY + ( ( eVWhich == SC_SPLIT_TOP ) ? nVisYT : nVisYB );
441 if ( nEndX > MAXCOL ) nEndX = MAXCOL;
442 if ( nEndY > MAXROW ) nEndY = MAXROW;
443 ScRange aVisible( nPosX, nPosY, nTab, nEndX, nEndY, nTab );
444 if ( pDoc->SetVisibleSpellRange( aVisible ) )
445 SC_MOD()->AnythingChanged(); // if visible area has changed
449 #ifndef HDR_SLIDERSIZE
450 #define HDR_SLIDERSIZE 2
451 #endif
453 void ScTabView::InvertHorizontal( ScVSplitPos eWhich, long nDragPos )
455 for (sal_uInt16 i=0; i<4; i++)
456 if (WhichV((ScSplitPos)i)==eWhich)
458 ScGridWindow* pWin = pGridWin[i];
459 if (pWin)
461 Rectangle aRect( 0,nDragPos, pWin->GetOutputSizePixel().Width()-1,nDragPos+HDR_SLIDERSIZE-1 );
462 pWin->Update();
463 pWin->DoInvertRect( aRect ); // Pixel
468 void ScTabView::InvertVertical( ScHSplitPos eWhich, long nDragPos )
470 for (sal_uInt16 i=0; i<4; i++)
471 if (WhichH((ScSplitPos)i)==eWhich)
473 ScGridWindow* pWin = pGridWin[i];
474 if (pWin)
476 Rectangle aRect( nDragPos,0, nDragPos+HDR_SLIDERSIZE-1,pWin->GetOutputSizePixel().Height()-1 );
477 pWin->Update();
478 pWin->DoInvertRect( aRect ); // Pixel
483 //==================================================================
485 void ScTabView::InterpretVisible()
487 // make sure all visible cells are interpreted,
488 // so the next paint will not execute a macro function
490 ScDocument* pDoc = aViewData.GetDocument();
491 if ( !pDoc->GetAutoCalc() )
492 return;
494 SCTAB nTab = aViewData.GetTabNo();
495 for (sal_uInt16 i=0; i<4; i++)
497 // rely on gridwin pointers to find used panes
498 // no IsVisible test in case the whole view is not yet shown
500 if (pGridWin[i])
502 ScHSplitPos eHWhich = WhichH( ScSplitPos(i) );
503 ScVSplitPos eVWhich = WhichV( ScSplitPos(i) );
505 SCCOL nX1 = aViewData.GetPosX( eHWhich );
506 SCROW nY1 = aViewData.GetPosY( eVWhich );
507 SCCOL nX2 = nX1 + aViewData.VisibleCellsX( eHWhich );
508 SCROW nY2 = nY1 + aViewData.VisibleCellsY( eVWhich );
510 if (nX2 > MAXCOL) nX2 = MAXCOL;
511 if (nY2 > MAXROW) nY2 = MAXROW;
513 ScCellIterator aIter( pDoc, nX1, nY1, nTab, nX2, nY2, nTab );
514 ScBaseCell* pCell = aIter.GetFirst();
515 while ( pCell )
517 if ( pCell->GetCellType() == CELLTYPE_FORMULA && ((ScFormulaCell*)pCell)->GetDirty() )
518 ((ScFormulaCell*)pCell)->Interpret();
520 pCell = aIter.GetNext();
525 // #i65047# repaint during the above loop may have set the bNeedsRepaint flag
526 CheckNeedsRepaint();
533 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */