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.

194 lines
5.7 KiB

  1. /*
  2. * This program source code file is part of KICAD, a free EDA CAD application.
  3. *
  4. * Copyright (C) 2020 Kicad Developers, see AUTHORS.txt for contributors.
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public License
  8. * as published by the Free Software Foundation; either version 2
  9. * of the License, or (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, you may find one here:
  18. * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
  19. * or you may search the http://www.gnu.org website for the version 2 license,
  20. * or you may write to the Free Software Foundation, Inc.,
  21. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
  22. */
  23. #include <gal/color4d.h>
  24. #include <widgets/number_badge.h>
  25. #include <algorithm>
  26. #include <kiplatform/ui.h>
  27. NUMBER_BADGE::NUMBER_BADGE( wxWindow* aParent, wxWindowID aId, const wxPoint& aPos,
  28. const wxSize& aSize, int aStyles ) :
  29. wxPanel( aParent, aId, aPos, aSize, aStyles ),
  30. m_textSize( 10 ),
  31. m_maxNumber( 1000 ),
  32. m_currentNumber( 0 ),
  33. m_showBadge( false )
  34. {
  35. computeSize();
  36. Bind( wxEVT_PAINT, &NUMBER_BADGE::onPaint, this );
  37. }
  38. void NUMBER_BADGE::UpdateNumber( int aNumber, SEVERITY aSeverity )
  39. {
  40. m_showBadge = true;
  41. m_currentNumber = aNumber;
  42. // Choose the colors of the badge rectangle and font
  43. if( aNumber < 0 )
  44. {
  45. m_showBadge = false;
  46. }
  47. else if( aNumber == 0 )
  48. {
  49. if( aSeverity == RPT_SEVERITY_ERROR || aSeverity == RPT_SEVERITY_WARNING )
  50. {
  51. m_badgeColour = KIGFX::COLOR4D( GREEN ).ToColour();
  52. m_textColour = *wxWHITE;
  53. }
  54. else
  55. {
  56. m_showBadge = false;
  57. }
  58. }
  59. else
  60. {
  61. switch( aSeverity )
  62. {
  63. case RPT_SEVERITY_ERROR:
  64. m_badgeColour = KIPLATFORM::UI::IsDarkTheme() ? wxColour( 240, 64, 64 ) : *wxRED;
  65. m_textColour = *wxWHITE;
  66. break;
  67. case RPT_SEVERITY_WARNING:
  68. m_badgeColour = *wxYELLOW;
  69. m_textColour = *wxBLACK;
  70. break;
  71. case RPT_SEVERITY_ACTION:
  72. m_badgeColour = KIGFX::COLOR4D( GREEN ).ToColour();
  73. m_textColour = *wxWHITE;
  74. break;
  75. case RPT_SEVERITY_EXCLUSION:
  76. case RPT_SEVERITY_INFO:
  77. default:
  78. m_badgeColour = *wxLIGHT_GREY;
  79. m_textColour = *wxBLACK;
  80. break;
  81. }
  82. }
  83. computeSize();
  84. // Force the badge UI to refresh so the new number and color is displayed
  85. Refresh();
  86. }
  87. void NUMBER_BADGE::SetMaximumNumber( int aMax )
  88. {
  89. m_maxNumber = aMax;
  90. }
  91. void NUMBER_BADGE::SetTextSize( int aSize )
  92. {
  93. m_textSize = aSize;
  94. computeSize();
  95. }
  96. // OSX has prevalent badges in the application bar at the bottom of the screen so we try to
  97. // match those. Other platforms may also need tweaks to spacing, fontweight, etc.
  98. #ifdef __WXMAC__
  99. #define BADGE_FONTWEIGHT wxFONTWEIGHT_NORMAL
  100. #define PLATFORM_FUDGE_X 0.92
  101. #define PLATFORM_FUDGE_Y 1.6
  102. #endif
  103. #ifdef __WXGTK__
  104. #define BADGE_FONTWEIGHT wxFONTWEIGHT_BOLD
  105. #define PLATFORM_FUDGE_X 1.0
  106. #define PLATFORM_FUDGE_Y 1.0
  107. #endif
  108. #ifdef __WXMSW__
  109. #define BADGE_FONTWEIGHT wxFONTWEIGHT_BOLD
  110. #define PLATFORM_FUDGE_X 1.0
  111. #define PLATFORM_FUDGE_Y 1.0
  112. #endif
  113. void NUMBER_BADGE::computeSize()
  114. {
  115. wxClientDC dc( this );
  116. wxString test = wxString::Format( wxT( "%d" ), m_currentNumber );
  117. int len = test.length();
  118. // Determine the size using the string "m999{+}" where the 'm' on the front serves as a margin
  119. // so the number isn't too close to the curved edge.
  120. test = "m";
  121. test.Pad( len, '9' );
  122. if( m_currentNumber > m_maxNumber )
  123. test += "+";
  124. dc.SetFont( wxFont( m_textSize, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, BADGE_FONTWEIGHT ) );
  125. wxSize size = dc.GetTextExtent( test );
  126. size.y *= PLATFORM_FUDGE_Y;
  127. size.x = std::max<int>( size.x * PLATFORM_FUDGE_X, size.y );
  128. SetMinSize( size );
  129. SetSize( size );
  130. }
  131. void NUMBER_BADGE::onPaint( wxPaintEvent& aEvt )
  132. {
  133. // The drawing rectangle
  134. wxSize clientSize = GetSize();
  135. wxPaintDC dc( this );
  136. wxString text;
  137. wxBrush brush;
  138. // Give the badge a transparent background to show the panel underneath
  139. dc.SetBackground( *wxTRANSPARENT_BRUSH );
  140. dc.Clear();
  141. // We always draw a transparent background, but only draw the badge when it is needed
  142. if( !m_showBadge )
  143. return;
  144. // The rectangle the color is drawn in needs to be shrunk by 1px on each axis because for some
  145. // reason it seems to be padded out by 1px and is cutoff otherwise.
  146. wxRect rect( wxPoint( 0, 0 ), clientSize - wxSize( 1, 1 ) );
  147. brush.SetStyle( wxBRUSHSTYLE_SOLID );
  148. brush.SetColour( m_badgeColour );
  149. dc.SetBrush( brush );
  150. dc.SetPen( wxPen( m_badgeColour, 0 ) );
  151. dc.DrawRoundedRectangle( rect, rect.height / 2 );
  152. // Cap the number displayed and add the "+" to the end if required
  153. if( m_currentNumber > m_maxNumber )
  154. text = wxString::Format( wxT( "%d+" ), m_maxNumber );
  155. else
  156. text = wxString::Format( wxT( "%d" ), m_currentNumber );
  157. dc.SetFont( wxFont( m_textSize, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, BADGE_FONTWEIGHT ) );
  158. dc.SetTextForeground( m_textColour );
  159. dc.DrawLabel( text, wxRect( wxPoint( 0, 0 ), clientSize ), wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL );
  160. }