diff --git a/scwx-qt/scwx-qt.cmake b/scwx-qt/scwx-qt.cmake index 78d45217..b300cd2a 100644 --- a/scwx-qt/scwx-qt.cmake +++ b/scwx-qt/scwx-qt.cmake @@ -252,6 +252,7 @@ set(HDR_UI source/scwx/qt/ui/about_dialog.hpp source/scwx/qt/ui/level2_products_widget.hpp source/scwx/qt/ui/level2_settings_widget.hpp source/scwx/qt/ui/level3_products_widget.hpp + source/scwx/qt/ui/line_label.hpp source/scwx/qt/ui/open_url_dialog.hpp source/scwx/qt/ui/placefile_dialog.hpp source/scwx/qt/ui/placefile_settings_widget.hpp @@ -278,6 +279,7 @@ set(SRC_UI source/scwx/qt/ui/about_dialog.cpp source/scwx/qt/ui/level2_products_widget.cpp source/scwx/qt/ui/level2_settings_widget.cpp source/scwx/qt/ui/level3_products_widget.cpp + source/scwx/qt/ui/line_label.cpp source/scwx/qt/ui/open_url_dialog.cpp source/scwx/qt/ui/placefile_dialog.cpp source/scwx/qt/ui/placefile_settings_widget.cpp diff --git a/scwx-qt/source/scwx/qt/ui/line_label.cpp b/scwx-qt/source/scwx/qt/ui/line_label.cpp new file mode 100644 index 00000000..6fd6c854 --- /dev/null +++ b/scwx-qt/source/scwx/qt/ui/line_label.cpp @@ -0,0 +1,176 @@ +#include +#include + +#include +#include + +namespace scwx +{ +namespace qt +{ +namespace ui +{ + +static const std::string logPrefix_ = "scwx::qt::ui::line_label"; +static const auto logger_ = scwx::util::Logger::Create(logPrefix_); + +class LineLabel::Impl +{ +public: + explicit Impl() {}; + ~Impl() = default; + + QImage GenerateImage() const; + + std::size_t borderWidth_ {1}; + std::size_t highlightWidth_ {1}; + std::size_t lineWidth_ {3}; + + boost::gil::rgba8_pixel_t borderColor_ {0, 0, 0, 255}; + boost::gil::rgba8_pixel_t highlightColor_ {255, 255, 0, 255}; + boost::gil::rgba8_pixel_t lineColor_ {0, 0, 255, 255}; + + QPixmap pixmap_ {}; + bool pixmapDirty_ {true}; +}; + +LineLabel::LineLabel(QWidget* parent) : + QFrame(parent), p {std::make_unique()} +{ +} + +LineLabel::~LineLabel() {} + +void LineLabel::set_border_width(std::size_t width) +{ + p->borderWidth_ = width; + p->pixmapDirty_ = true; + update(); +} + +void LineLabel::set_highlight_width(std::size_t width) +{ + p->highlightWidth_ = width; + p->pixmapDirty_ = true; + update(); +} + +void LineLabel::set_line_width(std::size_t width) +{ + p->lineWidth_ = width; + p->pixmapDirty_ = true; + update(); +} + +void LineLabel::set_border_color(boost::gil::rgba8_pixel_t color) +{ + p->borderColor_ = color; + p->pixmapDirty_ = true; + update(); +} + +void LineLabel::set_highlight_color(boost::gil::rgba8_pixel_t color) +{ + p->highlightColor_ = color; + p->pixmapDirty_ = true; + update(); +} + +void LineLabel::set_line_color(boost::gil::rgba8_pixel_t color) +{ + p->lineColor_ = color; + p->pixmapDirty_ = true; + update(); +} + +QSize LineLabel::minimumSizeHint() const +{ + return sizeHint(); +} + +QSize LineLabel::sizeHint() const +{ + QMargins margins = contentsMargins(); + + const std::size_t width = 1; + const std::size_t height = + (p->borderWidth_ + p->highlightWidth_) * 2 + p->lineWidth_; + + return QSize(static_cast(width) + margins.left() + margins.right(), + static_cast(height) + margins.top() + margins.bottom()); +} + +void LineLabel::paintEvent(QPaintEvent* e) +{ + logger_->trace("paintEvent"); + + QFrame::paintEvent(e); + + if (p->pixmapDirty_) + { + QImage image = p->GenerateImage(); + p->pixmap_ = QPixmap::fromImage(image); + p->pixmapDirty_ = false; + } + + // Don't stretch the line pixmap vertically + QRect rect = contentsRect(); + if (rect.height() > p->pixmap_.height()) + { + int dy = rect.height() - p->pixmap_.height(); + int dy1 = dy / 2; + int dy2 = dy - dy1; + rect.adjust(0, dy1, 0, -dy2); + } + + QPainter painter(this); + painter.drawPixmap(rect, p->pixmap_); +} + +QImage LineLabel::Impl::GenerateImage() const +{ + const QRgb borderRgba = qRgba(static_cast(borderColor_[0]), + static_cast(borderColor_[1]), + static_cast(borderColor_[2]), + static_cast(borderColor_[3])); + const QRgb highlightRgba = qRgba(static_cast(highlightColor_[0]), + static_cast(highlightColor_[1]), + static_cast(highlightColor_[2]), + static_cast(highlightColor_[3])); + const QRgb lineRgba = qRgba(static_cast(lineColor_[0]), + static_cast(lineColor_[1]), + static_cast(lineColor_[2]), + static_cast(lineColor_[3])); + + const std::size_t width = 1; + const std::size_t height = (borderWidth_ + highlightWidth_) * 2 + lineWidth_; + + QImage image(static_cast(width), + static_cast(height), + QImage::Format::Format_ARGB32); + + std::size_t y = 0; + for (std::size_t i = 0; i < borderWidth_; ++i, ++y) + { + image.setPixel(0, static_cast(y), borderRgba); + image.setPixel(0, static_cast(height - 1 - y), borderRgba); + } + + for (std::size_t i = 0; i < highlightWidth_; ++i, ++y) + { + image.setPixel(0, static_cast(y), highlightRgba); + image.setPixel(0, static_cast(height - 1 - y), highlightRgba); + } + + for (std::size_t i = 0; i < lineWidth_; ++i, ++y) + { + image.setPixel(0, static_cast(y), lineRgba); + image.setPixel(0, static_cast(height - 1 - y), lineRgba); + } + + return image; +} + +} // namespace ui +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/ui/line_label.hpp b/scwx-qt/source/scwx/qt/ui/line_label.hpp new file mode 100644 index 00000000..6036e92f --- /dev/null +++ b/scwx-qt/source/scwx/qt/ui/line_label.hpp @@ -0,0 +1,43 @@ +#pragma once + +#include + +#include + +namespace scwx +{ +namespace qt +{ +namespace ui +{ + +class LineLabel : public QFrame +{ + Q_OBJECT + Q_DISABLE_COPY_MOVE(LineLabel) + +public: + explicit LineLabel(QWidget* parent = nullptr); + ~LineLabel(); + + void set_border_color(boost::gil::rgba8_pixel_t color); + void set_highlight_color(boost::gil::rgba8_pixel_t color); + void set_line_color(boost::gil::rgba8_pixel_t color); + + void set_border_width(std::size_t width); + void set_highlight_width(std::size_t width); + void set_line_width(std::size_t width); + +protected: + QSize minimumSizeHint() const override; + QSize sizeHint() const override; + void paintEvent(QPaintEvent* e) override; + +private: + class Impl; + std::unique_ptr p; +}; + +} // namespace ui +} // namespace qt +} // namespace scwx