LCOV - code coverage report
Current view: top level - sc/source/ui/view - olinewin.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 272 536 50.7 %
Date: 2015-06-13 12:38:46 Functions: 41 62 66.1 %
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 <vcl/svapp.hxx>
      21             : #include <vcl/taskpanelist.hxx>
      22             : #include <vcl/settings.hxx>
      23             : 
      24             : #include "olinewin.hxx"
      25             : #include "olinetab.hxx"
      26             : #include "document.hxx"
      27             : #include "dbfunc.hxx"
      28             : #include "sc.hrc"
      29             : 
      30             : const long SC_OL_BITMAPSIZE                 = 12;
      31             : const long SC_OL_POSOFFSET                  = 2;
      32             : 
      33             : const size_t SC_OL_NOLEVEL                  = static_cast< size_t >( -1 );
      34             : const size_t SC_OL_HEADERENTRY              = static_cast< size_t >( -1 );
      35             : 
      36             : const sal_uInt16 SC_OL_IMAGE_PLUS               = 9;
      37             : const sal_uInt16 SC_OL_IMAGE_MINUS              = SC_OL_IMAGE_PLUS + 1;
      38             : const sal_uInt16 SC_OL_IMAGE_NOTPRESSED         = SC_OL_IMAGE_MINUS + 1;
      39             : const sal_uInt16 SC_OL_IMAGE_PRESSED            = SC_OL_IMAGE_NOTPRESSED + 1;
      40             : 
      41           5 : ScOutlineWindow::ScOutlineWindow( vcl::Window* pParent, ScOutlineMode eMode, ScViewData* pViewData, ScSplitPos eWhich ) :
      42             :     Window( pParent ),
      43             :     mrViewData( *pViewData ),
      44             :     meWhich( eWhich ),
      45           5 :     mbHoriz( eMode == SC_OUTLINE_HOR ),
      46             :     mbMirrorEntries( false ),           // updated in SetHeaderSize
      47             :     mbMirrorLevels( false ),            // updated in SetHeaderSize
      48             :     mpSymbols( NULL ),
      49             :     maLineColor( COL_BLACK ),
      50             :     mnHeaderSize( 0 ),
      51             :     mnHeaderPos( 0 ),
      52             :     mnMainFirstPos( 0 ),
      53             :     mnMainLastPos( 0 ),
      54             :     mbMTActive( false ),
      55             :     mbMTPressed( false ),
      56             :     mnFocusLevel( 0 ),
      57             :     mnFocusEntry( SC_OL_HEADERENTRY ),
      58          10 :     mbDontDrawFocus( false )
      59             : {
      60           5 :     EnableRTL( false );                 // mirroring is done manually
      61             : 
      62           5 :     InitSettings();
      63           5 :     maFocusRect.SetEmpty();
      64           5 :     SetHeaderSize( 0 );
      65             : 
      66             :     // insert the window into task pane list for "F6 cycling"
      67           5 :     if( SystemWindow* pSysWin = GetSystemWindow() )
      68           5 :         if( TaskPaneList* pTaskPaneList = pSysWin->GetTaskPaneList() )
      69           5 :             pTaskPaneList->AddWindow( this );
      70           5 : }
      71             : 
      72          15 : ScOutlineWindow::~ScOutlineWindow()
      73             : {
      74           5 :     disposeOnce();
      75          10 : }
      76             : 
      77           5 : void ScOutlineWindow::dispose()
      78             : {
      79             :     // remove the window from task pane list
      80           5 :     if( SystemWindow* pSysWin = GetSystemWindow() )
      81           5 :         if( TaskPaneList* pTaskPaneList = pSysWin->GetTaskPaneList() )
      82           5 :             pTaskPaneList->RemoveWindow( this );
      83           5 :     vcl::Window::dispose();
      84           5 : }
      85             : 
      86          55 : void ScOutlineWindow::SetHeaderSize( long nNewSize )
      87             : {
      88          55 :     bool bLayoutRTL = GetDoc().IsLayoutRTL( GetTab() );
      89          55 :     mbMirrorEntries = bLayoutRTL && mbHoriz;
      90          55 :     mbMirrorLevels = bLayoutRTL && !mbHoriz;
      91             : 
      92          55 :     bool bNew = (nNewSize != mnHeaderSize);
      93          55 :     mnHeaderSize = nNewSize;
      94          55 :     mnHeaderPos = mbMirrorEntries ? (GetOutputSizeEntry() - mnHeaderSize) : 0;
      95          55 :     mnMainFirstPos = mbMirrorEntries ? 0 : mnHeaderSize;
      96          55 :     mnMainLastPos = GetOutputSizeEntry() - (mbMirrorEntries ? mnHeaderSize : 0) - 1;
      97          55 :     if ( bNew )
      98           6 :         Invalidate();
      99          55 : }
     100             : 
     101          43 : long ScOutlineWindow::GetDepthSize() const
     102             : {
     103          43 :     long nSize = GetLevelCount() * SC_OL_BITMAPSIZE;
     104          43 :     if ( nSize > 0 )
     105          43 :         nSize += 2 * SC_OL_POSOFFSET + 1;
     106          43 :     return nSize;
     107             : }
     108             : 
     109           6 : void ScOutlineWindow::ScrollPixel( long nDiff )
     110             : {
     111           6 :     HideFocus();
     112           6 :     mbDontDrawFocus = true;
     113             : 
     114           6 :     long nStart = mnMainFirstPos;
     115           6 :     long nEnd = mnMainLastPos;
     116             : 
     117             :     long nInvStart, nInvEnd;
     118           6 :     if (nDiff < 0)
     119             :     {
     120           3 :         nStart -= nDiff;
     121           3 :         nInvStart = nEnd + nDiff;
     122           3 :         nInvEnd = nEnd;
     123             :     }
     124             :     else
     125             :     {
     126           3 :         nEnd -= nDiff;
     127           3 :         nInvStart = nStart;
     128           3 :         nInvEnd = nStart + nDiff;
     129             :     }
     130             : 
     131           6 :     ScrollRel( nDiff, nStart, nEnd );
     132           6 :     Invalidate( GetRectangle( 0, nInvStart, GetOutputSizeLevel() - 1, nInvEnd ) );
     133           6 :     Update();
     134             : 
     135             :     // if focus becomes invisible, move it to next visible button
     136           6 :     ImplMoveFocusToVisible( nDiff < 0 );
     137             : 
     138           6 :     mbDontDrawFocus = false;
     139           6 :     ShowFocus();
     140           6 : }
     141             : 
     142           6 : void ScOutlineWindow::ScrollRel( long nEntryDiff, long nEntryStart, long nEntryEnd )
     143             : {
     144           6 :     Rectangle aRect( GetRectangle( 0, nEntryStart, GetOutputSizeLevel() - 1, nEntryEnd ) );
     145           6 :     if ( mbHoriz )
     146           0 :         Scroll( nEntryDiff, 0, aRect );
     147             :     else
     148           6 :         Scroll( 0, nEntryDiff, aRect );
     149           6 : }
     150             : 
     151             : // internal -------------------------------------------------------------------
     152             : 
     153           7 : void ScOutlineWindow::InitSettings()
     154             : {
     155           7 :     const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
     156           7 :     SetBackground( rStyleSettings.GetFaceColor() );
     157           7 :     maLineColor = rStyleSettings.GetButtonTextColor();
     158           7 :     mpSymbols = ScGlobal::GetOutlineSymbols();
     159           7 :     Invalidate();
     160           7 : }
     161             : 
     162         116 : const ScOutlineArray* ScOutlineWindow::GetOutlineArray() const
     163             : {
     164         116 :     const ScOutlineTable* pTable = GetDoc().GetOutlineTable( GetTab() );
     165         116 :     if ( !pTable ) return NULL;
     166          83 :     return mbHoriz ? &pTable->GetColArray() : &pTable->GetRowArray();
     167             : }
     168             : 
     169          16 : const ScOutlineEntry* ScOutlineWindow::GetOutlineEntry( size_t nLevel, size_t nEntry ) const
     170             : {
     171          16 :     const ScOutlineArray* pArray = GetOutlineArray();
     172          16 :     return pArray ? pArray->GetEntry( sal::static_int_cast<sal_uInt16>(nLevel), sal::static_int_cast<sal_uInt16>(nEntry) ) : NULL;
     173             : }
     174             : 
     175          20 : bool ScOutlineWindow::IsHidden( SCCOLROW nColRowIndex ) const
     176             : {
     177             :     return mbHoriz ?
     178           0 :         GetDoc().ColHidden(static_cast<SCCOL>(nColRowIndex), GetTab()) :
     179          20 :         GetDoc().RowHidden(static_cast<SCROW>(nColRowIndex), GetTab());
     180             : }
     181             : 
     182          12 : bool ScOutlineWindow::IsFiltered( SCCOLROW nColRowIndex ) const
     183             : {
     184             :     // columns cannot be filtered
     185          12 :     return !mbHoriz && GetDoc().RowFiltered( static_cast<SCROW>(nColRowIndex), GetTab() );
     186             : }
     187             : 
     188           8 : bool ScOutlineWindow::IsFirstVisible( SCCOLROW nColRowIndex ) const
     189             : {
     190           8 :     bool bAllHidden = true;
     191          16 :     for ( SCCOLROW nPos = 0; (nPos < nColRowIndex) && bAllHidden; ++nPos )
     192           8 :         bAllHidden = IsHidden( nPos );
     193           8 :     return bAllHidden;
     194             : }
     195             : 
     196           5 : void ScOutlineWindow::GetVisibleRange( SCCOLROW& rnColRowStart, SCCOLROW& rnColRowEnd ) const
     197             : {
     198           5 :     if ( mbHoriz )
     199             :     {
     200           0 :         rnColRowStart = mrViewData.GetPosX( WhichH( meWhich ) );
     201           0 :         rnColRowEnd = rnColRowStart + mrViewData.VisibleCellsX( WhichH( meWhich ) );
     202             :     }
     203             :     else
     204             :     {
     205           5 :         rnColRowStart = mrViewData.GetPosY( WhichV( meWhich ) );
     206           5 :         rnColRowEnd = rnColRowStart + mrViewData.VisibleCellsY( WhichV( meWhich ) );
     207             :     }
     208             : 
     209             :     // include collapsed columns/rows in front of visible range
     210          10 :     while ( (rnColRowStart > 0) && IsHidden( rnColRowStart - 1 ) )
     211           0 :         --rnColRowStart;
     212           5 : }
     213             : 
     214          83 : Point ScOutlineWindow::GetPoint( long nLevelPos, long nEntryPos ) const
     215             : {
     216          83 :     return mbHoriz ? Point( nEntryPos, nLevelPos ) : Point( nLevelPos, nEntryPos );
     217             : }
     218             : 
     219          16 : Rectangle ScOutlineWindow::GetRectangle(
     220             :         long nLevelStart, long nEntryStart, long nLevelEnd, long nEntryEnd ) const
     221             : {
     222          16 :     return Rectangle( GetPoint( nLevelStart, nEntryStart ), GetPoint( nLevelEnd, nEntryEnd ) );
     223             : }
     224             : 
     225          17 : long ScOutlineWindow::GetOutputSizeLevel() const
     226             : {
     227          17 :     Size aSize( GetOutputSizePixel() );
     228          17 :     return mbHoriz ? aSize.Height() : aSize.Width();
     229             : }
     230             : 
     231          55 : long ScOutlineWindow::GetOutputSizeEntry() const
     232             : {
     233          55 :     Size aSize( GetOutputSizePixel() );
     234          55 :     return mbHoriz ? aSize.Width() : aSize.Height();
     235             : }
     236             : 
     237          80 : size_t ScOutlineWindow::GetLevelCount() const
     238             : {
     239          80 :     const ScOutlineArray* pArray = GetOutlineArray();
     240          80 :     size_t nLevelCount = pArray ? pArray->GetDepth() : 0;
     241          80 :     return nLevelCount ? (nLevelCount + 1) : 0;
     242             : }
     243             : 
     244          25 : long ScOutlineWindow::GetLevelPos( size_t nLevel ) const
     245             : {
     246             :     // #i51970# must always return the *left* edge of the area used by a level
     247          25 :     long nPos = static_cast< long >( SC_OL_POSOFFSET + nLevel * SC_OL_BITMAPSIZE );
     248          25 :     return mbMirrorLevels ? (GetOutputSizeLevel() - nPos - SC_OL_BITMAPSIZE) : nPos;
     249             : }
     250             : 
     251           0 : size_t ScOutlineWindow::GetLevelFromPos( long nLevelPos ) const
     252             : {
     253           0 :     if( mbMirrorLevels ) nLevelPos = GetOutputSizeLevel() - nLevelPos - 1;
     254           0 :     long nStart = SC_OL_POSOFFSET;
     255           0 :     if ( nLevelPos < nStart ) return SC_OL_NOLEVEL;
     256           0 :     size_t nLevel = static_cast< size_t >( (nLevelPos - nStart) / SC_OL_BITMAPSIZE );
     257           0 :     return (nLevel < GetLevelCount()) ? nLevel : SC_OL_NOLEVEL;
     258             : }
     259             : 
     260          24 : long ScOutlineWindow::GetColRowPos( SCCOLROW nColRowIndex ) const
     261             : {
     262             :     long nDocPos = mbHoriz ?
     263          24 :         mrViewData.GetScrPos( static_cast<SCCOL>(nColRowIndex), 0, meWhich, true ).X() :
     264          48 :         mrViewData.GetScrPos( 0, static_cast<SCROW>(nColRowIndex), meWhich, true ).Y();
     265          24 :     return mnMainFirstPos + nDocPos;
     266             : }
     267             : 
     268           5 : long ScOutlineWindow::GetHeaderEntryPos() const
     269             : {
     270           5 :     return mnHeaderPos + (mnHeaderSize - SC_OL_BITMAPSIZE) / 2;
     271             : }
     272             : 
     273          16 : bool ScOutlineWindow::GetEntryPos(
     274             :         size_t nLevel, size_t nEntry,
     275             :         long& rnStartPos, long& rnEndPos, long& rnImagePos ) const
     276             : {
     277          16 :     const ScOutlineEntry* pEntry = GetOutlineEntry( nLevel, nEntry );
     278          16 :     if ( !pEntry || !pEntry->IsVisible() )
     279           4 :         return false;
     280             : 
     281          12 :     SCCOLROW nStart = pEntry->GetStart();
     282          12 :     SCCOLROW nEnd = pEntry->GetEnd();
     283             : 
     284          12 :     long nEntriesSign = mbMirrorEntries ? -1 : 1;
     285             : 
     286             :     // --- common calculation ---
     287             : 
     288          12 :     rnStartPos = GetColRowPos( nStart );
     289          12 :     rnEndPos = GetColRowPos( nEnd + 1 );
     290             : 
     291          12 :     bool bHidden = IsHidden( nStart );
     292             :     rnImagePos = bHidden ?
     293           8 :                 (rnStartPos - ( SC_OL_BITMAPSIZE / 2 ) * nEntriesSign) :
     294          20 :                 rnStartPos + nEntriesSign;
     295          12 :     long nCenter = (rnStartPos + rnEndPos - SC_OL_BITMAPSIZE * nEntriesSign +
     296          12 :                         ( mbMirrorEntries ? 1 : 0 )) / 2L;
     297          12 :     rnImagePos = mbMirrorEntries ? std::max( rnImagePos, nCenter ) : std::min( rnImagePos, nCenter );
     298             : 
     299             :     // --- refinements ---
     300             : 
     301             :     // do not cut leftmost/topmost image
     302          12 :     if ( bHidden && IsFirstVisible( nStart ) )
     303           0 :         rnImagePos = rnStartPos;
     304             : 
     305             :     // do not cover previous collapsed image
     306          12 :     bool bDoNoCover = !bHidden && nEntry;
     307          12 :     const ScOutlineEntry* pPrevEntry = bDoNoCover ? GetOutlineEntry(nLevel, nEntry - 1) : NULL;
     308          12 :     if (pPrevEntry)
     309             :     {
     310           0 :         SCCOLROW nPrevEnd = pPrevEntry->GetEnd();
     311           0 :         if ( (nPrevEnd + 1 == nStart) && IsHidden( nPrevEnd ) )
     312             :         {
     313           0 :             if ( IsFirstVisible( pPrevEntry->GetStart() ) )
     314           0 :                 rnStartPos += SC_OL_BITMAPSIZE * nEntriesSign;
     315             :             else
     316           0 :                 rnStartPos += ( SC_OL_BITMAPSIZE / 2 ) * nEntriesSign;
     317           0 :             rnImagePos = rnStartPos;
     318             :         }
     319             :     }
     320             : 
     321             :     // restrict rnStartPos...rnEndPos to valid area
     322          12 :     rnStartPos = std::max( rnStartPos, mnMainFirstPos );
     323          12 :     rnEndPos = std::max( rnEndPos, mnMainFirstPos );
     324             : 
     325          12 :     if ( mbMirrorEntries )
     326           0 :         rnImagePos -= SC_OL_BITMAPSIZE - 1;     // start pos aligns with right edge of bitmap
     327             : 
     328             :     // --- all rows filtered? ---
     329             : 
     330          12 :     bool bVisible = true;
     331          12 :     if ( !mbHoriz )
     332             :     {
     333          12 :         bVisible = false;
     334          24 :         for ( SCCOLROW nRow = nStart; (nRow <= nEnd) && !bVisible; ++nRow )
     335          12 :             bVisible = !IsFiltered( nRow );
     336             :     }
     337          12 :     return bVisible;
     338             : }
     339             : 
     340           0 : bool ScOutlineWindow::GetImagePos( size_t nLevel, size_t nEntry, Point& rPos ) const
     341             : {
     342           0 :     bool bRet = nLevel < GetLevelCount();
     343           0 :     if ( bRet )
     344             :     {
     345           0 :         long nLevelPos = GetLevelPos( nLevel );
     346           0 :         if ( nEntry == SC_OL_HEADERENTRY )
     347           0 :             rPos = GetPoint( nLevelPos, GetHeaderEntryPos() );
     348             :         else
     349             :         {
     350             :             long nStartPos, nEndPos, nImagePos;
     351           0 :             bRet = GetEntryPos( nLevel, nEntry, nStartPos, nEndPos, nImagePos );
     352           0 :             rPos = GetPoint( nLevelPos, nImagePos );
     353             :         }
     354             :     }
     355           0 :     return bRet;
     356             : }
     357             : 
     358          37 : bool ScOutlineWindow::IsButtonVisible( size_t nLevel, size_t nEntry ) const
     359             : {
     360          37 :     bool bRet = false;
     361          37 :     if ( nEntry == SC_OL_HEADERENTRY )
     362          37 :         bRet = (mnHeaderSize > 0) && (nLevel < GetLevelCount());
     363             :     else
     364             :     {
     365           0 :         const ScOutlineEntry* pEntry = GetOutlineEntry( nLevel, nEntry );
     366           0 :         if ( pEntry && pEntry->IsVisible() )
     367             :         {
     368             :             SCCOLROW nStart, nEnd;
     369           0 :             GetVisibleRange( nStart, nEnd );
     370           0 :             bRet = (nStart <= pEntry->GetStart()) && (pEntry->GetStart() <= nEnd);
     371             :         }
     372             :     }
     373          37 :     return bRet;
     374             : }
     375             : 
     376           0 : bool ScOutlineWindow::ItemHit( const Point& rPos, size_t& rnLevel, size_t& rnEntry, bool& rbButton ) const
     377             : {
     378           0 :     const ScOutlineArray* pArray = GetOutlineArray();
     379           0 :     if ( !pArray ) return false;
     380             : 
     381             :     SCCOLROW nStartIndex, nEndIndex;
     382           0 :     GetVisibleRange( nStartIndex, nEndIndex );
     383             : 
     384           0 :     size_t nLevel = GetLevelFromPos( mbHoriz ? rPos.Y() : rPos.X() );
     385           0 :     if ( nLevel == SC_OL_NOLEVEL )
     386           0 :         return false;
     387             : 
     388           0 :     long nEntryMousePos = mbHoriz ? rPos.X() : rPos.Y();
     389             : 
     390             :     // --- level buttons ---
     391             : 
     392           0 :     if ( mnHeaderSize > 0 )
     393             :     {
     394           0 :         long nImagePos = GetHeaderEntryPos();
     395           0 :         if ( (nImagePos <= nEntryMousePos) && (nEntryMousePos < nImagePos + SC_OL_BITMAPSIZE) )
     396             :         {
     397           0 :             rnLevel = nLevel;
     398           0 :             rnEntry = SC_OL_HEADERENTRY;
     399           0 :             rbButton = true;
     400           0 :             return true;
     401             :         }
     402             :     }
     403             : 
     404             :     // --- expand/collapse buttons and expanded lines ---
     405             : 
     406             :     // search outline entries backwards
     407           0 :     size_t nEntry = pArray->GetCount( sal::static_int_cast<sal_uInt16>(nLevel) );
     408           0 :     while ( nEntry )
     409             :     {
     410           0 :         --nEntry;
     411             : 
     412           0 :         const ScOutlineEntry* pEntry = pArray->GetEntry( sal::static_int_cast<sal_uInt16>(nLevel),
     413           0 :                                                          sal::static_int_cast<sal_uInt16>(nEntry) );
     414           0 :         SCCOLROW nStart = pEntry->GetStart();
     415           0 :         SCCOLROW nEnd = pEntry->GetEnd();
     416             : 
     417           0 :         if ( (nEnd >= nStartIndex) && (nStart <= nEndIndex) )
     418             :         {
     419             :             long nStartPos, nEndPos, nImagePos;
     420           0 :             if ( GetEntryPos( nLevel, nEntry, nStartPos, nEndPos, nImagePos ) )
     421             :             {
     422           0 :                 rnLevel = nLevel;
     423           0 :                 rnEntry = nEntry;
     424             : 
     425             :                 // button?
     426           0 :                 if ( (nStart >= nStartIndex) && (nImagePos <= nEntryMousePos) && (nEntryMousePos < nImagePos + SC_OL_BITMAPSIZE) )
     427             :                 {
     428           0 :                     rbButton = true;
     429           0 :                     return true;
     430             :                 }
     431             : 
     432             :                 // line?
     433           0 :                 if ( mbMirrorEntries )
     434           0 :                     ::std::swap( nStartPos, nEndPos );      // in RTL mode, nStartPos is the larger value
     435           0 :                 if ( (nStartPos <= nEntryMousePos) && (nEntryMousePos <= nEndPos) )
     436             :                 {
     437           0 :                     rbButton = false;
     438           0 :                     return true;
     439             :                 }
     440             :             }
     441             :         }
     442             :     }
     443             : 
     444           0 :     return false;
     445             : }
     446             : 
     447           0 : bool ScOutlineWindow::ButtonHit( const Point& rPos, size_t& rnLevel, size_t& rnEntry ) const
     448             : {
     449             :     bool bButton;
     450           0 :     bool bRet = ItemHit( rPos, rnLevel, rnEntry, bButton );
     451           0 :     return bRet && bButton;
     452             : }
     453             : 
     454           0 : bool ScOutlineWindow::LineHit( const Point& rPos, size_t& rnLevel, size_t& rnEntry ) const
     455             : {
     456             :     bool bButton;
     457           0 :     bool bRet = ItemHit( rPos, rnLevel, rnEntry, bButton );
     458           0 :     return bRet && !bButton;
     459             : }
     460             : 
     461           0 : void ScOutlineWindow::DoFunction( size_t nLevel, size_t nEntry ) const
     462             : {
     463           0 :     ScDBFunc& rFunc = *mrViewData.GetView();
     464           0 :     if ( nEntry == SC_OL_HEADERENTRY )
     465           0 :         rFunc.SelectLevel( mbHoriz, sal::static_int_cast<sal_uInt16>(nLevel) );
     466             :     else
     467             :     {
     468           0 :         const ScOutlineEntry* pEntry = GetOutlineEntry( nLevel, nEntry );
     469           0 :         if ( pEntry )
     470             :         {
     471           0 :             if ( pEntry->IsHidden() )
     472           0 :                 rFunc.ShowOutline( mbHoriz, sal::static_int_cast<sal_uInt16>(nLevel), sal::static_int_cast<sal_uInt16>(nEntry) );
     473             :             else
     474           0 :                 rFunc.HideOutline( mbHoriz, sal::static_int_cast<sal_uInt16>(nLevel), sal::static_int_cast<sal_uInt16>(nEntry) );
     475             :         }
     476             :     }
     477           0 : }
     478             : 
     479           0 : void ScOutlineWindow::DoExpand( size_t nLevel, size_t nEntry ) const
     480             : {
     481           0 :     const ScOutlineEntry* pEntry = GetOutlineEntry( nLevel, nEntry );
     482           0 :     if ( pEntry && pEntry->IsHidden() )
     483           0 :         DoFunction( nLevel, nEntry );
     484           0 : }
     485             : 
     486           0 : void ScOutlineWindow::DoCollapse( size_t nLevel, size_t nEntry ) const
     487             : {
     488           0 :     const ScOutlineEntry* pEntry = GetOutlineEntry( nLevel, nEntry );
     489           0 :     if ( pEntry && !pEntry->IsHidden() )
     490           0 :         DoFunction( nLevel, nEntry );
     491           0 : }
     492             : 
     493          19 : void ScOutlineWindow::Resize()
     494             : {
     495          19 :     Window::Resize();
     496          19 :     SetHeaderSize( mnHeaderSize );  // recalculates header/group positions
     497          19 :     if ( !IsFocusButtonVisible() )
     498             :     {
     499           5 :         HideFocus();
     500           5 :         ShowFocus();    // calculates valid position
     501             :     }
     502          19 : }
     503             : 
     504           2 : void ScOutlineWindow::DataChanged( const DataChangedEvent& rDCEvt )
     505             : {
     506           8 :     if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) &&
     507           8 :          (rDCEvt.GetFlags() & AllSettingsFlags::STYLE) )
     508             :     {
     509           2 :         InitSettings();
     510           2 :         Invalidate();
     511             :     }
     512           2 :     Window::DataChanged( rDCEvt );
     513           2 : }
     514             : 
     515             : // drawing --------------------------------------------------------------------
     516             : 
     517           5 : void ScOutlineWindow::SetEntryAreaClipRegion()
     518             : {
     519             :     SetClipRegion( vcl::Region(Rectangle(
     520           5 :         GetPoint( 0, mnMainFirstPos ),
     521          10 :         GetPoint( GetOutputSizeLevel() - 1, mnMainLastPos ))));
     522           5 : }
     523             : 
     524          10 : void ScOutlineWindow::DrawLineRel(
     525             :         long nLevelStart, long nEntryStart, long nLevelEnd, long nEntryEnd )
     526             : {
     527          10 :     DrawLine( GetPoint( nLevelStart, nEntryStart ), GetPoint( nLevelEnd, nEntryEnd ) );
     528          10 : }
     529             : 
     530           4 : void ScOutlineWindow::DrawRectRel(
     531             :         long nLevelStart, long nEntryStart, long nLevelEnd, long nEntryEnd )
     532             : {
     533           4 :     DrawRect( GetRectangle( nLevelStart, nEntryStart, nLevelEnd, nEntryEnd ) );
     534           4 : }
     535             : 
     536          21 : void ScOutlineWindow::DrawImageRel( long nLevelPos, long nEntryPos, sal_uInt16 nId )
     537             : {
     538             :     OSL_ENSURE( mpSymbols, "ScOutlineWindow::DrawImageRel - no images" );
     539          21 :     const Image& rImage = mpSymbols->GetImage( nId );
     540          21 :     SetLineColor();
     541          21 :     SetFillColor( GetBackground().GetColor() );
     542          21 :     Point aPos( GetPoint( nLevelPos, nEntryPos ) );
     543          21 :     DrawRect( Rectangle( aPos, rImage.GetSizePixel() ) );
     544          21 :     DrawImage( aPos, rImage );
     545          21 : }
     546             : 
     547           0 : void ScOutlineWindow::DrawBorderRel( size_t nLevel, size_t nEntry, bool bPressed )
     548             : {
     549           0 :     Point aPos;
     550           0 :     if ( GetImagePos( nLevel, nEntry, aPos ) )
     551             :     {
     552             :         OSL_ENSURE( mpSymbols, "ScOutlineWindow::DrawBorderRel - no images" );
     553           0 :         sal_uInt16 nId = bPressed ? SC_OL_IMAGE_PRESSED : SC_OL_IMAGE_NOTPRESSED;
     554           0 :         bool bClip = (nEntry != SC_OL_HEADERENTRY);
     555           0 :         if ( bClip )
     556           0 :             SetEntryAreaClipRegion();
     557           0 :         DrawImage( aPos, mpSymbols->GetImage( nId ) );
     558           0 :         if ( bClip )
     559           0 :             SetClipRegion();
     560             :     }
     561           0 :     mbMTPressed = bPressed;
     562           0 : }
     563             : 
     564          16 : void ScOutlineWindow::ShowFocus()
     565             : {
     566          16 :     if ( HasFocus() )
     567             :     {
     568             :         // first move to a visible position
     569           0 :         ImplMoveFocusToVisible( true );
     570             : 
     571           0 :         if ( IsFocusButtonVisible() )
     572             :         {
     573           0 :             Point aPos;
     574           0 :             if ( GetImagePos( mnFocusLevel, mnFocusEntry, aPos ) )
     575             :             {
     576           0 :                 aPos += Point( 1, 1 );
     577           0 :                 maFocusRect = Rectangle( aPos, Size( SC_OL_BITMAPSIZE - 2, SC_OL_BITMAPSIZE - 2 ) );
     578           0 :                 bool bClip = (mnFocusEntry != SC_OL_HEADERENTRY);
     579           0 :                 if ( bClip )
     580           0 :                     SetEntryAreaClipRegion();
     581           0 :                 InvertTracking( maFocusRect, SHOWTRACK_SMALL | SHOWTRACK_WINDOW );
     582           0 :                 if ( bClip )
     583           0 :                     SetClipRegion();
     584             :             }
     585             :         }
     586             :     }
     587          16 : }
     588             : 
     589          11 : void ScOutlineWindow::HideFocus()
     590             : {
     591          11 :     if ( !maFocusRect.IsEmpty() )
     592             :     {
     593           0 :         bool bClip = (mnFocusEntry != SC_OL_HEADERENTRY);
     594           0 :         if ( bClip )
     595           0 :             SetEntryAreaClipRegion();
     596           0 :         InvertTracking( maFocusRect, SHOWTRACK_SMALL | SHOWTRACK_WINDOW );
     597           0 :         if ( bClip )
     598           0 :             SetClipRegion();
     599           0 :         maFocusRect.SetEmpty();
     600             :     }
     601          11 : }
     602             : 
     603           5 : void ScOutlineWindow::Paint( vcl::RenderContext& /*rRenderContext*/, const Rectangle& /* rRect */ )
     604             : {
     605           5 :     long nEntriesSign = mbMirrorEntries ? -1 : 1;
     606           5 :     long nLevelsSign  = mbMirrorLevels  ? -1 : 1;
     607             : 
     608           5 :     Size aSize = GetOutputSizePixel();
     609           5 :     long nLevelEnd = (mbHoriz ? aSize.Height() : aSize.Width()) - 1;
     610           5 :     long nEntryEnd = (mbHoriz ? aSize.Width() : aSize.Height()) - 1;
     611             : 
     612           5 :     SetLineColor( maLineColor );
     613           5 :     long nBorderPos = mbMirrorLevels ? 0 : nLevelEnd;
     614           5 :     DrawLineRel( nBorderPos, 0, nBorderPos, nEntryEnd );
     615             : 
     616           5 :     const ScOutlineArray* pArray = GetOutlineArray();
     617          10 :     if ( !pArray ) return;
     618             : 
     619           5 :     size_t nLevelCount = GetLevelCount();
     620             : 
     621             :     // --- draw header images ---
     622             : 
     623           5 :     if ( mnHeaderSize > 0 )
     624             :     {
     625           5 :         long nEntryPos = GetHeaderEntryPos();
     626          20 :         for ( size_t nLevel = 0; nLevel < nLevelCount; ++nLevel )
     627          15 :             DrawImageRel( GetLevelPos( nLevel ), nEntryPos, static_cast< sal_uInt16 >( nLevel + 1 ) );
     628             : 
     629           5 :         SetLineColor( maLineColor );
     630           5 :         long nLinePos = mnHeaderPos + (mbMirrorEntries ? 0 : (mnHeaderSize - 1));
     631           5 :         DrawLineRel( 0, nLinePos, nLevelEnd, nLinePos );
     632             :     }
     633             : 
     634             :     // --- draw lines & collapse/expand images ---
     635             : 
     636           5 :     SetEntryAreaClipRegion();
     637             : 
     638             :     SCCOLROW nStartIndex, nEndIndex;
     639           5 :     GetVisibleRange( nStartIndex, nEndIndex );
     640             : 
     641          15 :     for ( size_t nLevel = 0; nLevel + 1 < nLevelCount; ++nLevel )
     642             :     {
     643          10 :         long nLevelPos = GetLevelPos( nLevel );
     644          10 :         long nEntryPos1 = 0, nEntryPos2 = 0, nImagePos = 0;
     645             : 
     646          10 :         size_t nEntryCount = pArray->GetCount( sal::static_int_cast<sal_uInt16>(nLevel) );
     647             :         size_t nEntry;
     648             : 
     649             :         // first draw all lines in the current level
     650          10 :         SetLineColor();
     651          10 :         SetFillColor( maLineColor );
     652          22 :         for ( nEntry = 0; nEntry < nEntryCount; ++nEntry )
     653             :         {
     654          12 :             const ScOutlineEntry* pEntry = pArray->GetEntry( sal::static_int_cast<sal_uInt16>(nLevel),
     655          24 :                                                              sal::static_int_cast<sal_uInt16>(nEntry) );
     656          12 :             SCCOLROW nStart = pEntry->GetStart();
     657          12 :             SCCOLROW nEnd = pEntry->GetEnd();
     658             : 
     659             :             // visible range?
     660          12 :             bool bDraw = (nEnd >= nStartIndex) && (nStart <= nEndIndex);
     661             :             // find output coordinates
     662          12 :             if ( bDraw )
     663           8 :                 bDraw = GetEntryPos( nLevel, nEntry, nEntryPos1, nEntryPos2, nImagePos );
     664             :             // draw, if not collapsed
     665          12 :             if ( bDraw && !pEntry->IsHidden() )
     666             :             {
     667           2 :                 if ( nStart >= nStartIndex )
     668           2 :                     nEntryPos1 += nEntriesSign;
     669           2 :                 nEntryPos2 -= 2 * nEntriesSign;
     670           2 :                 long nLinePos = nLevelPos;
     671           2 :                 if ( mbMirrorLevels )
     672           0 :                     nLinePos += SC_OL_BITMAPSIZE - 1;   // align with right edge of bitmap
     673           2 :                 DrawRectRel( nLinePos, nEntryPos1, nLinePos + nLevelsSign, nEntryPos2 );
     674             : 
     675           2 :                 if ( nEnd <= nEndIndex )
     676             :                     DrawRectRel( nLinePos, nEntryPos2 - nEntriesSign,
     677           2 :                                  nLinePos + ( SC_OL_BITMAPSIZE / 3 ) * nLevelsSign, nEntryPos2 );
     678             :             }
     679             :         }
     680             : 
     681             :         // draw all images in the level from last to first
     682          10 :         nEntry = nEntryCount;
     683          32 :         while ( nEntry )
     684             :         {
     685          12 :             --nEntry;
     686             : 
     687          12 :             const ScOutlineEntry* pEntry = pArray->GetEntry( sal::static_int_cast<sal_uInt16>(nLevel),
     688          24 :                                                              sal::static_int_cast<sal_uInt16>(nEntry) );
     689          12 :             SCCOLROW nStart = pEntry->GetStart();
     690             : 
     691             :             // visible range?
     692          12 :             bool bDraw = (nStartIndex <= nStart) && (nStart <= nEndIndex + 1);
     693             :             // find output coordinates
     694          12 :             if ( bDraw )
     695           8 :                 bDraw = GetEntryPos( nLevel, nEntry, nEntryPos1, nEntryPos2, nImagePos );
     696             :             // draw, if not hidden by higher levels
     697          12 :             if ( bDraw )
     698             :             {
     699           6 :                 sal_uInt16 nImageId = pEntry->IsHidden() ? SC_OL_IMAGE_PLUS : SC_OL_IMAGE_MINUS;
     700           6 :                 DrawImageRel( nLevelPos, nImagePos, nImageId );
     701             :             }
     702             :         }
     703             :     }
     704             : 
     705           5 :     SetClipRegion();
     706             : 
     707           5 :     if ( !mbDontDrawFocus )
     708           5 :         ShowFocus();
     709             : }
     710             : 
     711             : // focus ----------------------------------------------------------------------
     712             : 
     713             : /** Increments or decrements a value and wraps at the specified limits.
     714             :     @return  true = value wrapped. */
     715           0 : static bool lcl_RotateValue( size_t& rnValue, size_t nMin, size_t nMax, bool bForward )
     716             : {
     717             :     OSL_ENSURE( nMin <= nMax, "lcl_RotateValue - invalid range" );
     718             :     OSL_ENSURE( nMax < static_cast< size_t >( -1 ), "lcl_RotateValue - range overflow" );
     719           0 :     bool bWrap = false;
     720           0 :     if ( bForward )
     721             :     {
     722           0 :         if ( rnValue < nMax )
     723           0 :             ++rnValue;
     724             :         else
     725             :         {
     726           0 :             rnValue = nMin;
     727           0 :             bWrap = true;
     728             :         }
     729             :     }
     730             :     else
     731             :     {
     732           0 :         if ( rnValue > nMin )
     733           0 :             --rnValue;
     734             :         else
     735             :         {
     736           0 :             rnValue = nMax;
     737           0 :             bWrap = true;
     738             :         }
     739             :     }
     740           0 :     return bWrap;
     741             : }
     742             : 
     743          37 : bool ScOutlineWindow::IsFocusButtonVisible() const
     744             : {
     745          37 :     return IsButtonVisible( mnFocusLevel, mnFocusEntry );
     746             : }
     747             : 
     748          12 : bool ScOutlineWindow::ImplMoveFocusByEntry( bool bForward, bool bFindVisible )
     749             : {
     750          12 :     const ScOutlineArray* pArray = GetOutlineArray();
     751          12 :     if ( !pArray )
     752          12 :         return false;
     753             : 
     754           0 :     bool bWrapped = false;
     755           0 :     size_t nEntryCount = pArray->GetCount( sal::static_int_cast<sal_uInt16>(mnFocusLevel) );
     756             :     // #i29530# entry count may be decreased after changing active sheet
     757           0 :     if( mnFocusEntry >= nEntryCount )
     758           0 :         mnFocusEntry = SC_OL_HEADERENTRY;
     759           0 :     size_t nOldEntry = mnFocusEntry;
     760             : 
     761           0 :     do
     762             :     {
     763           0 :         if ( mnFocusEntry == SC_OL_HEADERENTRY )
     764             :         {
     765             :             // move from header to first or last entry
     766           0 :             if ( nEntryCount > 0 )
     767           0 :                 mnFocusEntry = bForward ? 0 : (nEntryCount - 1);
     768             :             /*  wrapped, if forward from right header to first entry,
     769             :                 or if backward from left header to last entry */
     770             :             // Header and entries are now always in consistent order,
     771             :             // so there's no need to check for mirroring here.
     772           0 :             if ( !nEntryCount || !bForward )
     773           0 :                 bWrapped = true;
     774             :         }
     775           0 :         else if ( lcl_RotateValue( mnFocusEntry, 0, nEntryCount - 1, bForward ) )
     776             :         {
     777             :             // lcl_RotateValue returns true -> wrapped the entry range -> move to header
     778           0 :             mnFocusEntry = SC_OL_HEADERENTRY;
     779             :             /*  wrapped, if forward from last entry to left header,
     780             :                 or if backward from first entry to right header */
     781           0 :             if ( bForward )
     782           0 :                 bWrapped = true;
     783             :         }
     784             :     }
     785           0 :     while ( bFindVisible && !IsFocusButtonVisible() && (nOldEntry != mnFocusEntry) );
     786             : 
     787           0 :     return bWrapped;
     788             : }
     789             : 
     790           3 : bool ScOutlineWindow::ImplMoveFocusByLevel( bool bForward )
     791             : {
     792           3 :     const ScOutlineArray* pArray = GetOutlineArray();
     793           3 :     if ( !pArray )
     794           3 :         return false;
     795             : 
     796           0 :     bool bWrapped = false;
     797           0 :     size_t nLevelCount = GetLevelCount();
     798             : 
     799           0 :     if ( mnFocusEntry == SC_OL_HEADERENTRY )
     800             :     {
     801           0 :         if ( nLevelCount > 0 )
     802           0 :             bWrapped = lcl_RotateValue( mnFocusLevel, 0, nLevelCount - 1, bForward );
     803             :     }
     804             :     else
     805             :     {
     806             :         const ScOutlineEntry* pEntry = pArray->GetEntry(
     807           0 :             mnFocusLevel, mnFocusEntry);
     808             : 
     809           0 :         if ( pEntry )
     810             :         {
     811           0 :             SCCOLROW nStart = pEntry->GetStart();
     812           0 :             SCCOLROW nEnd = pEntry->GetEnd();
     813           0 :             size_t nNewLevel = mnFocusLevel;
     814           0 :             size_t nNewEntry = 0;
     815             : 
     816           0 :             bool bFound = false;
     817           0 :             if ( bForward && (mnFocusLevel + 2 < nLevelCount) )
     818             :             {
     819             :                 // next level -> find first child entry
     820           0 :                 nNewLevel = mnFocusLevel + 1;
     821           0 :                 bFound = pArray->GetEntryIndexInRange(nNewLevel, nStart, nEnd, nNewEntry);
     822             :             }
     823           0 :             else if ( !bForward && (mnFocusLevel > 0) )
     824             :             {
     825             :                 // previous level -> find parent entry
     826           0 :                 nNewLevel = mnFocusLevel - 1;
     827           0 :                 bFound = pArray->GetEntryIndex(nNewLevel, nStart, nNewEntry);
     828             :             }
     829             : 
     830           0 :             if ( bFound && IsButtonVisible( nNewLevel, nNewEntry ) )
     831             :             {
     832           0 :                 mnFocusLevel = nNewLevel;
     833           0 :                 mnFocusEntry = nNewEntry;
     834             :             }
     835             :         }
     836             :     }
     837             : 
     838           0 :     return bWrapped;
     839             : }
     840             : 
     841           6 : bool ScOutlineWindow::ImplMoveFocusByTabOrder( bool bForward, bool bFindVisible )
     842             : {
     843           6 :     bool bRet = false;
     844           6 :     size_t nOldLevel = mnFocusLevel;
     845           6 :     size_t nOldEntry = mnFocusEntry;
     846             : 
     847           6 :     do
     848             :     {
     849             :         /*  one level up, if backward from left header,
     850             :             or one level down, if forward from right header */
     851           6 :         if ( (!bForward) && (mnFocusEntry == SC_OL_HEADERENTRY) )
     852           3 :             bRet |= ImplMoveFocusByLevel( bForward );
     853             :         // move to next/previous entry
     854           6 :         bool bWrapInLevel = ImplMoveFocusByEntry( bForward, false );
     855           6 :         bRet |= bWrapInLevel;
     856             :         /*  one level up, if wrapped backward to right header,
     857             :             or one level down, if wrapped forward to right header */
     858           6 :         if ( bForward && bWrapInLevel )
     859           0 :             bRet |= ImplMoveFocusByLevel( bForward );
     860             :     }
     861           6 :     while ( bFindVisible && !IsFocusButtonVisible() && ((nOldLevel != mnFocusLevel) || (nOldEntry != mnFocusEntry)) );
     862             : 
     863           6 :     return bRet;
     864             : }
     865             : 
     866           6 : void ScOutlineWindow::ImplMoveFocusToVisible( bool bForward )
     867             : {
     868             :     // first try to find an entry in the same level
     869           6 :     if ( !IsFocusButtonVisible() )
     870           6 :         ImplMoveFocusByEntry( bForward, true );
     871             :     // then try to find any other entry
     872           6 :     if ( !IsFocusButtonVisible() )
     873           6 :         ImplMoveFocusByTabOrder( bForward, true );
     874           6 : }
     875             : 
     876           0 : void ScOutlineWindow::MoveFocusByEntry( bool bForward )
     877             : {
     878           0 :     HideFocus();
     879           0 :     ImplMoveFocusByEntry( bForward, true );
     880           0 :     ShowFocus();
     881           0 : }
     882             : 
     883           0 : void ScOutlineWindow::MoveFocusByLevel( bool bForward )
     884             : {
     885           0 :     HideFocus();
     886           0 :     ImplMoveFocusByLevel( bForward );
     887           0 :     ShowFocus();
     888           0 : }
     889             : 
     890           0 : void ScOutlineWindow::MoveFocusByTabOrder( bool bForward )
     891             : {
     892           0 :     HideFocus();
     893           0 :     ImplMoveFocusByTabOrder( bForward, true );
     894           0 :     ShowFocus();
     895           0 : }
     896             : 
     897           0 : void ScOutlineWindow::GetFocus()
     898             : {
     899           0 :     Window::GetFocus();
     900           0 :     ShowFocus();
     901           0 : }
     902             : 
     903           0 : void ScOutlineWindow::LoseFocus()
     904             : {
     905           0 :     HideFocus();
     906           0 :     Window::LoseFocus();
     907           0 : }
     908             : 
     909             : // mouse ----------------------------------------------------------------------
     910             : 
     911           0 : void ScOutlineWindow::StartMouseTracking( size_t nLevel, size_t nEntry )
     912             : {
     913           0 :     mbMTActive = true;
     914           0 :     mnMTLevel = nLevel;
     915           0 :     mnMTEntry = nEntry;
     916           0 :     DrawBorderRel( nLevel, nEntry, true );
     917           0 : }
     918             : 
     919           0 : void ScOutlineWindow::EndMouseTracking()
     920             : {
     921           0 :     if ( mbMTPressed )
     922           0 :         DrawBorderRel( mnMTLevel, mnMTEntry, false );
     923           0 :     mbMTActive = false;
     924           0 : }
     925             : 
     926           0 : void ScOutlineWindow::MouseMove( const MouseEvent& rMEvt )
     927             : {
     928           0 :     if ( IsMouseTracking() )
     929             :     {
     930             :         size_t nLevel, nEntry;
     931           0 :         bool bHit = false;
     932             : 
     933           0 :         if ( ButtonHit( rMEvt.GetPosPixel(), nLevel, nEntry ) )
     934           0 :             bHit = (nLevel == mnMTLevel) && (nEntry == mnMTEntry);
     935             : 
     936           0 :         if ( bHit != mbMTPressed )
     937           0 :             DrawBorderRel( mnMTLevel, mnMTEntry, bHit );
     938             :     }
     939           0 : }
     940             : 
     941           0 : void ScOutlineWindow::MouseButtonUp( const MouseEvent& rMEvt )
     942             : {
     943           0 :     if ( IsMouseTracking() )
     944             :     {
     945           0 :         EndMouseTracking();
     946             : 
     947             :         size_t nLevel, nEntry;
     948           0 :         if ( ButtonHit( rMEvt.GetPosPixel(), nLevel, nEntry ) )
     949           0 :             if ( (nLevel == mnMTLevel) && (nEntry == mnMTEntry) )
     950           0 :                 DoFunction( nLevel, nEntry );
     951             :     }
     952           0 : }
     953             : 
     954           0 : void ScOutlineWindow::MouseButtonDown( const MouseEvent& rMEvt )
     955             : {
     956             :     size_t nLevel, nEntry;
     957           0 :     bool bHit = ButtonHit( rMEvt.GetPosPixel(), nLevel, nEntry );
     958           0 :     if ( bHit )
     959           0 :         StartMouseTracking( nLevel, nEntry );
     960           0 :     else if ( rMEvt.GetClicks() == 2 )
     961             :     {
     962           0 :         bHit = LineHit( rMEvt.GetPosPixel(), nLevel, nEntry );
     963           0 :         if ( bHit )
     964           0 :             DoFunction( nLevel, nEntry );
     965             :     }
     966             : 
     967             :     // if an item has been hit and window is focused, move focus to this item
     968           0 :     if ( bHit && HasFocus() )
     969             :     {
     970           0 :         HideFocus();
     971           0 :         mnFocusLevel = nLevel;
     972           0 :         mnFocusEntry = nEntry;
     973           0 :         ShowFocus();
     974             :     }
     975           0 : }
     976             : 
     977             : // keyboard -------------------------------------------------------------------
     978             : 
     979           0 : void ScOutlineWindow::KeyInput( const KeyEvent& rKEvt )
     980             : {
     981           0 :     const vcl::KeyCode& rKCode = rKEvt.GetKeyCode();
     982           0 :     bool bNoMod = !rKCode.GetModifier();
     983           0 :     bool bShift = (rKCode.GetModifier() == KEY_SHIFT);
     984           0 :     bool bCtrl = (rKCode.GetModifier() == KEY_MOD1);
     985             : 
     986           0 :     sal_uInt16 nCode = rKCode.GetCode();
     987           0 :     bool bUpDownKey = (nCode == KEY_UP) || (nCode == KEY_DOWN);
     988           0 :     bool bLeftRightKey = (nCode == KEY_LEFT) || (nCode == KEY_RIGHT);
     989             : 
     990             :     // TAB key
     991           0 :     if ( (nCode == KEY_TAB) && (bNoMod || bShift) )
     992             :         // move forward without SHIFT key
     993           0 :         MoveFocusByTabOrder( bNoMod );      // TAB uses logical order, regardless of mirroring
     994             : 
     995             :     // LEFT/RIGHT/UP/DOWN keys
     996           0 :     else if ( bNoMod && (bUpDownKey || bLeftRightKey) )
     997             :     {
     998           0 :         bool bForward = (nCode == KEY_DOWN) || (nCode == KEY_RIGHT);
     999           0 :         if ( mbHoriz == bLeftRightKey )
    1000             :             // move inside level with LEFT/RIGHT in horizontal and with UP/DOWN in vertical
    1001           0 :             MoveFocusByEntry( bForward != mbMirrorEntries );
    1002             :         else
    1003             :             // move to next/prev level with LEFT/RIGHT in vertical and with UP/DOWN in horizontal
    1004           0 :             MoveFocusByLevel( bForward != mbMirrorLevels );
    1005             :     }
    1006             : 
    1007             :     // CTRL + number
    1008           0 :     else if ( bCtrl && (nCode >= KEY_1) && (nCode <= KEY_9) )
    1009             :     {
    1010           0 :         size_t nLevel = static_cast< size_t >( nCode - KEY_1 );
    1011           0 :         if ( nLevel < GetLevelCount() )
    1012           0 :             DoFunction( nLevel, SC_OL_HEADERENTRY );
    1013             :     }
    1014             : 
    1015             :     // other key codes
    1016           0 :     else switch ( rKCode.GetFullCode() )
    1017             :     {
    1018           0 :         case KEY_ADD:       DoExpand( mnFocusLevel, mnFocusEntry );     break;
    1019           0 :         case KEY_SUBTRACT:  DoCollapse( mnFocusLevel, mnFocusEntry );   break;
    1020             :         case KEY_SPACE:
    1021           0 :         case KEY_RETURN:    DoFunction( mnFocusLevel, mnFocusEntry );   break;
    1022           0 :         default:            Window::KeyInput( rKEvt );
    1023             :     }
    1024         156 : }
    1025             : 
    1026             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11