1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
3 * This file is part of the LibreOffice project.
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/.
10 #include <contentcontrolbutton.hxx>
13 #include <vcl/weldutils.hxx>
14 #include <vcl/event.hxx>
15 #include <vcl/decoview.hxx>
20 SwContentControlButton::SwContentControlButton(SwEditWin
* pEditWin
,
21 std::shared_ptr
<SwContentControl
> pContentControl
)
22 : Control(pEditWin
, WB_DIALOGCONTROL
)
23 , m_pContentControl(std::move(pContentControl
))
26 assert(dynamic_cast<SwEditWin
*>(GetParent()));
29 EnableChildTransparentMode();
30 SetParentClipMode(ParentClipMode::NoClip
);
31 SetPaintTransparent(true);
34 SwContentControlButton::~SwContentControlButton() { disposeOnce(); }
36 void SwContentControlButton::LaunchPopup()
38 m_xPopup
->connect_closed(LINK(this, SwContentControlButton
, PopupModeEndHdl
));
40 tools::Rectangle
aRect(Point(0, 0), GetSizePixel());
41 weld::Window
* pParent
= weld::GetPopupParent(*this, aRect
);
42 m_xPopup
->popup_at_rect(pParent
, aRect
);
45 void SwContentControlButton::DestroyPopup()
48 m_xPopupBuilder
.reset();
51 void SwContentControlButton::dispose()
57 void SwContentControlButton::CalcPosAndSize(const SwRect
& rPortionPaintArea
)
61 Point aBoxPos
= GetParent()->LogicToPixel(rPortionPaintArea
.Pos());
62 Size aBoxSize
= GetParent()->LogicToPixel(rPortionPaintArea
.SSize());
64 // First calculate the size of the frame around the content control's last portion
65 int nPadding
= aBoxSize
.Height() / 4;
66 aBoxPos
.AdjustX(-nPadding
/ 2);
68 aBoxSize
.AdjustWidth(nPadding
);
69 aBoxSize
.AdjustHeight(2);
71 m_aFramePixel
= tools::Rectangle(aBoxPos
, aBoxSize
);
73 // Then extend the size with the button area
76 aBoxPos
.AdjustX(-GetParent()->LogicToPixel(rPortionPaintArea
.SSize()).Height());
78 aBoxSize
.AdjustWidth(GetParent()->LogicToPixel(rPortionPaintArea
.SSize()).Height());
80 if (aBoxPos
!= GetPosPixel() || aBoxSize
!= GetSizePixel())
82 SetPosSizePixel(aBoxPos
, aBoxSize
);
87 void SwContentControlButton::MouseButtonDown(const MouseEvent
&) { StartPopup(); }
89 void SwContentControlButton::StartPopup()
91 if (m_xPopup
) // tdf#152257 already launched, don't relaunch
97 IMPL_LINK_NOARG(SwContentControlButton
, PopupModeEndHdl
, weld::Popover
&, void)
104 void SwContentControlButton::Paint(vcl::RenderContext
& rRenderContext
, const tools::Rectangle
&)
106 SetMapMode(MapMode(MapUnit::MapPixel
));
108 Color aLineColor
= COL_BLACK
;
109 Color aFillColor
= aLineColor
;
110 aFillColor
.IncreaseLuminance(255 * (m_xPopup
? 0.5 : 0.75));
112 // Calc the frame around the content control's last portion
114 Point
aPos(nPadding
, nPadding
);
115 Size
aSize(m_aFramePixel
.GetSize().Width() - nPadding
,
116 m_aFramePixel
.GetSize().Height() - nPadding
);
117 const tools::Rectangle
aFrameRect(tools::Rectangle(aPos
, aSize
));
119 // Draw the button next to the frame
120 Point
aButtonPos(aFrameRect
.TopLeft());
123 aButtonPos
.AdjustX(nPadding
* 2);
127 aButtonPos
.AdjustX(aFrameRect
.GetSize().getWidth() - nPadding
* 2);
129 Size
aButtonSize(aFrameRect
.GetSize());
130 aButtonSize
.setWidth(GetSizePixel().getWidth() - aFrameRect
.getOpenWidth() - nPadding
);
131 const tools::Rectangle
aButtonRect(tools::Rectangle(aButtonPos
, aButtonSize
));
133 // Background & border
134 rRenderContext
.SetLineColor(aLineColor
);
135 rRenderContext
.SetFillColor(aFillColor
);
136 rRenderContext
.DrawRect(aButtonRect
);
139 DecorationView
aDecoView(&rRenderContext
);
140 tools::Rectangle
aSymbolRect(aButtonRect
);
141 // 20% distance to the left and right button border
142 const tools::Long nBorderDistanceLeftAndRight
= aSymbolRect
.GetWidth() / 4;
143 aSymbolRect
.AdjustLeft(nBorderDistanceLeftAndRight
);
144 aSymbolRect
.AdjustRight(-nBorderDistanceLeftAndRight
);
145 // 20% distance to the top and bottom button border
146 const tools::Long nBorderDistanceTopAndBottom
= aSymbolRect
.GetHeight() / 4;
147 aSymbolRect
.AdjustTop(nBorderDistanceTopAndBottom
);
148 aSymbolRect
.AdjustBottom(-nBorderDistanceTopAndBottom
);
149 AntialiasingFlags eAntialiasing
= rRenderContext
.GetAntialiasing();
150 if (SwDrawView::IsAntiAliasing())
152 rRenderContext
.SetAntialiasing(eAntialiasing
| AntialiasingFlags::Enable
);
154 aDecoView
.DrawSymbol(aSymbolRect
, SymbolType::SPIN_DOWN
, GetTextColor(), DrawSymbolFlags::NONE
);
155 if (SwDrawView::IsAntiAliasing())
157 rRenderContext
.SetAntialiasing(eAntialiasing
);
161 WindowHitTest
SwContentControlButton::ImplHitTest(const Point
& rFramePos
)
163 // We need to check whether the position hits the button (the frame should be mouse transparent)
164 WindowHitTest aResult
= Control::ImplHitTest(rFramePos
);
165 if (aResult
!= WindowHitTest::Inside
)
171 return rFramePos
.X() <= m_aFramePixel
.Left() ? WindowHitTest::Inside
172 : WindowHitTest::Transparent
;
174 return rFramePos
.X() >= m_aFramePixel
.Right() ? WindowHitTest::Inside
175 : WindowHitTest::Transparent
;
179 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */