Package com.scriptographer.adm

Source Code of com.scriptographer.adm.Component

/*
* Scriptographer
*
* This file is part of Scriptographer, a Scripting Plugin for Adobe Illustrator
* http://scriptographer.org/
*
* Copyright (c) 2002-2010, Juerg Lehni
* http://scratchdisk.com/
*
* All rights reserved. See LICENSE file for details.
*
* File created on 02.01.2005.
*/

package com.scriptographer.adm;

import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.Insets;
import java.awt.LayoutManager;
import java.util.Map;
import java.util.regex.Pattern;

import com.scratchdisk.list.List;
import com.scratchdisk.script.Callable;
import com.scratchdisk.util.ConversionUtils;
import com.scratchdisk.util.IntegerEnumUtils;
import com.scriptographer.ScriptographerEngine;
import com.scriptographer.ScriptographerException;
import com.scriptographer.adm.layout.TableLayout;

/**
* Subclasses the NotificationHandler and adds functionality for
* defining track and draw callbacks (NotificationHandler can handle
* these but not set them).
* It also adds the onResize handler as both Item and Dialog need it,
* and these are the only subclasses of CallbackHandler
*
* @author lehni
*
* @jshide
*/
public abstract class Component extends NotificationHandler {

  protected Component parent;

  /*
   *  Fonts and Text Size
   */
  protected abstract int nativeGetFont();
 
  protected abstract void nativeSetFont(int font);

  public DialogFont getFont() {
    // Only call native function if this is actually a native item.
    // This avoids isValid() exceptions when using fake UI items such
    // as spacers.
    if (handle != 0)
        return IntegerEnumUtils.get(DialogFont.class, nativeGetFont());
    return DialogFont.DEFAULT;
  }

  public void setFont(DialogFont font) {
    if (font != null && handle != 0)
      nativeSetFont(font.value);
  }

  public Size getTextSize(String text, int maxWidth, boolean ignoreBreaks) {
    // Create an image to get a drawer to calculate text sizes
    Image image = new Image(1, 1, ImageType.RGB);
    Drawer drawer = image.getDrawer();
    drawer.setFont(getFont());
    // Split at new lines chars, and measure each line separately
    String[] lines = ignoreBreaks ? new String[] {
      text.replaceAll("\r\n|\n|\r", " ")
    } : text.split("\r\n|\n|\r");
    Size size = new Size(0, 0);
    for (int i = 0; i < lines.length; i++) {
      String line = lines[i];
      if (line.length() == 0)
        line = " "; // Make sure empty lines are measured too

      // Calculate the size of this part, using the drawer
      int width = drawer.getTextWidth(line);
      if (maxWidth > 0 && width > maxWidth)
        width = maxWidth;
      int height = drawer.getTextHeight(line, width + 1);

      // And add up size
      if (width > size.width)
        size.width = width;
      size.height += height;
    }
    drawer.dispose();
    return size;
  }

  public Size getTextSize(String text) {
    return getTextSize(text, -1, false);
  }

  public boolean isSmall() {
    DialogFont font = getFont();
    switch (font) {
    case PALETTE:
    case PALETTE_ITALIC:
    case PALETTE_BOLD:
    case PALETTE_BOLD_ITALIC:
      return true;
    default:
      return false;
    }
  }

  /*
   * Use an activation mechanism for the expensive callback routines (the ones
   * that get called often). These are only activated if the user actually
   * sets a callback functions.
   *
   * Abstract declarations for native functions that enable and disable the
   * native track and draw proc procedures:
   */
  private boolean trackCallback = false;

  /**
   * @jshide
   */
  public boolean getTrackCallback() {
    return trackCallback;
  }

  abstract protected void nativeSetTrackCallback(boolean enabled);

  public void setTrackCallback(boolean enabled) {
    nativeSetTrackCallback(enabled);
    trackCallback = enabled;
  }

  private boolean drawCallback = false;

  /**
   * @jshide
   */
  public boolean getDrawCallback() {
    return drawCallback;
  }

  abstract protected void nativeSetDrawCallback(boolean enabled);

  public void setDrawCallback(boolean enabled) {
    nativeSetDrawCallback(enabled);
    drawCallback = enabled;
  }
 
  /**
   * @param mask Tracker.MASK_*
   */
  abstract public void setTrackMask(int mask);
  abstract public int getTrackMask();

   protected Callable onTrack = null;

  public void setOnTrack(Callable func) {
    setTrackCallback(func != null);
    onTrack = func;
  }

  public Callable getOnTrack() {
    return onTrack;
  }

  protected boolean onTrack(Tracker tracker) {
    // Retrieve through getter so it can be overridden by subclasses,
    // e.g. HierarchyListBox
    Callable onTrack = this.getOnTrack();
    if (onTrack != null) {
      Object result = ScriptographerEngine.invoke(onTrack, this, tracker);
      if (result != null)
        return ConversionUtils.toBoolean(result);
    }
    return true;
  }

  protected Callable onDraw = null;

  public void setOnDraw(Callable func) {
    setDrawCallback(func != null);
    onDraw = func;
  }

  public Callable getOnDraw() {
    return onDraw;
  }

  protected boolean onDraw(Drawer drawer) {
    // Retrieve through getter so it can be overridden by subclasses,
    // e.g. HierarchyListBox
    Callable onDraw = this.getOnDraw();
    if (onDraw != null) {
      Object result = ScriptographerEngine.invoke(onDraw, this, drawer);
      if (result != null)
        return ConversionUtils.toBoolean(result);
    }
    return true;
  }
 
  protected Callable onResize = null;

  public void setOnResize(Callable func) {
    onResize = func;
  }

  public Callable getOnResize() {
    return onResize;
  }

  protected void onResize(int dx, int dy) {
    // Retrieve through getter so it can be overridden by subclasses,
    // e.g. HierarchyListBox
    Callable onResize = this.getOnResize();
    if (onResize != null)
      ScriptographerEngine.invoke(onResize, this, dx, dy);
  }

  /*
   * AWT / Layout Bridge
   */

  protected abstract java.awt.Component getAWTComponent(boolean create);

  protected AWTContainer getAWTContainer(boolean create) {
    java.awt.Component component = getAWTComponent(create);
    if (component == null && !create)
      return null;
    if (!(component instanceof AWTContainer))
      throw new ScriptographerException("Component does not support sub components.");
    return (AWTContainer) component;
  }

  public void setLayout(LayoutManager mgr) {
    getAWTContainer(true).setLayout(mgr);
  }

  public LayoutManager getLayout() {
    return getAWTContainer(true).getLayout();
  }

  public boolean usesLayout() {
    // See if this item or its parent uses a layout.
    AWTContainer container = getAWTContainer(false);
    return container != null && container.getLayout() != null
        || parent != null && parent.usesLayout();
  }

  public void doLayout() {
    AWTContainer container = getAWTContainer(false);
    if (container != null)
      container.doLayout();
  }

  /**
   * @jshide
   */
  public void setMargin(int top, int right, int bottom, int left) {
    this.getAWTContainer(true).setInsets(top, left, bottom, right);
  }

  public Border getMargin() {
    return new Border(this.getAWTContainer(true).getInsets());
  }

  public void setMargin(Border margin) {
    setMargin(margin.top, margin.right, margin.bottom, margin.left);
  }

  public void setMargin(int margin) {
    setMargin(margin, margin, margin, margin);
  }

  /**
   * @jshide
   */
  public void setMargin(int ver, int hor) {
    setMargin(ver, hor, ver, hor);
  }

  public int getMarginLeft() {
    return getMargin().left;
  }

  public void setMarginLeft(int left) {
    Border margin = getMargin();
    margin.left = left;
    setMargin(margin);
  }

  public int getMarginTop() {
    return getMargin().top;
  }

  public void setMarginTop(int top) {
    Border margin = getMargin();
    margin.top = top;
    setMargin(margin);
  }

  public int getMarginRight() {
    return getMargin().right;
  }

  public void setMarginRight(int right) {
    Border margin = getMargin();
    margin.right = right;
    setMargin(margin);
  }

  public int getMarginBottom() {
    return getMargin().bottom;
  }

  public void setMarginBottom(int bottom) {
    Border margin = getMargin();
    margin.bottom = bottom;
    setMargin(margin);
  }

  protected void addComponent(Component component) {
    // Do not really add component here, as only ItemGroup uses it.
    // Do not throw an UnsupportedOperationException though as it is also
    // used by Frame, which just applies its own layout to the added items
    // but does not actually nest them inside.
    component.parent = this;
  }

  protected void removeComponent(Component component) {
    // See above.
    component.parent = null;
  }

  private Content content = null;

  public Content getContent() {
    if (content == null)
      content = new Content(this);
    return content;
  }

  public void setContent(Component[] elements) {
    // The default for setting array elements is a flow layout
    if (this.getLayout() == null)
      this.setLayout(new FlowLayout());

    Content content = getContent();
    content.removeAll();
    content.addAll(elements);
  }

  public void setContent(List<? extends Component> elements) {
    // The default for setting array elements is a flow layout
    if (this.getLayout() == null)
      this.setLayout(new FlowLayout());

    Content content = getContent();
    content.removeAll();
    content.addAll(elements);
  }
 
  private static final Pattern borderLayoutPattern = Pattern.compile(
      "^(north|south|east|west|center|first|last|before|after)$",
      Pattern.CASE_INSENSITIVE);

  public void setContent(Map<String,? extends Component> elements) {
    // Find out what kind of layout we have by checking the keys
    // in the map:
    if (this.getLayout() == null) {
      boolean borderLayout = true;
      for (String key : elements.keySet())
        borderLayout = borderLayoutPattern.matcher(key).matches();
      if (borderLayout) {
        this.setLayout(new BorderLayout());
      } else {
        // TODO: Figure out amount of rows and columns by analyzing the keys.
        // for now we don't do that...
        this.setLayout(new TableLayout("preferred", "preferred"));
      }
    }

    Content content = getContent();
    content.removeAll();
    content.addAll(elements);
  }

  /**
   * @jshide
   */
  public void addToContent(Component component) {
    getContent().add(component);
  }

  /**
   * @jshide
   */
  public void addToContent(Component component, String constraints) {
    getContent().put(constraints, component);
  }

  /**
   * @jshide
   */
  public void addToContent(Component component, int index) {
    getContent().add(index, component);
  }

  /**
   * @jshide
   */
  public void removeFromContent(Component component) {
    getContent().remove(component);
  }
 
  /**
   * @jshide
   */
  public void removeFromContent(int index) {
    getContent().remove(index);
  }

  /**
   * @jshide
   */
  public void removeFromContent(String constraints) {
    getContent().remove(constraints);
  }

  /**
   * @jshide
   */
  public void removeContent() {
    getContent().removeAll();
  }

  /**
   * An abstract class that adds some commonly used things like
   * setInsets to java.awt.Container.
   *
   * @author lehni
   *
   */
  abstract class AWTContainer extends java.awt.Container implements
      ComponentWrapper {
    Insets insets;

    public void setInsets(int top, int left, int bottom, int right) {
      insets = new Insets(top, left, bottom, right);
    }

    public Insets getInsets() {
      return insets;
    }

    public void doLayout() {
      super.doLayout();
      // Walk through all the items do their layout as well:
      for (java.awt.Component component : getComponents())
        component.doLayout();
    }
  }
}
TOP

Related Classes of com.scriptographer.adm.Component

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.