LibreOffice Module sc (master) 1
select.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20#include <tools/urlobj.hxx>
21#include <sfx2/docfile.hxx>
22#include <osl/diagnose.h>
23
24#include <select.hxx>
25#include <tabvwsh.hxx>
26#include <scmod.hxx>
27#include <document.hxx>
28#include <transobj.hxx>
29#include <docsh.hxx>
30#include <tabprotection.hxx>
31#include <markdata.hxx>
32#include <gridwin.hxx>
33#include <sfx2/lokhelper.hxx>
34#include <comphelper/lok.hxx>
35
36#if defined(_WIN32)
37#define SC_SELENG_REFMODE_UPDATE_INTERVAL_MIN 65
38#endif
39
40using namespace com::sun::star;
41
43static bool bDidSwitch = false;
44
45// View (Gridwin / keyboard)
47 pViewData( pNewViewData ),
48 pEngine( nullptr ),
49 bAnchor( false ),
50 bStarted( false )
51{
52 OSL_ENSURE(pViewData, "ViewData==0 at FunctionSet");
53}
54
56{
57 if (pEngine)
58 return pEngine->GetWhich();
59 else
60 return pViewData->GetActivePart();
61}
62
63sal_uLong ScViewFunctionSet::CalcUpdateInterval( const Size& rWinSize, const Point& rEffPos,
64 bool bLeftScroll, bool bTopScroll, bool bRightScroll, bool bBottomScroll )
65{
67 vcl::Window* pWin = pEngine->GetWindow();
68 tools::Rectangle aScrRect = pWin->GetDesktopRectPixel();
69 Point aRootPos = pWin->OutputToAbsoluteScreenPixel(Point(0,0));
70 if (bRightScroll)
71 {
72 double nWinRight = rWinSize.getWidth() + aRootPos.getX();
73 double nMarginRight = aScrRect.GetWidth() - nWinRight;
74 double nHOffset = rEffPos.X() - rWinSize.Width();
75 double nHAccelRate = nHOffset / nMarginRight;
76
77 if (nHAccelRate > 1.0)
78 nHAccelRate = 1.0;
79
80 nUpdateInterval = static_cast<sal_uLong>(SELENG_AUTOREPEAT_INTERVAL_MAX*(1.0 - nHAccelRate));
81 }
82
83 if (bLeftScroll)
84 {
85 double nMarginLeft = aRootPos.getX();
86 double nHOffset = -rEffPos.X();
87 double nHAccelRate = nHOffset / nMarginLeft;
88
89 if (nHAccelRate > 1.0)
90 nHAccelRate = 1.0;
91
92 sal_uLong nTmp = static_cast<sal_uLong>(SELENG_AUTOREPEAT_INTERVAL_MAX*(1.0 - nHAccelRate));
93 if (nUpdateInterval > nTmp)
94 nUpdateInterval = nTmp;
95 }
96
97 if (bBottomScroll)
98 {
99 double nWinBottom = rWinSize.getHeight() + aRootPos.getY();
100 double nMarginBottom = aScrRect.GetHeight() - nWinBottom;
101 double nVOffset = rEffPos.Y() - rWinSize.Height();
102 double nVAccelRate = nVOffset / nMarginBottom;
103
104 if (nVAccelRate > 1.0)
105 nVAccelRate = 1.0;
106
107 sal_uLong nTmp = static_cast<sal_uLong>(SELENG_AUTOREPEAT_INTERVAL_MAX*(1.0 - nVAccelRate));
108 if (nUpdateInterval > nTmp)
109 nUpdateInterval = nTmp;
110 }
111
112 if (bTopScroll)
113 {
114 double nMarginTop = aRootPos.getY();
115 double nVOffset = -rEffPos.Y();
116 double nVAccelRate = nVOffset / nMarginTop;
117
118 if (nVAccelRate > 1.0)
119 nVAccelRate = 1.0;
120
121 sal_uLong nTmp = static_cast<sal_uLong>(SELENG_AUTOREPEAT_INTERVAL_MAX*(1.0 - nVAccelRate));
122 if (nUpdateInterval > nTmp)
123 nUpdateInterval = nTmp;
124 }
125
126#ifdef _WIN32
127 ScTabViewShell* pViewShell = pViewData->GetViewShell();
128 bool bRefMode = pViewShell && pViewShell->IsRefInputMode();
129 if (bRefMode && nUpdateInterval < SC_SELENG_REFMODE_UPDATE_INTERVAL_MIN)
130 // Lower the update interval during ref mode, because re-draw can be
131 // expensive on Windows. Making this interval too small would queue up
132 // the scroll/paint requests which would cause semi-infinite
133 // scrolls even after the mouse cursor is released. We don't have
134 // this problem on Linux.
135 nUpdateInterval = SC_SELENG_REFMODE_UPDATE_INTERVAL_MIN;
136#endif
137 return nUpdateInterval;
138}
139
141{
142 pEngine = pSelEngine;
143}
144
145// Drag & Drop
147{
148 SCTAB nTab = pViewData->GetTabNo();
149
150 SCCOL nPosX;
151 SCROW nPosY;
152 if (pEngine)
153 {
154 Point aMPos = pEngine->GetMousePosPixel();
155 pViewData->GetPosFromPixel( aMPos.X(), aMPos.Y(), GetWhich(), nPosX, nPosY );
156 }
157 else
158 {
159 nPosX = pViewData->GetCurX();
160 nPosY = pViewData->GetCurY();
161 }
162
163 ScModule* pScMod = SC_MOD();
164 bool bRefMode = pScMod->IsFormulaMode();
165 if (bRefMode)
166 return;
167
168 pViewData->GetView()->FakeButtonUp( GetWhich() ); // ButtonUp is swallowed
169
170 ScMarkData& rMark = pViewData->GetMarkData();
171 rMark.MarkToSimple();
172 if ( !rMark.IsMarked() || rMark.IsMultiMarked() )
173 return;
174
176 // bApi = TRUE -> no error messages
177 bool bCopied = pViewData->GetView()->CopyToClip( pClipDoc.get(), false, true );
178 if ( !bCopied )
179 return;
180
181 sal_Int8 nDragActions = pViewData->GetView()->SelectionEditable() ?
184
185 ScDocShell* pDocSh = pViewData->GetDocShell();
187 pDocSh->FillTransferableObjectDescriptor( aObjDesc );
188 aObjDesc.maDisplayName = pDocSh->GetMedium()->GetURLObject().GetURLNoPass();
189 // maSize is set in ScTransferObj ctor
190
191 rtl::Reference<ScTransferObj> pTransferObj = new ScTransferObj( std::move(pClipDoc), std::move(aObjDesc) );
192
193 // set position of dragged cell within range
194 ScRange aMarkRange = pTransferObj->GetRange();
195 SCCOL nStartX = aMarkRange.aStart.Col();
196 SCROW nStartY = aMarkRange.aStart.Row();
197 SCCOL nHandleX = (nPosX >= nStartX) ? nPosX - nStartX : 0;
198 SCROW nHandleY = (nPosY >= nStartY) ? nPosY - nStartY : 0;
199 pTransferObj->SetDragHandlePos( nHandleX, nHandleY );
200 pTransferObj->SetSourceCursorPos( pViewData->GetCurX(), pViewData->GetCurY() );
201 pTransferObj->SetVisibleTab( nTab );
202
203 pTransferObj->SetDragSource( pDocSh, rMark );
204
205 vcl::Window* pWindow = pViewData->GetActiveWin();
206 if ( pWindow->IsTracking() )
207 pWindow->EndTracking( TrackingEventFlags::Cancel ); // abort selecting
208
210 pWindow->LocalStartDrag();
211
212 SC_MOD()->SetDragObject( pTransferObj.get(), nullptr ); // for internal D&D
213 pTransferObj->StartDrag( pWindow, nDragActions );
214
215 return; // dragging started
216
217}
218
219// Selection
221{
222 if (bAnchor) return;
223
224 bool bRefMode = SC_MOD()->IsFormulaMode();
225 if (bRefMode)
227 else
229}
230
232{
233 bool bRefMode = SC_MOD()->IsFormulaMode();
234 ScTabView* pView = pViewData->GetView();
235 SCTAB nTab = pViewData->GetTabNo();
236
237 if (bRefMode)
238 {
239 pView->DoneRefMode();
240 aAnchorPos.Set( nPosX, nPosY, nTab );
243 bStarted = true;
244 }
245 else if (pViewData->IsAnyFillMode())
246 {
247 aAnchorPos.Set( nPosX, nPosY, nTab );
248 bStarted = true;
249 }
250 else
251 {
252 // don't go there and back again
253 if ( bStarted && pView->IsMarking( nPosX, nPosY, nTab ) )
254 {
255 // don't do anything
256 }
257 else
258 {
259 pView->DoneBlockMode( true );
260 aAnchorPos.Set( nPosX, nPosY, nTab );
261 ScMarkData& rMark = pViewData->GetMarkData();
262 if ( rMark.IsMarked() || rMark.IsMultiMarked() )
263 {
265 aAnchorPos.Tab(), true );
266 bStarted = true;
267 }
268 else
269 bStarted = false;
270 }
271 }
272 bAnchor = true;
273}
274
276{
277 bool bRefMode = SC_MOD()->IsFormulaMode();
278 if (bRefMode)
279 pViewData->GetView()->DoneRefMode( true );
280 else
281 pViewData->GetView()->DoneBlockMode( true );
282
283 bAnchor = false;
284}
285
287{
288 bAnchor = bSet;
289}
290
291void ScViewFunctionSet::SetCursorAtPoint( const Point& rPointPixel, bool /* bDontSelectAtCursor */ )
292{
293 if ( bDidSwitch )
294 {
295 if ( rPointPixel == aSwitchPos )
296 return; // don't scroll in wrong window
297 else
298 bDidSwitch = false;
299 }
300 aSwitchPos = rPointPixel; // only important, if bDidSwitch
301
302 // treat position 0 as -1, so scrolling is always possible
303 // (with full screen and hidden headers, the top left border may be at 0)
304 // (moved from ScViewData::GetPosFromPixel)
305
306 Point aEffPos = rPointPixel;
307 if ( aEffPos.X() == 0 )
308 aEffPos.setX( -1 );
309 if ( aEffPos.Y() == 0 )
310 aEffPos.setY( -1 );
311
312 // Scrolling
313 Size aWinSize = pEngine->GetWindow()->GetOutputSizePixel();
314 bool bLeftScroll = ( aEffPos.X() < 0 );
315 bool bTopScroll = ( aEffPos.Y() < 0 );
316
317 SCCOL nPosX;
318 SCROW nPosY;
319 pViewData->GetPosFromPixel( aEffPos.X(), aEffPos.Y(), GetWhich(),
320 nPosX, nPosY, true, true ); // with Repair
321
322 tools::Rectangle aEditArea = pViewData->GetEditArea(GetWhich(), nPosX, nPosY,
324 nullptr, false);
325
326 bool bFillingSelection = pViewData->IsFillMode() || pViewData->GetFillMode() == ScFillMode::MATRIX;
327 bool bBottomScroll;
328 bool bRightScroll;
329 // for Autofill don't yet assume we want to auto-scroll to the cell under the mouse
330 // because the autofill handle extends into a cells neighbours so initial click is usually
331 // above a neighbour cell
332 if (bFillingSelection)
333 {
334 bBottomScroll = aEffPos.Y() >= aWinSize.Height();
335 bRightScroll = aEffPos.X() >= aWinSize.Width();
336 }
337 else
338 {
339 //in the normal case make the full selected cell visible
340 bBottomScroll = aEditArea.Bottom() >= aWinSize.Height();
341 bRightScroll = aEditArea.Right() >= aWinSize.Width();
342 }
343
344 bool bScroll = bRightScroll || bBottomScroll || bLeftScroll || bTopScroll;
345
346 // for Autofill switch in the center of cell thereby don't prevent scrolling to bottom/right
347 if (bFillingSelection)
348 {
349 bool bLeft, bTop;
350 pViewData->GetMouseQuadrant( aEffPos, GetWhich(), nPosX, nPosY, bLeft, bTop );
352 SCTAB nTab = pViewData->GetTabNo();
353 if ( bLeft && !bRightScroll )
354 do --nPosX; while ( nPosX>=0 && rDoc.ColHidden( nPosX, nTab ) );
355 if ( bTop && !bBottomScroll )
356 {
357 if (--nPosY >= 0)
358 {
359 nPosY = rDoc.LastVisibleRow(0, nPosY, nTab);
360 if (!rDoc.ValidRow(nPosY))
361 nPosY = -1;
362 }
363 }
364 // negative value is allowed
365 }
366
367 // moved out of fix limit?
368 ScSplitPos eWhich = GetWhich();
369 if ( eWhich == pViewData->GetActivePart() )
370 {
372 if ( aEffPos.X() >= aWinSize.Width() )
373 {
374 if ( eWhich == SC_SPLIT_TOPLEFT )
375 {
377 bScroll = false;
378 bDidSwitch = true;
379 }
380 else if ( eWhich == SC_SPLIT_BOTTOMLEFT )
381 {
383 bScroll = false;
384 bDidSwitch = true;
385 }
386 }
387
389 if ( aEffPos.Y() >= aWinSize.Height() )
390 {
391 if ( eWhich == SC_SPLIT_TOPLEFT )
392 {
394 bScroll = false;
395 bDidSwitch = true;
396 }
397 else if ( eWhich == SC_SPLIT_TOPRIGHT )
398 {
400 bScroll = false;
401 bDidSwitch = true;
402 }
403 }
404 }
405
406 if (bScroll)
407 {
408 // Adjust update interval based on how far the mouse pointer is from the edge.
409 sal_uLong nUpdateInterval = CalcUpdateInterval(
410 aWinSize, aEffPos, bLeftScroll, bTopScroll, bRightScroll, bBottomScroll);
411 pEngine->SetUpdateInterval(nUpdateInterval);
412 }
413 else
414 {
415 // Don't forget to reset the interval when not scrolling!
417 }
418
420 SetCursorAtCell( nPosX, nPosY, bScroll );
421}
422
424{
425 SCCOL startX = pViewData->GetRefStartX();
426 SCROW startY = pViewData->GetRefStartY();
427
428 SCCOL endX = pViewData->GetRefEndX();
429 SCROW endY = pViewData->GetRefEndY();
430
431 return nPosX >= startX && nPosX <= endX && nPosY >= startY && nPosY <= endY;
432}
433
434bool ScViewFunctionSet::SetCursorAtCell( SCCOL nPosX, SCROW nPosY, bool bScroll )
435{
436 ScTabView* pView = pViewData->GetView();
437 SCTAB nTab = pViewData->GetTabNo();
439
440 if ( rDoc.IsTabProtected(nTab) )
441 {
442 if (nPosX < 0 || nPosY < 0)
443 return false;
444
445 const ScTableProtection* pProtect = rDoc.GetTabProtection(nTab);
446 if (!pProtect)
447 return false;
448
449 bool bSkipProtected = !pProtect->isOptionEnabled(ScTableProtection::SELECT_LOCKED_CELLS);
450 bool bSkipUnprotected = !pProtect->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS);
451
452 if ( bSkipProtected && bSkipUnprotected )
453 return false;
454
455 bool bCellProtected = rDoc.HasAttrib(nPosX, nPosY, nTab, nPosX, nPosY, nTab, HasAttrFlags::Protected);
456 if ( (bCellProtected && bSkipProtected) || (!bCellProtected && bSkipUnprotected) )
457 // Don't select this cell!
458 return false;
459 }
460
461 ScModule* pScMod = SC_MOD();
462 ScTabViewShell* pViewShell = pViewData->GetViewShell();
463 bool bRefMode = pViewShell && pViewShell->IsRefInputMode();
464
465 bool bHide = !bRefMode && !pViewData->IsAnyFillMode() &&
466 ( nPosX != pViewData->GetCurX() || nPosY != pViewData->GetCurY() );
467
468 if (bHide)
469 pView->HideAllCursors();
470
471 if (bScroll)
472 {
473 if (bRefMode)
474 {
475 ScSplitPos eWhich = GetWhich();
476 pView->AlignToCursor( nPosX, nPosY, SC_FOLLOW_LINE, &eWhich );
477 }
478 else
479 pView->AlignToCursor( nPosX, nPosY, SC_FOLLOW_LINE );
480 }
481
482 if (bRefMode)
483 {
484 // if no input is possible from this doc, don't move the reference cursor around
485 if ( !pScMod->IsModalMode(pViewData->GetSfxDocShell()) && (!CheckRefBounds(nPosX, nPosY) || SfxLokHelper::getDeviceFormFactor() != LOKDeviceFormFactor::MOBILE))
486 {
487 if (!bAnchor)
488 {
489 pView->DoneRefMode( true );
490 pView->InitRefMode( nPosX, nPosY, pViewData->GetTabNo(), SC_REFTYPE_REF );
491 }
492
493 if(SfxLokHelper::getDeviceFormFactor() != LOKDeviceFormFactor::MOBILE)
494 pView->UpdateRef( nPosX, nPosY, pViewData->GetTabNo() );
495
496 pView->SelectionChanged();
497 }
498 }
499 else if (pViewData->IsFillMode() ||
501 {
502 // If a matrix got touched, switch back to Autofill is possible with Ctrl
503
504 SCCOL nStartX, nEndX;
505 SCROW nStartY, nEndY; // Block
506 SCTAB nDummy;
507 pViewData->GetSimpleArea( nStartX, nStartY, nDummy, nEndX, nEndY, nDummy );
508
510 {
511 pView->InitRefMode( nStartX, nStartY, nTab, SC_REFTYPE_FILL );
512 CreateAnchor();
513 }
514
515 ScRange aDelRange;
516 bool bOldDelMark = pViewData->GetDelMark( aDelRange );
517
518 if ( nPosX+1 >= nStartX && nPosX <= nEndX &&
519 nPosY+1 >= nStartY && nPosY <= nEndY &&
520 ( nPosX != nEndX || nPosY != nEndY ) ) // minimize?
521 {
522 // direction (left or top)
523
524 tools::Long nSizeX = 0;
525 for (SCCOL i=nPosX+1; i<=nEndX; i++)
526 nSizeX += rDoc.GetColWidth( i, nTab );
527 tools::Long nSizeY = rDoc.GetRowHeight( nPosY+1, nEndY, nTab );
528
529 SCCOL nDelStartX = nStartX;
530 SCROW nDelStartY = nStartY;
531 if ( nSizeX > nSizeY )
532 nDelStartX = nPosX + 1;
533 else
534 nDelStartY = nPosY + 1;
535 // there is no need to check for zero, because nPosX/Y is also negative
536
537 if ( nDelStartX < nStartX )
538 nDelStartX = nStartX;
539 if ( nDelStartY < nStartY )
540 nDelStartY = nStartY;
541
542 // set range
543
544 pViewData->SetDelMark( ScRange( nDelStartX,nDelStartY,nTab,
545 nEndX,nEndY,nTab ) );
547
548 pViewData->GetView()->
549 PaintArea( nStartX,nDelStartY, nEndX,nEndY, ScUpdateMode::Marks );
550
551 nPosX = nEndX; // keep red border around range
552 nPosY = nEndY;
553
554 // reference the right way up, if it's upside down below
555 if ( nStartX != pViewData->GetRefStartX() || nStartY != pViewData->GetRefStartY() )
556 {
558 pViewData->GetView()->InitRefMode( nStartX, nStartY, nTab, SC_REFTYPE_FILL );
559 }
560 }
561 else
562 {
563 if ( bOldDelMark )
564 {
567 }
568
569 bool bNegX = ( nPosX < nStartX );
570 bool bNegY = ( nPosY < nStartY );
571
572 tools::Long nSizeX = 0;
573 if ( bNegX )
574 {
575 // in SetCursorAtPoint hidden columns are skipped.
576 // They must be skipped here too, or the result will always be the first hidden column.
577 do ++nPosX; while ( nPosX<nStartX && rDoc.ColHidden(nPosX, nTab) );
578 for (SCCOL i=nPosX; i<nStartX; i++)
579 nSizeX += rDoc.GetColWidth( i, nTab );
580 }
581 else
582 for (SCCOL i=nEndX+1; i<=nPosX; i++)
583 nSizeX += rDoc.GetColWidth( i, nTab );
584
585 tools::Long nSizeY = 0;
586 if ( bNegY )
587 {
588 // in SetCursorAtPoint hidden rows are skipped.
589 // They must be skipped here too, or the result will always be the first hidden row.
590 if (++nPosY < nStartY)
591 {
592 nPosY = rDoc.FirstVisibleRow(nPosY, nStartY-1, nTab);
593 if (!rDoc.ValidRow(nPosY))
594 nPosY = nStartY;
595 }
596 nSizeY += rDoc.GetRowHeight( nPosY, nStartY-1, nTab );
597 }
598 else
599 nSizeY += rDoc.GetRowHeight( nEndY+1, nPosY, nTab );
600
601 if ( nSizeX > nSizeY ) // Fill only ever in one direction
602 {
603 nPosY = nEndY;
604 bNegY = false;
605 }
606 else
607 {
608 nPosX = nEndX;
609 bNegX = false;
610 }
611
612 SCCOL nRefStX = bNegX ? nEndX : nStartX;
613 SCROW nRefStY = bNegY ? nEndY : nStartY;
614 if ( nRefStX != pViewData->GetRefStartX() || nRefStY != pViewData->GetRefStartY() )
615 {
617 pViewData->GetView()->InitRefMode( nRefStX, nRefStY, nTab, SC_REFTYPE_FILL );
618 }
619 }
620
621 pView->UpdateRef( nPosX, nPosY, nTab );
622 }
623 else if (pViewData->IsAnyFillMode())
624 {
626 if ( nMode == ScFillMode::EMBED_LT || nMode == ScFillMode::EMBED_RB )
627 {
628 OSL_ENSURE( rDoc.IsEmbedded(), "!rDoc.IsEmbedded()" );
629 ScRange aRange;
630 rDoc.GetEmbedded( aRange);
632 if (pViewData->GetRefType() != eRefMode)
633 {
634 if ( nMode == ScFillMode::EMBED_LT )
635 pView->InitRefMode( aRange.aEnd.Col(), aRange.aEnd.Row(), nTab, eRefMode );
636 else
637 pView->InitRefMode( aRange.aStart.Col(), aRange.aStart.Row(), nTab, eRefMode );
638 CreateAnchor();
639 }
640
641 pView->UpdateRef( nPosX, nPosY, nTab );
642 }
643 else if ( nMode == ScFillMode::MATRIX )
644 {
645 SCCOL nStartX, nEndX;
646 SCROW nStartY, nEndY; // Block
647 SCTAB nDummy;
648 pViewData->GetSimpleArea( nStartX, nStartY, nDummy, nEndX, nEndY, nDummy );
649
651 {
652 pView->InitRefMode( nStartX, nStartY, nTab, SC_REFTYPE_FILL );
653 CreateAnchor();
654 }
655
656 if ( nPosX < nStartX ) nPosX = nStartX;
657 if ( nPosY < nStartY ) nPosY = nStartY;
658
659 pView->UpdateRef( nPosX, nPosY, nTab );
660 }
661 // else new modes
662 }
663 else // regular selection
664 {
665 bool bHideCur = bAnchor && ( nPosX != pViewData->GetCurX() ||
666 nPosY != pViewData->GetCurY() );
667 if (bHideCur)
668 pView->HideAllCursors(); // otherwise twice: Block and SetCursor
669
670 if (bAnchor)
671 {
672 if (!bStarted)
673 {
674 bool bMove = ( nPosX != aAnchorPos.Col() ||
675 nPosY != aAnchorPos.Row() );
676 if ( bMove || ( pEngine && pEngine->GetMouseEvent().IsShift() ) )
677 {
679 aAnchorPos.Tab(), true );
680 bStarted = true;
681 }
682 }
683 if (bStarted)
684 // If the selection is already started, don't set the cursor.
685 pView->MarkCursor( nPosX, nPosY, nTab, false, false, true );
686 else
687 pView->SetCursor( nPosX, nPosY );
688 }
689 else
690 {
691 ScMarkData& rMark = pViewData->GetMarkData();
692 if (rMark.IsMarked() || rMark.IsMultiMarked())
693 {
694 pView->DoneBlockMode(true);
695 pView->InitBlockMode( nPosX, nPosY, nTab, true );
696 pView->MarkCursor( nPosX, nPosY, nTab );
697
698 aAnchorPos.Set( nPosX, nPosY, nTab );
699 bStarted = true;
700 }
701 // #i3875# *Hack* When a new cell is Ctrl-clicked with no pre-selected cells,
702 // it highlights that new cell as well as the old cell where the cursor is
703 // positioned prior to the click. A selection mode via Shift-F8 should also
704 // follow the same behavior.
705 else if ( pViewData->IsSelCtrlMouseClick() )
706 {
707 SCCOL nOldX = pViewData->GetCurX();
708 SCROW nOldY = pViewData->GetCurY();
709
710 pView->InitBlockMode( nOldX, nOldY, nTab, true );
711 pView->MarkCursor( nOldX, nOldY, nTab );
712
713 if ( nOldX != nPosX || nOldY != nPosY )
714 {
715 pView->DoneBlockMode( true );
716 pView->InitBlockMode( nPosX, nPosY, nTab, true );
717 pView->MarkCursor( nPosX, nPosY, nTab );
718 aAnchorPos.Set( nPosX, nPosY, nTab );
719 }
720
721 bStarted = true;
722 }
723 pView->SetCursor( nPosX, nPosY );
724 }
725
726 pViewData->SetRefStart( nPosX, nPosY, nTab );
727 if (bHideCur)
728 pView->ShowAllCursors();
729 }
730
731 if (bHide)
732 pView->ShowAllCursors();
733
734 return true;
735}
736
737bool ScViewFunctionSet::IsSelectionAtPoint( const Point& rPointPixel )
738{
739 bool bRefMode = SC_MOD()->IsFormulaMode();
740 if (bRefMode)
741 return false;
742
744 return false;
745
746 ScMarkData& rMark = pViewData->GetMarkData();
747 if (bAnchor || !rMark.IsMultiMarked())
748 {
749 SCCOL nPosX;
750 SCROW nPosY;
751 pViewData->GetPosFromPixel( rPointPixel.X(), rPointPixel.Y(), GetWhich(), nPosX, nPosY );
752 return pViewData->GetMarkData().IsCellMarked( nPosX, nPosY );
753 }
754
755 return false;
756}
757
758void ScViewFunctionSet::DeselectAtPoint( const Point& /* rPointPixel */ )
759{
760 // doesn't exist
761}
762
764{
766 return;
767
768 bool bRefMode = SC_MOD()->IsFormulaMode();
769 if (bRefMode)
770 {
772 }
773 else
774 {
777 }
778
779 bAnchor = false;
780}
781
783 ScSplitPos eSplitPos ) :
784 SelectionEngine( pWindow, &pView->GetFunctionSet() ),
785 eWhich( eSplitPos )
786{
787 SetSelectionMode( SelectionMode::Multiple );
788 EnableDrag( true );
789}
790
791// column and row headers
793 pViewData( pNewViewData ),
794 bColumn( false ),
795 eWhich( SC_SPLIT_TOPLEFT ),
796 bAnchor( false ),
797 nCursorPos( 0 )
798{
799 OSL_ENSURE(pViewData, "ViewData==0 at FunctionSet");
800}
801
803{
804 bColumn = bSet;
805}
806
808{
809 eWhich = eNew;
810}
811
813{
814 // doesn't exist
815}
816
818{
819 if (bAnchor)
820 return;
821
822 ScTabView* pView = pViewData->GetView();
823 pView->DoneBlockMode( true );
824 if (bColumn)
825 {
826 pView->InitBlockMode( static_cast<SCCOL>(nCursorPos), 0, pViewData->GetTabNo(), true, true );
827 pView->MarkCursor( static_cast<SCCOL>(nCursorPos), pViewData->MaxRow(), pViewData->GetTabNo() );
828 }
829 else
830 {
831 pView->InitBlockMode( 0, nCursorPos, pViewData->GetTabNo(), true, false, true );
833 }
834 bAnchor = true;
835}
836
838{
839 pViewData->GetView()->DoneBlockMode( true );
840 bAnchor = false;
841}
842
843void ScHeaderFunctionSet::SetCursorAtPoint( const Point& rPointPixel, bool /* bDontSelectAtCursor */ )
844{
845 if ( bDidSwitch )
846 {
847 // next valid position has to be originated from another window
848 if ( rPointPixel == aSwitchPos )
849 return; // don't scroll in the wrong window
850 else
851 bDidSwitch = false;
852 }
853
854 // Scrolling
856 bool bScroll;
857 if (bColumn)
858 bScroll = ( rPointPixel.X() < 0 || rPointPixel.X() >= aWinSize.Width() );
859 else
860 bScroll = ( rPointPixel.Y() < 0 || rPointPixel.Y() >= aWinSize.Height() );
861
862 // moved out of fix limit?
863 bool bSwitched = false;
864 if ( bColumn )
865 {
867 {
868 if ( rPointPixel.X() > aWinSize.Width() )
869 {
870 if ( eWhich == SC_SPLIT_TOPLEFT )
871 {
873 bSwitched = true;
874 }
875 else if ( eWhich == SC_SPLIT_BOTTOMLEFT )
876 {
878 bSwitched = true;
879 }
880 }
881 }
882 }
883 else // column headers
884 {
886 {
887 if ( rPointPixel.Y() > aWinSize.Height() )
888 {
889 if ( eWhich == SC_SPLIT_TOPLEFT )
890 {
892 bSwitched = true;
893 }
894 else if ( eWhich == SC_SPLIT_TOPRIGHT )
895 {
897 bSwitched = true;
898 }
899 }
900 }
901 }
902 if (bSwitched)
903 {
904 aSwitchPos = rPointPixel;
905 bDidSwitch = true;
906 return; // do not crunch with wrong positions
907 }
908
909 SCCOL nPosX;
910 SCROW nPosY;
911 pViewData->GetPosFromPixel( rPointPixel.X(), rPointPixel.Y(), pViewData->GetActivePart(),
912 nPosX, nPosY, false );
913 if (bColumn)
914 {
915 nCursorPos = static_cast<SCCOLROW>(nPosX);
917 }
918 else
919 {
920 nCursorPos = static_cast<SCCOLROW>(nPosY);
922 }
923
924 ScTabView* pView = pViewData->GetView();
925 bool bHide = pViewData->GetCurX() != nPosX ||
926 pViewData->GetCurY() != nPosY;
927 if (bHide)
928 pView->HideAllCursors();
929
930 if (bScroll)
931 pView->AlignToCursor( nPosX, nPosY, SC_FOLLOW_LINE );
932 pView->SetCursor( nPosX, nPosY );
933
934 if ( !bAnchor || !pView->IsBlockMode() )
935 {
936 pView->DoneBlockMode( true );
938 pView->InitBlockMode( nPosX, nPosY, pViewData->GetTabNo(), true, bColumn, !bColumn );
939
940 bAnchor = true;
941 }
942
943 pView->MarkCursor( nPosX, nPosY, pViewData->GetTabNo(), bColumn, !bColumn );
944
945 // SelectionChanged inside of HideCursor because of UpdateAutoFillMark
946 pView->SelectionChanged();
947
948 if (bHide)
949 pView->ShowAllCursors();
950}
951
952bool ScHeaderFunctionSet::IsSelectionAtPoint( const Point& rPointPixel )
953{
954 SCCOL nPosX;
955 SCROW nPosY;
956 pViewData->GetPosFromPixel( rPointPixel.X(), rPointPixel.Y(), pViewData->GetActivePart(),
957 nPosX, nPosY, false );
958
959 ScMarkData& rMark = pViewData->GetMarkData();
960 if (bColumn)
961 return rMark.IsColumnMarked( nPosX );
962 else
963 return rMark.IsRowMarked( nPosY );
964}
965
966void ScHeaderFunctionSet::DeselectAtPoint( const Point& /* rPointPixel */ )
967{
968}
969
971{
973 bAnchor = false;
974}
975
977 SelectionEngine( pWindow, pFuncSet )
978{
979 SetSelectionMode( SelectionMode::Multiple );
980 EnableDrag( false );
981}
982
983/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
OUString GetURLNoPass(DecodeMechanism eMechanism=DecodeMechanism::ToIUri, rtl_TextEncoding eCharset=RTL_TEXTENCODING_UTF8) const
bool IsShift() const
SCTAB Tab() const
Definition: address.hxx:283
void Set(SCCOL nCol, SCROW nRow, SCTAB nTab)
Definition: address.hxx:403
SCROW Row() const
Definition: address.hxx:274
SCCOL Col() const
Definition: address.hxx:279
SC_DLLPUBLIC sal_uInt16 GetRowHeight(SCROW nRow, SCTAB nTab, bool bHiddenAsZero=true) const
Definition: document.cxx:4224
SC_DLLPUBLIC sal_uInt16 GetColWidth(SCCOL nCol, SCTAB nTab, bool bHiddenAsZero=true) const
Definition: document.cxx:4183
bool ValidRow(SCROW nRow) const
Definition: document.hxx:899
SC_DLLPUBLIC const ScTableProtection * GetTabProtection(SCTAB nTab) const
Definition: documen3.cxx:1928
SC_DLLPUBLIC bool IsTabProtected(SCTAB nTab) const
Definition: documen3.cxx:1919
bool IsEmbedded() const
Definition: document.hxx:951
SC_DLLPUBLIC bool HasAttrib(SCCOL nCol1, SCROW nRow1, SCTAB nTab1, SCCOL nCol2, SCROW nRow2, SCTAB nTab2, HasAttrFlags nMask) const
Definition: document.cxx:5277
void GetEmbedded(ScRange &rRange) const
Definition: documen3.cxx:1717
SC_DLLPUBLIC bool ColHidden(SCCOL nCol, SCTAB nTab, SCCOL *pFirstCol=nullptr, SCCOL *pLastCol=nullptr) const
Definition: document.cxx:4508
SC_DLLPUBLIC SCROW LastVisibleRow(SCROW nStartRow, SCROW nEndRow, SCTAB nTab) const
Definition: document.cxx:4546
SC_DLLPUBLIC SCROW FirstVisibleRow(SCROW nStartRow, SCROW nEndRow, SCTAB nTab) const
Definition: document.cxx:4538
virtual void CreateAnchor() override
Definition: select.cxx:817
virtual void BeginDrag() override
Definition: select.cxx:812
virtual void DeselectAtPoint(const Point &rPointPixel) override
Definition: select.cxx:966
virtual void SetCursorAtPoint(const Point &rPointPixel, bool bDontSelectAtCursor=false) override
Definition: select.cxx:843
ScHeaderFunctionSet(ScViewData *pNewViewData)
Definition: select.cxx:792
void SetColumn(bool bSet)
Definition: select.cxx:802
SCCOLROW nCursorPos
Definition: select.hxx:83
ScViewData * pViewData
Definition: select.hxx:78
ScSplitPos eWhich
Definition: select.hxx:80
void SetWhich(ScSplitPos eNew)
Definition: select.cxx:807
virtual void DestroyAnchor() override
Definition: select.cxx:837
virtual bool IsSelectionAtPoint(const Point &rPointPixel) override
Definition: select.cxx:952
virtual void DeselectAll() override
Definition: select.cxx:970
ScHeaderSelectionEngine(vcl::Window *pWindow, ScHeaderFunctionSet *pFuncSet)
Definition: select.cxx:976
todo: It should be possible to have MarkArrays for each table, in order to enable "search all" across...
Definition: markdata.hxx:43
bool IsMultiMarked() const
Definition: markdata.hxx:81
bool IsColumnMarked(SCCOL nCol) const
Definition: markdata.cxx:287
bool IsRowMarked(SCROW nRow) const
Definition: markdata.cxx:303
bool IsCellMarked(SCCOL nCol, SCROW nRow, bool bNoSimple=false) const
Definition: markdata.cxx:270
void MarkToMulti()
Definition: markdata.cxx:209
bool IsMarked() const
Definition: markdata.hxx:80
void MarkToSimple()
Definition: markdata.cxx:222
bool IsModalMode(SfxObjectShell *pDocSh=nullptr)
Definition: scmod.cxx:1594
bool IsFormulaMode()
Definition: scmod.cxx:1678
ScAddress aEnd
Definition: address.hxx:498
ScAddress aStart
Definition: address.hxx:497
void UpdateInputHandler(bool bForce=false, bool bStopEditing=true)
Definition: tabvwsha.cxx:666
bool IsRefInputMode() const
Definition: tabvwsha.cxx:616
void InitBlockMode(SCCOL nCurX, SCROW nCurY, SCTAB nCurZ, bool bTestNeg=false, bool bCols=false, bool bRows=false, bool bForceNeg=false)
Definition: tabview2.cxx:353
void FakeButtonUp(ScSplitPos eWhich)
Definition: tabview3.cxx:214
bool IsBlockMode() const
Definition: tabview2.cxx:444
void AlignToCursor(SCCOL nCurX, SCROW nCurY, ScFollowMode eMode, const ScSplitPos *pWhich=nullptr)
Definition: tabview3.cxx:920
void DoneBlockMode(bool bContinue=false)
Definition: tabview2.cxx:409
void DoneRefMode(bool bContinue=false)
Definition: tabview4.cxx:159
void SelectionChanged(bool bFromPaste=false)
Definition: tabview3.cxx:532
void InitRefMode(SCCOL nCurX, SCROW nCurY, SCTAB nCurZ, ScRefType eType)
Definition: tabview4.cxx:309
void MarkCursor(SCCOL nCurX, SCROW nCurY, SCTAB nCurZ, bool bCols=false, bool bRows=false, bool bCellSelection=false)
Definition: tabview2.cxx:449
void ShowAllCursors()
Definition: tabview3.cxx:234
SC_DLLPUBLIC void SetCursor(SCCOL nPosX, SCROW nPosY, bool bNew=false)
Definition: tabview3.cxx:363
void ActivatePart(ScSplitPos eWhich)
Definition: tabview3.cxx:2907
void UpdateShrinkOverlay()
Definition: tabview2.cxx:1028
void UpdateRef(SCCOL nCurX, SCROW nCurY, SCTAB nCurZ)
Definition: tabview4.cxx:186
void HideAllCursors()
Definition: tabview3.cxx:220
bool IsMarking(SCCOL nCol, SCROW nRow, SCTAB nTab) const
Definition: tabview2.cxx:324
sheet protection state container
bool isOptionEnabled(Option eOption) const
bool IsFillMode() const
Definition: viewdata.hxx:515
ScFillMode GetFillMode() const
Definition: viewdata.hxx:516
ScMarkData & GetMarkData()
Definition: viewdata.cxx:3141
void GetMouseQuadrant(const Point &rClickPos, ScSplitPos eWhich, SCCOL nPosX, SCROW nPosY, bool &rLeft, bool &rTop)
Definition: viewdata.cxx:2895
SCCOL MaxCol() const
Definition: viewdata.hxx:396
SCTAB GetTabNo() const
Definition: viewdata.hxx:395
ScDocument & GetDocument() const
Definition: viewdata.hxx:380
SCROW GetPosY(ScVSplitPos eWhich, SCTAB nForTab=-1) const
Definition: viewdata.cxx:1416
void ResetDelMark()
Definition: viewdata.hxx:545
SCCOL GetRefStartX() const
Definition: viewdata.hxx:532
ScRefType GetRefType() const
Definition: viewdata.hxx:531
ScSplitMode GetHSplitMode() const
Definition: viewdata.hxx:416
bool IsSelCtrlMouseClick() const
Definition: viewdata.hxx:668
ScDocShell * GetDocShell() const
Definition: viewdata.hxx:354
ScGridWindow * GetActiveWin()
Definition: viewdata.cxx:3157
void GetPosFromPixel(tools::Long nClickX, tools::Long nClickY, ScSplitPos eWhich, SCCOL &rPosX, SCROW &rPosY, bool bTestMerge=true, bool bRepair=false, SCTAB nForTab=-1)
Definition: viewdata.cxx:2780
void SetDelMark(const ScRange &rRange)
Definition: viewdata.hxx:546
ScTabViewShell * GetViewShell() const
Definition: viewdata.hxx:357
ScMarkType GetSimpleArea(SCCOL &rStartCol, SCROW &rStartRow, SCTAB &rStartTab, SCCOL &rEndCol, SCROW &rEndRow, SCTAB &rEndTab) const
Definition: viewdata.cxx:1181
ScDBFunc * GetView() const
Definition: viewdata.cxx:863
ScSplitPos GetActivePart() const
Definition: viewdata.hxx:398
void ResetOldCursor()
Definition: viewdata.cxx:1397
SCROW GetRefEndY() const
Definition: viewdata.hxx:536
bool GetDelMark(ScRange &rRange) const
Definition: viewdata.hxx:549
SCCOL GetRefEndX() const
Definition: viewdata.hxx:535
SCROW GetRefStartY() const
Definition: viewdata.hxx:533
SCROW MaxRow() const
Definition: viewdata.hxx:397
ScSplitMode GetVSplitMode() const
Definition: viewdata.hxx:417
tools::Rectangle GetEditArea(ScSplitPos eWhich, SCCOL nPosX, SCROW nPosY, vcl::Window *pWin, const ScPatternAttr *pPattern, bool bForceToTop, bool bInPrintTwips=false)
Definition: viewdata.cxx:1509
SfxObjectShell * GetSfxDocShell() const
Definition: viewdata.hxx:358
SCROW GetCurY() const
Definition: viewdata.hxx:402
SCCOL GetCurX() const
Definition: viewdata.hxx:401
bool IsAnyFillMode() const
Definition: viewdata.hxx:514
SCCOL GetPosX(ScHSplitPos eWhich, SCTAB nForTab=-1) const
Definition: viewdata.cxx:1402
void SetRefStart(SCCOL nNewX, SCROW nNewY, SCTAB nNewZ)
Definition: viewdata.cxx:4132
bool SelectionEditable(bool *pOnlyNotBecauseOfMatrix=nullptr)
Definition: viewfunc.cxx:261
SC_DLLPUBLIC bool CopyToClip(ScDocument *pClipDoc, bool bCut, bool bApi=false, bool bIncludeObjects=false, bool bStopEdit=true)
Definition: viewfun3.cxx:168
virtual void DeselectAtPoint(const Point &rPointPixel) override
Definition: select.cxx:758
virtual void DeselectAll() override
Definition: select.cxx:763
bool SetCursorAtCell(SCCOL nPosX, SCROW nPosY, bool bScroll)
Definition: select.cxx:434
virtual void CreateAnchor() override
Definition: select.cxx:220
ScSplitPos GetWhich() const
Definition: select.cxx:55
virtual void BeginDrag() override
Definition: select.cxx:146
ScViewData * pViewData
Definition: select.hxx:43
void SetAnchorFlag(bool bSet)
Definition: select.cxx:286
sal_uLong CalcUpdateInterval(const Size &rWinSize, const Point &rEffPos, bool bLeftScroll, bool bTopScroll, bool bRightScroll, bool bBottomScroll)
Definition: select.cxx:63
void SetSelectionEngine(ScViewSelectionEngine *pSelEngine)
Definition: select.cxx:140
ScViewFunctionSet(ScViewData *pNewViewData)
Definition: select.cxx:46
virtual void DestroyAnchor() override
Definition: select.cxx:275
void SetAnchor(SCCOL nPosX, SCROW nPosY)
Definition: select.cxx:231
ScAddress aAnchorPos
Definition: select.hxx:48
ScViewSelectionEngine * pEngine
Definition: select.hxx:44
virtual void SetCursorAtPoint(const Point &rPointPixel, bool bDontSelectAtCursor=false) override
Definition: select.cxx:291
bool CheckRefBounds(SCCOL nPosX, SCROW nPosY)
Definition: select.cxx:423
virtual bool IsSelectionAtPoint(const Point &rPointPixel) override
Definition: select.cxx:737
ScSplitPos GetWhich() const
Definition: select.hxx:36
ScViewSelectionEngine(vcl::Window *pWindow, ScTabView *pView, ScSplitPos eSplitPos)
Definition: select.cxx:782
const MouseEvent & GetMouseEvent() const
const Point & GetMousePosPixel() const
void EnableDrag(bool bOn)
vcl::Window * GetWindow() const
void SetSelectionMode(SelectionMode eMode)
void SetUpdateInterval(sal_uLong nInterval)
static LOKDeviceFormFactor getDeviceFormFactor()
const INetURLObject & GetURLObject() const
void FillTransferableObjectDescriptor(TransferableObjectDescriptor &rDesc) const
SfxMedium * GetMedium() const
constexpr tools::Long getHeight() const
constexpr tools::Long Height() const
constexpr tools::Long getWidth() const
constexpr tools::Long Width() const
constexpr tools::Long GetWidth() const
constexpr tools::Long Right() const
constexpr tools::Long GetHeight() const
constexpr tools::Long Bottom() const
bool IsTracking() const
tools::Rectangle GetDesktopRectPixel() const
void EndTracking(TrackingEventFlags nFlags=TrackingEventFlags::NONE)
void LocalStartDrag()
Size GetOutputSizePixel() const
Point OutputToAbsoluteScreenPixel(const Point &rPos) const
std::unique_ptr< ScDocument, o3tl::default_delete< ScDocument > > ScDocumentUniquePtr
Definition: document.hxx:2717
@ SCDOCMODE_CLIP
Definition: document.hxx:256
sal_uInt16 nScFillModeMouseModifier
Definition: global.cxx:118
constexpr sal_uInt16 KEY_MOD1
int i
long Long
#define SC_MOD()
Definition: scmod.hxx:249
static bool bDidSwitch
Member.
Definition: select.cxx:43
static Point aSwitchPos
Definition: select.cxx:42
#define SELENG_AUTOREPEAT_INTERVAL_MAX
#define SELENG_AUTOREPEAT_INTERVAL
sal_uIntPtr sal_uLong
#define DND_ACTION_COPYMOVE
#define DND_ACTION_COPY
#define DND_ACTION_LINK
signed char sal_Int8
sal_Int32 SCCOLROW
a type capable of holding either SCCOL or SCROW
Definition: types.hxx:23
sal_Int16 SCTAB
Definition: types.hxx:22
sal_Int16 SCCOL
Definition: types.hxx:21
sal_Int32 SCROW
Definition: types.hxx:17
ScSplitPos
Definition: viewdata.hxx:44
@ SC_SPLIT_BOTTOMRIGHT
Definition: viewdata.hxx:44
@ SC_SPLIT_TOPLEFT
Definition: viewdata.hxx:44
@ SC_SPLIT_BOTTOMLEFT
Definition: viewdata.hxx:44
@ SC_SPLIT_TOPRIGHT
Definition: viewdata.hxx:44
ScHSplitPos WhichH(ScSplitPos ePos)
Definition: viewdata.hxx:722
@ SC_FOLLOW_LINE
Definition: viewdata.hxx:52
@ SC_SPLIT_FIX
Definition: viewdata.hxx:42
ScRefType
Mouse mode to select areas.
Definition: viewdata.hxx:55
@ SC_REFTYPE_EMBED_RB
Definition: viewdata.hxx:56
@ SC_REFTYPE_EMBED_LT
Definition: viewdata.hxx:56
@ SC_REFTYPE_FILL
Definition: viewdata.hxx:55
@ SC_REFTYPE_REF
Definition: viewdata.hxx:55
ScVSplitPos WhichV(ScSplitPos ePos)
Definition: viewdata.hxx:728
ScFillMode
Definition: viewdata.hxx:34