Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / sw / source / core / crsr / contentcontrolbutton.cxx
blob0d805cb492c321d0d2edd4f494e49ce71b7399b0
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
2 /*
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/.
8 */
10 #include <contentcontrolbutton.hxx>
12 #include <utility>
13 #include <vcl/weldutils.hxx>
14 #include <vcl/event.hxx>
15 #include <vcl/decoview.hxx>
17 #include <edtwin.hxx>
18 #include <dview.hxx>
20 SwContentControlButton::SwContentControlButton(SwEditWin* pEditWin,
21 std::shared_ptr<SwContentControl> pContentControl)
22 : Control(pEditWin, WB_DIALOGCONTROL)
23 , m_pContentControl(std::move(pContentControl))
25 assert(GetParent());
26 assert(dynamic_cast<SwEditWin*>(GetParent()));
28 SetBackground();
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()
47 m_xPopup.reset();
48 m_xPopupBuilder.reset();
51 void SwContentControlButton::dispose()
53 DestroyPopup();
54 Control::dispose();
57 void SwContentControlButton::CalcPosAndSize(const SwRect& rPortionPaintArea)
59 assert(GetParent());
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);
67 aBoxPos.AdjustY(-1);
68 aBoxSize.AdjustWidth(nPadding);
69 aBoxSize.AdjustHeight(2);
71 m_aFramePixel = tools::Rectangle(aBoxPos, aBoxSize);
73 // Then extend the size with the button area
74 if (m_bRTL)
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);
83 Invalidate();
87 void SwContentControlButton::MouseButtonDown(const MouseEvent&) { StartPopup(); }
89 void SwContentControlButton::StartPopup()
91 if (m_xPopup) // tdf#152257 already launched, don't relaunch
92 return;
93 LaunchPopup();
94 Invalidate();
97 IMPL_LINK_NOARG(SwContentControlButton, PopupModeEndHdl, weld::Popover&, void)
99 DestroyPopup();
100 Show(false);
101 Invalidate();
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
113 int nPadding = 1;
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());
121 if (m_bRTL)
123 aButtonPos.AdjustX(nPadding * 2);
125 else
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);
138 // the arrowhead
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)
166 return aResult;
167 else
169 if (m_bRTL)
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: */