1418 lines
46 KiB
C++
1418 lines
46 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 <sal/log.hxx>
|
|
#include <sal/types.h>
|
|
#include <sot/formats.hxx>
|
|
#include <utility>
|
|
#include <vcl/weld.hxx>
|
|
#include <svx/svditer.hxx>
|
|
#include <sfx2/docfile.hxx>
|
|
#include <svx/svdoole2.hxx>
|
|
#include <vcl/svapp.hxx>
|
|
#include <cusshow.hxx>
|
|
|
|
#include <sfx2/viewfrm.hxx>
|
|
|
|
#include <sdtreelb.hxx>
|
|
#include <DrawDocShell.hxx>
|
|
#include <drawdoc.hxx>
|
|
#include <sdpage.hxx>
|
|
#include <sdmod.hxx>
|
|
#include <sdresid.hxx>
|
|
#include <navigatr.hxx>
|
|
#include <strings.hrc>
|
|
|
|
#include <bitmaps.hlst>
|
|
#include <customshowlist.hxx>
|
|
#include <ViewShell.hxx>
|
|
#include <DrawController.hxx>
|
|
#include <ViewShellBase.hxx>
|
|
|
|
#include <com/sun/star/embed/XEmbedPersist.hpp>
|
|
#include <com/sun/star/embed/XEmbeddedObject.hpp>
|
|
#include <com/sun/star/frame/Desktop.hpp>
|
|
#include <svtools/acceleratorexecute.hxx>
|
|
#include <svtools/embedtransfer.hxx>
|
|
#include <comphelper/servicehelper.hxx>
|
|
#include <comphelper/processfactory.hxx>
|
|
|
|
#include <vcl/commandevent.hxx>
|
|
|
|
#include <svx/svdview.hxx>
|
|
#include <DrawViewShell.hxx>
|
|
|
|
#include <svx/svdoashp.hxx>
|
|
#include <svx/sdasitm.hxx>
|
|
#include <svl/poolitem.hxx>
|
|
#include <svl/stritem.hxx>
|
|
|
|
using namespace com::sun::star;
|
|
|
|
namespace {
|
|
|
|
sd::DrawViewShell* lcl_getDrawViewShell(const SdDrawDocument* pDoc)
|
|
{
|
|
if (!pDoc || !pDoc->GetDocSh())
|
|
return nullptr;
|
|
return static_cast<sd::DrawViewShell*>(pDoc->GetDocSh()->GetViewShell());
|
|
}
|
|
|
|
}
|
|
|
|
bool SdPageObjsTLV::bIsInDrag = false;
|
|
|
|
bool SdPageObjsTLV::IsInDrag()
|
|
{
|
|
return bIsInDrag;
|
|
}
|
|
|
|
SotClipboardFormatId SdPageObjsTLV::SdPageObjsTransferable::mnListBoxDropFormatId = static_cast<SotClipboardFormatId>(SAL_MAX_UINT32);
|
|
|
|
SdPageObjsTLV::SdPageObjsTransferable::SdPageObjsTransferable(
|
|
INetBookmark aBookmark,
|
|
::sd::DrawDocShell& rDocShell,
|
|
NavigatorDragType eDragType)
|
|
: SdTransferable(rDocShell.GetDoc(), nullptr, true),
|
|
maBookmark(std::move( aBookmark )),
|
|
mrDocShell( rDocShell ),
|
|
meDragType( eDragType )
|
|
{
|
|
}
|
|
|
|
SdPageObjsTLV::SdPageObjsTransferable::~SdPageObjsTransferable()
|
|
{
|
|
}
|
|
|
|
void SdPageObjsTLV::SdPageObjsTransferable::AddSupportedFormats()
|
|
{
|
|
AddFormat(SotClipboardFormatId::NETSCAPE_BOOKMARK);
|
|
AddFormat(SotClipboardFormatId::TREELISTBOX);
|
|
AddFormat(GetListBoxDropFormatId());
|
|
}
|
|
|
|
bool SdPageObjsTLV::SdPageObjsTransferable::GetData( const css::datatransfer::DataFlavor& rFlavor, const OUString& /*rDestDoc*/ )
|
|
{
|
|
SotClipboardFormatId nFormatId = SotExchange::GetFormat( rFlavor );
|
|
switch (nFormatId)
|
|
{
|
|
case SotClipboardFormatId::NETSCAPE_BOOKMARK:
|
|
SetINetBookmark( maBookmark, rFlavor );
|
|
return true;
|
|
|
|
case SotClipboardFormatId::TREELISTBOX:
|
|
{
|
|
css::uno::Any aTreeListBoxData; // empty for now
|
|
SetAny(aTreeListBoxData);
|
|
return true;
|
|
}
|
|
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
void SdPageObjsTLV::SdPageObjsTransferable::DragFinished( sal_Int8 nDropAction )
|
|
{
|
|
SdPageObjsTLV::OnDragFinished();
|
|
SdTransferable::DragFinished(nDropAction);
|
|
}
|
|
|
|
SdPageObjsTLV::SdPageObjsTransferable* SdPageObjsTLV::SdPageObjsTransferable::getImplementation( const css::uno::Reference< css::uno::XInterface >& rxData )
|
|
noexcept
|
|
{
|
|
return dynamic_cast<SdPageObjsTLV::SdPageObjsTransferable*>(rxData.get());
|
|
}
|
|
|
|
SotClipboardFormatId SdPageObjsTLV::SdPageObjsTransferable::GetListBoxDropFormatId()
|
|
{
|
|
if (mnListBoxDropFormatId == static_cast<SotClipboardFormatId>(SAL_MAX_UINT32))
|
|
mnListBoxDropFormatId = SotExchange::RegisterFormatMimeType(u"application/x-openoffice-treelistbox-moveonly;windows_formatname=\"SV_LBOX_DD_FORMAT_MOVE\""_ustr);
|
|
return mnListBoxDropFormatId;
|
|
}
|
|
|
|
/**
|
|
* @return true if children of the specified string are selected
|
|
*/
|
|
bool SdPageObjsTLV::HasSelectedChildren( std::u16string_view rName )
|
|
{
|
|
bool bChildren = false;
|
|
|
|
if( !rName.empty() )
|
|
{
|
|
std::unique_ptr<weld::TreeIter> xEntry(m_xTreeView->make_iterator());
|
|
OUString aTmp;
|
|
|
|
if (m_xTreeView->get_iter_first(*xEntry))
|
|
{
|
|
do
|
|
{
|
|
aTmp = m_xTreeView->get_text(*xEntry);
|
|
if (aTmp == rName)
|
|
{
|
|
|
|
// see if any of the selected nodes are subchildren of this node
|
|
m_xTreeView->selected_foreach([this, &bChildren, &xEntry](weld::TreeIter& rEntry){
|
|
std::unique_ptr<weld::TreeIter> xParent(m_xTreeView->make_iterator(&rEntry));
|
|
while (!bChildren && m_xTreeView->iter_parent(*xParent))
|
|
bChildren = m_xTreeView->iter_compare(*xParent, *xEntry) == 0;
|
|
return bChildren;
|
|
});
|
|
|
|
break;
|
|
}
|
|
}
|
|
while (m_xTreeView->iter_next(*xEntry));
|
|
}
|
|
}
|
|
|
|
return bChildren;
|
|
}
|
|
|
|
void SdPageObjsTLV::SetShowAllShapes (
|
|
const bool bShowAllShapes,
|
|
const bool bFillList)
|
|
{
|
|
m_bShowAllShapes = bShowAllShapes;
|
|
if (bFillList)
|
|
{
|
|
if (m_pMedium == nullptr)
|
|
Fill(m_pDoc, m_bShowAllPages, m_aDocName);
|
|
else
|
|
Fill(m_pDoc, m_pMedium, m_aDocName);
|
|
}
|
|
}
|
|
|
|
void SdPageObjsTLV::SetOrderFrontToBack(const bool bOrderFrontToBack)
|
|
{
|
|
m_bOrderFrontToBack = bOrderFrontToBack;
|
|
}
|
|
|
|
bool SdPageObjsTLV::IsEqualToShapeList(std::unique_ptr<weld::TreeIter>& rEntry, const SdrObjList& rList,
|
|
std::u16string_view rListName)
|
|
{
|
|
if (!rEntry)
|
|
return false;
|
|
OUString aName = m_xTreeView->get_text(*rEntry);
|
|
|
|
if (rListName != aName)
|
|
return false;
|
|
|
|
if (!m_xTreeView->iter_next(*rEntry))
|
|
rEntry.reset();
|
|
|
|
SdrObjListIter aIter(&rList,
|
|
!rList.HasObjectNavigationOrder() /* use navigation order, if available */,
|
|
SdrIterMode::Flat);
|
|
|
|
while (aIter.IsMore())
|
|
{
|
|
SdrObject* pObj = aIter.Next();
|
|
|
|
const OUString aObjectName(GetObjectName(pObj));
|
|
|
|
if (!aObjectName.isEmpty())
|
|
{
|
|
if (!rEntry)
|
|
return false;
|
|
|
|
aName = m_xTreeView->get_text(*rEntry);
|
|
|
|
if (aObjectName != aName)
|
|
return false;
|
|
|
|
if (pObj->IsGroupObject())
|
|
{
|
|
bool bRet = IsEqualToShapeList(rEntry, *pObj->GetSubList(), aObjectName);
|
|
if (!bRet)
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
if (!m_xTreeView->iter_next(*rEntry))
|
|
rEntry.reset();
|
|
}
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Checks if the pages (PageKind::Standard) of a doc and the objects on the pages
|
|
* are identical to the TreeLB.
|
|
* If a doc is provided, this will be the used doc (important by more than
|
|
* one document).
|
|
*/
|
|
bool SdPageObjsTLV::IsEqualToDoc( const SdDrawDocument* pInDoc )
|
|
{
|
|
if( pInDoc )
|
|
m_pDoc = pInDoc;
|
|
|
|
if( !m_pDoc )
|
|
return false;
|
|
|
|
sd::DrawViewShell* pDrawViewShell = lcl_getDrawViewShell(m_pDoc);
|
|
if (!pDrawViewShell)
|
|
return false;
|
|
PageKind eDrawViewShellPageKind = pDrawViewShell->GetPageKind();
|
|
if (eDrawViewShellPageKind != PageKind::Standard && eDrawViewShellPageKind != PageKind::Notes)
|
|
return false;
|
|
|
|
std::unique_ptr<weld::TreeIter> xEntry(m_xTreeView->make_iterator());
|
|
if (!m_xTreeView->get_iter_first(*xEntry))
|
|
xEntry.reset();
|
|
|
|
// compare all pages including the objects
|
|
sal_uInt16 nPage = 0;
|
|
const sal_uInt16 nMaxPages = m_pDoc->GetPageCount();
|
|
|
|
while( nPage < nMaxPages )
|
|
{
|
|
const SdPage* pPage = static_cast<const SdPage*>( m_pDoc->GetPage( nPage ) );
|
|
if (pPage->GetPageKind() == eDrawViewShellPageKind)
|
|
{
|
|
bool bRet = IsEqualToShapeList(xEntry, *pPage, pPage->GetName());
|
|
if (!bRet)
|
|
return false;
|
|
}
|
|
nPage++;
|
|
}
|
|
// If there are still entries in the listbox,
|
|
// then objects (with names) or pages were deleted
|
|
return !xEntry;
|
|
}
|
|
|
|
IMPL_LINK(SdPageObjsTLV, CommandHdl, const CommandEvent&, rCEvt, bool)
|
|
{
|
|
if (IsEditingActive())
|
|
return false;
|
|
|
|
if (rCEvt.GetCommand() == CommandEventId::ContextMenu)
|
|
{
|
|
m_xTreeView->grab_focus();
|
|
|
|
// select clicked entry
|
|
if (std::unique_ptr<weld::TreeIter> xEntry(m_xTreeView->make_iterator());
|
|
rCEvt.IsMouseEvent() && m_xTreeView->get_dest_row_at_pos(
|
|
rCEvt.GetMousePosPixel(), xEntry.get(), false))
|
|
{
|
|
m_bSelectionHandlerNavigates = true;
|
|
m_bNavigationGrabsFocus = false;
|
|
m_xTreeView->set_cursor(*xEntry);
|
|
Select();
|
|
}
|
|
|
|
bool bRet = m_aPopupMenuHdl.Call(rCEvt);
|
|
return bRet;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
IMPL_LINK(SdPageObjsTLV, KeyInputHdl, const KeyEvent&, rKEvt, bool)
|
|
{
|
|
const vcl::KeyCode& rKeyCode = rKEvt.GetKeyCode();
|
|
if (m_xAccel->execute(rKeyCode))
|
|
{
|
|
m_bEditing = false;
|
|
// the accelerator consumed the event
|
|
return true;
|
|
}
|
|
if (rKeyCode.GetCode() == KEY_RETURN)
|
|
{
|
|
m_bEditing = false;
|
|
std::unique_ptr<weld::TreeIter> xCursor(m_xTreeView->make_iterator());
|
|
if (m_xTreeView->get_cursor(xCursor.get()) && m_xTreeView->iter_has_child(*xCursor))
|
|
{
|
|
if (m_xTreeView->get_row_expanded(*xCursor))
|
|
m_xTreeView->collapse_row(*xCursor);
|
|
else
|
|
m_xTreeView->expand_row(*xCursor);
|
|
}
|
|
m_bNavigationGrabsFocus = true;
|
|
m_aRowActivatedHdl.Call(*m_xTreeView);
|
|
m_bNavigationGrabsFocus = false;
|
|
return true;
|
|
}
|
|
bool bRet = m_aKeyPressHdl.Call(rKEvt);
|
|
// m_bEditing needs to be set after key press handler call back or x11 won't end editing on
|
|
// Esc key press. See SdNavigatorWin::KeyInputHdl.
|
|
m_bEditing = false;
|
|
return bRet;
|
|
}
|
|
|
|
IMPL_LINK(SdPageObjsTLV, MousePressHdl, const MouseEvent&, rMEvt, bool)
|
|
{
|
|
m_bEditing = false;
|
|
m_bSelectionHandlerNavigates = rMEvt.GetClicks() == 1;
|
|
m_bNavigationGrabsFocus = rMEvt.GetClicks() != 1;
|
|
return false;
|
|
}
|
|
|
|
IMPL_LINK_NOARG(SdPageObjsTLV, MouseReleaseHdl, const MouseEvent&, bool)
|
|
{
|
|
if (m_aMouseReleaseHdl.IsSet() && m_aMouseReleaseHdl.Call(MouseEvent()))
|
|
return false;
|
|
|
|
m_bSelectionHandlerNavigates = false;
|
|
m_bNavigationGrabsFocus = true;
|
|
return false;
|
|
}
|
|
|
|
IMPL_LINK(SdPageObjsTLV, DragBeginHdl, bool&, rUnsetDragIcon, bool)
|
|
{
|
|
rUnsetDragIcon = false;
|
|
return StartDrag();
|
|
}
|
|
|
|
namespace
|
|
{
|
|
bool CanDragSource(const weld::TreeView& rTreeView)
|
|
{
|
|
std::unique_ptr<weld::TreeIter> xSource(rTreeView.make_iterator());
|
|
if (!rTreeView.get_selected(xSource.get()))
|
|
return false;
|
|
|
|
std::unique_ptr<weld::TreeIter> xSourceParent(rTreeView.make_iterator(xSource.get()));
|
|
bool bSourceHasParent = rTreeView.iter_parent(*xSourceParent);
|
|
// disallow root drag
|
|
if (!bSourceHasParent)
|
|
return false;
|
|
|
|
SdrObject* pSourceObject = weld::fromId<SdrObject*>(rTreeView.get_id(*xSource));
|
|
if (pSourceObject == reinterpret_cast<SdrObject*>(1))
|
|
pSourceObject = nullptr;
|
|
|
|
if (!pSourceObject)
|
|
return false;
|
|
|
|
SdrPage* pObjectList = pSourceObject->getSdrPageFromSdrObject();
|
|
if (!pObjectList)
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* StartDrag-Request
|
|
*/
|
|
bool SdPageObjsTLV::StartDrag()
|
|
{
|
|
return !CanDragSource(*m_xTreeView) || DoDrag();
|
|
}
|
|
|
|
/**
|
|
* Begin drag
|
|
*/
|
|
bool SdPageObjsTLV::DoDrag()
|
|
{
|
|
if (!m_pNavigator)
|
|
return true;
|
|
|
|
if (!m_xHelper)
|
|
return true;
|
|
|
|
// Get the view.
|
|
::sd::DrawDocShell* pDocShell = m_pDoc->GetDocSh();
|
|
::sd::ViewShell* pViewShell = GetViewShellForDocShell(*pDocShell);
|
|
if (pViewShell == nullptr)
|
|
{
|
|
OSL_ASSERT(pViewShell!=nullptr);
|
|
return true;
|
|
}
|
|
sd::View* pView = pViewShell->GetView();
|
|
if (pView == nullptr)
|
|
{
|
|
OSL_ASSERT(pView!=nullptr);
|
|
return true;
|
|
}
|
|
|
|
m_xDropTargetHelper->SetDrawView(pViewShell->GetDrawView());
|
|
m_xDropTargetHelper->SetOrderFrontToBack(m_bOrderFrontToBack);
|
|
bIsInDrag = true;
|
|
|
|
std::unique_ptr<weld::TreeIter> xEntry = m_xTreeView->make_iterator();
|
|
bool bUserData = m_xTreeView->get_cursor(xEntry.get());
|
|
|
|
SdrObject* pObject = nullptr;
|
|
sal_Int64 nUserData = bUserData ? m_xTreeView->get_id(*xEntry).toInt64() : 0;
|
|
if (nUserData != 1)
|
|
pObject = reinterpret_cast<SdrObject*>(nUserData);
|
|
if (pObject != nullptr)
|
|
{
|
|
// For shapes without a user supplied name (the automatically
|
|
// created name does not count), a different drag and drop technique
|
|
// is used.
|
|
if (GetObjectName(pObject, false).isEmpty())
|
|
{
|
|
AddShapeToTransferable(*m_xHelper, *pObject);
|
|
m_xHelper->SetView(pView);
|
|
SdModule::get()->pTransferDrag = m_xHelper.get();
|
|
}
|
|
|
|
// Unnamed shapes have to be selected to be recognized by the
|
|
// current drop implementation. In order to have a consistent
|
|
// behaviour for all shapes, every shape that is to be dragged is
|
|
// selected first.
|
|
SdrPageView* pPageView = pView->GetSdrPageView();
|
|
pView->UnmarkAllObj(pPageView);
|
|
pView->MarkObj(pObject, pPageView);
|
|
}
|
|
else
|
|
{
|
|
m_xHelper->SetView(pView);
|
|
SdModule::get()->pTransferDrag = m_xHelper.get();
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void SdPageObjsTLV::OnDragFinished()
|
|
{
|
|
bIsInDrag = false;
|
|
}
|
|
|
|
SdPageObjsTLVDropTarget::SdPageObjsTLVDropTarget(weld::TreeView& rTreeView)
|
|
: DropTargetHelper(rTreeView.get_drop_target())
|
|
, m_rTreeView(rTreeView)
|
|
, m_pSdrView(nullptr)
|
|
{
|
|
}
|
|
|
|
/**
|
|
* AcceptDrop-Event
|
|
*/
|
|
sal_Int8 SdPageObjsTLVDropTarget::AcceptDrop(const AcceptDropEvent& rEvt)
|
|
{
|
|
weld::TreeView* pSource = m_rTreeView.get_drag_source();
|
|
// only dragging within the same widget allowed
|
|
if (!pSource || pSource != &m_rTreeView)
|
|
return DND_ACTION_NONE;
|
|
|
|
std::unique_ptr<weld::TreeIter> xTarget(m_rTreeView.make_iterator());
|
|
if (!m_rTreeView.get_dest_row_at_pos(rEvt.maPosPixel, xTarget.get(), true))
|
|
return DND_ACTION_NONE;
|
|
|
|
// disallow when root is drop target
|
|
if (m_rTreeView.get_iter_depth(*xTarget) == 0)
|
|
return DND_ACTION_NONE;
|
|
|
|
// disallow if there is no source entry selected
|
|
std::unique_ptr<weld::TreeIter> xSource(m_rTreeView.make_iterator());
|
|
if (!m_rTreeView.get_selected(xSource.get()))
|
|
return DND_ACTION_NONE;
|
|
|
|
// disallow when root is source
|
|
if (m_rTreeView.get_iter_depth(*xSource) == 0)
|
|
return DND_ACTION_NONE;
|
|
|
|
// disallow when the source is the parent or ancestral parent of the target
|
|
std::unique_ptr<weld::TreeIter> xTargetParent(m_rTreeView.make_iterator(xTarget.get()));
|
|
while (m_rTreeView.get_iter_depth(*xTargetParent) > 1)
|
|
{
|
|
if (!m_rTreeView.iter_parent(*xTargetParent) ||
|
|
m_rTreeView.iter_compare(*xSource, *xTargetParent) == 0)
|
|
return DND_ACTION_NONE;
|
|
}
|
|
|
|
// disallow drop when source and target are not within the same page
|
|
std::unique_ptr<weld::TreeIter> xSourcePage(m_rTreeView.make_iterator(xSource.get()));
|
|
std::unique_ptr<weld::TreeIter> xTargetPage(m_rTreeView.make_iterator(xTarget.get()));
|
|
while (m_rTreeView.get_iter_depth(*xTargetPage))
|
|
m_rTreeView.iter_parent(*xTargetPage);
|
|
while (m_rTreeView.get_iter_depth(*xSourcePage))
|
|
m_rTreeView.iter_parent(*xSourcePage);
|
|
if (m_rTreeView.iter_compare(*xTargetPage, *xSourcePage) != 0)
|
|
return DND_ACTION_NONE;
|
|
|
|
return DND_ACTION_MOVE;
|
|
}
|
|
|
|
/**
|
|
* ExecuteDrop-Event
|
|
*/
|
|
sal_Int8 SdPageObjsTLVDropTarget::ExecuteDrop( const ExecuteDropEvent& rEvt )
|
|
{
|
|
weld::TreeView* pSource = m_rTreeView.get_drag_source();
|
|
// only dragging within the same widget allowed
|
|
if (!pSource || pSource != &m_rTreeView)
|
|
return DND_ACTION_NONE;
|
|
|
|
std::unique_ptr<weld::TreeIter> xSource(m_rTreeView.make_iterator());
|
|
if (!m_rTreeView.get_selected(xSource.get()))
|
|
return DND_ACTION_NONE;
|
|
|
|
std::unique_ptr<weld::TreeIter> xTarget(m_rTreeView.make_iterator());
|
|
if (!m_rTreeView.get_dest_row_at_pos(rEvt.maPosPixel, xTarget.get(), false))
|
|
return DND_ACTION_NONE;
|
|
|
|
auto nIterCompare = m_rTreeView.iter_compare(*xSource, *xTarget);
|
|
if (nIterCompare == 0)
|
|
{
|
|
// drop position is the same as source position
|
|
return DND_ACTION_NONE;
|
|
}
|
|
|
|
SdrObject* pTargetObject = weld::fromId<SdrObject*>(m_rTreeView.get_id(*xTarget));
|
|
SdrObject* pSourceObject = weld::fromId<SdrObject*>(m_rTreeView.get_id(*xSource));
|
|
if (pSourceObject == reinterpret_cast<SdrObject*>(1))
|
|
pSourceObject = nullptr;
|
|
if (pTargetObject == reinterpret_cast<SdrObject*>(1))
|
|
pTargetObject = nullptr;
|
|
|
|
if (pTargetObject != nullptr && pSourceObject != nullptr && m_pSdrView)
|
|
{
|
|
SdrPage* pObjectList = pSourceObject->getSdrPageFromSdrObject();
|
|
|
|
std::unique_ptr<weld::TreeIter> xSourceParent(m_rTreeView.make_iterator(xSource.get()));
|
|
m_rTreeView.iter_parent(*xSourceParent);
|
|
std::unique_ptr<weld::TreeIter> xTargetParent(m_rTreeView.make_iterator(xTarget.get()));
|
|
m_rTreeView.iter_parent(*xTargetParent);
|
|
|
|
int nTargetPos = m_rTreeView.get_iter_index_in_parent(*xTarget);
|
|
|
|
// Make the tree view what the model will be when it is changed below.
|
|
m_rTreeView.move_subtree(*xSource, xTargetParent.get(), nTargetPos);
|
|
m_rTreeView.iter_previous_sibling(*xTarget);
|
|
m_rTreeView.set_cursor(*xTarget);
|
|
|
|
// Remove and insert are required for moving objects into and out of groups.
|
|
// PutMarked... by itself would suffice if this wasn't allowed.
|
|
|
|
// Remove the source object from source parent list and insert it in the target parent list.
|
|
SdrObject* pSourceParentObject = weld::fromId<SdrObject*>(m_rTreeView.get_id(*xSourceParent));
|
|
SdrObject* pTargetParentObject = weld::fromId<SdrObject*>(m_rTreeView.get_id(*xTargetParent));
|
|
|
|
// Presumably there is need for a hard reference to hold on to the removed object so it is
|
|
// guaranteed to be valid for insert back into an object list.
|
|
rtl::Reference<SdrObject> rSourceObject;
|
|
|
|
// remove object
|
|
if (pSourceParentObject == reinterpret_cast<SdrObject*>(1))
|
|
{
|
|
rSourceObject = pObjectList->NbcRemoveObject(pSourceObject->GetOrdNum());
|
|
}
|
|
else
|
|
{
|
|
SdrObjList* pList = pSourceParentObject->GetSubList();
|
|
rSourceObject = pList->NbcRemoveObject(pSourceObject->GetOrdNum());
|
|
}
|
|
|
|
// insert object
|
|
if (pTargetParentObject == reinterpret_cast<SdrObject*>(1))
|
|
{
|
|
pObjectList->NbcInsertObject(rSourceObject.get());
|
|
}
|
|
else
|
|
{
|
|
SdrObjList* pList = pTargetParentObject->GetSubList();
|
|
pList->NbcInsertObject(rSourceObject.get());
|
|
}
|
|
|
|
m_bOrderFrontToBack ? m_pSdrView->PutMarkedInFrontOfObj(pTargetObject) :
|
|
m_pSdrView->PutMarkedBehindObj(pTargetObject);
|
|
}
|
|
|
|
return DND_ACTION_NONE;
|
|
}
|
|
|
|
void SdPageObjsTLV::AddShapeToTransferable (
|
|
SdTransferable& rTransferable,
|
|
const SdrObject& rObject) const
|
|
{
|
|
std::unique_ptr<TransferableObjectDescriptor> pObjectDescriptor(new TransferableObjectDescriptor);
|
|
bool bIsDescriptorFillingPending (true);
|
|
|
|
const SdrOle2Obj* pOleObject = dynamic_cast<const SdrOle2Obj*>(&rObject);
|
|
if (pOleObject != nullptr && pOleObject->GetObjRef().is())
|
|
{
|
|
// If object has no persistence it must be copied as part of the document
|
|
try
|
|
{
|
|
uno::Reference< embed::XEmbedPersist > xPersObj (pOleObject->GetObjRef(), uno::UNO_QUERY );
|
|
if (xPersObj.is() && xPersObj->hasEntry())
|
|
{
|
|
SvEmbedTransferHelper::FillTransferableObjectDescriptor(
|
|
*pObjectDescriptor,
|
|
pOleObject->GetObjRef(),
|
|
pOleObject->GetGraphic(),
|
|
pOleObject->GetAspect());
|
|
bIsDescriptorFillingPending = false;
|
|
}
|
|
}
|
|
catch( uno::Exception& )
|
|
{
|
|
}
|
|
}
|
|
|
|
::sd::DrawDocShell* pDocShell = m_pDoc->GetDocSh();
|
|
if (bIsDescriptorFillingPending && pDocShell!=nullptr)
|
|
{
|
|
pDocShell->FillTransferableObjectDescriptor(*pObjectDescriptor);
|
|
}
|
|
|
|
Point aDragPos (rObject.GetCurrentBoundRect().Center());
|
|
pObjectDescriptor->maDragStartPos = aDragPos;
|
|
if (pDocShell != nullptr)
|
|
pObjectDescriptor->maDisplayName = pDocShell->GetMedium()->GetURLObject().GetURLNoPass();
|
|
else
|
|
pObjectDescriptor->maDisplayName.clear();
|
|
|
|
rTransferable.SetStartPos(aDragPos);
|
|
rTransferable.SetObjectDescriptor( std::move(pObjectDescriptor) );
|
|
}
|
|
|
|
::sd::ViewShell* SdPageObjsTLV::GetViewShellForDocShell (::sd::DrawDocShell& rDocShell)
|
|
{
|
|
{
|
|
::sd::ViewShell* pViewShell = rDocShell.GetViewShell();
|
|
if (pViewShell != nullptr)
|
|
return pViewShell;
|
|
}
|
|
|
|
try
|
|
{
|
|
// Get a component enumeration from the desktop and search it for documents.
|
|
const uno::Reference<uno::XComponentContext>& xContext( ::comphelper::getProcessComponentContext());
|
|
|
|
uno::Reference<frame::XDesktop2> xDesktop = frame::Desktop::create(xContext);
|
|
|
|
if ( ! xDesktop.is())
|
|
return nullptr;
|
|
|
|
uno::Reference<container::XIndexAccess> xFrameAccess = xDesktop->getFrames();
|
|
if ( ! xFrameAccess.is())
|
|
return nullptr;
|
|
|
|
for (sal_Int32 nIndex=0,nCount=xFrameAccess->getCount(); nIndex<nCount; ++nIndex)
|
|
{
|
|
uno::Reference<frame::XFrame> xFrame;
|
|
if ( ! (xFrameAccess->getByIndex(nIndex) >>= xFrame))
|
|
continue;
|
|
|
|
auto xController = xFrame->getController();
|
|
::sd::DrawController* pController = dynamic_cast<sd::DrawController*>(xController.get());
|
|
if (pController == nullptr)
|
|
continue;
|
|
::sd::ViewShellBase* pBase = pController->GetViewShellBase();
|
|
if (pBase == nullptr)
|
|
continue;
|
|
if (pBase->GetDocShell() != &rDocShell)
|
|
continue;
|
|
|
|
const std::shared_ptr<sd::ViewShell> pViewShell (pBase->GetMainViewShell());
|
|
if (pViewShell)
|
|
return pViewShell.get();
|
|
}
|
|
}
|
|
catch (uno::Exception &)
|
|
{
|
|
// When there is an exception then simply use the default value of
|
|
// bIsEnabled and disable the controls.
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
SdPageObjsTLV::SdPageObjsTLV(std::unique_ptr<weld::TreeView> xTreeView)
|
|
: m_xTreeView(std::move(xTreeView))
|
|
, m_xScratchIter(m_xTreeView->make_iterator())
|
|
, m_xDropTargetHelper(new SdPageObjsTLVDropTarget(*m_xTreeView))
|
|
, m_xAccel(::svt::AcceleratorExecute::createAcceleratorHelper())
|
|
, m_pNavigator(nullptr)
|
|
, m_pDoc(nullptr)
|
|
, m_pBookmarkDoc(nullptr)
|
|
, m_pMedium(nullptr)
|
|
, m_pOwnMedium(nullptr)
|
|
, m_bLinkableSelected(false)
|
|
, m_bShowAllShapes(false)
|
|
, m_bOrderFrontToBack(false)
|
|
, m_bShowAllPages(false)
|
|
, m_bSelectionHandlerNavigates(false)
|
|
, m_bNavigationGrabsFocus(true)
|
|
, m_eSelectionMode(SelectionMode::Single)
|
|
, m_nSelectEventId(nullptr)
|
|
, m_nRowActivateEventId(nullptr)
|
|
{
|
|
m_xTreeView->connect_expanding(LINK(this, SdPageObjsTLV, RequestingChildrenHdl));
|
|
m_xTreeView->connect_changed(LINK(this, SdPageObjsTLV, SelectHdl));
|
|
m_xTreeView->connect_row_activated(LINK(this, SdPageObjsTLV, RowActivatedHdl));
|
|
m_xTreeView->connect_drag_begin(LINK(this, SdPageObjsTLV, DragBeginHdl));
|
|
m_xTreeView->connect_key_press(LINK(this, SdPageObjsTLV, KeyInputHdl));
|
|
m_xTreeView->connect_mouse_press(LINK(this, SdPageObjsTLV, MousePressHdl));
|
|
m_xTreeView->connect_mouse_release(LINK(this, SdPageObjsTLV, MouseReleaseHdl));
|
|
m_xTreeView->connect_editing(LINK(this, SdPageObjsTLV, EditingEntryHdl),
|
|
LINK(this, SdPageObjsTLV, EditedEntryHdl));
|
|
m_xTreeView->connect_popup_menu(LINK(this, SdPageObjsTLV, CommandHdl));
|
|
|
|
m_xTreeView->set_size_request(m_xTreeView->get_approximate_digit_width() * 28,
|
|
m_xTreeView->get_text_height() * 8);
|
|
m_xTreeView->set_column_editables({true});
|
|
}
|
|
|
|
IMPL_LINK(SdPageObjsTLV, EditEntryAgain, void*, p, void)
|
|
{
|
|
m_xTreeView->grab_focus();
|
|
std::unique_ptr<weld::TreeIter> xEntry(static_cast<weld::TreeIter*>(p));
|
|
m_xTreeView->start_editing(*xEntry);
|
|
m_bEditing = true;
|
|
}
|
|
|
|
IMPL_LINK_NOARG(SdPageObjsTLV, EditingEntryHdl, const weld::TreeIter&, bool)
|
|
{
|
|
m_bEditing = true;
|
|
return true;
|
|
}
|
|
|
|
IMPL_LINK(SdPageObjsTLV, EditedEntryHdl, const IterString&, rIterString, bool)
|
|
{
|
|
m_bEditing = false;
|
|
|
|
// Did the name change?
|
|
if (m_xTreeView->get_text(rIterString.first) == rIterString.second)
|
|
return true;
|
|
|
|
// If the new name is empty or not unique, start editing again.
|
|
if (rIterString.second.isEmpty() || m_pDoc->GetObj(rIterString.second))
|
|
{
|
|
std::unique_ptr<weld::TreeIter> xEntry(m_xTreeView->make_iterator(&rIterString.first));
|
|
Application::PostUserEvent(LINK(this, SdPageObjsTLV, EditEntryAgain), xEntry.release());
|
|
return false;
|
|
}
|
|
|
|
// set the new name
|
|
const auto aEntryId = m_xTreeView->get_id(rIterString.first);
|
|
if (aEntryId.toInt64() == 1)
|
|
{
|
|
// page name
|
|
if (::sd::DrawDocShell* pDocShell = m_pDoc->GetDocSh())
|
|
{
|
|
if (::sd::ViewShell* pViewShell = GetViewShellForDocShell(*pDocShell))
|
|
{
|
|
SdPage* pPage = pViewShell->GetActualPage();
|
|
pPage->SetName(rIterString.second);
|
|
}
|
|
}
|
|
}
|
|
else if (SdrObject* pCursorEntryObject = weld::fromId<SdrObject*>(aEntryId))
|
|
{
|
|
// object name
|
|
pCursorEntryObject->SetName(rIterString.second);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
IMPL_LINK_NOARG(SdPageObjsTLV, SelectHdl, weld::TreeView&, void)
|
|
{
|
|
if (m_nSelectEventId)
|
|
Application::RemoveUserEvent(m_nSelectEventId);
|
|
// post the event to process select event after mouse press event
|
|
m_nSelectEventId = Application::PostUserEvent(LINK(this, SdPageObjsTLV, AsyncSelectHdl));
|
|
}
|
|
|
|
IMPL_LINK_NOARG(SdPageObjsTLV, RowActivatedHdl, weld::TreeView&, bool)
|
|
{
|
|
if (m_nRowActivateEventId)
|
|
Application::RemoveUserEvent(m_nRowActivateEventId);
|
|
// post the event to process row activate after mouse press event
|
|
m_nRowActivateEventId = Application::PostUserEvent(LINK(this, SdPageObjsTLV, AsyncRowActivatedHdl));
|
|
return false;
|
|
}
|
|
|
|
IMPL_LINK_NOARG(SdPageObjsTLV, AsyncSelectHdl, void*, void)
|
|
{
|
|
Select();
|
|
}
|
|
|
|
void SdPageObjsTLV::Select()
|
|
{
|
|
m_nSelectEventId = nullptr;
|
|
|
|
if (IsEditingActive())
|
|
return;
|
|
|
|
m_bLinkableSelected = true;
|
|
|
|
m_xTreeView->selected_foreach([this](weld::TreeIter& rEntry){
|
|
if (m_xTreeView->get_id(rEntry).toInt64() == 0)
|
|
m_bLinkableSelected = false;
|
|
return false;
|
|
});
|
|
|
|
m_aChangeHdl.Call(*m_xTreeView);
|
|
|
|
if (m_bSelectionHandlerNavigates)
|
|
m_aRowActivatedHdl.Call(*m_xTreeView);
|
|
|
|
if (!m_pNavigator)
|
|
{
|
|
m_xHelper.clear();
|
|
return;
|
|
}
|
|
|
|
::sd::DrawDocShell* pDocShell = m_pDoc->GetDocSh();
|
|
OUString aURL = INetURLObject(pDocShell->GetMedium()->GetPhysicalName(), INetProtocol::File).GetMainURL(INetURLObject::DecodeMechanism::NONE);
|
|
NavigatorDragType eDragType = m_pNavigator->GetNavigatorDragType();
|
|
|
|
OUString sSelectedEntry = get_cursor_text(); // what about multiple selections?
|
|
aURL += "#" + sSelectedEntry;
|
|
|
|
INetBookmark aBookmark(aURL, sSelectedEntry);
|
|
sal_Int8 nDNDActions = DND_ACTION_COPYMOVE;
|
|
|
|
if( eDragType == NAVIGATOR_DRAGTYPE_LINK )
|
|
nDNDActions = DND_ACTION_LINK; // Either COPY *or* LINK, never both!
|
|
else if (m_pDoc->GetSdPageCount(PageKind::Standard) == 1)
|
|
{
|
|
// Can not move away the last slide in a document.
|
|
nDNDActions = DND_ACTION_COPY;
|
|
}
|
|
|
|
// object is destroyed by internal reference mechanism
|
|
m_xHelper.set(new SdPageObjsTLV::SdPageObjsTransferable(std::move(aBookmark), *pDocShell, eDragType));
|
|
rtl::Reference<TransferDataContainer> xHelper(m_xHelper);
|
|
m_xTreeView->enable_drag_source(xHelper, nDNDActions);
|
|
}
|
|
|
|
IMPL_LINK_NOARG(SdPageObjsTLV, AsyncRowActivatedHdl, void*, void)
|
|
{
|
|
m_nRowActivateEventId = nullptr;
|
|
m_aRowActivatedHdl.Call(*m_xTreeView);
|
|
}
|
|
|
|
OUString SdPageObjsTLV::GetObjectName(
|
|
const SdrObject* pObject,
|
|
const bool bCreate) const
|
|
{
|
|
OUString aRet;
|
|
|
|
if ( pObject )
|
|
{
|
|
aRet = pObject->GetName();
|
|
|
|
if (aRet.isEmpty())
|
|
if (auto pOleObj = dynamic_cast<const SdrOle2Obj* >(pObject))
|
|
aRet = pOleObj->GetPersistName();
|
|
}
|
|
|
|
if (bCreate
|
|
&& m_bShowAllShapes
|
|
&& aRet.isEmpty()
|
|
&& pObject!=nullptr)
|
|
{
|
|
OUString sObjName;
|
|
if (pObject->GetObjIdentifier() == SdrObjKind::CustomShape)
|
|
{
|
|
// taken from SdrObjCustomShape::GetCustomShapeName
|
|
OUString aEngine(pObject->GetMergedItem(SDRATTR_CUSTOMSHAPE_ENGINE).GetValue());
|
|
if (aEngine.isEmpty() || aEngine == "com.sun.star.drawing.EnhancedCustomShapeEngine")
|
|
{
|
|
OUString sShapeType;
|
|
const SdrCustomShapeGeometryItem& rGeometryItem
|
|
= pObject->GetMergedItem(SDRATTR_CUSTOMSHAPE_GEOMETRY);
|
|
const uno::Any* pAny = rGeometryItem.GetPropertyValueByName(u"Type"_ustr);
|
|
if (pAny && (*pAny >>= sShapeType))
|
|
sObjName = SdResId(STR_NAVIGATOR_CUSTOMSHAPE) + u": " + sShapeType;
|
|
}
|
|
}
|
|
else
|
|
sObjName = pObject->TakeObjNameSingul();
|
|
|
|
aRet = SdResId(STR_NAVIGATOR_SHAPE_BASE_NAME) + " (" + sObjName +")";
|
|
aRet = aRet.replaceFirst("%1", OUString::number(pObject->GetOrdNum() + 1));
|
|
}
|
|
|
|
return aRet;
|
|
}
|
|
|
|
std::vector<OUString> SdPageObjsTLV::GetSelectEntryList(const int nDepth) const
|
|
{
|
|
std::vector<OUString> aEntries;
|
|
|
|
m_xTreeView->selected_foreach([this, nDepth, &aEntries](weld::TreeIter& rEntry){
|
|
int nListDepth = m_xTreeView->get_iter_depth(rEntry);
|
|
if (nListDepth == nDepth)
|
|
aEntries.push_back(m_xTreeView->get_text(rEntry));
|
|
return false;
|
|
});
|
|
|
|
return aEntries;
|
|
}
|
|
|
|
std::vector<OUString> SdPageObjsTLV::GetSelectedEntryIds() const
|
|
{
|
|
std::vector<OUString> vEntryIds;
|
|
|
|
m_xTreeView->selected_foreach([this, &vEntryIds](weld::TreeIter& rEntry){
|
|
vEntryIds.push_back(m_xTreeView->get_id(rEntry));
|
|
return false;
|
|
});
|
|
|
|
return vEntryIds;
|
|
}
|
|
|
|
/**
|
|
* Checks if it is a draw file and opens the BookmarkDoc depending of
|
|
* the provided Docs
|
|
*/
|
|
SdDrawDocument* SdPageObjsTLV::GetBookmarkDoc(SfxMedium* pMed)
|
|
{
|
|
if (
|
|
!m_pBookmarkDoc ||
|
|
(pMed && (!m_pOwnMedium || m_pOwnMedium->GetName() != pMed->GetName()))
|
|
)
|
|
{
|
|
// create a new BookmarkDoc if now one exists or if a new Medium is provided
|
|
if (m_pOwnMedium != pMed)
|
|
{
|
|
CloseBookmarkDoc();
|
|
}
|
|
|
|
if (pMed)
|
|
{
|
|
// it looks that it is undefined if a Medium was set by Fill() already
|
|
DBG_ASSERT( !m_pMedium, "SfxMedium confusion!" );
|
|
delete m_pMedium;
|
|
m_pMedium = nullptr;
|
|
|
|
// take over this Medium (currently used only be Navigator)
|
|
m_pOwnMedium = pMed;
|
|
}
|
|
|
|
DBG_ASSERT( m_pMedium || pMed, "No SfxMedium provided!" );
|
|
|
|
if( pMed )
|
|
{
|
|
// in this mode the document is also owned and controlled by this instance
|
|
m_xBookmarkDocShRef = new ::sd::DrawDocShell(SfxObjectCreateMode::STANDARD, true, DocumentType::Impress);
|
|
if (m_xBookmarkDocShRef->DoLoad(pMed))
|
|
m_pBookmarkDoc = m_xBookmarkDocShRef->GetDoc();
|
|
else
|
|
m_pBookmarkDoc = nullptr;
|
|
}
|
|
else if ( m_pMedium )
|
|
// in this mode the document is owned and controlled by the SdDrawDocument
|
|
// it can be released by calling the corresponding CloseBookmarkDoc method
|
|
// successful creation of a document makes this the owner of the medium
|
|
m_pBookmarkDoc = const_cast<SdDrawDocument*>(m_pDoc)->OpenBookmarkDoc(m_pMedium);
|
|
|
|
if ( !m_pBookmarkDoc )
|
|
{
|
|
std::unique_ptr<weld::MessageDialog> xErrorBox(Application::CreateMessageDialog(m_xTreeView.get(),
|
|
VclMessageType::Warning, VclButtonsType::Ok, SdResId(STR_READ_DATA_ERROR)));
|
|
xErrorBox->run();
|
|
m_pMedium = nullptr; //On failure the SfxMedium is invalid
|
|
}
|
|
}
|
|
|
|
return m_pBookmarkDoc;
|
|
}
|
|
|
|
/**
|
|
* Entries are inserted only by request (double click)
|
|
*/
|
|
IMPL_LINK(SdPageObjsTLV, RequestingChildrenHdl, const weld::TreeIter&, rFileEntry, bool)
|
|
{
|
|
if (!m_xTreeView->iter_has_child(rFileEntry))
|
|
{
|
|
if (GetBookmarkDoc())
|
|
{
|
|
SdrObject* pObj = nullptr;
|
|
|
|
OUString sImgPage(BMP_PAGE);
|
|
OUString sImgPageObjs(BMP_PAGEOBJS);
|
|
OUString sImgObjects(BMP_OBJECTS);
|
|
OUString sImgOle(BMP_OLE);
|
|
OUString sImgGraphic(BMP_GRAPHIC);
|
|
|
|
// document name already inserted
|
|
|
|
// only insert all "normal" ? slides with objects
|
|
sal_uInt16 nPage = 0;
|
|
const sal_uInt16 nMaxPages = m_pBookmarkDoc->GetPageCount();
|
|
|
|
std::unique_ptr<weld::TreeIter> xPageEntry;
|
|
while (nPage < nMaxPages)
|
|
{
|
|
SdPage* pPage = static_cast<SdPage*>(m_pBookmarkDoc->GetPage(nPage));
|
|
if (pPage->GetPageKind() == PageKind::Standard)
|
|
{
|
|
OUString sId(OUString::number(1));
|
|
m_xTreeView->insert(&rFileEntry, -1, &pPage->GetName(), &sId,
|
|
nullptr, nullptr, false, m_xScratchIter.get());
|
|
m_xTreeView->set_image(*m_xScratchIter, sImgPage);
|
|
|
|
if (!xPageEntry)
|
|
{
|
|
xPageEntry = m_xTreeView->make_iterator(&rFileEntry);
|
|
(void)m_xTreeView->iter_children(*xPageEntry);
|
|
}
|
|
else
|
|
(void)m_xTreeView->iter_next_sibling(*xPageEntry);
|
|
|
|
SdrObjListIter aIter( pPage, SdrIterMode::DeepWithGroups );
|
|
|
|
while( aIter.IsMore() )
|
|
{
|
|
pObj = aIter.Next();
|
|
OUString aStr( GetObjectName( pObj ) );
|
|
if( !aStr.isEmpty() )
|
|
{
|
|
if( pObj->GetObjInventor() == SdrInventor::Default && pObj->GetObjIdentifier() == SdrObjKind::OLE2 )
|
|
{
|
|
m_xTreeView->insert(xPageEntry.get(), -1, &aStr, nullptr,
|
|
nullptr, nullptr, false, m_xScratchIter.get());
|
|
m_xTreeView->set_image(*m_xScratchIter, sImgOle);
|
|
}
|
|
else if( pObj->GetObjInventor() == SdrInventor::Default && pObj->GetObjIdentifier() == SdrObjKind::Graphic )
|
|
{
|
|
m_xTreeView->insert(xPageEntry.get(), -1, &aStr, nullptr,
|
|
nullptr, nullptr, false, m_xScratchIter.get());
|
|
m_xTreeView->set_image(*m_xScratchIter, sImgGraphic);
|
|
}
|
|
else
|
|
{
|
|
m_xTreeView->insert(xPageEntry.get(), -1, &aStr, nullptr,
|
|
nullptr, nullptr, false, m_xScratchIter.get());
|
|
m_xTreeView->set_image(*m_xScratchIter, sImgObjects);
|
|
}
|
|
}
|
|
}
|
|
if (m_xTreeView->iter_has_child(*xPageEntry))
|
|
{
|
|
m_xTreeView->set_image(*xPageEntry, sImgPageObjs);
|
|
}
|
|
}
|
|
nPage++;
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void SdPageObjsTLV::SetSdNavigator(SdNavigatorWin* pNavigator)
|
|
{
|
|
m_pNavigator = pNavigator;
|
|
}
|
|
|
|
void SdPageObjsTLV::SetViewFrame(const SfxViewFrame* pViewFrame)
|
|
{
|
|
if (sd::ViewShellBase* pBase = sd::ViewShellBase::GetViewShellBase(pViewFrame))
|
|
{
|
|
css::uno::Reference< css::frame::XFrame > xFrame;
|
|
if (std::shared_ptr<sd::ViewShell> xViewShell = pBase->GetMainViewShell())
|
|
{
|
|
if (SfxViewFrame* pFrame = xViewShell->GetViewFrame())
|
|
xFrame = pFrame->GetFrame().GetFrameInterface();
|
|
}
|
|
m_xAccel->init(::comphelper::getProcessComponentContext(), xFrame);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Close and delete bookmark document
|
|
*/
|
|
void SdPageObjsTLV::CloseBookmarkDoc()
|
|
{
|
|
if (m_xBookmarkDocShRef.is())
|
|
{
|
|
m_xBookmarkDocShRef->DoClose();
|
|
m_xBookmarkDocShRef.clear();
|
|
|
|
// Medium is owned by document, so it's destroyed already
|
|
m_pOwnMedium = nullptr;
|
|
}
|
|
else if (m_pBookmarkDoc)
|
|
{
|
|
DBG_ASSERT(!m_pOwnMedium, "SfxMedium confusion!");
|
|
if (m_pDoc)
|
|
{
|
|
// The document owns the Medium, so the Medium will be invalid after closing the document
|
|
const_cast<SdDrawDocument*>(m_pDoc)->CloseBookmarkDoc();
|
|
m_pMedium = nullptr;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// perhaps mpOwnMedium provided, but no successful creation of BookmarkDoc
|
|
delete m_pOwnMedium;
|
|
m_pOwnMedium = nullptr;
|
|
}
|
|
|
|
m_pBookmarkDoc = nullptr;
|
|
}
|
|
|
|
bool SdPageObjsTLV::PageBelongsToCurrentShow(const SdPage* pPage) const
|
|
{
|
|
// Return <TRUE/> as default when there is no custom show or when none
|
|
// is used. The page does then belong to the standard show.
|
|
bool bBelongsToShow = true;
|
|
|
|
if (m_pDoc->getPresentationSettings().mbCustomShow)
|
|
{
|
|
// Get the current custom show.
|
|
SdCustomShow* pCustomShow = nullptr;
|
|
SdCustomShowList* pShowList = const_cast<SdDrawDocument*>(m_pDoc)->GetCustomShowList();
|
|
if (pShowList != nullptr)
|
|
{
|
|
sal_uLong nCurrentShowIndex = pShowList->GetCurPos();
|
|
pCustomShow = (*pShowList)[nCurrentShowIndex].get();
|
|
}
|
|
|
|
// Check whether the given page is part of that custom show.
|
|
if (pCustomShow != nullptr)
|
|
{
|
|
bBelongsToShow = false;
|
|
size_t nPageCount = pCustomShow->PagesVector().size();
|
|
for (size_t i=0; i<nPageCount && !bBelongsToShow; i++)
|
|
if (pPage == pCustomShow->PagesVector()[i])
|
|
bBelongsToShow = true;
|
|
}
|
|
}
|
|
|
|
return bBelongsToShow;
|
|
}
|
|
|
|
void SdPageObjsTLV::AddShapeList (
|
|
const SdrObjList& rList,
|
|
const SdrObject* pShape,
|
|
const OUString& rsName,
|
|
const bool bIsExcluded,
|
|
const weld::TreeIter* pParentEntry)
|
|
{
|
|
OUString aIcon(BMP_PAGE);
|
|
if (bIsExcluded)
|
|
aIcon = BMP_PAGE_EXCLUDED;
|
|
else if (pShape != nullptr)
|
|
aIcon = BMP_GROUP;
|
|
|
|
OUString aUserData(u"1"_ustr);
|
|
if (pShape != nullptr)
|
|
aUserData = weld::toId(pShape);
|
|
|
|
std::unique_ptr<weld::TreeIter> xEntry = m_xTreeView->make_iterator();
|
|
InsertEntry(pParentEntry, aUserData, rsName, aIcon, xEntry.get());
|
|
|
|
SdrObjListIter aIter(
|
|
&rList,
|
|
!rList.HasObjectNavigationOrder() /* use navigation order, if available */,
|
|
SdrIterMode::Flat);
|
|
|
|
while( aIter.IsMore() )
|
|
{
|
|
SdrObject* pObj = aIter.Next();
|
|
assert(pObj!=nullptr);
|
|
|
|
// Get the shape name.
|
|
OUString aStr (GetObjectName( pObj ) );
|
|
OUString sId(weld::toId(pObj));
|
|
|
|
if( !aStr.isEmpty() )
|
|
{
|
|
if( pObj->GetObjInventor() == SdrInventor::Default && pObj->GetObjIdentifier() == SdrObjKind::OLE2 )
|
|
{
|
|
InsertEntry(xEntry.get(), sId, aStr, BMP_OLE);
|
|
}
|
|
else if( pObj->GetObjInventor() == SdrInventor::Default && pObj->GetObjIdentifier() == SdrObjKind::Graphic )
|
|
{
|
|
InsertEntry(xEntry.get(), sId, aStr, BMP_GRAPHIC);
|
|
}
|
|
else if (pObj->IsGroupObject())
|
|
{
|
|
AddShapeList(
|
|
*pObj->GetSubList(),
|
|
pObj,
|
|
aStr,
|
|
false,
|
|
xEntry.get());
|
|
}
|
|
else
|
|
{
|
|
InsertEntry(xEntry.get(), sId, aStr, BMP_OBJECTS); // BMP_OBJECTS
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!m_xTreeView->iter_has_child(*xEntry))
|
|
return;
|
|
|
|
if (bIsExcluded)
|
|
m_xTreeView->set_image(*xEntry, BMP_PAGEOBJS_EXCLUDED);
|
|
else
|
|
m_xTreeView->set_image(*xEntry, BMP_PAGEOBJS);
|
|
m_xTreeView->expand_row(*xEntry);
|
|
}
|
|
|
|
/**
|
|
* Fill TreeLB with pages and objects
|
|
*/
|
|
void SdPageObjsTLV::Fill(const SdDrawDocument* pInDoc, bool bAllPages, const OUString& rDocName)
|
|
{
|
|
OUString aSelection = m_xTreeView->get_selected_text();
|
|
clear();
|
|
|
|
m_pDoc = pInDoc;
|
|
m_aDocName = rDocName;
|
|
m_bShowAllPages = bAllPages;
|
|
m_pMedium = nullptr;
|
|
|
|
// first insert all pages including objects
|
|
sal_uInt16 nPage = 0;
|
|
const sal_uInt16 nMaxPages = m_pDoc->GetPageCount();
|
|
|
|
PageKind eDrawViewShellPageKind = PageKind::Standard;
|
|
if (sd::DrawViewShell* pDrawViewShell = lcl_getDrawViewShell(m_pDoc))
|
|
eDrawViewShellPageKind = pDrawViewShell->GetPageKind();
|
|
|
|
while( nPage < nMaxPages )
|
|
{
|
|
const SdPage* pPage = static_cast<const SdPage*>( m_pDoc->GetPage( nPage ) );
|
|
PageKind ePagePageKind = pPage->GetPageKind();
|
|
if ((m_bShowAllPages ||
|
|
(ePagePageKind == PageKind::Standard &&
|
|
eDrawViewShellPageKind == PageKind::Standard) ||
|
|
(ePagePageKind == PageKind::Notes &&
|
|
eDrawViewShellPageKind == PageKind::Notes)) &&
|
|
ePagePageKind != PageKind::Handout) //#94954# never list the normal handout page ( handout-masterpage is used instead )
|
|
{
|
|
bool bPageExcluded = pPage->IsExcluded();
|
|
|
|
bool bPageBelongsToShow = PageBelongsToCurrentShow (pPage);
|
|
bPageExcluded |= !bPageBelongsToShow;
|
|
|
|
AddShapeList(*pPage, nullptr, pPage->GetName(), bPageExcluded, nullptr);
|
|
}
|
|
nPage++;
|
|
}
|
|
|
|
// then insert all master pages including objects
|
|
if( m_bShowAllPages )
|
|
{
|
|
nPage = 0;
|
|
const sal_uInt16 nMaxMasterPages = m_pDoc->GetMasterPageCount();
|
|
|
|
while( nPage < nMaxMasterPages )
|
|
{
|
|
const SdPage* pPage = static_cast<const SdPage*>( m_pDoc->GetMasterPage( nPage ) );
|
|
AddShapeList(*pPage, nullptr, pPage->GetName(), false, nullptr);
|
|
nPage++;
|
|
}
|
|
}
|
|
if (!aSelection.isEmpty())
|
|
{
|
|
m_xTreeView->all_foreach([this, &aSelection](weld::TreeIter& rEntry){
|
|
if (m_xTreeView->get_text(rEntry) == aSelection)
|
|
{
|
|
m_xTreeView->select(rEntry);
|
|
return true;
|
|
}
|
|
return false;
|
|
});
|
|
}
|
|
}
|
|
|
|
/**
|
|
* We insert only the first entry. Children are created on demand.
|
|
*/
|
|
void SdPageObjsTLV::Fill( const SdDrawDocument* pInDoc, SfxMedium* pInMedium,
|
|
const OUString& rDocName )
|
|
{
|
|
m_pDoc = pInDoc;
|
|
|
|
// this object now owns the Medium
|
|
m_pMedium = pInMedium;
|
|
m_aDocName = rDocName;
|
|
|
|
OUString sId(OUString::number(1));
|
|
// insert document name
|
|
m_xTreeView->insert(nullptr, -1, &m_aDocName, &sId, nullptr, nullptr, true, m_xScratchIter.get());
|
|
m_xTreeView->set_image(*m_xScratchIter, BMP_DOC_OPEN);
|
|
}
|
|
|
|
/**
|
|
* select an entry in TreeLB
|
|
*/
|
|
bool SdPageObjsTLV::SelectEntry( std::u16string_view rName )
|
|
{
|
|
bool bFound = false;
|
|
|
|
if (!rName.empty())
|
|
{
|
|
std::unique_ptr<weld::TreeIter> xEntry(m_xTreeView->make_iterator());
|
|
OUString aTmp;
|
|
|
|
if (m_xTreeView->get_iter_first(*xEntry))
|
|
{
|
|
do
|
|
{
|
|
aTmp = m_xTreeView->get_text(*xEntry);
|
|
if (aTmp == rName)
|
|
{
|
|
m_xTreeView->set_cursor(*xEntry);
|
|
m_xTreeView->select(*xEntry);
|
|
bFound = true;
|
|
break;
|
|
}
|
|
}
|
|
while (m_xTreeView->iter_next(*xEntry));
|
|
}
|
|
}
|
|
|
|
return bFound;
|
|
}
|
|
|
|
void SdPageObjsTLV::SelectEntry(const SdrObject *pObj)
|
|
{
|
|
if (pObj)
|
|
{
|
|
m_xTreeView->all_foreach([this, &pObj](weld::TreeIter& rEntry){
|
|
if (weld::fromId<SdrObject*>(m_xTreeView->get_id(rEntry)) == pObj)
|
|
{
|
|
// Only scroll to the row of the first selected. And only when the treeview
|
|
// doesn't have the focus.
|
|
if (!m_xTreeView->has_focus() && m_xTreeView->get_selected_rows().empty())
|
|
m_xTreeView->set_cursor(rEntry);
|
|
m_xTreeView->select(rEntry);
|
|
return true;
|
|
}
|
|
return false;
|
|
});
|
|
}
|
|
}
|
|
|
|
SdPageObjsTLV::~SdPageObjsTLV()
|
|
{
|
|
if (m_nSelectEventId)
|
|
Application::RemoveUserEvent(m_nSelectEventId);
|
|
if (m_nRowActivateEventId)
|
|
Application::RemoveUserEvent(m_nRowActivateEventId);
|
|
|
|
if (m_pBookmarkDoc)
|
|
CloseBookmarkDoc();
|
|
else
|
|
{
|
|
// no document was created from m_pMedium, so this object is still the owner of it
|
|
delete m_pMedium;
|
|
}
|
|
m_xAccel.reset();
|
|
}
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|