fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / sc / source / ui / view / tabview4.cxx
blob3c47c9bd7f8994cee76e4344cc25934f372b5f54
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 "formulacell.hxx"
30 #include "dociter.hxx"
32 extern sal_uInt16 nScFillModeMouseModifier; // global.cxx
34 // STATIC DATA -----------------------------------------------------------
36 // --- Referenz-Eingabe / Fill-Cursor
38 void ScTabView::HideTip()
40 if ( nTipVisible )
42 Help::HideTip( nTipVisible );
43 nTipVisible = 0;
47 void ScTabView::ShowRefTip()
49 bool bDone = false;
50 if ( aViewData.GetRefType() == SC_REFTYPE_REF && Help::IsQuickHelpEnabled() )
52 SCCOL nStartX = aViewData.GetRefStartX();
53 SCROW nStartY = aViewData.GetRefStartY();
54 SCCOL nEndX = aViewData.GetRefEndX();
55 SCROW nEndY = aViewData.GetRefEndY();
56 if ( nEndX != nStartX || nEndY != nStartY ) // nicht fuer einzelne Zelle
58 bool bLeft = ( nEndX < nStartX );
59 bool bTop = ( nEndY < nStartY );
60 PutInOrder( nStartX, nEndX );
61 PutInOrder( nStartY, nEndY );
62 SCCOL nCols = nEndX+1-nStartX;
63 SCROW nRows = nEndY+1-nStartY;
65 OUString aHelp = ScGlobal::GetRscString( STR_QUICKHELP_REF );
66 aHelp = aHelp.replaceFirst("%1", OUString::number(nRows) );
67 aHelp = aHelp.replaceFirst("%2", OUString::number(nCols) );
69 ScSplitPos eWhich = aViewData.GetActivePart();
70 vcl::Window* pWin = pGridWin[eWhich];
71 if ( pWin )
73 Point aStart = aViewData.GetScrPos( nStartX, nStartY, eWhich );
74 Point aEnd = aViewData.GetScrPos( nEndX+1, nEndY+1, eWhich );
76 Point aPos( bLeft ? aStart.X() : ( aEnd.X() + 3 ),
77 bTop ? aStart.Y() : ( aEnd.Y() + 3 ) );
78 QuickHelpFlags nFlags = ( bLeft ? QuickHelpFlags::Right : QuickHelpFlags::Left ) |
79 ( bTop ? QuickHelpFlags::Bottom : QuickHelpFlags::Top );
81 // nicht ueber die editierte Formel
82 if ( !bTop && aViewData.HasEditView( eWhich ) &&
83 nEndY+1 == aViewData.GetEditViewRow() )
85 // dann an der oberen Kante der editierten Zelle ausrichten
86 aPos.Y() -= 2; // die 3 von oben
87 nFlags = ( nFlags & ~QuickHelpFlags::Top ) | QuickHelpFlags::Bottom;
90 Rectangle aRect( pWin->OutputToScreenPixel( aPos ), Size(1,1) );
92 //! Test, ob geaendert ??
94 HideTip();
95 nTipVisible = Help::ShowTip( pWin, aRect, aHelp, nFlags );
96 bDone = true;
101 if (!bDone)
102 HideTip();
105 void ScTabView::StopRefMode()
107 if (aViewData.IsRefMode())
109 aViewData.SetRefMode( false, SC_REFTYPE_NONE );
111 HideTip();
112 UpdateShrinkOverlay();
114 if ( aViewData.GetTabNo() >= aViewData.GetRefStartZ() &&
115 aViewData.GetTabNo() <= aViewData.GetRefEndZ() )
117 ScDocument* pDoc = aViewData.GetDocument();
118 SCCOL nStartX = aViewData.GetRefStartX();
119 SCROW nStartY = aViewData.GetRefStartY();
120 SCCOL nEndX = aViewData.GetRefEndX();
121 SCROW nEndY = aViewData.GetRefEndY();
122 if ( nStartX == nEndX && nStartY == nEndY )
123 pDoc->ExtendMerge( nStartX, nStartY, nEndX, nEndY, aViewData.GetTabNo() );
125 PaintArea( nStartX,nStartY,nEndX,nEndY, SC_UPDATE_MARKS );
128 pSelEngine->Reset();
129 pSelEngine->SetAddMode( false ); //! sollte das nicht bei Reset passieren?
131 ScSplitPos eOld = pSelEngine->GetWhich();
132 ScSplitPos eNew = aViewData.GetActivePart();
133 if ( eNew != eOld )
135 pSelEngine->SetWindow( pGridWin[ eNew ] );
136 pSelEngine->SetWhich( eNew );
137 pSelEngine->SetVisibleArea( Rectangle(Point(),
138 pGridWin[eNew]->GetOutputSizePixel()) );
139 pGridWin[eOld]->MoveMouseStatus(*pGridWin[eNew]);
143 // AlignToCursor(SC_FOLLOW_NONE): Only switch active part.
144 // This must also be done if no RefMode was active (for RangeFinder dragging),
145 // but if RefMode was set, AlignToCursor must be after SelectionEngine reset,
146 // so the SelectionEngine SetWindow call from AlignToCursor doesn't capture
147 // the mouse again when called from Tracking/MouseButtonUp (#94562#).
148 AlignToCursor( aViewData.GetCurX(), aViewData.GetCurY(), SC_FOLLOW_NONE );
151 void ScTabView::DoneRefMode( bool bContinue )
153 ScDocument* pDoc = aViewData.GetDocument();
154 if ( aViewData.GetRefType() == SC_REFTYPE_REF && bContinue )
155 SC_MOD()->AddRefEntry();
157 bool bWasRef = aViewData.IsRefMode();
158 aViewData.SetRefMode( false, SC_REFTYPE_NONE );
160 HideTip();
161 UpdateShrinkOverlay();
163 // Paint:
164 if ( bWasRef && aViewData.GetTabNo() >= aViewData.GetRefStartZ() &&
165 aViewData.GetTabNo() <= aViewData.GetRefEndZ() )
167 SCCOL nStartX = aViewData.GetRefStartX();
168 SCROW nStartY = aViewData.GetRefStartY();
169 SCCOL nEndX = aViewData.GetRefEndX();
170 SCROW nEndY = aViewData.GetRefEndY();
171 if ( nStartX == nEndX && nStartY == nEndY )
172 pDoc->ExtendMerge( nStartX, nStartY, nEndX, nEndY, aViewData.GetTabNo() );
174 PaintArea( nStartX,nStartY,nEndX,nEndY, SC_UPDATE_MARKS );
178 void ScTabView::UpdateRef( SCCOL nCurX, SCROW nCurY, SCTAB nCurZ )
180 ScDocument* pDoc = aViewData.GetDocument();
182 if (!aViewData.IsRefMode())
184 // Das kommt vor, wenn bei einem Referenz-Dialog als erstes mit Control in die
185 // die Tabelle geklickt wird. Dann die neue Referenz an den alten Inhalt anhaengen:
187 ScModule* pScMod = SC_MOD();
188 if (pScMod->IsFormulaMode())
189 pScMod->AddRefEntry();
191 InitRefMode( nCurX, nCurY, nCurZ, SC_REFTYPE_REF );
194 if ( nCurX != aViewData.GetRefEndX() || nCurY != aViewData.GetRefEndY() ||
195 nCurZ != aViewData.GetRefEndZ() )
197 ScMarkData& rMark = aViewData.GetMarkData();
198 SCTAB nTab = aViewData.GetTabNo();
200 SCCOL nStartX = aViewData.GetRefStartX();
201 SCROW nStartY = aViewData.GetRefStartY();
202 SCCOL nEndX = aViewData.GetRefEndX();
203 SCROW nEndY = aViewData.GetRefEndY();
204 if ( nStartX == nEndX && nStartY == nEndY )
205 pDoc->ExtendMerge( nStartX, nStartY, nEndX, nEndY, nTab );
206 ScUpdateRect aRect( nStartX, nStartY, nEndX, nEndY );
208 aViewData.SetRefEnd( nCurX, nCurY, nCurZ );
210 nStartX = aViewData.GetRefStartX();
211 nStartY = aViewData.GetRefStartY();
212 nEndX = aViewData.GetRefEndX();
213 nEndY = aViewData.GetRefEndY();
214 if ( nStartX == nEndX && nStartY == nEndY )
215 pDoc->ExtendMerge( nStartX, nStartY, nEndX, nEndY, nTab );
216 aRect.SetNew( nStartX, nStartY, nEndX, nEndY );
218 ScRefType eType = aViewData.GetRefType();
219 if ( eType == SC_REFTYPE_REF )
221 ScRange aRef(
222 aViewData.GetRefStartX(), aViewData.GetRefStartY(), aViewData.GetRefStartZ(),
223 aViewData.GetRefEndX(), aViewData.GetRefEndY(), aViewData.GetRefEndZ() );
224 SC_MOD()->SetReference( aRef, pDoc, &rMark );
225 ShowRefTip();
227 else if ( eType == SC_REFTYPE_EMBED_LT || eType == SC_REFTYPE_EMBED_RB )
229 PutInOrder(nStartX,nEndX);
230 PutInOrder(nStartY,nEndY);
231 pDoc->SetEmbedded( ScRange(nStartX,nStartY,nTab, nEndX,nEndY,nTab) );
232 ScDocShell* pDocSh = aViewData.GetDocShell();
233 pDocSh->UpdateOle( &aViewData, true );
234 pDocSh->SetDocumentModified();
237 SCCOL nPaintStartX;
238 SCROW nPaintStartY;
239 SCCOL nPaintEndX;
240 SCROW nPaintEndY;
241 if (aRect.GetDiff( nPaintStartX, nPaintStartY, nPaintEndX, nPaintEndY ))
242 PaintArea( nPaintStartX, nPaintStartY, nPaintEndX, nPaintEndY, SC_UPDATE_MARKS );
245 // Tip-Hilfe fuer Auto-Fill
246 if ( aViewData.GetRefType() == SC_REFTYPE_FILL && Help::IsQuickHelpEnabled() )
248 vcl::Window* pWin = GetActiveWin();
249 if ( pWin )
251 OUString aHelpStr;
252 ScRange aMarkRange;
253 aViewData.GetSimpleArea( aMarkRange );
254 SCCOL nEndX = aViewData.GetRefEndX();
255 SCROW nEndY = aViewData.GetRefEndY();
256 ScRange aDelRange;
257 if ( aViewData.GetFillMode() == SC_FILL_MATRIX && !(nScFillModeMouseModifier & KEY_MOD1) )
259 aHelpStr = ScGlobal::GetRscString( STR_TIP_RESIZEMATRIX );
260 SCCOL nCols = nEndX + 1 - aViewData.GetRefStartX(); // Reihenfolge ist richtig
261 SCROW nRows = nEndY + 1 - aViewData.GetRefStartY();
262 aHelpStr = aHelpStr.replaceFirst("%1", OUString::number(nRows) );
263 aHelpStr = aHelpStr.replaceFirst("%2", OUString::number(nCols) );
265 else if ( aViewData.GetDelMark( aDelRange ) )
266 aHelpStr = ScGlobal::GetRscString( STR_QUICKHELP_DELETE );
267 else if ( nEndX != aMarkRange.aEnd.Col() || nEndY != aMarkRange.aEnd.Row() )
268 aHelpStr = pDoc->GetAutoFillPreview( aMarkRange, nEndX, nEndY );
270 // je nach Richtung die obere oder untere Ecke:
271 SCCOL nAddX = ( nEndX >= aMarkRange.aEnd.Col() ) ? 1 : 0;
272 SCROW nAddY = ( nEndY >= aMarkRange.aEnd.Row() ) ? 1 : 0;
273 Point aPos = aViewData.GetScrPos( nEndX+nAddX, nEndY+nAddY, aViewData.GetActivePart() );
274 aPos.X() += 8;
275 aPos.Y() += 4;
276 aPos = pWin->OutputToScreenPixel( aPos );
277 Rectangle aRect( aPos, aPos );
278 QuickHelpFlags nAlign = QuickHelpFlags::Left|QuickHelpFlags::Top;
279 Help::ShowQuickHelp(pWin, aRect, aHelpStr, nAlign);
284 void ScTabView::InitRefMode( SCCOL nCurX, SCROW nCurY, SCTAB nCurZ, ScRefType eType, bool bPaint )
286 ScDocument* pDoc = aViewData.GetDocument();
287 ScMarkData& rMark = aViewData.GetMarkData();
288 if (!aViewData.IsRefMode())
290 aViewData.SetRefMode( true, eType );
291 aViewData.SetRefStart( nCurX, nCurY, nCurZ );
292 aViewData.SetRefEnd( nCurX, nCurY, nCurZ );
294 if (nCurZ == aViewData.GetTabNo() && bPaint)
296 SCCOL nStartX = nCurX;
297 SCROW nStartY = nCurY;
298 SCCOL nEndX = nCurX;
299 SCROW nEndY = nCurY;
300 pDoc->ExtendMerge( nStartX, nStartY, nEndX, nEndY, aViewData.GetTabNo() );
302 //! nur Markierung ueber Inhalte zeichnen!
303 PaintArea( nStartX,nStartY,nEndX,nEndY, SC_UPDATE_MARKS );
305 // SetReference ohne Merge-Anpassung
306 ScRange aRef( nCurX,nCurY,nCurZ, nCurX,nCurY,nCurZ );
307 SC_MOD()->SetReference( aRef, pDoc, &rMark );
312 void ScTabView::SetScrollBar( ScrollBar& rScroll, long nRangeMax, long nVisible, long nPos, bool bLayoutRTL )
314 if ( nVisible == 0 )
315 nVisible = 1; // #i59893# don't use visible size 0
317 rScroll.SetRange( Range( 0, nRangeMax ) );
318 rScroll.SetVisibleSize( nVisible );
319 rScroll.SetThumbPos( nPos );
321 rScroll.EnableRTL( bLayoutRTL );
324 long ScTabView::GetScrollBarPos( ScrollBar& rScroll )
326 return rScroll.GetThumbPos();
329 // UpdateScrollBars - sichtbaren Bereich und Scrollweite der Scrollbars einstellen
331 static long lcl_UpdateBar( ScrollBar& rScroll, SCCOLROW nSize ) // Size = (komplette) Zellen
333 long nOldPos;
334 long nNewPos;
336 nOldPos = rScroll.GetThumbPos();
337 rScroll.SetPageSize( static_cast<long>(nSize) );
338 nNewPos = rScroll.GetThumbPos();
339 #ifndef UNX
340 rScroll.SetPageSize( 1 ); // immer moeglich !
341 #endif
343 return nNewPos - nOldPos;
346 static long lcl_GetScrollRange( SCCOLROW nDocEnd, SCCOLROW nPos, SCCOLROW nVis, SCCOLROW nMax, SCCOLROW nStart )
348 // get the end (positive) of a scroll bar range that always starts at 0
350 ++nVis;
351 ++nMax; // for partially visible cells
352 SCCOLROW nEnd = std::max(nDocEnd, (SCCOLROW)(nPos+nVis)) + nVis;
353 if (nEnd > nMax)
354 nEnd = nMax;
356 return ( nEnd - nStart ); // for range starting at 0
359 void ScTabView::UpdateScrollBars()
361 long nDiff;
362 bool bTop = ( aViewData.GetVSplitMode() != SC_SPLIT_NONE );
363 bool bRight = ( aViewData.GetHSplitMode() != SC_SPLIT_NONE );
364 ScDocument* pDoc = aViewData.GetDocument();
365 SCTAB nTab = aViewData.GetTabNo();
366 bool bLayoutRTL = pDoc->IsLayoutRTL( nTab );
367 SCCOL nUsedX;
368 SCROW nUsedY;
369 pDoc->GetTableArea( nTab, nUsedX, nUsedY ); //! cachen !!!!!!!!!!!!!!!
371 SCCOL nVisXL = 0;
372 SCCOL nVisXR = 0;
373 SCROW nVisYB = 0;
374 SCROW nVisYT = 0;
376 SCCOL nStartX = 0;
377 SCROW nStartY = 0;
378 if (aViewData.GetHSplitMode()==SC_SPLIT_FIX)
379 nStartX = aViewData.GetFixPosX();
380 if (aViewData.GetVSplitMode()==SC_SPLIT_FIX)
381 nStartY = aViewData.GetFixPosY();
383 nVisXL = aViewData.VisibleCellsX( SC_SPLIT_LEFT );
384 long nMaxXL = lcl_GetScrollRange( nUsedX, aViewData.GetPosX(SC_SPLIT_LEFT), nVisXL, MAXCOL, 0 );
385 SetScrollBar( *aHScrollLeft.get(), nMaxXL, nVisXL, aViewData.GetPosX( SC_SPLIT_LEFT ), bLayoutRTL );
387 nVisYB = aViewData.VisibleCellsY( SC_SPLIT_BOTTOM );
388 long nMaxYB = lcl_GetScrollRange( nUsedY, aViewData.GetPosY(SC_SPLIT_BOTTOM), nVisYB, MAXROW, nStartY );
389 SetScrollBar( *aVScrollBottom.get(), nMaxYB, nVisYB, aViewData.GetPosY( SC_SPLIT_BOTTOM ) - nStartY, bLayoutRTL );
391 if (bRight)
393 nVisXR = aViewData.VisibleCellsX( SC_SPLIT_RIGHT );
394 long nMaxXR = lcl_GetScrollRange( nUsedX, aViewData.GetPosX(SC_SPLIT_RIGHT), nVisXR, MAXCOL, nStartX );
395 SetScrollBar( *aHScrollRight.get(), nMaxXR, nVisXR, aViewData.GetPosX( SC_SPLIT_RIGHT ) - nStartX, bLayoutRTL );
398 if (bTop)
400 nVisYT = aViewData.VisibleCellsY( SC_SPLIT_TOP );
401 long nMaxYT = lcl_GetScrollRange( nUsedY, aViewData.GetPosY(SC_SPLIT_TOP), nVisYT, MAXROW, 0 );
402 SetScrollBar( *aVScrollTop.get(), nMaxYT, nVisYT, aViewData.GetPosY( SC_SPLIT_TOP ), bLayoutRTL );
405 // Bereich testen
407 nDiff = lcl_UpdateBar( *aHScrollLeft.get(), nVisXL );
408 if (nDiff) ScrollX( nDiff, SC_SPLIT_LEFT );
409 if (bRight)
411 nDiff = lcl_UpdateBar( *aHScrollRight.get(), nVisXR );
412 if (nDiff) ScrollX( nDiff, SC_SPLIT_RIGHT );
415 nDiff = lcl_UpdateBar( *aVScrollBottom.get(), nVisYB );
416 if (nDiff) ScrollY( nDiff, SC_SPLIT_BOTTOM );
417 if (bTop)
419 nDiff = lcl_UpdateBar( *aVScrollTop.get(), nVisYT );
420 if (nDiff) ScrollY( nDiff, SC_SPLIT_TOP );
423 // set visible area for online spelling
425 if ( aViewData.IsActive() )
427 if (UpdateVisibleRange())
428 SC_MOD()->AnythingChanged(); // if visible area has changed
432 #ifndef HDR_SLIDERSIZE
433 #define HDR_SLIDERSIZE 2
434 #endif
436 void ScTabView::InvertHorizontal( ScVSplitPos eWhich, long nDragPos )
438 for (sal_uInt16 i=0; i<4; i++)
439 if (WhichV((ScSplitPos)i)==eWhich)
441 ScGridWindow* pWin = pGridWin[i];
442 if (pWin)
444 Rectangle aRect( 0,nDragPos, pWin->GetOutputSizePixel().Width()-1,nDragPos+HDR_SLIDERSIZE-1 );
445 pWin->Update();
446 pWin->DoInvertRect( aRect ); // Pixel
451 void ScTabView::InvertVertical( ScHSplitPos eWhich, long nDragPos )
453 for (sal_uInt16 i=0; i<4; i++)
454 if (WhichH((ScSplitPos)i)==eWhich)
456 ScGridWindow* pWin = pGridWin[i];
457 if (pWin)
459 Rectangle aRect( nDragPos,0, nDragPos+HDR_SLIDERSIZE-1,pWin->GetOutputSizePixel().Height()-1 );
460 pWin->Update();
461 pWin->DoInvertRect( aRect ); // Pixel
466 void ScTabView::InterpretVisible()
468 // make sure all visible cells are interpreted,
469 // so the next paint will not execute a macro function
471 ScDocument* pDoc = aViewData.GetDocument();
472 if ( !pDoc->GetAutoCalc() )
473 return;
475 SCTAB nTab = aViewData.GetTabNo();
476 for (sal_uInt16 i=0; i<4; i++)
478 // rely on gridwin pointers to find used panes
479 // no IsVisible test in case the whole view is not yet shown
481 if (pGridWin[i])
483 ScHSplitPos eHWhich = WhichH( ScSplitPos(i) );
484 ScVSplitPos eVWhich = WhichV( ScSplitPos(i) );
486 SCCOL nX1 = SanitizeCol( aViewData.GetPosX( eHWhich ));
487 SCROW nY1 = SanitizeRow( aViewData.GetPosY( eVWhich ));
488 SCCOL nX2 = SanitizeCol( nX1 + aViewData.VisibleCellsX( eHWhich ));
489 SCROW nY2 = SanitizeRow( nY1 + aViewData.VisibleCellsY( eVWhich ));
491 pDoc->InterpretDirtyCells(ScRange(nX1, nY1, nTab, nX2, nY2, nTab));
495 // #i65047# repaint during the above loop may have set the bNeedsRepaint flag
496 CheckNeedsRepaint();
499 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */