LCOV - code coverage report
Current view: top level - vcl/source/window - taskpanelist.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 27 134 20.1 %
Date: 2015-06-13 12:38:46 Functions: 5 12 41.7 %
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->IsDockingWindow() )
      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( GetWindowType::FirstChild ) )
      82           0 :         pWindow = pWindow->GetWindow( GetWindowType::FirstChild );
      83           0 :     pWindow->ImplGrabFocus( GetFocusFlags::F6 | (bForward ? GetFocusFlags::Forward : GetFocusFlags::Backward));
      84           0 : }
      85             : 
      86        3266 : TaskPaneList::TaskPaneList()
      87             : {
      88        3266 : }
      89             : 
      90        3258 : TaskPaneList::~TaskPaneList()
      91             : {
      92        3258 : }
      93             : 
      94       20190 : void TaskPaneList::AddWindow( vcl::Window *pWindow )
      95             : {
      96       20190 :     if( pWindow )
      97             :     {
      98       20190 :         auto insertionPos = mTaskPanes.end();
      99       74347 :         for ( auto p = mTaskPanes.begin(); p != mTaskPanes.end(); ++p )
     100             :         {
     101       54159 :             if ( *p == pWindow )
     102             :                 // avoid duplicates
     103       20190 :                 return;
     104             : 
     105             :             // If the new window is the child of an existing pane window, or vice versa,
     106             :             // ensure that in our pane list, *first* the child window appears, *then*
     107             :             // the ancestor window.
     108             :             // This is necessary for HandleKeyEvent: There, the list is traveled from the
     109             :             // beginning, until the first window is found which has the ChildPathFocus. Now
     110             :             // if this would be the ancestor window of another pane window, this would fudge
     111             :             // the result
     112       54159 :             if ( pWindow->IsWindowOrChild( *p ) )
     113             :             {
     114           0 :                 insertionPos = p + 1;
     115           0 :                 break;
     116             :             }
     117       54159 :             if ( (*p)->IsWindowOrChild( pWindow ) )
     118             :             {
     119           2 :                 insertionPos = p;
     120           2 :                 break;
     121             :             }
     122             :         }
     123             : 
     124       20190 :         mTaskPanes.insert( insertionPos, pWindow );
     125       20190 :         pWindow->ImplIsInTaskPaneList( true );
     126             :     }
     127             : }
     128             : 
     129       20153 : void TaskPaneList::RemoveWindow( vcl::Window *pWindow )
     130             : {
     131       20153 :     auto p = ::std::find( mTaskPanes.begin(), mTaskPanes.end(), VclPtr<vcl::Window>(pWindow) );
     132       20153 :     if( p != mTaskPanes.end() )
     133             :     {
     134       20153 :         mTaskPanes.erase( p );
     135       20153 :         pWindow->ImplIsInTaskPaneList( false );
     136             :     }
     137       20153 : }
     138             : 
     139       21158 : bool TaskPaneList::IsInList( vcl::Window *pWindow )
     140             : {
     141       21158 :     auto p = ::std::find( mTaskPanes.begin(), mTaskPanes.end(), VclPtr<vcl::Window>(pWindow) );
     142       21158 :     if( p != mTaskPanes.end() )
     143        6686 :         return true;
     144             :     else
     145       14472 :         return false;
     146             : }
     147             : 
     148           0 : bool TaskPaneList::HandleKeyEvent(const KeyEvent& rKeyEvent)
     149             : {
     150             : 
     151             :     // F6 cycles through everything and works always
     152             : 
     153             :     // MAV, #i104204#
     154             :     // The old design was the following one:
     155             :     // < Ctrl-TAB cycles through Menubar, Toolbars and Floatingwindows only and is
     156             :     // < only active if one of those items has the focus
     157             : 
     158             :     // Since the design of Ctrl-Tab looks to be inconsistent ( non-modal dialogs are not reachable
     159             :     // and the shortcut conflicts with tab-control shortcut ), it is no more supported
     160           0 :     vcl::KeyCode aKeyCode = rKeyEvent.GetKeyCode();
     161           0 :     bool bForward = !aKeyCode.IsShift();
     162           0 :     if( aKeyCode.GetCode() == KEY_F6 && ! aKeyCode.IsMod2() ) // F6
     163             :     {
     164           0 :         bool bSplitterOnly = false;
     165           0 :         bool bFocusInList = false;
     166             : 
     167           0 :         bSplitterOnly = aKeyCode.IsMod1() && aKeyCode.IsShift();
     168             : 
     169             :         // is the focus in the list ?
     170           0 :         auto p = mTaskPanes.begin();
     171           0 :         while( p != mTaskPanes.end() )
     172             :         {
     173           0 :             vcl::Window *pWin = *p;
     174           0 :             if( pWin->HasChildPathFocus( true ) )
     175             :             {
     176           0 :                 bFocusInList = true;
     177             : 
     178             :                 // Ctrl-F6 goes directly to the document
     179           0 :                 if( !pWin->IsDialog() && aKeyCode.IsMod1() && !aKeyCode.IsShift() )
     180             :                 {
     181           0 :                     pWin->ImplGrabFocusToDocument( GetFocusFlags::F6 );
     182           0 :                     return true;
     183             :                 }
     184             : 
     185             :                 // activate next task pane
     186           0 :                 vcl::Window *pNextWin = NULL;
     187             : 
     188           0 :                 if( bSplitterOnly )
     189           0 :                     pNextWin = FindNextSplitter( *p, true );
     190             :                 else
     191           0 :                     pNextWin = FindNextFloat( *p, bForward );
     192             : 
     193           0 :                 if( pNextWin != pWin )
     194             :                 {
     195           0 :                     ImplGetSVData()->maWinData.mbNoSaveFocus = true;
     196           0 :                     ImplTaskPaneListGrabFocus( pNextWin, bForward );
     197           0 :                     ImplGetSVData()->maWinData.mbNoSaveFocus = false;
     198             :                 }
     199             :                 else
     200             :                 {
     201             :                     // forward key if no splitter found
     202           0 :                     if( bSplitterOnly )
     203           0 :                         return false;
     204             : 
     205             :                     // we did not find another taskpane, so
     206             :                     // put focus back into document
     207           0 :                     pWin->ImplGrabFocusToDocument( GetFocusFlags::F6 | (bForward ? GetFocusFlags::Forward : GetFocusFlags::Backward));
     208             :                 }
     209             : 
     210           0 :                 return true;
     211             :             }
     212             :             else
     213           0 :                 ++p;
     214             :         }
     215             : 
     216             :         // the focus is not in the list: activate first float if F6 was pressed
     217           0 :         if( !bFocusInList )
     218             :         {
     219             :             vcl::Window *pWin;
     220           0 :             if( bSplitterOnly )
     221           0 :                 pWin = FindNextSplitter( NULL, true );
     222             :             else
     223           0 :                 pWin = FindNextFloat( NULL, bForward );
     224           0 :             if( pWin )
     225             :             {
     226           0 :                 ImplTaskPaneListGrabFocus( pWin, bForward );
     227           0 :                 return true;
     228             :             }
     229             :         }
     230             :     }
     231             : 
     232           0 :     return false;
     233             : }
     234             : 
     235             : // returns next splitter
     236           0 : vcl::Window* TaskPaneList::FindNextSplitter( vcl::Window *pWindow, bool bForward )
     237             : {
     238           0 :     if( bForward )
     239           0 :         ::std::stable_sort( mTaskPanes.begin(), mTaskPanes.end(), LTRSort() );
     240             :     else
     241           0 :         ::std::stable_sort( mTaskPanes.begin(), mTaskPanes.end(), LTRSortBackward() );
     242             : 
     243           0 :     auto p = mTaskPanes.begin();
     244           0 :     while( p != mTaskPanes.end() )
     245             :     {
     246           0 :         if( !pWindow || *p == pWindow )
     247             :         {
     248           0 :             unsigned n = mTaskPanes.size();
     249           0 :             while( --n )
     250             :             {
     251           0 :                 if( pWindow )   // increment before test
     252           0 :                     ++p;
     253           0 :                 if( p == mTaskPanes.end() )
     254           0 :                     p = mTaskPanes.begin();
     255           0 :                 if( (*p)->ImplIsSplitter() && (*p)->IsReallyVisible() && !(*p)->IsDialog() && (*p)->GetParent()->HasChildPathFocus() )
     256             :                 {
     257           0 :                     pWindow = *p;
     258           0 :                     break;
     259             :                 }
     260           0 :                 if( !pWindow )  // increment after test, otherwise first element is skipped
     261           0 :                     ++p;
     262             :             }
     263           0 :             break;
     264             :         }
     265             :         else
     266           0 :             ++p;
     267             :     }
     268             : 
     269           0 :     return pWindow;
     270             : }
     271             : 
     272             : // returns first valid item (regardless of type) if pWindow==0, otherwise returns next valid float
     273           0 : vcl::Window* TaskPaneList::FindNextFloat( vcl::Window *pWindow, bool bForward )
     274             : {
     275           0 :     if( bForward )
     276           0 :         ::std::stable_sort( mTaskPanes.begin(), mTaskPanes.end(), LTRSort() );
     277             :     else
     278           0 :         ::std::stable_sort( mTaskPanes.begin(), mTaskPanes.end(), LTRSortBackward() );
     279             : 
     280           0 :     auto p = mTaskPanes.begin();
     281           0 :     while( p != mTaskPanes.end() )
     282             :     {
     283           0 :         if( !pWindow || *p == pWindow )
     284             :         {
     285           0 :             while( p != mTaskPanes.end() )
     286             :             {
     287           0 :                 if( pWindow )   // increment before test
     288           0 :                     ++p;
     289           0 :                 if( p == mTaskPanes.end() )
     290           0 :                     break; // do not wrap, send focus back to document at end of list
     291             :                 /* #i83908# do not use the menubar if it is native and invisible
     292             :                    this relies on MenuBar::ImplCreate setting the height of the menubar
     293             :                    to 0 in this case
     294             :                 */
     295           0 :                 if( (*p)->IsReallyVisible() && !(*p)->ImplIsSplitter() &&
     296           0 :                     ( (*p)->GetType() != WINDOW_MENUBARWINDOW || (*p)->GetSizePixel().Height() > 0 )
     297             :                     )
     298             :                 {
     299           0 :                     pWindow = *p;
     300           0 :                     break;
     301             :                 }
     302           0 :                 if( !pWindow )  // increment after test, otherwise first element is skipped
     303           0 :                     ++p;
     304             :             }
     305           0 :             break;
     306             :         }
     307             :         else
     308           0 :             ++p;
     309             :     }
     310             : 
     311           0 :     return pWindow;
     312             : }
     313             : 
     314             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11