/*========================================================================= Library: CTK Copyright (c) Kitware Inc. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0.txt Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. =========================================================================*/ // Qt includes #include #include #include #include #include // CTK includes #include "ctkCrosshairLabel.h" #include "ctkLogger.h" // STD includes #include //-------------------------------------------------------------------------- static ctkLogger logger("org.commontk.visualization.vtk.widgets.ctkCrosshairLabel"); //-------------------------------------------------------------------------- //----------------------------------------------------------------------------- class ctkCrosshairLabelPrivate { Q_DECLARE_PUBLIC(ctkCrosshairLabel) protected: ctkCrosshairLabel* const q_ptr; public: ctkCrosshairLabelPrivate(ctkCrosshairLabel& object); void init(); void drawCrosshair(); void drawSimpleCrosshair(QPainter& painter); void drawBullsEyeCrosshair(QPainter& painter); static int round(double f) { return static_cast( f + ( f >= 0 ? 0.5 : -0.5 ) ); } bool ShowCrosshair; QPen CrosshairPen; ctkCrosshairLabel::CrosshairTypes CrosshairType; int BullsEyeWidth; static const double BULLS_EYE_BLANK_FRACTION; }; const double ctkCrosshairLabelPrivate::BULLS_EYE_BLANK_FRACTION = 0.1; // -------------------------------------------------------------------------- // ctkCrosshairLabelPrivate methods // -------------------------------------------------------------------------- ctkCrosshairLabelPrivate::ctkCrosshairLabelPrivate(ctkCrosshairLabel& object) :q_ptr(&object) { this->ShowCrosshair = true; this->CrosshairType = ctkCrosshairLabel::SimpleCrosshair; this->BullsEyeWidth = 15; } //--------------------------------------------------------------------------- void ctkCrosshairLabelPrivate::init() { Q_Q(ctkCrosshairLabel); q->setAutoFillBackground(true); q->setAlignment(Qt::AlignCenter); this->CrosshairPen.setColor(q->palette().color(QPalette::Highlight)); this->CrosshairPen.setWidth(0); this->CrosshairPen.setJoinStyle(Qt::MiterJoin); } //--------------------------------------------------------------------------- void ctkCrosshairLabelPrivate::drawCrosshair() { // Abort if we are not to draw the crosshair if (!this->ShowCrosshair) { return; } // Setup the painter object to paint on the label Q_Q(ctkCrosshairLabel); QPainter painter(q); painter.setPen(this->CrosshairPen); // Draw crosshair (based on current parameters) onto the label switch (this->CrosshairType) { case ctkCrosshairLabel::SimpleCrosshair: this->drawSimpleCrosshair(painter); break; case ctkCrosshairLabel::BullsEyeCrosshair: this->drawBullsEyeCrosshair(painter); break; default: qCritical() << "Unsupported crosshair type" << static_cast(this->CrosshairType); break; } } //--------------------------------------------------------------------------- void ctkCrosshairLabelPrivate::drawSimpleCrosshair(QPainter& painter) { Q_Q(ctkCrosshairLabel); QSize size = q->size(); double halfWidth = (size.width()-1.0) / 2.0; double halfHeight = (size.height()-1.0) / 2.0; painter.drawLine(QPointF(0, halfHeight), QPointF(size.width(), halfHeight)); painter.drawLine(QPointF(halfWidth, 0), QPointF(halfWidth, size.height())); } // -------------------------------------------------------------------------- void ctkCrosshairLabelPrivate::drawBullsEyeCrosshair(QPainter& painter) { Q_Q(ctkCrosshairLabel); QSize size = q->size(); // Draw rectangle double bullsEye = this->BullsEyeWidth; double lineWidth = painter.pen().width(); lineWidth = std::max(lineWidth, 1.0); double halfLineWidth = (lineWidth-1.0) / 2.0; double x = (size.width()-bullsEye) / 2.0; double y = (size.height()-bullsEye) / 2.0; double rectWidth = bullsEye; if (bullsEye != 1) { rectWidth = rectWidth - lineWidth; } rectWidth = std::max(rectWidth, 0.0); painter.drawRect( QRectF(x+halfLineWidth, y+halfLineWidth, rectWidth, rectWidth)); // Draw the lines double halfWidth = (size.width()-1.0) / 2.0; double halfHeight = (size.height()-1.0) / 2.0; double blank = ctkCrosshairLabelPrivate::round( std::min(halfWidth, halfHeight) * this->BULLS_EYE_BLANK_FRACTION); painter.drawLine(QPointF(0, halfHeight), QPointF(x-blank-1.0, halfHeight)); painter.drawLine(QPointF(x+bullsEye+blank, halfHeight), QPointF(size.width(), halfHeight)); painter.drawLine(QPointF(halfWidth, 0), QPointF(halfWidth, y-blank-1.0)); painter.drawLine(QPointF(halfWidth, y+bullsEye+blank), QPointF(halfWidth, size.height())); } //--------------------------------------------------------------------------- // ctkCrosshairLabel methods // -------------------------------------------------------------------------- ctkCrosshairLabel::ctkCrosshairLabel(QWidget* parent) : Superclass(parent) , d_ptr(new ctkCrosshairLabelPrivate(*this)) { Q_D(ctkCrosshairLabel); d->init(); } // -------------------------------------------------------------------------- ctkCrosshairLabel::~ctkCrosshairLabel() { } // -------------------------------------------------------------------------- CTK_GET_CPP(ctkCrosshairLabel, bool, showCrosshair, ShowCrosshair) // -------------------------------------------------------------------------- void ctkCrosshairLabel::setShowCrosshair(bool newShow) { Q_D(ctkCrosshairLabel); if (newShow == d->ShowCrosshair) { return; } d->ShowCrosshair = newShow; this->update(); } // -------------------------------------------------------------------------- CTK_GET_CPP(ctkCrosshairLabel, QPen, crosshairPen, CrosshairPen) // -------------------------------------------------------------------------- void ctkCrosshairLabel::setCrosshairPen(const QPen& newPen) { Q_D(ctkCrosshairLabel); if (newPen == d->CrosshairPen) { return; } d->CrosshairPen = newPen; this->update(); } // -------------------------------------------------------------------------- QColor ctkCrosshairLabel::crosshairColor() const { Q_D(const ctkCrosshairLabel); return d->CrosshairPen.color(); } // -------------------------------------------------------------------------- void ctkCrosshairLabel::setCrosshairColor(const QColor& newColor) { Q_D(ctkCrosshairLabel); if (d->CrosshairPen.color() == newColor) { return; } d->CrosshairPen.setColor(newColor); this->update(); } // -------------------------------------------------------------------------- int ctkCrosshairLabel::lineWidth() const { Q_D(const ctkCrosshairLabel); return d->CrosshairPen.width(); } // -------------------------------------------------------------------------- void ctkCrosshairLabel::setLineWidth(int newWidth) { Q_D(ctkCrosshairLabel); if (d->CrosshairPen.width() == newWidth || newWidth < 0) { return; } d->CrosshairPen.setWidth(newWidth); this->update(); } // -------------------------------------------------------------------------- CTK_GET_CPP(ctkCrosshairLabel, ctkCrosshairLabel::CrosshairTypes, crosshairType, CrosshairType) // -------------------------------------------------------------------------- void ctkCrosshairLabel::setCrosshairType(const CrosshairTypes& newType) { Q_D(ctkCrosshairLabel); if (newType == d->CrosshairType) { return; } d->CrosshairType = newType; this->update(); } // -------------------------------------------------------------------------- QColor ctkCrosshairLabel::marginColor() const { return this->palette().color(QPalette::Window); } // -------------------------------------------------------------------------- void ctkCrosshairLabel::setMarginColor(const QColor& newColor) { if (!newColor.isValid()) { return; } QPalette palette(this->palette()); QColor solidColor(newColor.rgb()); if (solidColor != palette.color(QPalette::Window)) { // Ignore alpha channel palette.setColor(QPalette::Window, solidColor); this->setPalette(palette); this->update(); } } // -------------------------------------------------------------------------- CTK_GET_CPP(ctkCrosshairLabel, int, bullsEyeWidth, BullsEyeWidth) // -------------------------------------------------------------------------- void ctkCrosshairLabel::setBullsEyeWidth(int newWidth) { Q_D(ctkCrosshairLabel); if (newWidth == d->BullsEyeWidth || newWidth < 0) { return; } d->BullsEyeWidth = newWidth; this->update(); } // -------------------------------------------------------------------------- void ctkCrosshairLabel::paintEvent(QPaintEvent * event) { Superclass::paintEvent(event); Q_D(ctkCrosshairLabel); d->drawCrosshair(); } // -------------------------------------------------------------------------- QSize ctkCrosshairLabel::minimumSizeHint()const { // Pretty arbitrary size (matches ctkVTKAbstractView) return QSize(50, 50); } // -------------------------------------------------------------------------- QSize ctkCrosshairLabel::sizeHint()const { // Pretty arbitrary size (matches ctkVTKAbstractView) return QSize(300, 300); } //---------------------------------------------------------------------------- bool ctkCrosshairLabel::hasHeightForWidth()const { return true; } //---------------------------------------------------------------------------- int ctkCrosshairLabel::heightForWidth(int width)const { // Tends to be square return width; }