--- a/sfx2/inc/sfx2/ipclient.hxx +++ a/sfx2/inc/sfx2/ipclient.hxx @@ -101,6 +101,7 @@ // used in Writer // Rectangle PixelObjVisAreaToLogic( const Rectangle & rObjRect ) const; // Rectangle LogicObjAreaToPixel( const Rectangle & rRect ) const; + virtual void FormatChanged(); // object format was changed (used for StarMath formulas aligning) }; #endif --- a/sfx2/source/view/ipclient.cxx +++ a/sfx2/source/view/ipclient.cxx @@ -214,6 +214,7 @@ if ( m_pClient && aEvent.EventName.equalsAscii("OnVisAreaChanged") && m_nAspect != embed::Aspects::MSOLE_ICON ) { + m_pClient->FormatChanged(); // for Writer when format of the object is changed with the area m_pClient->ViewChanged(); m_pClient->Invalidate(); } @@ -1074,6 +1075,11 @@ // dummy implementation } +void SfxInPlaceClient::FormatChanged() +{ + // dummy implementation +} + void SfxInPlaceClient::DeactivateObject() { if ( GetObject().is() ) --- a/starmath/inc/node.hxx +++ a/starmath/inc/node.hxx @@ -180,6 +180,9 @@ const SmNode * FindTokenAt(USHORT nRow, USHORT nCol) const; const SmNode * FindRectClosestTo(const Point &rPoint) const; + // --> 4.7.2010 #i972# + virtual long GetFormulaBaseline() const { return (long)0; } //dummy, used in SmTableNode + // <-- }; @@ -467,6 +470,9 @@ class SmTableNode : public SmStructureNode { + // --> 4.7.2010 #i972# + long nFormulaBaseline; + // <-- public: SmTableNode(const SmToken &rNodeToken) : SmStructureNode(NTABLE, rNodeToken) @@ -476,6 +482,7 @@ virtual SmNode * GetLeftMost(); virtual void Arrange(const OutputDevice &rDev, const SmFormat &rFormat); + long GetFormulaBaseline() const { return nFormulaBaseline; } }; --- a/starmath/source/node.cxx +++ a/starmath/source/node.cxx @@ -760,7 +760,7 @@ } Point aPos; - SmRect::operator = (SmRect(nMaxWidth, 0)); + SmRect::operator = (SmRect(nMaxWidth, 1)); for (i = 0; i < nSize; i++) { if (NULL != (pNode = GetSubNode(i))) { const SmRect &rNodeRect = pNode->GetRect(); @@ -776,6 +776,22 @@ ExtendBy(rNodeRect, nSize > 1 ? RCP_NONE : RCP_ARG); } } + // --> 4.7.2010 #i972# + if (HasBaseline()) + nFormulaBaseline = GetBaseline(); + else + { + SmTmpDevice aTmpDev ((OutputDevice &) rDev, TRUE); + aTmpDev.SetFont(GetFont()); + + SmRect aRect = (SmRect(aTmpDev, &rFormat, C2S("a"), + GetFont().GetBorderWidth())); + nFormulaBaseline = GetAlignM(); + // move from middle position by constant - distance + // between middle and baseline for single letter + nFormulaBaseline+= aRect.GetBaseline() - aRect.GetAlignM(); + } + // <-- } @@ -815,20 +831,21 @@ SmTmpDevice aTmpDev ((OutputDevice &) rDev, TRUE); aTmpDev.SetFont(GetFont()); - // provide an empty rectangle with alignment parameters for the "current" - // font (in order to make "a^1 {}_2^3 a_4" work correct, that is, have the - // same sub-/supscript positions.) - //! be sure to use a character that has explicitly defined HiAttribut - //! line in rect.cxx such as 'a' in order to make 'vec a' look same to - //! 'vec {a}'. - SmRect::operator = (SmRect(aTmpDev, &rFormat, C2S("a"), - GetFont().GetBorderWidth())); - // make sure that the rectangle occupies (almost) no space - SetWidth(1); - SetItalicSpaces(0, 0); - - if (nSize < 1) - return; + if (nSize < 1) + { + // provide an empty rectangle with alignment parameters for the "current" + // font (in order to make "a^1 {}_2^3 a_4" work correct, that is, have the + // same sub-/supscript positions.) + //! be sure to use a character that has explicitly defined HiAttribut + //! line in rect.cxx such as 'a' in order to make 'vec a' look same to + //! 'vec {a}'. + SmRect::operator = (SmRect(aTmpDev, &rFormat, C2S("a"), + GetFont().GetBorderWidth())); + // make sure that the rectangle occupies (almost) no space + SetWidth(1); + SetItalicSpaces(0, 0); + return; + } // make distance depend on font size long nDist = (rFormat.GetDistance(DIS_HORIZONTAL) * GetFont().GetSize().Height()) / 100L; @@ -836,7 +853,11 @@ nDist = 0; Point aPos; - for (i = 0; i < nSize; i++) + // copy the first node into LineNode and extend by the others + if (NULL != (pNode = GetSubNode(0))) + SmRect::operator = (pNode->GetRect()); + + for (i = 1; i < nSize; i++) if (NULL != (pNode = GetSubNode(i))) { aPos = pNode->AlignTo(*this, RP_RIGHT, RHA_CENTER, RVA_BASELINE); --- a/starmath/source/unomodel.cxx +++ a/starmath/source/unomodel.cxx @@ -237,7 +237,8 @@ // --> PB 2004-08-25 #i33095# Security Options HANDLE_LOAD_READONLY, // <-- - HANDLE_DIALOG_LIBRARIES // #i73329# + HANDLE_DIALOG_LIBRARIES, // #i73329# + HANDLE_BASELINE // 3.7.2010 #i972# }; PropertySetInfo * lcl_createModelPropertyInfo () @@ -308,6 +309,9 @@ // --> PB 2004-08-25 #i33095# Security Options { RTL_CONSTASCII_STRINGPARAM( "LoadReadonly" ), HANDLE_LOAD_READONLY, &::getBooleanCppuType(), PROPERTY_NONE, 0 }, // <-- + // --> 3.7.2010 #i972# + { RTL_CONSTASCII_STRINGPARAM( "BaseLine"), HANDLE_BASELINE, &::getCppuType((const sal_Int16*)0), PROPERTY_NONE, 0}, + // <-- { NULL, 0, 0, NULL, 0, 0 } }; PropertySetInfo *pInfo = new PropertySetInfo ( aModelPropertyInfoMap ); @@ -939,6 +943,21 @@ break; } // <-- + // --> 3.7.2010 #i972# + case HANDLE_BASELINE: + { + if ( !pDocSh->pTree ) + pDocSh->Parse(); + if ( pDocSh->pTree ) + { + if ( !pDocSh->IsFormulaArranged() ) + pDocSh->ArrangeFormula(); + + *pValue <<= static_cast( pDocSh->pTree->GetFormulaBaseline() ); + } + } + break; + // <-- } } } --- a/sw/inc/fesh.hxx +++ a/sw/inc/fesh.hxx @@ -549,6 +549,18 @@ BOOL ReplaceSdrObj( const String& rGrfName, const String& rFltName, const Graphic* pGrf = 0 ); + // --> #i972# + // Sets the format of the object to be aligned baseline to baseline + // for starmath formulas aligned as character. + // only set the SwFrmFmt if SwFlyFrm for the object doesn't exist yet + void AlignFormula( const ::com::sun::star::uno::Reference < ::com::sun::star::embed::XEmbeddedObject >& xObj , SwFrmFmt* pFrmFmt = 0 ); + // bSetAnchor determines whether the anchor is to be set to 'as char' + // then for starmath formulas anchored 'as char' it alignes it baseline to baseline + // changing the previous vertical orientation + void AlignFormulaToBaseline( const ::com::sun::star::uno::Reference < ::com::sun::star::embed::XEmbeddedObject >& xObj , bool bSetAnchor = FALSE ); + // aligns all formulas with anchor 'as char' to baseline + void AlignAllFormulasToBaseline(); + // <-- //------------------------------------------ --- a/sw/inc/swcli.hxx +++ a/sw/inc/swcli.hxx @@ -53,6 +53,8 @@ void SetInDoVerb( BOOL bFlag ) { bInDoVerb = bFlag; } BOOL IsCheckForOLEInCaption() const { return bOldCheckForOLEInCaption; } + + virtual void FormatChanged(); }; #endif --- a/sw/source/core/doc/poolfmt.cxx +++ a/sw/source/core/doc/poolfmt.cxx @@ -1332,7 +1332,7 @@ case RES_POOLFRM_FORMEL: { aSet.Put( SwFmtAnchor( FLY_AS_CHAR ) ); - aSet.Put( SwFmtVertOrient( 0, text::VertOrientation::CHAR_CENTER, text::RelOrientation::FRAME ) ); + aSet.Put( SwFmtVertOrient( 0, text::VertOrientation::NONE, text::RelOrientation::FRAME ) ); aSet.Put( SvxLRSpaceItem( 114, 114, 0, 0, RES_LR_SPACE ) ); } break; --- a/sw/source/core/frmedt/fefly1.cxx +++ a/sw/source/core/frmedt/fefly1.cxx @@ -73,6 +73,9 @@ #include // <-- #include +// --> 3.7.2010 #i972# +#include +// <-- // --> OD 2009-12-29 #i89920# #include #include @@ -1522,7 +1525,10 @@ pFly->ChgRelPos( aTmp ); } } - EndAllAction(); + + pFly->SetLastFlyFrmPrtRectPos( pFly->Prt().Pos() ); //stores the value of last Prt rect + + EndAllAction(); return aResult; } @@ -2154,3 +2160,136 @@ } } // <-- +// --> 8.7.2010 #i972# +void SwFEShell::AlignFormula( const uno::Reference < embed::XEmbeddedObject >& xObj , SwFrmFmt* pFrmFmt ) +{ + SvGlobalName aCLSID( xObj->getClassID() ); + BOOL bStarMath = ( SotExchange::IsMath( aCLSID ) != 0 ); + + if (bStarMath) //check the object is formula + { + SwFlyFrm *pFly = 0; + if ( !pFrmFmt ) //find format if it was not given + { + pFly = FindFlyFrm( xObj ); + if ( !pFly ) + { + ASSERT( pFly , "No fly frame!" ); + return; + } + pFrmFmt = pFly->GetFmt(); + } + + if (pFrmFmt) + { + if (FLY_AS_CHAR == pFrmFmt->GetAnchor().GetAnchorId()) // check the anchor is AsChar + { + uno::Any aBaseline; + + if( svt::EmbeddedObjectRef::TryRunningState( xObj ) ) + { + uno::Reference < beans::XPropertySet > xSet( xObj->getComponent(), uno::UNO_QUERY ); + if ( xSet.is() ) + { + try + { + aBaseline = xSet->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("BaseLine") ) ); + } + catch ( uno::Exception& ) + { + ASSERT( FALSE , "Baseline could not be retrieved from Starmath!" ); + } + } + } + + sal_Int32 nBaseline = ::comphelper::getINT32(aBaseline); + const MapMode aSourceMapMode( MAP_100TH_MM ); + const MapMode aTargetMapMode( MAP_TWIP ); + nBaseline = OutputDevice::LogicToLogic( nBaseline, aSourceMapMode.GetMapUnit(), aTargetMapMode.GetMapUnit() ); + + ASSERT( (nBaseline > 0) , "Wrong value of Baseline while retrieving from Starmath!" ); + //nBaseline must be moved by aPrt position + if ( pFly ) + nBaseline += pFly->GetLastFlyFrmPrtRectPos().Y(); + + const SwFmtVertOrient &rVert = pFrmFmt->GetVertOrient(); + SwFmtVertOrient aVert( rVert ); + aVert.SetPos( -nBaseline ); + + pFrmFmt->LockModify(); + pFrmFmt->SetFmtAttr( aVert ); + pFrmFmt->UnlockModify(); + if ( pFly ) + pFly->InvalidatePos(); + } + } + } +} + +void SwFEShell::AlignFormulaToBaseline( const uno::Reference < embed::XEmbeddedObject >& xObj , bool bSetAnchor ) +{ + SvGlobalName aCLSID( xObj->getClassID() ); + BOOL bStarMath = ( SotExchange::IsMath( aCLSID ) != 0 ); + + if ( bStarMath ) + { + SwFlyFrm *pFly = FindFlyFrm( xObj ); + if ( !pFly ) + { + ASSERT( pFly , "No fly frame!" ); + return; + } + + SwFrmFmt *pFmt = pFly->GetFmt(); + if ( pFmt ) + { + if ( bSetAnchor ) + { + const SwFmtAnchor &rAnchor = pFmt->GetAnchor(); + SwFmtAnchor aAnchor( rAnchor ); + aAnchor.SetType( FLY_AS_CHAR ); + pFmt->LockModify(); + pFmt->SetFmtAttr( aAnchor ); + pFmt->UnlockModify(); + } + + if ( FLY_AS_CHAR == pFmt->GetAnchor().GetAnchorId() ) + { + const SwFmtVertOrient &rVert = pFmt->GetVertOrient(); + SwFmtVertOrient aVert( rVert ); + aVert.SetVertOrient( com::sun::star::text::VertOrientation::NONE ); + pFmt->LockModify(); + pFmt->SetFmtAttr( aVert ); + pFmt->UnlockModify(); + + AlignFormula( xObj ); + } + } + } +} + +void SwFEShell::AlignAllFormulasToBaseline() +{ + StartAllAction(); + + SwStartNode *pStNd; + SwNodeIndex aIdx( *GetNodes().GetEndOfAutotext().StartOfSectionNode(), 1 ); + while ( 0 != (pStNd = aIdx.GetNode().GetStartNode()) ) + { + aIdx++; + SwNode& rNd = aIdx.GetNode(); + if( rNd.IsOLENode() ) + { + const uno::Reference < embed::XEmbeddedObject >& xObj = (dynamic_cast(rNd)).GetOLEObj().GetOleRef(); + SvGlobalName aCLSID( xObj->getClassID() ); + if ( SotExchange::IsMath( aCLSID ) ) + AlignFormulaToBaseline( xObj ); + } + + aIdx.Assign( *pStNd->EndOfSectionNode(), + 1 ); + } + + EndAllAction(); +} +// <-- + --- a/sw/source/core/inc/flyfrm.hxx +++ a/sw/source/core/inc/flyfrm.hxx @@ -77,6 +77,9 @@ // OD 2004-05-27 #i26791# - moved to // Point aRelPos; //Die Relative Position zum Master + Point aLastFlyFrmPrtRectPos; // it stores the previous position of Prt rectangle from RequestObjectResize + // so it can be used to move frames of non-resizable objects to align them correctly + // when they get borders (this is done in SwWrtShell::CalcAndGetScale) private: BOOL bLocked :1; //Cntnt-gebundene Flys muessen derart blockiert werden @@ -283,5 +286,9 @@ @author OD */ virtual bool IsFormatPossible() const; + + const Point GetLastFlyFrmPrtRectPos() const { return aLastFlyFrmPrtRectPos; } + void SetLastFlyFrmPrtRectPos( Point aPoint ) { aLastFlyFrmPrtRectPos = aPoint; } + }; #endif --- a/sw/source/core/inc/flyfrms.hxx +++ a/sw/source/core/inc/flyfrms.hxx @@ -188,6 +188,7 @@ BOOL bInvalidLayout :1; BOOL bInvalidCntnt :1; + bool bPosCalculated; protected: virtual void NotifyBackground( SwPageFrm *pPage, @@ -237,6 +238,8 @@ // format of the anchor frame virtual void _ActionOnInvalidation( const InvalidationType _nInvalid ); // <-- + + void SetPosCalculated( bool bNew ) { bPosCalculated = bNew; } }; inline void SwFlyInCntFrm::InvalidateLayout() const --- a/sw/source/core/layout/fly.cxx +++ a/sw/source/core/layout/fly.cxx @@ -119,6 +119,7 @@ // aRelPos(), pPrevLink( 0 ), pNextLink( 0 ), + aLastFlyFrmPrtRectPos( Point(0,0) ), bInCnt( FALSE ), bAtCnt( FALSE ), bLayout( FALSE ), --- a/sw/source/core/layout/flyincnt.cxx +++ a/sw/source/core/layout/flyincnt.cxx @@ -56,6 +56,7 @@ SwFlyFrm( pFmt, pAnch ) { bInCnt = bInvalidLayout = bInvalidCntnt = TRUE; + bPosCalculated = FALSE; SwTwips nRel = pFmt->GetVertOrient().GetPos(); // OD 2004-05-27 #i26791# - member moved to Point aRelPos; @@ -203,6 +204,11 @@ if ( !bValidPos ) { bValidPos = TRUE; + // --> let the position be set, only if it was calculated in + // SwAsCharAnchoredObjectPosition::CalcPosition + if ( !bPosCalculated ) + return; + // <-- SwFlyFrmFmt *pFmt = (SwFlyFrmFmt*)GetFmt(); const SwFmtVertOrient &rVert = pFmt->GetVertOrient(); //Und ggf. noch die aktuellen Werte im Format updaten, dabei darf --- a/sw/source/core/objectpositioning/ascharanchoredobjectposition.cxx +++ a/sw/source/core/objectpositioning/ascharanchoredobjectposition.cxx @@ -328,7 +328,11 @@ { // set new anchor position and relative position SwFlyInCntFrm* pFlyInCntFrm = &(const_cast(rFlyInCntFrm)); + // --> let SwFlyInCnt::MakeObjPos set position only at this place using bPosCalculated + pFlyInCntFrm->SetPosCalculated( TRUE ); pFlyInCntFrm->SetRefPoint( aAnchorPos, aRelAttr, aRelPos ); + pFlyInCntFrm->SetPosCalculated( FALSE ); + // <-- if( nObjWidth != (pFlyInCntFrm->Frm().*fnRect->fnGetWidth)() ) { // recalculate object bound rectangle, if object width has changed. --- a/sw/source/ui/uiview/swcli.cxx +++ a/sw/source/ui/uiview/swcli.cxx @@ -169,3 +169,17 @@ const SwWrtShell &rSh = ((SwView*)GetViewShell())->GetWrtShell(); rSh.MakeObjVisible( GetObject() ); } + +void SwOleClient::FormatChanged() +{ + // --> #i972# + const uno::Reference < embed::XEmbeddedObject >& xObj = GetObject(); + + SvGlobalName aCLSID( xObj->getClassID() ); + if ( SotExchange::IsMath( aCLSID ) ) + { + SwWrtShell &rSh = ( dynamic_cast( GetViewShell() ) )->GetWrtShell(); + rSh.AlignFormula( xObj ); + } + // <-- +} --- a/sw/source/ui/wrtsh/wrtsh1.cxx +++ a/sw/source/ui/wrtsh/wrtsh1.cxx @@ -493,7 +493,8 @@ if ( xObj.is() ) { - if( InsertOleObject( xObj ) && bActivate && bDoVerb ) + BOOL bActivate2 = InsertOleObject( xObj ); + if( bActivate && bDoVerb ) { SfxInPlaceClient* pClient = GetView().FindIPClient( xObj.GetObject(), &GetView().GetEditWin() ); if ( !pClient ) @@ -517,7 +518,8 @@ //#50270# Error brauchen wir nicht handeln, das erledigt das //DoVerb in der SfxViewShell - pClient->DoVerb( SVVERB_SHOW ); + if ( bActivate2 ) + pClient->DoVerb( SVVERB_SHOW ); // TODO/LATER: set document name - should be done in Client //if ( !ERRCODE_TOERROR( nErr ) ) @@ -614,6 +616,11 @@ aFrmMgr.SetSize( aSz ); SwFlyFrmFmt *pFmt = SwFEShell::InsertObject( xRef, &aFrmMgr.GetAttrSet() ); + // --> #i972# + if ( bStarMath ) //sets baseline + AlignFormula( xRef.GetObject() , pFmt ); + // <-- + if (pFlyFrmFmt) *pFlyFrmFmt = pFmt; @@ -774,6 +781,8 @@ if ( (embed::EmbedMisc::EMBED_ACTIVATEIMMEDIATELY & nMisc) || bLinkingChart // TODO/LATER: ResizeOnPrinterChange //|| SVOBJ_MISCSTATUS_RESIZEONPRINTERCHANGE & xObj->GetMiscStatus() + || nMisc & embed::EmbedMisc::EMBED_NEVERRESIZE // non-resizable objects need to be + // set the size back by this method ) { pCli = new SwOleClient( &GetView(), &GetView().GetEditWin(), xObj ); @@ -884,6 +893,20 @@ if ( bUseObjectSize ) { + // --> this moves non-resizable object so that when adding borders the baseline remains the same + const SwFlyFrm *pFly = GetCurrFlyFrm(); + if ( pFly ) + { + const Point aPoint = pFly->GetLastFlyFrmPrtRectPos(); + SwRect aRect( pFlyPrtRect ? *pFlyPrtRect + : GetAnyCurRect( RECT_FLY_PRT_EMBEDDED, 0, xObj.GetObject() )); + aArea += aPoint - aRect.Pos(); + } + else + { + ASSERT( FALSE , "Could not find fly frame." ); + } + // <-- aArea.Width ( _aVisArea.Width() ); aArea.Height( _aVisArea.Height() ); RequestObjectResize( aArea, xObj.GetObject() );