Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 : #include "SidebarController.hxx"
20 : #include "Deck.hxx"
21 : #include "DeckTitleBar.hxx"
22 : #include "Panel.hxx"
23 : #include "PanelTitleBar.hxx"
24 : #include "SidebarResource.hxx"
25 : #include "TabBar.hxx"
26 : #include <sfx2/sidebar/Theme.hxx>
27 : #include <sfx2/sidebar/SidebarChildWindow.hxx>
28 : #include <sfx2/sidebar/Tools.hxx>
29 : #include "SidebarDockingWindow.hxx"
30 : #include "Context.hxx"
31 :
32 : #include <sfx2/sfxresid.hxx>
33 : #include <sfx2/sfxsids.hrc>
34 : #include <sfx2/titledockwin.hxx>
35 : #include "sfxlocal.hrc"
36 : #include <vcl/floatwin.hxx>
37 : #include <vcl/fixed.hxx>
38 : #include "splitwin.hxx"
39 : #include <svl/smplhint.hxx>
40 : #include <tools/link.hxx>
41 : #include <toolkit/helper/vclunohelper.hxx>
42 : #include <comphelper/processfactory.hxx>
43 : #include <comphelper/namedvaluecollection.hxx>
44 :
45 : #include <com/sun/star/frame/XDispatchProvider.hpp>
46 : #include <com/sun/star/lang/XInitialization.hpp>
47 : #include <com/sun/star/ui/ContextChangeEventMultiplexer.hpp>
48 : #include <com/sun/star/ui/ContextChangeEventObject.hpp>
49 : #include <com/sun/star/ui/theUIElementFactoryManager.hpp>
50 : #include <com/sun/star/util/XURLTransformer.hpp>
51 : #include <com/sun/star/util/URL.hpp>
52 : #include <com/sun/star/rendering/XSpriteCanvas.hpp>
53 :
54 : #include <boost/bind.hpp>
55 : #include <boost/function.hpp>
56 : #include <boost/scoped_array.hpp>
57 :
58 :
59 : using namespace css;
60 : using namespace css::uno;
61 : using ::rtl::OUString;
62 :
63 :
64 : #undef VERBOSE
65 :
66 : namespace
67 : {
68 : const static char gsReadOnlyCommandName[] = ".uno:EditDoc";
69 : const static sal_Int32 gnMaximumSidebarWidth (400);
70 : const static sal_Int32 gnWidthCloseThreshold (70);
71 : const static sal_Int32 gnWidthOpenThreshold (40);
72 : }
73 :
74 :
75 : namespace sfx2 { namespace sidebar {
76 :
77 317 : SidebarController::SidebarControllerContainer SidebarController::maSidebarControllerContainer;
78 :
79 : namespace {
80 : enum MenuId
81 : {
82 : MID_UNLOCK_TASK_PANEL = 1,
83 : MID_LOCK_TASK_PANEL,
84 : MID_CUSTOMIZATION,
85 : MID_RESTORE_DEFAULT,
86 : MID_FIRST_PANEL,
87 : MID_FIRST_HIDE = 1000
88 : };
89 :
90 : /** When in doubt, show this deck.
91 : */
92 : static const char gsDefaultDeckId[] = "PropertyDeck";
93 : }
94 :
95 4700 : SidebarController::SidebarController (
96 : SidebarDockingWindow* pParentWindow,
97 : const css::uno::Reference<css::frame::XFrame>& rxFrame)
98 : : SidebarControllerInterfaceBase(m_aMutex),
99 : mpCurrentDeck(),
100 : mpParentWindow(pParentWindow),
101 : mpTabBar(new TabBar(
102 : mpParentWindow,
103 : rxFrame,
104 : ::boost::bind(&SidebarController::OpenThenSwitchToDeck, this, _1),
105 4700 : ::boost::bind(&SidebarController::ShowPopupMenu, this, _1,_2))),
106 : mxFrame(rxFrame),
107 : maCurrentContext(OUString(), OUString()),
108 : maRequestedContext(),
109 : mnRequestedForceFlags(SwitchFlag_NoForce),
110 : msCurrentDeckId(gsDefaultDeckId),
111 : msCurrentDeckTitle(),
112 : maPropertyChangeForwarder(::boost::bind(&SidebarController::BroadcastPropertyChange, this)),
113 : maContextChangeUpdate(::boost::bind(&SidebarController::UpdateConfigurations, this)),
114 : maAsynchronousDeckSwitch(),
115 : mbIsDeckRequestedOpen(),
116 : mbIsDeckOpen(),
117 : mbCanDeckBeOpened(true),
118 9400 : mnSavedSidebarWidth(pParentWindow->GetSizePixel().Width()),
119 : maFocusManager(::boost::bind(&SidebarController::ShowPanel, this, _1)),
120 : mxReadOnlyModeDispatch(),
121 : mbIsDocumentReadOnly(false),
122 : mpSplitWindow(NULL),
123 : mnWidthOnSplitterButtonDown(0),
124 18800 : mpCloseIndicator()
125 : {
126 : // Listen for context change events.
127 : css::uno::Reference<css::ui::XContextChangeEventMultiplexer> xMultiplexer (
128 : css::ui::ContextChangeEventMultiplexer::get(
129 4700 : ::comphelper::getProcessComponentContext()));
130 4700 : if (xMultiplexer.is())
131 4700 : xMultiplexer->addContextChangeEventListener(
132 : static_cast<css::ui::XContextChangeEventListener*>(this),
133 4700 : mxFrame->getController());
134 :
135 : // Listen for window events.
136 4700 : mpParentWindow->AddEventListener(LINK(this, SidebarController, WindowEventHandler));
137 :
138 : // Listen for theme property changes.
139 9400 : Theme::GetPropertySet()->addPropertyChangeListener(
140 : OUString(""),
141 4700 : static_cast<css::beans::XPropertyChangeListener*>(this));
142 :
143 : // Get the dispatch object as preparation to listen for changes of
144 : // the read-only state.
145 9400 : const util::URL aURL (Tools::GetURL(gsReadOnlyCommandName));
146 4700 : mxReadOnlyModeDispatch = Tools::GetDispatch(mxFrame, aURL);
147 4700 : if (mxReadOnlyModeDispatch.is())
148 4700 : mxReadOnlyModeDispatch->addStatusListener(this, aURL);
149 :
150 4700 : SwitchToDeck(gsDefaultDeckId);
151 :
152 9400 : WeakReference<SidebarController> xWeakController (this);
153 : maSidebarControllerContainer.insert(
154 : SidebarControllerContainer::value_type(
155 : rxFrame,
156 9400 : xWeakController));
157 4700 : }
158 :
159 9400 : SidebarController::~SidebarController (void)
160 : {
161 9400 : }
162 :
163 0 : SidebarController* SidebarController::GetSidebarControllerForFrame (
164 : const css::uno::Reference<css::frame::XFrame>& rxFrame)
165 : {
166 0 : SidebarControllerContainer::iterator iEntry (maSidebarControllerContainer.find(rxFrame));
167 0 : if (iEntry == maSidebarControllerContainer.end())
168 0 : return NULL;
169 :
170 0 : css::uno::Reference<XInterface> xController (iEntry->second.get());
171 0 : if ( ! xController.is())
172 0 : return NULL;
173 :
174 0 : return dynamic_cast<SidebarController*>(xController.get());
175 : }
176 :
177 4700 : void SAL_CALL SidebarController::disposing (void)
178 : {
179 4700 : SidebarControllerContainer::iterator iEntry (maSidebarControllerContainer.find(mxFrame));
180 4700 : if (iEntry != maSidebarControllerContainer.end())
181 4700 : maSidebarControllerContainer.erase(iEntry);
182 :
183 4700 : maFocusManager.Clear();
184 :
185 : css::uno::Reference<css::ui::XContextChangeEventMultiplexer> xMultiplexer (
186 : css::ui::ContextChangeEventMultiplexer::get(
187 4700 : ::comphelper::getProcessComponentContext()));
188 4700 : if (xMultiplexer.is())
189 4700 : xMultiplexer->removeAllContextChangeEventListeners(
190 4700 : static_cast<css::ui::XContextChangeEventListener*>(this));
191 :
192 4700 : if (mxReadOnlyModeDispatch.is())
193 4700 : mxReadOnlyModeDispatch->removeStatusListener(this, Tools::GetURL(gsReadOnlyCommandName));
194 4700 : if (mpSplitWindow != NULL)
195 : {
196 4700 : mpSplitWindow->RemoveEventListener(LINK(this, SidebarController, WindowEventHandler));
197 4700 : mpSplitWindow = NULL;
198 : }
199 :
200 4700 : if (mpParentWindow != NULL)
201 : {
202 4700 : mpParentWindow->RemoveEventListener(LINK(this, SidebarController, WindowEventHandler));
203 4700 : mpParentWindow = NULL;
204 : }
205 :
206 4700 : if (mpCurrentDeck)
207 : {
208 4700 : mpCurrentDeck->Dispose();
209 4700 : mpCurrentDeck->PrintWindowTree();
210 4700 : mpCurrentDeck.reset();
211 : }
212 :
213 4700 : mpTabBar.reset();
214 :
215 9400 : Theme::GetPropertySet()->removePropertyChangeListener(
216 : OUString(""),
217 4700 : static_cast<css::beans::XPropertyChangeListener*>(this));
218 :
219 4700 : maContextChangeUpdate.CancelRequest();
220 4700 : maAsynchronousDeckSwitch.CancelRequest();
221 4700 : }
222 :
223 :
224 :
225 :
226 10000 : void SAL_CALL SidebarController::notifyContextChangeEvent (const css::ui::ContextChangeEventObject& rEvent)
227 : throw(css::uno::RuntimeException, std::exception)
228 : {
229 : // Update to the requested new context asynchronously to avoid
230 : // subtle errors caused by SFX2 which in rare cases can not
231 : // properly handle a synchronous update.
232 20000 : maRequestedContext = Context(
233 : rEvent.ApplicationName,
234 10000 : rEvent.ContextName);
235 10000 : if (maRequestedContext != maCurrentContext)
236 : {
237 5283 : maAsynchronousDeckSwitch.CancelRequest();
238 5283 : maContextChangeUpdate.RequestCall();
239 : }
240 10000 : }
241 :
242 :
243 :
244 :
245 0 : void SAL_CALL SidebarController::disposing (const css::lang::EventObject& rEventObject)
246 : throw(css::uno::RuntimeException, std::exception)
247 : {
248 : (void)rEventObject;
249 :
250 0 : dispose();
251 0 : }
252 :
253 :
254 :
255 :
256 0 : void SAL_CALL SidebarController::propertyChange (const css::beans::PropertyChangeEvent& rEvent)
257 : throw(css::uno::RuntimeException, std::exception)
258 : {
259 : (void)rEvent;
260 :
261 0 : maPropertyChangeForwarder.RequestCall();
262 0 : }
263 :
264 :
265 :
266 :
267 4887 : void SAL_CALL SidebarController::statusChanged (const css::frame::FeatureStateEvent& rEvent)
268 : throw(css::uno::RuntimeException, std::exception)
269 : {
270 4887 : bool bIsReadWrite (true);
271 4887 : if (rEvent.IsEnabled)
272 3797 : rEvent.State >>= bIsReadWrite;
273 :
274 4887 : if (mbIsDocumentReadOnly != !bIsReadWrite)
275 : {
276 2 : mbIsDocumentReadOnly = !bIsReadWrite;
277 :
278 : // Force the current deck to update its panel list.
279 2 : if ( ! mbIsDocumentReadOnly)
280 0 : msCurrentDeckId = gsDefaultDeckId;
281 2 : mnRequestedForceFlags |= SwitchFlag_ForceSwitch;
282 2 : maAsynchronousDeckSwitch.CancelRequest();
283 2 : maContextChangeUpdate.RequestCall();
284 : }
285 4887 : }
286 :
287 :
288 :
289 :
290 806 : void SAL_CALL SidebarController::requestLayout (void)
291 : throw(css::uno::RuntimeException, std::exception)
292 : {
293 806 : sal_Int32 nMinimalWidth = 0;
294 806 : if (mpCurrentDeck)
295 : {
296 806 : mpCurrentDeck->RequestLayout();
297 806 : nMinimalWidth = mpCurrentDeck->GetMinimalWidth();
298 : }
299 806 : RestrictWidth(nMinimalWidth);
300 806 : }
301 :
302 0 : void SidebarController::BroadcastPropertyChange (void)
303 : {
304 0 : DataChangedEvent aEvent (DATACHANGED_USER);
305 0 : mpParentWindow->NotifyAllChildren(aEvent);
306 0 : mpParentWindow->Invalidate(INVALIDATE_CHILDREN);
307 0 : }
308 :
309 24190 : void SidebarController::NotifyResize (void)
310 : {
311 24190 : if (mpTabBar == 0)
312 : {
313 : OSL_ASSERT(mpTabBar!=0);
314 24190 : return;
315 : }
316 :
317 24190 : vcl::Window* pParentWindow = mpTabBar->GetParent();
318 24190 : sal_Int32 nTabBarDefaultWidth = TabBar::GetDefaultWidth() * mpTabBar->GetDPIScaleFactor();
319 :
320 24190 : const sal_Int32 nWidth (pParentWindow->GetSizePixel().Width());
321 24190 : const sal_Int32 nHeight (pParentWindow->GetSizePixel().Height());
322 :
323 24190 : mbIsDeckOpen = (nWidth > nTabBarDefaultWidth);
324 :
325 24190 : if (mnSavedSidebarWidth <= 0)
326 9398 : mnSavedSidebarWidth = nWidth;
327 :
328 : bool bIsDeckVisible;
329 24190 : if (mbCanDeckBeOpened)
330 : {
331 24190 : const bool bIsOpening (nWidth > mnWidthOnSplitterButtonDown);
332 24190 : if (bIsOpening)
333 19492 : bIsDeckVisible = nWidth >= nTabBarDefaultWidth + gnWidthOpenThreshold;
334 : else
335 4698 : bIsDeckVisible = nWidth >= nTabBarDefaultWidth + gnWidthCloseThreshold;
336 24190 : mbIsDeckRequestedOpen = bIsDeckVisible;
337 24190 : UpdateCloseIndicator(!bIsDeckVisible);
338 : }
339 : else
340 0 : bIsDeckVisible = false;
341 :
342 24190 : if (mpCurrentDeck)
343 : {
344 24190 : SfxSplitWindow* pSplitWindow = GetSplitWindow();
345 24190 : if (pSplitWindow) //in sidebar mode
346 : {
347 : // Find out that which side of the Window do we need to attach the Sidebar?
348 19492 : if ( pSplitWindow->GetAlign() == WINDOWALIGN_RIGHT ) // attach the Sidebar towards the right-side of screen
349 : {
350 : // Place the deck first.
351 : {
352 19492 : if (bIsDeckVisible)
353 : {
354 19492 : mpCurrentDeck->setPosSizePixel(0,0, nWidth-nTabBarDefaultWidth, nHeight);
355 19492 : mpCurrentDeck->Show();
356 19492 : mpCurrentDeck->RequestLayout();
357 : }
358 : else
359 0 : mpCurrentDeck->Hide();
360 : }
361 :
362 : // Now place the tab bar.
363 19492 : mpTabBar->setPosSizePixel(nWidth-nTabBarDefaultWidth,0,nTabBarDefaultWidth,nHeight);
364 19492 : mpTabBar->Show();
365 : }
366 0 : else if ( pSplitWindow->GetAlign() == WINDOWALIGN_LEFT) // attach the Sidebar towards the left-side of screen
367 : {
368 : // Place the tab bar first.
369 0 : mpTabBar->setPosSizePixel(0,0,nTabBarDefaultWidth,nHeight);
370 0 : mpTabBar->Show();
371 :
372 : // Now place the deck.
373 0 : if (bIsDeckVisible)
374 : {
375 0 : mpCurrentDeck->setPosSizePixel(nTabBarDefaultWidth,0, nWidth-nTabBarDefaultWidth, nHeight);
376 0 : mpCurrentDeck->Show();
377 0 : mpCurrentDeck->RequestLayout();
378 : }
379 : else
380 0 : mpCurrentDeck->Hide();
381 : }
382 : }
383 : else //floating window mode
384 : {
385 : // Place the deck first.
386 : {
387 4698 : if (bIsDeckVisible)
388 : {
389 0 : mpCurrentDeck->setPosSizePixel(0,0, nWidth-nTabBarDefaultWidth, nHeight);
390 0 : mpCurrentDeck->Show();
391 0 : mpCurrentDeck->RequestLayout();
392 : }
393 : else
394 4698 : mpCurrentDeck->Hide();
395 : }
396 :
397 : // Now place the tab bar.
398 4698 : mpTabBar->setPosSizePixel(nWidth-nTabBarDefaultWidth,0,nTabBarDefaultWidth,nHeight);
399 4698 : mpTabBar->Show();
400 : }
401 : }
402 :
403 : // Determine if the closer of the deck can be shown.
404 24190 : sal_Int32 nMinimalWidth = 0;
405 24190 : if (mpCurrentDeck)
406 : {
407 24190 : DeckTitleBar* pTitleBar = mpCurrentDeck->GetTitleBar();
408 24190 : if (pTitleBar != NULL && pTitleBar->IsVisible())
409 19492 : pTitleBar->SetCloserVisible(CanModifyChildWindowWidth());
410 24190 : nMinimalWidth = mpCurrentDeck->GetMinimalWidth();
411 : }
412 :
413 24190 : RestrictWidth(nMinimalWidth);
414 : }
415 :
416 0 : void SidebarController::ProcessNewWidth (const sal_Int32 nNewWidth)
417 : {
418 0 : if ( ! mbIsDeckRequestedOpen)
419 0 : return;
420 :
421 0 : if (mbIsDeckRequestedOpen.get())
422 : {
423 : // Deck became large enough to be shown. Show it.
424 0 : mnSavedSidebarWidth = nNewWidth;
425 0 : RequestOpenDeck();
426 : }
427 : else
428 : {
429 : // Deck became too small. Close it completely.
430 : // If window is wider than the tab bar then mark the deck as being visible, even when it its not.
431 : // This is to trigger an adjustment of the width to the width of the tab bar.
432 0 : mbIsDeckOpen = true;
433 0 : RequestCloseDeck();
434 :
435 0 : if (mnWidthOnSplitterButtonDown > TabBar::GetDefaultWidth() * mpTabBar->GetDPIScaleFactor())
436 0 : mnSavedSidebarWidth = mnWidthOnSplitterButtonDown;
437 : }
438 : }
439 :
440 :
441 :
442 :
443 788 : void SidebarController::UpdateConfigurations (void)
444 : {
445 1576 : if (maCurrentContext != maRequestedContext
446 788 : || mnRequestedForceFlags!=SwitchFlag_NoForce)
447 : {
448 786 : maCurrentContext = maRequestedContext;
449 :
450 : // Find the set of decks that could be displayed for the new context.
451 786 : ResourceManager::DeckContextDescriptorContainer aDecks;
452 786 : ResourceManager::Instance().GetMatchingDecks (
453 : aDecks,
454 : maCurrentContext,
455 : mbIsDocumentReadOnly,
456 1572 : mxFrame);
457 :
458 : // Notify the tab bar about the updated set of decks.
459 786 : mpTabBar->SetDecks(aDecks);
460 :
461 : // Find the new deck. By default that is the same as the old
462 : // one. If that is not set or not enabled, then choose the
463 : // first enabled deck (which is PropertyDeck).
464 1572 : OUString sNewDeckId;
465 800 : for (ResourceManager::DeckContextDescriptorContainer::const_iterator
466 786 : iDeck(aDecks.begin()),
467 786 : iEnd(aDecks.end());
468 : iDeck!=iEnd;
469 : ++iDeck)
470 : {
471 798 : if (iDeck->mbIsEnabled)
472 : {
473 786 : if (iDeck->msId.equals(msCurrentDeckId))
474 : {
475 784 : sNewDeckId = msCurrentDeckId;
476 784 : break;
477 : }
478 2 : else if (sNewDeckId.getLength() == 0)
479 2 : sNewDeckId = iDeck->msId;
480 : }
481 : }
482 :
483 786 : if (sNewDeckId.getLength() == 0)
484 : {
485 : // We did not find a valid deck.
486 0 : RequestCloseDeck();
487 788 : return;
488 : }
489 :
490 : // Tell the tab bar to highlight the button associated
491 : // with the deck.
492 786 : mpTabBar->HighlightDeck(sNewDeckId);
493 :
494 : const DeckDescriptor* pDescriptor =
495 786 : ResourceManager::Instance().GetDeckDescriptor(sNewDeckId);
496 :
497 786 : if (pDescriptor)
498 : {
499 : SwitchToDeck(
500 : *pDescriptor,
501 786 : maCurrentContext);
502 786 : }
503 : }
504 : }
505 :
506 :
507 :
508 :
509 0 : void SidebarController::OpenThenSwitchToDeck (
510 : const ::rtl::OUString& rsDeckId)
511 : {
512 0 : RequestOpenDeck();
513 0 : SwitchToDeck(rsDeckId);
514 0 : mpTabBar->Invalidate();
515 0 : }
516 :
517 4700 : void SidebarController::SwitchToDeck (
518 : const ::rtl::OUString& rsDeckId)
519 : {
520 9400 : if ( ! msCurrentDeckId.equals(rsDeckId)
521 4700 : || ! mbIsDeckOpen
522 4700 : || mnRequestedForceFlags!=SwitchFlag_NoForce)
523 : {
524 4700 : const DeckDescriptor* pDeckDescriptor = ResourceManager::Instance().GetDeckDescriptor(rsDeckId);
525 4700 : if (pDeckDescriptor != NULL)
526 4700 : SwitchToDeck(*pDeckDescriptor, maCurrentContext);
527 : }
528 4700 : }
529 :
530 10186 : void SidebarController::SwitchToDeck (
531 : const DeckDescriptor& rDeckDescriptor,
532 : const Context& rContext)
533 : {
534 10186 : maFocusManager.Clear();
535 :
536 10186 : const bool bForceNewDeck ((mnRequestedForceFlags&SwitchFlag_ForceNewDeck)!=0);
537 10186 : const bool bForceNewPanels ((mnRequestedForceFlags&SwitchFlag_ForceNewPanels)!=0);
538 10186 : mnRequestedForceFlags = SwitchFlag_NoForce;
539 :
540 20372 : if ( ! msCurrentDeckId.equals(rDeckDescriptor.msId)
541 10186 : || bForceNewDeck)
542 : {
543 : // When the deck changes then destroy the deck and all panels
544 : // and create everything new.
545 2 : if (mpCurrentDeck)
546 : {
547 2 : mpCurrentDeck->Dispose();
548 2 : mpCurrentDeck.reset();
549 : }
550 :
551 2 : msCurrentDeckId = rDeckDescriptor.msId;
552 : }
553 10186 : mpTabBar->HighlightDeck(msCurrentDeckId);
554 :
555 : // Determine the panels to display in the deck.
556 10186 : ResourceManager::PanelContextDescriptorContainer aPanelContextDescriptors;
557 10186 : ResourceManager::Instance().GetMatchingPanels(
558 : aPanelContextDescriptors,
559 : rContext,
560 : rDeckDescriptor.msId,
561 20372 : mxFrame);
562 :
563 10186 : if (aPanelContextDescriptors.empty())
564 : {
565 : // There are no panels to be displayed in the current context.
566 4700 : if (EnumContext::GetContextEnum(rContext.msContext) != EnumContext::Context_Empty)
567 : {
568 : // Switch to the "empty" context and try again.
569 : SwitchToDeck(
570 : rDeckDescriptor,
571 : Context(
572 : rContext.msApplication,
573 4700 : EnumContext::GetContextName(EnumContext::Context_Empty)));
574 4700 : return;
575 : }
576 : else
577 : {
578 : // This is already the "empty" context. Looks like we have
579 : // to live with an empty deck.
580 : }
581 : }
582 :
583 : // Provide a configuration and Deck object.
584 5486 : if ( ! mpCurrentDeck)
585 : {
586 : mpCurrentDeck.reset(
587 : new Deck(
588 : rDeckDescriptor,
589 : mpParentWindow,
590 4702 : ::boost::bind(&SidebarController::RequestCloseDeck, this)));
591 4702 : msCurrentDeckTitle = rDeckDescriptor.msTitle;
592 :
593 : }
594 5486 : if ( ! mpCurrentDeck)
595 0 : return;
596 :
597 : #ifdef DEBUG
598 : // Show the context name in the deck title bar.
599 : DeckTitleBar* pDebugTitleBar = mpCurrentDeck->GetTitleBar();
600 : if (pDebugTitleBar != NULL)
601 : pDebugTitleBar->SetTitle(rDeckDescriptor.msTitle + " (" + maCurrentContext.msContext + ")");
602 : #endif
603 :
604 : // Update the panel list.
605 5486 : const sal_Int32 nNewPanelCount (aPanelContextDescriptors.size());
606 10972 : SharedPanelContainer aNewPanels;
607 5486 : const SharedPanelContainer& rCurrentPanels (mpCurrentDeck->GetPanels());
608 5486 : aNewPanels.resize(nNewPanelCount);
609 5486 : sal_Int32 nWriteIndex (0);
610 5486 : bool bHasPanelSetChanged (false);
611 12488 : for (sal_Int32 nReadIndex=0; nReadIndex<nNewPanelCount; ++nReadIndex)
612 : {
613 : const ResourceManager::PanelContextDescriptor& rPanelContexDescriptor (
614 7002 : aPanelContextDescriptors[nReadIndex]);
615 :
616 : // Determine if the panel can be displayed.
617 7002 : const bool bIsPanelVisible (!mbIsDocumentReadOnly || rPanelContexDescriptor.mbShowForReadOnlyDocuments);
618 7002 : if ( ! bIsPanelVisible)
619 2 : continue;
620 :
621 : // Find the corresponding panel among the currently active
622 : // panels.
623 7000 : SharedPanelContainer::const_iterator iPanel;
624 7000 : if (bForceNewPanels)
625 : {
626 : // All panels have to be created in any case. There is no
627 : // point in searching already existing panels.
628 0 : iPanel = rCurrentPanels.end();
629 : }
630 : else
631 : {
632 : iPanel = ::std::find_if(
633 : rCurrentPanels.begin(),
634 : rCurrentPanels.end(),
635 7000 : ::boost::bind(&Panel::HasIdPredicate, _1, ::boost::cref(rPanelContexDescriptor.msId)));
636 : }
637 7000 : if (iPanel != rCurrentPanels.end())
638 : {
639 : // Panel already exists in current deck. Reuse it.
640 50 : aNewPanels[nWriteIndex] = *iPanel;
641 50 : aNewPanels[nWriteIndex]->SetExpanded(rPanelContexDescriptor.mbIsInitiallyVisible);
642 : }
643 : else
644 : {
645 : // Panel does not yet exist or creation of new panels is forced.
646 : // Create it.
647 13900 : aNewPanels[nWriteIndex] = CreatePanel(
648 : rPanelContexDescriptor.msId,
649 : mpCurrentDeck->GetPanelParentWindow(),
650 : rPanelContexDescriptor.mbIsInitiallyVisible,
651 6950 : rContext);
652 6950 : bHasPanelSetChanged = true;
653 : }
654 7000 : if (aNewPanels[nWriteIndex] != 0)
655 : {
656 : // Depending on the context we have to change the command
657 : // for the "more options" dialog.
658 5972 : PanelTitleBar* pTitleBar = aNewPanels[nWriteIndex]->GetTitleBar();
659 5972 : if (pTitleBar != NULL)
660 : {
661 : pTitleBar->SetMoreOptionsCommand(
662 : rPanelContexDescriptor.msMenuCommand,
663 5972 : mxFrame);
664 : }
665 :
666 5972 : ++nWriteIndex;
667 : }
668 :
669 : }
670 5486 : aNewPanels.resize(nWriteIndex);
671 :
672 : // Activate the deck and the new set of panels.
673 5486 : mpCurrentDeck->setPosSizePixel(
674 : 0,
675 : 0,
676 16458 : mpParentWindow->GetSizePixel().Width()-TabBar::GetDefaultWidth() * mpTabBar->GetDPIScaleFactor(),
677 21944 : mpParentWindow->GetSizePixel().Height());
678 :
679 5486 : mpCurrentDeck->SetPanels(aNewPanels);
680 5486 : mpCurrentDeck->Show();
681 :
682 5486 : mpParentWindow->SetText(rDeckDescriptor.msTitle);
683 :
684 5486 : if (bHasPanelSetChanged)
685 5466 : NotifyResize();
686 :
687 : // Tell the focus manager about the new panels and tab bar
688 : // buttons.
689 5486 : maFocusManager.SetDeckTitle(mpCurrentDeck->GetTitleBar());
690 5486 : maFocusManager.SetPanels(aNewPanels);
691 5486 : mpTabBar->UpdateFocusManager(maFocusManager);
692 10972 : UpdateTitleBarIcons();
693 : }
694 :
695 :
696 :
697 :
698 6950 : SharedPanel SidebarController::CreatePanel (
699 : const OUString& rsPanelId,
700 : vcl::Window* pParentWindow,
701 : const bool bIsInitiallyExpanded,
702 : const Context& rContext)
703 : {
704 6950 : const PanelDescriptor* pPanelDescriptor = ResourceManager::Instance().GetPanelDescriptor(rsPanelId);
705 6950 : if (pPanelDescriptor == NULL)
706 0 : return SharedPanel();
707 :
708 : // Create the panel which is the parent window of the UIElement.
709 : SharedPanel pPanel (new Panel(
710 : *pPanelDescriptor,
711 : pParentWindow,
712 : bIsInitiallyExpanded,
713 : ::boost::bind(&Deck::RequestLayout, mpCurrentDeck.get()),
714 6950 : ::boost::bind(&SidebarController::GetCurrentContext, this)));
715 :
716 : // Create the XUIElement.
717 : Reference<ui::XUIElement> xUIElement (CreateUIElement(
718 13900 : pPanel->GetComponentInterface(),
719 : pPanelDescriptor->msImplementationURL,
720 : pPanelDescriptor->mbWantsCanvas,
721 27800 : rContext));
722 6950 : if (xUIElement.is())
723 : {
724 : // Initialize the panel and add it to the active deck.
725 5922 : pPanel->SetUIElement(xUIElement);
726 : }
727 : else
728 : {
729 1028 : pPanel.reset();
730 : }
731 :
732 13900 : return pPanel;
733 : }
734 :
735 :
736 :
737 :
738 6950 : Reference<ui::XUIElement> SidebarController::CreateUIElement (
739 : const Reference<awt::XWindowPeer>& rxWindow,
740 : const ::rtl::OUString& rsImplementationURL,
741 : const bool bWantsCanvas,
742 : const Context& rContext)
743 : {
744 : try
745 : {
746 6950 : const Reference<XComponentContext> xComponentContext (::comphelper::getProcessComponentContext() );
747 : const Reference<ui::XUIElementFactory> xUIElementFactory =
748 13900 : ui::theUIElementFactoryManager::get( xComponentContext );
749 :
750 : // Create the XUIElement.
751 13900 : ::comphelper::NamedValueCollection aCreationArguments;
752 6950 : aCreationArguments.put("Frame", makeAny(mxFrame));
753 6950 : aCreationArguments.put("ParentWindow", makeAny(rxWindow));
754 6950 : SfxDockingWindow* pSfxDockingWindow = dynamic_cast<SfxDockingWindow*>(mpParentWindow);
755 6950 : if (pSfxDockingWindow != NULL)
756 6950 : aCreationArguments.put("SfxBindings", makeAny(sal_uInt64(&pSfxDockingWindow->GetBindings())));
757 6950 : aCreationArguments.put("Theme", Theme::GetPropertySet());
758 6950 : aCreationArguments.put("Sidebar", makeAny(Reference<ui::XSidebar>(static_cast<ui::XSidebar*>(this))));
759 6950 : if (bWantsCanvas)
760 : {
761 0 : Reference<rendering::XSpriteCanvas> xCanvas (VCLUnoHelper::GetWindow(rxWindow)->GetSpriteCanvas());
762 0 : aCreationArguments.put("Canvas", makeAny(xCanvas));
763 : }
764 6950 : aCreationArguments.put("ApplicationName", makeAny(rContext.msApplication));
765 6950 : aCreationArguments.put("ContextName", makeAny(rContext.msContext));
766 :
767 : Reference<ui::XUIElement> xUIElement(
768 6950 : xUIElementFactory->createUIElement(
769 : rsImplementationURL,
770 6950 : Sequence<beans::PropertyValue>(aCreationArguments.getPropertyValues())),
771 12872 : UNO_QUERY_THROW);
772 :
773 12872 : return xUIElement;
774 : }
775 1028 : catch(const Exception& rException)
776 : {
777 : SAL_WARN("sfx.sidebar", "Cannot create panel: " << rException.Message);
778 1028 : return NULL;
779 : }
780 : }
781 :
782 :
783 :
784 :
785 138904 : IMPL_LINK(SidebarController, WindowEventHandler, VclWindowEvent*, pEvent)
786 : {
787 69452 : if (pEvent==NULL)
788 0 : return sal_False;
789 :
790 69452 : if (pEvent->GetWindow() == mpParentWindow)
791 : {
792 49082 : switch (pEvent->GetId())
793 : {
794 : case VCLEVENT_WINDOW_SHOW:
795 : case VCLEVENT_WINDOW_RESIZE:
796 18724 : NotifyResize();
797 18724 : break;
798 :
799 : case VCLEVENT_WINDOW_DATACHANGED:
800 : // Force an update of deck and tab bar to reflect
801 : // changes in theme (high contrast mode).
802 8 : Theme::HandleDataChange();
803 8 : UpdateTitleBarIcons();
804 8 : mpParentWindow->Invalidate();
805 8 : mnRequestedForceFlags |= SwitchFlag_ForceNewDeck | SwitchFlag_ForceNewPanels;
806 8 : maAsynchronousDeckSwitch.CancelRequest();
807 8 : maContextChangeUpdate.RequestCall();
808 8 : break;
809 :
810 : case SFX_HINT_DYING:
811 0 : dispose();
812 0 : break;
813 :
814 : case VCLEVENT_WINDOW_PAINT:
815 : OSL_TRACE("Paint");
816 0 : break;
817 :
818 : default:
819 30350 : break;
820 : }
821 : }
822 20370 : else if (pEvent->GetWindow()==mpSplitWindow && mpSplitWindow!=NULL)
823 : {
824 20370 : switch (pEvent->GetId())
825 : {
826 : case VCLEVENT_WINDOW_MOUSEBUTTONDOWN:
827 0 : mnWidthOnSplitterButtonDown = mpParentWindow->GetSizePixel().Width();
828 0 : break;
829 :
830 : case VCLEVENT_WINDOW_MOUSEBUTTONUP:
831 : {
832 0 : ProcessNewWidth(mpParentWindow->GetSizePixel().Width());
833 0 : mnWidthOnSplitterButtonDown = 0;
834 0 : break;
835 : }
836 :
837 : case SFX_HINT_DYING:
838 0 : dispose();
839 0 : break;
840 : }
841 : }
842 :
843 69452 : return sal_True;
844 : }
845 :
846 :
847 :
848 :
849 0 : void SidebarController::ShowPopupMenu (
850 : const Rectangle& rButtonBox,
851 : const ::std::vector<TabBar::DeckMenuData>& rMenuData) const
852 : {
853 0 : ::boost::shared_ptr<PopupMenu> pMenu = CreatePopupMenu(rMenuData);
854 0 : pMenu->SetSelectHdl(LINK(const_cast<SidebarController*>(this), SidebarController, OnMenuItemSelected));
855 :
856 : // pass toolbox button rect so the menu can stay open on button up
857 0 : Rectangle aBox (rButtonBox);
858 0 : aBox.Move(mpTabBar->GetPosPixel().X(), 0);
859 0 : pMenu->Execute(mpParentWindow, aBox, POPUPMENU_EXECUTE_DOWN);
860 0 : }
861 :
862 :
863 :
864 :
865 0 : ::boost::shared_ptr<PopupMenu> SidebarController::CreatePopupMenu (
866 : const ::std::vector<TabBar::DeckMenuData>& rMenuData) const
867 : {
868 : // Create the top level popup menu.
869 0 : ::boost::shared_ptr<PopupMenu> pMenu (new PopupMenu());
870 0 : FloatingWindow* pMenuWindow = dynamic_cast<FloatingWindow*>(pMenu->GetWindow());
871 0 : if (pMenuWindow != NULL)
872 : {
873 0 : pMenuWindow->SetPopupModeFlags(pMenuWindow->GetPopupModeFlags() | FLOATWIN_POPUPMODE_NOMOUSEUPCLOSE);
874 : }
875 :
876 : // Create sub menu for customization (hiding of deck tabs.)
877 0 : PopupMenu* pCustomizationMenu = new PopupMenu();
878 :
879 0 : SidebarResource aLocalResource;
880 :
881 : // Add one entry for every tool panel element to individually make
882 : // them visible or hide them.
883 0 : sal_Int32 nIndex (0);
884 0 : for(::std::vector<TabBar::DeckMenuData>::const_iterator
885 0 : iItem(rMenuData.begin()),
886 0 : iEnd(rMenuData.end());
887 : iItem!=iEnd;
888 : ++iItem,++nIndex)
889 : {
890 0 : const sal_Int32 nMenuIndex (nIndex+MID_FIRST_PANEL);
891 0 : pMenu->InsertItem(nMenuIndex, iItem->msDisplayName, MenuItemBits::RADIOCHECK);
892 0 : pMenu->CheckItem(nMenuIndex, iItem->mbIsCurrentDeck ? sal_True : sal_False);
893 0 : pMenu->EnableItem(nMenuIndex, (iItem->mbIsEnabled&&iItem->mbIsActive) ? sal_True : sal_False);
894 :
895 0 : const sal_Int32 nSubMenuIndex (nIndex+MID_FIRST_HIDE);
896 0 : if (iItem->mbIsCurrentDeck)
897 : {
898 : // Don't allow the currently visible deck to be disabled.
899 0 : pCustomizationMenu->InsertItem(nSubMenuIndex, iItem->msDisplayName, MenuItemBits::RADIOCHECK);
900 0 : pCustomizationMenu->CheckItem(nSubMenuIndex, true);
901 : }
902 : else
903 : {
904 0 : pCustomizationMenu->InsertItem(nSubMenuIndex, iItem->msDisplayName, MenuItemBits::CHECKABLE);
905 0 : pCustomizationMenu->CheckItem(nSubMenuIndex, iItem->mbIsActive ? sal_True : sal_False);
906 : }
907 : }
908 :
909 0 : pMenu->InsertSeparator();
910 :
911 : // Add entry for docking or un-docking the tool panel.
912 0 : if (mpParentWindow->IsFloatingMode())
913 0 : pMenu->InsertItem(MID_LOCK_TASK_PANEL, SFX2_RESSTR(STR_SFX_DOCK));
914 : else
915 0 : pMenu->InsertItem(MID_UNLOCK_TASK_PANEL, SFX2_RESSTR(STR_SFX_UNDOCK));
916 :
917 0 : pCustomizationMenu->InsertSeparator();
918 0 : pCustomizationMenu->InsertItem(MID_RESTORE_DEFAULT, SFX2_RESSTR(STRING_RESTORE));
919 :
920 0 : pMenu->InsertItem(MID_CUSTOMIZATION, SFX2_RESSTR(STRING_CUSTOMIZATION));
921 0 : pMenu->SetPopupMenu(MID_CUSTOMIZATION, pCustomizationMenu);
922 :
923 0 : pMenu->RemoveDisabledEntries(false, false);
924 :
925 0 : return pMenu;
926 : }
927 :
928 :
929 :
930 :
931 0 : IMPL_LINK(SidebarController, OnMenuItemSelected, Menu*, pMenu)
932 : {
933 0 : if (pMenu == NULL)
934 : {
935 : OSL_ENSURE(pMenu!=NULL, "sfx2::sidebar::SidebarController::OnMenuItemSelected: illegal menu!");
936 0 : return 0;
937 : }
938 :
939 0 : pMenu->Deactivate();
940 0 : const sal_Int32 nIndex (pMenu->GetCurItemId());
941 0 : switch (nIndex)
942 : {
943 : case MID_UNLOCK_TASK_PANEL:
944 0 : mpParentWindow->SetFloatingMode(true);
945 0 : break;
946 :
947 : case MID_LOCK_TASK_PANEL:
948 0 : mpParentWindow->SetFloatingMode(false);
949 0 : break;
950 :
951 : case MID_RESTORE_DEFAULT:
952 0 : mpTabBar->RestoreHideFlags();
953 0 : break;
954 :
955 : default:
956 : {
957 : try
958 : {
959 0 : if (nIndex >= MID_FIRST_PANEL && nIndex<MID_FIRST_HIDE)
960 : {
961 0 : RequestOpenDeck();
962 0 : SwitchToDeck(mpTabBar->GetDeckIdForIndex(nIndex - MID_FIRST_PANEL));
963 : }
964 0 : else if (nIndex >=MID_FIRST_HIDE)
965 0 : if (pMenu->GetItemBits(nIndex) == MenuItemBits::CHECKABLE)
966 0 : mpTabBar->ToggleHideFlag(nIndex-MID_FIRST_HIDE);
967 : }
968 0 : catch (RuntimeException&)
969 : {
970 : }
971 : }
972 0 : break;
973 : }
974 :
975 0 : return 1;
976 : }
977 :
978 :
979 :
980 :
981 0 : void SidebarController::RequestCloseDeck (void)
982 : {
983 0 : mbIsDeckRequestedOpen = false;
984 0 : UpdateDeckOpenState();
985 :
986 : // remove highlight from TabBar, because Deck will be closed
987 0 : mpTabBar->RemoveDeckHighlight();
988 0 : }
989 :
990 :
991 :
992 :
993 0 : void SidebarController::RequestOpenDeck (void)
994 : {
995 0 : mbIsDeckRequestedOpen = true;
996 0 : UpdateDeckOpenState();
997 0 : }
998 :
999 :
1000 :
1001 :
1002 0 : void SidebarController::UpdateDeckOpenState (void)
1003 : {
1004 0 : if ( ! mbIsDeckRequestedOpen)
1005 : // No state requested.
1006 0 : return;
1007 :
1008 0 : sal_Int32 nTabBarDefaultWidth = TabBar::GetDefaultWidth() * mpTabBar->GetDPIScaleFactor();
1009 :
1010 : // Update (change) the open state when it either has not yet been initialized
1011 : // or when its value differs from the requested state.
1012 0 : if ( ! mbIsDeckOpen
1013 0 : || mbIsDeckOpen.get() != mbIsDeckRequestedOpen.get())
1014 : {
1015 0 : if (mbIsDeckRequestedOpen.get())
1016 : {
1017 0 : if (mnSavedSidebarWidth <= nTabBarDefaultWidth)
1018 0 : SetChildWindowWidth(SidebarChildWindow::GetDefaultWidth(mpParentWindow));
1019 : else
1020 0 : SetChildWindowWidth(mnSavedSidebarWidth);
1021 : }
1022 : else
1023 : {
1024 0 : if ( ! mpParentWindow->IsFloatingMode())
1025 0 : mnSavedSidebarWidth = SetChildWindowWidth(nTabBarDefaultWidth);
1026 0 : if (mnWidthOnSplitterButtonDown > nTabBarDefaultWidth)
1027 0 : mnSavedSidebarWidth = mnWidthOnSplitterButtonDown;
1028 0 : mpParentWindow->SetStyle(mpParentWindow->GetStyle() & ~WB_SIZEABLE);
1029 : }
1030 :
1031 0 : mbIsDeckOpen = mbIsDeckRequestedOpen.get();
1032 0 : if (mbIsDeckOpen.get() && mpCurrentDeck)
1033 0 : mpCurrentDeck->Show(mbIsDeckOpen.get());
1034 0 : NotifyResize();
1035 : }
1036 : }
1037 :
1038 :
1039 :
1040 :
1041 :
1042 :
1043 :
1044 :
1045 19492 : bool SidebarController::CanModifyChildWindowWidth (void)
1046 : {
1047 19492 : SfxSplitWindow* pSplitWindow = GetSplitWindow();
1048 19492 : if (pSplitWindow == NULL)
1049 0 : return false;
1050 :
1051 19492 : sal_uInt16 nRow (0xffff);
1052 19492 : sal_uInt16 nColumn (0xffff);
1053 19492 : if (pSplitWindow->GetWindowPos(mpParentWindow, nColumn, nRow))
1054 : {
1055 19492 : sal_uInt16 nRowCount (pSplitWindow->GetWindowCount(nColumn));
1056 19492 : return nRowCount==1;
1057 : }
1058 : else
1059 0 : return false;
1060 : }
1061 :
1062 :
1063 :
1064 :
1065 0 : sal_Int32 SidebarController::SetChildWindowWidth (const sal_Int32 nNewWidth)
1066 : {
1067 0 : SfxSplitWindow* pSplitWindow = GetSplitWindow();
1068 0 : if (pSplitWindow == NULL)
1069 0 : return 0;
1070 :
1071 0 : sal_uInt16 nRow (0xffff);
1072 0 : sal_uInt16 nColumn (0xffff);
1073 0 : pSplitWindow->GetWindowPos(mpParentWindow, nColumn, nRow);
1074 0 : const long nColumnWidth (pSplitWindow->GetLineSize(nColumn));
1075 :
1076 0 : vcl::Window* pWindow = mpParentWindow;
1077 0 : const Size aWindowSize (pWindow->GetSizePixel());
1078 :
1079 : pSplitWindow->MoveWindow(
1080 : mpParentWindow,
1081 : Size(nNewWidth, aWindowSize.Height()),
1082 : nColumn,
1083 0 : nRow);
1084 0 : static_cast<SplitWindow*>(pSplitWindow)->Split();
1085 :
1086 0 : return static_cast<sal_Int32>(nColumnWidth);
1087 : }
1088 :
1089 :
1090 :
1091 :
1092 24996 : void SidebarController::RestrictWidth (sal_Int32 nWidth)
1093 : {
1094 24996 : SfxSplitWindow* pSplitWindow = GetSplitWindow();
1095 24996 : if (pSplitWindow != NULL)
1096 : {
1097 20298 : const sal_uInt16 nId (pSplitWindow->GetItemId(mpParentWindow));
1098 20298 : const sal_uInt16 nSetId (pSplitWindow->GetSet(nId));
1099 : pSplitWindow->SetItemSizeRange(
1100 : nSetId,
1101 20298 : Range(TabBar::GetDefaultWidth() * mpTabBar->GetDPIScaleFactor() + nWidth,
1102 40596 : gnMaximumSidebarWidth * mpTabBar->GetDPIScaleFactor()));
1103 : }
1104 24996 : }
1105 :
1106 :
1107 :
1108 :
1109 68678 : SfxSplitWindow* SidebarController::GetSplitWindow (void)
1110 : {
1111 68678 : if (mpParentWindow != NULL)
1112 : {
1113 68678 : SfxSplitWindow* pSplitWindow = dynamic_cast<SfxSplitWindow*>(mpParentWindow->GetParent());
1114 68678 : if (pSplitWindow != mpSplitWindow)
1115 : {
1116 4700 : if (mpSplitWindow != NULL)
1117 0 : mpSplitWindow->RemoveEventListener(LINK(this, SidebarController, WindowEventHandler));
1118 :
1119 4700 : mpSplitWindow = pSplitWindow;
1120 :
1121 4700 : if (mpSplitWindow != NULL)
1122 4700 : mpSplitWindow->AddEventListener(LINK(this, SidebarController, WindowEventHandler));
1123 : }
1124 68678 : return mpSplitWindow;
1125 : }
1126 : else
1127 0 : return NULL;
1128 : }
1129 :
1130 :
1131 :
1132 :
1133 24190 : void SidebarController::UpdateCloseIndicator (const bool bCloseAfterDrag)
1134 : {
1135 24190 : if (mpParentWindow == NULL)
1136 24190 : return;
1137 :
1138 24190 : if (bCloseAfterDrag)
1139 : {
1140 : // Make sure that the indicator exists.
1141 4698 : if ( ! mpCloseIndicator)
1142 : {
1143 4698 : mpCloseIndicator.reset(new FixedImage(mpParentWindow));
1144 4698 : FixedImage* pFixedImage = static_cast<FixedImage*>(mpCloseIndicator.get());
1145 4698 : const Image aImage (Theme::GetImage(Theme::Image_CloseIndicator));
1146 4698 : pFixedImage->SetImage(aImage);
1147 4698 : pFixedImage->SetSizePixel(aImage.GetSizePixel());
1148 4698 : pFixedImage->SetBackground(Theme::GetWallpaper(Theme::Paint_DeckBackground));
1149 : }
1150 :
1151 : // Place and show the indicator.
1152 4698 : const Size aWindowSize (mpParentWindow->GetSizePixel());
1153 4698 : const Size aImageSize (mpCloseIndicator->GetSizePixel());
1154 4698 : mpCloseIndicator->SetPosPixel(
1155 : Point(
1156 4698 : aWindowSize.Width() - TabBar::GetDefaultWidth() * mpTabBar->GetDPIScaleFactor() - aImageSize.Width(),
1157 9396 : (aWindowSize.Height() - aImageSize.Height())/2));
1158 4698 : mpCloseIndicator->Show();
1159 : }
1160 : else
1161 : {
1162 : // Hide but don't delete the indicator.
1163 19492 : if (mpCloseIndicator)
1164 19484 : mpCloseIndicator->Hide();
1165 : }
1166 : }
1167 :
1168 :
1169 :
1170 :
1171 5494 : void SidebarController::UpdateTitleBarIcons (void)
1172 : {
1173 5494 : if ( ! mpCurrentDeck)
1174 5494 : return;
1175 :
1176 5494 : const bool bIsHighContrastModeActive (Theme::IsHighContrastMode());
1177 5494 : const ResourceManager& rResourceManager (ResourceManager::Instance());
1178 :
1179 : // Update the deck icon.
1180 5494 : const DeckDescriptor* pDeckDescriptor = rResourceManager.GetDeckDescriptor(mpCurrentDeck->GetId());
1181 5494 : if (pDeckDescriptor != NULL && mpCurrentDeck->GetTitleBar())
1182 : {
1183 : const OUString sIconURL(
1184 : bIsHighContrastModeActive
1185 : ? pDeckDescriptor->msHighContrastTitleBarIconURL
1186 5494 : : pDeckDescriptor->msTitleBarIconURL);
1187 5494 : mpCurrentDeck->GetTitleBar()->SetIcon(Tools::GetImage(sIconURL, mxFrame));
1188 : }
1189 :
1190 : // Update the panel icons.
1191 5494 : const SharedPanelContainer& rPanels (mpCurrentDeck->GetPanels());
1192 11466 : for (SharedPanelContainer::const_iterator
1193 5494 : iPanel(rPanels.begin()), iEnd(rPanels.end());
1194 : iPanel!=iEnd;
1195 : ++iPanel)
1196 : {
1197 5972 : if ( ! *iPanel)
1198 0 : continue;
1199 5972 : if ((*iPanel)->GetTitleBar() == NULL)
1200 0 : continue;
1201 5972 : const PanelDescriptor* pPanelDescriptor = rResourceManager.GetPanelDescriptor((*iPanel)->GetId());
1202 5972 : if (pPanelDescriptor == NULL)
1203 0 : continue;
1204 : const OUString sIconURL (
1205 : bIsHighContrastModeActive
1206 : ? pPanelDescriptor->msHighContrastTitleBarIconURL
1207 5972 : : pPanelDescriptor->msTitleBarIconURL);
1208 5972 : (*iPanel)->GetTitleBar()->SetIcon(Tools::GetImage(sIconURL, mxFrame));
1209 5972 : }
1210 : }
1211 :
1212 :
1213 :
1214 :
1215 0 : void SidebarController::ShowPanel (const Panel& rPanel)
1216 : {
1217 0 : if (mpCurrentDeck)
1218 0 : mpCurrentDeck->ShowPanel(rPanel);
1219 0 : }
1220 :
1221 :
1222 :
1223 :
1224 :
1225 :
1226 951 : } } // end of namespace sfx2::sidebar
1227 :
1228 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|