/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
class LayoutValueSet : public ValueSet
{ private:
LayoutMenu& mrMenu;
/** Calculate the number of displayed rows. This depends on the given item size, the given number of columns, and the size of the control. Note that this is not the number of rows managed by the valueset. This number may be larger. In that case a vertical scroll bar is displayed.
*/ int CalculateRowCount(const Size& rItemSize, int nColumnCount);
void LayoutMenu::implConstruct( DrawDocShell& rDocumentShell )
{
OSL_ENSURE( mrBase.GetDocument()->GetDocSh() == &rDocumentShell, "LayoutMenu::implConstruct: hmm?" ); // if this fires, then my assumption that the rDocumentShell parameter to our first ctor is superfluous ...
(void) rDocumentShell;
bool LayoutValueSet::Command(const CommandEvent& rEvent)
{ if (rEvent.GetCommand() != CommandEventId::ContextMenu) returnfalse;
// As a preparation for the context menu the item under the mouse is // selected. if (rEvent.IsMouseEvent())
{
sal_uInt16 nIndex = GetItemId(rEvent.GetMousePosPixel()); if (nIndex > 0)
SelectItem(nIndex);
}
// Call SID_INSERTPAGE with the right arguments. This is because // the popup menu can not call this slot with arguments directly.
SfxRequest aRequest (CreateRequest(SID_INSERTPAGE, aLayout)); if (aRequest.GetArgs() != nullptr)
{
pDispatcher->Execute(
SID_INSERTPAGE,
SfxCallMode::ASYNCHRON | SfxCallMode::RECORD,
*aRequest.GetArgs());
}
UpdateSelection();
}
void LayoutMenu::InvalidateContent()
{ // Throw away the current set and fill the menu anew according to the // current settings (this includes the support for vertical writing.)
Fill();
if (mxSidebar.is())
mxSidebar->requestLayout();
// set selection inside the control during Impress start up
UpdateSelection();
}
int LayoutValueSet::CalculateRowCount (const Size&, int nColumnCount)
{ int nRowCount = 0;
/** The specified layout is assigned to the current page of the view shell in the center pane.
*/ void LayoutMenu::AssignLayoutToSelectedSlides (AutoLayout aLayout)
{ usingnamespace ::sd::slidesorter; usingnamespace ::sd::slidesorter::controller;
do
{ // The view shell in the center pane has to be present.
ViewShell* pMainViewShell = mrBase.GetMainViewShell().get(); if (pMainViewShell == nullptr) break;
// Determine if the current view is in an invalid master page mode. // The handout view is always in master page mode and therefore not // invalid. bool bMasterPageMode (false); switch (pMainViewShell->GetShellType())
{ case ViewShell::ST_NOTES: case ViewShell::ST_IMPRESS:
{
DrawViewShell* pDrawViewShell = static_cast<DrawViewShell*>(pMainViewShell); if (pDrawViewShell->GetEditMode() == EditMode::MasterPage)
bMasterPageMode = true; break;
} default: break;
} if (bMasterPageMode) break;
// Get a list of all selected slides and call the SID_MODIFYPAGE // slot for all of them.
::sd::slidesorter::SharedPageSelection pPageSelection;
// Get a list of selected pages. // First we try to obtain this list from a slide sorter. This is // possible only some of the view shells in the center pane. When // no valid slide sorter is available then ask the main view shell // for its current page.
SlideSorterViewShell* pSlideSorter = nullptr; switch (pMainViewShell->GetShellType())
{ case ViewShell::ST_IMPRESS: case ViewShell::ST_NOTES: case ViewShell::ST_SLIDE_SORTER:
pSlideSorter = SlideSorterViewShell::GetSlideSorter(mrBase); break; default: break;
} if (pSlideSorter != nullptr)
{ // There is a slide sorter visible so get the list of selected pages from it.
pPageSelection = pSlideSorter->GetPageSelection();
}
if( (pSlideSorter == nullptr) || !pPageSelection || pPageSelection->empty() )
{ // No valid slide sorter available. Ask the main view shell for // its current page.
pPageSelection = std::make_shared<::sd::slidesorter::SlideSorterViewShell::PageSelection>();
pPageSelection->push_back(pMainViewShell->GetActualPage());
}
if (pPageSelection->empty()) break;
for (constauto& rpPage : *pPageSelection)
{ if (rpPage == nullptr) continue;
// Call the SID_ASSIGN_LAYOUT slot with all the necessary parameters.
SfxRequest aRequest(mrBase.GetViewFrame(), SID_ASSIGN_LAYOUT);
aRequest.AppendItem(SfxUInt32Item (ID_VAL_WHATPAGE, (rpPage->GetPageNum()-1)/2));
aRequest.AppendItem(SfxUInt32Item (ID_VAL_WHATLAYOUT, aLayout));
pMainViewShell->ExecuteSlot (aRequest, false);
}
} while(false);
}
// Get URL of the view in the center pane.
OUString sCenterPaneViewName; try
{ if (mrBase.GetDrawController())
{
Reference<XResourceId> xPaneId (ResourceId::create(
::comphelper::getProcessComponentContext(),
FrameworkHelper::msCenterPaneURL));
Reference<XView> xView (FrameworkHelper::Instance(mrBase)->GetView(xPaneId)); if (xView.is())
sCenterPaneViewName = xView->getResourceId()->getResourceURL();
}
} catch (RuntimeException&)
{}
void LayoutMenu::ShowContextMenu(const Point* pPos)
{ if (SdModule::get()->GetWaterCan()) return;
// Determine the position where to show the menu.
Point aMenuPosition; if (pPos)
{ auto nItemId = mxLayoutValueSet->GetItemId(*pPos); if (nItemId <= 0) return;
mxLayoutValueSet->SelectItem(nItemId);
aMenuPosition = *pPos;
} else
{ if (mxLayoutValueSet->GetSelectedItemId() == sal_uInt16(-1)) return;
::tools::Rectangle aBBox(mxLayoutValueSet->GetItemRect(mxLayoutValueSet->GetSelectedItemId()));
aMenuPosition = aBBox.Center();
}
// Disable the SID_INSERTPAGE_LAYOUT_MENU item when // the document is read-only.
SfxPoolItemHolder aResult; const SfxItemState aState (
mrBase.GetViewFrame().GetDispatcher()->QueryState(SID_INSERTPAGE, aResult)); if (aState == SfxItemState::DISABLED)
xMenu->set_sensitive(u"insert"_ustr, false);
// Show the menu.
OnMenuItemSelected(xMenu->popup_at_rect(pPopupParent, aRect));
}
void LayoutMenu::OnMenuItemSelected(std::u16string_view ident)
{ if (ident.empty()) return;
if (ident == u"apply")
{
AssignLayoutToSelectedSlides(GetSelectedAutoLayout());
} elseif (ident == u"insert")
{ // Add arguments to this slot and forward it to the main view // shell.
InsertPageWithLayout(GetSelectedAutoLayout());
}
}
// Selects an appropriate layout of the slide inside control. // // Method may be called several times with the same item-id to be selected - // only once the actually state of the control will be changed. // void LayoutMenu::UpdateSelection()
{ bool bItemSelected = false;
do
{ // Get current page of main view.
ViewShell* pViewShell = mrBase.GetMainViewShell().get(); if (pViewShell == nullptr) break;
SdPage* pCurrentPage = pViewShell->getCurrentPage(); if (pCurrentPage == nullptr) break;
// Get layout of current page.
AutoLayout aLayout (pCurrentPage->GetAutoLayout()); if (aLayout<AUTOLAYOUT_START || aLayout>AUTOLAYOUT_END) break;
// Find the entry of the menu for to the layout. const sal_uInt16 nItemCount = mxLayoutValueSet->GetItemCount(); for (sal_uInt16 nId=1; nId<=nItemCount; nId++)
{ if (*static_cast<AutoLayout*>(mxLayoutValueSet->GetItemData(nId)) == aLayout)
{ // do not set selection twice to the same item if (mxLayoutValueSet->GetSelectedItemId() != nId)
{
mxLayoutValueSet->SetNoSelection();
mxLayoutValueSet->SelectItem(nId);
}
bItemSelected = true; // no need to call SetNoSelection() break;
}
}
} while (false);
if (!bItemSelected)
mxLayoutValueSet->SetNoSelection();
}
IMPL_LINK(LayoutMenu, EventMultiplexerListener, ::sd::tools::EventMultiplexerEvent&, rEvent, void)
{ switch (rEvent.meEventId)
{ // tdf#89890 During changes of the Layout of the slide when focus is not set inside main area // we do not receive notification EventMultiplexerEventId::CurrentPageChanged, but we receive the following 3 notification types. // => let's make UpdateSelection() also when some shape is changed (during Layout changes) case EventMultiplexerEventId::ShapeChanged: case EventMultiplexerEventId::ShapeInserted: case EventMultiplexerEventId::ShapeRemoved: case EventMultiplexerEventId::CurrentPageChanged: case EventMultiplexerEventId::SlideSortedSelection:
UpdateSelection(); break;
case EventMultiplexerEventId::MainViewAdded:
mbIsMainViewChangePending = true; break;
case EventMultiplexerEventId::MainViewRemoved:
mxLayoutValueSet->Invalidate(); // redraw without focus break;
case EventMultiplexerEventId::ConfigurationUpdated: if (mbIsMainViewChangePending)
{
mbIsMainViewChangePending = false;
InvalidateContent();
} break;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.