merge the formfield patch from ooo-build
[ooovba.git] / vcl / source / window / taskpanelist.cxx
blobeaf1795d5e20c35fe9f5c98687ed0dfe3d6fde00
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: taskpanelist.cxx,v $
10 * $Revision: 1.24 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_vcl.hxx"
33 #include <vcl/svdata.hxx>
34 #include <tools/rcid.h>
35 #include <vcl/dockwin.hxx>
37 #include <vcl/taskpanelist.hxx>
38 #include <functional>
39 #include <algorithm>
41 // can't have static linkage because SUNPRO 5.2 complains
42 Point ImplTaskPaneListGetPos( const Window *w )
44 Point pos;
45 if( w->ImplIsDockingWindow() )
47 pos = ((DockingWindow*)w)->GetPosPixel();
48 Window *pF = ((DockingWindow*)w)->GetFloatingWindow();
49 if( pF )
50 pos = pF->OutputToAbsoluteScreenPixel( pF->ScreenToOutputPixel( pos ) );
51 else
52 pos = w->OutputToAbsoluteScreenPixel( pos );
54 else
55 pos = w->OutputToAbsoluteScreenPixel( w->GetPosPixel() );
57 return pos;
60 // compares window pos left-to-right
61 struct LTRSort : public ::std::binary_function< const Window*, const Window*, bool >
63 bool operator()( const Window* w1, const Window* w2 ) const
65 Point pos1(ImplTaskPaneListGetPos( w1 ));
66 Point pos2(ImplTaskPaneListGetPos( w2 ));
68 if( pos1.X() == pos2.X() )
69 return ( pos1.Y() < pos2.Y() );
70 else
71 return ( pos1.X() < pos2.X() );
74 struct LTRSortBackward : public ::std::binary_function< const Window*, const Window*, bool >
76 bool operator()( const Window* w2, const Window* w1 ) const
78 Point pos1(ImplTaskPaneListGetPos( w1 ));
79 Point pos2(ImplTaskPaneListGetPos( w2 ));
81 if( pos1.X() == pos2.X() )
82 return ( pos1.Y() < pos2.Y() );
83 else
84 return ( pos1.X() < pos2.X() );
88 // --------------------------------------------------
90 static void ImplTaskPaneListGrabFocus( Window *pWindow )
92 // put focus in child of floating windows which is typically a toolbar
93 // that can deal with the focus
94 if( pWindow->ImplIsFloatingWindow() && pWindow->GetWindow( WINDOW_FIRSTCHILD ) )
95 pWindow = pWindow->GetWindow( WINDOW_FIRSTCHILD );
96 pWindow->GrabFocus();
99 // --------------------------------------------------
101 TaskPaneList::TaskPaneList()
105 TaskPaneList::~TaskPaneList()
109 // --------------------------------------------------
111 void TaskPaneList::AddWindow( Window *pWindow )
113 #if OSL_DEBUG_LEVEL > 0
114 bool bDockingWindow=false;
115 bool bToolbox=false;
116 bool bDialog=false;
117 bool bUnknown=false;
118 #endif
120 if( pWindow )
122 #if OSL_DEBUG_LEVEL > 0
123 if( pWindow->GetType() == RSC_DOCKINGWINDOW )
124 bDockingWindow = true;
125 else if( pWindow->GetType() == RSC_TOOLBOX )
126 bToolbox = true;
127 else if( pWindow->IsDialog() )
128 bDialog = true;
129 else
130 bUnknown = true;
131 #endif
133 ::std::vector< Window* >::iterator insertionPos = mTaskPanes.end();
134 for ( ::std::vector< Window* >::iterator p = mTaskPanes.begin();
135 p != mTaskPanes.end();
139 if ( *p == pWindow )
140 // avoid duplicates
141 return;
143 // If the new window is the child of an existing pane window, or vice versa,
144 // ensure that in our pane list, *first* the child window appears, *then*
145 // the ancestor window.
146 // This is necessary for HandleKeyEvent: There, the list is traveled from the
147 // beginning, until the first window is found which has the ChildPathFocus. Now
148 // if this would be the ancestor window of another pane window, this would fudge
149 // the result
150 // 2004-09-27 - fs@openoffice.org, while fixing #i33573#, which included replacing
151 // the original fix for #98916# with this one here.
152 if ( pWindow->IsWindowOrChild( *p ) )
154 insertionPos = p + 1;
155 break;
157 if ( (*p)->IsWindowOrChild( pWindow ) )
159 insertionPos = p;
160 break;
164 mTaskPanes.insert( insertionPos, pWindow );
165 pWindow->ImplIsInTaskPaneList( TRUE );
169 // --------------------------------------------------
171 void TaskPaneList::RemoveWindow( Window *pWindow )
173 ::std::vector< Window* >::iterator p;
174 p = ::std::find( mTaskPanes.begin(), mTaskPanes.end(), pWindow );
175 if( p != mTaskPanes.end() )
177 mTaskPanes.erase( p );
178 pWindow->ImplIsInTaskPaneList( FALSE );
182 // --------------------------------------------------
184 BOOL TaskPaneList::IsInList( Window *pWindow )
186 ::std::vector< Window* >::iterator p;
187 p = ::std::find( mTaskPanes.begin(), mTaskPanes.end(), pWindow );
188 if( p != mTaskPanes.end() )
189 return TRUE;
190 else
191 return FALSE;
194 // --------------------------------------------------
196 BOOL TaskPaneList::HandleKeyEvent( KeyEvent aKeyEvent )
199 // F6 cycles through everything and works always
201 // MAV, #i104204#
202 // The old design was the following one:
203 // < Ctrl-TAB cycles through Menubar, Toolbars and Floatingwindows only and is
204 // < only active if one of those items has the focus
206 // Since the design of Ctrl-Tab looks to be inconsistent ( non-modal dialogs are not reachable
207 // and the shortcut conflicts with tab-control shortcut ), it is no more supported
208 BOOL bSplitterOnly = FALSE;
209 BOOL bFocusInList = FALSE;
210 KeyCode aKeyCode = aKeyEvent.GetKeyCode();
211 BOOL bForward = !aKeyCode.IsShift();
212 if( aKeyCode.GetCode() == KEY_F6 ) // F6
214 bSplitterOnly = aKeyCode.IsMod1() && aKeyCode.IsShift();
216 // is the focus in the list ?
217 ::std::vector< Window* >::iterator p = mTaskPanes.begin();
218 while( p != mTaskPanes.end() )
220 Window *pWin = *p;
221 if( pWin->HasChildPathFocus( TRUE ) )
223 bFocusInList = TRUE;
225 // Ctrl-F6 goes directly to the document
226 if( !pWin->IsDialog() && aKeyCode.IsMod1() && !aKeyCode.IsShift() )
228 pWin->GrabFocusToDocument();
229 return TRUE;
232 // activate next task pane
233 Window *pNextWin = NULL;
235 if( bSplitterOnly )
236 pNextWin = FindNextSplitter( *p, TRUE );
237 else
238 pNextWin = FindNextFloat( *p, bForward );
240 if( pNextWin != pWin )
242 ImplGetSVData()->maWinData.mbNoSaveFocus = TRUE;
243 ImplTaskPaneListGrabFocus( pNextWin );
244 ImplGetSVData()->maWinData.mbNoSaveFocus = FALSE;
246 else
248 // forward key if no splitter found
249 if( bSplitterOnly )
250 return FALSE;
252 // we did not find another taskpane, so
253 // put focus back into document
254 pWin->GrabFocusToDocument();
257 return TRUE;
259 else
260 p++;
263 // the focus is not in the list: activate first float if F6 was pressed
264 if( !bFocusInList )
266 Window *pWin;
267 if( bSplitterOnly )
268 pWin = FindNextSplitter( NULL, TRUE );
269 else
270 pWin = FindNextFloat( NULL, bForward );
271 if( pWin )
273 ImplTaskPaneListGrabFocus( pWin );
274 return TRUE;
279 return FALSE;
282 // --------------------------------------------------
284 // returns next valid pane
285 Window* TaskPaneList::FindNextPane( Window *pWindow, BOOL bForward )
287 if( bForward )
288 ::std::stable_sort( mTaskPanes.begin(), mTaskPanes.end(), LTRSort() );
289 else
290 ::std::stable_sort( mTaskPanes.begin(), mTaskPanes.end(), LTRSortBackward() );
292 ::std::vector< Window* >::iterator p = mTaskPanes.begin();
293 while( p != mTaskPanes.end() )
295 if( *p == pWindow )
297 unsigned n = mTaskPanes.size();
298 while( --n )
300 if( ++p == mTaskPanes.end() )
301 p = mTaskPanes.begin();
302 if( (*p)->IsReallyVisible() && !(*p)->IsDialog() && !(*p)->ImplIsSplitter() )
304 pWindow = *p;
305 break;
308 break;
310 else
311 ++p;
314 return pWindow;
317 // --------------------------------------------------
319 // returns next splitter
320 Window* TaskPaneList::FindNextSplitter( Window *pWindow, BOOL bForward )
322 if( bForward )
323 ::std::stable_sort( mTaskPanes.begin(), mTaskPanes.end(), LTRSort() );
324 else
325 ::std::stable_sort( mTaskPanes.begin(), mTaskPanes.end(), LTRSortBackward() );
327 ::std::vector< Window* >::iterator p = mTaskPanes.begin();
328 while( p != mTaskPanes.end() )
330 if( !pWindow || *p == pWindow )
332 unsigned n = mTaskPanes.size();
333 while( --n )
335 if( pWindow ) // increment before test
336 ++p;
337 if( p == mTaskPanes.end() )
338 p = mTaskPanes.begin();
339 if( (*p)->ImplIsSplitter() && (*p)->IsReallyVisible() && !(*p)->IsDialog() && (*p)->GetParent()->HasChildPathFocus() )
341 pWindow = *p;
342 break;
344 if( !pWindow ) // increment after test, otherwise first element is skipped
345 ++p;
347 break;
349 else
350 ++p;
353 return pWindow;
356 // --------------------------------------------------
358 // returns first valid item (regardless of type) if pWindow==0, otherwise returns next valid float
359 Window* TaskPaneList::FindNextFloat( Window *pWindow, BOOL bForward )
361 if( bForward )
362 ::std::stable_sort( mTaskPanes.begin(), mTaskPanes.end(), LTRSort() );
363 else
364 ::std::stable_sort( mTaskPanes.begin(), mTaskPanes.end(), LTRSortBackward() );
366 ::std::vector< Window* >::iterator p = mTaskPanes.begin();
367 while( p != mTaskPanes.end() )
369 if( !pWindow || *p == pWindow )
371 while( p != mTaskPanes.end() )
373 if( pWindow ) // increment before test
374 ++p;
375 if( p == mTaskPanes.end() )
376 break; // do not wrap, send focus back to document at end of list
377 /* #i83908# do not use the menubar if it is native and invisible
378 this relies on MenuBar::ImplCreate setting the height of the menubar
379 to 0 in this case
381 if( (*p)->IsReallyVisible() && !(*p)->ImplIsSplitter() &&
382 ( (*p)->GetType() != WINDOW_MENUBARWINDOW || (*p)->GetSizePixel().Height() > 0 )
385 pWindow = *p;
386 break;
388 if( !pWindow ) // increment after test, otherwise first element is skipped
389 ++p;
391 break;
393 else
394 ++p;
397 return pWindow;
400 // --------------------------------------------------