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.

141 lines
4.1KB

  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. #pragma once
  20. //==============================================================================
  21. class BuildStatusTabComp : public Component,
  22. private ChangeListener,
  23. private Timer
  24. {
  25. public:
  26. BuildStatusTabComp (ErrorList& el, ActivityList& al)
  27. : errorList (el), activityList (al)
  28. {
  29. setInterceptsMouseClicks (false, false);
  30. addAndMakeVisible (&spinner);
  31. activityList.addChangeListener (this);
  32. errorList.addChangeListener (this);
  33. }
  34. ~BuildStatusTabComp() override
  35. {
  36. activityList.removeChangeListener (this);
  37. errorList.removeChangeListener (this);
  38. }
  39. enum { size = 20 };
  40. void updateStatus()
  41. {
  42. State newState = nothing;
  43. if (activityList.getNumActivities() > 0) newState = busy;
  44. else if (errorList.getNumErrors() > 0) newState = errors;
  45. else if (errorList.getNumWarnings() > 0) newState = warnings;
  46. if (newState != state)
  47. {
  48. state = newState;
  49. setSize (state != nothing ? size : 0, size);
  50. spinner.setVisible (state == busy);
  51. repaint();
  52. }
  53. }
  54. void paint (Graphics& g) override
  55. {
  56. if (state == errors || state == warnings)
  57. {
  58. g.setColour (state == errors ? Colours::red : Colours::yellow);
  59. const Path& icon = (state == errors) ? getIcons().warning
  60. : getIcons().info;
  61. g.fillPath (icon, RectanglePlacement (RectanglePlacement::centred)
  62. .getTransformToFit (icon.getBounds(),
  63. getCentralArea().reduced (1, 1).toFloat()));
  64. }
  65. }
  66. void resized() override
  67. {
  68. spinner.setBounds (getCentralArea());
  69. }
  70. Rectangle<int> getCentralArea() const
  71. {
  72. return getLocalBounds().withTrimmedRight (4);
  73. }
  74. private:
  75. ErrorList& errorList;
  76. ActivityList& activityList;
  77. void changeListenerCallback (ChangeBroadcaster*) override { if (! isTimerRunning()) startTimer (150); }
  78. void timerCallback() override { stopTimer(); updateStatus(); }
  79. enum State
  80. {
  81. nothing,
  82. busy,
  83. errors,
  84. warnings
  85. };
  86. State state;
  87. //==============================================================================
  88. struct Spinner : public Component,
  89. private Timer
  90. {
  91. Spinner()
  92. {
  93. setInterceptsMouseClicks (false, false);
  94. }
  95. void paint (Graphics& g) override
  96. {
  97. if (findParentComponentOfClass<TabBarButton>() != nullptr)
  98. {
  99. getLookAndFeel().drawSpinningWaitAnimation (g, findColour (treeIconColourId),
  100. 0, 0, getWidth(), getHeight());
  101. startTimer (1000 / 20);
  102. }
  103. }
  104. void timerCallback() override
  105. {
  106. if (isVisible())
  107. repaint();
  108. else
  109. stopTimer();
  110. }
  111. };
  112. Spinner spinner;
  113. };