ctkCrosshairLabel.cpp 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346
  1. /*=========================================================================
  2. Library: CTK
  3. Copyright (c) Kitware Inc.
  4. Licensed under the Apache License, Version 2.0 (the "License");
  5. you may not use this file except in compliance with the License.
  6. You may obtain a copy of the License at
  7. http://www.apache.org/licenses/LICENSE-2.0.txt
  8. Unless required by applicable law or agreed to in writing, software
  9. distributed under the License is distributed on an "AS IS" BASIS,
  10. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  11. See the License for the specific language governing permissions and
  12. limitations under the License.
  13. =========================================================================*/
  14. // Qt includes
  15. #include <QColor>
  16. #include <QDebug>
  17. #include <QEvent>
  18. #include <QPainter>
  19. #include <QSize>
  20. // CTK includes
  21. #include "ctkCrosshairLabel.h"
  22. #include "ctkLogger.h"
  23. // STD includes
  24. #include <math.h>
  25. //--------------------------------------------------------------------------
  26. static ctkLogger logger("org.commontk.visualization.vtk.widgets.ctkCrosshairLabel");
  27. //--------------------------------------------------------------------------
  28. //-----------------------------------------------------------------------------
  29. class ctkCrosshairLabelPrivate
  30. {
  31. Q_DECLARE_PUBLIC(ctkCrosshairLabel)
  32. protected:
  33. ctkCrosshairLabel* const q_ptr;
  34. public:
  35. ctkCrosshairLabelPrivate(ctkCrosshairLabel& object);
  36. void init();
  37. void drawCrosshair();
  38. void drawSimpleCrosshair(QPainter& painter);
  39. void drawBullsEyeCrosshair(QPainter& painter);
  40. static int round(double f)
  41. { return static_cast<int>( f + ( f >= 0 ? 0.5 : -0.5 ) ); }
  42. bool ShowCrosshair;
  43. QPen CrosshairPen;
  44. ctkCrosshairLabel::CrosshairTypes CrosshairType;
  45. int BullsEyeWidth;
  46. static const double BULLS_EYE_BLANK_FRACTION;
  47. };
  48. const double ctkCrosshairLabelPrivate::BULLS_EYE_BLANK_FRACTION = 0.1;
  49. // --------------------------------------------------------------------------
  50. // ctkCrosshairLabelPrivate methods
  51. // --------------------------------------------------------------------------
  52. ctkCrosshairLabelPrivate::ctkCrosshairLabelPrivate(ctkCrosshairLabel& object)
  53. :q_ptr(&object)
  54. {
  55. this->ShowCrosshair = true;
  56. this->CrosshairType = ctkCrosshairLabel::SimpleCrosshair;
  57. this->BullsEyeWidth = 15;
  58. }
  59. //---------------------------------------------------------------------------
  60. void ctkCrosshairLabelPrivate::init()
  61. {
  62. Q_Q(ctkCrosshairLabel);
  63. q->setAutoFillBackground(true);
  64. q->setAlignment(Qt::AlignCenter);
  65. this->CrosshairPen.setColor(q->palette().color(QPalette::Highlight));
  66. this->CrosshairPen.setWidth(0);
  67. this->CrosshairPen.setJoinStyle(Qt::MiterJoin);
  68. }
  69. //---------------------------------------------------------------------------
  70. void ctkCrosshairLabelPrivate::drawCrosshair()
  71. {
  72. // Abort if we are not to draw the crosshair
  73. if (!this->ShowCrosshair)
  74. {
  75. return;
  76. }
  77. // Setup the painter object to paint on the label
  78. Q_Q(ctkCrosshairLabel);
  79. QPainter painter(q);
  80. painter.setPen(this->CrosshairPen);
  81. // Draw crosshair (based on current parameters) onto the label
  82. switch (this->CrosshairType)
  83. {
  84. case ctkCrosshairLabel::SimpleCrosshair:
  85. this->drawSimpleCrosshair(painter);
  86. break;
  87. case ctkCrosshairLabel::BullsEyeCrosshair:
  88. this->drawBullsEyeCrosshair(painter);
  89. break;
  90. default:
  91. qCritical() << "Unsupported crosshair type" << static_cast<int>(this->CrosshairType);
  92. break;
  93. }
  94. }
  95. //---------------------------------------------------------------------------
  96. void ctkCrosshairLabelPrivate::drawSimpleCrosshair(QPainter& painter)
  97. {
  98. Q_Q(ctkCrosshairLabel);
  99. QSize size = q->size();
  100. double halfWidth = (size.width()-1.0) / 2.0;
  101. double halfHeight = (size.height()-1.0) / 2.0;
  102. painter.drawLine(QPointF(0, halfHeight), QPointF(size.width(), halfHeight));
  103. painter.drawLine(QPointF(halfWidth, 0), QPointF(halfWidth, size.height()));
  104. }
  105. // --------------------------------------------------------------------------
  106. void ctkCrosshairLabelPrivate::drawBullsEyeCrosshair(QPainter& painter)
  107. {
  108. Q_Q(ctkCrosshairLabel);
  109. QSize size = q->size();
  110. // Draw rectangle
  111. double bullsEye = this->BullsEyeWidth;
  112. double lineWidth = painter.pen().width();
  113. lineWidth = std::max(lineWidth, 1.0);
  114. double halfLineWidth = (lineWidth-1.0) / 2.0;
  115. double x = (size.width()-bullsEye) / 2.0;
  116. double y = (size.height()-bullsEye) / 2.0;
  117. double rectWidth = bullsEye;
  118. if (bullsEye != 1)
  119. {
  120. rectWidth = rectWidth - lineWidth;
  121. }
  122. rectWidth = std::max(rectWidth, 0.0);
  123. painter.drawRect(
  124. QRectF(x+halfLineWidth, y+halfLineWidth, rectWidth, rectWidth));
  125. // Draw the lines
  126. double halfWidth = (size.width()-1.0) / 2.0;
  127. double halfHeight = (size.height()-1.0) / 2.0;
  128. double blank = ctkCrosshairLabelPrivate::round(
  129. std::min(halfWidth, halfHeight) * this->BULLS_EYE_BLANK_FRACTION);
  130. painter.drawLine(QPointF(0, halfHeight), QPointF(x-blank-1.0, halfHeight));
  131. painter.drawLine(QPointF(x+bullsEye+blank, halfHeight),
  132. QPointF(size.width(), halfHeight));
  133. painter.drawLine(QPointF(halfWidth, 0), QPointF(halfWidth, y-blank-1.0));
  134. painter.drawLine(QPointF(halfWidth, y+bullsEye+blank),
  135. QPointF(halfWidth, size.height()));
  136. }
  137. //---------------------------------------------------------------------------
  138. // ctkCrosshairLabel methods
  139. // --------------------------------------------------------------------------
  140. ctkCrosshairLabel::ctkCrosshairLabel(QWidget* parent)
  141. : Superclass(parent)
  142. , d_ptr(new ctkCrosshairLabelPrivate(*this))
  143. {
  144. Q_D(ctkCrosshairLabel);
  145. d->init();
  146. }
  147. // --------------------------------------------------------------------------
  148. ctkCrosshairLabel::~ctkCrosshairLabel()
  149. {
  150. }
  151. // --------------------------------------------------------------------------
  152. CTK_GET_CPP(ctkCrosshairLabel, bool, showCrosshair, ShowCrosshair)
  153. // --------------------------------------------------------------------------
  154. void ctkCrosshairLabel::setShowCrosshair(bool newShow)
  155. {
  156. Q_D(ctkCrosshairLabel);
  157. if (newShow == d->ShowCrosshair)
  158. {
  159. return;
  160. }
  161. d->ShowCrosshair = newShow;
  162. this->update();
  163. }
  164. // --------------------------------------------------------------------------
  165. CTK_GET_CPP(ctkCrosshairLabel, QPen, crosshairPen, CrosshairPen)
  166. // --------------------------------------------------------------------------
  167. void ctkCrosshairLabel::setCrosshairPen(const QPen& newPen)
  168. {
  169. Q_D(ctkCrosshairLabel);
  170. if (newPen == d->CrosshairPen)
  171. {
  172. return;
  173. }
  174. d->CrosshairPen = newPen;
  175. this->update();
  176. }
  177. // --------------------------------------------------------------------------
  178. QColor ctkCrosshairLabel::crosshairColor() const
  179. {
  180. Q_D(const ctkCrosshairLabel);
  181. return d->CrosshairPen.color();
  182. }
  183. // --------------------------------------------------------------------------
  184. void ctkCrosshairLabel::setCrosshairColor(const QColor& newColor)
  185. {
  186. Q_D(ctkCrosshairLabel);
  187. if (d->CrosshairPen.color() == newColor)
  188. {
  189. return;
  190. }
  191. d->CrosshairPen.setColor(newColor);
  192. this->update();
  193. }
  194. // --------------------------------------------------------------------------
  195. int ctkCrosshairLabel::lineWidth() const
  196. {
  197. Q_D(const ctkCrosshairLabel);
  198. return d->CrosshairPen.width();
  199. }
  200. // --------------------------------------------------------------------------
  201. void ctkCrosshairLabel::setLineWidth(int newWidth)
  202. {
  203. Q_D(ctkCrosshairLabel);
  204. if (d->CrosshairPen.width() == newWidth || newWidth < 0)
  205. {
  206. return;
  207. }
  208. d->CrosshairPen.setWidth(newWidth);
  209. this->update();
  210. }
  211. // --------------------------------------------------------------------------
  212. CTK_GET_CPP(ctkCrosshairLabel, ctkCrosshairLabel::CrosshairTypes,
  213. crosshairType, CrosshairType)
  214. // --------------------------------------------------------------------------
  215. void ctkCrosshairLabel::setCrosshairType(const CrosshairTypes& newType)
  216. {
  217. Q_D(ctkCrosshairLabel);
  218. if (newType == d->CrosshairType)
  219. {
  220. return;
  221. }
  222. d->CrosshairType = newType;
  223. this->update();
  224. }
  225. // --------------------------------------------------------------------------
  226. QColor ctkCrosshairLabel::marginColor() const
  227. {
  228. return this->palette().color(QPalette::Window);
  229. }
  230. // --------------------------------------------------------------------------
  231. void ctkCrosshairLabel::setMarginColor(const QColor& newColor)
  232. {
  233. if (!newColor.isValid())
  234. {
  235. return;
  236. }
  237. QPalette palette(this->palette());
  238. QColor solidColor(newColor.rgb());
  239. if (solidColor != palette.color(QPalette::Window))
  240. {
  241. // Ignore alpha channel
  242. palette.setColor(QPalette::Window, solidColor);
  243. this->setPalette(palette);
  244. this->update();
  245. }
  246. }
  247. // --------------------------------------------------------------------------
  248. CTK_GET_CPP(ctkCrosshairLabel, int, bullsEyeWidth, BullsEyeWidth)
  249. // --------------------------------------------------------------------------
  250. void ctkCrosshairLabel::setBullsEyeWidth(int newWidth)
  251. {
  252. Q_D(ctkCrosshairLabel);
  253. if (newWidth == d->BullsEyeWidth || newWidth < 0)
  254. {
  255. return;
  256. }
  257. d->BullsEyeWidth = newWidth;
  258. this->update();
  259. }
  260. // --------------------------------------------------------------------------
  261. void ctkCrosshairLabel::paintEvent(QPaintEvent * event)
  262. {
  263. Superclass::paintEvent(event);
  264. Q_D(ctkCrosshairLabel);
  265. d->drawCrosshair();
  266. }
  267. // --------------------------------------------------------------------------
  268. QSize ctkCrosshairLabel::minimumSizeHint()const
  269. {
  270. // Pretty arbitrary size (matches ctkVTKAbstractView)
  271. return QSize(50, 50);
  272. }
  273. // --------------------------------------------------------------------------
  274. QSize ctkCrosshairLabel::sizeHint()const
  275. {
  276. // Pretty arbitrary size (matches ctkVTKAbstractView)
  277. return QSize(300, 300);
  278. }
  279. //----------------------------------------------------------------------------
  280. bool ctkCrosshairLabel::hasHeightForWidth()const
  281. {
  282. return true;
  283. }
  284. //----------------------------------------------------------------------------
  285. int ctkCrosshairLabel::heightForWidth(int width)const
  286. {
  287. // Tends to be square
  288. return width;
  289. }