LibreOffice Module sw (master)  1
FormFieldButton.cxx
Go to the documentation of this file.
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.
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 
11 #include <edtwin.hxx>
13 #include <bookmark.hxx>
14 #include <vcl/weldutils.hxx>
15 #include <vcl/event.hxx>
16 
18  : Control(pEditWin, WB_DIALOGCONTROL)
19  , m_rFieldmark(rFieldmark)
20 {
21  assert(GetParent());
22  assert(dynamic_cast<SwEditWin*>(GetParent()));
23 
24  SetBackground();
26  SetParentClipMode(ParentClipMode::NoClip);
27  SetPaintTransparent(true);
28 }
29 
31 
33 {
34  m_xFieldPopup->connect_closed(LINK(this, DropDownFormFieldButton, FieldPopupModeEndHdl));
35 
36  tools::Rectangle aRect(Point(0, 0), GetSizePixel());
37  weld::Window* pParent = weld::GetPopupParent(*this, aRect);
38  m_xFieldPopup->popup_at_rect(pParent, aRect);
39 }
40 
42 {
43  m_xFieldPopup.reset();
44  m_xFieldPopupBuilder.reset();
45 }
46 
48 {
49  DestroyPopup();
51 }
52 
53 void FormFieldButton::CalcPosAndSize(const SwRect& rPortionPaintArea)
54 {
55  assert(GetParent());
56 
57  Point aBoxPos = GetParent()->LogicToPixel(rPortionPaintArea.Pos());
58  Size aBoxSize = GetParent()->LogicToPixel(rPortionPaintArea.SSize());
59 
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);
66 
67  m_aFieldFramePixel = tools::Rectangle(aBoxPos, aBoxSize);
68 
69  // Then extend the size with the button area
70  aBoxSize.AdjustWidth(GetParent()->LogicToPixel(rPortionPaintArea.SSize()).Height());
71 
72  if (aBoxPos != GetPosPixel() || aBoxSize != GetSizePixel())
73  {
74  SetPosSizePixel(aBoxPos, aBoxSize);
75  Invalidate();
76  }
77 }
78 
80 {
81  LaunchPopup();
82  Invalidate();
83 }
84 
85 IMPL_LINK_NOARG(FormFieldButton, FieldPopupModeEndHdl, weld::Popover&, void)
86 {
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();
92 }
93 
94 static basegfx::BColor lcl_GetFillColor(const basegfx::BColor& rLineColor, double aLuminance)
95 {
96  basegfx::BColor aHslLine = basegfx::utils::rgb2hsl(rLineColor);
97  aHslLine.setZ(aLuminance);
98  return basegfx::utils::hsl2rgb(aHslLine);
99 }
100 
102 {
103  SetMapMode(MapMode(MapUnit::MapPixel));
104 
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)));
108 
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);
119 
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.getWidth() - nPadding);
125  const tools::Rectangle aButtonRect(tools::Rectangle(aButtonPos, aButtonSize));
126 
127  // Background & border
128  rRenderContext.SetLineColor(aLineColor);
129  rRenderContext.SetFillColor(aFillColor);
130  rRenderContext.DrawRect(aButtonRect);
131 
132  // the arrowhead
133  rRenderContext.SetLineColor(aLineColor);
134  rRenderContext.SetFillColor(aLineColor);
135 
136  Point aCenter(aButtonPos.X() + (aButtonSize.Width() / 2),
137  aButtonPos.Y() + (aButtonSize.Height() / 2));
138  Size aArrowSize(aButtonSize.Width() / 4, aButtonSize.Height() / 10);
139 
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);
145 }
146 
148 {
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
154  {
155  return rFramePos.X() >= m_aFieldFramePixel.Right() ? WindowHitTest::Inside
156  : WindowHitTest::Transparent;
157  }
158 }
159 
160 /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
virtual Point GetPosPixel() const
void SetBackground()
BColor rgb2hsl(const BColor &rRGBColor)
WindowHitTest
void setWidth(tools::Long nWidth)
virtual WindowHitTest ImplHitTest(const Point &rFramePos)
constexpr::Color COL_TRANSPARENT(ColorTransparency, 0xFF, 0xFF, 0xFF, 0xFF)
void DrawPolygon(const tools::Polygon &rPoly)
virtual Size GetSizePixel() const
virtual WindowHitTest ImplHitTest(const Point &rFramePos) override
void SetParentClipMode(ParentClipMode nMode=ParentClipMode::NONE)
void Pos(const Point &rNew)
Definition: swrect.hxx:171
Of course Writer needs its own rectangles.
Definition: swrect.hxx:34
static basegfx::BColor lcl_GetFillColor(const basegfx::BColor &rLineColor, double aLuminance)
constexpr tools::Long Width() const
IMPL_LINK_NOARG(FormFieldButton, FieldPopupModeEndHdl, weld::Popover &, void)
void setZ(double fZ)
std::unique_ptr< weld::Builder > m_xFieldPopupBuilder
void DrawRect(const tools::Rectangle &rRect)
This button is shown when the cursor is on a form field with drop-down capability.
BColor hsl2rgb(const BColor &rHSLColor)
WinBits const WB_DIALOGCONTROL
void SetLineColor()
std::unique_ptr< weld::Popover > m_xFieldPopup
Point LogicToPixel(const Point &rLogicPt) const
Window class for the Writer edit area, this is the one handling mouse and keyboard events and doing t...
Definition: edtwin.hxx:58
weld::Window * GetPopupParent(vcl::Window &rOutWin, tools::Rectangle &rRect)
void CalcPosAndSize(const SwRect &rPortionPaintArea)
tools::Rectangle m_aFieldFramePixel
virtual void Invalidate(InvalidateFlags nFlags=InvalidateFlags::NONE)
constexpr tools::Long Right() const
void SetFillColor()
virtual void dispose() override
void SetPaintTransparent(bool bTransparent)
void SSize(const Size &rNew)
Definition: swrect.hxx:180
vcl::Window * GetParent() const
virtual ~FormFieldButton() override
virtual void SetPosSizePixel(const Point &rNewPos, const Size &rNewSize)
virtual void dispose() override
constexpr Size GetSize() const
constexpr tools::Long Height() const
virtual void Paint(vcl::RenderContext &rRenderContext, const tools::Rectangle &rRect) override
void EnableChildTransparentMode(bool bEnable=true)
tools::Long AdjustWidth(tools::Long n)
const ::std::vector< Color > ImpSvNumberformatScan::StandardColor COL_BLACK
tools::Long AdjustHeight(tools::Long n)
FormFieldButton(SwEditWin *pEditWin, sw::mark::Fieldmark &rFieldMark)
basegfx::BColor getBColor() const
virtual void LaunchPopup()
virtual void MouseButtonDown(const MouseEvent &rMEvt) override
constexpr tools::Long getWidth() const
virtual void DestroyPopup()
void SetMapMode()
This button is shown when the cursor is on a drop-down form field.