summaryrefslogtreecommitdiff
path: root/vcl/source/window/taskpanelist.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'vcl/source/window/taskpanelist.cxx')
-rw-r--r--vcl/source/window/taskpanelist.cxx398
1 files changed, 398 insertions, 0 deletions
diff --git a/vcl/source/window/taskpanelist.cxx b/vcl/source/window/taskpanelist.cxx
new file mode 100644
index 000000000000..c09dc464b809
--- /dev/null
+++ b/vcl/source/window/taskpanelist.cxx
@@ -0,0 +1,398 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_vcl.hxx"
+#include <vcl/svdata.hxx>
+#include <tools/rcid.h>
+#include <vcl/dockwin.hxx>
+
+#include <vcl/taskpanelist.hxx>
+#include <functional>
+#include <algorithm>
+
+// can't have static linkage because SUNPRO 5.2 complains
+Point ImplTaskPaneListGetPos( const Window *w )
+{
+ Point pos;
+ if( w->ImplIsDockingWindow() )
+ {
+ pos = ((DockingWindow*)w)->GetPosPixel();
+ Window *pF = ((DockingWindow*)w)->GetFloatingWindow();
+ if( pF )
+ pos = pF->OutputToAbsoluteScreenPixel( pF->ScreenToOutputPixel( pos ) );
+ else
+ pos = w->OutputToAbsoluteScreenPixel( pos );
+ }
+ else
+ pos = w->OutputToAbsoluteScreenPixel( w->GetPosPixel() );
+
+ return pos;
+}
+
+// compares window pos left-to-right
+struct LTRSort : public ::std::binary_function< const Window*, const Window*, bool >
+{
+ bool operator()( const Window* w1, const Window* w2 ) const
+ {
+ Point pos1(ImplTaskPaneListGetPos( w1 ));
+ Point pos2(ImplTaskPaneListGetPos( w2 ));
+
+ if( pos1.X() == pos2.X() )
+ return ( pos1.Y() < pos2.Y() );
+ else
+ return ( pos1.X() < pos2.X() );
+ }
+};
+struct LTRSortBackward : public ::std::binary_function< const Window*, const Window*, bool >
+{
+ bool operator()( const Window* w2, const Window* w1 ) const
+ {
+ Point pos1(ImplTaskPaneListGetPos( w1 ));
+ Point pos2(ImplTaskPaneListGetPos( w2 ));
+
+ if( pos1.X() == pos2.X() )
+ return ( pos1.Y() < pos2.Y() );
+ else
+ return ( pos1.X() < pos2.X() );
+ }
+};
+
+// --------------------------------------------------
+
+static void ImplTaskPaneListGrabFocus( Window *pWindow )
+{
+ // put focus in child of floating windows which is typically a toolbar
+ // that can deal with the focus
+ if( pWindow->ImplIsFloatingWindow() && pWindow->GetWindow( WINDOW_FIRSTCHILD ) )
+ pWindow = pWindow->GetWindow( WINDOW_FIRSTCHILD );
+ pWindow->GrabFocus();
+}
+
+// --------------------------------------------------
+
+TaskPaneList::TaskPaneList()
+{
+}
+
+TaskPaneList::~TaskPaneList()
+{
+}
+
+// --------------------------------------------------
+
+void TaskPaneList::AddWindow( Window *pWindow )
+{
+#if OSL_DEBUG_LEVEL > 0
+ bool bDockingWindow=false;
+ bool bToolbox=false;
+ bool bDialog=false;
+ bool bUnknown=false;
+#endif
+
+ if( pWindow )
+ {
+#if OSL_DEBUG_LEVEL > 0
+ if( pWindow->GetType() == RSC_DOCKINGWINDOW )
+ bDockingWindow = true;
+ else if( pWindow->GetType() == RSC_TOOLBOX )
+ bToolbox = true;
+ else if( pWindow->IsDialog() )
+ bDialog = true;
+ else
+ bUnknown = true;
+#endif
+
+ ::std::vector< Window* >::iterator insertionPos = mTaskPanes.end();
+ for ( ::std::vector< Window* >::iterator p = mTaskPanes.begin();
+ p != mTaskPanes.end();
+ ++p
+ )
+ {
+ if ( *p == pWindow )
+ // avoid duplicates
+ return;
+
+ // If the new window is the child of an existing pane window, or vice versa,
+ // ensure that in our pane list, *first* the child window appears, *then*
+ // the ancestor window.
+ // This is necessary for HandleKeyEvent: There, the list is traveled from the
+ // beginning, until the first window is found which has the ChildPathFocus. Now
+ // if this would be the ancestor window of another pane window, this would fudge
+ // the result
+ // 2004-09-27 - fs@openoffice.org, while fixing #i33573#, which included replacing
+ // the original fix for #98916# with this one here.
+ if ( pWindow->IsWindowOrChild( *p ) )
+ {
+ insertionPos = p + 1;
+ break;
+ }
+ if ( (*p)->IsWindowOrChild( pWindow ) )
+ {
+ insertionPos = p;
+ break;
+ }
+ }
+
+ mTaskPanes.insert( insertionPos, pWindow );
+ pWindow->ImplIsInTaskPaneList( TRUE );
+ }
+}
+
+// --------------------------------------------------
+
+void TaskPaneList::RemoveWindow( Window *pWindow )
+{
+ ::std::vector< Window* >::iterator p;
+ p = ::std::find( mTaskPanes.begin(), mTaskPanes.end(), pWindow );
+ if( p != mTaskPanes.end() )
+ {
+ mTaskPanes.erase( p );
+ pWindow->ImplIsInTaskPaneList( FALSE );
+ }
+}
+
+// --------------------------------------------------
+
+BOOL TaskPaneList::IsInList( Window *pWindow )
+{
+ ::std::vector< Window* >::iterator p;
+ p = ::std::find( mTaskPanes.begin(), mTaskPanes.end(), pWindow );
+ if( p != mTaskPanes.end() )
+ return TRUE;
+ else
+ return FALSE;
+}
+
+// --------------------------------------------------
+
+BOOL TaskPaneList::HandleKeyEvent( KeyEvent aKeyEvent )
+{
+
+ // F6 cycles through everything and works always
+
+ // MAV, #i104204#
+ // The old design was the following one:
+ // < Ctrl-TAB cycles through Menubar, Toolbars and Floatingwindows only and is
+ // < only active if one of those items has the focus
+ //
+ // Since the design of Ctrl-Tab looks to be inconsistent ( non-modal dialogs are not reachable
+ // and the shortcut conflicts with tab-control shortcut ), it is no more supported
+ BOOL bSplitterOnly = FALSE;
+ BOOL bFocusInList = FALSE;
+ KeyCode aKeyCode = aKeyEvent.GetKeyCode();
+ BOOL bForward = !aKeyCode.IsShift();
+ if( aKeyCode.GetCode() == KEY_F6 ) // F6
+ {
+ bSplitterOnly = aKeyCode.IsMod1() && aKeyCode.IsShift();
+
+ // is the focus in the list ?
+ ::std::vector< Window* >::iterator p = mTaskPanes.begin();
+ while( p != mTaskPanes.end() )
+ {
+ Window *pWin = *p;
+ if( pWin->HasChildPathFocus( TRUE ) )
+ {
+ bFocusInList = TRUE;
+
+ // Ctrl-F6 goes directly to the document
+ if( !pWin->IsDialog() && aKeyCode.IsMod1() && !aKeyCode.IsShift() )
+ {
+ pWin->GrabFocusToDocument();
+ return TRUE;
+ }
+
+ // activate next task pane
+ Window *pNextWin = NULL;
+
+ if( bSplitterOnly )
+ pNextWin = FindNextSplitter( *p, TRUE );
+ else
+ pNextWin = FindNextFloat( *p, bForward );
+
+ if( pNextWin != pWin )
+ {
+ ImplGetSVData()->maWinData.mbNoSaveFocus = TRUE;
+ ImplTaskPaneListGrabFocus( pNextWin );
+ ImplGetSVData()->maWinData.mbNoSaveFocus = FALSE;
+ }
+ else
+ {
+ // forward key if no splitter found
+ if( bSplitterOnly )
+ return FALSE;
+
+ // we did not find another taskpane, so
+ // put focus back into document
+ pWin->GrabFocusToDocument();
+ }
+
+ return TRUE;
+ }
+ else
+ p++;
+ }
+
+ // the focus is not in the list: activate first float if F6 was pressed
+ if( !bFocusInList )
+ {
+ Window *pWin;
+ if( bSplitterOnly )
+ pWin = FindNextSplitter( NULL, TRUE );
+ else
+ pWin = FindNextFloat( NULL, bForward );
+ if( pWin )
+ {
+ ImplTaskPaneListGrabFocus( pWin );
+ return TRUE;
+ }
+ }
+ }
+
+ return FALSE;
+}
+
+// --------------------------------------------------
+
+// returns next valid pane
+Window* TaskPaneList::FindNextPane( Window *pWindow, BOOL bForward )
+{
+ if( bForward )
+ ::std::stable_sort( mTaskPanes.begin(), mTaskPanes.end(), LTRSort() );
+ else
+ ::std::stable_sort( mTaskPanes.begin(), mTaskPanes.end(), LTRSortBackward() );
+
+ ::std::vector< Window* >::iterator p = mTaskPanes.begin();
+ while( p != mTaskPanes.end() )
+ {
+ if( *p == pWindow )
+ {
+ unsigned n = mTaskPanes.size();
+ while( --n )
+ {
+ if( ++p == mTaskPanes.end() )
+ p = mTaskPanes.begin();
+ if( (*p)->IsReallyVisible() && !(*p)->IsDialog() && !(*p)->ImplIsSplitter() )
+ {
+ pWindow = *p;
+ break;
+ }
+ }
+ break;
+ }
+ else
+ ++p;
+ }
+
+ return pWindow;
+}
+
+// --------------------------------------------------
+
+// returns next splitter
+Window* TaskPaneList::FindNextSplitter( Window *pWindow, BOOL bForward )
+{
+ if( bForward )
+ ::std::stable_sort( mTaskPanes.begin(), mTaskPanes.end(), LTRSort() );
+ else
+ ::std::stable_sort( mTaskPanes.begin(), mTaskPanes.end(), LTRSortBackward() );
+
+ ::std::vector< Window* >::iterator p = mTaskPanes.begin();
+ while( p != mTaskPanes.end() )
+ {
+ if( !pWindow || *p == pWindow )
+ {
+ unsigned n = mTaskPanes.size();
+ while( --n )
+ {
+ if( pWindow ) // increment before test
+ ++p;
+ if( p == mTaskPanes.end() )
+ p = mTaskPanes.begin();
+ if( (*p)->ImplIsSplitter() && (*p)->IsReallyVisible() && !(*p)->IsDialog() && (*p)->GetParent()->HasChildPathFocus() )
+ {
+ pWindow = *p;
+ break;
+ }
+ if( !pWindow ) // increment after test, otherwise first element is skipped
+ ++p;
+ }
+ break;
+ }
+ else
+ ++p;
+ }
+
+ return pWindow;
+}
+
+// --------------------------------------------------
+
+// returns first valid item (regardless of type) if pWindow==0, otherwise returns next valid float
+Window* TaskPaneList::FindNextFloat( Window *pWindow, BOOL bForward )
+{
+ if( bForward )
+ ::std::stable_sort( mTaskPanes.begin(), mTaskPanes.end(), LTRSort() );
+ else
+ ::std::stable_sort( mTaskPanes.begin(), mTaskPanes.end(), LTRSortBackward() );
+
+ ::std::vector< Window* >::iterator p = mTaskPanes.begin();
+ while( p != mTaskPanes.end() )
+ {
+ if( !pWindow || *p == pWindow )
+ {
+ while( p != mTaskPanes.end() )
+ {
+ if( pWindow ) // increment before test
+ ++p;
+ if( p == mTaskPanes.end() )
+ break; // do not wrap, send focus back to document at end of list
+ /* #i83908# do not use the menubar if it is native and invisible
+ this relies on MenuBar::ImplCreate setting the height of the menubar
+ to 0 in this case
+ */
+ if( (*p)->IsReallyVisible() && !(*p)->ImplIsSplitter() &&
+ ( (*p)->GetType() != WINDOW_MENUBARWINDOW || (*p)->GetSizePixel().Height() > 0 )
+ )
+ {
+ pWindow = *p;
+ break;
+ }
+ if( !pWindow ) // increment after test, otherwise first element is skipped
+ ++p;
+ }
+ break;
+ }
+ else
+ ++p;
+ }
+
+ return pWindow;
+}
+
+// --------------------------------------------------
+