Package org.eclipse.jst.pagedesigner.css2.layout

Source Code of org.eclipse.jst.pagedesigner.css2.layout.TextLayoutSupport

/*******************************************************************************
* Copyright (c) 2006 Sybase, Inc. and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
*     Sybase, Inc. - initial API and implementation
*******************************************************************************/
package org.eclipse.jst.pagedesigner.css2.layout;

import java.util.List;

import org.eclipse.draw2d.Graphics;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.jst.jsf.common.ui.internal.logging.Logger;
import org.eclipse.jst.pagedesigner.PDPlugin;
import org.eclipse.jst.pagedesigner.css2.property.TextDecorationMeta;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;

/**
* @author mengbo
*/
public class TextLayoutSupport {
  private static final Logger _log = PDPlugin
      .getLogger(TextLayoutSupport.class);

  private static final String[] DELIMITERS = { "\r\n", //$NON-NLS-1$
      "\n", //$NON-NLS-1$
      "\r" //$NON-NLS-1$
  };

  static private int delimeterLength;

  /**
   * Reuses an existing <code>TextFragmentBox</code>, or creates a new one.
   *
   * @param i
   *            the index
   * @param fragments
   *            the original list of fragments
   * @return a TextFragmentBox
   */
  // copied from TextLayout
  protected static TextFragmentBox getFragment(int i, List fragments) {
    if (fragments.size() > i) {
      return (TextFragmentBox) fragments.get(i);
    }
    TextFragmentBox box = new TextFragmentBox();
    fragments.add(box);
    return box;
  }

  /**
   * Returns the average character width of given TextFragmentbox
   *
   * @param fragment
   *            the TextFragmentBox
   * @return the average character width
   */
  public static float getAverageCharWidth(TextFragmentBox fragment) {
    if (fragment._width != 0 && fragment._length != 0) {
      return fragment._width / (float) fragment._length;
    }
    return 0.0f;
  }

  // ----------------------------------------------------------------------------------------
  /**
   * this method will create a set of TextFragment. Each fragment will offset
   * to the original text (whole text for the text figure).
   * @param context
   * @param text
   * @param fragments
   * @param font
   * @param wrappingStyle
   * @param trimLeading
   */
  public static void layoutNormal(FlowContext context, String text,
      List fragments, Font font, int wrappingStyle, boolean trimLeading) {
    int i = 0; // The index of the current fragment;
    int offset = 0;
    if (trimLeading) {
      offset = 1;
      text = text.substring(1);
    }

    int length = 0; // The length of the current fragment
    float prevAvgCharWidth;
    LineBox currentLine;
    TextFragmentBox fragment;

    while (text.length() > 0) {
      fragment = null;
      prevAvgCharWidth = 0f;
      fragment = getFragment(i, fragments);
      prevAvgCharWidth = getAverageCharWidth(fragment);

      // Check for newline, if it exists, call context.endLine and skip
      // over the newline
      // Exccept for first time through, don't do this.
      if (i != 0) {
        boolean changed = false;
        if (text.charAt(0) == '\r') {
          text = text.substring(1);
          changed = true;
          offset += 1;
        }
        if (text.length() != 0 && text.charAt(0) == '\n') {
          text = text.substring(1);
          changed = true;
          offset += 1;
        }
        if (changed) {
          context.endLine();
        }
      }

      fragment._offset = offset;

      // This loop is done at most twice.
      // The second time through, a context.endLine()
      // was requested, and the loop will break.
      while (true) {
        currentLine = context.getCurrentLine();
        length = FlowUtilities.setupFragmentBasedOnTextSpace(fragment,
            text, font, currentLine.getAvailableWidth(),
            prevAvgCharWidth, wrappingStyle);

        if (fragment._width <= currentLine.getAvailableWidth()
            || !context.isCurrentLineOccupied()) {
          break;
        }
        context.endLine();
      }
      // fragment.x = context.getCurrentX();
      context.addToCurrentLine(fragment);
      text = text.substring(length);
      offset += length;
      if (text.length() > 0) {
        context.endLine();
      }
      i++;
    }

    // Remove the remaining unused fragments.
    while (i < fragments.size()) {
      fragments.remove(fragments.size() - 1);
    }
  }

  /**
   * @param context
   * @param text
   * @param fragments
   * @param font
   */
  public static void layoutNoWrap(FlowContext context, String text,
      List fragments, Font font) {
    TextFragmentBox fragment;
    int i = 0;
    int offset = 0;

    while (offset < text.length()) {
      int result = nextLineBreak(text, offset);
      fragment = getFragment(i++, fragments);
      fragment._length = result - offset;
      fragment._offset = offset;
      FlowUtilities.setupFragment(fragment, font, text.substring(offset));
      context.getCurrentLine().add(fragment);
      offset = result + delimeterLength;
      if (delimeterLength != 0) {
        // in nextLineBreak we fo
        context.endLine();
      }

    }
    // Remove the remaining unused fragments.
    while (i < fragments.size()) {
      fragments.remove(i++);
    }
  }

  private static int nextLineBreak(String text, int offset) {
    int result = text.length();
    delimeterLength = 0;
    int current;
    for (int i = 0; i < DELIMITERS.length; i++) {
      current = text.indexOf(DELIMITERS[i], offset);
      if (current != -1 && current < result) {
        result = current;
        delimeterLength = DELIMITERS[i].length();
      }
    }
    return result;
  }

  /**
   * @param g
   * @param fragments
   * @param font
   * @param textDecoration
   */
  public static void paintTextFigure(Graphics g, List fragments, Font font,
      int textDecoration) {
    paintTextFigure(g, fragments, font, null, textDecoration);
  }

  /**
   * @param g
   * @param rect
   * @param textDecoration
   */
  public static void paintTextDecoration(Graphics g, Rectangle rect,
      int textDecoration) {
    if ((textDecoration & TextDecorationMeta.UNDERLINE) != 0) {
      g.drawLine(rect.x, rect.y + rect.height - 1, rect.x + rect.width
          - 1, rect.y + rect.height - 1);
    }
    if ((textDecoration & TextDecorationMeta.OVERLINE) != 0) {
      g.drawLine(rect.x, rect.y + 1, rect.x + rect.width - 1, rect.y + 1);
    }
    if ((textDecoration & TextDecorationMeta.LINETHROUGH) != 0) {
      g.drawLine(rect.x, rect.y + rect.height / 2, rect.x + rect.width
          - 1, rect.y + rect.height / 2);
    }
  }

  /**
   * @param g
   * @param fragments
   * @param font
   * @param color
   * @param textDecoration
   */
  public static void paintTextFigure(Graphics g, List fragments, Font font,
      Color color, int textDecoration) {
    // FIXME: It happens there is problem in this method's parameters. what
    // exception should be catched?
    try {
      TextFragmentBox frag;
      // XXX: adjust font. Here is not using setFont(), because that will
      // result in revalidate
      g.setFont(font);

      for (int i = 0; i < fragments.size(); i++) {
        frag = (TextFragmentBox) fragments.get(i);
        // if (!g.getClip(Rectangle.SINGLETON).intersects(frag))
        // continue;
        String draw;
        draw = frag.getTextData();

        if (color != null) {
          g.setForegroundColor(color);
        }
        g.drawText(draw, frag._x, frag._y);
        if ((textDecoration & TextDecorationMeta.UNDERLINE) != 0) {
          g.drawLine(frag._x, frag._y + frag.getHeight() - 1, frag._x
              + frag.getWidth(), frag._y + frag.getHeight() - 1);
        }
        if ((textDecoration & TextDecorationMeta.OVERLINE) != 0) {
          g.drawLine(frag._x, frag._y, frag._x + frag.getWidth(),
              frag._y);
        }
        if ((textDecoration & TextDecorationMeta.LINETHROUGH) != 0) {
          g.drawLine(frag._x, frag._y + frag.getHeight() / 2, frag._x
              + frag.getWidth(), frag._y + frag.getHeight() / 2);
        }

        if (Debug.DEBUG_BASELINE) {
          g.drawLine(frag._x, frag._y + frag.getAscent(), frag._x
              + frag.getWidth(), frag._y + frag.getAscent());
        }
      }
    } catch (Exception e) {
      // "Error in text painting:"
      _log.info("TextLayoutSupport.Info.1", e); //$NON-NLS-1$
    }
  }

  /**
   *
   * @param g
   * @param fragments
   * @param text
   *            all the text in the Text figure.
   * @param font
   * @param color
   * @param textDecoration
   * @param start
   * @param end
   * @param selectionForeColor
   * @param selectionBackColor
   */
  public static void paintTextFigureWithSelection(Graphics g, List fragments,
      String text, Font font, Color color, int textDecoration, int start,
      int end, Color selectionForeColor, Color selectionBackColor) {
    // FIXME: It happens there is problem in this method's parameters. what
    // exception should be catched?
    try {
      TextFragmentBox frag;

      Color originalForeground = g.getForegroundColor();
      Color originalBackgroud = g.getBackgroundColor();

      // XXX: adjust font. Here is not using setFont(), because that will
      // result in revalidate
      g.setFont(font);

      for (int i = 0, n = fragments.size(); i < n; i++) {
        frag = (TextFragmentBox) fragments.get(i);

        // to make things simpler, we always draw the line using default
        // color
        if (color != null) {
          g.setForegroundColor(color);
        }

        // if (!g.getClip(Rectangle.SINGLETON).intersects(frag))
        // continue;
        String draw;
        draw = frag.getTextData();
        if (frag._offset >= end || frag._offset + frag._length <= start) {
          // we are not in selection. no need to change color
          g.drawText(draw, frag._x, frag._y);
          paintTextDecoration(g, frag.getRectangle(), textDecoration);
        } else if (frag._offset >= start
            && frag._offset + frag._length <= end) {
          // we are fully in selection
          g.setForegroundColor(selectionForeColor);
          g.setBackgroundColor(selectionBackColor);
          g
              .fillRectangle(frag._x, frag._y, FlowUtilities
                  .getTextExtents(draw, font).width, frag
                  .getHeight());
          g.drawText(draw, frag._x, frag._y);
          paintTextDecoration(g, frag.getRectangle(), textDecoration);
        } else {
          // partial of the fragment's text is in selection.

          // draw the original string first
          g.drawText(draw, frag._x, frag._y);
          // then override with the selected parts.
          g.setForegroundColor(selectionForeColor);
          g.setBackgroundColor(selectionBackColor);
          int partialStart = frag._offset > start ? frag._offset
              : start;
          int partialEnd = (frag._offset + frag._length > end) ? end
              : (frag._offset + frag._length);
          int x = 0;
          String skip = text.substring(frag._offset, partialStart);
          x = FlowUtilities.getTextExtents(skip, font).width;
          String todraw = text.substring(partialStart, partialEnd);
          if (todraw.length() > 0) {
            Dimension dimension = FlowUtilities.getTextExtents(skip
                + todraw, font);
            g.fillRectangle(frag._x + x, frag._y, dimension.width
                - x, dimension.height);
            g.drawText(skip + todraw, frag._x, frag._y);
            if (color != null) {
              g.setForegroundColor(color);
            } else {
              g.setForegroundColor(originalForeground);
            }
            g.drawText(skip, frag._x, frag._y);
            paintTextDecoration(g, frag.getRectangle(),
                textDecoration);
            g.setForegroundColor(selectionForeColor);
            paintTextDecoration(g,
                new Rectangle(frag._x + x, frag._y,
                    dimension.width - x, dimension.height),
                textDecoration);
          }
        }

        // we do this in each loop, to make sure we are using correct
        // color
        g.setForegroundColor(originalForeground);
        g.setBackgroundColor(originalBackgroud);

      }
    } catch (Exception e) {
      // "Error in text painting:"
      _log.info("TextLayoutSupport.Info.1", e); //$NON-NLS-1$
    }
  }

  /**
   * @param textAlign
   * @param rect
   * @param textWidth
   * @return the x value
   */
  public static int getBeginX(Object textAlign, Rectangle rect, int textWidth) {
    int x = rect.x;
    if (textAlign != null) {
      String align = textAlign.toString();
      if ("left".equalsIgnoreCase(align)) //$NON-NLS-1$
      {
        x = rect.x + 1;
      } else if ("right".equalsIgnoreCase(align)) //$NON-NLS-1$
      {
        x = rect.x + rect.width - textWidth - 1;
        if (x < 1) {
          x = 1;
        }
      } else if ("center".equalsIgnoreCase(align)) //$NON-NLS-1$
      {
        int offset = (rect.width - textWidth) / 2;
        if (offset <= 0) {
          offset = 0;
        }
        x = x + offset + 1;
      }
    }
    return x;
  }
 
  private TextLayoutSupport()
  {
      // no instantiation
  }
}
TOP

Related Classes of org.eclipse.jst.pagedesigner.css2.layout.TextLayoutSupport

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.