@Override
    protected void paintTaskOutlines(Graphics g) {
      Graphics2D g2d = (Graphics2D) g.create();
      SubstanceColorScheme scheme =
          SubstanceColorSchemeUtilities.getColorScheme(
              ribbon, ColorSchemeAssociationKind.SEPARATOR, ComponentState.ENABLED);

      Set<RibbonTask> tasksWithTrailingSeparators = new HashSet<RibbonTask>();
      // add all regular tasks except the last
      for (int i = 0; i < ribbon.getTaskCount() - 1; i++) {
        RibbonTask task = ribbon.getTask(i);
        tasksWithTrailingSeparators.add(task);
        // System.out.println("Added " + task.getTitle());
      }
      // add all tasks of visible contextual groups except last task in
      // each group
      for (int i = 0; i < ribbon.getContextualTaskGroupCount(); i++) {
        RibbonContextualTaskGroup group = ribbon.getContextualTaskGroup(i);
        if (ribbon.isVisible(group)) {
          for (int j = 0; j < group.getTaskCount() - 1; j++) {
            RibbonTask task = group.getTask(j);
            tasksWithTrailingSeparators.add(task);
          }
        }
      }

      for (RibbonTask taskWithTrailingSeparator : tasksWithTrailingSeparators) {
        JRibbonTaskToggleButton taskToggleButton = taskToggleButtons.get(taskWithTrailingSeparator);
        Rectangle bounds = taskToggleButton.getBounds();
        int x = bounds.x + bounds.width + getTabButtonGap() / 2 - 1;
        g2d.translate(x, 0);
        SeparatorPainterUtils.paintSeparator(
            ribbon,
            g2d,
            scheme,
            2,
            getHeight(),
            SwingConstants.VERTICAL,
            false,
            getHeight() / 3,
            0,
            true);
        g2d.translate(-x, 0);
      }

      g2d.dispose();
    }
  @Test
  public void testSetContextualTaskGroupTitle() {
    Assertions.assertThat(taskGroup1.getTitle()).isEqualTo("Context 1");
    Assertions.assertThat(taskGroup2.getTitle()).isEqualTo("Context 2");

    GuiActionRunner.execute(
        new GuiTask() {
          @Override
          protected void executeInEDT() throws Throwable {
            taskGroup1.setTitle("New Context 1");
          }
        });
    robot().waitForIdle();
    Assertions.assertThat(taskGroup1.getTitle()).isEqualTo("New Context 1");
    Assertions.assertThat(taskGroup2.getTitle()).isEqualTo("Context 2");

    GuiActionRunner.execute(
        new GuiTask() {
          @Override
          protected void executeInEDT() throws Throwable {
            taskGroup2.setTitle("New Context 2");
          }
        });
    robot().waitForIdle();
    Assertions.assertThat(taskGroup1.getTitle()).isEqualTo("New Context 1");
    Assertions.assertThat(taskGroup2.getTitle()).isEqualTo("New Context 2");
  }
  /*
   * (non-Javadoc)
   *
   * @see org.jvnet.flamingo.ribbon.ui.BasicRibbonUI#paintTaskArea(java.awt.
   * Graphics , int, int, int, int)
   */
  @Override
  protected void paintTaskArea(Graphics g, int x, int y, int width, int height) {
    if (this.ribbon.getTaskCount() == 0) return;

    Graphics2D g2d = (Graphics2D) g.create();

    RibbonTask selectedTask = this.ribbon.getSelectedTask();
    JRibbonTaskToggleButton selectedTaskButton = this.taskToggleButtons.get(selectedTask);
    Rectangle selectedTaskButtonBounds = selectedTaskButton.getBounds();
    Point converted =
        SwingUtilities.convertPoint(
            selectedTaskButton.getParent(), selectedTaskButtonBounds.getLocation(), this.ribbon);
    float radius =
        SubstanceSizeUtils.getClassicButtonCornerRadius(
            SubstanceSizeUtils.getComponentFontSize(this.ribbon));

    float borderDelta = SubstanceSizeUtils.getBorderStrokeWidth() / 2.0f;

    SubstanceBorderPainter borderPainter = SubstanceCoreUtilities.getBorderPainter(this.ribbon);
    float borderThickness = SubstanceSizeUtils.getBorderStrokeWidth();

    AbstractRibbonBand band = (selectedTask.getBandCount() == 0) ? null : selectedTask.getBand(0);
    SubstanceColorScheme borderScheme =
        SubstanceColorSchemeUtilities.getColorScheme(
            band, ColorSchemeAssociationKind.BORDER, ComponentState.ENABLED);

    Rectangle taskToggleButtonsViewportBounds =
        taskToggleButtonsScrollablePanel.getView().getParent().getBounds();
    taskToggleButtonsViewportBounds.setLocation(
        SwingUtilities.convertPoint(
            taskToggleButtonsScrollablePanel,
            taskToggleButtonsViewportBounds.getLocation(),
            this.ribbon));
    int startSelectedX = Math.max(converted.x + 1, (int) taskToggleButtonsViewportBounds.getMinX());
    startSelectedX = Math.min(startSelectedX, (int) taskToggleButtonsViewportBounds.getMaxX());
    int endSelectedX =
        Math.min(
            converted.x + selectedTaskButtonBounds.width - 1,
            (int) taskToggleButtonsViewportBounds.getMaxX());
    endSelectedX = Math.max(endSelectedX, (int) taskToggleButtonsViewportBounds.getMinX());

    Shape outerContour =
        RibbonBorderShaper.getRibbonBorderOutline(
            this.ribbon,
            x + borderDelta,
            x + width - borderDelta,
            startSelectedX - borderThickness,
            endSelectedX + borderThickness,
            converted.y + borderDelta,
            y + borderDelta,
            y + height - borderDelta,
            radius);

    Shape innerContour =
        RibbonBorderShaper.getRibbonBorderOutline(
            this.ribbon,
            x + borderDelta + borderThickness,
            x + width - borderThickness - borderDelta,
            startSelectedX - borderThickness,
            endSelectedX + borderThickness,
            converted.y + borderDelta + borderThickness,
            y + borderDelta + borderThickness,
            y + height - borderThickness - borderDelta,
            radius);

    g2d.setColor(
        SubstanceColorSchemeUtilities.getColorScheme(band, ComponentState.ENABLED)
            .getBackgroundFillColor());
    g2d.clipRect(x, y, width, height + 2);
    g2d.fill(outerContour);

    // g2d.setColor(Color.red);
    // g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
    // RenderingHints.VALUE_ANTIALIAS_ON);
    // g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL,
    // RenderingHints.VALUE_STROKE_PURE);
    // g2d.setStroke(new BasicStroke(0.5f));
    // g2d.draw(outerContour);
    // g2d.setColor(Color.blue);
    // g2d.draw(innerContour);
    borderPainter.paintBorder(
        g2d,
        this.ribbon,
        width,
        height + selectedTaskButtonBounds.height + 1,
        outerContour,
        innerContour,
        borderScheme);

    // check whether the currently selected task is a contextual task
    RibbonTask selected = selectedTask;
    RibbonContextualTaskGroup contextualGroup = selected.getContextualGroup();
    if (contextualGroup != null) {
      // paint a small gradient directly below the task area
      Insets ins = this.ribbon.getInsets();
      int topY = ins.top + getTaskbarHeight();
      int bottomY = topY + 5;
      Color hueColor = contextualGroup.getHueColor();
      Paint paint =
          new GradientPaint(
              0,
              topY,
              FlamingoUtilities.getAlphaColor(
                  hueColor, (int) (255 * RibbonContextualTaskGroup.HUE_ALPHA)),
              0,
              bottomY,
              FlamingoUtilities.getAlphaColor(hueColor, 0));
      g2d.setPaint(paint);
      g2d.clip(outerContour);
      g2d.fillRect(0, topY, width, bottomY - topY + 1);
    }

    // paint outlines of the contextual task groups
    // paintContextualTaskGroupsOutlines(g);

    g2d.dispose();
  }