diff --git a/sw/source/core/layout/paintfrm.cxx b/sw/source/core/layout/paintfrm.cxx index c8138aafa28e..ad698e48abb6 100755 --- a/sw/source/core/layout/paintfrm.cxx +++ b/sw/source/core/layout/paintfrm.cxx @@ -127,6 +127,9 @@ #include #include +#include +#include +#include using namespace ::editeng; using namespace ::com::sun::star; @@ -2796,6 +2799,14 @@ SwRootFrm::Paint(SwRect const& rRect, SwPrintData const*const pPrintData) const else SwRootFrm::bInPaint = bResetRootPaint = sal_True; + SwWrtShell* pWrtSh = dynamic_cast< SwWrtShell* >( pSh ); + if ( pWrtSh ) + { + SwEditWin& rEditWin = pWrtSh->GetView().GetEditWin(); + rEditWin.ClearHeaderFooterControls( ); + } + + SwSavePaintStatics *pStatics = 0; if ( pGlobalShell ) pStatics = new SwSavePaintStatics(); @@ -3303,177 +3314,106 @@ void SwLayoutFrm::Paint(SwRect const& rRect, SwPrintData const*const) const } drawinglayer::primitive2d::Primitive2DSequence lcl_CreateHeaderFooterSeparatorPrimitives( - OutputDevice* pOut, drawinglayer::processor2d::BaseProcessor2D* pProcessor, - const SwPageFrm* pPageFrm, double nLabelRight, double nLineY, - bool bHeader, const String& rStyleName, const SwFrm* pFrm ) + const SwPageFrm* pPageFrm, double nLineY ) { // Adjust the Y-coordinate of the line to the header/footer box - if ( pFrm ) - { - const SwFrmFmt* pFmt = ((const SwLayoutFrm*)pFrm)->GetFmt(); - if ( bHeader ) - nLineY -= pFmt->GetULSpace().GetLower(); - else - nLineY += pFmt->GetULSpace().GetUpper(); - } - - drawinglayer::primitive2d::Primitive2DSequence aSeq( 3 ); + drawinglayer::primitive2d::Primitive2DSequence aSeq( 1 ); basegfx::B2DPoint aLeft ( pPageFrm->Frm().Left(), nLineY ); basegfx::B2DPoint aRight( pPageFrm->Frm().Right(), nLineY ); - // Compute the text to show - String aText = SW_RESSTR( STR_HEADER ); - if ( !bHeader ) - aText = SW_RESSTR( STR_FOOTER ); - aText += rStyleName; - - // Colors basegfx::BColor aLineColor = SwViewOption::GetHeaderFooterMarkColor().getBColor(); - basegfx::BColor aHslLine = basegfx::tools::rgb2hsl( aLineColor ); - double nLuminance = aHslLine.getZ() * 2.5; - if ( nLuminance == 0 ) - nLuminance = 0.5; - else if ( nLuminance >= 1.0 ) - nLuminance = aHslLine.getZ() * 0.4; - aHslLine.setZ( nLuminance ); - basegfx::BColor aFillColor = basegfx::tools::hsl2rgb( aHslLine ); // Only draw the dashed line for unexisting header / footers - if ( !pFrm ) - { - aSeq.realloc( 4 ); + aSeq.realloc( 4 ); - // Dashed line in twips - std::vector< double > aStrokePattern; - aStrokePattern.push_back( 110 ); - aStrokePattern.push_back( 110 ); + // Dashed line in twips + std::vector< double > aStrokePattern; + aStrokePattern.push_back( 110 ); + aStrokePattern.push_back( 110 ); - // Compute the dashed line primitive - basegfx::B2DPolygon aLinePolygon; - aLinePolygon.append( aLeft ); - aLinePolygon.append( aRight ); + // Compute the dashed line primitive + basegfx::B2DPolygon aLinePolygon; + aLinePolygon.append( aLeft ); + aLinePolygon.append( aRight ); - drawinglayer::primitive2d::PolyPolygonStrokePrimitive2D * pLine = - new drawinglayer::primitive2d::PolyPolygonStrokePrimitive2D ( - basegfx::B2DPolyPolygon( aLinePolygon ), - drawinglayer::attribute::LineAttribute( aLineColor, 20.0 ), - drawinglayer::attribute::StrokeAttribute( aStrokePattern ) ); - - aSeq[3] = drawinglayer::primitive2d::Primitive2DReference( pLine ); - } - - const SwRect& rVisArea = pPageFrm->getRootFrm()->GetCurrShell()->VisArea(); - double nVisRight = rVisArea.Right(); - - // Compute the text primitive - basegfx::B2DVector aFontSize; - - Font aFont = pOut->GetSettings().GetStyleSettings().GetAppFont(); - aFont.SetHeight( 8 * 20 ); // 8pt to twips - - // Compute the text width - const Font& rOldFont = pOut->GetFont(); - pOut->SetFont( aFont ); - double nTextWidth = pOut->GetTextWidth( aText ); - pOut->SetFont( rOldFont ); - - drawinglayer::attribute::FontAttribute aFontAttr = drawinglayer::primitive2d::getFontAttributeFromVclFont( - aFontSize, aFont, false, false ); - - FontMetric aFontMetric = pOut->GetFontMetric( aFont ); - - double nTextOffsetY = aFontMetric.GetHeight() - aFontMetric.GetDescent() + 70.0; - if ( !bHeader ) - nTextOffsetY = - aFontMetric.GetDescent() - 70.0; - basegfx::B2DHomMatrix aTextMatrix( basegfx::tools::createScaleTranslateB2DHomMatrix( - aFontSize.getX(), aFontSize.getY(), - std::min( nLabelRight, nVisRight ) - nTextWidth - 80.0, nLineY + nTextOffsetY ) ); - - - drawinglayer::primitive2d::TextSimplePortionPrimitive2D * pText = - new drawinglayer::primitive2d::TextSimplePortionPrimitive2D( - aTextMatrix, - aText, 0, aText.Len(), - std::vector< double >(), - aFontAttr, - lang::Locale(), - aLineColor ); - aSeq[2] = drawinglayer::primitive2d::Primitive2DReference( pText ); - basegfx::B2DRange aTextRange = pText->getB2DRange( pProcessor->getViewInformation2D() ); - - // Draw the polygon around the flag - basegfx::B2DPolygon aFlagPolygon; - basegfx::B2DVector aFlagVector( 0, 1 ); - - double nFlagHeight = aTextRange.getMaxY() - nLineY + 60.0; - - if ( !bHeader ) - { - aFlagVector = - aFlagVector; - nFlagHeight = nLineY - aTextRange.getMinY() + 60.0; - } - basegfx::B2DPoint aStartPt( aTextRange.getMinX() - 60.0, nLineY ); - aFlagPolygon.append( aStartPt ); - basegfx::B2DPoint aNextPt = aStartPt + aFlagVector * ( nFlagHeight ); - aFlagPolygon.append( aNextPt ); - aNextPt += ( aTextRange.getWidth() + 120.0 ) * basegfx::B2DVector( 1, 0 ); - aFlagPolygon.append( aNextPt ); - aNextPt.setY( nLineY ); - aFlagPolygon.append( aNextPt ); - - // Compute the flag background color primitive - aSeq[0] = drawinglayer::primitive2d::Primitive2DReference( - new drawinglayer::primitive2d::PolyPolygonColorPrimitive2D( - basegfx::B2DPolyPolygon( aFlagPolygon ), - aFillColor ) ); - - drawinglayer::primitive2d::PolygonHairlinePrimitive2D * pBoxLine = - new drawinglayer::primitive2d::PolygonHairlinePrimitive2D( - aFlagPolygon, aLineColor ); - aSeq[1] = drawinglayer::primitive2d::Primitive2DReference( pBoxLine ); + drawinglayer::primitive2d::PolyPolygonStrokePrimitive2D * pLine = + new drawinglayer::primitive2d::PolyPolygonStrokePrimitive2D ( + basegfx::B2DPolyPolygon( aLinePolygon ), + drawinglayer::attribute::LineAttribute( aLineColor, 20.0 ), + drawinglayer::attribute::StrokeAttribute( aStrokePattern ) ); + aSeq[0] = drawinglayer::primitive2d::Primitive2DReference( pLine ); return aSeq; } void SwPageFrm::PaintDecorators( OutputDevice *pOut ) const { - const SwLayoutFrm* pBody = FindBodyCont(); - if ( pBody ) + SwWrtShell* pWrtSh = dynamic_cast< SwWrtShell* >( pGlobalShell ); + if ( pWrtSh ) { - SwRect aBodyRect( pBody->Frm() ); + SwEditWin& rEditWin = pWrtSh->GetView().GetEditWin(); - if ( !pGlobalShell->GetViewOptions()->IsPrinting() && - !pGlobalShell->GetViewOptions()->IsPDFExport() && - !pGlobalShell->IsPreView() && - pGlobalShell->IsHeaderFooterEdit( ) ) + const SwLayoutFrm* pBody = FindBodyCont(); + if ( pBody ) { - const String aStyleName = GetPageDesc()->GetName(); - drawinglayer::processor2d::BaseProcessor2D* pProcessor = CreateProcessor2D(); + SwRect aBodyRect( pBody->Frm() ); - // Header - const SwFrm* pHeaderFrm = Lower(); - if ( !pHeaderFrm->IsHeaderFrm() ) - pHeaderFrm = NULL; + if ( !pGlobalShell->GetViewOptions()->IsPrinting() && + !pGlobalShell->GetViewOptions()->IsPDFExport() && + !pGlobalShell->IsPreView() && + pGlobalShell->IsHeaderFooterEdit( ) ) + { + const rtl::OUString& rStyleName = GetPageDesc()->GetName(); + rtl::OUString aHeaderText = ResId::toString( SW_RES( STR_HEADER ) ); + sal_Int32 nPos = aHeaderText.lastIndexOf( rtl::OUString::createFromAscii( "%1" ) ); + aHeaderText = aHeaderText.replaceAt( nPos, 2, rStyleName ); + drawinglayer::processor2d::BaseProcessor2D* pProcessor = CreateProcessor2D(); - double nLabelRight = aBodyRect.Right(); - pProcessor->process( lcl_CreateHeaderFooterSeparatorPrimitives( - pOut, pProcessor, this, nLabelRight, - double( aBodyRect.Top() ), true, aStyleName, pHeaderFrm ) ); + // Header + const SwFrm* pHeaderFrm = Lower(); + if ( !pHeaderFrm->IsHeaderFrm() ) + pHeaderFrm = NULL; - // Footer - const SwFrm* pFooterFrm = Lower(); - while ( pFooterFrm->GetNext() ) - pFooterFrm = pFooterFrm->GetNext(); - if ( !pFooterFrm->IsFooterFrm() ) - pFooterFrm = NULL; + const SwRect& rVisArea = pGlobalShell->VisArea(); + long nXOff = std::min( aBodyRect.Right(), rVisArea.Right() ); - pProcessor->process( lcl_CreateHeaderFooterSeparatorPrimitives( - pOut, pProcessor, this, nLabelRight, - double( aBodyRect.Bottom() ), false, aStyleName, pFooterFrm ) ); + // FIXME there are cases where the label isn't show but should be + if ( rVisArea.IsInside( Point( rVisArea.Left(), pHeaderFrm->Frm().Bottom() ) ) ) + { + long nOutputYOff = pHeaderFrm->Frm().Bottom(); + Point nOutputOff = rEditWin.LogicToPixel( Point( nXOff, nOutputYOff ) ); + rEditWin.AddHeaderFooterControl( aHeaderText, true, nOutputOff ); + } - delete pProcessor; + pProcessor->process( lcl_CreateHeaderFooterSeparatorPrimitives( + this, double( aBodyRect.Top() ) ) ); + + // Footer + const SwFrm* pFooterFrm = Lower(); + while ( pFooterFrm->GetNext() ) + pFooterFrm = pFooterFrm->GetNext(); + if ( !pFooterFrm->IsFooterFrm() ) + pFooterFrm = NULL; + + rtl::OUString aFooterText = ResId::toString( SW_RES( STR_FOOTER ) ); + nPos = aFooterText.lastIndexOf( rtl::OUString::createFromAscii( "%1" ) ); + aFooterText = aFooterText.replaceAt( nPos, 2, rStyleName ); + + // FIXME there are cases where the label isn't show but should be + if ( rVisArea.IsInside( Point( rVisArea.Left(), pFooterFrm->Frm().Top() ) ) ) + { + long nOutputYOff = pFooterFrm->Frm().Top(); + Point nOutputOff = rEditWin.LogicToPixel( Point( nXOff, nOutputYOff ) ); + rEditWin.AddHeaderFooterControl( aFooterText, false, nOutputOff ); + } + + pProcessor->process( lcl_CreateHeaderFooterSeparatorPrimitives( + this, double( aBodyRect.Bottom() ) ) ); + + delete pProcessor; + } } } } diff --git a/sw/source/ui/app/app.src b/sw/source/ui/app/app.src index 7736c575c081..ac126a51d9d7 100644 --- a/sw/source/ui/app/app.src +++ b/sw/source/ui/app/app.src @@ -412,12 +412,12 @@ String STR_EMPTYPAGE String STR_HEADER { - Text [ en-US ] = "Header: " ; + Text [ en-US ] = "Header (%1)" ; }; String STR_FOOTER { - Text [ en-US ] = "Footer: " ; + Text [ en-US ] = "Footer (%1)" ; }; QueryBox MSG_CLPBRD_CLEAR diff --git a/sw/source/ui/docvw/edtwin.cxx b/sw/source/ui/docvw/edtwin.cxx index 9be716fa83ba..d83f6932e753 100644 --- a/sw/source/ui/docvw/edtwin.cxx +++ b/sw/source/ui/docvw/edtwin.cxx @@ -74,6 +74,8 @@ #include #include #include +#include +#include #include #include @@ -5677,4 +5679,104 @@ Selection SwEditWin::GetSurroundingTextSelection() const } } +#define TEXT_PADDING 7 +#define BOX_DISTANCE 10 + +// the WB_MOVABLE flag is used here to avoid the window to appear on all desktops (on linux) +// and the WB_OWNERDRAWDECORATION prevents the system to draw the window decorations. +// +SwHeaderFooterControl::SwHeaderFooterControl( Window* pParent, const rtl::OUString& sLabel, bool bHeader, Point aOffset, Size aPosOffset ) : + FloatingWindow( pParent, WB_SYSTEMWINDOW | WB_NOBORDER | WB_NOSHADOW | WB_MOVEABLE | WB_OWNERDRAWDECORATION ), + m_sText( sLabel ), + m_bIsHeader( bHeader ), + m_aPosOffset( aPosOffset ) +{ + // Get the font and configure it + Font aFont = GetSettings().GetStyleSettings().GetToolFont(); + SetZoomedPointFont( aFont ); + + // Use pixels for the rest of the drawing + SetMapMode( MapMode ( MAP_PIXEL ) ); + + // Compute the position & size of the window + Rectangle aTextRect; + GetTextBoundRect( aTextRect, String( sLabel ) ); + Rectangle aTextPxRect = LogicToPixel( aTextRect ); + + Size aParentSize = pParent->GetSizePixel(); + + Size aBoxSize ( aTextPxRect.GetWidth() + TEXT_PADDING * 2, + aTextPxRect.GetHeight() + TEXT_PADDING * 2 ); + + long nYFooterOff = 0; + if ( !bHeader ) + nYFooterOff = aBoxSize.Height(); + + Point aBoxPos( m_aPosOffset.Width() + aOffset.X() - aBoxSize.Width() - BOX_DISTANCE, + m_aPosOffset.Height() + aOffset.Y() - nYFooterOff ); + + // Set the position & Size of the window + SetPosSizePixel( aBoxPos, aBoxSize ); + + // TODO Add the list_add.png picture +} + +void SwHeaderFooterControl::Paint( const Rectangle& rRect ) +{ + // Colors + basegfx::BColor aLineColor = SwViewOption::GetHeaderFooterMarkColor().getBColor(); + basegfx::BColor aHslLine = basegfx::tools::rgb2hsl( aLineColor ); + double nLuminance = aHslLine.getZ() * 2.5; + if ( nLuminance == 0 ) + nLuminance = 0.5; + else if ( nLuminance >= 1.0 ) + nLuminance = aHslLine.getZ() * 0.4; + aHslLine.setZ( nLuminance ); + basegfx::BColor aFillColor = basegfx::tools::hsl2rgb( aHslLine ); + + // Draw the background rect + SetFillColor( Color ( aFillColor ) ); + SetLineColor( Color ( aFillColor ) ); + DrawRect( rRect ); + + // Draw the lines around the rect + SetLineColor( Color( aLineColor ) ); + basegfx::B2DPolygon aPolygon; + aPolygon.append( basegfx::B2DPoint( rRect.Left(), rRect.Top() ) ); + aPolygon.append( basegfx::B2DPoint( rRect.Left(), rRect.Bottom() ) ); + DrawPolyLine( aPolygon, 1.0 ); + + aPolygon.clear(); + aPolygon.append( basegfx::B2DPoint( rRect.Right(), rRect.Top() ) ); + aPolygon.append( basegfx::B2DPoint( rRect.Right(), rRect.Bottom() ) ); + DrawPolyLine( aPolygon, 1.0 ); + + long nYLine = rRect.Bottom(); + if ( !m_bIsHeader ) + nYLine = rRect.Top(); + aPolygon.clear(); + aPolygon.append( basegfx::B2DPoint( rRect.Left(), nYLine ) ); + aPolygon.append( basegfx::B2DPoint( rRect.Right(), nYLine ) ); + DrawPolyLine( aPolygon, 1.0 ); + + + // Draw the text + SetTextColor( Color( aLineColor ) ); + DrawText( Point( rRect.Left() + TEXT_PADDING, rRect.Top() + TEXT_PADDING ), + String( m_sText ) ); +} + +void SwEditWin::AddHeaderFooterControl( const rtl::OUString& sLabel, bool bHeader, Point aOffset ) +{ + SwHeaderFooterControl::Pointer pNewControl( new SwHeaderFooterControl( this, sLabel, bHeader, aOffset, + Size( GetOutOffXPixel(), GetOutOffYPixel() ) ) ); + pNewControl->Show( ); + aHeadFootControls.push_back( pNewControl ); +} + +void SwEditWin::ClearHeaderFooterControls( ) +{ + aHeadFootControls.clear(); +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/ui/inc/edtwin.hxx b/sw/source/ui/inc/edtwin.hxx index 547d67883508..7c8c9727f85a 100644 --- a/sw/source/ui/inc/edtwin.hxx +++ b/sw/source/ui/inc/edtwin.hxx @@ -32,12 +32,15 @@ #include #include #include +#include #include #include #define _SVSTDARR_STRINGSISORTDTOR #include +#include + class SwWrtShell; class SwView; class SwRect; @@ -57,6 +60,20 @@ class SdrDropMarkerOverlay; Description: input window --------------------------------------------------------------------*/ +class SwHeaderFooterControl : public FloatingWindow +{ + const rtl::OUString m_sText; + bool m_bIsHeader; + Size m_aPosOffset; + +public: + SwHeaderFooterControl( Window* pParent, const rtl::OUString& sLabel, bool bHeader, Point aOffset, Size aOffsetPos ); + + virtual void Paint( const Rectangle& rRect ); + + typedef boost::shared_ptr< SwHeaderFooterControl > Pointer; +}; + class SwEditWin: public Window, public DropTargetHelper, public DragSourceHelper { @@ -146,6 +163,8 @@ friend void PageNumNotify( ViewShell* pVwSh, sal_uInt16 nKS_NUMDOWN_Count; // #i23725# sal_uInt16 nKS_NUMINDENTINC_Count; + std::vector< SwHeaderFooterControl::Pointer > aHeadFootControls; + void LeaveArea(const Point &); void JustifyAreaTimer(); inline void EnterArea(); @@ -299,6 +318,9 @@ public: void SetUseInputLanguage( sal_Bool bNew ); sal_Bool IsUseInputLanguage() const { return bUseInputLanguage; } + void AddHeaderFooterControl( const rtl::OUString& sLabel, bool bHeader, Point aOffset ); + void ClearHeaderFooterControls( ); + SwEditWin(Window *pParent, SwView &); virtual ~SwEditWin(); };