bump product version to 6.3.0.0.beta1
[LibreOffice.git] / sd / source / ui / sidebar / LayoutMenu.cxx
blob072f95a4ddc78de20294ead3123c250d64de7bce
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 "LayoutMenu.hxx"
22 #include <app.hrc>
23 #include <drawdoc.hxx>
24 #include <framework/FrameworkHelper.hxx>
25 #include <strings.hrc>
26 #include <glob.hxx>
27 #include <helpids.h>
28 #include <pres.hxx>
29 #include <sdmod.hxx>
31 #include <sdpage.hxx>
32 #include <sdresid.hxx>
33 #include <unokywds.hxx>
34 #include <bitmaps.hlst>
35 #include <tools/SlotStateListener.hxx>
36 #include <DrawController.hxx>
37 #include <DrawDocShell.hxx>
38 #include <DrawViewShell.hxx>
39 #include <EventMultiplexer.hxx>
40 #include <SlideSorterViewShell.hxx>
41 #include <ViewShellBase.hxx>
42 #include <sfx2/sidebar/Theme.hxx>
43 #include <sal/log.hxx>
45 #include <comphelper/processfactory.hxx>
46 #include <sfx2/app.hxx>
47 #include <sfx2/dispatch.hxx>
48 #include <sfx2/objface.hxx>
49 #include <sfx2/request.hxx>
50 #include <sfx2/viewfrm.hxx>
51 #include <svl/languageoptions.hxx>
52 #include <svl/stritem.hxx>
53 #include <svl/intitem.hxx>
54 #include <vcl/commandevent.hxx>
55 #include <vcl/image.hxx>
56 #include <vcl/floatwin.hxx>
57 #include <xmloff/autolayout.hxx>
59 #include <com/sun/star/drawing/framework/XControllerManager.hpp>
60 #include <com/sun/star/drawing/framework/XView.hpp>
61 #include <com/sun/star/drawing/framework/ResourceId.hpp>
63 #include <vector>
65 using namespace ::com::sun::star;
66 using namespace ::com::sun::star::text;
67 using namespace ::com::sun::star::uno;
68 using namespace ::com::sun::star::drawing::framework;
69 using namespace ::sd::slidesorter;
70 using ::sd::framework::FrameworkHelper;
72 namespace sd { namespace sidebar {
74 struct snewfoil_value_info
76 const char* msBmpResId;
77 const char* mpStrResId;
78 WritingMode const meWritingMode;
79 AutoLayout const maAutoLayout;
82 static const snewfoil_value_info notes[] =
84 {BMP_FOILN_01, STR_AUTOLAYOUT_NOTES, WritingMode_LR_TB,
85 AUTOLAYOUT_NOTES},
86 {"", nullptr, WritingMode_LR_TB, AUTOLAYOUT_NONE},
89 static const snewfoil_value_info handout[] =
91 {BMP_FOILH_01, STR_AUTOLAYOUT_HANDOUT1, WritingMode_LR_TB,
92 AUTOLAYOUT_HANDOUT1},
93 {BMP_FOILH_02, STR_AUTOLAYOUT_HANDOUT2, WritingMode_LR_TB,
94 AUTOLAYOUT_HANDOUT2},
95 {BMP_FOILH_03, STR_AUTOLAYOUT_HANDOUT3, WritingMode_LR_TB,
96 AUTOLAYOUT_HANDOUT3},
97 {BMP_FOILH_04, STR_AUTOLAYOUT_HANDOUT4, WritingMode_LR_TB,
98 AUTOLAYOUT_HANDOUT4},
99 {BMP_FOILH_06, STR_AUTOLAYOUT_HANDOUT6, WritingMode_LR_TB,
100 AUTOLAYOUT_HANDOUT6},
101 {BMP_FOILH_09, STR_AUTOLAYOUT_HANDOUT9, WritingMode_LR_TB,
102 AUTOLAYOUT_HANDOUT9},
103 {"", nullptr, WritingMode_LR_TB, AUTOLAYOUT_NONE},
106 static const snewfoil_value_info standard[] =
108 {BMP_LAYOUT_EMPTY, STR_AUTOLAYOUT_NONE, WritingMode_LR_TB, AUTOLAYOUT_NONE},
109 {BMP_LAYOUT_HEAD03, STR_AUTOLAYOUT_TITLE, WritingMode_LR_TB, AUTOLAYOUT_TITLE},
110 {BMP_LAYOUT_HEAD02, STR_AUTOLAYOUT_CONTENT, WritingMode_LR_TB, AUTOLAYOUT_TITLE_CONTENT},
111 {BMP_LAYOUT_HEAD02A, STR_AUTOLAYOUT_2CONTENT, WritingMode_LR_TB, AUTOLAYOUT_TITLE_2CONTENT},
112 {BMP_LAYOUT_HEAD01, STR_AUTOLAYOUT_ONLY_TITLE, WritingMode_LR_TB, AUTOLAYOUT_TITLE_ONLY},
113 {BMP_LAYOUT_TEXTONLY, STR_AUTOLAYOUT_ONLY_TEXT, WritingMode_LR_TB, AUTOLAYOUT_ONLY_TEXT},
114 {BMP_LAYOUT_HEAD03B, STR_AUTOLAYOUT_2CONTENT_CONTENT, WritingMode_LR_TB, AUTOLAYOUT_TITLE_2CONTENT_CONTENT},
115 {BMP_LAYOUT_HEAD03C, STR_AUTOLAYOUT_CONTENT_2CONTENT, WritingMode_LR_TB, AUTOLAYOUT_TITLE_CONTENT_2CONTENT},
116 {BMP_LAYOUT_HEAD03A, STR_AUTOLAYOUT_2CONTENT_OVER_CONTENT,WritingMode_LR_TB, AUTOLAYOUT_TITLE_2CONTENT_OVER_CONTENT},
117 {BMP_LAYOUT_HEAD02B, STR_AUTOLAYOUT_CONTENT_OVER_CONTENT, WritingMode_LR_TB, AUTOLAYOUT_TITLE_CONTENT_OVER_CONTENT},
118 {BMP_LAYOUT_HEAD04, STR_AUTOLAYOUT_4CONTENT, WritingMode_LR_TB, AUTOLAYOUT_TITLE_4CONTENT},
119 {BMP_LAYOUT_HEAD06, STR_AUTOLAYOUT_6CONTENT, WritingMode_LR_TB, AUTOLAYOUT_TITLE_6CONTENT},
121 // vertical
122 {BMP_LAYOUT_VERTICAL02, STR_AL_VERT_TITLE_TEXT_CHART, WritingMode_TB_RL, AUTOLAYOUT_VTITLE_VCONTENT_OVER_VCONTENT},
123 {BMP_LAYOUT_VERTICAL01, STR_AL_VERT_TITLE_VERT_OUTLINE, WritingMode_TB_RL, AUTOLAYOUT_VTITLE_VCONTENT},
124 {BMP_LAYOUT_HEAD02, STR_AL_TITLE_VERT_OUTLINE, WritingMode_TB_RL, AUTOLAYOUT_TITLE_VCONTENT},
125 {BMP_LAYOUT_HEAD02A, STR_AL_TITLE_VERT_OUTLINE_CLIPART, WritingMode_TB_RL, AUTOLAYOUT_TITLE_2VTEXT},
126 {"", nullptr, WritingMode_LR_TB, AUTOLAYOUT_NONE}
129 LayoutMenu::LayoutMenu (
130 vcl::Window* pParent,
131 ViewShellBase& rViewShellBase,
132 const css::uno::Reference<css::ui::XSidebar>& rxSidebar)
133 : ValueSet (pParent, WB_ITEMBORDER),
134 DragSourceHelper(this),
135 DropTargetHelper(this),
136 mrBase(rViewShellBase),
137 mbIsMainViewChangePending(false),
138 mxSidebar(rxSidebar),
139 mbIsDisposed(false)
141 implConstruct( *mrBase.GetDocument()->GetDocSh() );
142 SAL_INFO("sd.ui", "created LayoutMenu at " << this);
144 SetStyle(GetStyle() | WB_ITEMBORDER | WB_FLATVALUESET | WB_TABSTOP);
146 SetBackground(sfx2::sidebar::Theme::GetWallpaper(sfx2::sidebar::Theme::Paint_PanelBackground));
147 SetColor(sfx2::sidebar::Theme::GetColor(sfx2::sidebar::Theme::Paint_PanelBackground));
149 #ifdef DEBUG
150 SetText(OUString("sd:LayoutMenu"));
151 #endif
154 void LayoutMenu::implConstruct( DrawDocShell& rDocumentShell )
156 OSL_ENSURE( mrBase.GetDocument()->GetDocSh() == &rDocumentShell,
157 "LayoutMenu::implConstruct: hmm?" );
158 // if this fires, then my assumption that the rDocumentShell parameter to our first ctor is superfluous ...
159 (void) rDocumentShell;
161 SetStyle (
162 ( GetStyle() & ~(WB_ITEMBORDER) )
163 | WB_TABSTOP
164 | WB_MENUSTYLEVALUESET
165 | WB_NO_DIRECTSELECT
167 SetExtraSpacing(2);
168 SetSelectHdl (LINK(this, LayoutMenu, ClickHandler));
169 InvalidateContent();
171 Link<::sd::tools::EventMultiplexerEvent&,void> aEventListenerLink (LINK(this,LayoutMenu,EventMultiplexerListener));
172 mrBase.GetEventMultiplexer()->AddEventListener(aEventListenerLink);
174 Window::SetHelpId(HID_SD_TASK_PANE_PREVIEW_LAYOUTS);
175 SetAccessibleName(SdResId(STR_TASKPANEL_LAYOUT_MENU_TITLE));
177 Link<const OUString&,void> aStateChangeLink (LINK(this,LayoutMenu,StateChangeHandler));
178 mxListener = new ::sd::tools::SlotStateListener(
179 aStateChangeLink,
180 Reference<frame::XDispatchProvider>(mrBase.GetController()->getFrame(), UNO_QUERY),
181 ".uno:VerticalTextState");
183 SetSizePixel(GetParent()->GetSizePixel());
184 Link<VclWindowEvent&,void> aWindowEventHandlerLink (LINK(this,LayoutMenu,WindowEventHandler));
185 GetParent()->AddEventListener(aWindowEventHandlerLink);
188 LayoutMenu::~LayoutMenu()
190 disposeOnce();
193 void LayoutMenu::dispose()
195 SAL_INFO("sd.ui", "destroying LayoutMenu at " << this);
196 Dispose();
197 DragSourceHelper::dispose();
198 DropTargetHelper::dispose();
199 ValueSet::dispose();
202 void LayoutMenu::Dispose()
204 if (mbIsDisposed)
205 return;
207 SAL_INFO("sd.ui", "disposing LayoutMenu at " << this);
209 mbIsDisposed = true;
211 Reference<lang::XComponent> xComponent (mxListener, UNO_QUERY);
212 if (xComponent.is())
213 xComponent->dispose();
215 Clear();
216 Link<tools::EventMultiplexerEvent&,void> aLink (LINK(this,LayoutMenu,EventMultiplexerListener));
217 mrBase.GetEventMultiplexer()->RemoveEventListener (aLink);
219 Link<VclWindowEvent&,void> aWindowEventHandlerLink (LINK(this,LayoutMenu,WindowEventHandler));
220 GetParent()->RemoveEventListener(aWindowEventHandlerLink);
223 AutoLayout LayoutMenu::GetSelectedAutoLayout()
225 AutoLayout aResult = AUTOLAYOUT_NONE;
227 if ( ! IsNoSelection() && GetSelectedItemId()!=0)
229 AutoLayout* pLayout = static_cast<AutoLayout*>(GetItemData(GetSelectedItemId()));
230 if (pLayout != nullptr)
231 aResult = *pLayout;
234 return aResult;
237 ui::LayoutSize LayoutMenu::GetHeightForWidth (const sal_Int32 nWidth)
239 sal_Int32 nPreferredHeight = 200;
240 if (GetItemCount()>0)
242 Image aImage = GetItemImage(GetItemId(0));
243 Size aItemSize = CalcItemSizePixel (aImage.GetSizePixel());
244 if (nWidth>0 && aItemSize.Width()>0)
246 aItemSize.AdjustWidth(8 );
247 aItemSize.AdjustHeight(8 );
248 int nColumnCount = nWidth / aItemSize.Width();
249 if (nColumnCount <= 0)
250 nColumnCount = 1;
251 else if (nColumnCount > 4)
252 nColumnCount = 4;
253 int nRowCount = (GetItemCount() + nColumnCount-1) / nColumnCount;
254 nPreferredHeight = nRowCount * aItemSize.Height();
257 return ui::LayoutSize(nPreferredHeight,nPreferredHeight,nPreferredHeight);
260 void LayoutMenu::Resize()
262 Size aWindowSize = GetOutputSizePixel();
263 if (IsVisible() && aWindowSize.Width() > 0)
265 // Calculate the number of rows and columns.
266 if (GetItemCount() > 0)
268 Image aImage = GetItemImage(GetItemId(0));
269 Size aItemSize = CalcItemSizePixel (
270 aImage.GetSizePixel());
271 aItemSize.AdjustWidth(8 );
272 aItemSize.AdjustHeight(8 );
273 int nColumnCount = aWindowSize.Width() / aItemSize.Width();
274 if (nColumnCount < 1)
275 nColumnCount = 1;
276 else if (nColumnCount > 4)
277 nColumnCount = 4;
279 int nRowCount = CalculateRowCount (aItemSize, nColumnCount);
281 SetColCount (static_cast<sal_uInt16>(nColumnCount));
282 SetLineCount (static_cast<sal_uInt16>(nRowCount));
286 ValueSet::Resize ();
289 void LayoutMenu::MouseButtonDown (const MouseEvent& rEvent)
291 // As a preparation for the context menu the item under the mouse is
292 // selected.
293 if (rEvent.IsRight())
295 ReleaseMouse();
296 sal_uInt16 nIndex = GetItemId (rEvent.GetPosPixel());
297 if (nIndex > 0)
298 SelectItem(nIndex);
301 ValueSet::MouseButtonDown (rEvent);
304 void LayoutMenu::InsertPageWithLayout (AutoLayout aLayout)
306 ViewShell* pViewShell = mrBase.GetMainViewShell().get();
307 if (pViewShell == nullptr)
308 return;
310 SfxViewFrame* pViewFrame = mrBase.GetViewFrame();
311 if (pViewFrame == nullptr)
312 return;
314 SfxDispatcher* pDispatcher = pViewFrame->GetDispatcher();
315 if (pDispatcher == nullptr)
316 return;
318 // Call SID_INSERTPAGE with the right arguments. This is because
319 // the popup menu can not call this slot with arguments directly.
320 SfxRequest aRequest (CreateRequest(SID_INSERTPAGE, aLayout));
321 if (aRequest.GetArgs() != nullptr)
323 pDispatcher->Execute(
324 SID_INSERTPAGE,
325 SfxCallMode::ASYNCHRON | SfxCallMode::RECORD,
326 *aRequest.GetArgs());
328 UpdateSelection();
331 void LayoutMenu::InvalidateContent()
333 // Throw away the current set and fill the menu anew according to the
334 // current settings (this includes the support for vertical writing.)
335 Fill();
337 if (mxSidebar.is())
338 mxSidebar->requestLayout();
340 // set selection inside the control during Impress start up
341 UpdateSelection();
344 int LayoutMenu::CalculateRowCount (const Size&, int nColumnCount)
346 int nRowCount = 0;
348 if (GetItemCount() > 0 && nColumnCount > 0)
350 nRowCount = (GetItemCount() + nColumnCount - 1) / nColumnCount;
351 // nRowCount = GetOutputSizePixel().Height() / rItemSize.Height();
352 if (nRowCount < 1)
353 nRowCount = 1;
356 return nRowCount;
359 IMPL_LINK_NOARG(LayoutMenu, ClickHandler, ValueSet*, void)
361 AssignLayoutToSelectedSlides( GetSelectedAutoLayout() );
364 /** The specified layout is assigned to the current page of the view shell
365 in the center pane.
367 void LayoutMenu::AssignLayoutToSelectedSlides (AutoLayout aLayout)
369 using namespace ::sd::slidesorter;
370 using namespace ::sd::slidesorter::controller;
374 // The view shell in the center pane has to be present.
375 ViewShell* pMainViewShell = mrBase.GetMainViewShell().get();
376 if (pMainViewShell == nullptr)
377 break;
379 // Determine if the current view is in an invalid master page mode.
380 // The handout view is always in master page mode and therefore not
381 // invalid.
382 bool bMasterPageMode (false);
383 switch (pMainViewShell->GetShellType())
385 case ViewShell::ST_NOTES:
386 case ViewShell::ST_IMPRESS:
388 DrawViewShell* pDrawViewShell = static_cast<DrawViewShell*>(pMainViewShell);
389 if (pDrawViewShell->GetEditMode() == EditMode::MasterPage)
390 bMasterPageMode = true;
391 break;
393 default:
394 break;
396 if (bMasterPageMode)
397 break;
399 // Get a list of all selected slides and call the SID_MODIFYPAGE
400 // slot for all of them.
401 ::sd::slidesorter::SharedPageSelection pPageSelection;
403 // Get a list of selected pages.
404 // First we try to obtain this list from a slide sorter. This is
405 // possible only some of the view shells in the center pane. When
406 // no valid slide sorter is available then ask the main view shell
407 // for its current page.
408 SlideSorterViewShell* pSlideSorter = nullptr;
409 switch (pMainViewShell->GetShellType())
411 case ViewShell::ST_IMPRESS:
412 case ViewShell::ST_NOTES:
413 case ViewShell::ST_SLIDE_SORTER:
414 pSlideSorter = SlideSorterViewShell::GetSlideSorter(mrBase);
415 break;
416 default:
417 break;
419 if (pSlideSorter != nullptr)
421 // There is a slide sorter visible so get the list of selected pages from it.
422 pPageSelection = pSlideSorter->GetPageSelection();
425 if( (pSlideSorter == nullptr) || (pPageSelection.get() == nullptr) || pPageSelection->empty() )
427 // No valid slide sorter available. Ask the main view shell for
428 // its current page.
429 pPageSelection.reset(new ::sd::slidesorter::SlideSorterViewShell::PageSelection);
430 pPageSelection->push_back(pMainViewShell->GetActualPage());
433 if (pPageSelection->empty())
434 break;
436 for (const auto& rpPage : *pPageSelection)
438 if (rpPage == nullptr)
439 continue;
441 // Call the SID_ASSIGN_LAYOUT slot with all the necessary parameters.
442 SfxRequest aRequest (mrBase.GetViewFrame(), SID_ASSIGN_LAYOUT);
443 aRequest.AppendItem(SfxUInt32Item (ID_VAL_WHATPAGE, (rpPage->GetPageNum()-1)/2));
444 aRequest.AppendItem(SfxUInt32Item (ID_VAL_WHATLAYOUT, aLayout));
445 pMainViewShell->ExecuteSlot (aRequest, false);
448 while(false);
451 SfxRequest LayoutMenu::CreateRequest (
452 sal_uInt16 nSlotId,
453 AutoLayout aLayout)
455 SfxRequest aRequest (mrBase.GetViewFrame(), nSlotId);
459 SdrLayerAdmin& rLayerAdmin (mrBase.GetDocument()->GetLayerAdmin());
460 SdrLayerID aBackground (rLayerAdmin.GetLayerID(sUNO_LayerName_background));
461 SdrLayerID aBackgroundObject (rLayerAdmin.GetLayerID(sUNO_LayerName_background_objects));
462 ViewShell* pViewShell = mrBase.GetMainViewShell().get();
463 if (pViewShell == nullptr)
464 break;
465 SdPage* pPage = pViewShell->GetActualPage();
466 if (pPage == nullptr)
467 break;
469 SdrLayerIDSet aVisibleLayers (pPage->TRG_GetMasterPageVisibleLayers());
471 aRequest.AppendItem(
472 SfxStringItem (ID_VAL_PAGENAME, OUString()));//pPage->GetName()));
473 aRequest.AppendItem(SfxUInt32Item (ID_VAL_WHATLAYOUT, aLayout));
474 aRequest.AppendItem(
475 SfxBoolItem(ID_VAL_ISPAGEBACK, aVisibleLayers.IsSet(aBackground)));
476 aRequest.AppendItem(
477 SfxBoolItem(
478 ID_VAL_ISPAGEOBJ,
479 aVisibleLayers.IsSet(aBackgroundObject)));
481 while (false);
483 return aRequest;
486 void LayoutMenu::Fill()
488 SvtLanguageOptions aLanguageOptions;
489 bool bVertical = aLanguageOptions.IsVerticalTextEnabled();
490 SdDrawDocument* pDocument = mrBase.GetDocument();
491 bool bRightToLeft = (pDocument!=nullptr
492 && pDocument->GetDefaultWritingMode() == WritingMode_RL_TB);
494 // Get URL of the view in the center pane.
495 OUString sCenterPaneViewName;
498 Reference<XControllerManager> xControllerManager (
499 Reference<XWeak>(&mrBase.GetDrawController()), UNO_QUERY_THROW);
500 Reference<XResourceId> xPaneId (ResourceId::create(
501 ::comphelper::getProcessComponentContext(),
502 FrameworkHelper::msCenterPaneURL));
503 Reference<XView> xView (FrameworkHelper::Instance(mrBase)->GetView(xPaneId));
504 if (xView.is())
505 sCenterPaneViewName = xView->getResourceId()->getResourceURL();
507 catch (RuntimeException&)
510 const snewfoil_value_info* pInfo = nullptr;
511 if (sCenterPaneViewName == framework::FrameworkHelper::msNotesViewURL)
513 pInfo = notes;
515 else if (sCenterPaneViewName == framework::FrameworkHelper::msHandoutViewURL)
517 pInfo = handout;
519 else if (sCenterPaneViewName == framework::FrameworkHelper::msImpressViewURL
520 || sCenterPaneViewName == framework::FrameworkHelper::msSlideSorterURL)
522 pInfo = standard;
524 else
526 pInfo = nullptr;
529 Clear();
530 for (sal_uInt16 i=1; pInfo!=nullptr && pInfo->mpStrResId != nullptr; i++, pInfo++)
532 if ((WritingMode_TB_RL != pInfo->meWritingMode) || bVertical)
534 BitmapEx aBmp(OUString::createFromAscii(pInfo->msBmpResId));
536 if (bRightToLeft && (WritingMode_TB_RL != pInfo->meWritingMode))
537 aBmp.Mirror (BmpMirrorFlags::Horizontal);
539 InsertItem(i, Image(aBmp), SdResId(pInfo->mpStrResId));
540 SetItemData (i, new AutoLayout(pInfo->maAutoLayout));
545 void LayoutMenu::Clear()
547 for (size_t nId=1; nId<=GetItemCount(); nId++)
548 delete static_cast<AutoLayout*>(GetItemData(nId));
549 ValueSet::Clear();
552 void LayoutMenu::StartDrag (sal_Int8 , const Point& )
556 sal_Int8 LayoutMenu::AcceptDrop (const AcceptDropEvent& )
558 return 0;
561 sal_Int8 LayoutMenu::ExecuteDrop (const ExecuteDropEvent& )
563 return 0;
566 void LayoutMenu::Command (const CommandEvent& rEvent)
568 switch (rEvent.GetCommand())
570 case CommandEventId::ContextMenu:
571 if ( ! SD_MOD()->GetWaterCan())
573 // Determine the position where to show the menu.
574 Point aMenuPosition;
575 if (rEvent.IsMouseEvent())
577 if (GetItemId(rEvent.GetMousePosPixel()) <= 0)
578 return;
579 aMenuPosition = rEvent.GetMousePosPixel();
581 else
583 if (GetSelectedItemId() == sal_uInt16(-1))
584 return;
585 ::tools::Rectangle aBBox (GetItemRect(GetSelectedItemId()));
586 aMenuPosition = aBBox.Center();
589 // Setup the menu.
590 VclBuilder aBuilder(nullptr, VclBuilderContainer::getUIRootDir(), "modules/simpress/ui/layoutmenu.ui", "");
591 VclPtr<PopupMenu> pMenu(aBuilder.get_menu("menu"));
592 FloatingWindow* pMenuWindow = dynamic_cast<FloatingWindow*>(pMenu->GetWindow());
593 if (pMenuWindow != nullptr)
594 pMenuWindow->SetPopupModeFlags(
595 pMenuWindow->GetPopupModeFlags() | FloatWinPopupFlags::NoMouseUpClose);
596 pMenu->SetSelectHdl(LINK(this, LayoutMenu, OnMenuItemSelected));
598 // Disable the SID_INSERTPAGE_LAYOUT_MENU item when
599 // the document is read-only.
600 const SfxPoolItem* pItem = nullptr;
601 const SfxItemState aState (
602 mrBase.GetViewFrame()->GetDispatcher()->QueryState(SID_INSERTPAGE, pItem));
603 if (aState == SfxItemState::DISABLED)
604 pMenu->EnableItem(SID_INSERTPAGE_LAYOUT_MENU, false);
606 // Show the menu.
607 pMenu->Execute(this, ::tools::Rectangle(aMenuPosition,Size(1,1)), PopupMenuFlags::ExecuteDown);
609 break;
611 default:
612 ValueSet::Command(rEvent);
613 break;
617 IMPL_LINK_NOARG(LayoutMenu, StateChangeHandler, const OUString&, void)
619 InvalidateContent();
622 IMPL_LINK(LayoutMenu, OnMenuItemSelected, Menu*, pMenu, bool)
624 if (pMenu == nullptr)
626 OSL_ENSURE(pMenu!=nullptr, "LayoutMenu::OnMenuItemSelected: illegal menu!");
627 return false;
630 pMenu->Deactivate();
631 OString sIdent = pMenu->GetCurItemIdent();
633 if (sIdent == "apply")
635 AssignLayoutToSelectedSlides(GetSelectedAutoLayout());
637 else if (sIdent == "insert")
639 // Add arguments to this slot and forward it to the main view
640 // shell.
641 InsertPageWithLayout(GetSelectedAutoLayout());
644 return false;
647 // Selects an appropriate layout of the slide inside control.
649 // Method may be called several times with the same item-id to be selected -
650 // only once the actually state of the control will be changed.
652 void LayoutMenu::UpdateSelection()
654 bool bItemSelected = false;
658 // Get current page of main view.
659 ViewShell* pViewShell = mrBase.GetMainViewShell().get();
660 if (pViewShell == nullptr)
661 break;
663 SdPage* pCurrentPage = pViewShell->getCurrentPage();
664 if (pCurrentPage == nullptr)
665 break;
667 // Get layout of current page.
668 AutoLayout aLayout (pCurrentPage->GetAutoLayout());
669 if (aLayout<AUTOLAYOUT_START || aLayout>AUTOLAYOUT_END)
670 break;
672 // Find the entry of the menu for to the layout.
673 const sal_uInt16 nItemCount = GetItemCount();
674 for (sal_uInt16 nId=1; nId<=nItemCount; nId++)
676 if (*static_cast<AutoLayout*>(GetItemData(nId)) == aLayout)
678 // do not set selection twice to the same item
679 if (GetSelectedItemId() != nId)
681 SetNoSelection();
682 SelectItem(nId);
685 bItemSelected = true; // no need to call SetNoSelection()
686 break;
690 while (false);
692 if ( ! bItemSelected)
693 SetNoSelection();
696 IMPL_LINK(LayoutMenu, EventMultiplexerListener, ::sd::tools::EventMultiplexerEvent&, rEvent, void)
698 switch (rEvent.meEventId)
700 // tdf#89890 During changes of the Layout of the slide when focus is not set inside main area
701 // we do not receive notification EventMultiplexerEventId::CurrentPageChanged, but we receive the following 3 notification types.
702 // => let's make UpdateSelection() also when some shape is changed (during Layout changes)
703 case EventMultiplexerEventId::ShapeChanged:
704 case EventMultiplexerEventId::ShapeInserted:
705 case EventMultiplexerEventId::ShapeRemoved:
706 UpdateSelection();
707 break;
709 case EventMultiplexerEventId::CurrentPageChanged:
710 case EventMultiplexerEventId::SlideSortedSelection:
711 UpdateSelection();
712 break;
714 case EventMultiplexerEventId::MainViewAdded:
715 mbIsMainViewChangePending = true;
716 break;
718 case EventMultiplexerEventId::MainViewRemoved:
719 HideFocus();
720 break;
722 case EventMultiplexerEventId::ConfigurationUpdated:
723 if (mbIsMainViewChangePending)
725 mbIsMainViewChangePending = false;
726 InvalidateContent();
728 break;
730 default:
731 break;
735 IMPL_LINK(LayoutMenu, WindowEventHandler, VclWindowEvent&, rEvent, void)
737 switch (rEvent.GetId())
739 case VclEventId::WindowShow:
740 case VclEventId::WindowResize:
741 SetSizePixel(GetParent()->GetSizePixel());
742 break;
744 default: break;
748 void LayoutMenu::DataChanged (const DataChangedEvent& rEvent)
750 Fill();
751 ValueSet::DataChanged(rEvent);
752 SetBackground(sfx2::sidebar::Theme::GetWallpaper(sfx2::sidebar::Theme::Paint_PanelBackground));
753 SetColor(sfx2::sidebar::Theme::GetColor(sfx2::sidebar::Theme::Paint_PanelBackground));
756 } } // end of namespace ::sd::sidebar
758 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */