Audio plugin host https://kx.studio/carla
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

335 lines
9.2KB

  1. /*
  2. * Pixmap Dial, a custom Qt4 widget
  3. * Copyright (C) 2011-2013 Filipe Coelho <falktx@falktx.com>
  4. *
  5. * This program is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU General Public License as
  7. * published by the Free Software Foundation; either version 2 of
  8. * the License, or any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * For a full copy of the GNU General Public License see the doc/GPL.txt file.
  16. */
  17. #include "pixmapdial.hpp"
  18. #include <cmath>
  19. #include <QtCore/QTimer>
  20. #include <QtGui/QPainter>
  21. #include <QtGui/QPaintEvent>
  22. PixmapDial::PixmapDial(QWidget* parent)
  23. : QDial(parent),
  24. fPixmap(":/bitmaps/dial_01d.png"),
  25. fPixmapNum("01"),
  26. fCustomPaint(CUSTOM_PAINT_NULL),
  27. fOrientation(fPixmap.width() > fPixmap.height() ? HORIZONTAL : VERTICAL),
  28. fHovered(false),
  29. fHoverStep(HOVER_MIN),
  30. fLabel(""),
  31. fLabelPos(0.0f, 0.0f),
  32. fLabelWidth(0),
  33. fLabelHeight(0),
  34. fLabelGradient(0, 0, 0, 1)
  35. {
  36. fLabelFont.setPointSize(6);
  37. if (palette().window().color().lightness() > 100)
  38. {
  39. // Light background
  40. const QColor c(palette().dark().color());
  41. fColor1 = c;
  42. fColor2 = QColor(c.red(), c.green(), c.blue(), 0);
  43. fColorT[0] = palette().buttonText().color();
  44. fColorT[1] = palette().mid().color();
  45. }
  46. else
  47. {
  48. // Dark background
  49. fColor1 = QColor(0, 0, 0, 255);
  50. fColor2 = QColor(0, 0, 0, 0);
  51. fColorT[0] = Qt::white;
  52. fColorT[1] = Qt::darkGray;
  53. }
  54. updateSizes();
  55. }
  56. int PixmapDial::getSize() const
  57. {
  58. return fSize;
  59. }
  60. void PixmapDial::setCustomPaint(CustomPaint paint)
  61. {
  62. fCustomPaint = paint;
  63. fLabelPos.setY(fSize + fLabelHeight/2);
  64. update();
  65. }
  66. void PixmapDial::setEnabled(bool enabled)
  67. {
  68. if (isEnabled() != enabled)
  69. {
  70. fPixmap.load(QString(":/bitmaps/dial_%1%2.png").arg(fPixmapNum).arg(enabled ? "" : "d"));
  71. updateSizes();
  72. update();
  73. }
  74. QDial::setEnabled(enabled);
  75. }
  76. void PixmapDial::setLabel(QString label)
  77. {
  78. fLabel = label;
  79. fLabelWidth = QFontMetrics(font()).width(label);
  80. fLabelHeight = QFontMetrics(font()).height();
  81. fLabelPos.setX(float(fSize)/2.0f - float(fLabelWidth)/2.0f);
  82. fLabelPos.setY(fSize + fLabelHeight);
  83. fLabelGradient.setColorAt(0.0f, fColor1);
  84. fLabelGradient.setColorAt(0.6f, fColor1);
  85. fLabelGradient.setColorAt(1.0f, fColor2);
  86. fLabelGradient.setStart(0, float(fSize)/2.0f);
  87. fLabelGradient.setFinalStop(0, fSize + fLabelHeight + 5);
  88. fLabelGradientRect = QRectF(float(fSize)/8.0f, float(fSize)/2.0f, float(fSize*6)/8.0f, fSize+fLabelHeight+5);
  89. update();
  90. }
  91. void PixmapDial::setPixmap(int pixmapId)
  92. {
  93. fPixmapNum.sprintf("%02i", pixmapId);
  94. fPixmap.load(QString(":/bitmaps/dial_%1%2.png").arg(fPixmapNum).arg(isEnabled() ? "" : "d"));
  95. if (fPixmap.width() > fPixmap.height())
  96. fOrientation = HORIZONTAL;
  97. else
  98. fOrientation = VERTICAL;
  99. updateSizes();
  100. update();
  101. }
  102. QSize PixmapDial::minimumSizeHint() const
  103. {
  104. return QSize(fSize, fSize);
  105. }
  106. QSize PixmapDial::sizeHint() const
  107. {
  108. return QSize(fSize, fSize);
  109. }
  110. void PixmapDial::updateSizes()
  111. {
  112. fWidth = fPixmap.width();
  113. fHeight = fPixmap.height();
  114. if (fWidth < 1)
  115. fWidth = 1;
  116. if (fHeight < 1)
  117. fHeight = 1;
  118. if (fOrientation == HORIZONTAL)
  119. {
  120. fSize = fHeight;
  121. fCount = fWidth/fHeight;
  122. }
  123. else
  124. {
  125. fSize = fWidth;
  126. fCount = fHeight/fWidth;
  127. }
  128. setMinimumSize(fSize, fSize + fLabelHeight + 5);
  129. setMaximumSize(fSize, fSize + fLabelHeight + 5);
  130. }
  131. void PixmapDial::enterEvent(QEvent* event)
  132. {
  133. fHovered = true;
  134. if (fHoverStep == HOVER_MIN)
  135. fHoverStep = HOVER_MIN + 1;
  136. QDial::enterEvent(event);
  137. }
  138. void PixmapDial::leaveEvent(QEvent* event)
  139. {
  140. fHovered = false;
  141. if (fHoverStep == HOVER_MAX)
  142. fHoverStep = HOVER_MAX - 1;
  143. QDial::leaveEvent(event);
  144. }
  145. void PixmapDial::paintEvent(QPaintEvent* event)
  146. {
  147. event->accept();
  148. QPainter painter(this);
  149. painter.save();
  150. painter.setRenderHint(QPainter::Antialiasing, true);
  151. if (! fLabel.isEmpty())
  152. {
  153. if (fCustomPaint == CUSTOM_PAINT_NULL)
  154. {
  155. painter.setPen(fColor2);
  156. painter.setBrush(fLabelGradient);
  157. painter.drawRect(fLabelGradientRect);
  158. }
  159. painter.setFont(fLabelFont);
  160. painter.setPen(fColorT[isEnabled() ? 0 : 1]);
  161. painter.drawText(fLabelPos, fLabel);
  162. }
  163. if (isEnabled())
  164. {
  165. float current = value()-minimum();
  166. float divider = maximum()-minimum();
  167. if (divider == 0.0f)
  168. return;
  169. float value = current/divider;
  170. QRectF source, target(0.0f, 0.0f, fSize, fSize);
  171. int xpos, ypos, per = (fCount-1)*value;
  172. if (fOrientation == HORIZONTAL)
  173. {
  174. xpos = fSize*per;
  175. ypos = 0.0f;
  176. }
  177. else
  178. {
  179. xpos = 0.0f;
  180. ypos = fSize*per;
  181. }
  182. source = QRectF(xpos, ypos, fSize, fSize);
  183. painter.drawPixmap(target, fPixmap, source);
  184. // Custom knobs (Dry/Wet and Volume)
  185. if (fCustomPaint == CUSTOM_PAINT_CARLA_WET || fCustomPaint == CUSTOM_PAINT_CARLA_VOL)
  186. {
  187. // knob color
  188. QColor colorGreen(0x5D, 0xE7, 0x3D, 191 + fHoverStep*7);
  189. QColor colorBlue(0x3E, 0xB8, 0xBE, 191 + fHoverStep*7);
  190. // draw small circle
  191. QRectF ballRect(8.0f, 8.0f, 15.0f, 15.0f);
  192. QPainterPath ballPath;
  193. ballPath.addEllipse(ballRect);
  194. //painter.drawRect(ballRect);
  195. float tmpValue = (0.375f + 0.75f*value);
  196. float ballValue = tmpValue - std::floor(tmpValue);
  197. QPointF ballPoint(ballPath.pointAtPercent(ballValue));
  198. // draw arc
  199. int startAngle = 216*16;
  200. int spanAngle = -252*16*value;
  201. if (fCustomPaint == CUSTOM_PAINT_CARLA_WET)
  202. {
  203. painter.setBrush(colorBlue);
  204. painter.setPen(QPen(colorBlue, 0));
  205. painter.drawEllipse(QRectF(ballPoint.x(), ballPoint.y(), 2.2f, 2.2f));
  206. QConicalGradient gradient(15.5f, 15.5f, -45);
  207. gradient.setColorAt(0.0f, colorBlue);
  208. gradient.setColorAt(0.125f, colorBlue);
  209. gradient.setColorAt(0.625f, colorGreen);
  210. gradient.setColorAt(0.75f, colorGreen);
  211. gradient.setColorAt(0.76f, colorGreen);
  212. gradient.setColorAt(1.0f, colorGreen);
  213. painter.setBrush(gradient);
  214. painter.setPen(QPen(gradient, 3));
  215. }
  216. else
  217. {
  218. painter.setBrush(colorBlue);
  219. painter.setPen(QPen(colorBlue, 0));
  220. painter.drawEllipse(QRectF(ballPoint.x(), ballPoint.y(), 2.2f, 2.2f));
  221. painter.setBrush(colorBlue);
  222. painter.setPen(QPen(colorBlue, 3));
  223. }
  224. painter.drawArc(4.0f, 4.0f, 26.0f, 26.0f, startAngle, spanAngle);
  225. }
  226. // Custom knobs (L and R)
  227. else if (fCustomPaint == CUSTOM_PAINT_CARLA_L || fCustomPaint == CUSTOM_PAINT_CARLA_R)
  228. {
  229. // knob color
  230. QColor color(0xAD + fHoverStep*5, 0xD5 + fHoverStep*4, 0x4B + fHoverStep*5);
  231. // draw small circle
  232. QRectF ballRect(7.0f, 8.0f, 11.0f, 12.0f);
  233. QPainterPath ballPath;
  234. ballPath.addEllipse(ballRect);
  235. //painter.drawRect(ballRect);
  236. float tmpValue = (0.375f + 0.75f*value);
  237. float ballValue = tmpValue - std::floor(tmpValue);
  238. QPointF ballPoint(ballPath.pointAtPercent(ballValue));
  239. painter.setBrush(color);
  240. painter.setPen(QPen(color, 0));
  241. painter.drawEllipse(QRectF(ballPoint.x(), ballPoint.y(), 2.0f, 2.0f));
  242. int startAngle, spanAngle;
  243. // draw arc
  244. if (fCustomPaint == CUSTOM_PAINT_CARLA_L)
  245. {
  246. startAngle = 216*16;
  247. spanAngle = -252.0*16*value;
  248. }
  249. else if (fCustomPaint == CUSTOM_PAINT_CARLA_R)
  250. {
  251. startAngle = 324.0*16;
  252. spanAngle = 252.0*16*(1.0-value);
  253. }
  254. else
  255. return;
  256. painter.setPen(QPen(color, 2));
  257. painter.drawArc(3.5f, 4.5f, 22.0f, 22.0f, startAngle, spanAngle);
  258. if (HOVER_MIN < fHoverStep && fHoverStep < HOVER_MAX)
  259. {
  260. fHoverStep += fHovered ? 1 : -1;
  261. QTimer::singleShot(20, this, SLOT(update()));
  262. }
  263. }
  264. if (HOVER_MIN < fHoverStep && fHoverStep < HOVER_MAX)
  265. {
  266. fHoverStep += fHovered ? 1 : -1;
  267. QTimer::singleShot(20, this, SLOT(update()));
  268. }
  269. }
  270. else
  271. {
  272. QRectF target(0.0f, 0.0f, fSize, fSize);
  273. painter.drawPixmap(target, fPixmap, target);
  274. }
  275. painter.restore();
  276. }
  277. void PixmapDial::resizeEvent(QResizeEvent* event)
  278. {
  279. updateSizes();
  280. QDial::resizeEvent(event);
  281. }