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