/* -*- 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 .
*/
if (mrOutliner.GetViewCount() == 0)
{ // initialize Outliner: set Reference Device
bInitOutliner = true;
mrOutliner.Init( OutlinerMode::OutlineView );
mrOutliner.SetRefDevice(SdModule::get()->GetVirtualRefDevice()); //viewsize without the width of the image and number in front
mnPaperWidth = (mrOutlineViewShell.GetActiveWindow()->GetViewSize().Width() - 4000);
mrOutliner.SetPaperSize(Size(mnPaperWidth, 400000000));
} else
{ // width: DIN A4, two margins at 1 cm each
mnPaperWidth = 19000;
}
mpOutlinerViews[0].reset( new OutlinerView(mrOutliner, pWindow) );
mpOutlinerViews[0]->SetOutputArea(::tools::Rectangle());
mrOutliner.SetUpdateLayout(false);
mrOutliner.InsertView(mpOutlinerViews[0].get(), EE_APPEND);
onUpdateStyleSettings( true );
if (bInitOutliner)
{ // fill Outliner with contents
FillOutliner();
}
// Tell undo manager of the document about the undo manager of the // outliner, so that the former can synchronize with the later.
sd::UndoManager* pDocUndoMgr = dynamic_cast<sd::UndoManager*>(mpDocSh->GetUndoManager()); if (pDocUndoMgr != nullptr)
pDocUndoMgr->SetLinkedUndoManager(&mrOutliner.GetUndoManager());
}
// unregister OutlinerViews and destroy them for (auto & rpView : mpOutlinerViews)
{ if (rpView)
{
mrOutliner.RemoveView( rpView.get() );
rpView.reset();
}
}
if (mrOutliner.GetViewCount() == 0)
{ // uninitialize Outliner: enable color display
ResetLinks();
EEControlBits nCntrl = mrOutliner.GetControlWord();
mrOutliner.SetUpdateLayout(false); // otherwise there will be drawn on SetControlWord
mrOutliner.SetControlWord(nCntrl & ~EEControlBits::NOCOLORS);
mrOutliner.ForceAutoColor( officecfg::Office::Common::Accessibility::IsAutomaticFontColor::get() );
mrOutliner.Clear();
}
}
void OutlineView::ConnectToApplication()
{ // When the mode is switched to outline the main view shell grabs focus. // This is done for getting cut/copy/paste commands on slides in the left // pane (slide sorter view shell) to work properly.
SfxShell* pTopViewShell = mrOutlineViewShell.GetViewShellBase().GetViewShellManager()->GetTopViewShell(); if (pTopViewShell && pTopViewShell == &mrOutlineViewShell)
{
mrOutlineViewShell.GetActiveWindow()->GrabFocus();
}
/** * Return a pointer to the OutlinerView corresponding to the window
*/
OutlinerView* OutlineView::GetViewByWindow (vcl::Window const * pWin) const
{
OutlinerView* pOlView = nullptr; for (std::unique_ptr<OutlinerView> const & pView : mpOutlinerViews)
{ if (pView != nullptr)
{ if ( pWin == pView->GetWindow() )
{
pOlView = pView.get();
}
}
} return pOlView;
}
/** * Return the title before a random paragraph
*/
Paragraph* OutlineView::GetPrevTitle(const Paragraph* pPara)
{
sal_Int32 nPos = mrOutliner.GetAbsPos(pPara);
/** * Return the title after a random paragraph
*/
Paragraph* OutlineView::GetNextTitle(const Paragraph* pPara)
{
Paragraph* pResult = const_cast< Paragraph* >( pPara );
/** * Handler for inserting pages (paragraphs)
*/
IMPL_LINK( OutlineView, ParagraphInsertedHdl, Outliner::ParagraphHdlParam, aParam, void )
{ // we get calls to this handler during binary insert of drag and drop contents but // we ignore it here and handle it later in OnEndPasteOrDrop() if (maDragAndDropModelGuard != nullptr) return;
/** creates and inserts an empty slide for the given paragraph */
SdPage* OutlineView::InsertSlideForParagraph( Paragraph* pPara )
{
DBG_ASSERT( isRecordingUndo(), "sd::OutlineView::InsertSlideForParagraph(), model change without undo?!" );
OutlineViewPageChangesGuard aGuard(this);
mrOutliner.SetParaFlag( pPara, ParaFlag::ISPAGE ); // how many titles are there before the new title paragraph?
sal_uLong nExample = 0; // position of the "example" page
sal_uLong nTarget = 0; // position of insertion while(pPara)
{
pPara = GetPrevTitle(pPara); if (pPara)
nTarget++;
}
// if a new paragraph is created via RETURN before the first paragraph, the // Outliner reports the old paragraph (which was moved down) as a new // paragraph if (nTarget == 1)
{
OUString aTest = mrOutliner.GetText(mrOutliner.GetParagraph(0)); if (aTest.isEmpty())
{
nTarget = 0;
}
}
// the "example" page is the previous page - if it is available if (nTarget > 0)
{
nExample = nTarget - 1;
/********************************************************************** * All the time, a standard page is created before a notes page. * It is ensured that after each standard page the corresponding notes page * follows. A handout page is exactly one handout page.
**********************************************************************/
// this page is exemplary
SdPage* pExample = mrDoc.GetSdPage(static_cast<sal_uInt16>(nExample), PageKind::Standard);
rtl::Reference<SdPage> pPage = mrDoc.AllocSdPage(false);
// assign a master page to the notes page
pNotesPage->TRG_SetMasterPage(pExample->TRG_GetMasterPage());
// set page size, there must be already one page available
pNotesPage->SetSize(pExample->GetSize());
pNotesPage->SetBorder( pExample->GetLeftBorder(),
pExample->GetUpperBorder(),
pExample->GetRightBorder(),
pExample->GetLowerBorder() );
// how many titles are in front of the title paragraph in question?
sal_uLong nPos = 0; while(pPara)
{
pPara = GetPrevTitle(pPara); if (pPara) nPos++;
}
/** * Handler for changing the indentation depth of paragraphs (requires inserting * or deleting of pages in some cases)
*/
IMPL_LINK( OutlineView, DepthChangedHdl, ::Outliner::DepthChangeHdlParam, aParam, void )
{
DBG_ASSERT( isRecordingUndo(), "sd::OutlineView::DepthChangedHdl(), no undo for model change?!" );
OutlineViewPageChangesGuard aGuard(this);
Paragraph* pPara = aParam.pPara;
::Outliner* pOutliner = aParam.pOutliner; if( ::Outliner::HasParaFlag( pPara, ParaFlag::ISPAGE ) && ((aParam.nPrevFlags & ParaFlag::ISPAGE) == ParaFlag::NONE) )
{ // the current paragraph is transformed into a slide
mrOutliner.SetDepth( pPara, -1 );
// are multiple level 1 paragraphs being brought to level 0 and we // should start a progress view or a timer and didn't already? if (mnPagesToProcess == 0)
{
Window* pActWin = mrOutlineViewShell.GetActiveWindow();
OutlinerView* pOlView = GetViewByWindow(pActWin);
// should there be a progress display? if (mnPagesToProcess > PROCESS_WITH_PROGRESS_THRESHOLD)
{ if (mpProgress)
mpProgress->SetState(mnPagesProcessed);
}
// was this the last page? if (mnPagesProcessed == mnPagesToProcess)
{ if (mnPagesToProcess > PROCESS_WITH_PROGRESS_THRESHOLD && mpProgress)
{
mpProgress.reset();
} else
mpDocSh->SetWaitCursor( false );
mnPagesToProcess = 0;
mnPagesProcessed = 0;
}
pOutliner->UpdateFields();
} elseif( !::Outliner::HasParaFlag( pPara, ParaFlag::ISPAGE ) && ((aParam.nPrevFlags & ParaFlag::ISPAGE) != ParaFlag::NONE) )
{ // the paragraph was a page but now becomes a normal paragraph
// how many titles are before the title paragraph in question?
sal_uLong nPos = 0;
Paragraph* pParagraph = pPara; while(pParagraph)
{
pParagraph = GetPrevTitle(pParagraph); if (pParagraph)
nPos++;
} // delete page and notes page
// progress display if necessary if (mnPagesToProcess)
{
mnPagesProcessed++; if (mpProgress)
mpProgress->SetState(mnPagesProcessed);
if (mnPagesProcessed == mnPagesToProcess)
{
mpProgress.reset();
mnPagesToProcess = 0;
mnPagesProcessed = 0;
}
}
pOutliner->UpdateFields();
} elseif ( (pOutliner->GetPrevDepth() == 1) && ( pOutliner->GetDepth( pOutliner->GetAbsPos( pPara ) ) == 2 ) )
{ // how many titles are in front of the title paragraph in question?
sal_Int32 nPos = -1;
// before we set the style sheet we need to preserve the bullet item // since all items will be deleted while setting a new style sheet
SfxItemSet aOldAttrs( pOutliner->GetParaAttribs( nPara ) );
pOutliner->SetStyleSheet( nPara, pStyleSheet );
// restore the old bullet item but not if the style changed const SvxNumBulletItem* pBulletItem = nullptr; if ( pOutliner->GetPrevDepth() != -1 && nDepth != -1 &&
aOldAttrs.GetItemState( EE_PARA_NUMBULLET, true, &pBulletItem ) == SfxItemState::SET )
{
SfxItemSet aAttrs( pOutliner->GetParaAttribs( nPara ) );
aAttrs.Put( *pBulletItem );
pOutliner->SetParaAttribs( nPara, aAttrs );
}
}
/** * Handler for the start of a paragraph movement
*/
IMPL_LINK( OutlineView, BeginMovingHdl, ::Outliner *, pOutliner, void )
{
OutlineViewPageChangesGuard aGuard(this);
// list of selected title paragraphs
mpOutlinerViews[0]->CreateSelectionList(maSelectedParas);
/** * Handler for the end of a paragraph movement
*/
IMPL_LINK( OutlineView, EndMovingHdl, ::Outliner *, pOutliner, void )
{
OutlineViewPageChangesGuard aGuard(this);
DBG_ASSERT( isRecordingUndo(), "sd::OutlineView::EndMovingHdl(), model change without undo?!" );
// look for insertion position via the first paragraph
Paragraph* pSearchIt = maSelectedParas.empty() ? nullptr : *(maSelectedParas.begin());
// look for the first of the selected paragraphs in the new ordering
sal_uInt16 nPosNewOrder = 0;
sal_Int32 nParaPos = 0;
Paragraph* pPara = pOutliner->GetParagraph( 0 );
Paragraph* pPrev = nullptr; while (pPara && pPara != pSearchIt)
{ if( ::Outliner::HasParaFlag(pPara, ParaFlag::ISPAGE) )
{
nPosNewOrder++;
pPrev = pPara;
}
pPara = pOutliner->GetParagraph( ++nParaPos );
}
sal_uInt16 nPos = nPosNewOrder; // don't change nPosNewOrder if (nPos == 0)
{
nPos = sal_uInt16(-1); // insert before the first page
} else
{ // look for the predecessor in the old ordering
std::vector<Paragraph*>::const_iterator it = std::find(maOldParaOrder.begin(),
maOldParaOrder.end(),
pPrev);
/** * Look for the title text object in one page of the model
*/
SdrTextObj* OutlineView::GetTitleTextObject(SdrPage const * pPage)
{
SdrTextObj* pResult = nullptr;
/** * Look for the outline text object in one page of the model
*/
SdrTextObj* OutlineView::GetOutlineTextObject(SdrPage const * pPage)
{
SdrTextObj* pResult = nullptr;
SdrTextObj* OutlineView::CreateTitleTextObject(SdPage* pPage)
{
DBG_ASSERT( GetTitleTextObject(pPage) == nullptr, "sd::OutlineView::CreateTitleTextObject(), there is already a title text object!" );
if( pPage->GetAutoLayout() == AUTOLAYOUT_NONE )
{ // simple case
pPage->SetAutoLayout( AUTOLAYOUT_TITLE_ONLY, true );
} else
{ // we already have a layout with a title but the title // object was deleted, create a new one
pPage->InsertAutoLayoutShape( nullptr, PresObjKind::Title, false, pPage->GetTitleRect(), true );
}
return GetTitleTextObject(pPage);
}
SdrTextObj* OutlineView::CreateOutlineTextObject(SdPage* pPage)
{
DBG_ASSERT( GetOutlineTextObject(pPage) == nullptr, "sd::OutlineView::CreateOutlineTextObject(), there is already a layout text object!" );
AutoLayout eNewLayout = pPage->GetAutoLayout(); switch( eNewLayout )
{ case AUTOLAYOUT_NONE: case AUTOLAYOUT_TITLE_ONLY: case AUTOLAYOUT_TITLE: eNewLayout = AUTOLAYOUT_TITLE_CONTENT; break;
case AUTOLAYOUT_CHART: eNewLayout = AUTOLAYOUT_CHARTTEXT; break;
case AUTOLAYOUT_ORG: case AUTOLAYOUT_TAB: case AUTOLAYOUT_OBJ: eNewLayout = AUTOLAYOUT_OBJTEXT; break; default: break;
}
if( eNewLayout != pPage->GetAutoLayout() )
{
pPage->SetAutoLayout( eNewLayout, true );
} else
{ // we already have a layout with a text but the text // object was deleted, create a new one
pPage->InsertAutoLayoutShape( nullptr,
PresObjKind::Outline, false, pPage->GetLayoutRect(), true );
}
return GetOutlineTextObject(pPage);
}
/** updates draw model with all changes from outliner model */ void OutlineView::PrepareClose()
{
::sd::UndoManager* pDocUndoMgr = dynamic_cast<sd::UndoManager*>(mpDocSh->GetUndoManager()); if (pDocUndoMgr != nullptr)
pDocUndoMgr->SetLinkedUndoManager(nullptr);
/** * Set attributes of the selected text
*/ bool OutlineView::SetAttributes(const SfxItemSet& rSet, bool/*bSlide*/, bool /*bReplaceAll*/, bool /*bMaster*/)
{ bool bOk = false;
/** returns the first slide that is selected in the outliner or where
the cursor is located */
SdPage* OutlineView::GetActualPage()
{
::sd::Window* pWin = mrOutlineViewShell.GetActiveWindow();
OutlinerView* pActiveView = GetViewByWindow(pWin);
Paragraph* OutlineView::GetParagraphForPage( ::Outliner const & rOutl, SdPage const* pPage )
{ // get the number of paragraphs with ident 0 we need to skip before // we find the actual page
sal_uInt16 nPageNum = pPage->GetPageNum();
assert(nPageNum > 0);
sal_uInt32 nPagesToSkip = (nPageNum - 1) >> 1;
sal_Int32 nParaPos = 0;
Paragraph* pPara = rOutl.GetParagraph( 0 ); while( pPara )
{ // if this paragraph is a page... if( ::Outliner::HasParaFlag(pPara,ParaFlag::ISPAGE) )
{ // see if we already skipped enough pages if( 0 == nPagesToSkip ) break; // and if so, end the loop
// we skipped another page
nPagesToSkip--;
}
// get next paragraph
pPara = mrOutliner.GetParagraph( ++nParaPos );
}
return pPara;
}
/** selects the paragraph for the given page at the outliner view*/ void OutlineView::SetActualPage( SdPage const * pActual )
{ if( pActual && mrOutliner.GetIgnoreCurrentPageChangesLevel()==0 && !mbFirstPaint)
{ // if we found a paragraph, select its text at the outliner view
Paragraph* pPara = GetParagraphForPage( mrOutliner, pActual ); if( pPara )
mpOutlinerViews[0]->Select( pPara );
}
}
/** * Get StyleSheet from the selection
*/
SfxStyleSheet* OutlineView::GetStyleSheet() const
{
::sd::Window* pActWin = mrOutlineViewShell.GetActiveWindow();
OutlinerView* pOlView = GetViewByWindow(pActWin);
SfxStyleSheet* pResult = pOlView->GetStyleSheet(); return pResult;
}
/** * Mark pages as selected / not selected
*/ void OutlineView::SetSelectedPages()
{ // list of selected title paragraphs
std::vector<Paragraph*> aSelParas;
mpOutlinerViews[0]->CreateSelectionList(aSelParas);
// Re-implement GetScriptType for this view to get correct results
SvtScriptType OutlineView::GetScriptType() const
{
SvtScriptType nScriptType = ::sd::View::GetScriptType();
/** call this method before you do anything that can modify the outliner
and or the drawing document model. It will create needed undo actions */ void OutlineView::BeginModelChange()
{
mrOutliner.GetUndoManager().EnterListAction(u""_ustr, u""_ustr, 0, mrOutlineViewShell.GetViewShellBase().GetViewShellId());
BegUndo(SdResId(STR_UNDO_CHANGE_TITLE_AND_LAYOUT));
}
/** call this method after BeginModelChange(), when all possible model
changes are done. */ void OutlineView::EndModelChange()
{
UpdateDocument();
// find the top EditUndo action in the top undo action list
size_t nAction = pListAction->maUndoActions.size();
EditUndo* pEditUndo = nullptr; while( !pEditUndo && nAction )
{
pEditUndo = dynamic_cast< EditUndo* >(pListAction->GetUndoAction(--nAction));
}
sal_uInt16 nEditPos = nAction; // we need this later to remove the merged undo actions
// make sure it is the only EditUndo action in the top undo list while( pEditUndo && nAction )
{ if( dynamic_cast< EditUndo* >(pListAction->GetUndoAction(--nAction)) )
pEditUndo = nullptr;
}
// do we have one and only one EditUndo action in the top undo list? if( !pEditUndo ) return;
// yes, see if we can merge it with the prev undo list
// ok we merged the only EditUndo of the top undo list with // the top EditUndo of the previous undo list
// first remove the merged undo action
assert( pListAction->GetUndoAction(nEditPos) == pEditUndo && "sd::OutlineView::TryToMergeUndoActions(), wrong edit pos!" );
pListAction->Remove(nEditPos);
if ( !pListAction->maUndoActions.empty() )
{ // now we have to move all remaining doc undo actions from the top undo // list to the previous undo list and remove the top undo list
// paint slide number if( !(pPara && ::Outliner::HasParaFlag(pPara,ParaFlag::ISPAGE)) ) return;
::tools::Long nPage = 0; // todo, printing?? for ( sal_Int32 n = 0; n <= pInfo->mnPara; n++ )
{
Paragraph* p = mrOutliner.GetParagraph( n ); if ( ::Outliner::HasParaFlag(p,ParaFlag::ISPAGE) )
nPage++;
}
/** this is called after a paste or drop operation, make sure that the newly inserted paragraphs
get the correct style sheet and new slides are inserted. */ void OutlineView::OnEndPasteOrDrop( PasteOrDropInfos* pInfo )
{
SdPage* pPage = nullptr;
SfxStyleSheetBasePool* pStylePool = GetDoc().GetStyleSheetPool();
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.