merge the formfield patch from ooo-build
[ooovba.git] / sd / source / ui / view / ViewTabBar.cxx
blob10ede3835ed9d361792287f7002faf9adc0c0215
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: ViewTabBar.cxx,v $
10 * $Revision: 1.14 $
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"
49 #include "helpids.h"
50 #include "Client.hxx"
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;
68 namespace sd {
70 namespace {
71 bool IsEqual (const TabBarButton& rButton1, const TabBarButton& rButton2)
73 return (
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
82 public:
83 TabBarControl (
84 ::Window* pParentWindow,
85 const ::rtl::Reference<ViewTabBar>& rpViewTabBar);
86 virtual void Paint (const Rectangle& rRect);
87 virtual void ActivatePage (void);
88 private:
89 ::rtl::Reference<ViewTabBar> mpViewTabBar;
92 } // end of anonymous namespace
98 class ViewTabPage : public TabPage
100 public:
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),
117 maTabBarButtons(),
118 mpTabPage(NULL),
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()));
125 mpTabPage->Hide();
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
131 // view frame.
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(
150 this,
151 FrameworkHelper::msResourceActivationEvent,
152 Any());
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);
205 mpTabPage.reset();
206 mpTabControl.reset();
209 mxController = NULL;
215 ::boost::shared_ptr< ::TabControl> ViewTabBar::GetTabControl (void) const
217 return mpTabControl;
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
231 // view frame.
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.
252 if (pWindow == NULL)
254 Reference<XPane> xPane;
257 Reference<XControllerManager> xControllerManager (rxController, UNO_QUERY_THROW);
258 Reference<XConfigurationController> xCC (
259 xControllerManager->getConfigurationController());
260 if (xCC.is())
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()));
272 if (pPane != NULL)
273 pWindow = pPane->GetWindow()->GetParent();
275 catch (RuntimeException&)
279 return pWindow;
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;
311 mxController = 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)
385 return false;
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;
406 return *pSequence;
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);
423 return nResult;
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(
444 ResourceId::create(
445 ::comphelper::getProcessComponentContext(),
446 FrameworkHelper::msCenterPaneURL)),
447 UNO_QUERY);
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);
466 return true;
468 else
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");
481 return false;
487 int ViewTabBar::GetHeight (void)
489 int nHeight (0);
491 if (maTabBarButtons.size() > 0)
493 TabPage* pActivePage (mpTabControl->GetTabPage(
494 mpTabControl->GetCurPageId()));
495 if (pActivePage!=NULL && mpTabControl->IsReallyVisible())
496 nHeight = pActivePage->GetPosPixel().Y();
498 if (nHeight <= 0)
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.
502 nHeight = 21;
505 return nHeight;
511 void ViewTabBar::AddTabBarButton (
512 const ::com::sun::star::drawing::framework::TabBarButton& rButton,
513 const ::com::sun::star::drawing::framework::TabBarButton& rAnchor)
515 sal_uInt32 nIndex;
517 if ( ! rAnchor.ResourceId.is()
518 || (rAnchor.ResourceId->getResourceURL().getLength() == 0
519 && rAnchor.ButtonLabel.getLength() == 0))
521 nIndex = 0;
523 else
525 for (nIndex=0; nIndex<maTabBarButtons.size(); ++nIndex)
527 if (IsEqual(maTabBarButtons[nIndex], rAnchor))
529 ++nIndex;
530 break;
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,
552 sal_Int32 nPosition)
554 if (nPosition>=0
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)
572 USHORT nIndex;
573 for (nIndex=0; nIndex<maTabBarButtons.size(); ++nIndex)
575 if (IsEqual(maTabBarButtons[nIndex], rButton))
577 maTabBarButtons.erase(maTabBarButtons.begin()+nIndex);
578 UpdateTabBarButtons();
579 UpdateActiveButton();
580 break;
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))
597 bResult = true;
598 break;
602 return bResult;
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>
613 aList (nCount);
615 for (sal_uInt32 nIndex=0; nIndex<nCount; ++nIndex)
616 aList[nIndex] = maTabBarButtons[nIndex];
618 return aList;
624 void ViewTabBar::UpdateActiveButton (void)
626 Reference<XView> xView;
627 if (mpViewShellBase != NULL)
628 xView = FrameworkHelper::Instance(*mpViewShellBase)->GetView(
629 mxViewTabBarId->getAnchor());
630 if (xView.is())
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();
639 break;
648 void ViewTabBar::UpdateTabBarButtons (void)
650 TabBarButtonList::const_iterator iTab;
651 USHORT nPageCount (mpTabControl->GetPageCount());
652 USHORT nIndex;
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);
659 // Update the tab.
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);
669 mpTabPage->Hide();
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());
698 SetLineColor ();
699 DrawRect (rRect);
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