1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
|
// ************************************************************************************************
//
// BornAgain: simulate and fit reflection and scattering
//
//! @file GUI/View/Overlay/IMaskOverlay.cpp
//! @brief Implements interfaces IMaskOverlay.
//!
//! @homepage http://www.bornagainproject.org
//! @license GNU General Public License v3 or higher (see COPYING)
//! @copyright Forschungszentrum Jülich GmbH 2018
//! @authors Scientific Computing Group at MLZ (see CITATION, AUTHORS)
//
// ************************************************************************************************
#include "GUI/View/Overlay/IMaskOverlay.h"
#include "Base/Util/Assert.h"
#include "GUI/Model/Mask/MaskItems.h"
#include "GUI/View/Overlay/OverlayStyle.h"
#include "GUI/View/Plotter/ColorMap.h"
#include <QGraphicsScene>
namespace {
bool itemMaskValue(const OverlayItem* item)
{
ASSERT(item);
if (const auto* maskItem = dynamic_cast<const MaskItem*>(item))
return maskItem->maskValue();
return false;
}
void subtractTransmittingMasks(QPainterPath& result, qreal z, QVector<QGraphicsItem*> items)
{
for (const QGraphicsItem* item : items) {
const auto* overlay = dynamic_cast<const IOverlay*>(item);
if (!overlay)
continue;
if (!dynamic_cast<const IMaskOverlay*>(overlay))
continue;
if (::itemMaskValue(overlay->parameterizedItem()))
continue;
if (const auto* mask_item = dynamic_cast<const MaskItem*>(overlay->parameterizedItem()))
if (!mask_item->isVisible())
continue;
if (overlay->zValue() <= z)
continue;
const QPainterPath mask_shape = overlay->mapToScene(overlay->shape());
if (!mask_shape.intersects(result))
continue;
// Item lays on top and is non-masking -> subtract the path of the item
result = result.subtracted(mask_shape);
}
}
} // namespace
IMaskOverlay::IMaskOverlay(ColorMap* plot)
: IOverlay(plot)
{
setFlags(QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemIsMovable
| QGraphicsItem::ItemSendsGeometryChanges);
}
void IMaskOverlay::paint(QPainter* painter, const QStyleOptionGraphicsItem*, QWidget*)
{
const bool is_masked = ::itemMaskValue(parameterizedItem());
painter->setBrush(GUI::Overlay::getMaskBrush(is_masked));
painter->setPen(GUI::Overlay::getMaskPen(is_masked));
painter->setRenderHints(QPainter::Antialiasing);
painter->drawPath(maskedShape());
}
QPainterPath IMaskOverlay::maskedShape() const
{
QPainterPath result = mapToScene(shape());
::subtractTransmittingMasks(result, zValue(), scene()->items());
return mapFromScene(result);
}
void IMaskOverlay::onVisibilityChange()
{
if (m_block_on_property_change)
return;
m_block_on_property_change = true;
if (auto* maskItem = dynamic_cast<MaskItem*>(parameterizedItem()))
setVisible(maskItem->isVisible());
else
hide();
onPropertyChange();
update();
m_block_on_property_change = false;
}
|