Exemple #1
0
 private static int getProgressBarBaseline(JProgressBar pb, int height) {
   if (pb.isStringPainted() && pb.getOrientation() == JProgressBar.HORIZONTAL) {
     FontMetrics metrics = pb.getFontMetrics(pb.getFont());
     Insets insets = pb.getInsets();
     int y = insets.top;
     if (isWindows() && isXP()) {
       if (pb.isIndeterminate()) {
         y = -1;
         height--;
       } else {
         y = 0;
         height -= 3;
       }
     } else if (isGTK()) {
       return (height - metrics.getAscent() - metrics.getDescent()) / 2 + metrics.getAscent();
     } else if (isAqua()) {
       if (pb.isIndeterminate()) {
         // Aqua doesn't appear to support text on indeterminate
         // progress bars.
         return -1;
       }
       y -= 1;
       height -= (insets.top + insets.bottom);
     } else {
       height -= insets.top + insets.bottom;
     }
     return y + (height + metrics.getAscent() - metrics.getLeading() - metrics.getDescent()) / 2;
   }
   return -1;
 }
  @Override
  protected void paintComponent(Graphics g) {
    super.paintComponent(g);

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

    int width = getWidth();
    int height = getHeight();

    // rendering hints
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    g2.setRenderingHint(
        RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);

    // formatter
    DecimalFormat format = new DecimalFormat("##.#%");
    // text to display
    String percentage =
        (value == null || Double.parseDouble(value.toString()) == -1)
            ? ""
            : format.format(Double.parseDouble(value.toString()));

    // paint text
    g2.setColor(Color.black);
    g2.setFont(g2.getFont().deriveFont(Font.BOLD));
    FontMetrics fontMetrics = g2.getFontMetrics();
    int textWidth = fontMetrics.stringWidth(percentage);
    int xPos = (width - textWidth) / 2;
    int yPos = height / 2 + fontMetrics.getDescent() + 2;
    g2.drawString(percentage, xPos, yPos);

    g2.dispose();
  }
Exemple #3
0
  /**
   * The function prints out key to jumpshot data.
   */
  int print (Graphics g, int x, int y, int width, int height) {
    Font f = g.getFont ();
    FontMetrics fm = getToolkit ().getFontMetrics (f);
    
    int charW = fm.stringWidth (" "), charH = fm.getHeight ();
    int hgap1 = charW, hgap2 = 2 * charW, vgap = fm.getAscent ();
    int rectW = 30, rectH = charH; //Dimensions of state rectangles
    int xcord = x, ycord = y;
    
    Enumeration enum = parent.stateDefs.elements ();
    while (enum.hasMoreElements ()) {
      RecDef s = (RecDef)enum.nextElement ();
      
      if (s.stateVector.size () > 0) {
	int strW = fm.stringWidth (s.description);
	
	if ((xcord + rectW + hgap1 + strW) > (width + x)) {
          xcord = x; ycord += (charH + vgap);
        }
        
        g.setColor (s.color);
        g.fillRect (xcord, ycord, rectW, rectH);
        g.setColor (Color.black);
        g.drawRect (xcord, ycord, rectW - 1, rectH - 1);
        g.drawString( s.description,
                      xcord + rectW + hgap1,
                      ycord + rectH - fm.getDescent () - 1);
        xcord += (rectW + hgap1 + strW + hgap2);
      }
    }
    return (ycord - y + (2 * charH));
  }      
 protected void paintText(Graphics g, JComponent com, Rectangle rect, String s) {
   JButtonLinkA bn = (JButtonLinkA) com;
   ButtonModel bnModel = bn.getModel();
   Color color = bn.getForeground();
   Object obj = null;
   if (bnModel.isEnabled()) {
     if (bnModel.isPressed()) bn.setForeground(bn.getActiveLinkColor());
     else if (bn.isLinkVisited()) bn.setForeground(bn.getVisitedLinkColor());
     else bn.setForeground(bn.getLinkColor());
   } else {
     if (bn.getDisabledLinkColor() != null) bn.setForeground(bn.getDisabledLinkColor());
   }
   super.paintText(g, com, rect, s);
   int behaviour = bn.getLinkBehavior();
   boolean drawLine = false;
   if (behaviour == JButtonLinkA.HOVER_UNDERLINE) {
     if (bnModel.isRollover()) drawLine = true;
   } else if (behaviour == JButtonLinkA.ALWAYS_UNDERLINE
       || behaviour == JButtonLinkA.SYSTEM_DEFAULT) drawLine = true;
   if (!drawLine) return;
   FontMetrics fm = g.getFontMetrics();
   int x = rect.x + getTextShiftOffset();
   int y = (rect.y + fm.getAscent() + fm.getDescent() + getTextShiftOffset()) - 1;
   if (bnModel.isEnabled()) {
     g.setColor(bn.getForeground());
     g.drawLine(x, y, (x + rect.width) - 1, y);
   } else {
     g.setColor(bn.getBackground().brighter());
     g.drawLine(x, y, (x + rect.width) - 1, y);
   }
 }
Exemple #5
0
  private void calcGraphInsets() {
    int top = titleFm.getHeight() + titleFm.getDescent() + 10;
    int left = (int) (2.5 * fm.getHeight());
    int bottom = 2 * fm.getHeight();
    int right = (int) (2.5 * fm.getHeight());

    graphInsets = new Insets(top, left, bottom, right);
  }
  public Dimension getPreferredSize(JComponent c) {
    Dimension size;
    Insets border = progressBar.getInsets();
    FontMetrics fontSizer = progressBar.getFontMetrics(progressBar.getFont());

    if (progressBar.getOrientation() == JProgressBar.HORIZONTAL) {
      size = new Dimension(getPreferredInnerHorizontal());
      // Ensure that the progress string will fit
      if (progressBar.isStringPainted()) {
        // I'm doing this for completeness.
        String progString = progressBar.getString();
        int stringWidth = SwingUtilities2.stringWidth(progressBar, fontSizer, progString);
        if (stringWidth > size.width) {
          size.width = stringWidth;
        }
        // This uses both Height and Descent to be sure that
        // there is more than enough room in the progress bar
        // for everything.
        // This does have a strange dependency on
        // getStringPlacememnt() in a funny way.
        int stringHeight = fontSizer.getHeight() + fontSizer.getDescent();
        if (stringHeight > size.height) {
          size.height = stringHeight;
        }
      }
    } else {
      size = new Dimension(getPreferredInnerVertical());
      // Ensure that the progress string will fit.
      if (progressBar.isStringPainted()) {
        String progString = progressBar.getString();
        int stringHeight = fontSizer.getHeight() + fontSizer.getDescent();
        if (stringHeight > size.width) {
          size.width = stringHeight;
        }
        // This is also for completeness.
        int stringWidth = SwingUtilities2.stringWidth(progressBar, fontSizer, progString);
        if (stringWidth > size.height) {
          size.height = stringWidth;
        }
      }
    }

    size.width += border.left + border.right;
    size.height += border.top + border.bottom;
    return size;
  }
Exemple #7
0
 /**
  * Write the given text string in the current font, left-aligned at (x, y).
  *
  * @param x the x-coordinate of the text
  * @param y the y-coordinate of the text
  * @param s the text
  */
 public static void textLeft(double x, double y, String s) {
   offscreen.setFont(font);
   FontMetrics metrics = offscreen.getFontMetrics();
   double xs = scaleX(x);
   double ys = scaleY(y);
   int hs = metrics.getDescent();
   offscreen.drawString(s, (float) (xs), (float) (ys + hs));
   draw();
 }
Exemple #8
0
  /*
   *  Determine the Y offset for the current row
   */
  private int getOffsetY(int rowStartOffset, FontMetrics fontMetrics) throws BadLocationException {
    //  Get the bounding rectangle of the row

    Rectangle r = component.modelToView(rowStartOffset);
    int lineHeight = fontMetrics.getHeight();
    int y = r.y + r.height;
    int descent = 0;

    //  The text needs to be positioned above the bottom of the bounding
    //  rectangle based on the descent of the font(s) contained on the row.
    if (r.height == lineHeight) {
      // default font is being used
      descent = fontMetrics.getDescent();
    } else {
      // We need to check all the attributes for font changes
      if (fonts == null) {
        fonts = new HashMap<String, FontMetrics>();
      }

      Element root = component.getDocument().getDefaultRootElement();
      int index = root.getElementIndex(rowStartOffset);
      Element line = root.getElement(index);

      for (int i = 0; i < line.getElementCount(); i++) {
        Element child = line.getElement(i);
        AttributeSet as = child.getAttributes();
        String fontFamily = (String) as.getAttribute(StyleConstants.FontFamily);
        Integer fontSize = (Integer) as.getAttribute(StyleConstants.FontSize);
        String key = fontFamily + fontSize;

        FontMetrics fm = fonts.get(key);

        if (fm == null) {
          Font font = new Font(fontFamily, Font.PLAIN, fontSize);
          fm = component.getFontMetrics(font);
          fonts.put(key, fm);
        }

        descent = Math.max(descent, fm.getDescent());
      }
    }

    return y - descent;
  }
  /**
   * Designate the place where the progress string will be painted. This implementation places it at
   * the center of the progress bar (in both x and y). Override this if you want to right, left,
   * top, or bottom align the progress string or if you need to nudge it around for any reason.
   */
  protected Point getStringPlacement(
      Graphics g, String progressString, int x, int y, int width, int height) {
    FontMetrics fontSizer = SwingUtilities2.getFontMetrics(progressBar, g, progressBar.getFont());
    int stringWidth = SwingUtilities2.stringWidth(progressBar, fontSizer, progressString);

    if (progressBar.getOrientation() == JProgressBar.HORIZONTAL) {
      return new Point(
          x + Math.round(width / 2 - stringWidth / 2),
          y
              + ((height + fontSizer.getAscent() - fontSizer.getLeading() - fontSizer.getDescent())
                  / 2));
    } else { // VERTICAL
      return new Point(
          x
              + ((width - fontSizer.getAscent() + fontSizer.getLeading() + fontSizer.getDescent())
                  / 2),
          y + Math.round(height / 2 - stringWidth / 2));
    }
  }
Exemple #10
0
 private void adjustCanvasStuff() {
   Font f = parent.frameFont;
   setFont(f);
   fm = getToolkit().getFontMetrics(f);
   lineSize = fm.getHeight();
   rulerHt = 3 * lineSize;
   zLockStrW = fm.stringWidth("Zoom Lock");
   elTimeStrW = fm.stringWidth("Elapsed Time");
   fDescent = fm.getDescent();
   dpi = getToolkit().getScreenResolution();
 }
 /**
  * Returns the baseline.
  *
  * @throws NullPointerException {@inheritDoc}
  * @throws IllegalArgumentException {@inheritDoc}
  * @see javax.swing.JComponent#getBaseline(int, int)
  * @since 1.6
  */
 public int getBaseline(JComponent c, int width, int height) {
   super.getBaseline(c, width, height);
   if (progressBar.isStringPainted() && progressBar.getOrientation() == JProgressBar.HORIZONTAL) {
     FontMetrics metrics = progressBar.getFontMetrics(progressBar.getFont());
     Insets insets = progressBar.getInsets();
     int y = insets.top;
     height = height - insets.top - insets.bottom;
     return y + (height + metrics.getAscent() - metrics.getLeading() - metrics.getDescent()) / 2;
   }
   return -1;
 }
Exemple #12
0
 private static int getPanelBaseline(JPanel panel, int height) {
   Border border = panel.getBorder();
   if (border instanceof TitledBorder) {
     TitledBorder titledBorder = (TitledBorder) border;
     if (titledBorder.getTitle() != null && !"".equals(titledBorder.getTitle())) {
       Font font = titledBorder.getTitleFont();
       if (font == null) {
         font = panel.getFont();
         if (font == null) {
           font = new Font("Dialog", Font.PLAIN, 12);
         }
       }
       Border border2 = titledBorder.getBorder();
       Insets borderInsets;
       if (border2 != null) {
         borderInsets = border2.getBorderInsets(panel);
       } else {
         borderInsets = EMPTY_INSETS;
       }
       FontMetrics fm = panel.getFontMetrics(font);
       int fontHeight = fm.getHeight();
       int descent = fm.getDescent();
       int ascent = fm.getAscent();
       int y = EDGE_SPACING;
       int h = height - EDGE_SPACING * 2;
       int diff;
       switch (((TitledBorder) border).getTitlePosition()) {
         case TitledBorder.ABOVE_TOP:
           diff = ascent + descent + (Math.max(EDGE_SPACING, TEXT_SPACING * 2) - EDGE_SPACING);
           return y + diff - (descent + TEXT_SPACING);
         case TitledBorder.TOP:
         case TitledBorder.DEFAULT_POSITION:
           diff = Math.max(0, ((ascent / 2) + TEXT_SPACING) - EDGE_SPACING);
           return (y + diff - descent) + (borderInsets.top + ascent + descent) / 2;
         case TitledBorder.BELOW_TOP:
           return y + borderInsets.top + ascent + TEXT_SPACING;
         case TitledBorder.ABOVE_BOTTOM:
           return (y + h) - (borderInsets.bottom + descent + TEXT_SPACING);
         case TitledBorder.BOTTOM:
           h -= fontHeight / 2;
           return ((y + h) - descent) + ((ascent + descent) - borderInsets.bottom) / 2;
         case TitledBorder.BELOW_BOTTOM:
           h -= fontHeight;
           return y + h + ascent + TEXT_SPACING;
       }
     }
   }
   return -1;
 }
  public void paintComponent(Graphics g) {
    super.paintComponent(g);
    ((Graphics2D) g)
        .setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    Dimension theSize = getSize();

    if (mColorListMode == VisualizationColor.cColorListModeCategories) {
      int categories = mCategoryColorList.length;
      if (categories <= cMaxEditableColors) {
        int fieldWidth = (theSize.width - 2 * cBorder + cSpacing) / categories - cSpacing;
        mRect = new Rectangle[categories];
        for (int i = 0; i < categories; i++) {
          mRect[i] =
              new Rectangle(
                  cBorder + i * (fieldWidth + cSpacing),
                  cBorder,
                  fieldWidth,
                  theSize.height - 2 * cBorder);
          drawColorButton(g, i);
        }
      } else {
        final String message = "<too many colors to edit>";
        g.setColor(Color.GRAY);
        g.setFont(new Font("Arial", Font.BOLD, 13));
        FontMetrics m = g.getFontMetrics();
        g.drawString(
            message,
            (theSize.width - m.stringWidth(message)) / 2,
            (theSize.height + m.getHeight()) / 2 - m.getDescent());
      }
    } else {
      int size = theSize.height - 2 * cBorder;
      int x1 = 2 * cBorder + size;
      int x2 = theSize.width - 2 * cBorder - size;
      mRect = new Rectangle[3];
      mRect[0] = new Rectangle(cBorder, cBorder, size, size);
      mRect[1] =
          new Rectangle(
              theSize.width - size - cBorder, theSize.height - size - cBorder, size, size);
      mRect[cColorWedgeButton] = new Rectangle(x1, cBorder, x2 - x1, size);
      drawColorButton(g, 0);
      drawColorButton(g, 1);
      drawColorButton(g, cColorWedgeButton);
    }
  }
Exemple #14
0
  private void establishFontMetrics() {
    final BufferedImage img = createBufferedImage(1, 1);
    final Graphics2D graphics = img.createGraphics();
    graphics.setFont(myNormalFont);

    final float lineSpace = mySettingsProvider.getLineSpace();
    final FontMetrics fo = graphics.getFontMetrics();

    myDescent = fo.getDescent();
    myCharSize.width = fo.charWidth('W');
    myCharSize.height = fo.getHeight() + (int) (lineSpace * 2);
    myDescent += lineSpace;

    myMonospaced = isMonospaced(fo);
    if (!myMonospaced) {
      LOG.info("WARNING: Font " + myNormalFont.getName() + " is non-monospaced");
    }

    img.flush();
    graphics.dispose();
  }
Exemple #15
0
    public void run() {

      Thread me = Thread.currentThread();

      while (thread == me && !isShowing() || getSize().width == 0) {
        try {
          thread.sleep(500);
        } catch (InterruptedException e) {
          return;
        }
      }

      while (thread == me && isShowing()) {
        Dimension d = getSize();
        if (d.width != w || d.height != h) {
          w = d.width;
          h = d.height;
          bimg = (BufferedImage) createImage(w, h);
          big = bimg.createGraphics();
          big.setFont(font);
          FontMetrics fm = big.getFontMetrics(font);
          ascent = (int) fm.getAscent();
          descent = (int) fm.getDescent();
        }
        repaint();
        try {
          thread.sleep(sleepAmount);
        } catch (InterruptedException e) {
          break;
        }
        if (MemoryMonitor.dateStampCB.isSelected()) {
          System.out.println(new Date().toString() + " " + usedStr);
        }
      }
      thread = null;
    }
Exemple #16
0
  private static int getSliderBaseline(JSlider slider, int height) {
    // We don't handle GTK as too much is hidden to be able to calculate it
    if (slider.getPaintLabels() && !isGTK()) {
      boolean isAqua = isAqua();
      FontMetrics metrics = slider.getFontMetrics(slider.getFont());
      Insets insets = slider.getInsets();
      Insets focusInsets = (Insets) UIManager.get("Slider.focusInsets");
      if (slider.getOrientation() == JSlider.HORIZONTAL) {
        int tickLength = 8;
        int contentHeight =
            height - insets.top - insets.bottom - focusInsets.top - focusInsets.bottom;
        int thumbHeight = 20;
        if (isMetal()) {
          tickLength = ((Integer) UIManager.get("Slider.majorTickLength")).intValue() + 5;
          thumbHeight = UIManager.getIcon("Slider.horizontalThumbIcon").getIconHeight();
        } else if (isWindows() && isXP()) {
          // NOTE: this is not correct, this should come from
          // the skin (in >= 1.5), but short of reflection
          // hacks we don't have access to the real value.
          thumbHeight++;
        }
        int centerSpacing = thumbHeight;
        if (isAqua || slider.getPaintTicks()) {
          // centerSpacing += getTickLength();
          centerSpacing += tickLength;
        }
        // Assume uniform labels.
        centerSpacing += metrics.getAscent() + metrics.getDescent();
        int trackY = insets.top + focusInsets.top + (contentHeight - centerSpacing - 1) / 2;
        if (isAqua) {
          if (slider.getPaintTicks()) {
            int prefHeight = slider.getUI().getPreferredSize(slider).height;
            int prefDelta = height - prefHeight;
            if (prefDelta > 0) {
              trackY -= Math.min(1, prefDelta);
            }
          } else {
            trackY--;
          }
        }

        int trackHeight = thumbHeight;
        int tickY = trackY + trackHeight;
        int tickHeight = tickLength;
        if (!isAqua && !slider.getPaintTicks()) {
          tickHeight = 0;
        }
        int labelY = tickY + tickHeight;
        return labelY + metrics.getAscent();
      } else { // vertical
        boolean inverted = slider.getInverted();
        Integer value = inverted ? getMinSliderValue(slider) : getMaxSliderValue(slider);
        if (value != null) {
          int thumbHeight = 11;
          if (isMetal()) {
            thumbHeight = UIManager.getIcon("Slider.verticalThumbIcon").getIconHeight();
          }
          int trackBuffer = Math.max(metrics.getHeight() / 2, thumbHeight / 2);
          int contentY = focusInsets.top + insets.top;
          int trackY = contentY + trackBuffer;
          int trackHeight =
              height
                  - focusInsets.top
                  - focusInsets.bottom
                  - insets.top
                  - insets.bottom
                  - trackBuffer
                  - trackBuffer;
          int maxValue = getMaxSliderValue(slider).intValue();
          int min = slider.getMinimum();
          int max = slider.getMaximum();
          double valueRange = (double) max - (double) min;
          double pixelsPerValue = (double) trackHeight / (double) valueRange;
          int trackBottom = trackY + (trackHeight - 1);
          if (isAqua) {
            trackY -= 3;
            trackBottom += 6;
          }
          int yPosition = trackY;
          double offset;

          if (!inverted) {
            offset = pixelsPerValue * ((double) max - value.intValue());
          } else {
            offset = pixelsPerValue * ((double) value.intValue() - min);
          }
          if (isAqua) {
            yPosition += Math.floor(offset);
          } else {
            yPosition += Math.round(offset);
          }
          yPosition = Math.max(trackY, yPosition);
          yPosition = Math.min(trackBottom, yPosition);
          if (isAqua) {
            return yPosition + metrics.getAscent();
          }
          return yPosition - metrics.getHeight() / 2 + metrics.getAscent();
        }
      }
    }
    return -1;
  }
  protected int doPaintText(Graphics2D g, int offset, boolean focusAroundIcon) {
    // If there is no icon, then we have to add left internal padding
    if (offset == 0) {
      offset = myIpad.left;
    }

    int textStart = offset;
    if (myBorder != null) {
      offset += myBorder.getBorderInsets(this).left;
    }

    final List<Object[]> searchMatches = new ArrayList<>();

    applyAdditionalHints(g);
    final Font baseFont = getBaseFont();
    g.setFont(baseFont);
    offset += computeTextAlignShift(baseFont);
    int baseSize = baseFont.getSize();
    FontMetrics baseMetrics = g.getFontMetrics();
    Rectangle area = computePaintArea();
    final int textBaseline = area.y + getTextBaseLine(baseMetrics, area.height);
    boolean wasSmaller = false;
    for (int i = 0; i < myFragments.size(); i++) {
      final SimpleTextAttributes attributes = myAttributes.get(i);

      Font font = g.getFont();
      boolean isSmaller = attributes.isSmaller();
      if (font.getStyle() != attributes.getFontStyle()
          || isSmaller != wasSmaller) { // derive font only if it is necessary
        font =
            font.deriveFont(
                attributes.getFontStyle(),
                isSmaller ? UIUtil.getFontSize(UIUtil.FontSize.SMALL) : baseSize);
      }
      wasSmaller = isSmaller;

      g.setFont(font);
      final FontMetrics metrics = g.getFontMetrics(font);

      final int fragmentWidth = computeStringWidth(i, font);

      final int fragmentPadding = myFragmentPadding.get(i);

      final Color bgColor = attributes.isSearchMatch() ? null : attributes.getBgColor();
      if ((attributes.isOpaque() || isOpaque()) && bgColor != null) {
        g.setColor(bgColor);
        g.fillRect(offset, 0, fragmentWidth, getHeight());
      }

      Color color = attributes.getFgColor();
      if (color
          == null) { // in case if color is not defined we have to get foreground color from Swing
                     // hierarchy
        color = getForeground();
      }
      if (!isEnabled()) {
        color = UIUtil.getInactiveTextColor();
      }
      g.setColor(color);

      final int fragmentAlignment = myFragmentAlignment.get(i);

      final int endOffset;
      if (fragmentPadding > 0 && fragmentPadding > fragmentWidth) {
        endOffset = fragmentPadding;
        if (fragmentAlignment == SwingConstants.RIGHT
            || fragmentAlignment == SwingConstants.TRAILING) {
          offset = fragmentPadding - fragmentWidth;
        }
      } else {
        endOffset = offset + fragmentWidth;
      }

      if (!attributes.isSearchMatch()) {
        if (shouldDrawMacShadow()) {
          g.setColor(SHADOW_COLOR);
          doDrawString(g, i, offset, textBaseline + 1);
        }

        if (shouldDrawDimmed()) {
          color = ColorUtil.dimmer(color);
        }

        g.setColor(color);
        doDrawString(g, i, offset, textBaseline);
      }

      // for some reason strokeState here may be incorrect, resetting the stroke helps
      g.setStroke(g.getStroke());

      // 1. Strikeout effect
      if (attributes.isStrikeout() && !attributes.isSearchMatch()) {
        EffectPainter.STRIKE_THROUGH.paint(
            g, offset, textBaseline, fragmentWidth, getCharHeight(g), font);
      }
      // 2. Waved effect
      if (attributes.isWaved()) {
        if (attributes.getWaveColor() != null) {
          g.setColor(attributes.getWaveColor());
        }
        EffectPainter.WAVE_UNDERSCORE.paint(
            g, offset, textBaseline + 1, fragmentWidth, Math.max(2, metrics.getDescent()), font);
      }
      // 3. Underline
      if (attributes.isUnderline()) {
        EffectPainter.LINE_UNDERSCORE.paint(
            g, offset, textBaseline, fragmentWidth, metrics.getDescent(), font);
      }
      // 4. Bold Dotted Line
      if (attributes.isBoldDottedLine()) {
        final int dottedAt = SystemInfo.isMac ? textBaseline : textBaseline + 1;
        final Color lineColor = attributes.getWaveColor();
        UIUtil.drawBoldDottedLine(
            g, offset, offset + fragmentWidth, dottedAt, bgColor, lineColor, isOpaque());
      }

      if (attributes.isSearchMatch()) {
        searchMatches.add(
            new Object[] {
              offset,
              offset + fragmentWidth,
              textBaseline,
              myFragments.get(i),
              g.getFont(),
              attributes
            });
      }

      offset = endOffset;
    }

    // Paint focus border around the text and icon (if necessary)
    if (myPaintFocusBorder && myBorder != null) {
      if (focusAroundIcon) {
        myBorder.paintBorder(this, g, 0, 0, getWidth(), getHeight());
      } else {
        myBorder.paintBorder(this, g, textStart, 0, getWidth() - textStart, getHeight());
      }
    }

    // draw search matches after all
    for (final Object[] info : searchMatches) {
      Integer x1 = (Integer) info[0];
      Integer x2 = (Integer) info[1];
      UIUtil.drawSearchMatch(g, x1, x2, getHeight());
      g.setFont((Font) info[4]);

      Integer baseline = (Integer) info[2];
      String text = (String) info[3];
      if (shouldDrawMacShadow()) {
        g.setColor(SHADOW_COLOR);
        g.drawString(text, x1, baseline + 1);
      }

      g.setColor(new JBColor(Gray._50, Gray._0));
      g.drawString(text, x1, baseline);

      if (((SimpleTextAttributes) info[5]).isStrikeout()) {
        EffectPainter.STRIKE_THROUGH.paint(g, x1, baseline, x2 - x1, getCharHeight(g), g.getFont());
      }
    }
    return offset;
  }
 private int getTextBaseLine() {
   FontMetrics fm = getFontMetrics(getFont());
   return getHeight() / 2 + (fm.getHeight() / 2 - fm.getDescent());
 }