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

Generated by: LCOV version 1.10