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.

523 lines
14KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCETICE project - Copyright 2009 by Lucio Asnaghi.
  4. JUCETICE is based around the JUCE library - "Jules' Utility Class Extensions"
  5. Copyright 2007 by Julian Storer.
  6. ------------------------------------------------------------------------------
  7. JUCE and JUCETICE can be redistributed and/or modified under the terms of
  8. the GNU General Public License, as published by the Free Software Foundation;
  9. either version 2 of the License, or (at your option) any later version.
  10. JUCE and JUCETICE are distributed in the hope that they 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. You should have received a copy of the GNU General Public License
  15. along with JUCE and JUCETICE; if not, visit www.gnu.org/licenses or write to
  16. Free Software Foundation, Inc., 59 Temple Place, Suite 330,
  17. Boston, MA 02111-1307 USA
  18. ==============================================================================
  19. */
  20. BEGIN_JUCE_NAMESPACE
  21. #include "jucetice_PianoGrid.h"
  22. //==============================================================================
  23. MidiGridItem::MidiGridItem ()
  24. : beat(0),
  25. hasBeenSelected (false),
  26. isDragging (false)
  27. {
  28. }
  29. MidiGridItem::~MidiGridItem ()
  30. {
  31. }
  32. //==============================================================================
  33. void MidiGridItem::startDragging (const MouseEvent& e)
  34. {
  35. isDragging = true;
  36. dragger.startDraggingComponent (this, e);
  37. toFront (true);
  38. repaint ();
  39. }
  40. void MidiGridItem::continueDragging (const MouseEvent& e)
  41. {
  42. dragger.dragComponent (this, e, 0);
  43. }
  44. void MidiGridItem::endDragging (const MouseEvent& e)
  45. {
  46. isDragging = false;
  47. repaint ();
  48. }
  49. //==============================================================================
  50. PianoGridNote::PianoGridNote (PianoGrid* owner_)
  51. : note (0),
  52. length (0.0f),
  53. velocity (1.0f),
  54. owner (owner_),
  55. isResizing (false),
  56. isEditingVelocity (false)
  57. {
  58. setOpaque (false);
  59. toFront (false);
  60. }
  61. PianoGridNote::~PianoGridNote()
  62. {
  63. }
  64. //==============================================================================
  65. void PianoGridNote::initialize (const int note_,
  66. const float beat_,
  67. const float length_,
  68. const float velocity_)
  69. {
  70. note = note_;
  71. beat = beat_;
  72. length = length_;
  73. velocity = velocity_;
  74. }
  75. //==============================================================================
  76. bool PianoGridNote::isNoteToggled (const int note_, const float beat_)
  77. {
  78. return ((beat_ >= beat && beat_ <= (int)(beat + length)) && (note_ == note));
  79. }
  80. void PianoGridNote::continueDragging (const MouseEvent& e)
  81. {
  82. int originalX = getX();
  83. int originalY = getY();
  84. dragger.dragComponent (this, e, 0);
  85. int newNote = -1;
  86. float newBeat = -1;
  87. if (owner->getRowsColsByMousePosition (getX(), getY(), newNote, newBeat))
  88. {
  89. if (newNote != note || newBeat != beat)
  90. {
  91. owner->moveNote (this, newNote, newBeat);
  92. }
  93. setBounds (owner->getNoteRect (this));
  94. }
  95. else
  96. {
  97. setTopLeftPosition (originalX, originalY);
  98. }
  99. }
  100. //==============================================================================
  101. void PianoGridNote::startResizing (const MouseEvent& e)
  102. {
  103. isResizing = true;
  104. toFront (true);
  105. repaint ();
  106. }
  107. void PianoGridNote::continueResizing (const MouseEvent& e)
  108. {
  109. int newNote = -1;
  110. float newBeat = -1;
  111. if (owner->getRowsColsByMousePosition (getX() + e.x, getY() + e.y, newNote, newBeat))
  112. {
  113. if (newBeat > beat)
  114. {
  115. float newLength = newBeat - beat;
  116. if (newLength != length)
  117. {
  118. owner->resizeNote (this, beat, newLength);
  119. setBounds (owner->getNoteRect (this));
  120. }
  121. }
  122. }
  123. }
  124. void PianoGridNote::endResizing (const MouseEvent& e)
  125. {
  126. isResizing = false;
  127. repaint ();
  128. }
  129. //==============================================================================
  130. void PianoGridNote::startVelocity (const MouseEvent& e)
  131. {
  132. isEditingVelocity = true;
  133. setMouseCursor (MouseCursor (MouseCursor::UpDownResizeCursor));
  134. toFront (true);
  135. repaint ();
  136. }
  137. void PianoGridNote::continueVelocity (const MouseEvent& e)
  138. {
  139. float newVelocity = velocity + e.getDistanceFromDragStartY () / 100.0f;
  140. if (newVelocity != velocity)
  141. {
  142. owner->changeNoteVelocity (this, newVelocity);
  143. repaint();
  144. }
  145. }
  146. void PianoGridNote::endVelocity (const MouseEvent& e)
  147. {
  148. isEditingVelocity = false;
  149. setMouseCursor (MouseCursor (MouseCursor::NormalCursor));
  150. repaint ();
  151. }
  152. //==============================================================================
  153. void PianoGridNote::mouseMove (const MouseEvent& e)
  154. {
  155. if (e.x >= getWidth() - 2)
  156. {
  157. setMouseCursor (MouseCursor (MouseCursor::LeftRightResizeCursor));
  158. }
  159. else
  160. {
  161. setMouseCursor (MouseCursor (MouseCursor::NormalCursor));
  162. }
  163. }
  164. void PianoGridNote::mouseDown (const MouseEvent& e)
  165. {
  166. if (! owner) return;
  167. SelectedItemSet<MidiGridItem*> selection = owner->getLassoSelection ();
  168. if (! selection.isSelected (this))
  169. owner->selectNote (this, true);
  170. if (e.mods.isLeftButtonDown())
  171. {
  172. if (e.x >= getWidth() - 2)
  173. {
  174. for (int i = 0; i < selection.getNumSelected (); i++)
  175. {
  176. PianoGridNote* component = dynamic_cast<PianoGridNote*>(selection.getSelectedItem (i));
  177. if (component)
  178. component->startResizing (e);
  179. }
  180. }
  181. else
  182. {
  183. for (int i = 0; i < selection.getNumSelected (); i++)
  184. {
  185. MidiGridItem* component = selection.getSelectedItem (i);
  186. component->startDragging (component == this ? e : e.getEventRelativeTo (component));
  187. }
  188. }
  189. DBG ("Note: " + String (note) + " " + String (beat) + " " + String (length));
  190. }
  191. else if (e.mods.isMiddleButtonDown())
  192. {
  193. for (int i = 0; i < selection.getNumSelected (); i++)
  194. {
  195. PianoGridNote* component = dynamic_cast<PianoGridNote*>(selection.getSelectedItem (i));
  196. if (component)
  197. component->startVelocity (e);
  198. }
  199. }
  200. }
  201. void PianoGridNote::mouseDrag (const MouseEvent& e)
  202. {
  203. if (! owner) return;
  204. SelectedItemSet<MidiGridItem*> selection = owner->getLassoSelection ();
  205. if (e.mods.isLeftButtonDown())
  206. {
  207. if (isResizing)
  208. {
  209. for (int i = 0; i < selection.getNumSelected (); i++)
  210. {
  211. PianoGridNote* component = dynamic_cast<PianoGridNote*>(selection.getSelectedItem (i));
  212. if (component)
  213. component->continueResizing (e);
  214. }
  215. }
  216. else if (isDragging)
  217. {
  218. for (int i = 0; i < selection.getNumSelected (); i++)
  219. {
  220. MidiGridItem* component = selection.getSelectedItem (i);
  221. component->continueDragging (component == this ? e : e.getEventRelativeTo (component));
  222. }
  223. }
  224. }
  225. else if (e.mods.isMiddleButtonDown())
  226. {
  227. if (isEditingVelocity)
  228. {
  229. for (int i = 0; i < selection.getNumSelected (); i++)
  230. {
  231. PianoGridNote* component = dynamic_cast<PianoGridNote*>(selection.getSelectedItem (i));
  232. if (component)
  233. component->continueVelocity (e);
  234. }
  235. }
  236. }
  237. }
  238. void PianoGridNote::mouseUp (const MouseEvent& e)
  239. {
  240. if (owner)
  241. {
  242. SelectedItemSet<MidiGridItem*> selection = owner->getLassoSelection ();
  243. if (e.mods.isLeftButtonDown())
  244. {
  245. if (isResizing)
  246. {
  247. for (int i = 0; i < selection.getNumSelected (); i++)
  248. {
  249. PianoGridNote* component = dynamic_cast<PianoGridNote*>(selection.getSelectedItem (i));
  250. if (component)
  251. component->endResizing (e);
  252. }
  253. }
  254. else if (isDragging)
  255. {
  256. for (int i = 0; i < selection.getNumSelected (); i++)
  257. {
  258. MidiGridItem* component = selection.getSelectedItem (i);
  259. component->endDragging (e);
  260. }
  261. }
  262. repaint ();
  263. }
  264. else if (e.mods.isMiddleButtonDown())
  265. {
  266. if (isEditingVelocity)
  267. {
  268. for (int i = 0; i < selection.getNumSelected (); i++)
  269. {
  270. PianoGridNote* component = dynamic_cast<PianoGridNote*>(selection.getSelectedItem (i));
  271. if (component)
  272. component->endVelocity (component == this ? e : e.getEventRelativeTo (component));
  273. }
  274. }
  275. }
  276. else if (e.mods.isRightButtonDown())
  277. {
  278. for (int i = 0; i < selection.getNumSelected (); i++)
  279. {
  280. PianoGridNote* component = dynamic_cast<PianoGridNote*>(selection.getSelectedItem (i));
  281. if (component && component != this)
  282. owner->removeNote (component, true);
  283. }
  284. owner->removeNote (this, false);
  285. delete (this);
  286. }
  287. }
  288. }
  289. void PianoGridNote::paint (Graphics& g)
  290. {
  291. Colour fillColour = findColour (PianoGrid::noteFillColourId);
  292. Colour borderColour = findColour (PianoGrid::noteBorderColourId);
  293. if (isDragging || isResizing)
  294. {
  295. if (hasBeenSelected) {
  296. fillColour = fillColour.darker (0.4f);
  297. borderColour = borderColour.darker (0.4f);
  298. }
  299. else
  300. {
  301. fillColour = fillColour.brighter (0.4f);
  302. borderColour = borderColour.brighter (0.4f);
  303. }
  304. }
  305. else
  306. {
  307. if (hasBeenSelected) {
  308. fillColour = fillColour.brighter (0.4f);
  309. borderColour = borderColour.brighter (0.4f);
  310. }
  311. }
  312. float alphaStep = 0.2f + velocity * 0.8f;
  313. fillColour = fillColour.withAlpha (alphaStep);
  314. borderColour = borderColour.withAlpha (alphaStep);
  315. g.fillAll (fillColour);
  316. g.setColour (borderColour);
  317. g.drawRect (0, 0, getWidth(), getHeight());
  318. }
  319. //==============================================================================
  320. AutomationEvent::AutomationEvent (AutomationGrid* owner_)
  321. : owner (owner_),
  322. value (0),
  323. controller(0)
  324. {
  325. }
  326. AutomationEvent::~AutomationEvent()
  327. {
  328. }
  329. void AutomationEvent::initialize (const int controller_,
  330. const double value_,
  331. const double beat_,
  332. const Colour colour_,
  333. const Colour outlineColour_)
  334. {
  335. controller = controller_;
  336. value = value_;
  337. beat = beat_;
  338. colour = colour_;
  339. outlineColour = outlineColour_;
  340. }
  341. void AutomationEvent::setValue (const double value_)
  342. {
  343. value = value_;
  344. value = std::max(value, 0.0);
  345. value = std::min(value, 1.0);
  346. }
  347. void AutomationEvent::mouseDown (const MouseEvent& e)
  348. {
  349. if (! owner) return;
  350. SelectedItemSet<MidiGridItem*> selection = owner->getLassoSelection ();
  351. if (! selection.isSelected (this))
  352. owner->selectNote (this, true);
  353. if (e.mods.isLeftButtonDown())
  354. {
  355. for (int i = 0; i < selection.getNumSelected (); i++)
  356. {
  357. MidiGridItem* component = selection.getSelectedItem (i);
  358. component->startDragging (component == this ? e : e.getEventRelativeTo (component));
  359. owner->repaint();
  360. }
  361. }
  362. }
  363. void AutomationEvent::mouseDrag (const MouseEvent& e)
  364. {
  365. if (! owner) return;
  366. SelectedItemSet<MidiGridItem*> selection = owner->getLassoSelection ();
  367. if (e.mods.isLeftButtonDown())
  368. {
  369. if (isDragging)
  370. {
  371. for (int i = 0; i < selection.getNumSelected (); i++)
  372. {
  373. MidiGridItem* component = selection.getSelectedItem (i);
  374. component->continueDragging (component == this ? e : e.getEventRelativeTo (component));
  375. owner->repaint();
  376. }
  377. }
  378. }
  379. }
  380. void AutomationEvent::mouseUp (const MouseEvent& e)
  381. {
  382. if (owner)
  383. {
  384. SelectedItemSet<MidiGridItem*> selection = owner->getLassoSelection ();
  385. if (e.mods.isLeftButtonDown())
  386. {
  387. for (int i = 0; i < selection.getNumSelected (); i++)
  388. {
  389. MidiGridItem* component = selection.getSelectedItem (i);
  390. component->endDragging (e);
  391. owner->repaint();
  392. }
  393. repaint ();
  394. }
  395. else if (e.mods.isRightButtonDown())
  396. {
  397. for (int i = 0; i < selection.getNumSelected (); i++)
  398. {
  399. AutomationEvent* component = dynamic_cast<AutomationEvent*>(selection.getSelectedItem (i));
  400. if (component && component != this)
  401. owner->removeNote (component, true);
  402. }
  403. owner->removeNote (this, false);
  404. delete (this);
  405. }
  406. }
  407. }
  408. void AutomationEvent::continueDragging (const MouseEvent& e)
  409. {
  410. int originalX = getX();
  411. int originalY = getY();
  412. dragger.dragComponent (this, e, 0);
  413. double newValue = -1;
  414. double newBeat = -1;
  415. if (owner->getRowsColsByMousePosition (getX(), getY(), newValue, newBeat))
  416. {
  417. if (newValue != value || newBeat != beat)
  418. {
  419. owner->moveEvent (this, newBeat, newValue);
  420. }
  421. setBounds (owner->getNoteRect (this));
  422. }
  423. else
  424. {
  425. setTopLeftPosition (originalX, originalY);
  426. }
  427. }
  428. void AutomationEvent::paint (Graphics& g)
  429. {
  430. Colour fillColour = colour;
  431. Colour borderColour = outlineColour;
  432. int borderWidth = 1;
  433. if (hasBeenSelected)
  434. {
  435. fillColour = fillColour.darker (0.6);
  436. borderColour = borderColour.darker ();
  437. borderWidth = 2;
  438. }
  439. g.setColour (fillColour);
  440. g.fillEllipse (0, 0, getWidth(), getHeight());
  441. g.setColour (borderColour);
  442. g.drawEllipse (0, 0, getWidth(), getHeight(), borderWidth);
  443. }
  444. END_JUCE_NAMESPACE