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 <DropDownFormFieldButton.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
)
22 assert(dynamic_cast<SwEditWin
*>(GetParent()));
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()
53 void FormFieldButton::CalcPosAndSize(const SwRect
& rPortionPaintArea
)
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
);
79 void FormFieldButton::MouseButtonDown(const MouseEvent
&)
85 IMPL_LINK_NOARG(FormFieldButton
, FieldPopupModeEndHdl
, weld::Popover
&, void)
88 m_rFieldmark
.Invalidate();
89 // Hide the button here and make it visible later, to make transparent background work with SAL_USE_VCLPLUGIN=gen
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
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
);
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
)
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: */