Beispiel #1
1
void Oscilloscope::paint(Graphics& g) {
  static const DropShadow shadow(Colour(0xbb000000), 5, Point<int>(0, 0));
  g.drawImageWithin(background_,
                    0, 0, getWidth(), getHeight(), RectanglePlacement());

  shadow.drawForPath(g, wave_path_);

  g.setColour(Colour(0xff565656));
  g.fillPath(wave_path_);
  g.setColour(Colour(0xffaaaaaa));
  g.strokePath(wave_path_, PathStrokeType(1.0f, PathStrokeType::beveled, PathStrokeType::rounded));
}
Beispiel #2
0
void XYPad::paint(Graphics& g) {
  static const PathStrokeType stroke(1.5f, PathStrokeType::beveled, PathStrokeType::rounded);
  static const DropShadow shadow(Colour(0xbb000000), 5, Point<int>(0, 0));

  g.drawImage(background_,
              0, 0, getWidth(), getHeight(),
              0, 0, background_.getWidth(), background_.getHeight());

  float x = x_slider_->getValue() * getWidth();
  float y = (1.0f - y_slider_->getValue()) * getHeight();

  Path target;
  target.addEllipse(x - 6.0f, y - 6.0f, 12.0f, 12.0f);
  shadow.drawForPath(g, target);

  g.setColour(Colour(0xff565656));
  g.fillPath(target);

  if (active_)
    g.setColour(Colour(0xff03a9f4));
  else
    g.setColour(Colour(0xff777777));
  g.strokePath(target, stroke);
  g.fillEllipse(x - 1.0f, y - 1.0f, 2.0f, 2.0f);

  if (mouse_down_) {
    g.setColour(Colour(0x11ffffff));
    g.fillEllipse(x - 20.0, y - 20.0, 40.0, 40.0);
  }
}
Beispiel #3
0
void SaveSection::paint(Graphics& g) {
  static const DropShadow shadow(Colour(0xff000000), 5, Point<int>(0, 0));

  g.setColour(Colour(0xbb111111));
  g.fillAll();

  Rectangle<int> save_rect = getSaveRect();
  shadow.drawForRectangle(g, save_rect);
  g.setColour(Colour(0xff212121));
  g.fillRect(save_rect);

  g.saveState();
  g.setOrigin(save_rect.getX() + PADDING_X, save_rect.getY() + PADDING_Y);

  g.setFont(Fonts::instance()->proportional_regular().withPointHeight(14.0f));
  g.setColour(Colour(0xff888888));

  g.drawText(TRANS("PATCH NAME"),
             0, PADDING_Y, DIVISION - 10, TEXT_EDITOR_HEIGHT,
             Justification::centredRight, false);
  g.drawText(TRANS("AUTHOR"),
             0, 2 * PADDING_Y + TEXT_EDITOR_HEIGHT, DIVISION - 10, TEXT_EDITOR_HEIGHT,
             Justification::centredRight, false);
  g.drawText(TRANS("FOLDER"),
             0, 3 * PADDING_Y + 2 * TEXT_EDITOR_HEIGHT, DIVISION - 10, TEXT_EDITOR_HEIGHT,
             Justification::centredRight, false);

  g.restoreState();
}
Beispiel #4
0
void DeleteSection::paint(Graphics& g) {
  static const DropShadow shadow(Colour(0xff000000), 5, Point<int>(0, 0));

  g.setColour(Colour(0xbb212121));
  g.fillAll();

  Rectangle<int> delete_rect = getDeleteRect();
  shadow.drawForRectangle(g, delete_rect);
  g.setColour(Colour(0xff303030));
  g.fillRect(delete_rect);

  g.saveState();
  g.setOrigin(delete_rect.getX() + PADDING_X, delete_rect.getY() + PADDING_Y);

  g.setFont(Fonts::instance()->proportional_light().withPointHeight(14.0f));
  g.setColour(Colour(0xffaaaaaa));

  String text;
  if (file_.isDirectory())
    text = TRANS("Are you sure you want to delte this folder?");
  else
  text = TRANS("Are you sure you want to delte this patch?");
  g.drawText(text,
             0, 0.0f, delete_rect.getWidth() - 2 * PADDING_X, 22.0f,
             Justification::centred, false);

  g.setFont(Fonts::instance()->monospace().withPointHeight(16.0f));
  g.setColour(Colour(0xff03a9f4));
  g.drawText(file_.getFileNameWithoutExtension(),
             0, 20.0f, delete_rect.getWidth() - 2 * PADDING_X, 22.0f,
             Justification::centred, false);

  g.restoreState();
}
void CustomLookAndFeel::drawLinearSliderThumb (Graphics& g, int x, int y, int width,
                                               int height, float sliderPos,
                                               float minSliderPos, float maxSliderPos,
                                               const Slider::SliderStyle style,
                                               Slider& slider)
{
    if (style == Slider::LinearVertical)
    {
        bool isDownOrDragging = slider.isEnabled() && (slider.isMouseOverOrDragging() || slider.isMouseButtonDown());
        Colour knobColour (slider.findColour (Slider::thumbColourId).withMultipliedSaturation ((slider.hasKeyboardFocus (false) || isDownOrDragging) ? 1.3f : 0.9f)
                           .withMultipliedAlpha (slider.isEnabled() ? 1.0f : 0.7f));
        
        const float thumbWidth = jmin (slider.getWidth() - 2 * spaceBetweenThumbAndComponentBorder,
                                       maxThumbWidthVertical);
        const float thumbHeight = thumbWidth * heightToWidthRatioVertical;
        
        const float xCenter = x + width * 0.5f;
        // Originally it was yCenter = sliderPos. But that way the thumb (and especially the center line) did
        // not always look the same because of aliasing. With this additional rounding it is ensured that the
        // vertical position of the thumb "snaps" to the closest pixel and therefore looks always the same.
        const float yCenter = (int)(sliderPos) + 0.5f;
        const float xThumb = xCenter - 0.5f * thumbWidth;
        const float yThumb = yCenter - 0.5f * thumbHeight;
        
        // The shape of the thumb
        Path p;
        p.addRoundedRectangle(xThumb, yThumb, thumbWidth, thumbHeight, 5.0f);
        
        // Drop shadow
        const DropShadow ds (Colours::black, 4, Point<int> (0, 0));
        ds.drawForPath (g, p);
        
        // Outline
        const float outlineThickness = slider.isEnabled() ? 0.8f : 0.3f;
        g.setColour (Colours::black);
        //g.setColour (knobColour.darker());
        g.strokePath (p, PathStrokeType (outlineThickness));
        
        // Fill
        ColourGradient gradient (knobColour.darker(), xThumb, yThumb,
                                 knobColour.darker(), xThumb, yThumb + thumbHeight, false);
        gradient.addColour (0.5, knobColour.brighter());
        g.setGradientFill(gradient);
        g.fillPath (p);
//        g.setColour (knobColour);
//        g.fillPath (p);
        
        // Middle line
        g.setColour(Colours::black);
        g.drawLine(xThumb, yCenter, xThumb + thumbWidth, yCenter);
    }
    else
    {
        // Just call the base class for the demo
        LookAndFeel_V3::drawLinearSliderThumb (g, x, y, width, height, sliderPos, minSliderPos, maxSliderPos, style, slider);
    }
}
Beispiel #6
0
void SynthSlider::drawRectangularShadow(Graphics &g) {
  static const DropShadow shadow(Colour(0xbb000000), 2, Point<int>(0, 0));

  g.saveState();
  g.setOrigin(getX(), getY());
  shadow.drawForRectangle(g, getLocalBounds());

  g.restoreState();
}
void DropShadowEffect::applyEffect (Image& image, Graphics& g, float scaleFactor, float alpha)
{
    DropShadow s (shadow);
    s.radius = roundToInt (s.radius * scaleFactor);
    s.colour = s.colour.withMultipliedAlpha (alpha);
    s.offset.x = roundToInt (s.offset.x * scaleFactor);
    s.offset.y = roundToInt (s.offset.y * scaleFactor);

    s.drawForImage (g, image);

    g.setOpacity (alpha);
    g.drawImageAt (image, 0, 0);
}
void DefaultLookAndFeel::drawLinearSlider(Graphics& g, int x, int y, int width, int height,
                                          float slider_pos, float min, float max,
                                          const Slider::SliderStyle style, Slider& slider) {
  static const DropShadow thumb_shadow(Colour(0x88000000), 3, Point<int>(-1, 0));

  bool bipolar = false;
  bool active = true;
  SynthSlider* s_slider = dynamic_cast<SynthSlider*>(&slider);
  if (s_slider) {
    bipolar = s_slider->isBipolar();
    active = s_slider->isActive();
  }

  Colour slider_color(0xff888888);
  Colour thumb_color(0xffffffff);

  if (!active) {
    slider_color = Colour(0xff424242);
    thumb_color = Colour(0xff888888);
  }

  float pos = slider_pos - 1.0f;
  if (style == Slider::SliderStyle::LinearBar) {
    float h = slider.getHeight();

    g.setColour(slider_color);
    if (bipolar)
      fillHorizontalRect(g, width / 2.0f, pos, h);
    else
      fillHorizontalRect(g, 0.0f, pos, h);

    thumb_shadow.drawForRectangle(g, Rectangle<int>(pos + 0.5f, 0, 2, h));
    g.setColour(thumb_color);
    g.fillRect(pos, 0.0f, 2.0f, h);
  }
  else if (style == Slider::SliderStyle::LinearBarVertical) {
    float w = slider.getWidth();

    g.setColour(slider_color);

    if (bipolar)
      fillVerticalRect(g, height / 2.0f, pos, w);
    else
      fillVerticalRect(g, 0, pos, w);

    thumb_shadow.drawForRectangle(g, Rectangle<int>(0, pos + 0.5f, w, 2));
    g.setColour(thumb_color);
    g.fillRect(0.0f, pos, w, 2.0f);
  }
}
Beispiel #9
0
void SynthSlider::drawRotaryShadow(Graphics &g) {
  static const DropShadow shadow(Colour(0xbb000000), 3, Point<int>(0, 0));
  static const float shadow_angle = mopo::PI / 1.3f;

  g.saveState();
  g.setOrigin(getX(), getY());

  float full_radius = std::min(getWidth() / 2.0f, getHeight() / 2.0f);
  Path shadow_path;
  shadow_path.addCentredArc(full_radius, full_radius,
                            0.87f * full_radius, 0.85f * full_radius,
                            0, -shadow_angle, shadow_angle, true);
  shadow.drawForPath(g, shadow_path);
  g.restoreState();
}
Beispiel #10
0
void FilterResponse::paint(Graphics& g) {
  static const PathStrokeType stroke(1.5f, PathStrokeType::beveled, PathStrokeType::rounded);
  static const DropShadow shadow(Colour(0xbb000000), 5, Point<int>(0, 0));

  g.drawImage(background_,
              0, 0, getWidth(), getHeight(),
              0, 0, background_.getWidth(), background_.getHeight());

  shadow.drawForPath(g, filter_response_path_);

  g.setColour(Colour(0xff565656));
  g.fillPath(filter_response_path_);

  g.setColour(Colour(0xff03a9f4));
  g.strokePath(filter_response_path_, stroke);
}
Beispiel #11
0
    void drawRoundThumb (Graphics& g, const float x, const float y,
                         const float diameter, const Colour& colour, float outlineThickness)
    {
        const Rectangle<float> a (x, y, diameter, diameter);
        const float halfThickness = outlineThickness * 0.5f;

        Path p;
        p.addEllipse (x + halfThickness, y + halfThickness, diameter - outlineThickness, diameter - outlineThickness);

        const DropShadow ds (Colours::black, 1, Point<int> (0, 0));
        ds.drawForPath (g, p);

        g.setColour (colour);
        g.fillPath (p);

        g.setColour (colour.brighter());
        g.strokePath (p, PathStrokeType (outlineThickness));
    }
Beispiel #12
0
void WaveViewer::paintBackground(Graphics& g) {
  static const DropShadow shadow(Colour(0xbb000000), 5, Point<int>(0, 0));

  g.fillAll(Colour(0xff424242));

  g.setColour(Colour(0xff4a4a4a));
  for (int x = 0; x < getWidth(); x += GRID_CELL_WIDTH)
    g.drawLine(x, 0, x, getHeight());
  for (int y = 0; y < getHeight(); y += GRID_CELL_WIDTH)
    g.drawLine(0, y, getWidth(), y);

  shadow.drawForPath(g, wave_path_);

  g.setColour(Colour(0xff565656));
  g.fillPath(wave_path_);
  g.setColour(Colour(0xff03a9f4));
  g.strokePath(wave_path_, PathStrokeType(1.5f, PathStrokeType::beveled, PathStrokeType::rounded));
}
Beispiel #13
0
void OscillatorSection::paintBackground(Graphics& g) {
  static const float extra_knob_padding = 4.0f;
  static const DropShadow component_shadow(Colour(0x99000000), 3, Point<int>(0, 1));

  SynthSection::paintBackground(g);

  g.setColour(Colour(0xff212121));
  g.fillEllipse(transpose_1_->getBounds().toFloat().expanded(extra_knob_padding));
  g.fillEllipse(tune_1_->getBounds().toFloat().expanded(extra_knob_padding));
  g.fillEllipse(transpose_2_->getBounds().toFloat().expanded(extra_knob_padding));
  g.fillEllipse(tune_2_->getBounds().toFloat().expanded(extra_knob_padding));

  g.setColour(Colour(0xff303030));
  g.fillRect(0, tune_1_->getBottom() + 2, getWidth(), 5);

  g.setColour(Colour(0xff4fc3f7));
  g.strokePath(top_left_cross_path_, PathStrokeType(1.0f));

  g.setColour(Colour(0xff4fc3f7));
  g.strokePath(top_right_cross_path_, PathStrokeType(1.0f));

  g.setColour(Colour(0xff4fc3f7));
  g.strokePath(bottom_left_cross_path_, PathStrokeType(1.0f));

  g.setColour(Colour(0xff4fc3f7));
  g.strokePath(bottom_right_cross_path_, PathStrokeType(1.0f));

  g.setColour(Colour(0xffbbbbbb));
  g.setFont(Fonts::getInstance()->proportional_regular().withPointHeight(10.0f));
  drawTextForComponent(g, TRANS("MOD"), cross_modulation_);
  drawTextForComponent(g, TRANS("TRANS"), transpose_1_);
  drawTextForComponent(g, TRANS("TRANS"), transpose_2_);
  drawTextForComponent(g, TRANS("TUNE"), tune_1_);
  drawTextForComponent(g, TRANS("TUNE"), tune_2_);
  drawTextForComponent(g, TRANS("UNISON"), unison_detune_1_);
  drawTextForComponent(g, TRANS("UNISON"), unison_detune_2_);

  component_shadow.drawForRectangle(g, wave_viewer_1_->getBounds());
  component_shadow.drawForRectangle(g, wave_viewer_2_->getBounds());

  g.setColour(Colour(0xff424242));
  paintKnobShadows(g);
}
void GraphicalStepSequencer::paintBackground(Graphics& g) {
  static const DropShadow shadow(Colour(0xbb000000), 1, Point<int>(0, 0));
  if (sequence_.size() == 0 || num_steps_slider_ == nullptr)
    return;

  g.fillAll(Colour(0xff424242));

  float x_inc = getWidth() / (1.0f * num_steps_);
  g.setColour(Colour(0xff545454));
  for (int i = 1; i * x_inc < getWidth(); ++i)
    g.drawLine(i * x_inc, 0, i * x_inc, getHeight());

  // Draw shadows.
  float x = 0.0f;
  for (int i = 0; i < num_steps_; ++i) {
    float val = sequence_[i]->getValue();
    float bar_position = (getHeight() - 1.0f) * ((1.0f - val) / 2.0f);
    Rectangle<int> rect(x, bar_position, x_inc, 1.5f);
    shadow.drawForRectangle(g, rect);
    x += x_inc;
  }

  // Draw bars.
  x = 0.0f;
  for (int i = 0; i < num_steps_; ++i) {
    float val = sequence_[i]->getValue();
    float bar_position = (getHeight() - 1.0f) * ((1.0f - val) / 2.0f);
    if (val >= 0) {
      g.setColour(Colour(0xff565656));
      g.fillRect(x, bar_position, x_inc, proportionOfHeight(0.5f) - bar_position);
    }
    else {
      float half_height = proportionOfHeight(0.5f);
      g.setColour(Colour(0xff565656));
      g.fillRect(x, half_height, x_inc, bar_position - half_height);
    }

    g.setColour(Colour(0xff03a9f4));
    g.fillRect(x, bar_position, x_inc, 1.5f);

    x += x_inc;
  }
}
Beispiel #15
0
void FullInterface::paintBackground(Graphics& g) {
  static const DropShadow shadow(Colour(0xcc000000), 3, Point<int>(0, 1));
  static const DropShadow logo_shadow(Colour(0xff000000), 8, Point<int>(0, 0));
  static const DropShadow component_shadow(Colour(0xcc000000), 5, Point<int>(0, 1));
  static Font roboto_reg(Typeface::createSystemTypefaceFor(BinaryData::RobotoRegular_ttf,
                                                           BinaryData::RobotoRegular_ttfSize));
  static Font roboto_light(Typeface::createSystemTypefaceFor(BinaryData::RobotoLight_ttf,
                                                             BinaryData::RobotoLight_ttfSize));
  static const Image helm_small = ImageCache::getFromMemory(BinaryData::helm_icon_32_2x_png,
                                                            BinaryData::helm_icon_32_2x_pngSize);
  g.setColour(Colour(0xff212121));
  g.fillRect(getLocalBounds());

  shadow.drawForRectangle(g, arp_section_->getBounds());
  shadow.drawForRectangle(g, global_tool_tip_->getBounds());
  shadow.drawForRectangle(g, oscilloscope_->getBounds());
  shadow.drawForRectangle(g, Rectangle<int>(92, 8, 244, TOP_HEIGHT));

  shadow.drawForRectangle(g, Rectangle<int>(16, 8, 68, 64));
  g.setColour(Colour(0xff303030));
  g.fillRoundedRectangle(16.0f, 8.0f, 68.0f, 64.0f, 3.0f);

  g.saveState();
  g.setOrigin(18, 8);

  logo_shadow.drawForImage(g, helm_small);
  g.restoreState();

  g.setColour(Colour(0xff303030));
  g.fillRect(92, 8, 244, TOP_HEIGHT);

  g.setColour(Colour(0xffbbbbbb));
  g.setFont(roboto_reg.withPointHeight(10.0f));
  g.drawText(TRANS("BPM"), patch_selector_->getX(), beats_per_minute_->getY(),
             44, beats_per_minute_->getHeight(),
             Justification::centred, false);

  component_shadow.drawForRectangle(g, patch_selector_->getBounds());

  paintKnobShadows(g);
}
void DefaultLookAndFeel::drawToggleButton(Graphics& g, ToggleButton& button,
                                          bool isMouseOverButton, bool isButtonDown) {
  static const DropShadow shadow(Colour(0x88000000), 1.0f, Point<int>(0, 0));
  static float stroke_percent = 0.1;
  static float padding = 3.0f;
  static float hover_padding = 1.0f;

  float full_radius = std::min(button.getWidth(), button.getHeight()) / 2.0;
  float stroke_width = 2.0f * full_radius * stroke_percent;
  PathStrokeType stroke_type(stroke_width, PathStrokeType::beveled, PathStrokeType::rounded);
  float outer_radius = full_radius - stroke_width - padding;
  Path outer;
  outer.addCentredArc(full_radius, full_radius, outer_radius, outer_radius,
                      mopo::PI, -POWER_ARC_ANGLE, POWER_ARC_ANGLE, true);

  Path shadow_path;
  stroke_type.createStrokedPath(shadow_path, outer);
  shadow.drawForPath(g, shadow_path);
  Rectangle<int> bar_shadow_rect(full_radius - 1.0f, padding, 2.0f, full_radius - padding);
  shadow.drawForRectangle(g, bar_shadow_rect);

  if (button.getToggleState())
    g.setColour(Colours::white);
  else
    g.setColour(Colours::grey);

  g.strokePath(outer, stroke_type);
  g.fillRoundedRectangle(full_radius - 1.0f, padding, 2.0f, full_radius - padding, 1.0f);

  if (isButtonDown) {
    g.setColour(Colour(0x11000000));
    g.fillEllipse(hover_padding, hover_padding,
                  button.getWidth() - 2 * hover_padding, button.getHeight() - 2 * hover_padding);
  }
  else if (isMouseOverButton) {
    g.setColour(Colour(0x11ffffff));
    g.fillEllipse(hover_padding, hover_padding,
                  button.getWidth() - 2 * hover_padding, button.getHeight() - 2 * hover_padding);  }
}
Beispiel #17
0
void DeleteSection::paint(Graphics& g) {
  static Font patch_font(Typeface::createSystemTypefaceFor(BinaryData::DroidSansMono_ttf,
                                                           BinaryData::DroidSansMono_ttfSize));
  static Font roboto_light(Typeface::createSystemTypefaceFor(BinaryData::RobotoLight_ttf,
                                                             BinaryData::RobotoLight_ttfSize));
  static const DropShadow shadow(Colour(0xff000000), 5, Point<int>(0, 0));

  g.setColour(Colour(0xbb212121));
  g.fillAll();

  Rectangle<int> delete_rect = getDeleteRect();
  shadow.drawForRectangle(g, delete_rect);
  g.setColour(Colour(0xff303030));
  g.fillRect(delete_rect);

  g.saveState();
  g.setOrigin(delete_rect.getX() + PADDING_X, delete_rect.getY() + PADDING_Y);

  g.setFont(roboto_light.withPointHeight(14.0f));
  g.setColour(Colour(0xffaaaaaa));

  String text;
  if (file_.isDirectory())
    text = TRANS("Are you sure you want to delte this folder?");
  else
  text = TRANS("Are you sure you want to delte this patch?");
  g.drawText(text,
             0, 0.0f, delete_rect.getWidth() - 2 * PADDING_X, 22.0f,
             Justification::centred, false);

  g.setFont(patch_font.withPointHeight(16.0f));
  g.setColour(Colour(0xff03a9f4));
  g.drawText(file_.getFileNameWithoutExtension(),
             0, 20.0f, delete_rect.getWidth() - 2 * PADDING_X, 22.0f,
             Justification::centred, false);

  g.restoreState();
}
Beispiel #18
0
void AboutSection::paint(Graphics& g) {
  static const DropShadow shadow(Colour(0xff000000), 5, Point<int>(0, 0));

  g.setColour(Colour(0xbb212121));
  g.fillAll();

  Rectangle<int> info_rect = getInfoRect();
  shadow.drawForRectangle(g, info_rect);
  g.setColour(Colour(0xff303030));
  g.fillRect(info_rect);

  g.saveState();
  g.setOrigin(info_rect.getX() + PADDING_X, info_rect.getY() + PADDING_Y);
  Image helm_small = ImageCache::getFromMemory(BinaryData::helm_icon_128_1x_png,
                                               BinaryData::helm_icon_128_1x_pngSize);
  shadow.drawForImage(g, helm_small);

  const Desktop::Displays::Display& display = Desktop::getInstance().getDisplays().getMainDisplay();
  if (display.scale > 1.5) {
    Image helm = ImageCache::getFromMemory(BinaryData::helm_icon_128_2x_png,
                                           BinaryData::helm_icon_128_2x_pngSize);
    g.drawImage(helm, 0, 0, 128, 128, 0, 0, 256, 256);
  }
  else
    g.drawImage(helm_small, 0, 0, 128, 128, 0, 0, 128, 128);

  g.setFont(Fonts::getInstance()->proportional_regular().withPointHeight(32.0));
  g.setColour(Colour(0xff2196f3));
  g.drawText(TRANS("HELM"),
             0.0f, 0.0f,
             info_rect.getWidth() - 2 * PADDING_X, 32.0f, Justification::centredTop);

  g.setFont(Fonts::getInstance()->proportional_light().withPointHeight(12.0));
  g.setColour(Colour(0xff666666));
  g.drawText(TRANS("v") + " " + ProjectInfo::versionString,
             0.0f, 36.0f,
             info_rect.getWidth() - 2 * PADDING_X, 32.0f, Justification::centredTop);

  g.setFont(Fonts::getInstance()->proportional_light().withPointHeight(12.0));
  g.drawText(TRANS("Developed by"),
             0.0f, 4.0f,
             info_rect.getWidth() - 2 * PADDING_X, 20.0f, Justification::right);

  g.setColour(Colour(0xffaaaaaa));
  g.drawText(TRANS("Helm is free software and"),
             0.0f, 62.0,
             info_rect.getWidth() - 2 * PADDING_X, 20.0f, Justification::topRight);

  g.drawText(TRANS("comes with no warranty"),
             0.0f, 76.0f,
             info_rect.getWidth() - 2 * PADDING_X, 20.0f, Justification::topRight);

  g.setFont(Fonts::getInstance()->proportional_light().withPointHeight(12.0));
  g.drawText(TRANS("Check for updates"),
             0.0f, 141.0f,
             info_rect.getWidth() - 2 * PADDING_X - 1.5 * BUTTON_WIDTH,
             20.0f, Justification::topRight);
  g.drawText(TRANS("Animate graphics"),
             0.0f, 141.0f,
             273.0f - PADDING_X - 0.5 * BUTTON_WIDTH,
             20.0f, Justification::topRight);

  g.restoreState();
}