xref: /core/sw/source/uibase/docvw/HeaderFooterWin.cxx (revision 16bd75a56c16cce6d07284d041f225a81550eb48)
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  */
9 
10 #include <strings.hrc>
11 
12 #include <doc.hxx>
13 #include <drawdoc.hxx>
14 #include <cmdid.h>
15 #include <DashedLine.hxx>
16 #include <docsh.hxx>
17 #include <edtwin.hxx>
18 #include <fmthdft.hxx>
19 #include <HeaderFooterWin.hxx>
20 #include <pagedesc.hxx>
21 #include <pagefrm.hxx>
22 #include <view.hxx>
23 #include <viewopt.hxx>
24 #include <wrtsh.hxx>
25 #include <IDocumentDrawModelAccess.hxx>
26 
27 #include <basegfx/color/bcolortools.hxx>
28 #include <basegfx/matrix/b2dhommatrixtools.hxx>
29 #include <basegfx/polygon/b2dpolygon.hxx>
30 #include <basegfx/range/b2drectangle.hxx>
31 #include <basegfx/vector/b2dsize.hxx>
32 #include <basegfx/utils/gradienttools.hxx>
33 #include <drawinglayer/attribute/fillgradientattribute.hxx>
34 #include <drawinglayer/attribute/fontattribute.hxx>
35 #include <drawinglayer/primitive2d/fillgradientprimitive2d.hxx>
36 #include <drawinglayer/primitive2d/modifiedcolorprimitive2d.hxx>
37 #include <drawinglayer/primitive2d/PolygonHairlinePrimitive2D.hxx>
38 #include <drawinglayer/primitive2d/PolyPolygonColorPrimitive2D.hxx>
39 #include <drawinglayer/primitive2d/textlayoutdevice.hxx>
40 #include <drawinglayer/primitive2d/textprimitive2d.hxx>
41 #include <editeng/boxitem.hxx>
42 #include <svx/hdft.hxx>
43 #include <sfx2/bindings.hxx>
44 #include <sfx2/viewfrm.hxx>
45 #include <drawinglayer/processor2d/baseprocessor2d.hxx>
46 #include <drawinglayer/processor2d/processor2dtools.hxx>
47 #include <vcl/canvastools.hxx>
48 #include <vcl/metric.hxx>
49 #include <vcl/svapp.hxx>
50 #include <vcl/settings.hxx>
51 #include <vcl/virdev.hxx>
52 #include <memory>
53 
54 #define TEXT_PADDING 5
55 #define BOX_DISTANCE 10
56 #define BUTTON_WIDTH 18
57 
58 using namespace basegfx;
59 using namespace basegfx::utils;
60 using namespace drawinglayer::attribute;
61 
62 namespace
63 {
lcl_GetFillColor(const basegfx::BColor & rLineColor)64     basegfx::BColor lcl_GetFillColor(const basegfx::BColor& rLineColor)
65     {
66         basegfx::BColor aHslLine = basegfx::utils::rgb2hsl(rLineColor);
67         double nLuminance = aHslLine.getZ() * 2.5;
68         if ( nLuminance == 0 )
69             nLuminance = 0.5;
70         else if ( nLuminance >= 1.0 )
71             nLuminance = aHslLine.getZ() * 0.4;
72         aHslLine.setZ( nLuminance );
73         return basegfx::utils::hsl2rgb( aHslLine );
74     }
75 
lcl_GetLighterGradientColor(const basegfx::BColor & rDarkColor)76     basegfx::BColor lcl_GetLighterGradientColor(const basegfx::BColor& rDarkColor)
77     {
78         basegfx::BColor aHslDark = basegfx::utils::rgb2hsl(rDarkColor);
79         double nLuminance = aHslDark.getZ() * 255 + 20;
80         aHslDark.setZ( nLuminance / 255.0 );
81         return basegfx::utils::hsl2rgb( aHslDark );
82     }
83 
lcl_GetPolygon(const::tools::Rectangle & rRect,bool bOnTop)84     B2DPolygon lcl_GetPolygon( const ::tools::Rectangle& rRect, bool bOnTop )
85     {
86         const double nRadius = 3;
87         const double nKappa((M_SQRT2 - 1.0) * 4.0 / 3.0);
88 
89         B2DPolygon aPolygon;
90         aPolygon.append( B2DPoint( rRect.Left(), rRect.Top() ) );
91 
92         {
93             B2DPoint aCorner( rRect.Left(), rRect.Bottom() );
94             B2DPoint aStart( rRect.Left(), rRect.Bottom() - nRadius );
95             B2DPoint aEnd( rRect.Left() + nRadius, rRect.Bottom() );
96             aPolygon.append( aStart );
97             aPolygon.appendBezierSegment(
98                     interpolate( aStart, aCorner, nKappa ),
99                     interpolate( aEnd, aCorner, nKappa ),
100                     aEnd );
101         }
102 
103         {
104             B2DPoint aCorner( rRect.Right(), rRect.Bottom() );
105             B2DPoint aStart( rRect.Right() - nRadius, rRect.Bottom() );
106             B2DPoint aEnd( rRect.Right(), rRect.Bottom() - nRadius );
107             aPolygon.append( aStart );
108             aPolygon.appendBezierSegment(
109                     interpolate( aStart, aCorner, nKappa ),
110                     interpolate( aEnd, aCorner, nKappa ),
111                     aEnd );
112         }
113 
114         aPolygon.append( B2DPoint( rRect.Right(), rRect.Top() ) );
115 
116         if ( !bOnTop )
117         {
118             B2DRectangle aBRect = vcl::unotools::b2DRectangleFromRectangle(rRect);
119             B2DHomMatrix aRotation = createRotateAroundPoint(
120                    aBRect.getCenterX(), aBRect.getCenterY(), M_PI );
121             aPolygon.transform( aRotation );
122         }
123 
124         return aPolygon;
125     }
126 }
127 
PaintButton(drawinglayer::primitive2d::Primitive2DContainer & rSeq,const tools::Rectangle & rRect,bool bOnTop)128 void SwFrameButtonPainter::PaintButton(drawinglayer::primitive2d::Primitive2DContainer& rSeq,
129                                        const tools::Rectangle& rRect, bool bOnTop)
130 {
131     rSeq.clear();
132     B2DPolygon aPolygon = lcl_GetPolygon(rRect, bOnTop);
133 
134     // Colors
135     basegfx::BColor aLineColor = SwViewOption::GetCurrentViewOptions().GetHeaderFooterMarkColor().getBColor();
136     basegfx::BColor aFillColor = lcl_GetFillColor(aLineColor);
137     basegfx::BColor aLighterColor = lcl_GetLighterGradientColor(aFillColor);
138 
139     const StyleSettings& rSettings = Application::GetSettings().GetStyleSettings();
140     if (rSettings.GetHighContrastMode())
141     {
142         aFillColor = rSettings.GetDialogColor().getBColor();
143         aLineColor = rSettings.GetDialogTextColor().getBColor();
144 
145         rSeq.push_back(new drawinglayer::primitive2d::PolyPolygonColorPrimitive2D(B2DPolyPolygon(aPolygon), aFillColor));
146     }
147     else
148     {
149         B2DRectangle aGradientRect = vcl::unotools::b2DRectangleFromRectangle(rRect);
150         double nAngle = M_PI;
151         if (bOnTop)
152             nAngle = 0;
153 
154         FillGradientAttribute aFillAttrs(css::awt::GradientStyle_LINEAR, 0.0, 0.0, 0.0, nAngle,
155             basegfx::BColorStops(aLighterColor, aFillColor));
156         rSeq.push_back(new drawinglayer::primitive2d::FillGradientPrimitive2D(aGradientRect, std::move(aFillAttrs)));
157     }
158 
159     // Create the border lines primitive
160     rSeq.push_back(new drawinglayer::primitive2d::PolygonHairlinePrimitive2D(std::move(aPolygon), aLineColor));
161 }
162 
SwHeaderFooterDashedLine(SwEditWin * pEditWin,const SwFrame * pFrame,bool bHeader)163 SwHeaderFooterDashedLine::SwHeaderFooterDashedLine(SwEditWin* pEditWin, const SwFrame *pFrame, bool bHeader)
164     : SwDashedLine(pEditWin, &SwViewOption::GetHeaderFooterMarkColor)
165     , m_pEditWin(pEditWin)
166     , m_pFrame(pFrame)
167     , m_bIsHeader(bHeader)
168 {
169 }
170 
IsOnScreen()171 bool SwHeaderFooterDashedLine::IsOnScreen()
172 {
173     tools::Rectangle aBounds(GetPosPixel(), GetSizePixel());
174     tools::Rectangle aVisArea = GetEditWin()->LogicToPixel(GetEditWin()->GetView().GetVisArea());
175     return aBounds.Overlaps(aVisArea);
176 }
177 
EnsureWin()178 void SwHeaderFooterDashedLine::EnsureWin()
179 {
180     if (!m_pWin)
181     {
182         m_pWin = VclPtr<SwHeaderFooterWin>::Create(m_pEditWin, m_pFrame, m_bIsHeader);
183         m_pWin->SetZOrder(this, ZOrderFlags::Before);
184     }
185 }
186 
ShowAll(bool bShow)187 void SwHeaderFooterDashedLine::ShowAll(bool bShow)
188 {
189     Show(bShow);
190     if (!m_pWin && IsOnScreen())
191         EnsureWin();
192     if (m_pWin)
193         m_pWin->ShowAll(bShow);
194 }
195 
SetReadonly(bool bReadonly)196 void SwHeaderFooterDashedLine::SetReadonly(bool bReadonly)
197 {
198     ShowAll(!bReadonly);
199 }
200 
Contains(const Point & rDocPt) const201 bool SwHeaderFooterDashedLine::Contains(const Point &rDocPt) const
202 {
203     if (m_pWin && m_pWin->Contains(rDocPt))
204         return true;
205 
206     ::tools::Rectangle aLineRect(GetPosPixel(), GetSizePixel());
207     return aLineRect.Contains(rDocPt);
208 }
209 
SetOffset(Point aOffset,tools::Long nXLineStart,tools::Long nXLineEnd)210 void SwHeaderFooterDashedLine::SetOffset(Point aOffset, tools::Long nXLineStart, tools::Long nXLineEnd)
211 {
212     Point aLinePos(nXLineStart, aOffset.Y());
213     Size aLineSize(nXLineEnd - nXLineStart, 1);
214     SetPosSizePixel(aLinePos, aLineSize);
215 
216     bool bOnScreen = IsOnScreen();
217     if (!m_pWin && bOnScreen)
218     {
219         EnsureWin();
220         m_pWin->ShowAll(true);
221     }
222     else if (m_pWin && !bOnScreen)
223         m_pWin.disposeAndClear();
224 
225     if (m_pWin)
226         m_pWin->SetOffset(aOffset);
227 }
228 
SwHeaderFooterWin(SwEditWin * pEditWin,const SwFrame * pFrame,bool bHeader)229 SwHeaderFooterWin::SwHeaderFooterWin(SwEditWin* pEditWin, const SwFrame *pFrame, bool bHeader ) :
230     InterimItemWindow(pEditWin, u"modules/swriter/ui/hfmenubutton.ui"_ustr, u"HFMenuButton"_ustr),
231     m_xMenuButton(m_xBuilder->weld_menu_button(u"menubutton"_ustr)),
232     m_xPushButton(m_xBuilder->weld_button(u"button"_ustr)),
233     m_pEditWin(pEditWin),
234     m_pFrame(pFrame),
235     m_bIsHeader( bHeader ),
236     m_bIsAppearing( false ),
237     m_nFadeRate( 100 ),
238     m_aFadeTimer("SwHeaderFooterWin m_aFadeTimer")
239 {
240     m_xVirDev = m_xMenuButton->create_virtual_device();
241     SwFrameMenuButtonBase::SetVirDevFont(*m_xVirDev);
242 
243     m_xPushButton->connect_clicked(LINK(this, SwHeaderFooterWin, ClickHdl));
244     m_xMenuButton->connect_selected(LINK(this, SwHeaderFooterWin, SelectHdl));
245 
246     // set the PopupMenu
247     // Rewrite the menu entries' text
248     if (m_bIsHeader)
249     {
250         m_xMenuButton->set_item_label(u"edit"_ustr, SwResId(STR_FORMAT_HEADER));
251         m_xMenuButton->set_item_label(u"delete"_ustr, SwResId(STR_DELETE_HEADER));
252     }
253     else
254     {
255         m_xMenuButton->set_item_label(u"edit"_ustr, SwResId(STR_FORMAT_FOOTER));
256         m_xMenuButton->set_item_label(u"delete"_ustr, SwResId(STR_DELETE_FOOTER));
257     }
258 
259     m_aFadeTimer.SetTimeout(50);
260     m_aFadeTimer.SetInvokeHandler(LINK(this, SwHeaderFooterWin, FadeHandler));
261 }
262 
~SwHeaderFooterWin()263 SwHeaderFooterWin::~SwHeaderFooterWin( )
264 {
265     disposeOnce();
266 }
267 
dispose()268 void SwHeaderFooterWin::dispose()
269 {
270     m_xPushButton.reset();
271     m_xMenuButton.reset();
272     m_pEditWin.reset();
273     m_xVirDev.disposeAndClear();
274     InterimItemWindow::dispose();
275 }
276 
SetOffset(Point aOffset)277 void SwHeaderFooterWin::SetOffset(Point aOffset)
278 {
279     // Compute the text to show
280     const SwPageFrame* pPageFrame = SwFrameMenuButtonBase::GetPageFrame(m_pFrame);
281     const SwPageDesc* pDesc = pPageFrame->GetPageDesc();
282     bool bIsFirst = !pDesc->IsFirstShared() && pPageFrame->OnFirstPage();
283     bool bIsLeft  = !pDesc->IsHeaderShared() && !pPageFrame->OnRightPage();
284     bool bIsRight = !pDesc->IsHeaderShared() && pPageFrame->OnRightPage();
285     m_sLabel = SwResId(STR_HEADER_TITLE);
286     if (!m_bIsHeader)
287         m_sLabel = bIsFirst ? SwResId(STR_FIRST_FOOTER_TITLE)
288             : bIsLeft  ? SwResId(STR_LEFT_FOOTER_TITLE)
289             : bIsRight ? SwResId(STR_RIGHT_FOOTER_TITLE)
290             : SwResId(STR_FOOTER_TITLE );
291     else
292         m_sLabel = bIsFirst ? SwResId(STR_FIRST_HEADER_TITLE)
293             : bIsLeft  ? SwResId(STR_LEFT_HEADER_TITLE)
294             : bIsRight ? SwResId(STR_RIGHT_HEADER_TITLE)
295             : SwResId(STR_HEADER_TITLE);
296 
297     sal_Int32 nPos = m_sLabel.lastIndexOf("%1");
298     m_sLabel = m_sLabel.replaceAt(nPos, 2, pDesc->GetName().toString());
299     m_xMenuButton->set_accessible_name(m_sLabel);
300 
301     // Compute the text size and get the box position & size from it
302     ::tools::Rectangle aTextRect;
303     m_xVirDev->GetTextBoundRect(aTextRect, m_sLabel);
304     ::tools::Rectangle aTextPxRect = m_xVirDev->LogicToPixel(aTextRect);
305     FontMetric aFontMetric = m_xVirDev->GetFontMetric(m_xVirDev->GetFont());
306     Size aBoxSize (aTextPxRect.GetWidth() + BUTTON_WIDTH + TEXT_PADDING * 2,
307                    aFontMetric.GetLineHeight() + TEXT_PADDING  * 2 );
308 
309     tools::Long nYFooterOff = 0;
310     if (!m_bIsHeader)
311         nYFooterOff = aBoxSize.Height();
312 
313     Point aBoxPos(aOffset.X() - aBoxSize.Width() - BOX_DISTANCE,
314                   aOffset.Y() - nYFooterOff);
315 
316     if (AllSettings::GetLayoutRTL())
317     {
318         aBoxPos.setX( aOffset.X() + BOX_DISTANCE );
319     }
320 
321     // Set the position & Size of the window
322     SetPosSizePixel(aBoxPos, aBoxSize);
323 
324     m_xVirDev->SetOutputSizePixel(aBoxSize);
325     PaintButton();
326 }
327 
ShowAll(bool bShow)328 void SwHeaderFooterWin::ShowAll(bool bShow)
329 {
330     bool bIsEmptyHeaderFooter = IsEmptyHeaderFooter();
331     m_xMenuButton->set_visible(!bIsEmptyHeaderFooter);
332     m_xPushButton->set_visible(bIsEmptyHeaderFooter);
333 
334     m_bIsAppearing = bShow;
335 
336     if (m_aFadeTimer.IsActive())
337         m_aFadeTimer.Stop();
338     m_aFadeTimer.Start();
339 }
340 
Contains(const Point & rDocPt) const341 bool SwHeaderFooterWin::Contains( const Point &rDocPt ) const
342 {
343     ::tools::Rectangle aRect(GetPosPixel(), GetSizePixel());
344     return aRect.Contains(rDocPt);
345 }
346 
PaintButton()347 void SwHeaderFooterWin::PaintButton()
348 {
349     if (!m_xVirDev)
350         return;
351 
352     // Use pixels for the rest of the drawing
353     SetMapMode(MapMode(MapUnit::MapPixel));
354     drawinglayer::primitive2d::Primitive2DContainer aSeq;
355     const ::tools::Rectangle aRect(::tools::Rectangle(Point(0, 0), m_xVirDev->PixelToLogic(GetSizePixel())));
356 
357     SwFrameButtonPainter::PaintButton(aSeq, aRect, m_bIsHeader);
358 
359     // Create the text primitive
360     basegfx::BColor aLineColor = SwViewOption::GetCurrentViewOptions().GetHeaderFooterMarkColor().getBColor();
361     B2DVector aFontSize;
362     FontAttribute aFontAttr = drawinglayer::primitive2d::getFontAttributeFromVclFont(aFontSize, m_xVirDev->GetFont(), false, false);
363 
364     FontMetric aFontMetric = m_xVirDev->GetFontMetric(m_xVirDev->GetFont());
365     double nTextOffsetY = aFontMetric.GetAscent() + TEXT_PADDING;
366     Point aTextPos(TEXT_PADDING, nTextOffsetY);
367 
368     basegfx::B2DHomMatrix aTextMatrix(createScaleTranslateB2DHomMatrix(
369                                             aFontSize.getX(), aFontSize.getY(),
370                                             double(aTextPos.X()), double(aTextPos.Y())));
371 
372     aSeq.push_back(new drawinglayer::primitive2d::TextSimplePortionPrimitive2D(
373                         aTextMatrix, m_sLabel, 0, m_sLabel.getLength(),
374                         std::vector<double>(), {}, std::move(aFontAttr), css::lang::Locale(), aLineColor));
375 
376     // Create the 'plus' or 'arrow' primitive
377     B2DRectangle aSignArea(B2DPoint(aRect.Right() - BUTTON_WIDTH, 0.0),
378                            B2DVector(aRect.Right(), aRect.getOpenHeight()));
379 
380     B2DPolygon aSign;
381     bool bIsEmptyHeaderFooter = IsEmptyHeaderFooter();
382     if (bIsEmptyHeaderFooter)
383     {
384         // Create the + polygon
385         double nLeft = aSignArea.getMinX() + TEXT_PADDING;
386         double nRight = aSignArea.getMaxX() - TEXT_PADDING;
387         double nHalfW = ( nRight - nLeft ) / 2.0;
388 
389         double nTop = aSignArea.getCenterY() - nHalfW;
390         double nBottom = aSignArea.getCenterY() + nHalfW;
391 
392         aSign.append(B2DPoint(nLeft, aSignArea.getCenterY() - 1.0));
393         aSign.append(B2DPoint(aSignArea.getCenterX() - 1.0, aSignArea.getCenterY() - 1.0));
394         aSign.append(B2DPoint(aSignArea.getCenterX() - 1.0, nTop));
395         aSign.append(B2DPoint(aSignArea.getCenterX() + 1.0, nTop));
396         aSign.append(B2DPoint(aSignArea.getCenterX() + 1.0, aSignArea.getCenterY() - 1.0));
397         aSign.append(B2DPoint(nRight, aSignArea.getCenterY() - 1.0));
398         aSign.append(B2DPoint(nRight, aSignArea.getCenterY() + 1.0));
399         aSign.append(B2DPoint(aSignArea.getCenterX() + 1.0, aSignArea.getCenterY() + 1.0));
400         aSign.append(B2DPoint(aSignArea.getCenterX() + 1.0, nBottom));
401         aSign.append(B2DPoint(aSignArea.getCenterX() - 1.0, nBottom));
402         aSign.append(B2DPoint(aSignArea.getCenterX() - 1.0, aSignArea.getCenterY() + 1.0));
403         aSign.append(B2DPoint(nLeft, aSignArea.getCenterY() + 1.0));
404         aSign.setClosed(true);
405     }
406     else
407     {
408         // Create the v polygon
409         B2DPoint aLeft(aSignArea.getMinX() + TEXT_PADDING, aSignArea.getCenterY());
410         B2DPoint aRight(aSignArea.getMaxX() - TEXT_PADDING, aSignArea.getCenterY());
411         B2DPoint aBottom((aLeft.getX() + aRight.getX()) / 2.0, aLeft.getY() + 4.0);
412         aSign.append(aLeft);
413         aSign.append(aRight);
414         aSign.append(aBottom);
415         aSign.setClosed(true);
416     }
417 
418     BColor aSignColor = COL_BLACK.getBColor();
419     if (Application::GetSettings().GetStyleSettings().GetHighContrastMode())
420         aSignColor = COL_WHITE.getBColor();
421 
422     aSeq.push_back(new drawinglayer::primitive2d::PolyPolygonColorPrimitive2D(
423                                         B2DPolyPolygon(aSign), aSignColor) );
424 
425     // Create the processor and process the primitives
426     const drawinglayer::geometry::ViewInformation2D aNewViewInfos;
427     std::unique_ptr<drawinglayer::processor2d::BaseProcessor2D> pProcessor(
428         drawinglayer::processor2d::createProcessor2DFromOutputDevice(*m_xVirDev, aNewViewInfos));
429 
430     // TODO Ghost it all if needed
431     drawinglayer::primitive2d::Primitive2DContainer aGhostedSeq;
432     double nFadeRate = double(m_nFadeRate) / 100.0;
433 
434     basegfx::BColorModifierSharedPtr aBColorModifier =
435         std::make_shared<basegfx::BColorModifier_interpolate>(COL_WHITE.getBColor(),
436                                                 1.0 - nFadeRate);
437 
438     aGhostedSeq.push_back(new drawinglayer::primitive2d::ModifiedColorPrimitive2D(std::move(aSeq), std::move(aBColorModifier)));
439 
440     pProcessor->process(aGhostedSeq);
441 
442     if (bIsEmptyHeaderFooter)
443         m_xPushButton->set_custom_button(m_xVirDev.get());
444     else
445         m_xMenuButton->set_custom_button(m_xVirDev.get());
446 }
447 
IsEmptyHeaderFooter() const448 bool SwHeaderFooterWin::IsEmptyHeaderFooter( ) const
449 {
450     bool bResult = true;
451 
452     const SwPageFrame* pPageFrame = SwFrameMenuButtonBase::GetPageFrame(m_pFrame);
453     if (!pPageFrame)
454     {
455         return bResult;
456     }
457 
458     // Actually check it
459     const SwPageDesc* pDesc = pPageFrame->GetPageDesc();
460 
461     bool const bFirst(pPageFrame->OnFirstPage());
462     const SwFrameFormat *const pFormat = (pPageFrame->OnRightPage())
463         ? pDesc->GetRightFormat(bFirst)
464         : pDesc->GetLeftFormat(bFirst);
465 
466     if ( pFormat )
467     {
468         if ( m_bIsHeader )
469             bResult = !pFormat->GetHeader().IsActive();
470         else
471             bResult = !pFormat->GetFooter().IsActive();
472     }
473 
474     return bResult;
475 }
476 
ExecuteCommand(std::u16string_view rIdent)477 void SwHeaderFooterWin::ExecuteCommand(std::u16string_view rIdent)
478 {
479     SwView& rView = m_pEditWin->GetView();
480     SwWrtShell& rSh = rView.GetWrtShell();
481 
482     const SwPageFrame* pPageFrame = SwFrameMenuButtonBase::GetPageFrame(m_pFrame);
483     const UIName& rStyleName = pPageFrame->GetPageDesc()->GetName();
484     if (rIdent == u"edit")
485     {
486         OUString sPageId = m_bIsHeader ? u"header"_ustr : u"footer"_ustr;
487         rView.GetDocShell()->FormatPage(rView.GetFrameWeld(), rStyleName, sPageId, rSh);
488     }
489     else if (rIdent == u"borderback")
490     {
491         const SwPageDesc* pDesc = pPageFrame->GetPageDesc();
492         const SwFrameFormat& rMaster = pDesc->GetMaster();
493         SwFrameFormat* pHFFormat = const_cast< SwFrameFormat* >( rMaster.GetFooter().GetFooterFormat() );
494         if ( m_bIsHeader )
495             pHFFormat = const_cast< SwFrameFormat* >( rMaster.GetHeader().GetHeaderFormat() );
496         SfxItemSet aSet( pHFFormat->GetAttrSet() );
497 
498         // Items to hand over XPropertyList things like XColorList,
499         // XHatchList, XGradientList, and XBitmapList to the Area TabPage:
500         aSet.MergeRange( SID_COLOR_TABLE, SID_PATTERN_LIST );
501         // create needed items for XPropertyList entries from the DrawModel so that
502         // the Area TabPage can access them
503         rSh.GetDoc()->getIDocumentDrawModelAccess().GetDrawModel()->PutAreaListItems( aSet );
504 
505         aSet.MergeRange(SID_ATTR_BORDER_INNER, SID_ATTR_BORDER_INNER);
506         // Create a box info item... needed by the dialog
507         std::shared_ptr<SvxBoxInfoItem> aBoxInfo(std::make_shared<SvxBoxInfoItem>(SID_ATTR_BORDER_INNER));
508         if (const SvxBoxInfoItem *pBoxInfo = pHFFormat->GetAttrSet().GetItemIfSet(SID_ATTR_BORDER_INNER))
509             aBoxInfo.reset(pBoxInfo->Clone());
510 
511         aBoxInfo->SetTable(false);
512         aBoxInfo->SetDist(true);
513         aBoxInfo->SetMinDist(false);
514         aBoxInfo->SetDefDist(MIN_BORDER_DIST);
515         aBoxInfo->SetValid(SvxBoxInfoItemValidFlags::DISABLE);
516         aSet.Put(*aBoxInfo);
517 
518         if (svx::ShowBorderBackgroundDlg( GetFrameWeld(), &aSet ) )
519         {
520             pHFFormat->SetFormatAttr( aSet );
521             rView.GetDocShell()->SetModified();
522         }
523     }
524     else if (rIdent == u"delete")
525     {
526         rSh.ChangeHeaderOrFooter( rStyleName, m_bIsHeader, false, true );
527         // warning: "this" may be disposed now
528         rSh.GetWin()->GrabFocusToDocument();
529     }
530     else if (rIdent == u"insert_pagenumber")
531     {
532         SfxViewFrame& rVFrame = rSh.GetView().GetViewFrame();
533         rVFrame.GetBindings().Execute(FN_INSERT_FLD_PGNUMBER);
534     }
535     else if (rIdent == u"insert_pagecount")
536     {
537         SfxViewFrame& rVFrame = rSh.GetView().GetViewFrame();
538         rVFrame.GetBindings().Execute(FN_INSERT_FLD_PGCOUNT);
539     }
540     else if (rIdent == u"insert_pagecount_in_range")
541     {
542         SfxViewFrame& rVFrame = rSh.GetView().GetViewFrame();
543         rVFrame.GetBindings().Execute(FN_INSERT_FLD_RANGE_PGCOUNT);
544     }
545 }
546 
IMPL_LINK_NOARG(SwHeaderFooterWin,ClickHdl,weld::Button &,void)547 IMPL_LINK_NOARG(SwHeaderFooterWin, ClickHdl, weld::Button&, void)
548 {
549     SwView& rView = m_pEditWin->GetView();
550     SwWrtShell& rSh = rView.GetWrtShell();
551 
552     const SwPageFrame* pPageFrame = SwFrameMenuButtonBase::GetPageFrame(m_pFrame);
553     const UIName& rStyleName = pPageFrame->GetPageDesc()->GetName();
554     {
555         VclPtr<SwHeaderFooterWin> xThis(this);
556         rSh.ChangeHeaderOrFooter( rStyleName, m_bIsHeader, true, false );
557         //tdf#153059 after ChangeHeaderOrFooter is it possible that "this" is disposed
558         if (xThis->isDisposed())
559             return;
560     }
561     m_xPushButton->hide();
562     m_xMenuButton->show();
563     PaintButton();
564 }
565 
IMPL_LINK(SwHeaderFooterWin,SelectHdl,const OUString &,rIdent,void)566 IMPL_LINK(SwHeaderFooterWin, SelectHdl, const OUString&, rIdent, void)
567 {
568     ExecuteCommand(rIdent);
569 }
570 
IMPL_LINK_NOARG(SwHeaderFooterWin,FadeHandler,Timer *,void)571 IMPL_LINK_NOARG(SwHeaderFooterWin, FadeHandler, Timer *, void)
572 {
573     if (m_bIsAppearing && m_nFadeRate > 0)
574         m_nFadeRate -= 25;
575     else if (!m_bIsAppearing && m_nFadeRate < 100)
576         m_nFadeRate += 25;
577 
578     if (m_nFadeRate != 100 && !IsVisible())
579     {
580         Show();
581     }
582     else if (m_nFadeRate == 100 && IsVisible())
583     {
584         Show(false);
585     }
586     else
587         PaintButton();
588 
589     if (IsVisible() && m_nFadeRate > 0 && m_nFadeRate < 100)
590         m_aFadeTimer.Start();
591 }
592 
593 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
594