1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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"
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()
42 Help::HideTip( nTipVisible
);
47 void ScTabView::ShowRefTip()
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
];
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 ??
95 nTipVisible
= Help::ShowTip( pWin
, aRect
, aHelp
, nFlags
);
105 void ScTabView::StopRefMode()
107 if (aViewData
.IsRefMode())
109 aViewData
.SetRefMode( false, SC_REFTYPE_NONE
);
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
);
129 pSelEngine
->SetAddMode( false ); //! sollte das nicht bei Reset passieren?
131 ScSplitPos eOld
= pSelEngine
->GetWhich();
132 ScSplitPos eNew
= aViewData
.GetActivePart();
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
);
161 UpdateShrinkOverlay();
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
)
222 aViewData
.GetRefStartX(), aViewData
.GetRefStartY(), aViewData
.GetRefStartZ(),
223 aViewData
.GetRefEndX(), aViewData
.GetRefEndY(), aViewData
.GetRefEndZ() );
224 SC_MOD()->SetReference( aRef
, pDoc
, &rMark
);
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();
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();
253 aViewData
.GetSimpleArea( aMarkRange
);
254 SCCOL nEndX
= aViewData
.GetRefEndX();
255 SCROW nEndY
= aViewData
.GetRefEndY();
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() );
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
;
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
)
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
336 nOldPos
= rScroll
.GetThumbPos();
337 rScroll
.SetPageSize( static_cast<long>(nSize
) );
338 nNewPos
= rScroll
.GetThumbPos();
340 rScroll
.SetPageSize( 1 ); // immer moeglich !
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
351 ++nMax
; // for partially visible cells
352 SCCOLROW nEnd
= std::max(nDocEnd
, (SCCOLROW
)(nPos
+nVis
)) + nVis
;
356 return ( nEnd
- nStart
); // for range starting at 0
359 void ScTabView::UpdateScrollBars()
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
);
369 pDoc
->GetTableArea( nTab
, nUsedX
, nUsedY
); //! cachen !!!!!!!!!!!!!!!
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
);
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
);
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
);
407 nDiff
= lcl_UpdateBar( *aHScrollLeft
.get(), nVisXL
);
408 if (nDiff
) ScrollX( nDiff
, SC_SPLIT_LEFT
);
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
);
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
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
];
444 Rectangle
aRect( 0,nDragPos
, pWin
->GetOutputSizePixel().Width()-1,nDragPos
+HDR_SLIDERSIZE
-1 );
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
];
459 Rectangle
aRect( nDragPos
,0, nDragPos
+HDR_SLIDERSIZE
-1,pWin
->GetOutputSizePixel().Height()-1 );
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() )
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
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
499 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */