2015-09-06 11:29:03 +02:00
/* -*- 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 <svx/svdotext.hxx>
# include <svx/svdoutl.hxx>
# include <editeng/outlobj.hxx>
# include <editeng/editobj.hxx>
# include <editeng/overflowingtxt.hxx>
# include <svx/textchainflow.hxx>
TextChainFlow : : TextChainFlow ( SdrTextObj * pChainTarget )
: mpTargetLink ( pChainTarget )
{
2015-09-20 01:42:12 +02:00
SAL_INFO ( " svx.chaining " , " [TEXTCHAINFLOW] Creating a new TextChainFlow " ) ;
2015-09-06 11:29:03 +02:00
mpTextChain = mpTargetLink - > GetTextChain ( ) ;
mpNextLink = mpTargetLink - > GetNextLinkInChain ( ) ;
bUnderflow = bOverflow = false ;
mbOFisUFinduced = false ;
2015-11-10 10:25:28 +01:00
mpOverflChText = nullptr ;
mpUnderflChText = nullptr ;
2015-09-06 11:29:03 +02:00
mbPossiblyCursorOut = false ;
}
TextChainFlow : : ~ TextChainFlow ( )
{
2017-05-31 15:40:25 +02:00
delete mpOverflChText ;
delete mpUnderflChText ;
2015-09-06 11:29:03 +02:00
}
void TextChainFlow : : impSetFlowOutlinerParams ( SdrOutliner * , SdrOutliner * )
{
// Nothing to do if not in editing mode
}
/*
* Check for overflow in the state of pFlowOutl .
* If pParamOutl is not NULL sets some parameters from there .
* This is useful in case the outliner is not set for overflow
* ( e . g . in editing mode we check for overflow in drawing outl but
* parameters come from editing outliner )
*/
void TextChainFlow : : impCheckForFlowEvents ( SdrOutliner * pFlowOutl , SdrOutliner * pParamOutl )
{
bool bOldUpdateMode = pFlowOutl - > GetUpdateMode ( ) ;
// XXX: This could be reorganized moving most of this stuff inside EditingTextChainFlow
2015-11-10 10:25:28 +01:00
if ( pParamOutl ! = nullptr )
2015-09-06 11:29:03 +02:00
{
// We need this since it's required to check overflow
pFlowOutl - > SetUpdateMode ( true ) ;
// XXX: does this work if you do it before setting the text? Seems so.
impSetFlowOutlinerParams ( pFlowOutl , pParamOutl ) ;
}
bool bIsPageOverflow = pFlowOutl - > IsPageOverflow ( ) ;
// NOTE: overflow and underflow cannot be both true
bOverflow = bIsPageOverflow & & mpNextLink ;
bUnderflow = ! bIsPageOverflow & & mpNextLink & & mpNextLink - > HasText ( ) ;
// Get old state on whether to merge para-s or not
// NOTE: We handle UF/OF using the _old_ state. The new one is simply saved
bool bMustMergeParaAmongLinks = GetTextChain ( ) - > GetIsPartOfLastParaInNextLink ( mpTargetLink ) ;
// Set (Non)OverflowingTxt here (if any)
// If we had an underflow before we have to deep merge paras anyway
bool bMustMergeParaOF = bMustMergeParaAmongLinks | | mbOFisUFinduced ;
mpOverflChText = bOverflow ?
new OFlowChainedText ( pFlowOutl , bMustMergeParaOF ) :
2015-11-10 10:25:28 +01:00
nullptr ;
2015-09-06 11:29:03 +02:00
// Set current underflowing text (if any)
mpUnderflChText = bUnderflow ?
new UFlowChainedText ( pFlowOutl , bMustMergeParaAmongLinks ) :
2015-11-10 10:25:28 +01:00
nullptr ;
2015-09-06 11:29:03 +02:00
// Reset update mode // Reset it here because we use WriteRTF (needing updatemode = true) in the two constructors above
if ( ! bOldUpdateMode ) // Reset only if the old value was false
pFlowOutl - > SetUpdateMode ( bOldUpdateMode ) ;
// NOTE: Must be called after mp*ChText abd b*flow have been set but before mbOFisUFinduced is reset
impUpdateCursorInfo ( ) ;
// To check whether an overflow is underflow induced or not (useful in cursor checking)
mbOFisUFinduced = bUnderflow ;
}
void TextChainFlow : : impUpdateCursorInfo ( )
{
// XXX: Maybe we can get rid of mbOFisUFinduced by not allowing handling of more than one event by the same TextChainFlow
// if this is not an OF triggered during an UF
mbPossiblyCursorOut = bOverflow ;
if ( mbPossiblyCursorOut ) {
2017-05-22 15:55:38 +02:00
maOverflowPosSel = mpOverflChText - > GetOverflowPointSel ( ) ;
2015-09-06 11:29:03 +02:00
ESelection aSelAtUFTime = GetTextChain ( ) - > GetPreChainingSel ( GetLinkTarget ( ) ) ;
// Might be an invalid selection if the cursor at UF time was before
// the (possibly UF-induced) Overflowing point but we don't use it in that case
maPostChainingSel = ESelection ( aSelAtUFTime . nStartPara - maOverflowPosSel . nStartPara ,
aSelAtUFTime . nStartPos - maOverflowPosSel . nStartPos ) ;
}
// XXX: It may not be necessary anymore to keep this method separated from EditingTextChainFlow::impBroadcastCursorInfo
}
void TextChainFlow : : CheckForFlowEvents ( SdrOutliner * pFlowOutl )
{
2015-11-10 10:25:28 +01:00
impCheckForFlowEvents ( pFlowOutl , nullptr ) ;
2015-09-06 11:29:03 +02:00
}
bool TextChainFlow : : IsOverflow ( ) const
{
return bOverflow ;
}
bool TextChainFlow : : IsUnderflow ( ) const
{
return bUnderflow ;
}
// XXX: In editing mode you need to get "underflowing" text from editing outliner, so it's kinda separate from the drawing one!
2015-09-29 18:10:33 +02:00
// XXX:Would it be possible to unify underflow and its possibly following overflow?
2015-09-06 11:29:03 +02:00
void TextChainFlow : : ExecuteUnderflow ( SdrOutliner * pOutl )
{
//GetTextChain()->SetNilChainingEvent(mpTargetLink, true);
// making whole text
2015-09-29 10:13:18 +01:00
bool bNewTextTransferred = false ;
2016-10-26 14:59:38 +02:00
// merges underflowing text with the one in the next box
OutlinerParaObject * pNewText = mpUnderflChText - > CreateMergedUnderflowParaObject ( pOutl , mpNextLink - > GetOutlinerParaObject ( ) ) ;
2015-09-06 11:29:03 +02:00
// Set the other box empty; it will be replaced by the rest of the text if overflow occurs
if ( ! mpTargetLink - > GetPreventChainable ( ) )
mpNextLink - > NbcSetOutlinerParaObject ( pOutl - > GetEmptyParaObject ( ) ) ;
// We store the size since NbcSetOutlinerParaObject can change it
2015-09-06 12:06:47 +02:00
//Size aOldSize = pOutl->GetMaxAutoPaperSize();
2015-09-06 11:29:03 +02:00
// This should not be done in editing mode!! //XXX
if ( ! mpTargetLink - > IsInEditMode ( ) )
2015-09-29 10:13:18 +01:00
{
2015-09-06 11:29:03 +02:00
mpTargetLink - > NbcSetOutlinerParaObject ( pNewText ) ;
2015-09-29 10:13:18 +01:00
bNewTextTransferred = true ;
}
2015-09-06 11:29:03 +02:00
// Restore size and set new text
2015-09-06 12:06:47 +02:00
//pOutl->SetMaxAutoPaperSize(aOldSize); // XXX (it seems to be working anyway without this)
2015-09-06 11:29:03 +02:00
pOutl - > SetText ( * pNewText ) ;
//GetTextChain()->SetNilChainingEvent(mpTargetLink, false);
2015-09-29 10:13:18 +01:00
if ( ! bNewTextTransferred )
delete pNewText ;
2015-09-06 11:29:03 +02:00
// Check for new overflow
CheckForFlowEvents ( pOutl ) ;
}
void TextChainFlow : : ExecuteOverflow ( SdrOutliner * pNonOverflOutl , SdrOutliner * pOverflOutl )
{
//GetTextChain()->SetNilChainingEvent(mpTargetLink, true);
// Leave only non overflowing text
impLeaveOnlyNonOverflowingText ( pNonOverflOutl ) ;
// Transfer of text to next link
if ( ! mpTargetLink - > GetPreventChainable ( ) ) // we don't transfer text while dragging because of resizing
{
impMoveChainedTextToNextLink ( pOverflOutl ) ;
}
//GetTextChain()->SetNilChainingEvent(mpTargetLink, false);
}
void TextChainFlow : : impLeaveOnlyNonOverflowingText ( SdrOutliner * pNonOverflOutl )
{
OutlinerParaObject * pNewText = mpOverflChText - > RemoveOverflowingText ( pNonOverflOutl ) ;
2015-09-20 01:42:12 +02:00
SAL_INFO ( " svx.chaining " , " [TEXTCHAINFLOW - OF] SOURCE box set to "
< < pNewText - > GetTextObject ( ) . GetParagraphCount ( ) < < " paras " ) ;
2015-09-06 11:29:03 +02:00
// adds it to current outliner anyway (useful in static decomposition)
pNonOverflOutl - > SetText ( * pNewText ) ;
mpTargetLink - > NbcSetOutlinerParaObject ( pNewText ) ;
// For some reason the paper size is lost after last instruction, so we set it.
pNonOverflOutl - > SetPaperSize ( Size ( pNonOverflOutl - > GetPaperSize ( ) . Width ( ) ,
pNonOverflOutl - > GetTextHeight ( ) ) ) ;
}
void TextChainFlow : : impMoveChainedTextToNextLink ( SdrOutliner * pOverflOutl )
{
// prevent copying text in same box
if ( mpNextLink = = mpTargetLink ) {
2015-09-20 01:42:12 +02:00
SAL_INFO ( " svx.chaining " , " [CHAINING] Trying to copy text for next link in same object " ) ;
2015-09-06 11:29:03 +02:00
return ;
}
OutlinerParaObject * pNewText =
mpOverflChText - > InsertOverflowingText ( pOverflOutl ,
mpNextLink - > GetOutlinerParaObject ( ) ) ;
2015-09-20 01:42:12 +02:00
SAL_INFO ( " svx.chaining " , " [TEXTCHAINFLOW - OF] DEST box set to "
< < pNewText - > GetTextObject ( ) . GetParagraphCount ( ) < < " paras " ) ;
2015-09-06 11:29:03 +02:00
if ( pNewText )
mpNextLink - > NbcSetOutlinerParaObject ( pNewText ) ;
// Set Deep Merge status
2015-09-20 01:42:12 +02:00
SAL_INFO ( " svx.chaining " , " [DEEPMERGE] Setting deepMerge to "
< < mpOverflChText - > IsLastParaInterrupted ( ) ) ;
2015-09-06 11:29:03 +02:00
GetTextChain ( ) - > SetIsPartOfLastParaInNextLink (
mpTargetLink ,
mpOverflChText - > IsLastParaInterrupted ( ) ) ;
}
SdrTextObj * TextChainFlow : : GetLinkTarget ( ) const
{
return mpTargetLink ;
}
TextChain * TextChainFlow : : GetTextChain ( ) const
{
return mpTextChain ;
}
// EditingTextChainFlow
EditingTextChainFlow : : EditingTextChainFlow ( SdrTextObj * pLinkTarget ) :
TextChainFlow ( pLinkTarget )
{
2015-09-20 01:42:12 +02:00
SAL_INFO ( " svx.chaining " , " [TEXTCHAINFLOW] Creating a new EditingTextChainFlow " ) ;
2015-09-06 11:29:03 +02:00
}
void EditingTextChainFlow : : CheckForFlowEvents ( SdrOutliner * pFlowOutl )
{
// if this is editing outliner no need to set parameters
if ( pFlowOutl = = GetLinkTarget ( ) - > pEdtOutl )
2015-11-10 10:25:28 +01:00
impCheckForFlowEvents ( pFlowOutl , nullptr ) ;
2015-09-06 11:29:03 +02:00
else
impCheckForFlowEvents ( pFlowOutl , GetLinkTarget ( ) - > pEdtOutl ) ;
// Broadcast events for cursor handling
impBroadcastCursorInfo ( ) ;
}
void EditingTextChainFlow : : impLeaveOnlyNonOverflowingText ( SdrOutliner * pNonOverflOutl )
{
2015-09-29 10:27:15 +01:00
OutlinerParaObject * pNewText = mpOverflChText - > RemoveOverflowingText ( pNonOverflOutl ) ;
delete pNewText ;
2015-09-06 11:29:03 +02:00
//impSetTextForEditingOutliner(pNewText); //XXX: Don't call it since we do everything with NonOverflowingText::ToParaObject // XXX: You may need this for Underflow
// XXX: I'm not sure whether we need this (after all operations such as Paste don't change this - as far as I understand)
//GetLinkTarget()->NbcSetOutlinerParaObject(pNewText);
}
void EditingTextChainFlow : : impSetFlowOutlinerParams ( SdrOutliner * pFlowOutl , SdrOutliner * pParamOutl )
{
// Set right size for overflow
pFlowOutl - > SetMaxAutoPaperSize ( pParamOutl - > GetMaxAutoPaperSize ( ) ) ;
pFlowOutl - > SetMinAutoPaperSize ( pParamOutl - > GetMinAutoPaperSize ( ) ) ;
pFlowOutl - > SetPaperSize ( pParamOutl - > GetPaperSize ( ) ) ;
}
void EditingTextChainFlow : : impBroadcastCursorInfo ( ) const
{
ESelection aPreChainingSel = GetTextChain ( ) - > GetPreChainingSel ( GetLinkTarget ( ) ) ;
// Test whether the cursor is out of the box.
2017-09-28 13:06:51 +02:00
bool bCursorOut = mbPossiblyCursorOut & & maOverflowPosSel < aPreChainingSel ;
2015-09-06 11:29:03 +02:00
// NOTE: I handled already the stuff for the comments below. They will be kept temporarily till stuff settles down.
// Possibility: 1) why don't we stop passing the actual event to the TextChain and instead we pass
// the overflow pos and mbPossiblyCursorOut
// 2) We pass the current selection before anything happens and we make impBroadcastCursorInfo compute it.
if ( bCursorOut ) {
//maCursorEvent = CursorChainingEvent::TO_NEXT_LINK;
GetTextChain ( ) - > SetPostChainingSel ( GetLinkTarget ( ) , maPostChainingSel ) ;
GetTextChain ( ) - > SetCursorEvent ( GetLinkTarget ( ) , CursorChainingEvent : : TO_NEXT_LINK ) ;
} else {
//maCursorEvent = CursorChainingEvent::UNCHANGED;
GetTextChain ( ) - > SetPostChainingSel ( GetLinkTarget ( ) , aPreChainingSel ) ;
GetTextChain ( ) - > SetCursorEvent ( GetLinkTarget ( ) , CursorChainingEvent : : UNCHANGED ) ;
}
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */