LCOV - code coverage report
Current view: top level - sc/source/ui/view - select.cxx (source / functions) Hit Total Coverage
Test: commit e02a6cb2c3e2b23b203b422e4e0680877f232636 Lines: 0 466 0.0 %
Date: 2014-04-14 Functions: 0 28 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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 <vcl/svapp.hxx>
      22             : #include <sfx2/docfile.hxx>
      23             : 
      24             : #include "select.hxx"
      25             : #include "sc.hrc"
      26             : #include "tabvwsh.hxx"
      27             : #include "scmod.hxx"
      28             : #include "document.hxx"
      29             : #include "transobj.hxx"
      30             : #include "docsh.hxx"
      31             : #include "tabprotection.hxx"
      32             : #include "markdata.hxx"
      33             : 
      34             : #if defined WNT
      35             : #define SC_SELENG_REFMODE_UPDATE_INTERVAL_MIN 65
      36             : #endif
      37             : 
      38             : extern sal_uInt16 nScFillModeMouseModifier;             // global.cxx
      39             : 
      40             : using namespace com::sun::star;
      41             : 
      42             : // STATIC DATA -----------------------------------------------------------
      43             : 
      44           0 : static Point aSwitchPos;                //! Member
      45             : static bool bDidSwitch = false;
      46             : 
      47             : // View (Gridwin / keyboard)
      48           0 : ScViewFunctionSet::ScViewFunctionSet( ScViewData* pNewViewData ) :
      49             :         pViewData( pNewViewData ),
      50             :         pEngine( NULL ),
      51             :         bAnchor( false ),
      52           0 :         bStarted( false )
      53             : {
      54             :     OSL_ENSURE(pViewData, "ViewData==0 at FunctionSet");
      55           0 : }
      56             : 
      57           0 : ScSplitPos ScViewFunctionSet::GetWhich()
      58             : {
      59           0 :     if (pEngine)
      60           0 :         return pEngine->GetWhich();
      61             :     else
      62           0 :         return pViewData->GetActivePart();
      63             : }
      64             : 
      65           0 : sal_uLong ScViewFunctionSet::CalcUpdateInterval( const Size& rWinSize, const Point& rEffPos,
      66             :                                              bool bLeftScroll, bool bTopScroll, bool bRightScroll, bool bBottomScroll )
      67             : {
      68           0 :     sal_uLong nUpdateInterval = SELENG_AUTOREPEAT_INTERVAL_MAX;
      69           0 :     Window* pWin = pEngine->GetWindow();
      70           0 :     Rectangle aScrRect = pWin->GetDesktopRectPixel();
      71           0 :     Point aRootPos = pWin->OutputToAbsoluteScreenPixel(Point(0,0));
      72           0 :     if (bRightScroll)
      73             :     {
      74           0 :         double nWinRight = rWinSize.getWidth() + aRootPos.getX();
      75           0 :         double nMarginRight = aScrRect.GetWidth() - nWinRight;
      76           0 :         double nHOffset = rEffPos.X() - rWinSize.Width();
      77           0 :         double nHAccelRate = nHOffset / nMarginRight;
      78             : 
      79           0 :         if (nHAccelRate > 1.0)
      80           0 :             nHAccelRate = 1.0;
      81             : 
      82           0 :         nUpdateInterval = static_cast<sal_uLong>(SELENG_AUTOREPEAT_INTERVAL_MAX*(1.0 - nHAccelRate));
      83             :     }
      84             : 
      85           0 :     if (bLeftScroll)
      86             :     {
      87           0 :         double nMarginLeft = aRootPos.getX();
      88           0 :         double nHOffset = -rEffPos.X();
      89           0 :         double nHAccelRate = nHOffset / nMarginLeft;
      90             : 
      91           0 :         if (nHAccelRate > 1.0)
      92           0 :             nHAccelRate = 1.0;
      93             : 
      94           0 :         sal_uLong nTmp = static_cast<sal_uLong>(SELENG_AUTOREPEAT_INTERVAL_MAX*(1.0 - nHAccelRate));
      95           0 :         if (nUpdateInterval > nTmp)
      96           0 :             nUpdateInterval = nTmp;
      97             :     }
      98             : 
      99           0 :     if (bBottomScroll)
     100             :     {
     101           0 :         double nWinBottom = rWinSize.getHeight() + aRootPos.getY();
     102           0 :         double nMarginBottom = aScrRect.GetHeight() - nWinBottom;
     103           0 :         double nVOffset = rEffPos.Y() - rWinSize.Height();
     104           0 :         double nVAccelRate = nVOffset / nMarginBottom;
     105             : 
     106           0 :         if (nVAccelRate > 1.0)
     107           0 :             nVAccelRate = 1.0;
     108             : 
     109           0 :         sal_uLong nTmp = static_cast<sal_uLong>(SELENG_AUTOREPEAT_INTERVAL_MAX*(1.0 - nVAccelRate));
     110           0 :         if (nUpdateInterval > nTmp)
     111           0 :             nUpdateInterval = nTmp;
     112             :     }
     113             : 
     114           0 :     if (bTopScroll)
     115             :     {
     116           0 :         double nMarginTop = aRootPos.getY();
     117           0 :         double nVOffset = -rEffPos.Y();
     118           0 :         double nVAccelRate = nVOffset / nMarginTop;
     119             : 
     120           0 :         if (nVAccelRate > 1.0)
     121           0 :             nVAccelRate = 1.0;
     122             : 
     123           0 :         sal_uLong nTmp = static_cast<sal_uLong>(SELENG_AUTOREPEAT_INTERVAL_MAX*(1.0 - nVAccelRate));
     124           0 :         if (nUpdateInterval > nTmp)
     125           0 :             nUpdateInterval = nTmp;
     126             :     }
     127             : 
     128             : #ifdef WNT
     129             :     ScTabViewShell* pViewShell = pViewData->GetViewShell();
     130             :     bool bRefMode = pViewShell && pViewShell->IsRefInputMode();
     131             :     if (bRefMode && nUpdateInterval < SC_SELENG_REFMODE_UPDATE_INTERVAL_MIN)
     132             :         // Lower the update interval during ref mode, because re-draw can be
     133             :         // expensive on Windows.  Making this interval too small would queue up
     134             :         // the scroll/paint requests which would cause semi-infinite
     135             :         // scrolls even after the mouse cursor is released.  We don't have
     136             :         // this problem on Linux.
     137             :         nUpdateInterval = SC_SELENG_REFMODE_UPDATE_INTERVAL_MIN;
     138             : #endif
     139           0 :     return nUpdateInterval;
     140             : }
     141             : 
     142           0 : void ScViewFunctionSet::SetSelectionEngine( ScViewSelectionEngine* pSelEngine )
     143             : {
     144           0 :     pEngine = pSelEngine;
     145           0 : }
     146             : 
     147             : // Drag & Drop
     148           0 : void ScViewFunctionSet::BeginDrag()
     149             : {
     150           0 :     SCTAB nTab = pViewData->GetTabNo();
     151             : 
     152             :     SCsCOL nPosX;
     153             :     SCsROW nPosY;
     154           0 :     if (pEngine)
     155             :     {
     156           0 :         Point aMPos = pEngine->GetMousePosPixel();
     157           0 :         pViewData->GetPosFromPixel( aMPos.X(), aMPos.Y(), GetWhich(), nPosX, nPosY );
     158             :     }
     159             :     else
     160             :     {
     161           0 :         nPosX = pViewData->GetCurX();
     162           0 :         nPosY = pViewData->GetCurY();
     163             :     }
     164             : 
     165           0 :     ScModule* pScMod = SC_MOD();
     166           0 :     bool bRefMode = pScMod->IsFormulaMode();
     167           0 :     if (!bRefMode)
     168             :     {
     169           0 :         pViewData->GetView()->FakeButtonUp( GetWhich() );   // ButtonUp is swallowed
     170             : 
     171           0 :         ScMarkData& rMark = pViewData->GetMarkData();
     172           0 :         rMark.MarkToSimple();
     173           0 :         if ( rMark.IsMarked() && !rMark.IsMultiMarked() )
     174             :         {
     175           0 :             ScDocument* pClipDoc = new ScDocument( SCDOCMODE_CLIP );
     176             :             // bApi = TRUE -> no error messages
     177           0 :             bool bCopied = pViewData->GetView()->CopyToClip( pClipDoc, false, true );
     178           0 :             if ( bCopied )
     179             :             {
     180           0 :                 sal_Int8 nDragActions = pViewData->GetView()->SelectionEditable() ?
     181             :                                         ( DND_ACTION_COPYMOVE | DND_ACTION_LINK ) :
     182           0 :                                         ( DND_ACTION_COPY | DND_ACTION_LINK );
     183             : 
     184           0 :                 ScDocShell* pDocSh = pViewData->GetDocShell();
     185           0 :                 TransferableObjectDescriptor aObjDesc;
     186           0 :                 pDocSh->FillTransferableObjectDescriptor( aObjDesc );
     187           0 :                 aObjDesc.maDisplayName = pDocSh->GetMedium()->GetURLObject().GetURLNoPass();
     188             :                 // maSize is set in ScTransferObj ctor
     189             : 
     190           0 :                 ScTransferObj* pTransferObj = new ScTransferObj( pClipDoc, aObjDesc );
     191           0 :                 uno::Reference<datatransfer::XTransferable> xTransferable( pTransferObj );
     192             : 
     193             :                 // set position of dragged cell within range
     194           0 :                 ScRange aMarkRange = pTransferObj->GetRange();
     195           0 :                 SCCOL nStartX = aMarkRange.aStart.Col();
     196           0 :                 SCROW nStartY = aMarkRange.aStart.Row();
     197           0 :                 SCCOL nHandleX = (nPosX >= (SCsCOL) nStartX) ? nPosX - nStartX : 0;
     198           0 :                 SCROW nHandleY = (nPosY >= (SCsROW) nStartY) ? nPosY - nStartY : 0;
     199           0 :                 pTransferObj->SetDragHandlePos( nHandleX, nHandleY );
     200           0 :                 pTransferObj->SetVisibleTab( nTab );
     201             : 
     202           0 :                 pTransferObj->SetDragSource( pDocSh, rMark );
     203             : 
     204           0 :                 Window* pWindow = pViewData->GetActiveWin();
     205           0 :                 if ( pWindow->IsTracking() )
     206           0 :                     pWindow->EndTracking( ENDTRACK_CANCEL );    // abort selecting
     207             : 
     208           0 :                 SC_MOD()->SetDragObject( pTransferObj, NULL );      // for internal D&D
     209           0 :                 pTransferObj->StartDrag( pWindow, nDragActions );
     210             : 
     211           0 :                 return;         // dragging started
     212             :             }
     213             :             else
     214           0 :                 delete pClipDoc;
     215             :         }
     216             :     }
     217             : 
     218             : }
     219             : 
     220             : // Selection
     221           0 : void ScViewFunctionSet::CreateAnchor()
     222             : {
     223           0 :     if (bAnchor) return;
     224             : 
     225           0 :     bool bRefMode = SC_MOD()->IsFormulaMode();
     226           0 :     if (bRefMode)
     227           0 :         SetAnchor( pViewData->GetRefStartX(), pViewData->GetRefStartY() );
     228             :     else
     229           0 :         SetAnchor( pViewData->GetCurX(), pViewData->GetCurY() );
     230             : }
     231             : 
     232           0 : void ScViewFunctionSet::SetAnchor( SCCOL nPosX, SCROW nPosY )
     233             : {
     234           0 :     bool bRefMode = SC_MOD()->IsFormulaMode();
     235           0 :     ScTabView* pView = pViewData->GetView();
     236           0 :     SCTAB nTab = pViewData->GetTabNo();
     237             : 
     238           0 :     if (bRefMode)
     239             :     {
     240           0 :         pView->DoneRefMode( false );
     241           0 :         aAnchorPos.Set( nPosX, nPosY, nTab );
     242           0 :         pView->InitRefMode( aAnchorPos.Col(), aAnchorPos.Row(), aAnchorPos.Tab(),
     243           0 :                             SC_REFTYPE_REF );
     244           0 :         bStarted = true;
     245             :     }
     246           0 :     else if (pViewData->IsAnyFillMode())
     247             :     {
     248           0 :         aAnchorPos.Set( nPosX, nPosY, nTab );
     249           0 :         bStarted = true;
     250             :     }
     251             :     else
     252             :     {
     253             :         // don't go there and back again
     254           0 :         if ( bStarted && pView->IsMarking( nPosX, nPosY, nTab ) )
     255             :         {
     256             :             // don't do anything
     257             :         }
     258             :         else
     259             :         {
     260           0 :             pView->DoneBlockMode( true );
     261           0 :             aAnchorPos.Set( nPosX, nPosY, nTab );
     262           0 :             ScMarkData& rMark = pViewData->GetMarkData();
     263           0 :             if ( rMark.IsMarked() || rMark.IsMultiMarked() )
     264             :             {
     265           0 :                 pView->InitBlockMode( aAnchorPos.Col(), aAnchorPos.Row(),
     266           0 :                                         aAnchorPos.Tab(), true );
     267           0 :                 bStarted = true;
     268             :             }
     269             :             else
     270           0 :                 bStarted = false;
     271             :         }
     272             :     }
     273           0 :     bAnchor = true;
     274           0 : }
     275             : 
     276           0 : void ScViewFunctionSet::DestroyAnchor()
     277             : {
     278           0 :     bool bRefMode = SC_MOD()->IsFormulaMode();
     279           0 :     if (bRefMode)
     280           0 :         pViewData->GetView()->DoneRefMode( true );
     281             :     else
     282           0 :         pViewData->GetView()->DoneBlockMode( true );
     283             : 
     284           0 :     bAnchor = false;
     285           0 : }
     286             : 
     287           0 : void ScViewFunctionSet::SetAnchorFlag( bool bSet )
     288             : {
     289           0 :     bAnchor = bSet;
     290           0 : }
     291             : 
     292           0 : bool ScViewFunctionSet::SetCursorAtPoint( const Point& rPointPixel, bool /* bDontSelectAtCursor */ )
     293             : {
     294           0 :     if ( bDidSwitch )
     295             :     {
     296           0 :         if ( rPointPixel == aSwitchPos )
     297           0 :             return false;                   // don't scroll in wrong window
     298             :         else
     299           0 :             bDidSwitch = false;
     300             :     }
     301           0 :     aSwitchPos = rPointPixel;       // only important, if bDidSwitch
     302             : 
     303             :     //  treat position 0 as -1, so scrolling is always possible
     304             :     //  (with full screen and hidden headers, the top left border may be at 0)
     305             :     //  (moved from ScViewData::GetPosFromPixel)
     306             : 
     307           0 :     Point aEffPos = rPointPixel;
     308           0 :     if ( aEffPos.X() == 0 )
     309           0 :         aEffPos.X() = -1;
     310           0 :     if ( aEffPos.Y() == 0 )
     311           0 :         aEffPos.Y() = -1;
     312             : 
     313             :     //  Scrolling
     314           0 :     Size aWinSize = pEngine->GetWindow()->GetOutputSizePixel();
     315           0 :     bool bRightScroll  = ( aEffPos.X() >= aWinSize.Width() );
     316           0 :     bool bLeftScroll  = ( aEffPos.X() < 0 );
     317           0 :     bool bBottomScroll = ( aEffPos.Y() >= aWinSize.Height() );
     318           0 :     bool bTopScroll = ( aEffPos.Y() < 0 );
     319           0 :     bool bScroll = bRightScroll || bBottomScroll || bLeftScroll || bTopScroll;
     320             : 
     321             :     SCsCOL  nPosX;
     322             :     SCsROW  nPosY;
     323           0 :     pViewData->GetPosFromPixel( aEffPos.X(), aEffPos.Y(), GetWhich(),
     324           0 :                                 nPosX, nPosY, true, true );     // with Repair
     325             : 
     326             :     // for Autofill switch in the center of cell
     327             :     // thereby don't prevent scrolling to bottom/right
     328           0 :     if ( pViewData->IsFillMode() || pViewData->GetFillMode() == SC_FILL_MATRIX )
     329             :     {
     330             :         bool bLeft, bTop;
     331           0 :         pViewData->GetMouseQuadrant( aEffPos, GetWhich(), nPosX, nPosY, bLeft, bTop );
     332           0 :         ScDocument* pDoc = pViewData->GetDocument();
     333           0 :         SCTAB nTab = pViewData->GetTabNo();
     334           0 :         if ( bLeft && !bRightScroll )
     335           0 :             do --nPosX; while ( nPosX>=0 && pDoc->ColHidden( nPosX, nTab ) );
     336           0 :         if ( bTop && !bBottomScroll )
     337             :         {
     338           0 :             if (--nPosY >= 0)
     339             :             {
     340           0 :                 nPosY = pDoc->LastVisibleRow(0, nPosY, nTab);
     341           0 :                 if (!ValidRow(nPosY))
     342           0 :                     nPosY = -1;
     343             :             }
     344             :         }
     345             :         // negative value is allowed
     346             :     }
     347             : 
     348             :     // moved out of fix limit?
     349           0 :     ScSplitPos eWhich = GetWhich();
     350           0 :     if ( eWhich == pViewData->GetActivePart() )
     351             :     {
     352           0 :         if ( pViewData->GetHSplitMode() == SC_SPLIT_FIX )
     353           0 :             if ( aEffPos.X() >= aWinSize.Width() )
     354             :             {
     355           0 :                 if ( eWhich == SC_SPLIT_TOPLEFT )
     356           0 :                     pViewData->GetView()->ActivatePart( SC_SPLIT_TOPRIGHT ), bScroll = false, bDidSwitch = true;
     357           0 :                 else if ( eWhich == SC_SPLIT_BOTTOMLEFT )
     358           0 :                     pViewData->GetView()->ActivatePart( SC_SPLIT_BOTTOMRIGHT ), bScroll = false, bDidSwitch = true;
     359             :             }
     360             : 
     361           0 :         if ( pViewData->GetVSplitMode() == SC_SPLIT_FIX )
     362           0 :             if ( aEffPos.Y() >= aWinSize.Height() )
     363             :             {
     364           0 :                 if ( eWhich == SC_SPLIT_TOPLEFT )
     365           0 :                     pViewData->GetView()->ActivatePart( SC_SPLIT_BOTTOMLEFT ), bScroll = false, bDidSwitch = true;
     366           0 :                 else if ( eWhich == SC_SPLIT_TOPRIGHT )
     367           0 :                     pViewData->GetView()->ActivatePart( SC_SPLIT_BOTTOMRIGHT ), bScroll = false, bDidSwitch = true;
     368             :             }
     369             :     }
     370             : 
     371           0 :     if (bScroll)
     372             :     {
     373             :         // Adjust update interval based on how far the mouse pointer is from the edge.
     374             :         sal_uLong nUpdateInterval = CalcUpdateInterval(
     375           0 :             aWinSize, aEffPos, bLeftScroll, bTopScroll, bRightScroll, bBottomScroll);
     376           0 :         pEngine->SetUpdateInterval(nUpdateInterval);
     377             :     }
     378             :     else
     379             :     {
     380             :         // Don't forget to reset the interval when not scrolling!
     381           0 :         pEngine->SetUpdateInterval(SELENG_AUTOREPEAT_INTERVAL);
     382             :     }
     383             : 
     384           0 :     pViewData->ResetOldCursor();
     385           0 :     return SetCursorAtCell( nPosX, nPosY, bScroll );
     386             : }
     387             : 
     388           0 : bool ScViewFunctionSet::SetCursorAtCell( SCsCOL nPosX, SCsROW nPosY, bool bScroll )
     389             : {
     390           0 :     ScTabView* pView = pViewData->GetView();
     391           0 :     SCTAB nTab = pViewData->GetTabNo();
     392           0 :     ScDocument* pDoc = pViewData->GetDocument();
     393             : 
     394           0 :     if ( pDoc->IsTabProtected(nTab) )
     395             :     {
     396           0 :         if (nPosX < 0 || nPosY < 0)
     397           0 :             return false;
     398             : 
     399           0 :         ScTableProtection* pProtect = pDoc->GetTabProtection(nTab);
     400           0 :         if (!pProtect)
     401           0 :             return false;
     402             : 
     403           0 :         bool bSkipProtected   = !pProtect->isOptionEnabled(ScTableProtection::SELECT_LOCKED_CELLS);
     404           0 :         bool bSkipUnprotected = !pProtect->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS);
     405             : 
     406           0 :         if ( bSkipProtected && bSkipUnprotected )
     407           0 :             return false;
     408             : 
     409           0 :         bool bCellProtected = pDoc->HasAttrib(nPosX, nPosY, nTab, nPosX, nPosY, nTab, HASATTR_PROTECTED);
     410           0 :         if ( (bCellProtected && bSkipProtected) || (!bCellProtected && bSkipUnprotected) )
     411             :             // Don't select this cell!
     412           0 :             return false;
     413             :     }
     414             : 
     415           0 :     ScModule* pScMod = SC_MOD();
     416           0 :     ScTabViewShell* pViewShell = pViewData->GetViewShell();
     417           0 :     bool bRefMode = ( pViewShell ? pViewShell->IsRefInputMode() : false );
     418             : 
     419           0 :     bool bHide = !bRefMode && !pViewData->IsAnyFillMode() &&
     420           0 :             ( nPosX != (SCsCOL) pViewData->GetCurX() || nPosY != (SCsROW) pViewData->GetCurY() );
     421             : 
     422           0 :     if (bHide)
     423           0 :         pView->HideAllCursors();
     424             : 
     425           0 :     if (bScroll)
     426             :     {
     427           0 :         if (bRefMode)
     428             :         {
     429           0 :             ScSplitPos eWhich = GetWhich();
     430           0 :             pView->AlignToCursor( nPosX, nPosY, SC_FOLLOW_LINE, &eWhich );
     431             :         }
     432             :         else
     433           0 :             pView->AlignToCursor( nPosX, nPosY, SC_FOLLOW_LINE );
     434             :     }
     435             : 
     436           0 :     if (bRefMode)
     437             :     {
     438             :         // if no input is possible from this doc, don't move the reference cursor around
     439           0 :         if ( !pScMod->IsModalMode(pViewData->GetSfxDocShell()) )
     440             :         {
     441           0 :             if (!bAnchor)
     442             :             {
     443           0 :                 pView->DoneRefMode( true );
     444           0 :                 pView->InitRefMode( nPosX, nPosY, pViewData->GetTabNo(), SC_REFTYPE_REF );
     445             :             }
     446             : 
     447           0 :             pView->UpdateRef( nPosX, nPosY, pViewData->GetTabNo() );
     448           0 :             pView->SelectionChanged();
     449             :         }
     450             :     }
     451           0 :     else if (pViewData->IsFillMode() ||
     452           0 :             (pViewData->GetFillMode() == SC_FILL_MATRIX && (nScFillModeMouseModifier & KEY_MOD1) ))
     453             :     {
     454             :         // If a matrix got touched, switch back to Autofill is possible with Ctrl
     455             : 
     456             :         SCCOL nStartX, nEndX;
     457             :         SCROW nStartY, nEndY; // Block
     458             :         SCTAB nDummy;
     459           0 :         pViewData->GetSimpleArea( nStartX, nStartY, nDummy, nEndX, nEndY, nDummy );
     460             : 
     461           0 :         if (pViewData->GetRefType() != SC_REFTYPE_FILL)
     462             :         {
     463           0 :             pView->InitRefMode( nStartX, nStartY, nTab, SC_REFTYPE_FILL );
     464           0 :             CreateAnchor();
     465             :         }
     466             : 
     467           0 :         ScRange aDelRange;
     468           0 :         bool bOldDelMark = pViewData->GetDelMark( aDelRange );
     469             : 
     470           0 :         if ( nPosX+1 >= (SCsCOL) nStartX && nPosX <= (SCsCOL) nEndX &&
     471           0 :              nPosY+1 >= (SCsROW) nStartY && nPosY <= (SCsROW) nEndY &&
     472           0 :              ( nPosX != nEndX || nPosY != nEndY ) )                     // minimize?
     473             :         {
     474             :             // direction (left or top)
     475             : 
     476           0 :             long nSizeX = 0;
     477           0 :             for (SCCOL i=nPosX+1; i<=nEndX; i++)
     478           0 :                 nSizeX += pDoc->GetColWidth( i, nTab );
     479           0 :             long nSizeY = (long) pDoc->GetRowHeight( nPosY+1, nEndY, nTab );
     480             : 
     481           0 :             SCCOL nDelStartX = nStartX;
     482           0 :             SCROW nDelStartY = nStartY;
     483           0 :             if ( nSizeX > nSizeY )
     484           0 :                 nDelStartX = nPosX + 1;
     485             :             else
     486           0 :                 nDelStartY = nPosY + 1;
     487             :             // there is no need to check for zero, because nPosX/Y is also negative
     488             : 
     489           0 :             if ( nDelStartX < nStartX )
     490           0 :                 nDelStartX = nStartX;
     491           0 :             if ( nDelStartY < nStartY )
     492           0 :                 nDelStartY = nStartY;
     493             : 
     494             :             // set range
     495             : 
     496             :             pViewData->SetDelMark( ScRange( nDelStartX,nDelStartY,nTab,
     497           0 :                                             nEndX,nEndY,nTab ) );
     498           0 :             pViewData->GetView()->UpdateShrinkOverlay();
     499             : 
     500           0 :             pViewData->GetView()->
     501           0 :                 PaintArea( nStartX,nDelStartY, nEndX,nEndY, SC_UPDATE_MARKS );
     502             : 
     503           0 :             nPosX = nEndX;      // keep red border around range
     504           0 :             nPosY = nEndY;
     505             : 
     506             :             // reference the right way up, if it's upside down below
     507           0 :             if ( nStartX != pViewData->GetRefStartX() || nStartY != pViewData->GetRefStartY() )
     508             :             {
     509           0 :                 pViewData->GetView()->DoneRefMode();
     510           0 :                 pViewData->GetView()->InitRefMode( nStartX, nStartY, nTab, SC_REFTYPE_FILL );
     511           0 :             }
     512             :         }
     513             :         else
     514             :         {
     515           0 :             if ( bOldDelMark )
     516             :             {
     517           0 :                 pViewData->ResetDelMark();
     518           0 :                 pViewData->GetView()->UpdateShrinkOverlay();
     519             :             }
     520             : 
     521           0 :             bool bNegX = ( nPosX < (SCsCOL) nStartX );
     522           0 :             bool bNegY = ( nPosY < (SCsROW) nStartY );
     523             : 
     524           0 :             long nSizeX = 0;
     525           0 :             if ( bNegX )
     526             :             {
     527             :                 //  in SetCursorAtPoint hidden columns are skipped.
     528             :                 //  They must be skipped here too, or the result will always be the first hidden column.
     529           0 :                 do ++nPosX; while ( nPosX<nStartX && pDoc->ColHidden(nPosX, nTab) );
     530           0 :                 for (SCCOL i=nPosX; i<nStartX; i++)
     531           0 :                     nSizeX += pDoc->GetColWidth( i, nTab );
     532             :             }
     533             :             else
     534           0 :                 for (SCCOL i=nEndX+1; i<=nPosX; i++)
     535           0 :                     nSizeX += pDoc->GetColWidth( i, nTab );
     536             : 
     537           0 :             long nSizeY = 0;
     538           0 :             if ( bNegY )
     539             :             {
     540             :                 //  in SetCursorAtPoint hidden rows are skipped.
     541             :                 //  They must be skipped here too, or the result will always be the first hidden row.
     542           0 :                 if (++nPosY < nStartY)
     543             :                 {
     544           0 :                     nPosY = pDoc->FirstVisibleRow(nPosY, nStartY-1, nTab);
     545           0 :                     if (!ValidRow(nPosY))
     546           0 :                         nPosY = nStartY;
     547             :                 }
     548           0 :                 nSizeY += pDoc->GetRowHeight( nPosY, nStartY-1, nTab );
     549             :             }
     550             :             else
     551           0 :                 nSizeY += pDoc->GetRowHeight( nEndY+1, nPosY, nTab );
     552             : 
     553           0 :             if ( nSizeX > nSizeY )          // Fill only ever in one direction
     554             :             {
     555           0 :                 nPosY = nEndY;
     556           0 :                 bNegY = false;
     557             :             }
     558             :             else
     559             :             {
     560           0 :                 nPosX = nEndX;
     561           0 :                 bNegX = false;
     562             :             }
     563             : 
     564           0 :             SCCOL nRefStX = bNegX ? nEndX : nStartX;
     565           0 :             SCROW nRefStY = bNegY ? nEndY : nStartY;
     566           0 :             if ( nRefStX != pViewData->GetRefStartX() || nRefStY != pViewData->GetRefStartY() )
     567             :             {
     568           0 :                 pViewData->GetView()->DoneRefMode();
     569           0 :                 pViewData->GetView()->InitRefMode( nRefStX, nRefStY, nTab, SC_REFTYPE_FILL );
     570             :             }
     571             :         }
     572             : 
     573           0 :         pView->UpdateRef( nPosX, nPosY, nTab );
     574             :     }
     575           0 :     else if (pViewData->IsAnyFillMode())
     576             :     {
     577           0 :         sal_uInt8 nMode = pViewData->GetFillMode();
     578           0 :         if ( nMode == SC_FILL_EMBED_LT || nMode == SC_FILL_EMBED_RB )
     579             :         {
     580             :             OSL_ENSURE( pDoc->IsEmbedded(), "!pDoc->IsEmbedded()" );
     581           0 :             ScRange aRange;
     582           0 :             pDoc->GetEmbedded( aRange);
     583           0 :             ScRefType eRefMode = (nMode == SC_FILL_EMBED_LT) ? SC_REFTYPE_EMBED_LT : SC_REFTYPE_EMBED_RB;
     584           0 :             if (pViewData->GetRefType() != eRefMode)
     585             :             {
     586           0 :                 if ( nMode == SC_FILL_EMBED_LT )
     587           0 :                     pView->InitRefMode( aRange.aEnd.Col(), aRange.aEnd.Row(), nTab, eRefMode );
     588             :                 else
     589           0 :                     pView->InitRefMode( aRange.aStart.Col(), aRange.aStart.Row(), nTab, eRefMode );
     590           0 :                 CreateAnchor();
     591             :             }
     592             : 
     593           0 :             pView->UpdateRef( nPosX, nPosY, nTab );
     594             :         }
     595           0 :         else if ( nMode == SC_FILL_MATRIX )
     596             :         {
     597             :             SCCOL nStartX, nEndX;
     598             :             SCROW nStartY, nEndY; // Block
     599             :             SCTAB nDummy;
     600           0 :             pViewData->GetSimpleArea( nStartX, nStartY, nDummy, nEndX, nEndY, nDummy );
     601             : 
     602           0 :             if (pViewData->GetRefType() != SC_REFTYPE_FILL)
     603             :             {
     604           0 :                 pView->InitRefMode( nStartX, nStartY, nTab, SC_REFTYPE_FILL );
     605           0 :                 CreateAnchor();
     606             :             }
     607             : 
     608           0 :             if ( nPosX < nStartX ) nPosX = nStartX;
     609           0 :             if ( nPosY < nStartY ) nPosY = nStartY;
     610             : 
     611           0 :             pView->UpdateRef( nPosX, nPosY, nTab );
     612             :         }
     613             :         // else new modes
     614             :     }
     615             :     else                    // regular selection
     616             :     {
     617           0 :         bool bHideCur = bAnchor && ( (SCCOL)nPosX != pViewData->GetCurX() ||
     618           0 :                                      (SCROW)nPosY != pViewData->GetCurY() );
     619           0 :         if (bHideCur)
     620           0 :             pView->HideAllCursors();            // otherwise twice: Block and SetCursor
     621             : 
     622           0 :         if (bAnchor)
     623             :         {
     624           0 :             if (!bStarted)
     625             :             {
     626           0 :                 bool bMove = ( nPosX != (SCsCOL) aAnchorPos.Col() ||
     627           0 :                                 nPosY != (SCsROW) aAnchorPos.Row() );
     628           0 :                 if ( bMove || ( pEngine && pEngine->GetMouseEvent().IsShift() ) )
     629             :                 {
     630           0 :                     pView->InitBlockMode( aAnchorPos.Col(), aAnchorPos.Row(),
     631           0 :                                             aAnchorPos.Tab(), true );
     632           0 :                     bStarted = true;
     633             :                 }
     634             :             }
     635           0 :             if (bStarted)
     636             :                 // If the selection is already started, don't set the cursor.
     637           0 :                 pView->MarkCursor( (SCCOL) nPosX, (SCROW) nPosY, nTab, false, false, true );
     638             :             else
     639           0 :                 pView->SetCursor( (SCCOL) nPosX, (SCROW) nPosY );
     640             :         }
     641             :         else
     642             :         {
     643           0 :             ScMarkData& rMark = pViewData->GetMarkData();
     644           0 :             if (rMark.IsMarked() || rMark.IsMultiMarked())
     645             :             {
     646           0 :                 pView->DoneBlockMode(true);
     647           0 :                 pView->InitBlockMode( nPosX, nPosY, nTab, true );
     648           0 :                 pView->MarkCursor( (SCCOL) nPosX, (SCROW) nPosY, nTab );
     649             : 
     650           0 :                 aAnchorPos.Set( nPosX, nPosY, nTab );
     651           0 :                 bStarted = true;
     652             :             }
     653             :             // #i3875# *Hack* When a new cell is Ctrl-clicked with no pre-selected cells,
     654             :             // it highlights that new cell as well as the old cell where the cursor is
     655             :             // positioned prior to the click.  A selection mode via Shift-F8 should also
     656             :             // follow the same behavior.
     657           0 :             else if ( pViewData->IsSelCtrlMouseClick() )
     658             :             {
     659           0 :                 SCCOL nOldX = pViewData->GetCurX();
     660           0 :                 SCROW nOldY = pViewData->GetCurY();
     661             : 
     662           0 :                 pView->InitBlockMode( nOldX, nOldY, nTab, true );
     663           0 :                 pView->MarkCursor( (SCCOL) nOldX, (SCROW) nOldY, nTab );
     664             : 
     665           0 :                 if ( nOldX != nPosX || nOldY != nPosY )
     666             :                 {
     667           0 :                     pView->DoneBlockMode( true );
     668           0 :                     pView->InitBlockMode( nPosX, nPosY, nTab, true );
     669           0 :                     pView->MarkCursor( (SCCOL) nPosX, (SCROW) nPosY, nTab );
     670           0 :                     aAnchorPos.Set( nPosX, nPosY, nTab );
     671             :                 }
     672             : 
     673           0 :                 bStarted = true;
     674             :             }
     675           0 :             pView->SetCursor( (SCCOL) nPosX, (SCROW) nPosY );
     676             :         }
     677             : 
     678           0 :         pViewData->SetRefStart( nPosX, nPosY, nTab );
     679           0 :         if (bHideCur)
     680           0 :             pView->ShowAllCursors();
     681             :     }
     682             : 
     683           0 :     if (bHide)
     684           0 :         pView->ShowAllCursors();
     685             : 
     686           0 :     return true;
     687             : }
     688             : 
     689           0 : bool ScViewFunctionSet::IsSelectionAtPoint( const Point& rPointPixel )
     690             : {
     691           0 :     bool bRefMode = SC_MOD()->IsFormulaMode();
     692           0 :     if (bRefMode)
     693           0 :         return false;
     694             : 
     695           0 :     if (pViewData->IsAnyFillMode())
     696           0 :         return false;
     697             : 
     698           0 :     ScMarkData& rMark = pViewData->GetMarkData();
     699           0 :     if (bAnchor || !rMark.IsMultiMarked())
     700             :     {
     701             :         SCsCOL  nPosX;
     702             :         SCsROW  nPosY;
     703           0 :         pViewData->GetPosFromPixel( rPointPixel.X(), rPointPixel.Y(), GetWhich(), nPosX, nPosY );
     704           0 :         return pViewData->GetMarkData().IsCellMarked( (SCCOL) nPosX, (SCROW) nPosY );
     705             :     }
     706             : 
     707           0 :     return false;
     708             : }
     709             : 
     710           0 : void ScViewFunctionSet::DeselectAtPoint( const Point& /* rPointPixel */ )
     711             : {
     712             :     // doesn't exist
     713           0 : }
     714             : 
     715           0 : void ScViewFunctionSet::DeselectAll()
     716             : {
     717           0 :     if (pViewData->IsAnyFillMode())
     718           0 :         return;
     719             : 
     720           0 :     bool bRefMode = SC_MOD()->IsFormulaMode();
     721           0 :     if (bRefMode)
     722             :     {
     723           0 :         pViewData->GetView()->DoneRefMode( false );
     724             :     }
     725             :     else
     726             :     {
     727           0 :         pViewData->GetView()->DoneBlockMode( false );
     728           0 :         pViewData->GetViewShell()->UpdateInputHandler();
     729             :     }
     730             : 
     731           0 :     bAnchor = false;
     732             : }
     733             : 
     734           0 : ScViewSelectionEngine::ScViewSelectionEngine( Window* pWindow, ScTabView* pView,
     735             :                                                 ScSplitPos eSplitPos ) :
     736           0 :         SelectionEngine( pWindow, pView->GetFunctionSet() ),
     737           0 :         eWhich( eSplitPos )
     738             : {
     739           0 :     SetSelectionMode( MULTIPLE_SELECTION );
     740           0 :     EnableDrag( true );
     741           0 : }
     742             : 
     743             : // column and row headers
     744           0 : ScHeaderFunctionSet::ScHeaderFunctionSet( ScViewData* pNewViewData ) :
     745             :         pViewData( pNewViewData ),
     746             :         bColumn( false ),
     747             :         eWhich( SC_SPLIT_TOPLEFT ),
     748             :         bAnchor( false ),
     749           0 :         nCursorPos( 0 )
     750             : {
     751             :     OSL_ENSURE(pViewData, "ViewData==0 at FunctionSet");
     752           0 : }
     753             : 
     754           0 : void ScHeaderFunctionSet::SetColumn( bool bSet )
     755             : {
     756           0 :     bColumn = bSet;
     757           0 : }
     758             : 
     759           0 : void ScHeaderFunctionSet::SetWhich( ScSplitPos eNew )
     760             : {
     761           0 :     eWhich = eNew;
     762           0 : }
     763             : 
     764           0 : void ScHeaderFunctionSet::BeginDrag()
     765             : {
     766             :     // doesn't exist
     767           0 : }
     768             : 
     769           0 : void ScHeaderFunctionSet::CreateAnchor()
     770             : {
     771           0 :     if (bAnchor)
     772           0 :         return;
     773             : 
     774           0 :     ScTabView* pView = pViewData->GetView();
     775           0 :     pView->DoneBlockMode( true );
     776           0 :     if (bColumn)
     777             :     {
     778           0 :         pView->InitBlockMode( static_cast<SCCOL>(nCursorPos), 0, pViewData->GetTabNo(), true, true, false );
     779           0 :         pView->MarkCursor( static_cast<SCCOL>(nCursorPos), MAXROW, pViewData->GetTabNo() );
     780             :     }
     781             :     else
     782             :     {
     783           0 :         pView->InitBlockMode( 0, nCursorPos, pViewData->GetTabNo(), true, false, true );
     784           0 :         pView->MarkCursor( MAXCOL, nCursorPos, pViewData->GetTabNo() );
     785             :     }
     786           0 :     bAnchor = true;
     787             : }
     788             : 
     789           0 : void ScHeaderFunctionSet::DestroyAnchor()
     790             : {
     791           0 :     pViewData->GetView()->DoneBlockMode( true );
     792           0 :     bAnchor = false;
     793           0 : }
     794             : 
     795           0 : bool ScHeaderFunctionSet::SetCursorAtPoint( const Point& rPointPixel, bool /* bDontSelectAtCursor */ )
     796             : {
     797           0 :     if ( bDidSwitch )
     798             :     {
     799             :         // next valid position has to be originated from another window
     800           0 :         if ( rPointPixel == aSwitchPos )
     801           0 :             return false;                   // don't scroll in the wrong window
     802             :         else
     803           0 :             bDidSwitch = false;
     804             :     }
     805             : 
     806             :     //  Scrolling
     807           0 :     Size aWinSize = pViewData->GetActiveWin()->GetOutputSizePixel();
     808             :     bool bScroll;
     809           0 :     if (bColumn)
     810           0 :         bScroll = ( rPointPixel.X() < 0 || rPointPixel.X() >= aWinSize.Width() );
     811             :     else
     812           0 :         bScroll = ( rPointPixel.Y() < 0 || rPointPixel.Y() >= aWinSize.Height() );
     813             : 
     814             :     // moved out of fix limit?
     815           0 :     bool bSwitched = false;
     816           0 :     if ( bColumn )
     817             :     {
     818           0 :         if ( pViewData->GetHSplitMode() == SC_SPLIT_FIX )
     819             :         {
     820           0 :             if ( rPointPixel.X() > aWinSize.Width() )
     821             :             {
     822           0 :                 if ( eWhich == SC_SPLIT_TOPLEFT )
     823           0 :                     pViewData->GetView()->ActivatePart( SC_SPLIT_TOPRIGHT ), bSwitched = true;
     824           0 :                 else if ( eWhich == SC_SPLIT_BOTTOMLEFT )
     825           0 :                     pViewData->GetView()->ActivatePart( SC_SPLIT_BOTTOMRIGHT ), bSwitched = true;
     826             :             }
     827             :         }
     828             :     }
     829             :     else                // column headers
     830             :     {
     831           0 :         if ( pViewData->GetVSplitMode() == SC_SPLIT_FIX )
     832             :         {
     833           0 :             if ( rPointPixel.Y() > aWinSize.Height() )
     834             :             {
     835           0 :                 if ( eWhich == SC_SPLIT_TOPLEFT )
     836           0 :                     pViewData->GetView()->ActivatePart( SC_SPLIT_BOTTOMLEFT ), bSwitched = true;
     837           0 :                 else if ( eWhich == SC_SPLIT_TOPRIGHT )
     838           0 :                     pViewData->GetView()->ActivatePart( SC_SPLIT_BOTTOMRIGHT ), bSwitched = true;
     839             :             }
     840             :         }
     841             :     }
     842           0 :     if (bSwitched)
     843             :     {
     844           0 :         aSwitchPos = rPointPixel;
     845           0 :         bDidSwitch = true;
     846           0 :         return false;               // do not crunch with wrong positions
     847             :     }
     848             : 
     849             :     SCsCOL  nPosX;
     850             :     SCsROW  nPosY;
     851             :     pViewData->GetPosFromPixel( rPointPixel.X(), rPointPixel.Y(), pViewData->GetActivePart(),
     852           0 :                                 nPosX, nPosY, false );
     853           0 :     if (bColumn)
     854             :     {
     855           0 :         nCursorPos = static_cast<SCCOLROW>(nPosX);
     856           0 :         nPosY = pViewData->GetPosY(WhichV(pViewData->GetActivePart()));
     857             :     }
     858             :     else
     859             :     {
     860           0 :         nCursorPos = static_cast<SCCOLROW>(nPosY);
     861           0 :         nPosX = pViewData->GetPosX(WhichH(pViewData->GetActivePart()));
     862             :     }
     863             : 
     864           0 :     ScTabView* pView = pViewData->GetView();
     865           0 :     bool bHide = pViewData->GetCurX() != nPosX ||
     866           0 :                  pViewData->GetCurY() != nPosY;
     867           0 :     if (bHide)
     868           0 :         pView->HideAllCursors();
     869             : 
     870           0 :     if (bScroll)
     871           0 :         pView->AlignToCursor( nPosX, nPosY, SC_FOLLOW_LINE );
     872           0 :     pView->SetCursor( nPosX, nPosY );
     873             : 
     874           0 :     if ( !bAnchor || !pView->IsBlockMode() )
     875             :     {
     876           0 :         pView->DoneBlockMode( true );
     877           0 :         pViewData->GetMarkData().MarkToMulti();         //! who changes this?
     878           0 :         pView->InitBlockMode( nPosX, nPosY, pViewData->GetTabNo(), true, bColumn, !bColumn );
     879             : 
     880           0 :         bAnchor = true;
     881             :     }
     882             : 
     883           0 :     pView->MarkCursor( nPosX, nPosY, pViewData->GetTabNo(), bColumn, !bColumn );
     884             : 
     885             :     // SelectionChanged inside of HideCursor because of UpdateAutoFillMark
     886           0 :     pView->SelectionChanged();
     887             : 
     888           0 :     if (bHide)
     889           0 :         pView->ShowAllCursors();
     890             : 
     891           0 :     return true;
     892             : }
     893             : 
     894           0 : bool ScHeaderFunctionSet::IsSelectionAtPoint( const Point& rPointPixel )
     895             : {
     896             :     SCsCOL  nPosX;
     897             :     SCsROW  nPosY;
     898             :     pViewData->GetPosFromPixel( rPointPixel.X(), rPointPixel.Y(), pViewData->GetActivePart(),
     899           0 :                                 nPosX, nPosY, false );
     900             : 
     901           0 :     ScMarkData& rMark = pViewData->GetMarkData();
     902           0 :     if (bColumn)
     903           0 :         return rMark.IsColumnMarked( nPosX );
     904             :     else
     905           0 :         return rMark.IsRowMarked( nPosY );
     906             : }
     907             : 
     908           0 : void ScHeaderFunctionSet::DeselectAtPoint( const Point& /* rPointPixel */ )
     909             : {
     910           0 : }
     911             : 
     912           0 : void ScHeaderFunctionSet::DeselectAll()
     913             : {
     914           0 :     pViewData->GetView()->DoneBlockMode( false );
     915           0 :     bAnchor = false;
     916           0 : }
     917             : 
     918           0 : ScHeaderSelectionEngine::ScHeaderSelectionEngine( Window* pWindow, ScHeaderFunctionSet* pFuncSet ) :
     919           0 :         SelectionEngine( pWindow, pFuncSet )
     920             : {
     921           0 :     SetSelectionMode( MULTIPLE_SELECTION );
     922           0 :     EnableDrag( false );
     923           0 : }
     924             : 
     925             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10