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 m_pViewData( pNewViewData ),
48 m_pEngine( nullptr ),
49 m_bAnchor( false ),
50 m_bStarted( false )
51{
52 OSL_ENSURE(m_pViewData, "ViewData==0 at FunctionSet");
53}
54
56{
57 if (m_pEngine)
58 return m_pEngine->GetWhich();
59 else
60 return m_pViewData->GetActivePart();
61}
62
64 bool bLeftScroll, bool bTopScroll, bool bRightScroll, bool bBottomScroll )
65{
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 = m_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 m_pEngine = pSelEngine;
143}
144
145// Drag & Drop
147{
148 SCTAB nTab = m_pViewData->GetTabNo();
149
150 SCCOL nPosX;
151 SCROW nPosY;
152 if (m_pEngine)
153 {
155 m_pViewData->GetPosFromPixel( aMPos.X(), aMPos.Y(), GetWhich(), nPosX, nPosY );
156 }
157 else
158 {
159 nPosX = m_pViewData->GetCurX();
160 nPosY = m_pViewData->GetCurY();
161 }
162
163 ScModule* pScMod = SC_MOD();
164 bool bRefMode = pScMod->IsFormulaMode();
165 if (bRefMode)
166 return;
167
168 m_pViewData->GetView()->FakeButtonUp( GetWhich() ); // ButtonUp is swallowed
169
171 rMark.MarkToSimple();
172 if ( !rMark.IsMarked() || rMark.IsMultiMarked() )
173 return;
174
176 // bApi = TRUE -> no error messages
177 bool bCopied = m_pViewData->GetView()->CopyToClip( pClipDoc.get(), false, true );
178 if ( !bCopied )
179 return;
180
181 sal_Int8 nDragActions = m_pViewData->GetView()->SelectionEditable() ?
184
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( m_pViewData->GetCurX(), m_pViewData->GetCurY() );
201 pTransferObj->SetVisibleTab( nTab );
202
203 pTransferObj->SetDragSource( pDocSh, rMark );
204
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 (m_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 = m_pViewData->GetView();
235 SCTAB nTab = m_pViewData->GetTabNo();
236
237 if (bRefMode)
238 {
239 pView->DoneRefMode();
240 m_aAnchorPos.Set( nPosX, nPosY, nTab );
243 m_bStarted = true;
244 }
245 else if (m_pViewData->IsAnyFillMode())
246 {
247 m_aAnchorPos.Set( nPosX, nPosY, nTab );
248 m_bStarted = true;
249 }
250 else
251 {
252 // don't go there and back again
253 if ( m_bStarted && pView->IsMarking( nPosX, nPosY, nTab ) )
254 {
255 // don't do anything
256 }
257 else
258 {
259 pView->DoneBlockMode( true );
260 m_aAnchorPos.Set( nPosX, nPosY, nTab );
262 if ( rMark.IsMarked() || rMark.IsMultiMarked() )
263 {
265 m_aAnchorPos.Tab(), true );
266 m_bStarted = true;
267 }
268 else
269 m_bStarted = false;
270 }
271 }
272 m_bAnchor = true;
273}
274
276{
278 return;
279
280 bool bRefMode = SC_MOD()->IsFormulaMode();
281 if (bRefMode)
282 m_pViewData->GetView()->DoneRefMode( true );
283 else
285
286 m_bAnchor = false;
287}
288
290{
291 m_bAnchor = bSet;
292}
293
294void ScViewFunctionSet::SetCursorAtPoint( const Point& rPointPixel, bool /* bDontSelectAtCursor */ )
295{
296 if ( bDidSwitch )
297 {
298 if ( rPointPixel == aSwitchPos )
299 return; // don't scroll in wrong window
300 else
301 bDidSwitch = false;
302 }
303 aSwitchPos = rPointPixel; // only important, if bDidSwitch
304
305 // treat position 0 as -1, so scrolling is always possible
306 // (with full screen and hidden headers, the top left border may be at 0)
307 // (moved from ScViewData::GetPosFromPixel)
308
309 Point aEffPos = rPointPixel;
310 if ( aEffPos.X() == 0 )
311 aEffPos.setX( -1 );
312 if ( aEffPos.Y() == 0 )
313 aEffPos.setY( -1 );
314
315 // Scrolling
317 bool bLeftScroll = ( aEffPos.X() < 0 );
318 bool bTopScroll = ( aEffPos.Y() < 0 );
319
320 SCCOL nPosX;
321 SCROW nPosY;
322 m_pViewData->GetPosFromPixel( aEffPos.X(), aEffPos.Y(), GetWhich(),
323 nPosX, nPosY, true, true ); // with Repair
324
325 tools::Rectangle aEditArea = m_pViewData->GetEditArea(GetWhich(), nPosX, nPosY,
327 nullptr, false);
328
329 bool bFillingSelection = m_pViewData->IsFillMode() || m_pViewData->GetFillMode() == ScFillMode::MATRIX;
330 bool bBottomScroll;
331 bool bRightScroll;
332 // for Autofill don't yet assume we want to auto-scroll to the cell under the mouse
333 // because the autofill handle extends into a cells neighbours so initial click is usually
334 // above a neighbour cell
335 if (bFillingSelection)
336 {
337 bBottomScroll = aEffPos.Y() >= aWinSize.Height();
338 bRightScroll = aEffPos.X() >= aWinSize.Width();
339 }
340 else
341 {
342 //in the normal case make the full selected cell visible
343 bBottomScroll = aEditArea.Bottom() >= aWinSize.Height();
344 bRightScroll = aEditArea.Right() >= aWinSize.Width();
345 }
346
347 bool bScroll = bRightScroll || bBottomScroll || bLeftScroll || bTopScroll;
348
349 // for Autofill switch in the center of cell thereby don't prevent scrolling to bottom/right
350 if (bFillingSelection)
351 {
352 bool bLeft, bTop;
353 m_pViewData->GetMouseQuadrant( aEffPos, GetWhich(), nPosX, nPosY, bLeft, bTop );
355 SCTAB nTab = m_pViewData->GetTabNo();
356 if ( bLeft && !bRightScroll )
357 do --nPosX; while ( nPosX>=0 && rDoc.ColHidden( nPosX, nTab ) );
358 if ( bTop && !bBottomScroll )
359 {
360 if (--nPosY >= 0)
361 {
362 nPosY = rDoc.LastVisibleRow(0, nPosY, nTab);
363 if (!rDoc.ValidRow(nPosY))
364 nPosY = -1;
365 }
366 }
367 // negative value is allowed
368 }
369
370 // moved out of fix limit?
371 ScSplitPos eWhich = GetWhich();
372 if ( eWhich == m_pViewData->GetActivePart() )
373 {
375 if ( aEffPos.X() >= aWinSize.Width() )
376 {
377 if ( eWhich == SC_SPLIT_TOPLEFT )
378 {
380 bScroll = false;
381 bDidSwitch = true;
382 }
383 else if ( eWhich == SC_SPLIT_BOTTOMLEFT )
384 {
386 bScroll = false;
387 bDidSwitch = true;
388 }
389 }
390
392 if ( aEffPos.Y() >= aWinSize.Height() )
393 {
394 if ( eWhich == SC_SPLIT_TOPLEFT )
395 {
397 bScroll = false;
398 bDidSwitch = true;
399 }
400 else if ( eWhich == SC_SPLIT_TOPRIGHT )
401 {
403 bScroll = false;
404 bDidSwitch = true;
405 }
406 }
407 }
408
409 if (bScroll)
410 {
411 // Adjust update interval based on how far the mouse pointer is from the edge.
412 sal_uLong nUpdateInterval = CalcUpdateInterval(
413 aWinSize, aEffPos, bLeftScroll, bTopScroll, bRightScroll, bBottomScroll);
414 m_pEngine->SetUpdateInterval(nUpdateInterval);
415 }
416 else
417 {
418 // Don't forget to reset the interval when not scrolling!
420 }
421
423 SetCursorAtCell( nPosX, nPosY, bScroll );
424}
425
427{
428 SCCOL startX = m_pViewData->GetRefStartX();
429 SCROW startY = m_pViewData->GetRefStartY();
430
431 SCCOL endX = m_pViewData->GetRefEndX();
432 SCROW endY = m_pViewData->GetRefEndY();
433
434 return nPosX >= startX && nPosX <= endX && nPosY >= startY && nPosY <= endY;
435}
436
437bool ScViewFunctionSet::SetCursorAtCell( SCCOL nPosX, SCROW nPosY, bool bScroll )
438{
439 ScTabView* pView = m_pViewData->GetView();
440 SCTAB nTab = m_pViewData->GetTabNo();
442
443 if ( rDoc.IsTabProtected(nTab) )
444 {
445 if (nPosX < 0 || nPosY < 0)
446 return false;
447
448 const ScTableProtection* pProtect = rDoc.GetTabProtection(nTab);
449 if (!pProtect)
450 return false;
451
452 bool bSkipProtected = !pProtect->isOptionEnabled(ScTableProtection::SELECT_LOCKED_CELLS);
453 bool bSkipUnprotected = !pProtect->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS);
454
455 if ( bSkipProtected && bSkipUnprotected )
456 return false;
457
458 bool bCellProtected = rDoc.HasAttrib(nPosX, nPosY, nTab, nPosX, nPosY, nTab, HasAttrFlags::Protected);
459 if ( (bCellProtected && bSkipProtected) || (!bCellProtected && bSkipUnprotected) )
460 // Don't select this cell!
461 return false;
462 }
463
464 ScModule* pScMod = SC_MOD();
465 ScTabViewShell* pViewShell = m_pViewData->GetViewShell();
466 bool bRefMode = pViewShell && pViewShell->IsRefInputMode();
467
468 bool bHide = !bRefMode && !m_pViewData->IsAnyFillMode() &&
469 ( nPosX != m_pViewData->GetCurX() || nPosY != m_pViewData->GetCurY() );
470
471 if (bHide)
472 pView->HideAllCursors();
473
474 if (bScroll)
475 {
476 if (bRefMode)
477 {
478 ScSplitPos eWhich = GetWhich();
479 pView->AlignToCursor( nPosX, nPosY, SC_FOLLOW_LINE, &eWhich );
480 }
481 else
482 pView->AlignToCursor( nPosX, nPosY, SC_FOLLOW_LINE );
483 }
484
485 if (bRefMode)
486 {
487 // if no input is possible from this doc, don't move the reference cursor around
488 if ( !pScMod->IsModalMode(m_pViewData->GetSfxDocShell()) && (!CheckRefBounds(nPosX, nPosY) || SfxLokHelper::getDeviceFormFactor() != LOKDeviceFormFactor::MOBILE))
489 {
490 if (!m_bAnchor)
491 {
492 pView->DoneRefMode( true );
493 pView->InitRefMode( nPosX, nPosY, m_pViewData->GetTabNo(), SC_REFTYPE_REF );
494 }
495
496 if(SfxLokHelper::getDeviceFormFactor() != LOKDeviceFormFactor::MOBILE)
497 pView->UpdateRef( nPosX, nPosY, m_pViewData->GetTabNo() );
498
499 pView->SelectionChanged();
500 }
501 }
502 else if (m_pViewData->IsFillMode() ||
504 {
505 // If a matrix got touched, switch back to Autofill is possible with Ctrl
506
507 SCCOL nStartX, nEndX;
508 SCROW nStartY, nEndY; // Block
509 SCTAB nDummy;
510 m_pViewData->GetSimpleArea( nStartX, nStartY, nDummy, nEndX, nEndY, nDummy );
511
513 {
514 pView->InitRefMode( nStartX, nStartY, nTab, SC_REFTYPE_FILL );
515 CreateAnchor();
516 }
517
518 ScRange aDelRange;
519 bool bOldDelMark = m_pViewData->GetDelMark( aDelRange );
520
521 if ( nPosX+1 >= nStartX && nPosX <= nEndX &&
522 nPosY+1 >= nStartY && nPosY <= nEndY &&
523 ( nPosX != nEndX || nPosY != nEndY ) ) // minimize?
524 {
525 // direction (left or top)
526
527 tools::Long nSizeX = 0;
528 for (SCCOL i=nPosX+1; i<=nEndX; i++)
529 nSizeX += rDoc.GetColWidth( i, nTab );
530 tools::Long nSizeY = rDoc.GetRowHeight( nPosY+1, nEndY, nTab );
531
532 SCCOL nDelStartX = nStartX;
533 SCROW nDelStartY = nStartY;
534 if ( nSizeX > nSizeY )
535 nDelStartX = nPosX + 1;
536 else
537 nDelStartY = nPosY + 1;
538 // there is no need to check for zero, because nPosX/Y is also negative
539
540 if ( nDelStartX < nStartX )
541 nDelStartX = nStartX;
542 if ( nDelStartY < nStartY )
543 nDelStartY = nStartY;
544
545 // set range
546
547 m_pViewData->SetDelMark( ScRange( nDelStartX,nDelStartY,nTab,
548 nEndX,nEndY,nTab ) );
550
552 PaintArea( nStartX,nDelStartY, nEndX,nEndY, ScUpdateMode::Marks );
553
554 nPosX = nEndX; // keep red border around range
555 nPosY = nEndY;
556
557 // reference the right way up, if it's upside down below
558 if ( nStartX != m_pViewData->GetRefStartX() || nStartY != m_pViewData->GetRefStartY() )
559 {
561 m_pViewData->GetView()->InitRefMode( nStartX, nStartY, nTab, SC_REFTYPE_FILL );
562 }
563 }
564 else
565 {
566 if ( bOldDelMark )
567 {
570 }
571
572 bool bNegX = ( nPosX < nStartX );
573 bool bNegY = ( nPosY < nStartY );
574
575 tools::Long nSizeX = 0;
576 if ( bNegX )
577 {
578 // in SetCursorAtPoint hidden columns are skipped.
579 // They must be skipped here too, or the result will always be the first hidden column.
580 do ++nPosX; while ( nPosX<nStartX && rDoc.ColHidden(nPosX, nTab) );
581 for (SCCOL i=nPosX; i<nStartX; i++)
582 nSizeX += rDoc.GetColWidth( i, nTab );
583 }
584 else
585 for (SCCOL i=nEndX+1; i<=nPosX; i++)
586 nSizeX += rDoc.GetColWidth( i, nTab );
587
588 tools::Long nSizeY = 0;
589 if ( bNegY )
590 {
591 // in SetCursorAtPoint hidden rows are skipped.
592 // They must be skipped here too, or the result will always be the first hidden row.
593 if (++nPosY < nStartY)
594 {
595 nPosY = rDoc.FirstVisibleRow(nPosY, nStartY-1, nTab);
596 if (!rDoc.ValidRow(nPosY))
597 nPosY = nStartY;
598 }
599 nSizeY += rDoc.GetRowHeight( nPosY, nStartY-1, nTab );
600 }
601 else
602 nSizeY += rDoc.GetRowHeight( nEndY+1, nPosY, nTab );
603
604 if ( nSizeX > nSizeY ) // Fill only ever in one direction
605 {
606 nPosY = nEndY;
607 bNegY = false;
608 }
609 else
610 {
611 nPosX = nEndX;
612 bNegX = false;
613 }
614
615 SCCOL nRefStX = bNegX ? nEndX : nStartX;
616 SCROW nRefStY = bNegY ? nEndY : nStartY;
617 if ( nRefStX != m_pViewData->GetRefStartX() || nRefStY != m_pViewData->GetRefStartY() )
618 {
620 m_pViewData->GetView()->InitRefMode( nRefStX, nRefStY, nTab, SC_REFTYPE_FILL );
621 }
622 }
623
624 pView->UpdateRef( nPosX, nPosY, nTab );
625 }
626 else if (m_pViewData->IsAnyFillMode())
627 {
629 if ( nMode == ScFillMode::EMBED_LT || nMode == ScFillMode::EMBED_RB )
630 {
631 OSL_ENSURE( rDoc.IsEmbedded(), "!rDoc.IsEmbedded()" );
632 ScRange aRange;
633 rDoc.GetEmbedded( aRange);
635 if (m_pViewData->GetRefType() != eRefMode)
636 {
637 if ( nMode == ScFillMode::EMBED_LT )
638 pView->InitRefMode( aRange.aEnd.Col(), aRange.aEnd.Row(), nTab, eRefMode );
639 else
640 pView->InitRefMode( aRange.aStart.Col(), aRange.aStart.Row(), nTab, eRefMode );
641 CreateAnchor();
642 }
643
644 pView->UpdateRef( nPosX, nPosY, nTab );
645 }
646 else if ( nMode == ScFillMode::MATRIX )
647 {
648 SCCOL nStartX, nEndX;
649 SCROW nStartY, nEndY; // Block
650 SCTAB nDummy;
651 m_pViewData->GetSimpleArea( nStartX, nStartY, nDummy, nEndX, nEndY, nDummy );
652
654 {
655 pView->InitRefMode( nStartX, nStartY, nTab, SC_REFTYPE_FILL );
656 CreateAnchor();
657 }
658
659 if ( nPosX < nStartX ) nPosX = nStartX;
660 if ( nPosY < nStartY ) nPosY = nStartY;
661
662 pView->UpdateRef( nPosX, nPosY, nTab );
663 }
664 // else new modes
665 }
666 else // regular selection
667 {
668 bool bHideCur = m_bAnchor && ( nPosX != m_pViewData->GetCurX() ||
669 nPosY != m_pViewData->GetCurY() );
670 if (bHideCur)
671 pView->HideAllCursors(); // otherwise twice: Block and SetCursor
672
673 if (m_bAnchor)
674 {
675 if (!m_bStarted)
676 {
677 bool bMove = ( nPosX != m_aAnchorPos.Col() ||
678 nPosY != m_aAnchorPos.Row() );
679 if ( bMove || ( m_pEngine && m_pEngine->GetMouseEvent().IsShift() ) )
680 {
682 m_aAnchorPos.Tab(), true );
683 m_bStarted = true;
684 }
685 }
686 if (m_bStarted)
687 // If the selection is already started, don't set the cursor.
688 pView->MarkCursor( nPosX, nPosY, nTab, false, false, true );
689 else
690 pView->SetCursor( nPosX, nPosY );
691 }
692 else
693 {
695 if (rMark.IsMarked() || rMark.IsMultiMarked())
696 {
697 pView->DoneBlockMode(true);
698 pView->InitBlockMode( nPosX, nPosY, nTab, true );
699 pView->MarkCursor( nPosX, nPosY, nTab );
700
701 m_aAnchorPos.Set( nPosX, nPosY, nTab );
702 m_bStarted = true;
703 }
704 // #i3875# *Hack* When a new cell is Ctrl-clicked with no pre-selected cells,
705 // it highlights that new cell as well as the old cell where the cursor is
706 // positioned prior to the click. A selection mode via Shift-F8 should also
707 // follow the same behavior.
708 else if ( m_pViewData->IsSelCtrlMouseClick() )
709 {
710 SCCOL nOldX = m_pViewData->GetCurX();
711 SCROW nOldY = m_pViewData->GetCurY();
712
713 pView->InitBlockMode( nOldX, nOldY, nTab, true );
714 pView->MarkCursor( nOldX, nOldY, nTab );
715
716 if ( nOldX != nPosX || nOldY != nPosY )
717 {
718 pView->DoneBlockMode( true );
719 pView->InitBlockMode( nPosX, nPosY, nTab, true );
720 pView->MarkCursor( nPosX, nPosY, nTab );
721 m_aAnchorPos.Set( nPosX, nPosY, nTab );
722 }
723
724 m_bStarted = true;
725 }
726 pView->SetCursor( nPosX, nPosY );
727 }
728
729 m_pViewData->SetRefStart( nPosX, nPosY, nTab );
730 if (bHideCur)
731 pView->ShowAllCursors();
732 }
733
734 if (bHide)
735 pView->ShowAllCursors();
736
737 return true;
738}
739
741{
742 bool bRefMode = SC_MOD()->IsFormulaMode();
743 if (bRefMode)
744 return false;
745
747 return false;
748
750 if (m_bAnchor || !rMark.IsMultiMarked())
751 {
752 SCCOL nPosX;
753 SCROW nPosY;
754 m_pViewData->GetPosFromPixel( rPointPixel.X(), rPointPixel.Y(), GetWhich(), nPosX, nPosY );
755 return m_pViewData->GetMarkData().IsCellMarked( nPosX, nPosY );
756 }
757
758 return false;
759}
760
761void ScViewFunctionSet::DeselectAtPoint( const Point& /* rPointPixel */ )
762{
763 // doesn't exist
764}
765
767{
769 return;
770
771 bool bRefMode = SC_MOD()->IsFormulaMode();
772 if (bRefMode)
773 {
775 }
776 else
777 {
780 }
781
782 m_bAnchor = false;
783}
784
786 ScSplitPos eSplitPos ) :
787 SelectionEngine( pWindow, &pView->GetFunctionSet() ),
788 eWhich( eSplitPos )
789{
790 SetSelectionMode( SelectionMode::Multiple );
791 EnableDrag( true );
792}
793
794// column and row headers
796 pViewData( pNewViewData ),
797 bColumn( false ),
798 eWhich( SC_SPLIT_TOPLEFT ),
799 bAnchor( false ),
800 nCursorPos( 0 )
801{
802 OSL_ENSURE(pViewData, "ViewData==0 at FunctionSet");
803}
804
806{
807 bColumn = bSet;
808}
809
811{
812 eWhich = eNew;
813}
814
816{
817 // doesn't exist
818}
819
821{
822 if (bAnchor)
823 return;
824
825 ScTabView* pView = pViewData->GetView();
826 pView->DoneBlockMode( true );
827 if (bColumn)
828 {
829 pView->InitBlockMode( static_cast<SCCOL>(nCursorPos), 0, pViewData->GetTabNo(), true, true );
830 pView->MarkCursor( static_cast<SCCOL>(nCursorPos), pViewData->MaxRow(), pViewData->GetTabNo() );
831 }
832 else
833 {
834 pView->InitBlockMode( 0, nCursorPos, pViewData->GetTabNo(), true, false, true );
836 }
837 bAnchor = true;
838}
839
841{
842 pViewData->GetView()->DoneBlockMode( true );
843 bAnchor = false;
844}
845
846void ScHeaderFunctionSet::SetCursorAtPoint( const Point& rPointPixel, bool /* bDontSelectAtCursor */ )
847{
848 if ( bDidSwitch )
849 {
850 // next valid position has to be originated from another window
851 if ( rPointPixel == aSwitchPos )
852 return; // don't scroll in the wrong window
853 else
854 bDidSwitch = false;
855 }
856
857 // Scrolling
859 bool bScroll;
860 if (bColumn)
861 bScroll = ( rPointPixel.X() < 0 || rPointPixel.X() >= aWinSize.Width() );
862 else
863 bScroll = ( rPointPixel.Y() < 0 || rPointPixel.Y() >= aWinSize.Height() );
864
865 // moved out of fix limit?
866 bool bSwitched = false;
867 if ( bColumn )
868 {
870 {
871 if ( rPointPixel.X() > aWinSize.Width() )
872 {
873 if ( eWhich == SC_SPLIT_TOPLEFT )
874 {
876 bSwitched = true;
877 }
878 else if ( eWhich == SC_SPLIT_BOTTOMLEFT )
879 {
881 bSwitched = true;
882 }
883 }
884 }
885 }
886 else // column headers
887 {
889 {
890 if ( rPointPixel.Y() > aWinSize.Height() )
891 {
892 if ( eWhich == SC_SPLIT_TOPLEFT )
893 {
895 bSwitched = true;
896 }
897 else if ( eWhich == SC_SPLIT_TOPRIGHT )
898 {
900 bSwitched = true;
901 }
902 }
903 }
904 }
905 if (bSwitched)
906 {
907 aSwitchPos = rPointPixel;
908 bDidSwitch = true;
909 return; // do not crunch with wrong positions
910 }
911
912 SCCOL nPosX;
913 SCROW nPosY;
914 pViewData->GetPosFromPixel( rPointPixel.X(), rPointPixel.Y(), pViewData->GetActivePart(),
915 nPosX, nPosY, false );
916 if (bColumn)
917 {
918 nCursorPos = static_cast<SCCOLROW>(nPosX);
920 }
921 else
922 {
923 nCursorPos = static_cast<SCCOLROW>(nPosY);
925 }
926
927 ScTabView* pView = pViewData->GetView();
928 bool bHide = pViewData->GetCurX() != nPosX ||
929 pViewData->GetCurY() != nPosY;
930 if (bHide)
931 pView->HideAllCursors();
932
933 if (bScroll)
934 pView->AlignToCursor( nPosX, nPosY, SC_FOLLOW_LINE );
935 pView->SetCursor( nPosX, nPosY );
936
937 if ( !bAnchor || !pView->IsBlockMode() )
938 {
939 pView->DoneBlockMode( true );
941 pView->InitBlockMode( nPosX, nPosY, pViewData->GetTabNo(), true, bColumn, !bColumn );
942
943 bAnchor = true;
944 }
945
946 pView->MarkCursor( nPosX, nPosY, pViewData->GetTabNo(), bColumn, !bColumn );
947
948 // SelectionChanged inside of HideCursor because of UpdateAutoFillMark
949 pView->SelectionChanged();
950
951 if (bHide)
952 pView->ShowAllCursors();
953}
954
956{
957 SCCOL nPosX;
958 SCROW nPosY;
959 pViewData->GetPosFromPixel( rPointPixel.X(), rPointPixel.Y(), pViewData->GetActivePart(),
960 nPosX, nPosY, false );
961
962 ScMarkData& rMark = pViewData->GetMarkData();
963 if (bColumn)
964 return rMark.IsColumnMarked( nPosX );
965 else
966 return rMark.IsRowMarked( nPosY );
967}
968
969void ScHeaderFunctionSet::DeselectAtPoint( const Point& /* rPointPixel */ )
970{
971}
972
974{
976 bAnchor = false;
977}
978
980 SelectionEngine( pWindow, pFuncSet )
981{
982 SetSelectionMode( SelectionMode::Multiple );
983 EnableDrag( false );
984}
985
986/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
OUString GetURLNoPass(DecodeMechanism eMechanism=DecodeMechanism::ToIUri, rtl_TextEncoding eCharset=RTL_TEXTENCODING_UTF8) const
bool IsShift() const
constexpr tools::Long Y() const
void setX(tools::Long nX)
void setY(tools::Long nY)
constexpr tools::Long X() const
constexpr tools::Long getX() const
constexpr tools::Long getY() 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:4161
SC_DLLPUBLIC sal_uInt16 GetColWidth(SCCOL nCol, SCTAB nTab, bool bHiddenAsZero=true) const
Definition: document.cxx:4122
bool ValidRow(SCROW nRow) const
Definition: document.hxx:900
SC_DLLPUBLIC const ScTableProtection * GetTabProtection(SCTAB nTab) const
Definition: documen3.cxx:1914
SC_DLLPUBLIC bool IsTabProtected(SCTAB nTab) const
Definition: documen3.cxx:1905
bool IsEmbedded() const
Definition: document.hxx:952
SC_DLLPUBLIC bool HasAttrib(SCCOL nCol1, SCROW nRow1, SCTAB nTab1, SCCOL nCol2, SCROW nRow2, SCTAB nTab2, HasAttrFlags nMask) const
Definition: document.cxx:5161
void GetEmbedded(ScRange &rRange) const
Definition: documen3.cxx:1703
SC_DLLPUBLIC bool ColHidden(SCCOL nCol, SCTAB nTab, SCCOL *pFirstCol=nullptr, SCCOL *pLastCol=nullptr) const
Definition: document.cxx:4430
SC_DLLPUBLIC SCROW LastVisibleRow(SCROW nStartRow, SCROW nEndRow, SCTAB nTab) const
Definition: document.cxx:4461
SC_DLLPUBLIC SCROW FirstVisibleRow(SCROW nStartRow, SCROW nEndRow, SCTAB nTab) const
Definition: document.cxx:4454
virtual void CreateAnchor() override
Definition: select.cxx:820
virtual void BeginDrag() override
Definition: select.cxx:815
virtual void DeselectAtPoint(const Point &rPointPixel) override
Definition: select.cxx:969
virtual void SetCursorAtPoint(const Point &rPointPixel, bool bDontSelectAtCursor=false) override
Definition: select.cxx:846
ScHeaderFunctionSet(ScViewData *pNewViewData)
Definition: select.cxx:795
void SetColumn(bool bSet)
Definition: select.cxx:805
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:810
virtual void DestroyAnchor() override
Definition: select.cxx:840
virtual bool IsSelectionAtPoint(const Point &rPointPixel) override
Definition: select.cxx:955
virtual void DeselectAll() override
Definition: select.cxx:973
ScHeaderSelectionEngine(vcl::Window *pWindow, ScHeaderFunctionSet *pFuncSet)
Definition: select.cxx:979
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:1597
bool IsFormulaMode()
Definition: scmod.cxx:1681
ScAddress aEnd
Definition: address.hxx:498
ScAddress aStart
Definition: address.hxx:497
void UpdateInputHandler(bool bForce=false, bool bStopEditing=true)
Definition: tabvwsha.cxx:690
bool IsRefInputMode() const
Definition: tabvwsha.cxx:634
void InitBlockMode(SCCOL nCurX, SCROW nCurY, SCTAB nCurZ, bool bTestNeg=false, bool bCols=false, bool bRows=false, bool bForceNeg=false)
Definition: tabview2.cxx:453
void FakeButtonUp(ScSplitPos eWhich)
Definition: tabview3.cxx:214
bool IsBlockMode() const
Definition: tabview2.cxx:544
void AlignToCursor(SCCOL nCurX, SCROW nCurY, ScFollowMode eMode, const ScSplitPos *pWhich=nullptr)
Definition: tabview3.cxx:917
void DoneBlockMode(bool bContinue=false)
Definition: tabview2.cxx:509
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:549
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:1130
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:424
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:3146
void GetMouseQuadrant(const Point &rClickPos, ScSplitPos eWhich, SCCOL nPosX, SCROW nPosY, bool &rLeft, bool &rTop)
Definition: viewdata.cxx:2900
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:1417
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:3162
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:2785
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:1182
ScDBFunc * GetView() const
Definition: viewdata.cxx:864
ScSplitPos GetActivePart() const
Definition: viewdata.hxx:398
void ResetOldCursor()
Definition: viewdata.cxx:1398
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:1510
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:1403
void SetRefStart(SCCOL nNewX, SCROW nNewY, SCTAB nNewZ)
Definition: viewdata.cxx:4124
bool SelectionEditable(bool *pOnlyNotBecauseOfMatrix=nullptr)
Definition: viewfunc.cxx:274
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:761
virtual void DeselectAll() override
Definition: select.cxx:766
bool SetCursorAtCell(SCCOL nPosX, SCROW nPosY, bool bScroll)
Definition: select.cxx:437
ScAddress m_aAnchorPos
Definition: select.hxx:48
virtual void CreateAnchor() override
Definition: select.cxx:220
ScViewData * m_pViewData
Definition: select.hxx:43
ScSplitPos GetWhich() const
Definition: select.cxx:55
virtual void BeginDrag() override
Definition: select.cxx:146
void SetAnchorFlag(bool bSet)
Definition: select.cxx:289
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
virtual void SetCursorAtPoint(const Point &rPointPixel, bool bDontSelectAtCursor=false) override
Definition: select.cxx:294
bool CheckRefBounds(SCCOL nPosX, SCROW nPosY)
Definition: select.cxx:426
ScViewSelectionEngine * m_pEngine
Definition: select.hxx:44
virtual bool IsSelectionAtPoint(const Point &rPointPixel) override
Definition: select.cxx:740
ScSplitPos GetWhich() const
Definition: select.hxx:36
ScViewSelectionEngine(vcl::Window *pWindow, ScTabView *pView, ScSplitPos eSplitPos)
Definition: select.cxx:785
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:2720
@ SCDOCMODE_CLIP
Definition: document.hxx:257
sal_uInt16 nScFillModeMouseModifier
Definition: global.cxx:118
constexpr sal_uInt16 KEY_MOD1
int i
long Long
#define SC_MOD()
Definition: scmod.hxx:247
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