blob: 8a2403ef6bb991d3de633fdaf2d90918b82d2ef6 [file] [log] [blame]
/**************************************************************
*
* 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
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_svx.hxx"
#include <svl/style.hxx>
#include <svx/svdotext.hxx>
#include "svx/svditext.hxx"
#include <svx/svdmodel.hxx> // fuer GetMaxObjSize und GetStyleSheetPool
#include <svx/svdoutl.hxx>
#include <svx/svdorect.hxx> // fuer SetDirty bei NbcAdjustTextFrameWidthAndHeight
#include <svx/svdocapt.hxx> // fuer SetDirty bei NbcAdjustTextFrameWidthAndHeight
#include <svx/svdetc.hxx>
#include <editeng/writingmodeitem.hxx>
#include <editeng/editeng.hxx>
#include <editeng/eeitem.hxx>
#include <editeng/flditem.hxx>
#include <svx/sdtfchim.hxx>
#include <editeng/editview.hxx>
#include <svl/smplhint.hxx>
#include <svl/whiter.hxx>
#include <editeng/outlobj.hxx>
#include <editeng/outliner.hxx>
#include <editeng/eeitem.hxx>
#include <editeng/editobj.hxx>
#include <editeng/fhgtitem.hxx>
#include <editeng/charscaleitem.hxx>
#include <svl/style.hxx>
#include <svl/itemiter.hxx>
#include <editeng/lrspitem.hxx>
#include <svl/itempool.hxx>
#include <editeng/numitem.hxx>
#include <editeng/editeng.hxx>
#include <editeng/postitem.hxx>
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// @@@@@@ @@@@@ @@ @@ @@@@@@ @@@@ @@@@@ @@@@@@
// @@ @@ @@@ @@@ @@ @@ @@ @@ @@ @@
// @@ @@ @@@@@ @@ @@ @@ @@ @@ @@
// @@ @@@@ @@@ @@ @@ @@ @@@@@ @@
// @@ @@ @@@@@ @@ @@ @@ @@ @@ @@
// @@ @@ @@@ @@@ @@ @@ @@ @@ @@ @@ @@
// @@ @@@@@ @@ @@ @@ @@@@ @@@@@ @@@@
//
// Attribute, StyleSheets und AutoGrow
//
////////////////////////////////////////////////////////////////////////////////////////////////////
FASTBOOL SdrTextObj::AdjustTextFrameWidthAndHeight(Rectangle& rR, FASTBOOL bHgt, FASTBOOL bWdt) const
{
if (bTextFrame && pModel!=NULL && !rR.IsEmpty())
{
SdrFitToSizeType eFit=GetFitToSize();
FASTBOOL bFitToSize=(eFit==SDRTEXTFIT_PROPORTIONAL || eFit==SDRTEXTFIT_ALLLINES);
FASTBOOL bWdtGrow=bWdt && IsAutoGrowWidth();
FASTBOOL bHgtGrow=bHgt && IsAutoGrowHeight();
SdrTextAniKind eAniKind=GetTextAniKind();
SdrTextAniDirection eAniDir=GetTextAniDirection();
FASTBOOL bScroll=eAniKind==SDRTEXTANI_SCROLL || eAniKind==SDRTEXTANI_ALTERNATE || eAniKind==SDRTEXTANI_SLIDE;
FASTBOOL bHScroll=bScroll && (eAniDir==SDRTEXTANI_LEFT || eAniDir==SDRTEXTANI_RIGHT);
FASTBOOL bVScroll=bScroll && (eAniDir==SDRTEXTANI_UP || eAniDir==SDRTEXTANI_DOWN);
if (!bFitToSize && (bWdtGrow || bHgtGrow))
{
Rectangle aR0(rR);
long nHgt=0,nMinHgt=0,nMaxHgt=0;
long nWdt=0,nMinWdt=0,nMaxWdt=0;
Size aSiz(rR.GetSize()); aSiz.Width()--; aSiz.Height()--;
Size aMaxSiz(100000,100000);
Size aTmpSiz(pModel->GetMaxObjSize());
if (aTmpSiz.Width()!=0) aMaxSiz.Width()=aTmpSiz.Width();
if (aTmpSiz.Height()!=0) aMaxSiz.Height()=aTmpSiz.Height();
if (bWdtGrow)
{
nMinWdt=GetMinTextFrameWidth();
nMaxWdt=GetMaxTextFrameWidth();
if (nMaxWdt==0 || nMaxWdt>aMaxSiz.Width()) nMaxWdt=aMaxSiz.Width();
if (nMinWdt<=0) nMinWdt=1;
aSiz.Width()=nMaxWdt;
}
if (bHgtGrow)
{
nMinHgt=GetMinTextFrameHeight();
nMaxHgt=GetMaxTextFrameHeight();
if (nMaxHgt==0 || nMaxHgt>aMaxSiz.Height()) nMaxHgt=aMaxSiz.Height();
if (nMinHgt<=0) nMinHgt=1;
aSiz.Height()=nMaxHgt;
}
long nHDist=GetTextLeftDistance()+GetTextRightDistance();
long nVDist=GetTextUpperDistance()+GetTextLowerDistance();
aSiz.Width()-=nHDist;
aSiz.Height()-=nVDist;
if (aSiz.Width()<2) aSiz.Width()=2; // Mindestgroesse 2
if (aSiz.Height()<2) aSiz.Height()=2; // Mindestgroesse 2
// #101684#
sal_Bool bInEditMode = IsInEditMode();
if(!bInEditMode)
{
if (bHScroll) aSiz.Width()=0x0FFFFFFF; // Laufschrift nicht umbrechen
if (bVScroll) aSiz.Height()=0x0FFFFFFF;
}
if(pEdtOutl)
{
pEdtOutl->SetMaxAutoPaperSize(aSiz);
if (bWdtGrow) {
Size aSiz2(pEdtOutl->CalcTextSize());
nWdt=aSiz2.Width()+1; // lieber etwas Tolleranz
if (bHgtGrow) nHgt=aSiz2.Height()+1; // lieber etwas Tolleranz
} else {
nHgt=pEdtOutl->GetTextHeight()+1; // lieber etwas Tolleranz
}
} else {
Outliner& rOutliner=ImpGetDrawOutliner();
rOutliner.SetPaperSize(aSiz);
rOutliner.SetUpdateMode(sal_True);
// !!! hier sollte ich wohl auch noch mal die Optimierung mit
// bPortionInfoChecked usw einbauen
OutlinerParaObject* pOutlinerParaObject = GetOutlinerParaObject();
if ( pOutlinerParaObject != NULL )
{
rOutliner.SetText(*pOutlinerParaObject);
rOutliner.SetFixedCellHeight(((const SdrTextFixedCellHeightItem&)GetMergedItem(SDRATTR_TEXT_USEFIXEDCELLHEIGHT)).GetValue());
}
if (bWdtGrow)
{
Size aSiz2(rOutliner.CalcTextSize());
nWdt=aSiz2.Width()+1; // lieber etwas Tolleranz
if (bHgtGrow) nHgt=aSiz2.Height()+1; // lieber etwas Tolleranz
} else {
nHgt=rOutliner.GetTextHeight()+1; // lieber etwas Tolleranz
}
rOutliner.Clear();
}
if (nWdt<nMinWdt) nWdt=nMinWdt;
if (nWdt>nMaxWdt) nWdt=nMaxWdt;
nWdt+=nHDist;
if (nWdt<1) nWdt=1; // nHDist kann auch negativ sein
if (nHgt<nMinHgt) nHgt=nMinHgt;
if (nHgt>nMaxHgt) nHgt=nMaxHgt;
nHgt+=nVDist;
if (nHgt<1) nHgt=1; // nVDist kann auch negativ sein
long nWdtGrow=nWdt-(rR.Right()-rR.Left());
long nHgtGrow=nHgt-(rR.Bottom()-rR.Top());
if (nWdtGrow==0) bWdtGrow=sal_False;
if (nHgtGrow==0) bHgtGrow=sal_False;
if (bWdtGrow || bHgtGrow) {
if (bWdtGrow) {
SdrTextHorzAdjust eHAdj=GetTextHorizontalAdjust();
if (eHAdj==SDRTEXTHORZADJUST_LEFT) rR.Right()+=nWdtGrow;
else if (eHAdj==SDRTEXTHORZADJUST_RIGHT) rR.Left()-=nWdtGrow;
else {
long nWdtGrow2=nWdtGrow/2;
rR.Left()-=nWdtGrow2;
rR.Right()=rR.Left()+nWdt;
}
}
if (bHgtGrow) {
SdrTextVertAdjust eVAdj=GetTextVerticalAdjust();
if (eVAdj==SDRTEXTVERTADJUST_TOP) rR.Bottom()+=nHgtGrow;
else if (eVAdj==SDRTEXTVERTADJUST_BOTTOM) rR.Top()-=nHgtGrow;
else {
long nHgtGrow2=nHgtGrow/2;
rR.Top()-=nHgtGrow2;
rR.Bottom()=rR.Top()+nHgt;
}
}
if (aGeo.nDrehWink!=0) {
Point aD1(rR.TopLeft());
aD1-=aR0.TopLeft();
Point aD2(aD1);
RotatePoint(aD2,Point(),aGeo.nSin,aGeo.nCos);
aD2-=aD1;
rR.Move(aD2.X(),aD2.Y());
}
return sal_True;
}
}
}
return sal_False;
}
FASTBOOL SdrTextObj::NbcAdjustTextFrameWidthAndHeight(FASTBOOL bHgt, FASTBOOL bWdt)
{
FASTBOOL bRet=AdjustTextFrameWidthAndHeight(aRect,bHgt,bWdt);
if (bRet) {
SetRectsDirty();
if (HAS_BASE(SdrRectObj,this)) { // mal wieder 'nen Hack
((SdrRectObj*)this)->SetXPolyDirty();
}
if (HAS_BASE(SdrCaptionObj,this)) { // mal wieder 'nen Hack
((SdrCaptionObj*)this)->ImpRecalcTail();
}
}
return bRet;
}
FASTBOOL SdrTextObj::AdjustTextFrameWidthAndHeight(FASTBOOL bHgt, FASTBOOL bWdt)
{
Rectangle aNeuRect(aRect);
FASTBOOL bRet=AdjustTextFrameWidthAndHeight(aNeuRect,bHgt,bWdt);
if (bRet) {
Rectangle aBoundRect0; if (pUserCall!=NULL) aBoundRect0=GetLastBoundRect();
// #110094#-14 SendRepaintBroadcast();
aRect=aNeuRect;
SetRectsDirty();
if (HAS_BASE(SdrRectObj,this)) { // mal wieder 'nen Hack
((SdrRectObj*)this)->SetXPolyDirty();
}
if (HAS_BASE(SdrCaptionObj,this)) { // mal wieder 'nen Hack
((SdrCaptionObj*)this)->ImpRecalcTail();
}
SetChanged();
BroadcastObjectChange();
SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0);
}
return bRet;
}
void SdrTextObj::ImpSetTextStyleSheetListeners()
{
SfxStyleSheetBasePool* pStylePool=pModel!=NULL ? pModel->GetStyleSheetPool() : NULL;
if (pStylePool!=NULL)
{
Container aStyles(1024,64,64);
OutlinerParaObject* pOutlinerParaObject = GetOutlinerParaObject();
if (pOutlinerParaObject!=NULL)
{
// Zunaechst werden alle im ParaObject enthaltenen StyleSheets
// im Container aStyles gesammelt. Dazu wird die Family jeweils
// ans Ende des StyleSheet-Namen drangehaengt.
const EditTextObject& rTextObj=pOutlinerParaObject->GetTextObject();
XubString aStyleName;
SfxStyleFamily eStyleFam;
sal_uInt16 nParaAnz=rTextObj.GetParagraphCount();
for(sal_uInt16 nParaNum(0); nParaNum < nParaAnz; nParaNum++)
{
rTextObj.GetStyleSheet(nParaNum, aStyleName, eStyleFam);
if(aStyleName.Len())
{
XubString aFam = UniString::CreateFromInt32((sal_uInt16)eStyleFam);
aFam.Expand(5);
aStyleName += sal_Unicode('|');
aStyleName += aFam;
sal_Bool bFnd(sal_False);
sal_uInt32 nNum(aStyles.Count());
while(!bFnd && nNum > 0)
{
// kein StyleSheet doppelt!
nNum--;
bFnd = (aStyleName.Equals(*(XubString*)aStyles.GetObject(nNum)));
}
if(!bFnd)
{
aStyles.Insert(new XubString(aStyleName), CONTAINER_APPEND);
}
}
}
}
// nun die Strings im Container durch StyleSheet* ersetzten
sal_uIntPtr nNum=aStyles.Count();
while (nNum>0) {
nNum--;
XubString* pName=(XubString*)aStyles.GetObject(nNum);
// UNICODE: String aFam(pName->Cut(pName->Len()-6));
String aFam = pName->Copy(0, pName->Len() - 6);
aFam.Erase(0,1);
aFam.EraseTrailingChars();
// UNICODE: sal_uInt16 nFam=sal_uInt16(aFam);
sal_uInt16 nFam = (sal_uInt16)aFam.ToInt32();
SfxStyleFamily eFam=(SfxStyleFamily)nFam;
SfxStyleSheetBase* pStyleBase=pStylePool->Find(*pName,eFam);
SfxStyleSheet* pStyle=PTR_CAST(SfxStyleSheet,pStyleBase);
delete pName;
if (pStyle!=NULL && pStyle!=GetStyleSheet()) {
aStyles.Replace(pStyle,nNum);
} else {
aStyles.Remove(nNum);
}
}
// jetzt alle ueberfluessigen StyleSheets entfernen
nNum=GetBroadcasterCount();
while (nNum>0) {
nNum--;
SfxBroadcaster* pBroadcast=GetBroadcasterJOE((sal_uInt16)nNum);
SfxStyleSheet* pStyle=PTR_CAST(SfxStyleSheet,pBroadcast);
if (pStyle!=NULL && pStyle!=GetStyleSheet()) { // Sonderbehandlung fuer den StyleSheet des Objekts
if (aStyles.GetPos(pStyle)==CONTAINER_ENTRY_NOTFOUND) {
EndListening(*pStyle);
}
}
}
// und schliesslich alle in aStyles enthaltenen StyleSheets mit den vorhandenen Broadcastern mergen
nNum=aStyles.Count();
while (nNum>0) {
nNum--;
SfxStyleSheet* pStyle=(SfxStyleSheet*)aStyles.GetObject(nNum);
// StartListening soll selbst nachsehen, ob hier nicht evtl. schon gehorcht wird
StartListening(*pStyle,sal_True);
}
}
}
void SdrTextObj::NbcResizeTextAttributes(const Fraction& xFact, const Fraction& yFact)
{
OutlinerParaObject* pOutlinerParaObject = GetOutlinerParaObject();
if (pOutlinerParaObject!=NULL && xFact.IsValid() && yFact.IsValid())
{
Fraction n100(100,1);
long nX=long(xFact*n100);
long nY=long(yFact*n100);
if (nX<0) nX=-nX;
if (nX<1) nX=1;
if (nX>0xFFFF) nX=0xFFFF;
if (nY<0) nY=-nY;
if (nY<1) nY=1;
if (nY>0xFFFF) nY=0xFFFF;
if (nX!=100 || nY!=100)
{
// Rahmenattribute
const SfxItemSet& rSet = GetObjectItemSet();
const SvxCharScaleWidthItem& rOldWdt=(SvxCharScaleWidthItem&)rSet.Get(EE_CHAR_FONTWIDTH);
const SvxFontHeightItem& rOldHgt=(SvxFontHeightItem&)rSet.Get(EE_CHAR_FONTHEIGHT);
// erstmal die alten Werte holen
long nRelWdt=rOldWdt.GetValue();
long nAbsHgt=rOldHgt.GetHeight();
long nRelHgt=rOldHgt.GetProp();
// Relative Breite aendern
nRelWdt*=nX;
nRelWdt/=nY;
if (nRelWdt<0) nRelWdt=-nRelWdt; // nicht negativ
if (nRelWdt<=0) nRelWdt=1; // und mind. 1%
if (nRelWdt>0xFFFF) nRelWdt=0xFFFF;
// Absolute Hoehe aendern
nAbsHgt*=nY;
nAbsHgt/=100;
if (nAbsHgt<0) nAbsHgt=-nAbsHgt; // nicht negativ
if (nAbsHgt<=0) nAbsHgt=1; // und mind. 1
if (nAbsHgt>0xFFFF) nAbsHgt=0xFFFF;
// und nun attributieren
SetObjectItem(SvxCharScaleWidthItem( (sal_uInt16) nRelWdt, EE_CHAR_FONTWIDTH));
SetObjectItem(SvxFontHeightItem(nAbsHgt,(sal_uInt16)nRelHgt, EE_CHAR_FONTHEIGHT));
// Zeichen- und Absatzattribute innerhalb des OutlinerParaObjects
Outliner& rOutliner=ImpGetDrawOutliner();
rOutliner.SetPaperSize(Size(LONG_MAX,LONG_MAX));
rOutliner.SetText(*pOutlinerParaObject);
rOutliner.DoStretchChars((sal_uInt16)nX,(sal_uInt16)nY);
OutlinerParaObject* pNewPara=rOutliner.CreateParaObject();
NbcSetOutlinerParaObject(pNewPara);
rOutliner.Clear();
}
}
}
/** #103836# iterates over the paragraphs of a given SdrObject and removes all
hard set character attributes with the which ids contained in the
given vector
*/
void SdrTextObj::RemoveOutlinerCharacterAttribs( const std::vector<sal_uInt16>& rCharWhichIds )
{
sal_Int32 nText = getTextCount();
while( --nText >= 0 )
{
SdrText* pText = getText( nText );
OutlinerParaObject* pOutlinerParaObject = pText ? pText->GetOutlinerParaObject() : 0;
if(pOutlinerParaObject)
{
Outliner* pOutliner = 0;
if( pEdtOutl || (pText == getActiveText()) )
pOutliner = pEdtOutl;
if(!pOutliner)
{
pOutliner = &ImpGetDrawOutliner();
pOutliner->SetText(*pOutlinerParaObject);
}
ESelection aSelAll( 0, 0, 0xffff, 0xffff );
std::vector<sal_uInt16>::const_iterator aIter( rCharWhichIds.begin() );
while( aIter != rCharWhichIds.end() )
{
pOutliner->RemoveAttribs( aSelAll, false, (*aIter++) );
}
if(!pEdtOutl || (pText != getActiveText()) )
{
const sal_uInt32 nParaCount = pOutliner->GetParagraphCount();
OutlinerParaObject* pTemp = pOutliner->CreateParaObject(0, (sal_uInt16)nParaCount);
pOutliner->Clear();
NbcSetOutlinerParaObjectForText(pTemp, pText);
}
}
}
}
bool SdrTextObj::HasText() const
{
if( pEdtOutl )
return HasEditText();
OutlinerParaObject* pOPO = GetOutlinerParaObject();
bool bHasText = false;
if( pOPO )
{
const EditTextObject& rETO = pOPO->GetTextObject();
sal_uInt16 nParaCount = rETO.GetParagraphCount();
if( nParaCount > 0 )
bHasText = (nParaCount > 1) || (rETO.GetText( 0 ).Len() != 0);
}
return bHasText;
}