179 lines
5.8 KiB
C++
179 lines
5.8 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
|
|
/*
|
|
* This file is part of the LibreOffice project.
|
|
*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
*/
|
|
|
|
#include <contentcontrolbutton.hxx>
|
|
|
|
#include <utility>
|
|
#include <vcl/weldutils.hxx>
|
|
#include <vcl/event.hxx>
|
|
#include <vcl/decoview.hxx>
|
|
|
|
#include <edtwin.hxx>
|
|
#include <dview.hxx>
|
|
|
|
SwContentControlButton::SwContentControlButton(SwEditWin* pEditWin,
|
|
std::shared_ptr<SwContentControl> pContentControl)
|
|
: Control(pEditWin, WB_DIALOGCONTROL)
|
|
, m_pContentControl(std::move(pContentControl))
|
|
{
|
|
assert(GetParent());
|
|
assert(dynamic_cast<SwEditWin*>(GetParent()));
|
|
|
|
SetBackground();
|
|
EnableChildTransparentMode();
|
|
SetParentClipMode(ParentClipMode::NoClip);
|
|
SetPaintTransparent(true);
|
|
}
|
|
|
|
SwContentControlButton::~SwContentControlButton() { disposeOnce(); }
|
|
|
|
void SwContentControlButton::LaunchPopup()
|
|
{
|
|
m_xPopup->connect_closed(LINK(this, SwContentControlButton, PopupModeEndHdl));
|
|
|
|
tools::Rectangle aRect(Point(0, 0), GetSizePixel());
|
|
weld::Window* pParent = weld::GetPopupParent(*this, aRect);
|
|
m_xPopup->popup_at_rect(pParent, aRect);
|
|
}
|
|
|
|
void SwContentControlButton::DestroyPopup()
|
|
{
|
|
m_xPopup.reset();
|
|
m_xPopupBuilder.reset();
|
|
}
|
|
|
|
void SwContentControlButton::dispose()
|
|
{
|
|
DestroyPopup();
|
|
Control::dispose();
|
|
}
|
|
|
|
void SwContentControlButton::CalcPosAndSize(const SwRect& rPortionPaintArea)
|
|
{
|
|
assert(GetParent());
|
|
|
|
Point aBoxPos = GetParent()->LogicToPixel(rPortionPaintArea.Pos());
|
|
Size aBoxSize = GetParent()->LogicToPixel(rPortionPaintArea.SSize());
|
|
|
|
// First calculate the size of the frame around the content control's last portion
|
|
int nPadding = aBoxSize.Height() / 4;
|
|
aBoxPos.AdjustX(-nPadding / 2);
|
|
aBoxPos.AdjustY(-1);
|
|
aBoxSize.AdjustWidth(nPadding);
|
|
aBoxSize.AdjustHeight(2);
|
|
|
|
m_aFramePixel = tools::Rectangle(aBoxPos, aBoxSize);
|
|
|
|
// Then extend the size with the button area
|
|
if (m_bRTL)
|
|
{
|
|
aBoxPos.AdjustX(-GetParent()->LogicToPixel(rPortionPaintArea.SSize()).Height());
|
|
}
|
|
aBoxSize.AdjustWidth(GetParent()->LogicToPixel(rPortionPaintArea.SSize()).Height());
|
|
|
|
if (aBoxPos != GetPosPixel() || aBoxSize != GetSizePixel())
|
|
{
|
|
SetPosSizePixel(aBoxPos, aBoxSize);
|
|
Invalidate();
|
|
}
|
|
}
|
|
|
|
void SwContentControlButton::MouseButtonDown(const MouseEvent&) { StartPopup(); }
|
|
|
|
void SwContentControlButton::StartPopup()
|
|
{
|
|
if (m_xPopup) // tdf#152257 already launched, don't relaunch
|
|
return;
|
|
LaunchPopup();
|
|
Invalidate();
|
|
}
|
|
|
|
IMPL_LINK_NOARG(SwContentControlButton, PopupModeEndHdl, weld::Popover&, void)
|
|
{
|
|
DestroyPopup();
|
|
Show(false);
|
|
Invalidate();
|
|
}
|
|
|
|
void SwContentControlButton::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle&)
|
|
{
|
|
SetMapMode(MapMode(MapUnit::MapPixel));
|
|
|
|
Color aLineColor = COL_BLACK;
|
|
Color aFillColor = aLineColor;
|
|
aFillColor.IncreaseLuminance(255 * (m_xPopup ? 0.5 : 0.75));
|
|
|
|
// Calc the frame around the content control's last portion
|
|
int nPadding = 1;
|
|
Point aPos(nPadding, nPadding);
|
|
Size aSize(m_aFramePixel.GetSize().Width() - nPadding,
|
|
m_aFramePixel.GetSize().Height() - nPadding);
|
|
const tools::Rectangle aFrameRect(tools::Rectangle(aPos, aSize));
|
|
|
|
// Draw the button next to the frame
|
|
Point aButtonPos(aFrameRect.TopLeft());
|
|
if (m_bRTL)
|
|
{
|
|
aButtonPos.AdjustX(nPadding * 2);
|
|
}
|
|
else
|
|
{
|
|
aButtonPos.AdjustX(aFrameRect.GetSize().getWidth() - nPadding * 2);
|
|
}
|
|
Size aButtonSize(aFrameRect.GetSize());
|
|
aButtonSize.setWidth(GetSizePixel().getWidth() - aFrameRect.getOpenWidth() - nPadding);
|
|
const tools::Rectangle aButtonRect(tools::Rectangle(aButtonPos, aButtonSize));
|
|
|
|
// Background & border
|
|
rRenderContext.SetLineColor(aLineColor);
|
|
rRenderContext.SetFillColor(aFillColor);
|
|
rRenderContext.DrawRect(aButtonRect);
|
|
|
|
// the arrowhead
|
|
DecorationView aDecoView(&rRenderContext);
|
|
tools::Rectangle aSymbolRect(aButtonRect);
|
|
// 20% distance to the left and right button border
|
|
const tools::Long nBorderDistanceLeftAndRight = aSymbolRect.GetWidth() / 4;
|
|
aSymbolRect.AdjustLeft(nBorderDistanceLeftAndRight);
|
|
aSymbolRect.AdjustRight(-nBorderDistanceLeftAndRight);
|
|
// 20% distance to the top and bottom button border
|
|
const tools::Long nBorderDistanceTopAndBottom = aSymbolRect.GetHeight() / 4;
|
|
aSymbolRect.AdjustTop(nBorderDistanceTopAndBottom);
|
|
aSymbolRect.AdjustBottom(-nBorderDistanceTopAndBottom);
|
|
AntialiasingFlags eAntialiasing = rRenderContext.GetAntialiasing();
|
|
if (SwDrawView::IsAntiAliasing())
|
|
{
|
|
rRenderContext.SetAntialiasing(eAntialiasing | AntialiasingFlags::Enable);
|
|
}
|
|
aDecoView.DrawSymbol(aSymbolRect, SymbolType::SPIN_DOWN, GetTextColor(), DrawSymbolFlags::NONE);
|
|
if (SwDrawView::IsAntiAliasing())
|
|
{
|
|
rRenderContext.SetAntialiasing(eAntialiasing);
|
|
}
|
|
}
|
|
|
|
WindowHitTest SwContentControlButton::ImplHitTest(const Point& rFramePos)
|
|
{
|
|
// We need to check whether the position hits the button (the frame should be mouse transparent)
|
|
WindowHitTest aResult = Control::ImplHitTest(rFramePos);
|
|
if (aResult != WindowHitTest::Inside)
|
|
return aResult;
|
|
else
|
|
{
|
|
if (m_bRTL)
|
|
{
|
|
return rFramePos.X() <= m_aFramePixel.Left() ? WindowHitTest::Inside
|
|
: WindowHitTest::Transparent;
|
|
}
|
|
return rFramePos.X() >= m_aFramePixel.Right() ? WindowHitTest::Inside
|
|
: WindowHitTest::Transparent;
|
|
}
|
|
}
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|