Package DisplayProject.controls

Source Code of DisplayProject.controls.TextGraphic

/*
Copyright (c) 2003-2009 ITerative Consulting Pty Ltd. All Rights Reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted
provided that the following conditions are met:

o Redistributions of source code must retain the above copyright notice, this list of conditions and
the following disclaimer.
 
o Redistributions in binary form must reproduce the above copyright notice, this list of conditions
and the following disclaimer in the documentation and/or other materials provided with the distribution.
   
o This jcTOOL Helper Class software, whether in binary or source form may not be used within,
or to derive, any other product without the specific prior written permission of the copyright holder

 
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


*/
package DisplayProject.controls;

import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Insets;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;

import javax.swing.Icon;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
import javax.swing.border.Border;

import DisplayProject.Constants;
import DisplayProject.GridCell;
import DisplayProject.StatusTextListener;
import DisplayProject.actions.AppData;
import DisplayProject.actions.FrameWeight;
import DisplayProject.actions.HeightPolicy;
import DisplayProject.actions.WidgetSelected;
import DisplayProject.actions.WidthPolicy;
import DisplayProject.factory.GraphicFactory;
import Framework.CloneHelper;
import Framework.TextData;

/**
* The TextGraphic class defines images of text (decorative graphics not associated with data) that are associated with the graphic layer in the form.
*
*/
@SuppressWarnings("serial")
public class TextGraphic extends JLabel implements Graphic{
    public class qq_Resolver {
        public static final int cCOLUMN_ROW = 1;
        public static final int cTEXT = 2;
    }
    /**
     * A list of the strings in this textGraphic, split out over newlines
     */
    protected List<String> allLines;

    /**
     * The sizes of a textGraphic in forte were slightly different to those in java, differing by a few
     * pixels one way or the other. In some cases, such as column headers for JTables, we need to use
     * standard java sizing and not compensate for these few pixels. Set this value to true to use
     * the same sizing as a java JLabel
     */
    private boolean useStandardJavaSizing = false;
   
    // TF:21/11/07:Added the margins in here, rather than in the GraphicFactory
    private static final int topMargin = -1;
    private static final int leftMargin = 3;
    private static final int rightMargin = 2;
    private static final int bottomMargin = -1;

    /**
     * Creates a <code>TextGraphic</code> instance with
     * no image and with an empty string for the title.
     * The label is centered vertically
     * in its display area.
     * The label's contents, once set, will be displayed on the leading edge
     * of the label's display area.
     */
    public TextGraphic() {
        super();
        this.setup();
    }

    /**
     * Creates a <code>TextGraphic</code> instance with the specified
     * image and horizontal alignment.
     * The label is centered vertically in its display area.
     *
     * @param image  The image to be displayed by the label.
     * @param horizontalAlignment  One of the following constants
     *           defined in <code>SwingConstants</code>:
     *           <code>LEFT</code>,
     *           <code>CENTER</code>,
     *           <code>RIGHT</code>,
     *           <code>LEADING</code> or
     *           <code>TRAILING</code>.
     */
    public TextGraphic(Icon image, int horizontalAlignment) {
        super(image, horizontalAlignment);
        this.setup();
    }

    /**
     * Creates a <code>TextGraphic</code> instance with the specified image.
     * The label is centered vertically and horizontally
     * in its display area.
     *
     * @param image  The image to be displayed by the label.
     */
    public TextGraphic(Icon image) {
        super(image);
        this.setup();
    }

    /**
     * Creates a <code>TextGraphic</code> instance with the specified
     * text, image, and horizontal alignment.
     * The label is centered vertically in its display area.
     * The text is on the trailing edge of the image.
     *
     * @param text  The text to be displayed by the label.
     * @param icon  The image to be displayed by the label.
     * @param horizontalAlignment  One of the following constants
     *           defined in <code>SwingConstants</code>:
     *           <code>LEFT</code>,
     *           <code>CENTER</code>,
     *           <code>RIGHT</code>,
     *           <code>LEADING</code> or
     *           <code>TRAILING</code>.
     */
    public TextGraphic(String text, Icon icon, int horizontalAlignment) {
        super(text, icon, horizontalAlignment);
        this.setup();
    }

    /**
     * Creates a <code>TextGraphic</code> instance with the specified
     * text and horizontal alignment.
     * The label is centered vertically in its display area.
     *
     * @param text  The text to be displayed by the label.
     * @param horizontalAlignment  One of the following constants
     *           defined in <code>SwingConstants</code>:
     *           <code>LEFT</code>,
     *           <code>CENTER</code>,
     *           <code>RIGHT</code>,
     *           <code>LEADING</code> or
     *           <code>TRAILING</code>.
     */
    public TextGraphic(String text, int horizontalAlignment) {
        super(text, horizontalAlignment);
        this.setup();
    }

    /**
     * Creates a <code>TextGraphic</code> instance with the specified text.
     * The label is aligned against the leading edge of its display area,
     * and centered vertically.
     *
     * @param text  The text to be displayed by the label.
     */
    public TextGraphic(String text) {
        super(text);
        this.setup();
    }
   
    public TextGraphic(TextData text, int pResolver) {
      this();
      if (pResolver == qq_Resolver.cTEXT) {
        this.setText(text.toString());
      }
    }

    private void setup() {
        setBackground(null);//PM:21/07/2008:Defaulted the background colour to inherit
        setOpaque(false)// TF:25/07/2008:Set the opacity the same as Forte
        // TF:13/11/2009:DET-130:Added status line listener
        this.addMouseListener(StatusTextListener.sharedInstance());
      // TF:15/12/2009:DET-141:Set this up to allow inheriting of popup menu
      this.setInheritsPopupMenu(true);
    }
   
    /**
     * The sizes of a textGraphic in forte were slightly different to those in java, differing by a few
     * pixels one way or the other. In some cases, such as column headers for JTables, we need to use
     * standard java sizing and not compensate for these few pixels. Set this value to true to use
     * the same sizing as a java JLabel
     */
    public void setStandardJavaSizing(boolean pStdSizing) {
      this.useStandardJavaSizing = pStdSizing;
      // Reset the sizing
      this.setMinimumSize(null);
      this.setPreferredSize(null);
    }
   
    public Object getAppData() {
        return AppData.get(this);
    }

    public boolean isSelected() {
        return WidgetSelected.is(this);
    }

    public boolean isTransparent() {
        return !this.isOpaque();
    }

    public void setAppData(Object appData) {
        AppData.set(this,  appData);
    }

    public void setSelected(boolean selected) {
        WidgetSelected.set(this, selected);
    }

    public void setTransparent(boolean transparent) {
        this.setOpaque(!transparent);
    }

    // TF:21/11/07: Overrode this to get the same minimum height and behaviour that Forte had
    @Override
    public Dimension getMinimumSize() {
        if (!isMinimumSizeSet()) {
            recalculateSizes();
        }
        return super.getMinimumSize();
    }
   
    /**
     * Set the minimum size of the TextGraphic. The minimum size may or may not actually get set
     * to this value, depending on the size policy. For example, if the size policy is natural,
     * the set minimum size will be ignored, whereas if its explicit, the minimum size will be respected.
     */
    @Override
    public void setMinimumSize(Dimension minimumSize) {
        if (!useStandardJavaSizing) {
      Dimension d = determineSizes();
      if (d == null) {
        // this shouldn't happen.
          super.setMinimumSize(minimumSize);
      }
      else {
        if (WidthPolicy.get(this) == Constants.SP_EXPLICIT) {
          d.width = minimumSize.width;
        }
        if (HeightPolicy.get(this) == Constants.SP_EXPLICIT) {
          d.height = minimumSize.height;
        }
        super.setMinimumSize(d);
      }
        }
        else {
          super.setMinimumSize(minimumSize);
        }
    }
   
    @Override
    public Insets getInsets(Insets insets) {
        // The insets we want to use are our parent's insets plus our margins
        Insets result = super.getInsets(insets);
        if (!useStandardJavaSizing) {
          result.left += leftMargin;
          result.right += rightMargin;
          result.top += topMargin;
          result.bottom += bottomMargin;
        }
        return result;
    }

    @Override
    public Insets getInsets() {
        // The insets we want to use are our parent's insets plus our margins
        Insets result = super.getInsets();
        if (!useStandardJavaSizing) {
          result.left += leftMargin;
          result.right += rightMargin;
          result.top += topMargin;
          result.bottom += bottomMargin;
        }
        return result;
    }
   
    /**
     * Cache the font metrics associated with this widget for efficiency
     */
    private FontMetrics fontMetrics = null;

    /**
     * Set the font of the text graphic
     */
    @Override
    public void setFont(Font font) {
        if (font != getFont()) {
            super.setFont(font);
            fontMetrics = getFontMetrics(font);
            recalculateSizes();
        }
    }

    /**
     * Determine the size of this widget based on the size policy, the font and the text/
     * @return the size of the widget
     */
    private Dimension determineSizes() {
        // Get the current font metrics so we can compute the size we need.
        if (fontMetrics == null) {
            Font f = getFont();
            if (f == null) {
                return null;
            }
            fontMetrics = getFontMetrics(f);
        }
        FontMetrics fm = fontMetrics;
        // Now we have the lines in the array list, find their widths
        int width = 0;
        if (allLines != null) {
            for (String thisLine : allLines) {
                int thisLineWidth = SwingUtilities.computeStringWidth(fm, thisLine);
                if (thisLineWidth > width) {
                    width = thisLineWidth;
                }
            }
        }

        Dimension d = new Dimension();
        d.width = width + 1;
        d.height = (fm.getHeight() + fm.getDescent()) * Math.max(1, getLineCount());

        // Now apply the margins onto the size if needed
        Insets i = getInsets();
        GridCell cell = GridCell.get(this);
        switch (cell.getWidthPolicy()) {
            case Constants.SP_TO_PARENT:
                d.width += i.left + i.right;
                d.width = Math.max(d.width, getWidth());
                break;
            case Constants.SP_EXPLICIT:
                d.width = getWidth();
                break;
            case Constants.SP_NATURAL:
            case Constants.SP_TO_PARTNER:
            default:
                d.width += i.left + i.right;
                break;
        }
        switch (cell.getHeightPolicy()) {
            case Constants.SP_TO_PARENT:
                d.height += i.top + i.bottom;
                d.height = Math.max(d.height, getHeight());
                break;
            case Constants.SP_EXPLICIT:
                d.height = getHeight();
                break;
            case Constants.SP_NATURAL:
            case Constants.SP_TO_PARTNER:
            default:
                d.height += i.top + i.bottom;
                break;
        }

        // Cater for a frame.  CraigM 03/01/2008.
        if (FrameWeight.get(this) > 0) {
          // TF:06/08/2008:If we're explicitly set then we don't adjust the size.
          int size = FrameWeight.get(this);
          if (cell.getWidthPolicy() != Constants.SP_EXPLICIT) {
            d.height += size;
          }
          if (cell.getHeightPolicy() != Constants.SP_EXPLICIT) {
            d.width += size;
          }
        }
        return d;
    }
    /**
     * Recalculate the size of the text based on the current lines and the current font.
     * This method assumes that the current text has already been set on the superclass
     * prior to invoking it.<p>
     * <p>
     * This method will set the minimum size, preferred size and size of the component.
     */
    private void recalculateSizes() {
        if (!useStandardJavaSizing) {
        Dimension d = this.determineSizes();
        if (d == null) {
          return;
        }
 
          if (!isMinimumSizeSet() || super.getMinimumSize() != d) {
              setMinimumSize(d);
          }
          if (!isPreferredSizeSet() || super.getPreferredSize() != d) {
              setPreferredSize(d);
          }
          if (getWidth() != d.width || getHeight() != d.height) {
              setSize(d);
          }
        }
    }

    @Override
    public void setBorder(Border border) {
        super.setBorder(border);

        // Setting a border (usually via setting a frame) affects our size.  CraigM 03/01/2008.
        this.recalculateSizes();
    }

    @Override
    public void setText(String text) {
      if (!useStandardJavaSizing) {
          // CraigM:22/07/2008 - Remove the trailing "\n" character if it exists.
        if (text != null && text.length() > 1 && text.charAt(text.length()-1) == '\n') {
          text = text.substring(0,text.length()-1);
        }
       
          if (allLines == null) {
              allLines = new ArrayList<String>();
          }
          else {
              allLines.clear();
          }
          String labelTxt = formatLabelAsHTML(text, allLines);
          super.setText(labelTxt);
 
          // Now re-adjust the sizes
          recalculateSizes();
      }
      else {
        super.setText(text);
      }
    }

    public TextGraphic cloneComponent(){
        TextGraphic clone = GraphicFactory.newTextGraphic(this.getFont());
        CloneHelper.cloneComponent(this, clone, new String[]{"parent"});
        return clone;
    }

    /**
     * Get a count of the number of lines in this textGraphic
     */
    public int getLineCount() {
        return allLines == null ? 0 : allLines.size();
    }

    public static String formatLabelAsHTML(String text) {
        return formatLabelAsHTML(text, null, JLabel.LEFT);
    }

    public static String formatLabelAsHTML(String text, int pAlignment) {
        return formatLabelAsHTML(text, null, pAlignment);
    }

    public static String formatLabelAsHTML(String text, List<String> lines) {
        return formatLabelAsHTML(text, lines, JLabel.LEFT);
    }

    public static String formatLabelAsHTML(String text, List<String> lines, int pAlignment) {
        String result = null;
        String labelTxt = text;
        if (lines == null) {
            lines = new ArrayList<String>();
        }
        else {
            lines.clear();
        }
        boolean isHTMLFormatted = false;
        if (labelTxt != null) {
            // If the new text starts with <html>, it's already formatted for html.
            // Note that as an optimisation, we look for this case sensitive.
            if (text.startsWith("<html>")) {
             
              // TF:27/08/2009:If we're html formatted, we just need to populate the lines array and return
              // our current value. The lines array must contain each line of original text, so we
              // <ul>
              //  <li>Search for </?html> and replace with nothing</li>
              //  <li>Search for <div align="\w+"> and replace with nothing</li>
              //  <li>Search for </div> and replace with nothing</li>
              //  <li>Search for &nbsp; and replace with " "</li>
              //  <li>Search for <br> or <p>, case insensitive, and replace with <p></li>
              // </ul>
              // Then we run through looking for <br> or <p> tags and separating these out into lines
              // This fixes bugs in the previous version where lines would include html tags like
              // <html><div align="left"/>fred
              // which would result in things like headers being too long on array fields.
              String newText = text.replaceAll("</?html>", "");
              newText = newText.replaceAll("<div(\\s*align=\"\\w+\")?\\s*>", "");
              newText = newText.replaceAll("</div>", "");
              newText = newText.replaceAll("&nbsp;", " ");
              newText = newText.replaceAll("(?i)<br>", "<p>");
              newText = newText.replaceAll("(?i)<p>", "<p>");
                // It's possible we've already processed this text, or it was sent as html, so we need
                // to look for html line terminators, eg <br>, <p>. However, we must search case insensitive
                isHTMLFormatted = true;
                int index = 0;
                do {
                    int paraIndex = newText.indexOf("<p>", index);
                    if (paraIndex >= 0) {
                        // There's at least one more token. Copy the normal case
                        // text.
                        String thisLine = newText.substring(index, paraIndex);
                        lines.add(thisLine);
                        // Reset the search index, ensuring we skip over the
                        // remainder of this tag
                        index = newText.indexOf(">", paraIndex + 1) + 1;
                    }
                    else {
                        // no more tokens, just copy what we currently have
                        String thisLine = newText.substring(index);
                        lines.add(thisLine);
                        index = -1;
                    }
                } while (index >= 0);
                return text;
            }
            else {
              // CraigM:21/07/2008 - Stop StringTokenizer skipping over multiple tokens
//                StringTokenizer s = new StringTokenizer(labelTxt, "\n");
//                while (s.hasMoreTokens()) {
//                    lines.add(s.nextToken());
//                }
                StringTokenizer s = new StringTokenizer(labelTxt, "\n", true);
                String token = "";
                while (s.hasMoreTokens()) {
                  String x = s.nextToken();
                 
                  if (x.equals("\n")) {
                        lines.add(token);
                        token = "";
                  }
                  else {
                    token = x;
                  }
                }
                lines.add(token);
            }
        }

        // Insert html tags in labels where appropriate and resize labels from metrics.
        if (text != null && !isHTMLFormatted) {
            if (lines.size() == 0) {
                result = "";
            }
            else if (lines.size() == 1) {
                result = lines.get(0);
            }
            else {
                StringBuilder htmlText = new StringBuilder(100);
                htmlText.append("<html>");
                switch (pAlignment) {
                    case JLabel.LEFT:
                        htmlText.append("<div align=\"left\">");
                        break;
                    case JLabel.RIGHT:
                        htmlText.append("<div align=\"right\">");
                        break;
                    case JLabel.CENTER:
                        htmlText.append("<div align=\"center\">");
                        break;
                }
                boolean isFirst = true;
                for (String thisLine : lines) {
                    if (!isFirst) {
                        htmlText.append("<br>");
                    }
                    else {
                        isFirst = false;
                    }
                    htmlText.append(thisLine);
                }
               
                // Replace tabs with 8 spaces as Java/HTML doesn't support tabs.  CraigM:01/08/2008.
                int tabIndex = htmlText.indexOf("\t");

                while (tabIndex != -1) {
                  htmlText.replace(tabIndex, tabIndex+1, "        ");
                  tabIndex = htmlText.indexOf("\t", tabIndex);
                }
               
                // Replace double spaces with &nbsp;&nbsp;  CraigM: 28/02/2008
                int doubleSpaceIndex = htmlText.indexOf("  ");
               
                while (doubleSpaceIndex != -1) {
                  htmlText.replace(doubleSpaceIndex, doubleSpaceIndex+2, "&nbsp;&nbsp;");
                  doubleSpaceIndex = htmlText.indexOf("  ", doubleSpaceIndex);
                }
               
               
                switch (pAlignment) {
                case JLabel.LEFT:
                case JLabel.RIGHT:
                case JLabel.CENTER:
                    htmlText.append("</div>");
                    break;
            }
                htmlText.append("</html>");
                result = htmlText.toString();
            }
        }
        else {
            result = text;
        }

        return result;
    }
}
TOP

Related Classes of DisplayProject.controls.TextGraphic

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.