fdo#74697 Add Bluez 5 support for impress remote.
[LibreOffice.git] / sd / source / ui / view / ViewTabBar.cxx
blobae0891d90b4c2381a3c616a9267f7cab3057db10
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 "ViewTabBar.hxx"
23 #include "ViewShell.hxx"
24 #include "ViewShellBase.hxx"
25 #include "DrawViewShell.hxx"
26 #include "FrameView.hxx"
27 #include "EventMultiplexer.hxx"
28 #include "framework/FrameworkHelper.hxx"
29 #include "framework/Pane.hxx"
30 #include "DrawController.hxx"
32 #include "sdresid.hxx"
33 #include "strings.hrc"
34 #include "helpids.h"
35 #include "Client.hxx"
36 #include <vcl/svapp.hxx>
37 #include <vcl/tabpage.hxx>
38 #include <osl/mutex.hxx>
39 #include <sfx2/viewfrm.hxx>
40 #include <com/sun/star/drawing/framework/ResourceId.hpp>
41 #include <com/sun/star/drawing/framework/XControllerManager.hpp>
42 #include <com/sun/star/lang/XUnoTunnel.hpp>
43 #include <com/sun/star/lang/DisposedException.hpp>
44 #include <comphelper/processfactory.hxx>
45 #include <comphelper/servicehelper.hxx>
46 #include <tools/diagnose_ex.h>
48 using namespace ::com::sun::star;
49 using namespace ::com::sun::star::uno;
50 using namespace ::com::sun::star::drawing::framework;
51 using ::sd::framework::FrameworkHelper;
52 using ::sd::tools::EventMultiplexerEvent;
54 namespace sd {
56 namespace {
57 bool IsEqual (const TabBarButton& rButton1, const TabBarButton& rButton2)
59 return (
60 (rButton1.ResourceId.is()
61 && rButton2.ResourceId.is()
62 && rButton1.ResourceId->compareTo(rButton2.ResourceId)==0)
63 || rButton1.ButtonLabel == rButton2.ButtonLabel);
66 class TabBarControl : public ::TabControl
68 public:
69 TabBarControl (
70 ::Window* pParentWindow,
71 const ::rtl::Reference<ViewTabBar>& rpViewTabBar);
72 virtual void Paint (const Rectangle& rRect);
73 virtual void ActivatePage (void);
74 private:
75 ::rtl::Reference<ViewTabBar> mpViewTabBar;
78 } // end of anonymous namespace
84 class ViewTabPage : public TabPage
86 public:
87 ViewTabPage (Window* pParent) : TabPage(pParent) {}
88 virtual void Resize (void)
89 { SetPosSizePixel(Point(0,0),GetParent()->GetOutputSizePixel()); }
95 //===== ViewTabBar ============================================================
97 ViewTabBar::ViewTabBar (
98 const Reference<XResourceId>& rxViewTabBarId,
99 const Reference<frame::XController>& rxController)
100 : ViewTabBarInterfaceBase(maMutex),
101 mpTabControl(new TabBarControl(GetAnchorWindow(rxViewTabBarId,rxController), this)),
102 mxController(rxController),
103 maTabBarButtons(),
104 mpTabPage(NULL),
105 mxViewTabBarId(rxViewTabBarId),
106 mpViewShellBase(NULL)
108 // Set one new tab page for all tab entries. We need it only to
109 // determine the height of the tab bar.
110 mpTabPage.reset(new TabPage (mpTabControl.get()));
111 mpTabPage->Hide();
113 // add some space before the tabitems
114 mpTabControl->SetItemsOffset(Point(5, 3));
116 // Tunnel through the controller and use the ViewShellBase to obtain the
117 // view frame.
120 Reference<lang::XUnoTunnel> xTunnel (mxController, UNO_QUERY_THROW);
121 DrawController* pController = reinterpret_cast<DrawController*>(
122 xTunnel->getSomething(DrawController::getUnoTunnelId()));
123 mpViewShellBase = pController->GetViewShellBase();
125 catch (const RuntimeException&)
129 // Register as listener at XConfigurationController.
130 Reference<XControllerManager> xControllerManager (mxController, UNO_QUERY);
131 if (xControllerManager.is())
133 mxConfigurationController = xControllerManager->getConfigurationController();
134 if (mxConfigurationController.is())
136 mxConfigurationController->addConfigurationChangeListener(
137 this,
138 FrameworkHelper::msResourceActivationEvent,
139 Any());
143 mpTabControl->Show();
145 if (mpViewShellBase != NULL
146 && rxViewTabBarId->isBoundToURL(
147 FrameworkHelper::msCenterPaneURL, AnchorBindingMode_DIRECT))
149 mpViewShellBase->SetViewTabBar(this);
156 ViewTabBar::~ViewTabBar (void)
163 void ViewTabBar::disposing (void)
165 if (mpViewShellBase != NULL
166 && mxViewTabBarId->isBoundToURL(
167 FrameworkHelper::msCenterPaneURL, AnchorBindingMode_DIRECT))
169 mpViewShellBase->SetViewTabBar(NULL);
172 if (mxConfigurationController.is())
174 // Unregister listener from XConfigurationController.
177 mxConfigurationController->removeConfigurationChangeListener(this);
179 catch (const lang::DisposedException&)
181 // Receiving a disposed exception is the normal case. Is there
182 // a way to avoid it?
184 mxConfigurationController = NULL;
188 const SolarMutexGuard aSolarGuard;
189 // Set all references to the one tab page to NULL and delete the page.
190 for (sal_uInt16 nIndex=0; nIndex<mpTabControl->GetPageCount(); ++nIndex)
191 mpTabControl->SetTabPage(nIndex, NULL);
192 mpTabPage.reset();
193 mpTabControl.reset();
196 mxController = NULL;
202 ::boost::shared_ptr< ::TabControl> ViewTabBar::GetTabControl (void) const
204 return mpTabControl;
210 ::Window* ViewTabBar::GetAnchorWindow(
211 const Reference<XResourceId>& rxViewTabBarId,
212 const Reference<frame::XController>& rxController)
214 ::Window* pWindow = NULL;
215 ViewShellBase* pBase = NULL;
217 // Tunnel through the controller and use the ViewShellBase to obtain the
218 // view frame.
221 Reference<lang::XUnoTunnel> xTunnel (rxController, UNO_QUERY_THROW);
222 DrawController* pController = reinterpret_cast<DrawController*>(
223 xTunnel->getSomething(DrawController::getUnoTunnelId()));
224 pBase = pController->GetViewShellBase();
226 catch (const RuntimeException&)
230 // The ViewTabBar supports at the moment only the center pane.
231 if (rxViewTabBarId.is()
232 && rxViewTabBarId->isBoundToURL(
233 FrameworkHelper::msCenterPaneURL, AnchorBindingMode_DIRECT))
235 if (pBase != NULL && pBase->GetViewFrame() != NULL)
236 pWindow = &pBase->GetViewFrame()->GetWindow();
239 // The rest is (at the moment) just for the emergency case.
240 if (pWindow == NULL)
242 Reference<XPane> xPane;
245 Reference<XControllerManager> xControllerManager (rxController, UNO_QUERY_THROW);
246 Reference<XConfigurationController> xCC (
247 xControllerManager->getConfigurationController());
248 if (xCC.is())
249 xPane = Reference<XPane>(xCC->getResource(rxViewTabBarId->getAnchor()), UNO_QUERY);
251 catch (const RuntimeException&)
255 // Tunnel through the XWindow to the VCL side.
258 Reference<lang::XUnoTunnel> xTunnel (xPane, UNO_QUERY_THROW);
259 framework::Pane* pPane = reinterpret_cast<framework::Pane*>(
260 xTunnel->getSomething(framework::Pane::getUnoTunnelId()));
261 if (pPane != NULL)
262 pWindow = pPane->GetWindow()->GetParent();
264 catch (const RuntimeException&)
269 return pWindow;
275 //----- XConfigurationChangeListener ------------------------------------------
277 void SAL_CALL ViewTabBar::notifyConfigurationChange (
278 const ConfigurationChangeEvent& rEvent)
279 throw (RuntimeException)
281 if (rEvent.Type.equals(FrameworkHelper::msResourceActivationEvent)
282 && rEvent.ResourceId->getResourceURL().match(FrameworkHelper::msViewURLPrefix)
283 && rEvent.ResourceId->isBoundTo(mxViewTabBarId->getAnchor(), AnchorBindingMode_DIRECT))
285 UpdateActiveButton();
292 //----- XEventListener --------------------------------------------------------
294 void SAL_CALL ViewTabBar::disposing(
295 const lang::EventObject& rEvent)
296 throw (RuntimeException)
298 if (rEvent.Source == mxConfigurationController)
300 mxConfigurationController = NULL;
301 mxController = NULL;
308 //----- XTabBar ---------------------------------------------------------------
310 void SAL_CALL ViewTabBar::addTabBarButtonAfter (
311 const TabBarButton& rButton,
312 const TabBarButton& rAnchor)
313 throw (::com::sun::star::uno::RuntimeException)
315 const SolarMutexGuard aSolarGuard;
316 AddTabBarButton(rButton, rAnchor);
322 void SAL_CALL ViewTabBar::appendTabBarButton (const TabBarButton& rButton)
323 throw (::com::sun::star::uno::RuntimeException)
325 const SolarMutexGuard aSolarGuard;
326 AddTabBarButton(rButton);
331 void SAL_CALL ViewTabBar::removeTabBarButton (const TabBarButton& rButton)
332 throw (::com::sun::star::uno::RuntimeException)
334 const SolarMutexGuard aSolarGuard;
335 RemoveTabBarButton(rButton);
341 sal_Bool SAL_CALL ViewTabBar::hasTabBarButton (const TabBarButton& rButton)
342 throw (::com::sun::star::uno::RuntimeException)
344 const SolarMutexGuard aSolarGuard;
345 return HasTabBarButton(rButton);
351 Sequence<TabBarButton> SAL_CALL ViewTabBar::getTabBarButtons (void)
352 throw (::com::sun::star::uno::RuntimeException)
354 const SolarMutexGuard aSolarGuard;
355 return GetTabBarButtons();
361 //----- XResource -------------------------------------------------------------
363 Reference<XResourceId> SAL_CALL ViewTabBar::getResourceId (void)
364 throw (RuntimeException)
366 return mxViewTabBarId;
372 sal_Bool SAL_CALL ViewTabBar::isAnchorOnly (void)
373 throw (RuntimeException)
375 return false;
381 //----- XUnoTunnel ------------------------------------------------------------
383 namespace
385 class theViewTabBarUnoTunnelId : public rtl::Static< UnoTunnelIdInit, theViewTabBarUnoTunnelId > {};
388 const Sequence<sal_Int8>& ViewTabBar::getUnoTunnelId (void)
390 return theViewTabBarUnoTunnelId::get().getSeq();
393 sal_Int64 SAL_CALL ViewTabBar::getSomething (const Sequence<sal_Int8>& rId)
394 throw (RuntimeException)
396 sal_Int64 nResult = 0;
398 if (rId.getLength() == 16
399 && memcmp(getUnoTunnelId().getConstArray(), rId.getConstArray(), 16) == 0)
401 nResult = reinterpret_cast<sal_Int64>(this);
404 return nResult;
410 //-----------------------------------------------------------------------------
412 bool ViewTabBar::ActivatePage (void)
416 Reference<XControllerManager> xControllerManager (mxController,UNO_QUERY_THROW);
417 Reference<XConfigurationController> xConfigurationController (
418 xControllerManager->getConfigurationController());
419 if ( ! xConfigurationController.is())
420 throw RuntimeException();
421 Reference<XView> xView;
424 xView = Reference<XView>(xConfigurationController->getResource(
425 ResourceId::create(
426 ::comphelper::getProcessComponentContext(),
427 FrameworkHelper::msCenterPaneURL)),
428 UNO_QUERY);
430 catch (const DeploymentException&)
434 Client* pIPClient = NULL;
435 if (mpViewShellBase != NULL)
436 pIPClient = dynamic_cast<Client*>(mpViewShellBase->GetIPClient());
437 if (pIPClient==NULL || ! pIPClient->IsObjectInPlaceActive())
439 sal_uInt16 nIndex (mpTabControl->GetCurPageId() - 1);
440 if (nIndex < maTabBarButtons.size())
442 xConfigurationController->requestResourceActivation(
443 maTabBarButtons[nIndex].ResourceId,
444 ResourceActivationMode_REPLACE);
447 return true;
449 else
451 // When we run into this else branch then we have an active OLE
452 // object. We ignore the request to switch views. Additionally
453 // we put the active tab back to the one for the current view.
454 UpdateActiveButton();
457 catch (const RuntimeException&)
459 DBG_UNHANDLED_EXCEPTION();
462 return false;
468 int ViewTabBar::GetHeight (void)
470 int nHeight (0);
472 if (!maTabBarButtons.empty())
474 TabPage* pActivePage (mpTabControl->GetTabPage(
475 mpTabControl->GetCurPageId()));
476 if (pActivePage!=NULL && mpTabControl->IsReallyVisible())
477 nHeight = pActivePage->GetPosPixel().Y();
479 if (nHeight <= 0)
480 // Using a default when the real height can not be determined.
481 // To get correct height this method should be called when the
482 // control is visible.
483 nHeight = 21;
486 return nHeight;
492 void ViewTabBar::AddTabBarButton (
493 const ::com::sun::star::drawing::framework::TabBarButton& rButton,
494 const ::com::sun::star::drawing::framework::TabBarButton& rAnchor)
496 sal_uInt32 nIndex;
498 if ( ! rAnchor.ResourceId.is()
499 || (rAnchor.ResourceId->getResourceURL().isEmpty()
500 && rAnchor.ButtonLabel.isEmpty()))
502 nIndex = 0;
504 else
506 for (nIndex=0; nIndex<maTabBarButtons.size(); ++nIndex)
508 if (IsEqual(maTabBarButtons[nIndex], rAnchor))
510 ++nIndex;
511 break;
516 AddTabBarButton(rButton,nIndex);
522 void ViewTabBar::AddTabBarButton (
523 const ::com::sun::star::drawing::framework::TabBarButton& rButton)
525 AddTabBarButton(rButton, maTabBarButtons.size());
531 void ViewTabBar::AddTabBarButton (
532 const ::com::sun::star::drawing::framework::TabBarButton& rButton,
533 sal_Int32 nPosition)
535 if (nPosition>=0
536 && nPosition<=mpTabControl->GetPageCount())
538 sal_uInt16 nIndex ((sal_uInt16)nPosition);
540 // Insert the button into our local array.
541 maTabBarButtons.insert(maTabBarButtons.begin()+nIndex, rButton);
542 UpdateTabBarButtons();
543 UpdateActiveButton();
550 void ViewTabBar::RemoveTabBarButton (
551 const ::com::sun::star::drawing::framework::TabBarButton& rButton)
553 sal_uInt16 nIndex;
554 for (nIndex=0; nIndex<maTabBarButtons.size(); ++nIndex)
556 if (IsEqual(maTabBarButtons[nIndex], rButton))
558 maTabBarButtons.erase(maTabBarButtons.begin()+nIndex);
559 UpdateTabBarButtons();
560 UpdateActiveButton();
561 break;
569 bool ViewTabBar::HasTabBarButton (
570 const ::com::sun::star::drawing::framework::TabBarButton& rButton)
572 bool bResult (false);
574 for (sal_uInt32 nIndex=0; nIndex<maTabBarButtons.size(); ++nIndex)
576 if (IsEqual(maTabBarButtons[nIndex], rButton))
578 bResult = true;
579 break;
583 return bResult;
589 ::com::sun::star::uno::Sequence<com::sun::star::drawing::framework::TabBarButton>
590 ViewTabBar::GetTabBarButtons (void)
592 sal_uInt32 nCount (maTabBarButtons.size());
593 ::com::sun::star::uno::Sequence<com::sun::star::drawing::framework::TabBarButton>
594 aList (nCount);
596 for (sal_uInt32 nIndex=0; nIndex<nCount; ++nIndex)
597 aList[nIndex] = maTabBarButtons[nIndex];
599 return aList;
605 void ViewTabBar::UpdateActiveButton (void)
607 Reference<XView> xView;
608 if (mpViewShellBase != NULL)
609 xView = FrameworkHelper::Instance(*mpViewShellBase)->GetView(
610 mxViewTabBarId->getAnchor());
611 if (xView.is())
613 Reference<XResourceId> xViewId (xView->getResourceId());
614 for (sal_uInt16 nIndex=0; nIndex<maTabBarButtons.size(); ++nIndex)
616 if (maTabBarButtons[nIndex].ResourceId->compareTo(xViewId) == 0)
618 mpTabControl->SetCurPageId(nIndex+1);
619 mpTabControl->::TabControl::ActivatePage();
620 break;
629 void ViewTabBar::UpdateTabBarButtons (void)
631 TabBarButtonList::const_iterator iTab;
632 sal_uInt16 nPageCount (mpTabControl->GetPageCount());
633 sal_uInt16 nIndex;
634 for (iTab=maTabBarButtons.begin(),nIndex=1; iTab!=maTabBarButtons.end(); ++iTab,++nIndex)
636 // Create a new tab when there are not enough.
637 if (nPageCount < nIndex)
638 mpTabControl->InsertPage(nIndex, iTab->ButtonLabel);
640 // Update the tab.
641 mpTabControl->SetPageText(nIndex, iTab->ButtonLabel);
642 mpTabControl->SetHelpText(nIndex, iTab->HelpText);
643 mpTabControl->SetTabPage(nIndex, mpTabPage.get());
646 // Delete tabs that are no longer used.
647 for (; nIndex<=nPageCount; ++nIndex)
648 mpTabControl->RemovePage(nIndex);
650 mpTabPage->Hide();
656 //===== TabBarControl =========================================================
658 TabBarControl::TabBarControl (
659 ::Window* pParentWindow,
660 const ::rtl::Reference<ViewTabBar>& rpViewTabBar)
661 : ::TabControl(pParentWindow),
662 mpViewTabBar(rpViewTabBar)
669 void TabBarControl::Paint (const Rectangle& rRect)
671 Color aOriginalFillColor (GetFillColor());
672 Color aOriginalLineColor (GetLineColor());
674 // Because the actual window background is transparent--to avoid
675 // flickering due to multiple background paintings by this and by child
676 // windows--we have to paint the background for this control explicitly:
677 // the actual control is not painted over its whole bounding box.
678 SetFillColor (GetSettings().GetStyleSettings().GetDialogColor());
679 SetLineColor ();
680 DrawRect (rRect);
681 ::TabControl::Paint (rRect);
683 SetFillColor (aOriginalFillColor);
684 SetLineColor (aOriginalLineColor);
690 void TabBarControl::ActivatePage (void)
692 if (mpViewTabBar->ActivatePage())
694 // Call the parent so that the correct tab is highlighted.
695 this->::TabControl::ActivatePage();
699 } // end of namespace sd
701 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */