bump product version to 5.0.4.1
[LibreOffice.git] / sd / source / ui / view / ViewTabBar.cxx
blobc32b92ff43ae9e630de352bf740e9578777acda0
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 .
20 #include "ViewTabBar.hxx"
22 #include "ViewShell.hxx"
23 #include "ViewShellBase.hxx"
24 #include "DrawViewShell.hxx"
25 #include "FrameView.hxx"
26 #include "EventMultiplexer.hxx"
27 #include "framework/FrameworkHelper.hxx"
28 #include "framework/Pane.hxx"
29 #include "DrawController.hxx"
31 #include "sdresid.hxx"
32 #include "strings.hrc"
33 #include "helpids.h"
34 #include "Client.hxx"
35 #include <vcl/svapp.hxx>
36 #include <vcl/tabpage.hxx>
37 #include <vcl/settings.hxx>
39 #include <osl/mutex.hxx>
40 #include <sfx2/viewfrm.hxx>
41 #include <com/sun/star/drawing/framework/ResourceId.hpp>
42 #include <com/sun/star/drawing/framework/XControllerManager.hpp>
43 #include <com/sun/star/lang/XUnoTunnel.hpp>
44 #include <com/sun/star/lang/DisposedException.hpp>
45 #include <comphelper/processfactory.hxx>
46 #include <comphelper/servicehelper.hxx>
47 #include <tools/diagnose_ex.h>
49 using namespace ::com::sun::star;
50 using namespace ::com::sun::star::uno;
51 using namespace ::com::sun::star::drawing::framework;
52 using ::sd::framework::FrameworkHelper;
53 using ::sd::tools::EventMultiplexerEvent;
55 namespace sd {
57 namespace {
58 bool IsEqual (const TabBarButton& rButton1, const TabBarButton& rButton2)
60 return ((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 (vcl::Window* pParentWindow, const ::rtl::Reference<ViewTabBar>& rpViewTabBar);
70 virtual void Paint (vcl::RenderContext& rRenderContext, const Rectangle& rRect) SAL_OVERRIDE;
71 virtual void ActivatePage() SAL_OVERRIDE;
72 private:
73 ::rtl::Reference<ViewTabBar> mpViewTabBar;
76 } // end of anonymous namespace
78 ViewTabBar::ViewTabBar (
79 const Reference<XResourceId>& rxViewTabBarId,
80 const Reference<frame::XController>& rxController)
81 : ViewTabBarInterfaceBase(maMutex),
82 mpTabControl(VclPtr<TabBarControl>::Create(GetAnchorWindow(rxViewTabBarId,rxController), this)),
83 mxController(rxController),
84 maTabBarButtons(),
85 mpTabPage(NULL),
86 mxViewTabBarId(rxViewTabBarId),
87 mpViewShellBase(NULL)
89 // Set one new tab page for all tab entries. We need it only to
90 // determine the height of the tab bar.
91 mpTabPage.reset(VclPtr<TabPage>::Create(mpTabControl.get()));
92 mpTabPage->Hide();
94 // add some space before the tabitems
95 mpTabControl->SetItemsOffset(Point(5, 3));
97 // Tunnel through the controller and use the ViewShellBase to obtain the
98 // view frame.
99 try
101 Reference<lang::XUnoTunnel> xTunnel (mxController, UNO_QUERY_THROW);
102 DrawController* pController = reinterpret_cast<DrawController*>(
103 xTunnel->getSomething(DrawController::getUnoTunnelId()));
104 mpViewShellBase = pController->GetViewShellBase();
106 catch (const RuntimeException&)
110 // Register as listener at XConfigurationController.
111 Reference<XControllerManager> xControllerManager (mxController, UNO_QUERY);
112 if (xControllerManager.is())
114 mxConfigurationController = xControllerManager->getConfigurationController();
115 if (mxConfigurationController.is())
117 mxConfigurationController->addConfigurationChangeListener(
118 this,
119 FrameworkHelper::msResourceActivationEvent,
120 Any());
124 mpTabControl->Show();
126 if (mpViewShellBase != NULL
127 && rxViewTabBarId->isBoundToURL(
128 FrameworkHelper::msCenterPaneURL, AnchorBindingMode_DIRECT))
130 mpViewShellBase->SetViewTabBar(this);
134 ViewTabBar::~ViewTabBar()
138 void ViewTabBar::disposing()
140 if (mpViewShellBase != NULL
141 && mxViewTabBarId->isBoundToURL(
142 FrameworkHelper::msCenterPaneURL, AnchorBindingMode_DIRECT))
144 mpViewShellBase->SetViewTabBar(NULL);
147 if (mxConfigurationController.is())
149 // Unregister listener from XConfigurationController.
152 mxConfigurationController->removeConfigurationChangeListener(this);
154 catch (const lang::DisposedException&)
156 // Receiving a disposed exception is the normal case. Is there
157 // a way to avoid it?
159 mxConfigurationController = NULL;
163 const SolarMutexGuard aSolarGuard;
164 // Set all references to the one tab page to NULL and delete the page.
165 for (sal_uInt16 nIndex=0; nIndex<mpTabControl->GetPageCount(); ++nIndex)
166 mpTabControl->SetTabPage(nIndex, NULL);
167 mpTabPage.disposeAndClear();
168 mpTabControl.disposeAndClear();
171 mxController = NULL;
174 vcl::Window* ViewTabBar::GetAnchorWindow(
175 const Reference<XResourceId>& rxViewTabBarId,
176 const Reference<frame::XController>& rxController)
178 vcl::Window* pWindow = NULL;
179 ViewShellBase* pBase = NULL;
181 // Tunnel through the controller and use the ViewShellBase to obtain the
182 // view frame.
185 Reference<lang::XUnoTunnel> xTunnel (rxController, UNO_QUERY_THROW);
186 DrawController* pController = reinterpret_cast<DrawController*>(
187 xTunnel->getSomething(DrawController::getUnoTunnelId()));
188 pBase = pController->GetViewShellBase();
190 catch (const RuntimeException&)
194 // The ViewTabBar supports at the moment only the center pane.
195 if (rxViewTabBarId.is()
196 && rxViewTabBarId->isBoundToURL(
197 FrameworkHelper::msCenterPaneURL, AnchorBindingMode_DIRECT))
199 if (pBase != NULL && pBase->GetViewFrame() != NULL)
200 pWindow = &pBase->GetViewFrame()->GetWindow();
203 // The rest is (at the moment) just for the emergency case.
204 if (pWindow == NULL)
206 Reference<XPane> xPane;
209 Reference<XControllerManager> xControllerManager (rxController, UNO_QUERY_THROW);
210 Reference<XConfigurationController> xCC (
211 xControllerManager->getConfigurationController());
212 if (xCC.is())
213 xPane = Reference<XPane>(xCC->getResource(rxViewTabBarId->getAnchor()), UNO_QUERY);
215 catch (const RuntimeException&)
219 // Tunnel through the XWindow to the VCL side.
222 Reference<lang::XUnoTunnel> xTunnel (xPane, UNO_QUERY_THROW);
223 framework::Pane* pPane = reinterpret_cast<framework::Pane*>(
224 xTunnel->getSomething(framework::Pane::getUnoTunnelId()));
225 if (pPane != NULL)
226 pWindow = pPane->GetWindow()->GetParent();
228 catch (const RuntimeException&)
233 return pWindow;
236 //----- XConfigurationChangeListener ------------------------------------------
238 void SAL_CALL ViewTabBar::notifyConfigurationChange (
239 const ConfigurationChangeEvent& rEvent)
240 throw (RuntimeException, std::exception)
242 if (rEvent.Type.equals(FrameworkHelper::msResourceActivationEvent)
243 && rEvent.ResourceId->getResourceURL().match(FrameworkHelper::msViewURLPrefix)
244 && rEvent.ResourceId->isBoundTo(mxViewTabBarId->getAnchor(), AnchorBindingMode_DIRECT))
246 UpdateActiveButton();
250 //----- XEventListener --------------------------------------------------------
252 void SAL_CALL ViewTabBar::disposing(
253 const lang::EventObject& rEvent)
254 throw (RuntimeException, std::exception)
256 if (rEvent.Source == mxConfigurationController)
258 mxConfigurationController = NULL;
259 mxController = NULL;
263 //----- XTabBar ---------------------------------------------------------------
265 void SAL_CALL ViewTabBar::addTabBarButtonAfter (
266 const TabBarButton& rButton,
267 const TabBarButton& rAnchor)
268 throw (::com::sun::star::uno::RuntimeException, std::exception)
270 const SolarMutexGuard aSolarGuard;
271 AddTabBarButton(rButton, rAnchor);
274 void SAL_CALL ViewTabBar::appendTabBarButton (const TabBarButton& rButton)
275 throw (::com::sun::star::uno::RuntimeException, std::exception)
277 const SolarMutexGuard aSolarGuard;
278 AddTabBarButton(rButton);
281 void SAL_CALL ViewTabBar::removeTabBarButton (const TabBarButton& rButton)
282 throw (::com::sun::star::uno::RuntimeException, std::exception)
284 const SolarMutexGuard aSolarGuard;
285 RemoveTabBarButton(rButton);
288 sal_Bool SAL_CALL ViewTabBar::hasTabBarButton (const TabBarButton& rButton)
289 throw (::com::sun::star::uno::RuntimeException, std::exception)
291 const SolarMutexGuard aSolarGuard;
292 return HasTabBarButton(rButton);
295 Sequence<TabBarButton> SAL_CALL ViewTabBar::getTabBarButtons()
296 throw (::com::sun::star::uno::RuntimeException, std::exception)
298 const SolarMutexGuard aSolarGuard;
299 return GetTabBarButtons();
302 //----- XResource -------------------------------------------------------------
304 Reference<XResourceId> SAL_CALL ViewTabBar::getResourceId()
305 throw (RuntimeException, std::exception)
307 return mxViewTabBarId;
310 sal_Bool SAL_CALL ViewTabBar::isAnchorOnly()
311 throw (RuntimeException, std::exception)
313 return false;
316 //----- XUnoTunnel ------------------------------------------------------------
318 namespace
320 class theViewTabBarUnoTunnelId : public rtl::Static< UnoTunnelIdInit, theViewTabBarUnoTunnelId > {};
323 const Sequence<sal_Int8>& ViewTabBar::getUnoTunnelId()
325 return theViewTabBarUnoTunnelId::get().getSeq();
328 sal_Int64 SAL_CALL ViewTabBar::getSomething (const Sequence<sal_Int8>& rId)
329 throw (RuntimeException, std::exception)
331 sal_Int64 nResult = 0;
333 if (rId.getLength() == 16
334 && memcmp(getUnoTunnelId().getConstArray(), rId.getConstArray(), 16) == 0)
336 nResult = reinterpret_cast<sal_Int64>(this);
339 return nResult;
342 bool ViewTabBar::ActivatePage()
346 Reference<XControllerManager> xControllerManager (mxController,UNO_QUERY_THROW);
347 Reference<XConfigurationController> xConfigurationController (
348 xControllerManager->getConfigurationController());
349 if ( ! xConfigurationController.is())
350 throw RuntimeException();
351 Reference<XView> xView;
354 xView = Reference<XView>(xConfigurationController->getResource(
355 ResourceId::create(
356 ::comphelper::getProcessComponentContext(),
357 FrameworkHelper::msCenterPaneURL)),
358 UNO_QUERY);
360 catch (const DeploymentException&)
364 Client* pIPClient = NULL;
365 if (mpViewShellBase != NULL)
366 pIPClient = dynamic_cast<Client*>(mpViewShellBase->GetIPClient());
367 if (pIPClient==NULL || ! pIPClient->IsObjectInPlaceActive())
369 sal_uInt16 nIndex (mpTabControl->GetCurPageId() - 1);
370 if (nIndex < maTabBarButtons.size())
372 xConfigurationController->requestResourceActivation(
373 maTabBarButtons[nIndex].ResourceId,
374 ResourceActivationMode_REPLACE);
377 return true;
379 else
381 // When we run into this else branch then we have an active OLE
382 // object. We ignore the request to switch views. Additionally
383 // we put the active tab back to the one for the current view.
384 UpdateActiveButton();
387 catch (const RuntimeException&)
389 DBG_UNHANDLED_EXCEPTION();
392 return false;
395 int ViewTabBar::GetHeight()
397 int nHeight (0);
399 if (!maTabBarButtons.empty())
401 TabPage* pActivePage (mpTabControl->GetTabPage(
402 mpTabControl->GetCurPageId()));
403 if (pActivePage!=NULL && mpTabControl->IsReallyVisible())
404 nHeight = pActivePage->GetPosPixel().Y();
406 if (nHeight <= 0)
407 // Using a default when the real height can not be determined.
408 // To get correct height this method should be called when the
409 // control is visible.
410 nHeight = 21;
413 return nHeight;
416 void ViewTabBar::AddTabBarButton (
417 const ::com::sun::star::drawing::framework::TabBarButton& rButton,
418 const ::com::sun::star::drawing::framework::TabBarButton& rAnchor)
420 sal_uInt32 nIndex;
422 if ( ! rAnchor.ResourceId.is()
423 || (rAnchor.ResourceId->getResourceURL().isEmpty()
424 && rAnchor.ButtonLabel.isEmpty()))
426 nIndex = 0;
428 else
430 for (nIndex=0; nIndex<maTabBarButtons.size(); ++nIndex)
432 if (IsEqual(maTabBarButtons[nIndex], rAnchor))
434 ++nIndex;
435 break;
440 AddTabBarButton(rButton,nIndex);
443 void ViewTabBar::AddTabBarButton (
444 const ::com::sun::star::drawing::framework::TabBarButton& rButton)
446 AddTabBarButton(rButton, maTabBarButtons.size());
449 void ViewTabBar::AddTabBarButton (
450 const ::com::sun::star::drawing::framework::TabBarButton& rButton,
451 sal_Int32 nPosition)
453 if (nPosition>=0
454 && nPosition<=mpTabControl->GetPageCount())
456 sal_uInt16 nIndex ((sal_uInt16)nPosition);
458 // Insert the button into our local array.
459 maTabBarButtons.insert(maTabBarButtons.begin()+nIndex, rButton);
460 UpdateTabBarButtons();
461 UpdateActiveButton();
465 void ViewTabBar::RemoveTabBarButton (
466 const ::com::sun::star::drawing::framework::TabBarButton& rButton)
468 sal_uInt16 nIndex;
469 for (nIndex=0; nIndex<maTabBarButtons.size(); ++nIndex)
471 if (IsEqual(maTabBarButtons[nIndex], rButton))
473 maTabBarButtons.erase(maTabBarButtons.begin()+nIndex);
474 UpdateTabBarButtons();
475 UpdateActiveButton();
476 break;
481 bool ViewTabBar::HasTabBarButton (
482 const ::com::sun::star::drawing::framework::TabBarButton& rButton)
484 bool bResult (false);
486 for (sal_uInt32 nIndex=0; nIndex<maTabBarButtons.size(); ++nIndex)
488 if (IsEqual(maTabBarButtons[nIndex], rButton))
490 bResult = true;
491 break;
495 return bResult;
498 ::com::sun::star::uno::Sequence<com::sun::star::drawing::framework::TabBarButton>
499 ViewTabBar::GetTabBarButtons()
501 sal_uInt32 nCount (maTabBarButtons.size());
502 ::com::sun::star::uno::Sequence<com::sun::star::drawing::framework::TabBarButton>
503 aList (nCount);
505 for (sal_uInt32 nIndex=0; nIndex<nCount; ++nIndex)
506 aList[nIndex] = maTabBarButtons[nIndex];
508 return aList;
511 void ViewTabBar::UpdateActiveButton()
513 Reference<XView> xView;
514 if (mpViewShellBase != NULL)
515 xView = FrameworkHelper::Instance(*mpViewShellBase)->GetView(
516 mxViewTabBarId->getAnchor());
517 if (xView.is())
519 Reference<XResourceId> xViewId (xView->getResourceId());
520 for (sal_uInt16 nIndex=0; nIndex<maTabBarButtons.size(); ++nIndex)
522 if (maTabBarButtons[nIndex].ResourceId->compareTo(xViewId) == 0)
524 mpTabControl->SetCurPageId(nIndex+1);
525 mpTabControl->::TabControl::ActivatePage();
526 break;
532 void ViewTabBar::UpdateTabBarButtons()
534 TabBarButtonList::const_iterator iTab;
535 sal_uInt16 nPageCount (mpTabControl->GetPageCount());
536 sal_uInt16 nIndex;
537 for (iTab=maTabBarButtons.begin(),nIndex=1; iTab!=maTabBarButtons.end(); ++iTab,++nIndex)
539 // Create a new tab when there are not enough.
540 if (nPageCount < nIndex)
541 mpTabControl->InsertPage(nIndex, iTab->ButtonLabel);
543 // Update the tab.
544 mpTabControl->SetPageText(nIndex, iTab->ButtonLabel);
545 mpTabControl->SetHelpText(nIndex, iTab->HelpText);
546 mpTabControl->SetTabPage(nIndex, mpTabPage.get());
549 // Delete tabs that are no longer used.
550 for (; nIndex<=nPageCount; ++nIndex)
551 mpTabControl->RemovePage(nIndex);
553 mpTabPage->Hide();
556 //===== TabBarControl =========================================================
558 TabBarControl::TabBarControl (
559 vcl::Window* pParentWindow,
560 const ::rtl::Reference<ViewTabBar>& rpViewTabBar)
561 : ::TabControl(pParentWindow),
562 mpViewTabBar(rpViewTabBar)
566 void TabBarControl::Paint (vcl::RenderContext& rRenderContext, const Rectangle& rRect)
568 Color aOriginalFillColor(rRenderContext.GetFillColor());
569 Color aOriginalLineColor(rRenderContext.GetLineColor());
571 // Because the actual window background is transparent--to avoid
572 // flickering due to multiple background paintings by this and by child
573 // windows--we have to paint the background for this control explicitly:
574 // the actual control is not painted over its whole bounding box.
575 rRenderContext.SetFillColor(rRenderContext.GetSettings().GetStyleSettings().GetDialogColor());
576 rRenderContext.SetLineColor();
577 rRenderContext.DrawRect(rRect);
579 ::TabControl::Paint(rRenderContext, rRect);
581 rRenderContext.SetFillColor(aOriginalFillColor);
582 rRenderContext.SetLineColor(aOriginalLineColor);
585 void TabBarControl::ActivatePage()
587 if (mpViewTabBar->ActivatePage())
589 // Call the parent so that the correct tab is highlighted.
590 this->::TabControl::ActivatePage();
594 } // end of namespace sd
596 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */