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: ViewTabBar.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_sd.hxx"
34 #include "ViewTabBar.hxx"
36 #define USE_TAB_CONTROL
38 #include "ViewShell.hxx"
39 #include "ViewShellBase.hxx"
40 #include "DrawViewShell.hxx"
41 #include "FrameView.hxx"
42 #include "EventMultiplexer.hxx"
43 #include "framework/FrameworkHelper.hxx"
44 #include "framework/Pane.hxx"
45 #include "DrawController.hxx"
47 #include "sdresid.hxx"
48 #include "strings.hrc"
51 #include <vcl/svapp.hxx>
52 #include <vcl/tabpage.hxx>
53 #include <vos/mutex.hxx>
54 #include <sfx2/viewfrm.hxx>
55 #include <com/sun/star/drawing/framework/ResourceId.hpp>
56 #include <com/sun/star/drawing/framework/XControllerManager.hpp>
57 #include <com/sun/star/lang/XUnoTunnel.hpp>
58 #include <com/sun/star/lang/DisposedException.hpp>
59 #include <comphelper/processfactory.hxx>
61 using namespace ::com::sun::star
;
62 using namespace ::com::sun::star::uno
;
63 using namespace ::com::sun::star::drawing::framework
;
64 using ::sd::framework::FrameworkHelper
;
65 using ::sd::tools::EventMultiplexerEvent
;
66 using ::rtl::OUString
;
71 bool IsEqual (const TabBarButton
& rButton1
, const TabBarButton
& rButton2
)
74 (rButton1
.ResourceId
.is()
75 && rButton2
.ResourceId
.is()
76 && rButton1
.ResourceId
->compareTo(rButton2
.ResourceId
)==0)
77 || rButton1
.ButtonLabel
== rButton2
.ButtonLabel
);
80 class TabBarControl
: public ::TabControl
84 ::Window
* pParentWindow
,
85 const ::rtl::Reference
<ViewTabBar
>& rpViewTabBar
);
86 virtual void Paint (const Rectangle
& rRect
);
87 virtual void ActivatePage (void);
89 ::rtl::Reference
<ViewTabBar
> mpViewTabBar
;
92 } // end of anonymous namespace
98 class ViewTabPage
: public TabPage
101 ViewTabPage (Window
* pParent
) : TabPage(pParent
) {}
102 virtual void Resize (void)
103 { SetPosSizePixel(Point(0,0),GetParent()->GetOutputSizePixel()); }
109 //===== ViewTabBar ============================================================
111 ViewTabBar::ViewTabBar (
112 const Reference
<XResourceId
>& rxViewTabBarId
,
113 const Reference
<frame::XController
>& rxController
)
114 : ViewTabBarInterfaceBase(maMutex
),
115 mpTabControl(new TabBarControl(GetAnchorWindow(rxViewTabBarId
,rxController
), this)),
116 mxController(rxController
),
119 mxViewTabBarId(rxViewTabBarId
),
120 mpViewShellBase(NULL
)
122 // Set one new tab page for all tab entries. We need it only to
123 // determine the height of the tab bar.
124 mpTabPage
.reset(new TabPage (mpTabControl
.get()));
127 // add some space before the tabitems
128 mpTabControl
->SetItemsOffset(Point(5, 3));
130 // Tunnel through the controller and use the ViewShellBase to obtain the
134 Reference
<lang::XUnoTunnel
> xTunnel (mxController
, UNO_QUERY_THROW
);
135 DrawController
* pController
= reinterpret_cast<DrawController
*>(
136 xTunnel
->getSomething(DrawController::getUnoTunnelId()));
137 mpViewShellBase
= pController
->GetViewShellBase();
139 catch(RuntimeException
&)
142 // Register as listener at XConfigurationController.
143 Reference
<XControllerManager
> xControllerManager (mxController
, UNO_QUERY
);
144 if (xControllerManager
.is())
146 mxConfigurationController
= xControllerManager
->getConfigurationController();
147 if (mxConfigurationController
.is())
149 mxConfigurationController
->addConfigurationChangeListener(
151 FrameworkHelper::msResourceActivationEvent
,
156 mpTabControl
->Show();
158 if (mpViewShellBase
!= NULL
159 && rxViewTabBarId
->isBoundToURL(
160 FrameworkHelper::msCenterPaneURL
, AnchorBindingMode_DIRECT
))
162 mpViewShellBase
->SetViewTabBar(this);
169 ViewTabBar::~ViewTabBar (void)
176 void ViewTabBar::disposing (void)
178 if (mpViewShellBase
!= NULL
179 && mxViewTabBarId
->isBoundToURL(
180 FrameworkHelper::msCenterPaneURL
, AnchorBindingMode_DIRECT
))
182 mpViewShellBase
->SetViewTabBar(NULL
);
185 if (mxConfigurationController
.is())
187 // Unregister listener from XConfigurationController.
190 mxConfigurationController
->removeConfigurationChangeListener(this);
192 catch (lang::DisposedException e
)
194 // Receiving a disposed exception is the normal case. Is there
195 // a way to avoid it?
197 mxConfigurationController
= NULL
;
201 const ::vos::OGuard
aSolarGuard (Application::GetSolarMutex());
202 // Set all references to the one tab page to NULL and delete the page.
203 for (USHORT nIndex
=0; nIndex
<mpTabControl
->GetPageCount(); ++nIndex
)
204 mpTabControl
->SetTabPage(nIndex
, NULL
);
206 mpTabControl
.reset();
215 ::boost::shared_ptr
< ::TabControl
> ViewTabBar::GetTabControl (void) const
223 ::Window
* ViewTabBar::GetAnchorWindow(
224 const Reference
<XResourceId
>& rxViewTabBarId
,
225 const Reference
<frame::XController
>& rxController
)
227 ::Window
* pWindow
= NULL
;
228 ViewShellBase
* pBase
= NULL
;
230 // Tunnel through the controller and use the ViewShellBase to obtain the
234 Reference
<lang::XUnoTunnel
> xTunnel (rxController
, UNO_QUERY_THROW
);
235 DrawController
* pController
= reinterpret_cast<DrawController
*>(
236 xTunnel
->getSomething(DrawController::getUnoTunnelId()));
237 pBase
= pController
->GetViewShellBase();
239 catch(RuntimeException
&)
242 // The ViewTabBar supports at the moment only the center pane.
243 if (rxViewTabBarId
.is()
244 && rxViewTabBarId
->isBoundToURL(
245 FrameworkHelper::msCenterPaneURL
, AnchorBindingMode_DIRECT
))
247 if (pBase
!= NULL
&& pBase
->GetViewFrame() != NULL
)
248 pWindow
= &pBase
->GetViewFrame()->GetWindow();
251 // The rest is (at the moment) just for the emergency case.
254 Reference
<XPane
> xPane
;
257 Reference
<XControllerManager
> xControllerManager (rxController
, UNO_QUERY_THROW
);
258 Reference
<XConfigurationController
> xCC (
259 xControllerManager
->getConfigurationController());
261 xPane
= Reference
<XPane
>(xCC
->getResource(rxViewTabBarId
->getAnchor()), UNO_QUERY
);
263 catch (RuntimeException
&)
266 // Tunnel through the XWindow to the VCL side.
269 Reference
<lang::XUnoTunnel
> xTunnel (xPane
, UNO_QUERY_THROW
);
270 framework::Pane
* pPane
= reinterpret_cast<framework::Pane
*>(
271 xTunnel
->getSomething(framework::Pane::getUnoTunnelId()));
273 pWindow
= pPane
->GetWindow()->GetParent();
275 catch (RuntimeException
&)
285 //----- XConfigurationChangeListener ------------------------------------------
287 void SAL_CALL
ViewTabBar::notifyConfigurationChange (
288 const ConfigurationChangeEvent
& rEvent
)
289 throw (RuntimeException
)
291 if (rEvent
.Type
.equals(FrameworkHelper::msResourceActivationEvent
)
292 && rEvent
.ResourceId
->getResourceURL().match(FrameworkHelper::msViewURLPrefix
)
293 && rEvent
.ResourceId
->isBoundTo(mxViewTabBarId
->getAnchor(), AnchorBindingMode_DIRECT
))
295 UpdateActiveButton();
302 //----- XEventListener --------------------------------------------------------
304 void SAL_CALL
ViewTabBar::disposing(
305 const lang::EventObject
& rEvent
)
306 throw (RuntimeException
)
308 if (rEvent
.Source
== mxConfigurationController
)
310 mxConfigurationController
= NULL
;
318 //----- XTabBar ---------------------------------------------------------------
320 void SAL_CALL
ViewTabBar::addTabBarButtonAfter (
321 const TabBarButton
& rButton
,
322 const TabBarButton
& rAnchor
)
323 throw (::com::sun::star::uno::RuntimeException
)
325 const ::vos::OGuard
aSolarGuard (Application::GetSolarMutex());
326 AddTabBarButton(rButton
, rAnchor
);
332 void SAL_CALL
ViewTabBar::appendTabBarButton (const TabBarButton
& rButton
)
333 throw (::com::sun::star::uno::RuntimeException
)
335 const ::vos::OGuard
aSolarGuard (Application::GetSolarMutex());
336 AddTabBarButton(rButton
);
341 void SAL_CALL
ViewTabBar::removeTabBarButton (const TabBarButton
& rButton
)
342 throw (::com::sun::star::uno::RuntimeException
)
344 const ::vos::OGuard
aSolarGuard (Application::GetSolarMutex());
345 RemoveTabBarButton(rButton
);
351 sal_Bool SAL_CALL
ViewTabBar::hasTabBarButton (const TabBarButton
& rButton
)
352 throw (::com::sun::star::uno::RuntimeException
)
354 const ::vos::OGuard
aSolarGuard (Application::GetSolarMutex());
355 return HasTabBarButton(rButton
);
361 Sequence
<TabBarButton
> SAL_CALL
ViewTabBar::getTabBarButtons (void)
362 throw (::com::sun::star::uno::RuntimeException
)
364 const ::vos::OGuard
aSolarGuard (Application::GetSolarMutex());
365 return GetTabBarButtons();
371 //----- XResource -------------------------------------------------------------
373 Reference
<XResourceId
> SAL_CALL
ViewTabBar::getResourceId (void)
374 throw (RuntimeException
)
376 return mxViewTabBarId
;
382 sal_Bool SAL_CALL
ViewTabBar::isAnchorOnly (void)
383 throw (RuntimeException
)
391 //----- XUnoTunnel ------------------------------------------------------------
393 const Sequence
<sal_Int8
>& ViewTabBar::getUnoTunnelId (void)
395 static Sequence
<sal_Int8
>* pSequence
= NULL
;
396 if (pSequence
== NULL
)
398 const ::vos::OGuard
aSolarGuard (Application::GetSolarMutex());
399 if (pSequence
== NULL
)
401 static ::com::sun::star::uno::Sequence
<sal_Int8
> aSequence (16);
402 rtl_createUuid((sal_uInt8
*)aSequence
.getArray(), 0, sal_True
);
403 pSequence
= &aSequence
;
412 sal_Int64 SAL_CALL
ViewTabBar::getSomething (const Sequence
<sal_Int8
>& rId
)
413 throw (RuntimeException
)
415 sal_Int64 nResult
= 0;
417 if (rId
.getLength() == 16
418 && rtl_compareMemory(getUnoTunnelId().getConstArray(), rId
.getConstArray(), 16) == 0)
420 nResult
= reinterpret_cast<sal_Int64
>(this);
429 //-----------------------------------------------------------------------------
431 bool ViewTabBar::ActivatePage (void)
435 Reference
<XControllerManager
> xControllerManager (mxController
,UNO_QUERY_THROW
);
436 Reference
<XConfigurationController
> xConfigurationController (
437 xControllerManager
->getConfigurationController());
438 if ( ! xConfigurationController
.is())
439 throw RuntimeException();
440 Reference
<XView
> xView
;
443 xView
= Reference
<XView
>(xConfigurationController
->getResource(
445 ::comphelper::getProcessComponentContext(),
446 FrameworkHelper::msCenterPaneURL
)),
449 catch (DeploymentException
)
453 Client
* pIPClient
= NULL
;
454 if (mpViewShellBase
!= NULL
)
455 pIPClient
= dynamic_cast<Client
*>(mpViewShellBase
->GetIPClient());
456 if (pIPClient
==NULL
|| ! pIPClient
->IsObjectInPlaceActive())
458 USHORT
nIndex (mpTabControl
->GetCurPageId() - 1);
459 if (nIndex
< maTabBarButtons
.size())
461 xConfigurationController
->requestResourceActivation(
462 maTabBarButtons
[nIndex
].ResourceId
,
463 ResourceActivationMode_REPLACE
);
470 // When we run into this else branch then we have an active OLE
471 // object. We ignore the request to switch views. Additionally
472 // we put the active tab back to the one for the current view.
473 UpdateActiveButton();
476 catch (RuntimeException
&)
478 DBG_ASSERT(false,"ViewTabBar::ActivatePage(): caught exception");
487 int ViewTabBar::GetHeight (void)
491 if (maTabBarButtons
.size() > 0)
493 TabPage
* pActivePage (mpTabControl
->GetTabPage(
494 mpTabControl
->GetCurPageId()));
495 if (pActivePage
!=NULL
&& mpTabControl
->IsReallyVisible())
496 nHeight
= pActivePage
->GetPosPixel().Y();
499 // Using a default when the real height can not be determined.
500 // To get correct height this method should be called when the
501 // control is visible.
511 void ViewTabBar::AddTabBarButton (
512 const ::com::sun::star::drawing::framework::TabBarButton
& rButton
,
513 const ::com::sun::star::drawing::framework::TabBarButton
& rAnchor
)
517 if ( ! rAnchor
.ResourceId
.is()
518 || (rAnchor
.ResourceId
->getResourceURL().getLength() == 0
519 && rAnchor
.ButtonLabel
.getLength() == 0))
525 for (nIndex
=0; nIndex
<maTabBarButtons
.size(); ++nIndex
)
527 if (IsEqual(maTabBarButtons
[nIndex
], rAnchor
))
535 AddTabBarButton(rButton
,nIndex
);
541 void ViewTabBar::AddTabBarButton (
542 const ::com::sun::star::drawing::framework::TabBarButton
& rButton
)
544 AddTabBarButton(rButton
, maTabBarButtons
.size());
550 void ViewTabBar::AddTabBarButton (
551 const ::com::sun::star::drawing::framework::TabBarButton
& rButton
,
555 && nPosition
<=mpTabControl
->GetPageCount())
557 USHORT
nIndex ((USHORT
)nPosition
);
559 // Insert the button into our local array.
560 maTabBarButtons
.insert(maTabBarButtons
.begin()+nIndex
, rButton
);
561 UpdateTabBarButtons();
562 UpdateActiveButton();
569 void ViewTabBar::RemoveTabBarButton (
570 const ::com::sun::star::drawing::framework::TabBarButton
& rButton
)
573 for (nIndex
=0; nIndex
<maTabBarButtons
.size(); ++nIndex
)
575 if (IsEqual(maTabBarButtons
[nIndex
], rButton
))
577 maTabBarButtons
.erase(maTabBarButtons
.begin()+nIndex
);
578 UpdateTabBarButtons();
579 UpdateActiveButton();
588 bool ViewTabBar::HasTabBarButton (
589 const ::com::sun::star::drawing::framework::TabBarButton
& rButton
)
591 bool bResult (false);
593 for (sal_uInt32 nIndex
=0; nIndex
<maTabBarButtons
.size(); ++nIndex
)
595 if (IsEqual(maTabBarButtons
[nIndex
], rButton
))
608 ::com::sun::star::uno::Sequence
<com::sun::star::drawing::framework::TabBarButton
>
609 ViewTabBar::GetTabBarButtons (void)
611 sal_uInt32
nCount (maTabBarButtons
.size());
612 ::com::sun::star::uno::Sequence
<com::sun::star::drawing::framework::TabBarButton
>
615 for (sal_uInt32 nIndex
=0; nIndex
<nCount
; ++nIndex
)
616 aList
[nIndex
] = maTabBarButtons
[nIndex
];
624 void ViewTabBar::UpdateActiveButton (void)
626 Reference
<XView
> xView
;
627 if (mpViewShellBase
!= NULL
)
628 xView
= FrameworkHelper::Instance(*mpViewShellBase
)->GetView(
629 mxViewTabBarId
->getAnchor());
632 Reference
<XResourceId
> xViewId (xView
->getResourceId());
633 for (USHORT nIndex
=0; nIndex
<maTabBarButtons
.size(); ++nIndex
)
635 if (maTabBarButtons
[nIndex
].ResourceId
->compareTo(xViewId
) == 0)
637 mpTabControl
->SetCurPageId(nIndex
+1);
638 mpTabControl
->::TabControl::ActivatePage();
648 void ViewTabBar::UpdateTabBarButtons (void)
650 TabBarButtonList::const_iterator iTab
;
651 USHORT
nPageCount (mpTabControl
->GetPageCount());
653 for (iTab
=maTabBarButtons
.begin(),nIndex
=1; iTab
!=maTabBarButtons
.end(); ++iTab
,++nIndex
)
655 // Create a new tab when there are not enough.
656 if (nPageCount
< nIndex
)
657 mpTabControl
->InsertPage(nIndex
, iTab
->ButtonLabel
);
660 mpTabControl
->SetPageText(nIndex
, iTab
->ButtonLabel
);
661 mpTabControl
->SetHelpText(nIndex
, iTab
->HelpText
);
662 mpTabControl
->SetTabPage(nIndex
, mpTabPage
.get());
665 // Delete tabs that are no longer used.
666 for (; nIndex
<=nPageCount
; ++nIndex
)
667 mpTabControl
->RemovePage(nIndex
);
675 //===== TabBarControl =========================================================
677 TabBarControl::TabBarControl (
678 ::Window
* pParentWindow
,
679 const ::rtl::Reference
<ViewTabBar
>& rpViewTabBar
)
680 : ::TabControl(pParentWindow
),
681 mpViewTabBar(rpViewTabBar
)
688 void TabBarControl::Paint (const Rectangle
& rRect
)
690 Color
aOriginalFillColor (GetFillColor());
691 Color
aOriginalLineColor (GetLineColor());
693 // Because the actual window background is transparent--to avoid
694 // flickering due to multiple background paintings by this and by child
695 // windows--we have to paint the background for this control explicitly:
696 // the actual control is not painted over its whole bounding box.
697 SetFillColor (GetSettings().GetStyleSettings().GetDialogColor());
700 ::TabControl::Paint (rRect
);
702 SetFillColor (aOriginalFillColor
);
703 SetLineColor (aOriginalLineColor
);
709 void TabBarControl::ActivatePage (void)
711 if (mpViewTabBar
->ActivatePage())
713 // Call the parent so that the correct tab is highlighted.
714 this->::TabControl::ActivatePage();
718 } // end of namespace sd