572 lines
18 KiB
C++
572 lines
18 KiB
C++
/* -*- 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 .
|
|
*/
|
|
|
|
#include <LayerTabBar.hxx>
|
|
#include <svx/svdlayer.hxx>
|
|
#include <svx/svdpagv.hxx>
|
|
#include <vcl/commandevent.hxx>
|
|
#include <vcl/svapp.hxx>
|
|
#include <vcl/weld.hxx>
|
|
#include <sfx2/dispatch.hxx>
|
|
#include <sfx2/viewfrm.hxx>
|
|
|
|
#include <helpids.h>
|
|
#include <app.hrc>
|
|
#include <strings.hrc>
|
|
|
|
#include <DrawViewShell.hxx>
|
|
#include <View.hxx>
|
|
#include <drawdoc.hxx>
|
|
#include <sdresid.hxx>
|
|
#include <unokywds.hxx>
|
|
#include <DrawDocShell.hxx>
|
|
#include <drawview.hxx>
|
|
#include <undolayer.hxx>
|
|
|
|
#include <svx/sdr/overlay/overlaymanager.hxx>
|
|
#include <svx/sdr/overlay/overlayselection.hxx>
|
|
#include <svx/svditer.hxx>
|
|
#include <sdpage.hxx>
|
|
#include <svx/sdrpaintwindow.hxx>
|
|
|
|
#include <officecfg/Office/Draw.hxx>
|
|
|
|
namespace sd {
|
|
|
|
/**
|
|
* default constructor
|
|
*/
|
|
LayerTabBar::LayerTabBar(DrawViewShell* pViewSh, vcl::Window* pParent)
|
|
: TabBar( pParent, WinBits( WB_BORDER | WB_3DLOOK | WB_SCROLL ) ),
|
|
DropTargetHelper( this ),
|
|
pDrViewSh(pViewSh),
|
|
m_aBringLayerObjectsToAttentionDelayTimer("LayerTabBar m_aBringLayerObjectsToAttentionDelayTimer")
|
|
{
|
|
EnableEditMode();
|
|
SetSizePixel(Size(0, 0));
|
|
SetMaxPageWidth( 150 );
|
|
SetHelpId( HID_SD_TABBAR_LAYERS );
|
|
|
|
m_aBringLayerObjectsToAttentionDelayTimer.SetInvokeHandler(
|
|
LINK(this, LayerTabBar, BringLayerObjectsToAttentionDelayTimerHdl));
|
|
m_aBringLayerObjectsToAttentionDelayTimer.SetTimeout(500);
|
|
}
|
|
|
|
LayerTabBar::~LayerTabBar()
|
|
{
|
|
disposeOnce();
|
|
}
|
|
|
|
void LayerTabBar::dispose()
|
|
{
|
|
DropTargetHelper::dispose();
|
|
TabBar::dispose();
|
|
}
|
|
|
|
OUString LayerTabBar::convertToLocalizedName(const OUString& rName)
|
|
{
|
|
if ( rName == sUNO_LayerName_background )
|
|
return SdResId( STR_LAYER_BCKGRND );
|
|
|
|
if ( rName == sUNO_LayerName_background_objects )
|
|
return SdResId( STR_LAYER_BCKGRNDOBJ );
|
|
|
|
if ( rName == sUNO_LayerName_layout )
|
|
return SdResId( STR_LAYER_LAYOUT );
|
|
|
|
if ( rName == sUNO_LayerName_controls )
|
|
return SdResId( STR_LAYER_CONTROLS );
|
|
|
|
if ( rName == sUNO_LayerName_measurelines )
|
|
return SdResId( STR_LAYER_MEASURELINES );
|
|
|
|
return rName;
|
|
}
|
|
|
|
// Use a method name, that is specific to LayerTabBar to make code better readable
|
|
const OUString & LayerTabBar::GetLayerName(sal_uInt16 nPageId) const
|
|
{
|
|
return GetAuxiliaryText(nPageId);
|
|
}
|
|
|
|
void LayerTabBar::SetLayerName( sal_uInt16 nPageId, const OUString& rText )
|
|
{
|
|
SetAuxiliaryText(nPageId, rText);
|
|
}
|
|
|
|
// Here "Page" is a tab in the LayerTabBar.
|
|
void LayerTabBar::InsertPage( sal_uInt16 nPageId, const OUString& rText,
|
|
TabBarPageBits nBits, sal_uInt16 nPos)
|
|
{
|
|
OUString sLocalizedName(convertToLocalizedName(rText));
|
|
TabBar::InsertPage(nPageId, sLocalizedName, nBits, nPos );
|
|
SetLayerName(nPageId, rText);
|
|
}
|
|
|
|
void LayerTabBar::SetPageText( sal_uInt16 nPageId, const OUString& rText )
|
|
{
|
|
OUString sLocalizedName(convertToLocalizedName(rText));
|
|
SetLayerName(nPageId, rText);
|
|
TabBar::SetPageText(nPageId, sLocalizedName);
|
|
}
|
|
|
|
bool LayerTabBar::IsLocalizedNameOfStandardLayer(std::u16string_view rName)
|
|
{
|
|
return ( rName == SdResId(STR_LAYER_LAYOUT)
|
|
|| rName == SdResId(STR_LAYER_CONTROLS)
|
|
|| rName == SdResId(STR_LAYER_MEASURELINES)
|
|
|| rName == SdResId(STR_LAYER_BCKGRND)
|
|
|| rName == SdResId(STR_LAYER_BCKGRNDOBJ) );
|
|
}
|
|
|
|
bool LayerTabBar::IsRealNameOfStandardLayer(std::u16string_view rName)
|
|
{
|
|
return ( rName == sUNO_LayerName_layout
|
|
|| rName == sUNO_LayerName_controls
|
|
|| rName == sUNO_LayerName_measurelines
|
|
|| rName == sUNO_LayerName_background
|
|
|| rName == sUNO_LayerName_background_objects );
|
|
}
|
|
|
|
void LayerTabBar::Select()
|
|
{
|
|
if (SfxViewFrame* pFrame = pDrViewSh->GetViewFrame())
|
|
{
|
|
SfxDispatcher* pDispatcher = pFrame->GetDispatcher();
|
|
pDispatcher->Execute(SID_SWITCHLAYER, SfxCallMode::SYNCHRON);
|
|
}
|
|
}
|
|
|
|
void LayerTabBar::MouseMove(const MouseEvent &rMEvt)
|
|
{
|
|
sal_uInt16 nPageId = 0;
|
|
if (!rMEvt.IsLeaveWindow())
|
|
nPageId = GetPageId(rMEvt.GetPosPixel());
|
|
BringLayerObjectsToAttention(nPageId);
|
|
return;
|
|
}
|
|
|
|
void LayerTabBar::BringLayerObjectsToAttention(const sal_uInt16 nPageId)
|
|
{
|
|
if (nPageId == m_nBringLayerObjectsToAttentionLastPageId)
|
|
return;
|
|
|
|
m_aBringLayerObjectsToAttentionDelayTimer.Stop();
|
|
|
|
if (m_xOverlayObject && m_xOverlayObject->getOverlayManager())
|
|
m_xOverlayObject->getOverlayManager()->remove(*m_xOverlayObject);
|
|
|
|
m_nBringLayerObjectsToAttentionLastPageId = nPageId;
|
|
|
|
std::vector<basegfx::B2DRange> aRanges;
|
|
|
|
if (nPageId != 0)
|
|
{
|
|
sal_uInt16 nDisableLayerObjectsOverlay
|
|
= officecfg::Office::Draw::Misc::DisableLayerHighlighting::get();
|
|
OUString aLayerName(GetLayerName(nPageId));
|
|
if (nDisableLayerObjectsOverlay > 0 // don't show tooltip message when 0 - meaning feature is turned off
|
|
&& pDrViewSh->GetView()->GetSdrPageView()->IsLayerVisible(aLayerName))
|
|
{
|
|
SdrLayerAdmin& rLayerAdmin = pDrViewSh->GetDoc()->GetLayerAdmin();
|
|
SdrObjListIter aIter(pDrViewSh->GetActualPage(), SdrIterMode::DeepWithGroups);
|
|
while (aIter.IsMore())
|
|
{
|
|
SdrObject* pObj = aIter.Next();
|
|
assert(pObj != nullptr);
|
|
if (!pObj)
|
|
continue;
|
|
const SdrLayer* pSdrLayer = rLayerAdmin.GetLayerPerID(pObj->GetLayer());
|
|
if (!pSdrLayer)
|
|
continue;
|
|
if (aLayerName == pSdrLayer->GetName())
|
|
{
|
|
::tools::Rectangle aRect(pObj->GetLogicRect());
|
|
if (!aRect.IsEmpty())
|
|
{
|
|
aRanges.emplace_back(aRect.Left(), aRect.Top(), aRect.Right(), aRect.Bottom());
|
|
if (aRanges.size() > nDisableLayerObjectsOverlay)
|
|
{
|
|
OUString sHelpText = SdResId(STR_LAYER_HIGHLIGHTING_DISABLED);
|
|
sHelpText = sHelpText.replaceFirst(
|
|
"%1", OUString::number(nDisableLayerObjectsOverlay));
|
|
SetQuickHelpText(sHelpText);
|
|
m_xOverlayObject.reset();
|
|
return;
|
|
}
|
|
}
|
|
// skip over objects in groups
|
|
if (pObj->IsGroupObject())
|
|
{
|
|
SdrObjListIter aSubListIter(pObj->GetSubList(), SdrIterMode::DeepWithGroups);
|
|
while (aSubListIter.IsMore())
|
|
{
|
|
aIter.Next();
|
|
aSubListIter.Next();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
SetQuickHelpText(u""_ustr);
|
|
|
|
if (aRanges.empty())
|
|
m_xOverlayObject.reset();
|
|
else
|
|
{
|
|
m_xOverlayObject.reset(new sdr::overlay::OverlaySelection(
|
|
sdr::overlay::OverlayType::Invert,
|
|
Color(), std::move(aRanges), true/*unused for Invert type*/));
|
|
m_aBringLayerObjectsToAttentionDelayTimer.Start();
|
|
}
|
|
}
|
|
|
|
IMPL_LINK_NOARG(LayerTabBar, BringLayerObjectsToAttentionDelayTimerHdl, Timer *, void)
|
|
{
|
|
m_aBringLayerObjectsToAttentionDelayTimer.Stop();
|
|
if (m_xOverlayObject)
|
|
{
|
|
if (SdrView* pView = pDrViewSh->GetDrawView())
|
|
{
|
|
if (SdrPaintWindow* pPaintWindow = pView->GetPaintWindow(0))
|
|
{
|
|
const rtl::Reference<sdr::overlay::OverlayManager>& xOverlayManager =
|
|
pPaintWindow->GetOverlayManager();
|
|
xOverlayManager->add(*m_xOverlayObject);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void LayerTabBar::MouseButtonDown(const MouseEvent& rMEvt)
|
|
{
|
|
bool bSetPageID=false;
|
|
|
|
if (rMEvt.IsLeft())
|
|
{
|
|
Point aPosPixel = rMEvt.GetPosPixel();
|
|
sal_uInt16 aTabId = GetPageId( PixelToLogic(aPosPixel) );
|
|
if (aTabId == 0)
|
|
{
|
|
if (SfxViewFrame* pFrame = pDrViewSh->GetViewFrame())
|
|
{
|
|
SfxDispatcher* pDispatcher = pFrame->GetDispatcher();
|
|
pDispatcher->Execute(SID_INSERTLAYER, SfxCallMode::SYNCHRON);
|
|
|
|
bSetPageID=true;
|
|
}
|
|
}
|
|
else if (rMEvt.IsMod2())
|
|
{
|
|
// direct editing of tab text
|
|
// make sure the clicked tab is the current tab otherwise Edit() acts on the wrong tab
|
|
if ( aTabId != GetCurPageId())
|
|
{
|
|
MouseEvent aSyntheticEvent (rMEvt.GetPosPixel(), 1, MouseEventModifiers::SYNTHETIC, MOUSE_LEFT, 0);
|
|
TabBar::MouseButtonDown(aSyntheticEvent);
|
|
}
|
|
}
|
|
else if (rMEvt.IsMod1() || rMEvt.IsShift())
|
|
{
|
|
// keyboard Shortcuts to change layer attributes
|
|
|
|
OUString aName(GetLayerName(aTabId));
|
|
SdrPageView* pPV = pDrViewSh->GetView()->GetSdrPageView();
|
|
|
|
// Save old state
|
|
|
|
bool bOldPrintable = pPV->IsLayerPrintable(aName);
|
|
bool bOldVisible = pPV->IsLayerVisible(aName);
|
|
bool bOldLocked = pPV->IsLayerLocked(aName);
|
|
|
|
bool bNewPrintable = bOldPrintable;
|
|
bool bNewVisible = bOldVisible;
|
|
bool bNewLocked = bOldLocked;
|
|
|
|
if (rMEvt.IsMod1() && rMEvt.IsShift())
|
|
{
|
|
// Shift+Ctrl: Toggle between layer printable / not printable
|
|
bNewPrintable = !bOldPrintable;
|
|
pPV->SetLayerPrintable(aName, bNewPrintable);
|
|
}
|
|
else if (rMEvt.IsShift())
|
|
{
|
|
// Shift: Toggle between layer visible / hidden
|
|
// see also SID_TOGGLELAYERVISIBILITY / tdf#113439
|
|
bNewVisible = !bOldVisible;
|
|
pPV->SetLayerVisible(aName, bNewVisible);
|
|
}
|
|
else // if (rMEvt.IsMod1())
|
|
{
|
|
// Ctrl: Toggle between layer locked / unlocked
|
|
bNewLocked = !bOldLocked;
|
|
pPV->SetLayerLocked(aName, bNewLocked);
|
|
}
|
|
|
|
pDrViewSh->ResetActualLayer();
|
|
|
|
// Add Undo action
|
|
|
|
::sd::View* pView = pDrViewSh->GetView();
|
|
DrawView* pDrView = dynamic_cast<DrawView*>(pView);
|
|
|
|
SdDrawDocument& rDoc = pView->GetDoc();
|
|
SdrLayer* pLayer = rDoc.GetLayerAdmin().GetLayer(aName);
|
|
|
|
if (pLayer)
|
|
{
|
|
assert (pDrView && "Change layer attribute undo action is only working with a SdDrawView");
|
|
if(pDrView)
|
|
{
|
|
SfxUndoManager* pManager = rDoc.GetDocSh()->GetUndoManager();
|
|
std::unique_ptr<SdLayerModifyUndoAction> pAction(new SdLayerModifyUndoAction(
|
|
&rDoc,
|
|
pLayer,
|
|
aName,
|
|
pLayer->GetTitle(),
|
|
pLayer->GetDescription(),
|
|
bOldVisible,
|
|
bOldLocked,
|
|
bOldPrintable,
|
|
aName,
|
|
pLayer->GetTitle(),
|
|
pLayer->GetDescription(),
|
|
bNewVisible,
|
|
bNewLocked,
|
|
bNewPrintable
|
|
));
|
|
pManager->AddUndoAction(std::move(pAction));
|
|
}
|
|
}
|
|
|
|
// Mark document changed
|
|
|
|
pView->GetDoc().SetChanged();
|
|
}
|
|
}
|
|
|
|
// If you insert a new layer you must not call TabBar::MouseButtonDown(rMEvt);
|
|
// because you want to activate the new layer
|
|
if( !bSetPageID )
|
|
TabBar::MouseButtonDown(rMEvt);
|
|
}
|
|
|
|
void LayerTabBar::DoubleClick()
|
|
{
|
|
if (GetCurPageId() != 0)
|
|
{
|
|
if (SfxViewFrame* pFrame = pDrViewSh->GetViewFrame())
|
|
{
|
|
SfxDispatcher* pDispatcher = pFrame->GetDispatcher();
|
|
pDispatcher->Execute( SID_MODIFYLAYER, SfxCallMode::SYNCHRON );
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* AcceptDrop-Event
|
|
*/
|
|
|
|
sal_Int8 LayerTabBar::AcceptDrop( const AcceptDropEvent& rEvt )
|
|
{
|
|
sal_Int8 nRet = DND_ACTION_NONE;
|
|
|
|
if( rEvt.mbLeaving )
|
|
EndSwitchPage();
|
|
|
|
if( !pDrViewSh->GetDocSh()->IsReadOnly() )
|
|
{
|
|
Point aPos( PixelToLogic( rEvt.maPosPixel ) );
|
|
OUString sLayerName( GetLayerName(GetPageId(aPos)) );
|
|
SdrLayerID nLayerId = pDrViewSh->GetView()->GetDoc().GetLayerAdmin().GetLayerID(sLayerName);
|
|
|
|
nRet = pDrViewSh->AcceptDrop( rEvt, *this, nullptr, SDRPAGE_NOTFOUND, nLayerId );
|
|
|
|
SwitchPage( aPos );
|
|
}
|
|
|
|
return nRet;
|
|
}
|
|
|
|
/**
|
|
* ExecuteDrop-Event
|
|
*/
|
|
sal_Int8 LayerTabBar::ExecuteDrop( const ExecuteDropEvent& rEvt )
|
|
{
|
|
Point aPos( PixelToLogic(rEvt.maPosPixel) );
|
|
OUString sLayerName( GetLayerName(GetPageId(aPos)) );
|
|
SdrLayerID nLayerId = pDrViewSh->GetView()->GetDoc().GetLayerAdmin().GetLayerID(sLayerName);
|
|
|
|
sal_Int8 nRet = pDrViewSh->ExecuteDrop( rEvt, *this, nullptr, SDRPAGE_NOTFOUND, nLayerId );
|
|
|
|
EndSwitchPage();
|
|
|
|
return nRet;
|
|
|
|
}
|
|
|
|
void LayerTabBar::Command(const CommandEvent& rCEvt)
|
|
{
|
|
if ( rCEvt.GetCommand() == CommandEventId::ContextMenu )
|
|
{
|
|
BringLayerObjectsToAttention();
|
|
if (SfxViewFrame* pFrame = pDrViewSh->GetViewFrame())
|
|
{
|
|
SfxDispatcher* pDispatcher = pFrame->GetDispatcher();
|
|
pDispatcher->ExecutePopup(u"layertab"_ustr);
|
|
}
|
|
}
|
|
}
|
|
|
|
bool LayerTabBar::StartRenaming()
|
|
{
|
|
bool bOK = true;
|
|
OUString aLayerName = GetLayerName( GetEditPageId() );
|
|
|
|
if ( IsRealNameOfStandardLayer(aLayerName))
|
|
{
|
|
// It is not allowed to change these names
|
|
bOK = false;
|
|
}
|
|
else
|
|
{
|
|
::sd::View* pView = pDrViewSh->GetView();
|
|
|
|
if ( pView->IsTextEdit() )
|
|
{
|
|
pView->SdrEndTextEdit();
|
|
}
|
|
}
|
|
|
|
return bOK;
|
|
}
|
|
|
|
TabBarAllowRenamingReturnCode LayerTabBar::AllowRenaming()
|
|
{
|
|
bool bOK = true;
|
|
|
|
// Check if names already exists
|
|
::sd::View* pView = pDrViewSh->GetView();
|
|
SdDrawDocument& rDoc = pView->GetDoc();
|
|
OUString aLayerName = pView->GetActiveLayer();
|
|
SdrLayerAdmin& rLayerAdmin = rDoc.GetLayerAdmin();
|
|
OUString aNewName( GetEditText() );
|
|
|
|
if (aNewName.isEmpty() ||
|
|
(rLayerAdmin.GetLayer( aNewName ) && aLayerName != aNewName) )
|
|
{
|
|
if (SfxViewFrame* pFrame = pDrViewSh->GetViewFrame())
|
|
{
|
|
// Name already exists.
|
|
std::unique_ptr<weld::MessageDialog> xWarn(Application::CreateMessageDialog(pFrame->GetFrameWeld(),
|
|
VclMessageType::Warning, VclButtonsType::Ok,
|
|
SdResId(STR_WARN_NAME_DUPLICATE)));
|
|
xWarn->run();
|
|
bOK = false;
|
|
}
|
|
}
|
|
|
|
if (bOK)
|
|
{
|
|
if ( IsLocalizedNameOfStandardLayer(aNewName) || IsRealNameOfStandardLayer(aNewName) )
|
|
{
|
|
// Standard layer names may not be changed.
|
|
bOK = false;
|
|
}
|
|
}
|
|
|
|
return bOK ? TABBAR_RENAMING_YES : TABBAR_RENAMING_NO;
|
|
}
|
|
|
|
void LayerTabBar::EndRenaming()
|
|
{
|
|
if( IsEditModeCanceled() )
|
|
return;
|
|
|
|
::sd::View* pView = pDrViewSh->GetView();
|
|
DrawView* pDrView = dynamic_cast<DrawView*>( pView );
|
|
|
|
SdDrawDocument& rDoc = pView->GetDoc();
|
|
OUString aLayerName = pView->GetActiveLayer();
|
|
SdrLayerAdmin& rLayerAdmin = rDoc.GetLayerAdmin();
|
|
SdrLayer* pLayer = rLayerAdmin.GetLayer(aLayerName);
|
|
|
|
if (!pLayer)
|
|
return;
|
|
|
|
OUString aNewName( GetEditText() );
|
|
assert (pDrView && "Rename layer undo action is only working with a SdDrawView");
|
|
if( pDrView )
|
|
{
|
|
SfxUndoManager* pManager = rDoc.GetDocSh()->GetUndoManager();
|
|
std::unique_ptr<SdLayerModifyUndoAction> pAction(new SdLayerModifyUndoAction(
|
|
&rDoc,
|
|
pLayer,
|
|
aLayerName,
|
|
pLayer->GetTitle(),
|
|
pLayer->GetDescription(),
|
|
pDrView->IsLayerVisible(aLayerName),
|
|
pDrView->IsLayerLocked(aLayerName),
|
|
pDrView->IsLayerPrintable(aLayerName),
|
|
aNewName,
|
|
pLayer->GetTitle(),
|
|
pLayer->GetDescription(),
|
|
pDrView->IsLayerVisible(aLayerName),
|
|
pDrView->IsLayerLocked(aLayerName),
|
|
pDrView->IsLayerPrintable(aLayerName)
|
|
));
|
|
pManager->AddUndoAction( std::move(pAction) );
|
|
}
|
|
|
|
// First notify View since SetName() calls ResetActualLayer() and
|
|
// the View then already has to know the Layer
|
|
pView->SetActiveLayer(aNewName);
|
|
pLayer->SetName(aNewName);
|
|
rDoc.SetChanged();
|
|
}
|
|
|
|
void LayerTabBar::ActivatePage()
|
|
{
|
|
if (pDrViewSh!=nullptr)
|
|
{
|
|
if (SfxViewFrame* pFrame = pDrViewSh->GetViewFrame())
|
|
{
|
|
SfxDispatcher* pDispatcher = pFrame->GetDispatcher();
|
|
pDispatcher->Execute(SID_SWITCHLAYER, SfxCallMode::ASYNCHRON);
|
|
}
|
|
}
|
|
}
|
|
|
|
void LayerTabBar::SendActivatePageEvent()
|
|
{
|
|
CallEventListeners (VclEventId::TabbarPageActivated,
|
|
reinterpret_cast<void*>(GetCurPageId()));
|
|
}
|
|
|
|
void LayerTabBar::SendDeactivatePageEvent()
|
|
{
|
|
CallEventListeners (VclEventId::TabbarPageDeactivated,
|
|
reinterpret_cast<void*>(GetCurPageId()));
|
|
}
|
|
|
|
} // end of namespace sd
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|