1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
21 #include "dummypanel.hxx"
22 #include "toolpanelcollection.hxx"
23 #include "paneldecklisteners.hxx"
24 #include "toolpaneldeckpeer.hxx"
25 #include "svtools/toolpanel/toolpaneldeck.hxx"
26 #include "svtools/toolpanel/tablayouter.hxx"
27 #include "svtools/toolpanel/drawerlayouter.hxx"
29 #include <com/sun/star/accessibility/XAccessible.hpp>
30 #include <com/sun/star/accessibility/AccessibleRole.hpp>
32 #include <tools/diagnose_ex.h>
34 #include <boost/optional.hpp>
36 //........................................................................
39 //........................................................................
41 using ::com::sun::star::uno::Reference
;
42 using ::com::sun::star::accessibility::XAccessible
;
43 using ::com::sun::star::awt::XWindowPeer
;
44 using ::com::sun::star::uno::UNO_SET_THROW
;
46 namespace AccessibleRole
= ::com::sun::star::accessibility::AccessibleRole
;
50 /// activates the first panel
51 ACTION_ACTIVATE_FIRST
,
52 // activates the panel after the currently active panel
54 // activates the panel before the currently active panel
56 // activates the last panel
59 // toggles the focus between the active panel and the panel selector
63 //====================================================================
64 //= ToolPanelDeck_Impl
65 //====================================================================
66 class ToolPanelDeck_Impl
: public IToolPanelDeckListener
69 ToolPanelDeck_Impl( ToolPanelDeck
& i_rDeck
)
71 ,m_aPanelAnchor( &i_rDeck
, WB_DIALOGCONTROL
| WB_CHILDDLGCTRL
)
73 ,m_pDummyPanel( new DummyPanel
)
76 ,m_pAccessibleParent( NULL
)
78 m_aPanels
.AddListener( *this );
79 m_aPanelAnchor
.Show();
80 m_aPanelAnchor
.SetAccessibleRole( AccessibleRole::PANEL
);
83 virtual ~ToolPanelDeck_Impl()
88 PDeckLayouter
GetLayouter() const { return m_pLayouter
; }
89 void SetLayouter( const PDeckLayouter
& i_pNewLayouter
);
91 Window
& GetPanelWindowAnchor() { return m_aPanelAnchor
; }
92 const Window
& GetPanelWindowAnchor() const { return m_aPanelAnchor
; }
94 bool IsDead() const { return m_bInDtor
; }
96 /// notifies our listeners that we're going to die. Only to be called from with our anti-impl's destructor
99 m_aPanels
.RemoveListener( *this );
100 m_aListeners
.Dying();
103 // IToolPanelDeck equivalents
104 size_t GetPanelCount() const;
105 PToolPanel
GetPanel( const size_t i_nPos
) const;
106 ::boost::optional
< size_t >
107 GetActivePanel() const;
108 void ActivatePanel( const ::boost::optional
< size_t >& i_rPanel
);
109 size_t InsertPanel( const PToolPanel
& i_pPanel
, const size_t i_nPosition
);
110 PToolPanel
RemovePanel( const size_t i_nPosition
);
111 void AddListener( IToolPanelDeckListener
& i_rListener
);
112 void RemoveListener( IToolPanelDeckListener
& i_rListener
);
114 /// re-layouts everything
115 void LayoutAll() { ImplDoLayout(); }
117 void DoAction( const DeckAction i_eAction
);
119 bool FocusActivePanel();
121 void SetAccessibleParentWindow( Window
* i_pAccessibleParent
);
122 Window
* GetAccessibleParentWindow() const { return m_pAccessibleParent
; }
125 // IToolPanelDeckListener
126 virtual void PanelInserted( const PToolPanel
& i_pPanel
, const size_t i_nPosition
);
127 virtual void PanelRemoved( const size_t i_nPosition
);
128 virtual void ActivePanelChanged( const ::boost::optional
< size_t >& i_rOldActive
, const ::boost::optional
< size_t >& i_rNewActive
);
129 virtual void LayouterChanged( const PDeckLayouter
& i_rNewLayouter
);
130 virtual void Dying();
134 PToolPanel
GetActiveOrDummyPanel_Impl();
137 ToolPanelDeck
& m_rDeck
;
138 Window m_aPanelAnchor
;
139 ToolPanelCollection m_aPanels
;
140 PToolPanel m_pDummyPanel
;
141 PanelDeckListeners m_aListeners
;
142 PDeckLayouter m_pLayouter
;
144 Window
* m_pAccessibleParent
;
147 //--------------------------------------------------------------------
148 PToolPanel
ToolPanelDeck_Impl::GetActiveOrDummyPanel_Impl()
150 ::boost::optional
< size_t > aActivePanel( m_aPanels
.GetActivePanel() );
152 return m_pDummyPanel
;
153 return m_aPanels
.GetPanel( *aActivePanel
);
156 //--------------------------------------------------------------------
157 void ToolPanelDeck_Impl::SetLayouter( const PDeckLayouter
& i_pNewLayouter
)
159 ENSURE_OR_RETURN_VOID( i_pNewLayouter
.get(), "invalid layouter" );
161 if ( m_pLayouter
.get() )
162 m_pLayouter
->Destroy();
164 m_pLayouter
= i_pNewLayouter
;
168 m_aListeners
.LayouterChanged( m_pLayouter
);
171 //--------------------------------------------------------------------
172 size_t ToolPanelDeck_Impl::GetPanelCount() const
174 return m_aPanels
.GetPanelCount();
177 //--------------------------------------------------------------------
178 PToolPanel
ToolPanelDeck_Impl::GetPanel( const size_t i_nPos
) const
180 return m_aPanels
.GetPanel( i_nPos
);
183 //--------------------------------------------------------------------
184 ::boost::optional
< size_t > ToolPanelDeck_Impl::GetActivePanel() const
186 return m_aPanels
.GetActivePanel();
189 //--------------------------------------------------------------------
190 void ToolPanelDeck_Impl::ActivatePanel( const ::boost::optional
< size_t >& i_rPanel
)
192 m_aPanels
.ActivatePanel( i_rPanel
);
195 //--------------------------------------------------------------------
196 size_t ToolPanelDeck_Impl::InsertPanel( const PToolPanel
& i_pPanel
, const size_t i_nPosition
)
198 return m_aPanels
.InsertPanel( i_pPanel
, i_nPosition
);
201 //--------------------------------------------------------------------
202 PToolPanel
ToolPanelDeck_Impl::RemovePanel( const size_t i_nPosition
)
204 return m_aPanels
.RemovePanel( i_nPosition
);
207 //--------------------------------------------------------------------
208 void ToolPanelDeck_Impl::ImplDoLayout()
210 const Rectangle
aDeckPlayground( Point(), m_rDeck
.GetOutputSizePixel() );
212 // ask the layouter what is left for our panel, and position the panel container window appropriately
213 Rectangle
aPlaygroundArea( aDeckPlayground
);
214 OSL_ENSURE( m_pLayouter
.get(), "ToolPanelDeck_Impl::ImplDoLayout: no layouter!" );
215 if ( m_pLayouter
.get() )
217 aPlaygroundArea
= m_pLayouter
->Layout( aDeckPlayground
);
219 m_aPanelAnchor
.SetPosSizePixel( aPlaygroundArea
.TopLeft(), aPlaygroundArea
.GetSize() );
221 // position the active panel
222 const PToolPanel
pActive( GetActiveOrDummyPanel_Impl() );
223 pActive
->SetSizePixel( m_aPanelAnchor
.GetOutputSizePixel() );
226 //--------------------------------------------------------------------
227 void ToolPanelDeck_Impl::AddListener( IToolPanelDeckListener
& i_rListener
)
229 m_aListeners
.AddListener( i_rListener
);
232 //--------------------------------------------------------------------
233 void ToolPanelDeck_Impl::RemoveListener( IToolPanelDeckListener
& i_rListener
)
235 m_aListeners
.RemoveListener( i_rListener
);
238 //--------------------------------------------------------------------
239 void ToolPanelDeck_Impl::DoAction( const DeckAction i_eAction
)
241 const size_t nPanelCount( m_aPanels
.GetPanelCount() );
242 ::boost::optional
< size_t > aActivatePanel
;
243 ::boost::optional
< size_t > aCurrentPanel( GetActivePanel() );
247 case ACTION_ACTIVATE_FIRST
:
248 if ( nPanelCount
> 0 )
251 case ACTION_ACTIVATE_PREV
:
252 if ( !aCurrentPanel
&& ( nPanelCount
> 0 ) )
253 aActivatePanel
= nPanelCount
- 1;
254 else if ( !!aCurrentPanel
&& ( *aCurrentPanel
> 0 ) )
255 aActivatePanel
= *aCurrentPanel
- 1;
257 case ACTION_ACTIVATE_NEXT
:
258 if ( !aCurrentPanel
&& ( nPanelCount
> 0 ) )
260 else if ( !!aCurrentPanel
&& ( *aCurrentPanel
< nPanelCount
- 1 ) )
261 aActivatePanel
= *aCurrentPanel
+ 1;
263 case ACTION_ACTIVATE_LAST
:
264 if ( nPanelCount
> 0 )
265 aActivatePanel
= nPanelCount
- 1;
267 case ACTION_TOGGLE_FOCUS
:
269 PToolPanel
pActivePanel( GetActiveOrDummyPanel_Impl() );
270 if ( !m_aPanelAnchor
.HasChildPathFocus() )
271 pActivePanel
->GrabFocus();
273 GetLayouter()->SetFocusToPanelSelector();
278 if ( !!aActivatePanel
)
280 ActivatePanel( aActivatePanel
);
284 //--------------------------------------------------------------------
285 bool ToolPanelDeck_Impl::FocusActivePanel()
287 ::boost::optional
< size_t > aActivePanel( m_aPanels
.GetActivePanel() );
291 PToolPanel
pActivePanel( m_aPanels
.GetPanel( *aActivePanel
) );
292 pActivePanel
->GrabFocus();
296 //--------------------------------------------------------------------
297 void ToolPanelDeck_Impl::PanelInserted( const PToolPanel
& i_pPanel
, const size_t i_nPosition
)
299 // multiplex to our own listeners
300 m_aListeners
.PanelInserted( i_pPanel
, i_nPosition
);
303 //--------------------------------------------------------------------
304 void ToolPanelDeck_Impl::PanelRemoved( const size_t i_nPosition
)
306 // multiplex to our own listeners
307 m_aListeners
.PanelRemoved( i_nPosition
);
310 //--------------------------------------------------------------------
311 void ToolPanelDeck_Impl::ActivePanelChanged( const ::boost::optional
< size_t >& i_rOldActive
, const ::boost::optional
< size_t >& i_rNewActive
)
313 // hide the old panel
314 if ( !!i_rOldActive
)
316 const PToolPanel
pOldActive( m_aPanels
.GetPanel( *i_rOldActive
) );
317 pOldActive
->Deactivate();
320 // position and show the new panel
321 const PToolPanel
pNewActive( !i_rNewActive
? m_pDummyPanel
: m_aPanels
.GetPanel( *i_rNewActive
) );
322 pNewActive
->Activate( m_aPanelAnchor
);
323 pNewActive
->GrabFocus();
325 // resize the panel (cannot guarantee it has ever been resized before
326 pNewActive
->SetSizePixel( m_aPanelAnchor
.GetOutputSizePixel() );
328 // multiplex to our own listeners
329 m_aListeners
.ActivePanelChanged( i_rOldActive
, i_rNewActive
);
332 //--------------------------------------------------------------------
333 void ToolPanelDeck_Impl::LayouterChanged( const PDeckLayouter
& i_rNewLayouter
)
336 (void)i_rNewLayouter
;
339 //--------------------------------------------------------------------
340 void ToolPanelDeck_Impl::Dying()
342 // not interested in. Since the ToolPanelCollection is our member, this just means we ourself
343 // are dying, and we already sent this notification in our dtor.
346 //--------------------------------------------------------------------
347 void ToolPanelDeck_Impl::SetAccessibleParentWindow( Window
* i_pAccessibleParent
)
349 m_pAccessibleParent
= i_pAccessibleParent
;
352 //====================================================================
354 //====================================================================
355 //--------------------------------------------------------------------
356 ToolPanelDeck::ToolPanelDeck( Window
& i_rParent
, const WinBits i_nStyle
)
357 :Control( &i_rParent
, i_nStyle
)
358 ,m_pImpl( new ToolPanelDeck_Impl( *this ) )
360 // use a default layouter
361 // SetLayouter( PDeckLayouter( new TabDeckLayouter( *this, *this, TABS_RIGHT, TABITEM_IMAGE_AND_TEXT ) ) );
362 SetLayouter( PDeckLayouter( new DrawerDeckLayouter( *this, *this ) ) );
365 //--------------------------------------------------------------------
366 ToolPanelDeck::~ToolPanelDeck()
368 m_pImpl
->NotifyDying();
369 GetLayouter()->Destroy();
372 for ( size_t i
=0; i
<GetPanelCount(); ++i
)
374 PToolPanel
pPanel( GetPanel( i
) );
379 //--------------------------------------------------------------------
380 size_t ToolPanelDeck::GetPanelCount() const
382 return m_pImpl
->GetPanelCount();
385 //--------------------------------------------------------------------
386 PToolPanel
ToolPanelDeck::GetPanel( const size_t i_nPos
) const
388 return m_pImpl
->GetPanel( i_nPos
);
391 //--------------------------------------------------------------------
392 ::boost::optional
< size_t > ToolPanelDeck::GetActivePanel() const
394 return m_pImpl
->GetActivePanel();
397 //--------------------------------------------------------------------
398 void ToolPanelDeck::ActivatePanel( const ::boost::optional
< size_t >& i_rPanel
)
400 m_pImpl
->ActivatePanel( i_rPanel
);
403 //--------------------------------------------------------------------
404 size_t ToolPanelDeck::InsertPanel( const PToolPanel
& i_pPanel
, const size_t i_nPosition
)
406 return m_pImpl
->InsertPanel( i_pPanel
, i_nPosition
);
409 //--------------------------------------------------------------------
410 PToolPanel
ToolPanelDeck::RemovePanel( const size_t i_nPosition
)
412 return m_pImpl
->RemovePanel( i_nPosition
);
415 //--------------------------------------------------------------------
416 PDeckLayouter
ToolPanelDeck::GetLayouter() const
418 return m_pImpl
->GetLayouter();
421 //--------------------------------------------------------------------
422 void ToolPanelDeck::SetLayouter( const PDeckLayouter
& i_pNewLayouter
)
424 return m_pImpl
->SetLayouter( i_pNewLayouter
);
427 //--------------------------------------------------------------------
428 void ToolPanelDeck::AddListener( IToolPanelDeckListener
& i_rListener
)
430 m_pImpl
->AddListener( i_rListener
);
433 //--------------------------------------------------------------------
434 void ToolPanelDeck::RemoveListener( IToolPanelDeckListener
& i_rListener
)
436 m_pImpl
->RemoveListener( i_rListener
);
439 //--------------------------------------------------------------------
440 Window
& ToolPanelDeck::GetPanelWindowAnchor()
442 return m_pImpl
->GetPanelWindowAnchor();
445 //--------------------------------------------------------------------
446 const Window
& ToolPanelDeck::GetPanelWindowAnchor() const
448 return m_pImpl
->GetPanelWindowAnchor();
451 //--------------------------------------------------------------------
452 void ToolPanelDeck::Resize()
455 m_pImpl
->LayoutAll();
458 //--------------------------------------------------------------------
459 long ToolPanelDeck::Notify( NotifyEvent
& i_rNotifyEvent
)
461 bool bHandled
= false;
462 if ( i_rNotifyEvent
.GetType() == EVENT_KEYINPUT
)
464 const KeyEvent
* pEvent
= i_rNotifyEvent
.GetKeyEvent();
465 const KeyCode
& rKeyCode
= pEvent
->GetKeyCode();
466 if ( rKeyCode
.GetModifier() == KEY_MOD1
)
469 switch ( rKeyCode
.GetCode() )
472 m_pImpl
->DoAction( ACTION_ACTIVATE_FIRST
);
475 m_pImpl
->DoAction( ACTION_ACTIVATE_PREV
);
478 m_pImpl
->DoAction( ACTION_ACTIVATE_NEXT
);
481 m_pImpl
->DoAction( ACTION_ACTIVATE_LAST
);
488 else if ( rKeyCode
.GetModifier() == ( KEY_MOD1
| KEY_SHIFT
) )
490 if ( rKeyCode
.GetCode() == KEY_E
)
492 m_pImpl
->DoAction( ACTION_TOGGLE_FOCUS
);
501 return Control::Notify( i_rNotifyEvent
);
504 //--------------------------------------------------------------------
505 void ToolPanelDeck::GetFocus()
508 if ( m_pImpl
->IsDead() )
510 if ( !m_pImpl
->FocusActivePanel() )
512 PDeckLayouter
pLayouter( GetLayouter() );
513 ENSURE_OR_RETURN_VOID( pLayouter
.get(), "ToolPanelDeck::GetFocus: no layouter?!" );
514 pLayouter
->SetFocusToPanelSelector();
518 //--------------------------------------------------------------------
519 void ToolPanelDeck::SetAccessibleParentWindow( Window
* i_pAccessibleParent
)
521 m_pImpl
->SetAccessibleParentWindow( i_pAccessibleParent
);
524 //--------------------------------------------------------------------
525 Window
* ToolPanelDeck::GetAccessibleParentWindow() const
527 Window
* pAccessibleParent( m_pImpl
->GetAccessibleParentWindow() );
528 if ( !pAccessibleParent
)
529 pAccessibleParent
= Window::GetAccessibleParentWindow();
530 return pAccessibleParent
;
533 //--------------------------------------------------------------------
534 Reference
< XWindowPeer
> ToolPanelDeck::GetComponentInterface( sal_Bool i_bCreate
)
536 Reference
< XWindowPeer
> xWindowPeer( Control::GetComponentInterface( sal_False
) );
537 if ( !xWindowPeer
.is() && i_bCreate
)
539 xWindowPeer
.set( new ToolPanelDeckPeer( *this ) );
540 SetComponentInterface( xWindowPeer
);
545 //........................................................................
547 //........................................................................
549 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */