1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: taskpanelist.cxx,v $
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>
41 // can't have static linkage because SUNPRO 5.2 complains
42 Point
ImplTaskPaneListGetPos( const Window
*w
)
45 if( w
->ImplIsDockingWindow() )
47 pos
= ((DockingWindow
*)w
)->GetPosPixel();
48 Window
*pF
= ((DockingWindow
*)w
)->GetFloatingWindow();
50 pos
= pF
->OutputToAbsoluteScreenPixel( pF
->ScreenToOutputPixel( pos
) );
52 pos
= w
->OutputToAbsoluteScreenPixel( pos
);
55 pos
= w
->OutputToAbsoluteScreenPixel( w
->GetPosPixel() );
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() );
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() );
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
);
99 // --------------------------------------------------
101 TaskPaneList::TaskPaneList()
105 TaskPaneList::~TaskPaneList()
109 // --------------------------------------------------
111 void TaskPaneList::AddWindow( Window
*pWindow
)
113 #if OSL_DEBUG_LEVEL > 0
114 bool bDockingWindow
=false;
122 #if OSL_DEBUG_LEVEL > 0
123 if( pWindow
->GetType() == RSC_DOCKINGWINDOW
)
124 bDockingWindow
= true;
125 else if( pWindow
->GetType() == RSC_TOOLBOX
)
127 else if( pWindow
->IsDialog() )
133 ::std::vector
< Window
* >::iterator insertionPos
= mTaskPanes
.end();
134 for ( ::std::vector
< Window
* >::iterator p
= mTaskPanes
.begin();
135 p
!= mTaskPanes
.end();
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
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;
157 if ( (*p
)->IsWindowOrChild( pWindow
) )
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() )
194 // --------------------------------------------------
196 BOOL
TaskPaneList::HandleKeyEvent( KeyEvent aKeyEvent
)
199 // F6 cycles through everything and works always
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() )
221 if( pWin
->HasChildPathFocus( TRUE
) )
225 // Ctrl-F6 goes directly to the document
226 if( !pWin
->IsDialog() && aKeyCode
.IsMod1() && !aKeyCode
.IsShift() )
228 pWin
->GrabFocusToDocument();
232 // activate next task pane
233 Window
*pNextWin
= NULL
;
236 pNextWin
= FindNextSplitter( *p
, TRUE
);
238 pNextWin
= FindNextFloat( *p
, bForward
);
240 if( pNextWin
!= pWin
)
242 ImplGetSVData()->maWinData
.mbNoSaveFocus
= TRUE
;
243 ImplTaskPaneListGrabFocus( pNextWin
);
244 ImplGetSVData()->maWinData
.mbNoSaveFocus
= FALSE
;
248 // forward key if no splitter found
252 // we did not find another taskpane, so
253 // put focus back into document
254 pWin
->GrabFocusToDocument();
263 // the focus is not in the list: activate first float if F6 was pressed
268 pWin
= FindNextSplitter( NULL
, TRUE
);
270 pWin
= FindNextFloat( NULL
, bForward
);
273 ImplTaskPaneListGrabFocus( pWin
);
282 // --------------------------------------------------
284 // returns next valid pane
285 Window
* TaskPaneList::FindNextPane( Window
*pWindow
, BOOL bForward
)
288 ::std::stable_sort( mTaskPanes
.begin(), mTaskPanes
.end(), LTRSort() );
290 ::std::stable_sort( mTaskPanes
.begin(), mTaskPanes
.end(), LTRSortBackward() );
292 ::std::vector
< Window
* >::iterator p
= mTaskPanes
.begin();
293 while( p
!= mTaskPanes
.end() )
297 unsigned n
= mTaskPanes
.size();
300 if( ++p
== mTaskPanes
.end() )
301 p
= mTaskPanes
.begin();
302 if( (*p
)->IsReallyVisible() && !(*p
)->IsDialog() && !(*p
)->ImplIsSplitter() )
317 // --------------------------------------------------
319 // returns next splitter
320 Window
* TaskPaneList::FindNextSplitter( Window
*pWindow
, BOOL bForward
)
323 ::std::stable_sort( mTaskPanes
.begin(), mTaskPanes
.end(), LTRSort() );
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();
335 if( pWindow
) // increment before test
337 if( p
== mTaskPanes
.end() )
338 p
= mTaskPanes
.begin();
339 if( (*p
)->ImplIsSplitter() && (*p
)->IsReallyVisible() && !(*p
)->IsDialog() && (*p
)->GetParent()->HasChildPathFocus() )
344 if( !pWindow
) // increment after test, otherwise first element is skipped
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
)
362 ::std::stable_sort( mTaskPanes
.begin(), mTaskPanes
.end(), LTRSort() );
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
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
381 if( (*p
)->IsReallyVisible() && !(*p
)->ImplIsSplitter() &&
382 ( (*p
)->GetType() != WINDOW_MENUBARWINDOW
|| (*p
)->GetSizePixel().Height() > 0 )
388 if( !pWindow
) // increment after test, otherwise first element is skipped
400 // --------------------------------------------------