content: /*****************************************************************
   *   Licensed to the Apache Software Foundation (ASF) under one
   *  or more contributor license agreements.  See the NOTICE file
   *  distributed with this work for additional information
   *  regarding copyright ownership.  The ASF licenses this file
   *  to you under the Apache License, Version 2.0 (the
   *  "License"); you may not use this file except in compliance
   *  with the License.  You may obtain a copy of the License at
   *
   *    https://www.apache.org/licenses/LICENSE-2.0
   *
   *  Unless required by applicable law or agreed to in writing,
   *  software distributed under the License is distributed on an
   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
   *  KIND, either express or implied.  See the License for the
   *  specific language governing permissions and limitations
   *  under the License.
   ****************************************************************/
  package org.apache.cayenne.swing.components.textpane;
  
  import java.awt.Color;
  import java.awt.FontMetrics;
  import java.awt.Graphics;
  import java.awt.Rectangle;
  import java.awt.Shape;
  
  import javax.swing.text.BadLocationException;
  import javax.swing.text.DefaultHighlighter;
  import javax.swing.text.Highlighter;
  import javax.swing.text.JTextComponent;
  import javax.swing.text.LayeredHighlighter;
  import javax.swing.text.Position;
  import javax.swing.text.View;
  
  public class UnderlineHighlighterForText extends DefaultHighlighter {
  
      public UnderlineHighlighterForText(Color c) {
          painter = (c == null ? sharedPainter : new UnderlineHighlightPainter(c));
      }
  
      // Convenience method to add a highlight with
      // the default painter.
      public Object addHighlight(int p0, int p1) throws BadLocationException {
          return addHighlight(p0, p1, painter);
      }
  
      public void setDrawsLayeredHighlights(boolean newValue) {
          // Illegal if false - we only support layered highlights
          if (newValue == false) {
              throw new IllegalArgumentException(
                      "UnderlineHighlighterForArea only draws layered highlights");
          }
          super.setDrawsLayeredHighlights(true);
      }
  
      // Painter for underlined highlights
      public static class UnderlineHighlightPainter extends LayeredHighlighter.LayerPainter {
  
          public UnderlineHighlightPainter(Color c) {
              color = c;
          }
  
          public void paint(Graphics g, int offs0, int offs1, Shape bounds, JTextComponent c) {
              // Do nothing: this method will never be called
          }
  
          public Shape paintLayer(
                  Graphics g,
                  int offs0,
                  int offs1,
                  Shape bounds,
                  JTextComponent c,
                  View view) {
              g.setColor(color == null ? c.getSelectionColor() : color);
  
              Rectangle alloc = null;
              if (offs0 == view.getStartOffset() && offs1 == view.getEndOffset()) {
                  if (bounds instanceof Rectangle) {
                      alloc = (Rectangle) bounds;
                  }
                  else {
                      alloc = bounds.getBounds();
                  }
              }
              else {
                  try {
                      Shape shape = view.modelToView(
                              offs0,
                              Position.Bias.Forward,
                              offs1,
                              Position.Bias.Backward,
                              bounds);
                      alloc = (shape instanceof Rectangle) ? (Rectangle) shape : shape
                              .getBounds();
                  }
                  catch (BadLocationException e) {
                      return null;
                  }
              }
  
              FontMetrics fm = c.getFontMetrics(c.getFont());
              int baseline = alloc.y + alloc.height - fm.getDescent() + 1;
  
              int i = alloc.x;
              int end = alloc.x + alloc.width - 1;
              while (i < end) {
                  g.drawLine(i, baseline, i + 2, baseline);
                  g.drawLine(i, baseline + 1, i + 2, baseline + 1);
                  i += 4;
              }
  
              return alloc;
          }
  
          protected Color color; // The color for the underline
      }
  
      // Shared painter used for default highlighting
      protected static final Highlighter.HighlightPainter sharedPainter = new UnderlineHighlightPainter(
              null);
  
      // Painter used for this highlighter
      protected Highlighter.HighlightPainter painter;
  
  }
  