in flutter-idea/src/io/flutter/view/MultiIconSimpleColoredComponent.java [789:956]
protected int doPaintTextAndIcons(Graphics2D g, boolean focusAroundIcon) {
float offset = myIpad.left;
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();
final int baseSize = baseFont.getSize();
final FontMetrics baseMetrics = g.getFontMetrics();
final Rectangle area = computePaintArea();
final int textBaseline = area.y + getTextBaseLine(baseMetrics, area.height);
boolean wasSmaller = false;
assert (myFragments.size() == myAttributes.size());
int i = 0;
int iconIndex = 0;
while (true) {
// Go through all icons up to attribute i.
while (iconIndex < myIcons.size() && myIcons.get(iconIndex).index <= i) {
final Icon icon = myIcons.get(iconIndex).icon;
final int iconWidth = icon.getIconWidth() + myIconTextGap;
doPaintIcon(g, icon, (int)offset);
offset += iconWidth + myIconTextGap;
iconIndex++;
}
if (i >= myFragments.size()) {
break;
}
final SimpleTextAttributes attributes = myAttributes.get(i);
Font font = g.getFont();
final 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 float 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((int)offset, 0, (int)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 float 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, (int)offset, textBaseline, (int)fragmentWidth, getCharHeight(g), font);
}
// 2. Waved effect
if (attributes.isWaved()) {
if (attributes.getWaveColor() != null) {
g.setColor(attributes.getWaveColor());
}
EffectPainter.WAVE_UNDERSCORE.paint(g, (int)offset, textBaseline + 1, (int)fragmentWidth, Math.max(2, metrics.getDescent()), font);
}
// 3. Underline
if (attributes.isUnderline()) {
EffectPainter.LINE_UNDERSCORE.paint(g, (int)offset, textBaseline, (int)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, (int)offset, (int)(offset + fragmentWidth), dottedAt, bgColor, lineColor, isOpaque());
}
if (attributes.isSearchMatch()) {
searchMatches.add(new Object[]{offset, offset + fragmentWidth, (float)textBaseline, myFragments.get(i), g.getFont(), attributes});
}
offset = endOffset;
i++;
}
// 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 {
int textStart = 0;
// Skip all icons that occur before any text.
for (PositionedIcon positionedIcon : myIcons) {
if (positionedIcon.index != 0) {
break;
}
textStart += positionedIcon.icon.getIconWidth() + myIconTextGap;
}
myBorder.paintBorder(this, g, textStart, 0, getWidth() - textStart, getHeight());
}
}
// draw search matches after all
for (final Object[] info : searchMatches) {
final float x1 = (float)info[0];
final float x2 = (float)info[1];
UIUtil.drawSearchMatch(g, x1, x2, getHeight());
g.setFont((Font)info[4]);
final float baseline = (float)info[2];
final 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, (int)x1, (int)baseline, (int)(x2 - x1), getCharHeight(g), g.getFont());
}
}
return (int)offset;
}