LCOV - code coverage report
Current view: top level - vcl/source/window - taskpanelist.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 31 138 22.5 %
Date: 2014-11-03 Functions: 7 14 50.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include <tools/rcid.h>
      21             : 
      22             : #include <vcl/dockwin.hxx>
      23             : #include <vcl/taskpanelist.hxx>
      24             : 
      25             : #include <svdata.hxx>
      26             : 
      27             : #include <functional>
      28             : #include <algorithm>
      29             : 
      30             : // can't have static linkage because SUNPRO 5.2 complains
      31           0 : Point ImplTaskPaneListGetPos( const vcl::Window *w )
      32             : {
      33           0 :     Point pos;
      34           0 :     if( w->ImplIsDockingWindow() )
      35             :     {
      36           0 :         pos = static_cast<const DockingWindow*>(w)->GetPosPixel();
      37           0 :         vcl::Window *pF = static_cast<const DockingWindow*>(w)->GetFloatingWindow();
      38           0 :         if( pF )
      39           0 :             pos = pF->OutputToAbsoluteScreenPixel( pF->ScreenToOutputPixel( pos ) );
      40             :         else
      41           0 :             pos = w->OutputToAbsoluteScreenPixel( pos );
      42             :     }
      43             :     else
      44           0 :         pos = w->OutputToAbsoluteScreenPixel( w->GetPosPixel() );
      45             : 
      46           0 :     return pos;
      47             : }
      48             : 
      49             : // compares window pos left-to-right
      50             : struct LTRSort : public ::std::binary_function< const vcl::Window*, const vcl::Window*, bool >
      51             : {
      52           0 :     bool operator()( const vcl::Window* w1, const vcl::Window* w2 ) const
      53             :     {
      54           0 :         Point pos1(ImplTaskPaneListGetPos( w1 ));
      55           0 :         Point pos2(ImplTaskPaneListGetPos( w2 ));
      56             : 
      57           0 :         if( pos1.X() == pos2.X() )
      58           0 :             return ( pos1.Y() < pos2.Y() );
      59             :         else
      60           0 :             return ( pos1.X() < pos2.X() );
      61             :     }
      62             : };
      63             : struct LTRSortBackward : public ::std::binary_function< const vcl::Window*, const vcl::Window*, bool >
      64             : {
      65           0 :     bool operator()( const vcl::Window* w2, const vcl::Window* w1 ) const
      66             :     {
      67           0 :         Point pos1(ImplTaskPaneListGetPos( w1 ));
      68           0 :         Point pos2(ImplTaskPaneListGetPos( w2 ));
      69             : 
      70           0 :         if( pos1.X() == pos2.X() )
      71           0 :             return ( pos1.Y() < pos2.Y() );
      72             :         else
      73           0 :             return ( pos1.X() < pos2.X() );
      74             :     }
      75             : };
      76             : 
      77           0 : static void ImplTaskPaneListGrabFocus( vcl::Window *pWindow, bool bForward )
      78             : {
      79             :     // put focus in child of floating windows which is typically a toolbar
      80             :     // that can deal with the focus
      81           0 :     if( pWindow->ImplIsFloatingWindow() && pWindow->GetWindow( WINDOW_FIRSTCHILD ) )
      82           0 :         pWindow = pWindow->GetWindow( WINDOW_FIRSTCHILD );
      83           0 :     pWindow->ImplGrabFocus( GETFOCUS_F6 | (bForward ? GETFOCUS_FORWARD : GETFOCUS_BACKWARD));
      84           0 : }
      85             : 
      86        5548 : TaskPaneList::TaskPaneList()
      87             : {
      88        5548 : }
      89             : 
      90        5542 : TaskPaneList::~TaskPaneList()
      91             : {
      92        5542 : }
      93             : 
      94       33866 : void TaskPaneList::AddWindow( vcl::Window *pWindow )
      95             : {
      96       33866 :     if( pWindow )
      97             :     {
      98       33866 :         ::std::vector< vcl::Window* >::iterator insertionPos = mTaskPanes.end();
      99      366390 :         for ( ::std::vector< vcl::Window* >::iterator p = mTaskPanes.begin();
     100      244260 :               p != mTaskPanes.end();
     101             :               ++p
     102             :             )
     103             :         {
     104       88268 :             if ( *p == pWindow )
     105             :                 // avoid duplicates
     106       33866 :                 return;
     107             : 
     108             :             // If the new window is the child of an existing pane window, or vice versa,
     109             :             // ensure that in our pane list, *first* the child window appears, *then*
     110             :             // the ancestor window.
     111             :             // This is necessary for HandleKeyEvent: There, the list is traveled from the
     112             :             // beginning, until the first window is found which has the ChildPathFocus. Now
     113             :             // if this would be the ancestor window of another pane window, this would fudge
     114             :             // the result
     115       88268 :             if ( pWindow->IsWindowOrChild( *p ) )
     116             :             {
     117           0 :                 insertionPos = p + 1;
     118           0 :                 break;
     119             :             }
     120       88268 :             if ( (*p)->IsWindowOrChild( pWindow ) )
     121             :             {
     122           4 :                 insertionPos = p;
     123           4 :                 break;
     124             :             }
     125             :         }
     126             : 
     127       33866 :         mTaskPanes.insert( insertionPos, pWindow );
     128       33866 :         pWindow->ImplIsInTaskPaneList( true );
     129             :     }
     130             : }
     131             : 
     132       33852 : void TaskPaneList::RemoveWindow( vcl::Window *pWindow )
     133             : {
     134       33852 :     ::std::vector< vcl::Window* >::iterator p;
     135       33852 :     p = ::std::find( mTaskPanes.begin(), mTaskPanes.end(), pWindow );
     136       33852 :     if( p != mTaskPanes.end() )
     137             :     {
     138       33852 :         mTaskPanes.erase( p );
     139       33852 :         pWindow->ImplIsInTaskPaneList( false );
     140             :     }
     141       33852 : }
     142             : 
     143       26312 : bool TaskPaneList::IsInList( vcl::Window *pWindow )
     144             : {
     145       26312 :     ::std::vector< vcl::Window* >::iterator p;
     146       26312 :     p = ::std::find( mTaskPanes.begin(), mTaskPanes.end(), pWindow );
     147       26312 :     if( p != mTaskPanes.end() )
     148       11542 :         return true;
     149             :     else
     150       14770 :         return false;
     151             : }
     152             : 
     153           0 : bool TaskPaneList::HandleKeyEvent( KeyEvent aKeyEvent )
     154             : {
     155             : 
     156             :     // F6 cycles through everything and works always
     157             : 
     158             :     // MAV, #i104204#
     159             :     // The old design was the following one:
     160             :     // < Ctrl-TAB cycles through Menubar, Toolbars and Floatingwindows only and is
     161             :     // < only active if one of those items has the focus
     162             : 
     163             :     // Since the design of Ctrl-Tab looks to be inconsistent ( non-modal dialogs are not reachable
     164             :     // and the shortcut conflicts with tab-control shortcut ), it is no more supported
     165           0 :     bool bSplitterOnly = false;
     166           0 :     bool bFocusInList = false;
     167           0 :     vcl::KeyCode aKeyCode = aKeyEvent.GetKeyCode();
     168           0 :     bool bForward = !aKeyCode.IsShift();
     169           0 :     if( aKeyCode.GetCode() == KEY_F6 && ! aKeyCode.IsMod2() ) // F6
     170             :     {
     171           0 :         bSplitterOnly = aKeyCode.IsMod1() && aKeyCode.IsShift();
     172             : 
     173             :         // is the focus in the list ?
     174           0 :         ::std::vector< vcl::Window* >::iterator p = mTaskPanes.begin();
     175           0 :         while( p != mTaskPanes.end() )
     176             :         {
     177           0 :             vcl::Window *pWin = *p;
     178           0 :             if( pWin->HasChildPathFocus( true ) )
     179             :             {
     180           0 :                 bFocusInList = true;
     181             : 
     182             :                 // Ctrl-F6 goes directly to the document
     183           0 :                 if( !pWin->IsDialog() && aKeyCode.IsMod1() && !aKeyCode.IsShift() )
     184             :                 {
     185           0 :                     pWin->ImplGrabFocusToDocument( GETFOCUS_F6 );
     186           0 :                     return true;
     187             :                 }
     188             : 
     189             :                 // activate next task pane
     190           0 :                 vcl::Window *pNextWin = NULL;
     191             : 
     192           0 :                 if( bSplitterOnly )
     193           0 :                     pNextWin = FindNextSplitter( *p, true );
     194             :                 else
     195           0 :                     pNextWin = FindNextFloat( *p, bForward );
     196             : 
     197           0 :                 if( pNextWin != pWin )
     198             :                 {
     199           0 :                     ImplGetSVData()->maWinData.mbNoSaveFocus = true;
     200           0 :                     ImplTaskPaneListGrabFocus( pNextWin, bForward );
     201           0 :                     ImplGetSVData()->maWinData.mbNoSaveFocus = false;
     202             :                 }
     203             :                 else
     204             :                 {
     205             :                     // forward key if no splitter found
     206           0 :                     if( bSplitterOnly )
     207           0 :                         return false;
     208             : 
     209             :                     // we did not find another taskpane, so
     210             :                     // put focus back into document
     211           0 :                     pWin->ImplGrabFocusToDocument( GETFOCUS_F6 | (bForward ? GETFOCUS_FORWARD : GETFOCUS_BACKWARD));
     212             :                 }
     213             : 
     214           0 :                 return true;
     215             :             }
     216             :             else
     217           0 :                 ++p;
     218             :         }
     219             : 
     220             :         // the focus is not in the list: activate first float if F6 was pressed
     221           0 :         if( !bFocusInList )
     222             :         {
     223             :             vcl::Window *pWin;
     224           0 :             if( bSplitterOnly )
     225           0 :                 pWin = FindNextSplitter( NULL, true );
     226             :             else
     227           0 :                 pWin = FindNextFloat( NULL, bForward );
     228           0 :             if( pWin )
     229             :             {
     230           0 :                 ImplTaskPaneListGrabFocus( pWin, bForward );
     231           0 :                 return true;
     232             :             }
     233             :         }
     234             :     }
     235             : 
     236           0 :     return false;
     237             : }
     238             : 
     239             : // returns next splitter
     240           0 : vcl::Window* TaskPaneList::FindNextSplitter( vcl::Window *pWindow, bool bForward )
     241             : {
     242           0 :     if( bForward )
     243           0 :         ::std::stable_sort( mTaskPanes.begin(), mTaskPanes.end(), LTRSort() );
     244             :     else
     245           0 :         ::std::stable_sort( mTaskPanes.begin(), mTaskPanes.end(), LTRSortBackward() );
     246             : 
     247           0 :     ::std::vector< vcl::Window* >::iterator p = mTaskPanes.begin();
     248           0 :     while( p != mTaskPanes.end() )
     249             :     {
     250           0 :         if( !pWindow || *p == pWindow )
     251             :         {
     252           0 :             unsigned n = mTaskPanes.size();
     253           0 :             while( --n )
     254             :             {
     255           0 :                 if( pWindow )   // increment before test
     256           0 :                     ++p;
     257           0 :                 if( p == mTaskPanes.end() )
     258           0 :                     p = mTaskPanes.begin();
     259           0 :                 if( (*p)->ImplIsSplitter() && (*p)->IsReallyVisible() && !(*p)->IsDialog() && (*p)->GetParent()->HasChildPathFocus() )
     260             :                 {
     261           0 :                     pWindow = *p;
     262           0 :                     break;
     263             :                 }
     264           0 :                 if( !pWindow )  // increment after test, otherwise first element is skipped
     265           0 :                     ++p;
     266             :             }
     267           0 :             break;
     268             :         }
     269             :         else
     270           0 :             ++p;
     271             :     }
     272             : 
     273           0 :     return pWindow;
     274             : }
     275             : 
     276             : // returns first valid item (regardless of type) if pWindow==0, otherwise returns next valid float
     277           0 : vcl::Window* TaskPaneList::FindNextFloat( vcl::Window *pWindow, bool bForward )
     278             : {
     279           0 :     if( bForward )
     280           0 :         ::std::stable_sort( mTaskPanes.begin(), mTaskPanes.end(), LTRSort() );
     281             :     else
     282           0 :         ::std::stable_sort( mTaskPanes.begin(), mTaskPanes.end(), LTRSortBackward() );
     283             : 
     284           0 :     ::std::vector< vcl::Window* >::iterator p = mTaskPanes.begin();
     285           0 :     while( p != mTaskPanes.end() )
     286             :     {
     287           0 :         if( !pWindow || *p == pWindow )
     288             :         {
     289           0 :             while( p != mTaskPanes.end() )
     290             :             {
     291           0 :                 if( pWindow )   // increment before test
     292           0 :                     ++p;
     293           0 :                 if( p == mTaskPanes.end() )
     294           0 :                     break; // do not wrap, send focus back to document at end of list
     295             :                 /* #i83908# do not use the menubar if it is native and invisible
     296             :                    this relies on MenuBar::ImplCreate setting the height of the menubar
     297             :                    to 0 in this case
     298             :                 */
     299           0 :                 if( (*p)->IsReallyVisible() && !(*p)->ImplIsSplitter() &&
     300           0 :                     ( (*p)->GetType() != WINDOW_MENUBARWINDOW || (*p)->GetSizePixel().Height() > 0 )
     301             :                     )
     302             :                 {
     303           0 :                     pWindow = *p;
     304           0 :                     break;
     305             :                 }
     306           0 :                 if( !pWindow )  // increment after test, otherwise first element is skipped
     307           0 :                     ++p;
     308             :             }
     309           0 :             break;
     310             :         }
     311             :         else
     312           0 :             ++p;
     313             :     }
     314             : 
     315           0 :     return pWindow;
     316        1233 : }
     317             : 
     318             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10