Collection of tools useful for audio production
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.

336 lines
9.3KB

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