Files
qt-migration-legatus/qt6-after/qt6-migrated-legatus/Lts/Viewer/SituationMap/GraphicalObjects/graphical_object_text.cpp
T

345 lines
11 KiB
C++
Executable File

/**
* @RDE_HEADER@
* GraphicalObjectText
* $Id$
* $HeadURL$
* $Author$
*/
// Own
#include "graphical_object_text.h"
#include <Map/situation_map_utils.h> // operator<<
// ESRI
#include <GraphicsOverlay.h>
#include <TextSymbol.h>
#include <PictureMarkerSymbol.h>
#include <SymbolTypes.h>
#include <Graphic.h>
#include <Point.h>
#include <SpatialReference.h>
// Qt
#include <QString>
#include <iostream>
#include <algorithm>
namespace SituationMap
{
GraphicalObjectText::GraphicalObjectText(const Esri::ArcGISRuntime::GeoView *geoView
, Esri::ArcGISRuntime::GraphicsOverlay *graphicsLayer
, const QString &debugInfo
, const UniqueMapId &uniqueMapId)
: BaseClass(geoView, graphicsLayer, debugInfo, uniqueMapId)
, m_textSymbol(nullptr)
, m_logger(getLogger("GraphicalObjectText"))
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'";
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'";
}
GraphicalObjectText::~GraphicalObjectText()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'"
<< " text='" << m_text << "'";
delete m_textSymbol;
m_textSymbol = nullptr;
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'"
<< " text='" << m_text << "'";
}
QString GraphicalObjectText::toString() const
{
QString str;
// str.append( BaseClass::toString() );
if (!m_debugInfo.isEmpty())
str.append(QStringLiteral("debugInfo=%1").arg(m_debugInfo));
if (m_graphicsLayer)
str.append(QStringLiteral(" layer='%1'").arg(m_graphicsLayer->objectName()));
if (m_graphic)
str.append(QStringLiteral(" zIndex='%1'").arg(m_graphic->zIndex()));
std::ostringstream stream;
stream << this->origin();
str.append(QLatin1String(stream.str().c_str()));
if (!m_text.value().isEmpty())
str.append(QStringLiteral("text=%1").arg(m_text.value()));
return str;
}
QString GraphicalObjectText::text() const
{
return m_text.value();
}
void GraphicalObjectText::setText(const QString &text)
{
m_text = text;
}
TextStyle GraphicalObjectText::textStyle() const
{
return m_textStyle.value();
}
TextStyle &GraphicalObjectText::rTextStyle()
{
return m_textStyle.refValue();
}
void GraphicalObjectText::setTextStyle(const TextStyle &textStyle)
{
m_textStyle = textStyle;
}
float GraphicalObjectText::xOffset() const
{
return m_offset.value().x();
}
void GraphicalObjectText::setXOffset(float xOffset)
{
QPointF temp = m_offset.value();
temp.rx() = xOffset;
m_offset = temp;
}
float GraphicalObjectText::yOffset() const
{
return m_offset.value().y();
}
void GraphicalObjectText::setYOffset(float yOffset)
{
QPointF temp = m_offset.value();
temp.ry() = yOffset;
m_offset = temp;
}
bool GraphicalObjectText::create()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'"
<< " text='" << m_text << "'"
<< " origin =" << this->origin() // .x() << " , " << this->origin().y()
<< " visibility=" << m_visibility;
bool success = true;
// some checks:
if (!m_graphicsLayer)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'"
<< " no graphicsLayer";
return false;
}
BaseClass::create();
if (!m_textSymbol)
m_textSymbol = new Esri::ArcGISRuntime::TextSymbol();
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'"
<< " text='" << m_text << "'"
<< " success=" << success
<< " drawOrder = " << m_graphic->zIndex();
return success;
}
bool GraphicalObjectText::updateViewImpl()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'"
<< " text='" << m_text << "'"
<< " origin =" << this->origin() // .x() << " , " << this->origin().y()
<< " visibility=" << m_visibility
<< " m_textStyle=" << m_textStyle
<< " offset=" << m_offset;
// some checks:
if (!this->isSinglePoint())
{
ERROR_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'"
<< " incorrect number of positions"
<< " (" << this->positions().count() << ")";
return false;
}
bool success = true;
if (m_visibility.value())
{
success = create(); // create only if visible
if (!success)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'"
<< " create failed";
return false;
}
if (! BaseClass::updateViewImpl())
{
ERROR_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'"
<< " updateViewImpl failed";
}
// FATAL_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'"
// << " text='" << m_text << "'"
// << " changed1=" << m_text.changed()
// << " changed2="<< m_textStyle.changed();
bool assignTextSymbol = false;
// || m_visibility.changed()) -> szenario: create invisible object and make it visible
if (m_text.changed() || m_visibility.changed())
{
m_textSymbol->setText(m_text.value());
assignTextSymbol = true;
}
// TextStyle to TextSymbol@ESRI :
if (m_textStyle.changed()
|| m_scale.changed()
|| m_visibility.changed() // -> szenario: create invisible object and make it visible
)
{
const TextStyle &textStyle = m_textStyle.value();
m_textSymbol->setColor(textStyle.textColor());
// High values can lead to coredump with 'SymbolDrawHelper::create_line_image FAILED, SkBitmap is NULL or empty' -> limit
m_textSymbol->setSize(std::min(500.0f, textStyle.size() * m_scale.value()));
m_textSymbol->setAngle(textStyle.angle());
m_textSymbol->setFontFamily(textStyle.fontFamily());
m_textSymbol->setFontWeight(textStyle.bold() ? Esri::ArcGISRuntime::FontWeight::Bold : Esri::ArcGISRuntime::FontWeight::Normal);
m_textSymbol->setFontStyle(textStyle.italic() ? Esri::ArcGISRuntime::FontStyle::Italic : Esri::ArcGISRuntime::FontStyle::Normal);
Esri::ArcGISRuntime::FontDecoration fd = Esri::ArcGISRuntime::FontDecoration::None;
if (textStyle.underline())
fd = Esri::ArcGISRuntime::FontDecoration::Underline;
if (textStyle.strikeThrough())
fd = Esri::ArcGISRuntime::FontDecoration::LineThrough;
m_textSymbol->setFontDecoration(fd);
float outlineWidth = 0;
if (textStyle.textOutlineWidth() > 0)
outlineWidth = textStyle.textOutlineWidth() * m_scale.value();
if (m_textSymbol->size() <= 15) // small size -> outline reduces readability :-(
outlineWidth = 0.0;
m_textSymbol->setHaloWidth(outlineWidth);
if (textStyle.textOutlineColor().isValid())
m_textSymbol->setHaloColor(textStyle.textOutlineColor());
// qWarning() << " haloWidth = " << m_textSymbol->haloWidth();
// m_textSymbol->setHaloColor(Qt::white);
// m_textSymbol->setHaloWidth(outlineWidth);
// qWarning() << " fontSize " << textStyle.size() * m_scale.value()
// <<" (textStyle.size() " << textStyle.size()
// << " m_scale.value() " << m_scale.value() << ")";
// qWarning() << " outlineWidth " << outlineWidth
// <<" (textStyle.textOutlineWidth() " << textStyle.textOutlineWidth()
// << " m_scale.value() " << m_scale.value() << ")";
// if (textStyle.backgroundColor().isValid())
m_textSymbol->setBackgroundColor(textStyle.backgroundColor());
// m_textSymbol->setAntiAliased(textStyle.antiAliased());
m_textSymbol->setHorizontalAlignment(convert(textStyle.horizontalAlignment()));
m_textSymbol->setVerticalAlignment(convert(textStyle.verticalAlignment()));
assignTextSymbol = true;
// : TextStyle to TextSymbol@ESRI
}
// || m_visibility.changed()) -> szenario: create invisible object and make it visible
if (m_offset.changed() || m_visibility.changed())
{
m_textSymbol->setOffsetX(m_offset.value().x());
m_textSymbol->setOffsetY(m_offset.value().y());
assignTextSymbol = true;
}
if (assignTextSymbol)
m_graphic->setSymbol(m_textSymbol);
// check ChangedFlags:
// Object is created and text is invisble due to scale (meterPerPixel)
// map is zoomed in -> text should arise, but on m_visibility is changed:
if (m_visibility.changed() || m_positions.changed())
{
const Point3D &origin = this->origin();
m_graphic->setGeometry(Esri::ArcGISRuntime::Point(origin.x(),
origin.y(),
origin.z(),
spatialReference()));
success = addUpdateGraphic();
} // m_visibility.changed() || m_positions.changed()
}
else // if visible
{
BaseClass::updateViewImpl();
success = addUpdateGraphic();
}
if (m_logger.isTraceEnabled())
{
int drawOrder = -1;
if (m_graphic)
drawOrder = m_graphic->zIndex();
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'"
<< " text='" << m_text << "'"
<< " success=" << success
<< " drawOrder = " << drawOrder;
}
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'"
// << " fontFamily='" << m_textSymbol->fontFamily() << "'"
;
return success;
}
Esri::ArcGISRuntime::HorizontalAlignment GraphicalObjectText::convert(const HorizontalAlignment horizontalAlignment)
{
Esri::ArcGISRuntime::HorizontalAlignment esriAlignmenmt =
Esri::ArcGISRuntime::HorizontalAlignment::Left;
switch (horizontalAlignment)
{
case HorizontalAlignment::Left: esriAlignmenmt = Esri::ArcGISRuntime::HorizontalAlignment::Left; break;
case HorizontalAlignment::Center: esriAlignmenmt = Esri::ArcGISRuntime::HorizontalAlignment::Center; break;
case HorizontalAlignment::Right: esriAlignmenmt = Esri::ArcGISRuntime::HorizontalAlignment::Right; break;
case HorizontalAlignment::Justify: esriAlignmenmt = Esri::ArcGISRuntime::HorizontalAlignment::Justify; break;
} // switch
return esriAlignmenmt;
}
Esri::ArcGISRuntime::VerticalAlignment GraphicalObjectText::convert(const VerticalAlignment verticalAlignment)
{
Esri::ArcGISRuntime::VerticalAlignment esriAlignmenmt =
Esri::ArcGISRuntime::VerticalAlignment::Bottom;
switch (verticalAlignment)
{
case VerticalAlignment::Bottom: esriAlignmenmt = Esri::ArcGISRuntime::VerticalAlignment::Bottom; break;
case VerticalAlignment::Middle: esriAlignmenmt = Esri::ArcGISRuntime::VerticalAlignment::Middle; break;
case VerticalAlignment::Top: esriAlignmenmt = Esri::ArcGISRuntime::VerticalAlignment::Top; break;
case VerticalAlignment::BaseLine: esriAlignmenmt = Esri::ArcGISRuntime::VerticalAlignment::Baseline; break;
} // switch
return esriAlignmenmt;
}
} // namespace SituationMap