Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / sw / source / core / crsr / FormFieldButton.cxx
blob319dcdb9c0dd6f6f3891df6a3397d72023ca25c3
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 <DropDownFormFieldButton.hxx>
11 #include <edtwin.hxx>
12 #include <basegfx/color/bcolortools.hxx>
13 #include <bookmark.hxx>
14 #include <vcl/weldutils.hxx>
15 #include <vcl/event.hxx>
17 FormFieldButton::FormFieldButton(SwEditWin* pEditWin, sw::mark::Fieldmark& rFieldmark)
18 : Control(pEditWin, WB_DIALOGCONTROL)
19 , m_rFieldmark(rFieldmark)
21 assert(GetParent());
22 assert(dynamic_cast<SwEditWin*>(GetParent()));
24 SetBackground();
25 EnableChildTransparentMode();
26 SetParentClipMode(ParentClipMode::NoClip);
27 SetPaintTransparent(true);
30 FormFieldButton::~FormFieldButton() { disposeOnce(); }
32 void FormFieldButton::LaunchPopup()
34 m_xFieldPopup->connect_closed(LINK(this, DropDownFormFieldButton, FieldPopupModeEndHdl));
36 tools::Rectangle aRect(Point(0, 0), GetSizePixel());
37 weld::Window* pParent = weld::GetPopupParent(*this, aRect);
38 m_xFieldPopup->popup_at_rect(pParent, aRect);
41 void FormFieldButton::DestroyPopup()
43 m_xFieldPopup.reset();
44 m_xFieldPopupBuilder.reset();
47 void FormFieldButton::dispose()
49 DestroyPopup();
50 Control::dispose();
53 void FormFieldButton::CalcPosAndSize(const SwRect& rPortionPaintArea)
55 assert(GetParent());
57 Point aBoxPos = GetParent()->LogicToPixel(rPortionPaintArea.Pos());
58 Size aBoxSize = GetParent()->LogicToPixel(rPortionPaintArea.SSize());
60 // First calculate the size of the frame around the field
61 int nPadding = aBoxSize.Height() / 4;
62 aBoxPos.AdjustX(-nPadding);
63 aBoxPos.AdjustY(-nPadding);
64 aBoxSize.AdjustWidth(2 * nPadding);
65 aBoxSize.AdjustHeight(2 * nPadding);
67 m_aFieldFramePixel = tools::Rectangle(aBoxPos, aBoxSize);
69 // Then extend the size with the button area
70 aBoxSize.AdjustWidth(GetParent()->LogicToPixel(rPortionPaintArea.SSize()).Height());
72 if (aBoxPos != GetPosPixel() || aBoxSize != GetSizePixel())
74 SetPosSizePixel(aBoxPos, aBoxSize);
75 Invalidate();
79 void FormFieldButton::MouseButtonDown(const MouseEvent&)
81 LaunchPopup();
82 Invalidate();
85 IMPL_LINK_NOARG(FormFieldButton, FieldPopupModeEndHdl, weld::Popover&, void)
87 DestroyPopup();
88 m_rFieldmark.Invalidate();
89 // Hide the button here and make it visible later, to make transparent background work with SAL_USE_VCLPLUGIN=gen
90 Show(false);
91 Invalidate();
94 static basegfx::BColor lcl_GetFillColor(const basegfx::BColor& rLineColor, double aLuminance)
96 basegfx::BColor aHslLine = basegfx::utils::rgb2hsl(rLineColor);
97 aHslLine.setZ(aLuminance);
98 return basegfx::utils::hsl2rgb(aHslLine);
101 void FormFieldButton::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle&)
103 SetMapMode(MapMode(MapUnit::MapPixel));
105 //const StyleSettings& rSettings = Application::GetSettings().GetStyleSettings();
106 Color aLineColor = COL_BLACK;
107 Color aFillColor(lcl_GetFillColor(aLineColor.getBColor(), (m_xFieldPopup ? 0.5 : 0.75)));
109 // Draw the frame around the field
110 // GTK3 backend cuts down the frame's top and left border, to avoid that add a padding around the frame
111 int nPadding = 1;
112 Point aPos(nPadding, nPadding);
113 Size aSize(m_aFieldFramePixel.GetSize().Width() - nPadding,
114 m_aFieldFramePixel.GetSize().Height() - nPadding);
115 const tools::Rectangle aFrameRect(tools::Rectangle(aPos, aSize));
116 rRenderContext.SetLineColor(aLineColor);
117 rRenderContext.SetFillColor(COL_TRANSPARENT);
118 rRenderContext.DrawRect(aFrameRect);
120 // Draw the button next to the frame
121 Point aButtonPos(aFrameRect.TopLeft());
122 aButtonPos.AdjustX(aFrameRect.GetSize().getWidth() - 1);
123 Size aButtonSize(aFrameRect.GetSize());
124 aButtonSize.setWidth(GetSizePixel().getWidth() - aFrameRect.getOpenWidth() - nPadding);
125 const tools::Rectangle aButtonRect(tools::Rectangle(aButtonPos, aButtonSize));
127 // Background & border
128 rRenderContext.SetLineColor(aLineColor);
129 rRenderContext.SetFillColor(aFillColor);
130 rRenderContext.DrawRect(aButtonRect);
132 // the arrowhead
133 rRenderContext.SetLineColor(aLineColor);
134 rRenderContext.SetFillColor(aLineColor);
136 Point aCenter(aButtonPos.X() + (aButtonSize.Width() / 2),
137 aButtonPos.Y() + (aButtonSize.Height() / 2));
138 Size aArrowSize(aButtonSize.Width() / 4, aButtonSize.Height() / 10);
140 tools::Polygon aPoly(3);
141 aPoly.SetPoint(Point(aCenter.X() - aArrowSize.Width(), aCenter.Y() - aArrowSize.Height()), 0);
142 aPoly.SetPoint(Point(aCenter.X() + aArrowSize.Width(), aCenter.Y() - aArrowSize.Height()), 1);
143 aPoly.SetPoint(Point(aCenter.X(), aCenter.Y() + aArrowSize.Height()), 2);
144 rRenderContext.DrawPolygon(aPoly);
147 WindowHitTest FormFieldButton::ImplHitTest(const Point& rFramePos)
149 // We need to check whether the position hits the button (the frame should be mouse transparent)
150 WindowHitTest aResult = Control::ImplHitTest(rFramePos);
151 if (aResult != WindowHitTest::Inside)
152 return aResult;
153 else
155 return rFramePos.X() >= m_aFieldFramePixel.Right() ? WindowHitTest::Inside
156 : WindowHitTest::Transparent;
160 /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */