The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
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.

137 lines
4.0KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2017 - ROLI Ltd.
  5. JUCE is an open source library subject to commercial or open-source
  6. licensing.
  7. By using JUCE, you agree to the terms of both the JUCE 5 End-User License
  8. Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
  9. 27th April 2017).
  10. End User License Agreement: www.juce.com/juce-5-licence
  11. Privacy Policy: www.juce.com/juce-5-privacy-policy
  12. Or: You may also use this code under the terms of the GPL v3 (see
  13. www.gnu.org/licenses).
  14. JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
  15. EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
  16. DISCLAIMED.
  17. ==============================================================================
  18. */
  19. class BuildStatusTabComp : public Component,
  20. private ChangeListener,
  21. private Timer
  22. {
  23. public:
  24. BuildStatusTabComp (ErrorList& el, ActivityList& al)
  25. : errorList (el), activityList (al)
  26. {
  27. setInterceptsMouseClicks (false, false);
  28. addAndMakeVisible (&spinner);
  29. activityList.addChangeListener (this);
  30. errorList.addChangeListener (this);
  31. }
  32. ~BuildStatusTabComp()
  33. {
  34. activityList.removeChangeListener (this);
  35. errorList.removeChangeListener (this);
  36. }
  37. enum { size = 20 };
  38. void updateStatus()
  39. {
  40. State newState = nothing;
  41. if (activityList.getNumActivities() > 0) newState = busy;
  42. else if (errorList.getNumErrors() > 0) newState = errors;
  43. else if (errorList.getNumWarnings() > 0) newState = warnings;
  44. if (newState != state)
  45. {
  46. state = newState;
  47. setSize (state != nothing ? size : 0, size);
  48. spinner.setVisible (state == busy);
  49. repaint();
  50. }
  51. }
  52. void paint (Graphics& g) override
  53. {
  54. if (state == errors || state == warnings)
  55. {
  56. g.setColour (state == errors ? Colours::red : Colours::yellow);
  57. const Path& icon = (state == errors) ? getIcons().warning
  58. : getIcons().info;
  59. g.fillPath (icon, RectanglePlacement (RectanglePlacement::centred)
  60. .getTransformToFit (icon.getBounds(),
  61. getCentralArea().reduced (1, 1).toFloat()));
  62. }
  63. }
  64. void resized() override
  65. {
  66. spinner.setBounds (getCentralArea());
  67. }
  68. Rectangle<int> getCentralArea() const
  69. {
  70. return getLocalBounds().withTrimmedRight (4);
  71. }
  72. private:
  73. ErrorList& errorList;
  74. ActivityList& activityList;
  75. void changeListenerCallback (ChangeBroadcaster*) override { if (! isTimerRunning()) startTimer (150); }
  76. void timerCallback() override { stopTimer(); updateStatus(); }
  77. enum State
  78. {
  79. nothing,
  80. busy,
  81. errors,
  82. warnings
  83. };
  84. State state;
  85. //==============================================================================
  86. struct Spinner : public Component,
  87. private Timer
  88. {
  89. Spinner()
  90. {
  91. setInterceptsMouseClicks (false, false);
  92. }
  93. void paint (Graphics& g) override
  94. {
  95. if (findParentComponentOfClass<TabBarButton>() != nullptr)
  96. {
  97. getLookAndFeel().drawSpinningWaitAnimation (g, findColour (treeIconColourId),
  98. 0, 0, getWidth(), getHeight());
  99. startTimer (1000 / 20);
  100. }
  101. }
  102. void timerCallback() override
  103. {
  104. if (isVisible())
  105. repaint();
  106. else
  107. stopTimer();
  108. }
  109. };
  110. Spinner spinner;
  111. };