1*cdf0e10cSrcweir /************************************************************************* 2*cdf0e10cSrcweir * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3*cdf0e10cSrcweir * 4*cdf0e10cSrcweir * Copyright 2000, 2010 Oracle and/or its affiliates. 5*cdf0e10cSrcweir * 6*cdf0e10cSrcweir * OpenOffice.org - a multi-platform office productivity suite 7*cdf0e10cSrcweir * 8*cdf0e10cSrcweir * This file is part of OpenOffice.org. 9*cdf0e10cSrcweir * 10*cdf0e10cSrcweir * OpenOffice.org is free software: you can redistribute it and/or modify 11*cdf0e10cSrcweir * it under the terms of the GNU Lesser General Public License version 3 12*cdf0e10cSrcweir * only, as published by the Free Software Foundation. 13*cdf0e10cSrcweir * 14*cdf0e10cSrcweir * OpenOffice.org is distributed in the hope that it will be useful, 15*cdf0e10cSrcweir * but WITHOUT ANY WARRANTY; without even the implied warranty of 16*cdf0e10cSrcweir * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17*cdf0e10cSrcweir * GNU Lesser General Public License version 3 for more details 18*cdf0e10cSrcweir * (a copy is included in the LICENSE file that accompanied this code). 19*cdf0e10cSrcweir * 20*cdf0e10cSrcweir * You should have received a copy of the GNU Lesser General Public License 21*cdf0e10cSrcweir * version 3 along with OpenOffice.org. If not, see 22*cdf0e10cSrcweir * <http://www.openoffice.org/license.html> 23*cdf0e10cSrcweir * for a copy of the LGPLv3 License. 24*cdf0e10cSrcweir * 25*cdf0e10cSrcweir ************************************************************************/ 26*cdf0e10cSrcweir 27*cdf0e10cSrcweir #include "precompiled_svtools.hxx" 28*cdf0e10cSrcweir 29*cdf0e10cSrcweir #include "svtools/toolpanel/drawerlayouter.hxx" 30*cdf0e10cSrcweir #include "toolpaneldrawer.hxx" 31*cdf0e10cSrcweir 32*cdf0e10cSrcweir #include <com/sun/star/accessibility/XAccessible.hpp> 33*cdf0e10cSrcweir 34*cdf0e10cSrcweir #include <comphelper/accimplaccess.hxx> 35*cdf0e10cSrcweir #include <tools/diagnose_ex.h> 36*cdf0e10cSrcweir 37*cdf0e10cSrcweir //...................................................................................................................... 38*cdf0e10cSrcweir namespace svt 39*cdf0e10cSrcweir { 40*cdf0e10cSrcweir //...................................................................................................................... 41*cdf0e10cSrcweir 42*cdf0e10cSrcweir /** === begin UNO using === **/ 43*cdf0e10cSrcweir using ::com::sun::star::uno::Reference; 44*cdf0e10cSrcweir using ::com::sun::star::accessibility::XAccessible; 45*cdf0e10cSrcweir /** === end UNO using === **/ 46*cdf0e10cSrcweir 47*cdf0e10cSrcweir //================================================================================================================== 48*cdf0e10cSrcweir //= DrawerDeckLayouter 49*cdf0e10cSrcweir //================================================================================================================== 50*cdf0e10cSrcweir //------------------------------------------------------------------------------------------------------------------ 51*cdf0e10cSrcweir DrawerDeckLayouter::DrawerDeckLayouter( ::Window& i_rParentWindow, IToolPanelDeck& i_rPanels ) 52*cdf0e10cSrcweir :m_rParentWindow( i_rParentWindow ) 53*cdf0e10cSrcweir ,m_rPanelDeck( i_rPanels ) 54*cdf0e10cSrcweir ,m_aDrawers() 55*cdf0e10cSrcweir ,m_aLastKnownActivePanel() 56*cdf0e10cSrcweir { 57*cdf0e10cSrcweir m_rPanelDeck.AddListener( *this ); 58*cdf0e10cSrcweir 59*cdf0e10cSrcweir // simulate PanelInserted events for the panels which are already there 60*cdf0e10cSrcweir for ( size_t i=0; i<m_rPanelDeck.GetPanelCount(); ++i ) 61*cdf0e10cSrcweir PanelInserted( m_rPanelDeck.GetPanel( i ), i ); 62*cdf0e10cSrcweir } 63*cdf0e10cSrcweir 64*cdf0e10cSrcweir //------------------------------------------------------------------------------------------------------------------ 65*cdf0e10cSrcweir DrawerDeckLayouter::~DrawerDeckLayouter() 66*cdf0e10cSrcweir { 67*cdf0e10cSrcweir } 68*cdf0e10cSrcweir 69*cdf0e10cSrcweir //------------------------------------------------------------------------------------------------------------------ 70*cdf0e10cSrcweir IMPLEMENT_IREFERENCE( DrawerDeckLayouter ) 71*cdf0e10cSrcweir 72*cdf0e10cSrcweir //------------------------------------------------------------------------------------------------------------------ 73*cdf0e10cSrcweir Rectangle DrawerDeckLayouter::Layout( const Rectangle& i_rDeckPlayground ) 74*cdf0e10cSrcweir { 75*cdf0e10cSrcweir const size_t nPanelCount( m_rPanelDeck.GetPanelCount() ); 76*cdf0e10cSrcweir if ( nPanelCount == 0 ) 77*cdf0e10cSrcweir return i_rDeckPlayground; 78*cdf0e10cSrcweir 79*cdf0e10cSrcweir const int nWidth( i_rDeckPlayground.GetWidth() ); 80*cdf0e10cSrcweir ::boost::optional< size_t > aActivePanel( m_rPanelDeck.GetActivePanel() ); 81*cdf0e10cSrcweir if ( !aActivePanel ) 82*cdf0e10cSrcweir aActivePanel = m_aLastKnownActivePanel; 83*cdf0e10cSrcweir 84*cdf0e10cSrcweir // arrange the title bars which are *above* the active panel (or *all* if there is no active panel), plus 85*cdf0e10cSrcweir // the title bar of the active panel itself 86*cdf0e10cSrcweir Point aUpperDrawerPos( i_rDeckPlayground.TopLeft() ); 87*cdf0e10cSrcweir const size_t nUpperBound = !!aActivePanel ? *aActivePanel : nPanelCount - 1; 88*cdf0e10cSrcweir for ( size_t i=0; i<=nUpperBound; ++i ) 89*cdf0e10cSrcweir { 90*cdf0e10cSrcweir long const nDrawerHeight = m_aDrawers[i]->GetPreferredHeightPixel(); 91*cdf0e10cSrcweir m_aDrawers[i]->SetPosSizePixel( 92*cdf0e10cSrcweir aUpperDrawerPos, Size( nWidth, nDrawerHeight ) ); 93*cdf0e10cSrcweir aUpperDrawerPos.Move( 0, nDrawerHeight ); 94*cdf0e10cSrcweir } 95*cdf0e10cSrcweir 96*cdf0e10cSrcweir // arrange title bars which are below the active panel (or *none* if there is no active panel) 97*cdf0e10cSrcweir Point aLowerDrawerPos( i_rDeckPlayground.BottomLeft() ); 98*cdf0e10cSrcweir for ( size_t j = nPanelCount - 1; j > nUpperBound; --j ) 99*cdf0e10cSrcweir { 100*cdf0e10cSrcweir long const nDrawerHeight = m_aDrawers[j]->GetPreferredHeightPixel(); 101*cdf0e10cSrcweir m_aDrawers[j]->SetPosSizePixel( 102*cdf0e10cSrcweir Point( aLowerDrawerPos.X(), aLowerDrawerPos.Y() - nDrawerHeight + 1 ), 103*cdf0e10cSrcweir Size( nWidth, nDrawerHeight ) 104*cdf0e10cSrcweir ); 105*cdf0e10cSrcweir aLowerDrawerPos.Move( 0, -nDrawerHeight ); 106*cdf0e10cSrcweir } 107*cdf0e10cSrcweir 108*cdf0e10cSrcweir // fincally calculate the rectangle for the active panel 109*cdf0e10cSrcweir return Rectangle( 110*cdf0e10cSrcweir aUpperDrawerPos, 111*cdf0e10cSrcweir Size( nWidth, aLowerDrawerPos.Y() - aUpperDrawerPos.Y() + 1 ) 112*cdf0e10cSrcweir ); 113*cdf0e10cSrcweir } 114*cdf0e10cSrcweir 115*cdf0e10cSrcweir //------------------------------------------------------------------------------------------------------------------ 116*cdf0e10cSrcweir void DrawerDeckLayouter::Destroy() 117*cdf0e10cSrcweir { 118*cdf0e10cSrcweir while ( !m_aDrawers.empty() ) 119*cdf0e10cSrcweir impl_removeDrawer( 0 ); 120*cdf0e10cSrcweir m_rPanelDeck.RemoveListener( *this ); 121*cdf0e10cSrcweir } 122*cdf0e10cSrcweir 123*cdf0e10cSrcweir //------------------------------------------------------------------------------------------------------------------ 124*cdf0e10cSrcweir void DrawerDeckLayouter::SetFocusToPanelSelector() 125*cdf0e10cSrcweir { 126*cdf0e10cSrcweir const size_t nPanelCount( m_rPanelDeck.GetPanelCount() ); 127*cdf0e10cSrcweir if ( !nPanelCount ) 128*cdf0e10cSrcweir // nothing to focus 129*cdf0e10cSrcweir return; 130*cdf0e10cSrcweir ::boost::optional< size_t > aActivePanel( m_rPanelDeck.GetActivePanel() ); 131*cdf0e10cSrcweir if ( !aActivePanel ) 132*cdf0e10cSrcweir aActivePanel = 0; 133*cdf0e10cSrcweir ENSURE_OR_RETURN_VOID( *aActivePanel < m_aDrawers.size(), "DrawerDeckLayouter::SetFocusToPanelSelector: invalid active panel, or inconsistent drawers!" ); 134*cdf0e10cSrcweir m_aDrawers[ *aActivePanel ]->GrabFocus(); 135*cdf0e10cSrcweir } 136*cdf0e10cSrcweir 137*cdf0e10cSrcweir //------------------------------------------------------------------------------------------------------------------ 138*cdf0e10cSrcweir size_t DrawerDeckLayouter::GetAccessibleChildCount() const 139*cdf0e10cSrcweir { 140*cdf0e10cSrcweir return m_aDrawers.size(); 141*cdf0e10cSrcweir } 142*cdf0e10cSrcweir 143*cdf0e10cSrcweir //------------------------------------------------------------------------------------------------------------------ 144*cdf0e10cSrcweir Reference< XAccessible > DrawerDeckLayouter::GetAccessibleChild( const size_t i_nChildIndex, const Reference< XAccessible >& i_rParentAccessible ) 145*cdf0e10cSrcweir { 146*cdf0e10cSrcweir ENSURE_OR_RETURN( i_nChildIndex < m_aDrawers.size(), "illegal index", NULL ); 147*cdf0e10cSrcweir 148*cdf0e10cSrcweir const PToolPanelDrawer pDrawer( m_aDrawers[ i_nChildIndex ] ); 149*cdf0e10cSrcweir 150*cdf0e10cSrcweir Reference< XAccessible > xItemAccessible = pDrawer->GetAccessible( sal_False ); 151*cdf0e10cSrcweir if ( !xItemAccessible.is() ) 152*cdf0e10cSrcweir { 153*cdf0e10cSrcweir xItemAccessible = pDrawer->GetAccessible( sal_True ); 154*cdf0e10cSrcweir ENSURE_OR_RETURN( xItemAccessible.is(), "illegal accessible provided by the drawer implementation!", NULL ); 155*cdf0e10cSrcweir OSL_VERIFY( ::comphelper::OAccessibleImplementationAccess::setAccessibleParent( xItemAccessible->getAccessibleContext(), 156*cdf0e10cSrcweir i_rParentAccessible ) ); 157*cdf0e10cSrcweir } 158*cdf0e10cSrcweir 159*cdf0e10cSrcweir return xItemAccessible; 160*cdf0e10cSrcweir } 161*cdf0e10cSrcweir 162*cdf0e10cSrcweir //------------------------------------------------------------------------------------------------------------------ 163*cdf0e10cSrcweir void DrawerDeckLayouter::PanelInserted( const PToolPanel& i_pPanel, const size_t i_nPosition ) 164*cdf0e10cSrcweir { 165*cdf0e10cSrcweir OSL_PRECOND( i_nPosition <= m_aDrawers.size(), "DrawerDeckLayouter::PanelInserted: inconsistency!" ); 166*cdf0e10cSrcweir 167*cdf0e10cSrcweir PToolPanelDrawer pDrawer( new ToolPanelDrawer( m_rParentWindow, i_pPanel->GetDisplayName() ) ); 168*cdf0e10cSrcweir pDrawer->SetHelpId( i_pPanel->GetHelpID() ); 169*cdf0e10cSrcweir // proper Z-Order 170*cdf0e10cSrcweir if ( i_nPosition == 0 ) 171*cdf0e10cSrcweir { 172*cdf0e10cSrcweir pDrawer->SetZOrder( NULL, WINDOW_ZORDER_FIRST ); 173*cdf0e10cSrcweir } 174*cdf0e10cSrcweir else 175*cdf0e10cSrcweir { 176*cdf0e10cSrcweir const PToolPanelDrawer pFirstDrawer( m_aDrawers[ i_nPosition - 1 ] ); 177*cdf0e10cSrcweir pDrawer->SetZOrder( pFirstDrawer.get(), WINDOW_ZORDER_BEHIND ); 178*cdf0e10cSrcweir } 179*cdf0e10cSrcweir 180*cdf0e10cSrcweir pDrawer->Show(); 181*cdf0e10cSrcweir pDrawer->AddEventListener( LINK( this, DrawerDeckLayouter, OnWindowEvent ) ); 182*cdf0e10cSrcweir m_aDrawers.insert( m_aDrawers.begin() + i_nPosition, pDrawer ); 183*cdf0e10cSrcweir impl_triggerRearrange(); 184*cdf0e10cSrcweir } 185*cdf0e10cSrcweir 186*cdf0e10cSrcweir //------------------------------------------------------------------------------------------------------------------ 187*cdf0e10cSrcweir void DrawerDeckLayouter::PanelRemoved( const size_t i_nPosition ) 188*cdf0e10cSrcweir { 189*cdf0e10cSrcweir impl_removeDrawer( i_nPosition ); 190*cdf0e10cSrcweir impl_triggerRearrange(); 191*cdf0e10cSrcweir } 192*cdf0e10cSrcweir 193*cdf0e10cSrcweir //------------------------------------------------------------------------------------------------------------------ 194*cdf0e10cSrcweir void DrawerDeckLayouter::impl_triggerRearrange() const 195*cdf0e10cSrcweir { 196*cdf0e10cSrcweir // this is somewhat hacky, it assumes that the parent of our panels is a tool panel deck, which, in its 197*cdf0e10cSrcweir // Resize implementation, rearrances all elements. 198*cdf0e10cSrcweir m_rParentWindow.Resize(); 199*cdf0e10cSrcweir } 200*cdf0e10cSrcweir 201*cdf0e10cSrcweir //------------------------------------------------------------------------------------------------------------------ 202*cdf0e10cSrcweir void DrawerDeckLayouter::ActivePanelChanged( const ::boost::optional< size_t >& i_rOldActive, const ::boost::optional< size_t >& i_rNewActive ) 203*cdf0e10cSrcweir { 204*cdf0e10cSrcweir if ( !!i_rOldActive ) 205*cdf0e10cSrcweir { 206*cdf0e10cSrcweir OSL_ENSURE( *i_rOldActive < m_aDrawers.size(), "DrawerDeckLayouter::ActivePanelChanged: illegal old index!" ); 207*cdf0e10cSrcweir m_aDrawers[ *i_rOldActive ]->SetExpanded( false ); 208*cdf0e10cSrcweir } 209*cdf0e10cSrcweir 210*cdf0e10cSrcweir if ( !!i_rNewActive ) 211*cdf0e10cSrcweir { 212*cdf0e10cSrcweir OSL_ENSURE( *i_rNewActive < m_aDrawers.size(), "DrawerDeckLayouter::ActivePanelChanged: illegal new index!" ); 213*cdf0e10cSrcweir m_aDrawers[ *i_rNewActive ]->SetExpanded( true ); 214*cdf0e10cSrcweir } 215*cdf0e10cSrcweir 216*cdf0e10cSrcweir impl_triggerRearrange(); 217*cdf0e10cSrcweir } 218*cdf0e10cSrcweir 219*cdf0e10cSrcweir //------------------------------------------------------------------------------------------------------------------ 220*cdf0e10cSrcweir void DrawerDeckLayouter::LayouterChanged( const PDeckLayouter& i_rNewLayouter ) 221*cdf0e10cSrcweir { 222*cdf0e10cSrcweir // not interested in 223*cdf0e10cSrcweir (void)i_rNewLayouter; 224*cdf0e10cSrcweir } 225*cdf0e10cSrcweir 226*cdf0e10cSrcweir //------------------------------------------------------------------------------------------------------------------ 227*cdf0e10cSrcweir size_t DrawerDeckLayouter::impl_getPanelPositionFromWindow( const Window* i_pDrawerWindow ) const 228*cdf0e10cSrcweir { 229*cdf0e10cSrcweir for ( ::std::vector< PToolPanelDrawer >::const_iterator drawerPos = m_aDrawers.begin(); 230*cdf0e10cSrcweir drawerPos != m_aDrawers.end(); 231*cdf0e10cSrcweir ++drawerPos 232*cdf0e10cSrcweir ) 233*cdf0e10cSrcweir { 234*cdf0e10cSrcweir if ( drawerPos->get() == i_pDrawerWindow ) 235*cdf0e10cSrcweir return drawerPos - m_aDrawers.begin(); 236*cdf0e10cSrcweir } 237*cdf0e10cSrcweir return m_aDrawers.size(); 238*cdf0e10cSrcweir } 239*cdf0e10cSrcweir 240*cdf0e10cSrcweir //------------------------------------------------------------------------------------------------------------------ 241*cdf0e10cSrcweir void DrawerDeckLayouter::impl_removeDrawer( const size_t i_nPosition ) 242*cdf0e10cSrcweir { 243*cdf0e10cSrcweir OSL_PRECOND( i_nPosition < m_aDrawers.size(), "DrawerDeckLayouter::impl_removeDrawer: invalid panel position!" ); 244*cdf0e10cSrcweir m_aDrawers[ i_nPosition ]->RemoveEventListener( LINK( this, DrawerDeckLayouter, OnWindowEvent ) ); 245*cdf0e10cSrcweir OSL_ENSURE( m_aDrawers[ i_nPosition ].unique(), "DrawerDeckLayouter::impl_removeDrawer: somebody else is still holding a reference!" ); 246*cdf0e10cSrcweir m_aDrawers.erase( m_aDrawers.begin() + i_nPosition ); 247*cdf0e10cSrcweir } 248*cdf0e10cSrcweir 249*cdf0e10cSrcweir //------------------------------------------------------------------------------------------------------------------ 250*cdf0e10cSrcweir IMPL_LINK( DrawerDeckLayouter, OnWindowEvent, VclSimpleEvent*, i_pEvent ) 251*cdf0e10cSrcweir { 252*cdf0e10cSrcweir const VclWindowEvent* pWindowEvent = PTR_CAST( VclWindowEvent, i_pEvent ); 253*cdf0e10cSrcweir ENSURE_OR_RETURN( pWindowEvent, "no WindowEvent", 0L ); 254*cdf0e10cSrcweir 255*cdf0e10cSrcweir bool bActivatePanel = false; 256*cdf0e10cSrcweir switch ( pWindowEvent->GetId() ) 257*cdf0e10cSrcweir { 258*cdf0e10cSrcweir case VCLEVENT_WINDOW_MOUSEBUTTONUP: 259*cdf0e10cSrcweir { 260*cdf0e10cSrcweir const MouseEvent* pMouseEvent = static_cast< const MouseEvent* >( pWindowEvent->GetData() ); 261*cdf0e10cSrcweir ENSURE_OR_RETURN( pMouseEvent, "no mouse event with MouseButtonUp", 0L ); 262*cdf0e10cSrcweir if ( pMouseEvent->GetButtons() == MOUSE_LEFT ) 263*cdf0e10cSrcweir { 264*cdf0e10cSrcweir bActivatePanel = true; 265*cdf0e10cSrcweir } 266*cdf0e10cSrcweir } 267*cdf0e10cSrcweir break; 268*cdf0e10cSrcweir case VCLEVENT_WINDOW_KEYINPUT: 269*cdf0e10cSrcweir { 270*cdf0e10cSrcweir const KeyEvent* pKeyEvent = static_cast< const KeyEvent* >( pWindowEvent->GetData() ); 271*cdf0e10cSrcweir ENSURE_OR_RETURN( pKeyEvent, "no key event with KeyInput", 0L ); 272*cdf0e10cSrcweir const KeyCode& rKeyCode( pKeyEvent->GetKeyCode() ); 273*cdf0e10cSrcweir if ( ( rKeyCode.GetModifier() == 0 ) && ( rKeyCode.GetCode() == KEY_RETURN ) ) 274*cdf0e10cSrcweir { 275*cdf0e10cSrcweir bActivatePanel = true; 276*cdf0e10cSrcweir } 277*cdf0e10cSrcweir } 278*cdf0e10cSrcweir break; 279*cdf0e10cSrcweir } 280*cdf0e10cSrcweir if ( bActivatePanel ) 281*cdf0e10cSrcweir { 282*cdf0e10cSrcweir const size_t nPanelPos = impl_getPanelPositionFromWindow( pWindowEvent->GetWindow() ); 283*cdf0e10cSrcweir if ( nPanelPos != m_rPanelDeck.GetActivePanel() ) 284*cdf0e10cSrcweir { 285*cdf0e10cSrcweir m_rPanelDeck.ActivatePanel( nPanelPos ); 286*cdf0e10cSrcweir } 287*cdf0e10cSrcweir else 288*cdf0e10cSrcweir { 289*cdf0e10cSrcweir PToolPanel pPanel( m_rPanelDeck.GetPanel( nPanelPos ) ); 290*cdf0e10cSrcweir pPanel->GrabFocus(); 291*cdf0e10cSrcweir } 292*cdf0e10cSrcweir return 1L; 293*cdf0e10cSrcweir } 294*cdf0e10cSrcweir return 0L; 295*cdf0e10cSrcweir } 296*cdf0e10cSrcweir 297*cdf0e10cSrcweir //------------------------------------------------------------------------------------------------------------------ 298*cdf0e10cSrcweir void DrawerDeckLayouter::Dying() 299*cdf0e10cSrcweir { 300*cdf0e10cSrcweir Destroy(); 301*cdf0e10cSrcweir } 302*cdf0e10cSrcweir 303*cdf0e10cSrcweir //...................................................................................................................... 304*cdf0e10cSrcweir } // namespace svt 305*cdf0e10cSrcweir //...................................................................................................................... 306