JavaBeans Example - TextEditor Bean



TextEditor - Source Code

package sunw.demo.TextEditor;


          /*
          * File         : TextEditor.java
          * Author       : Mahesh Rengaswamy
          * Revision     : $Revision$
          * Updated      : $Date$
          * Copyright: Northeast Parallel Architectures Center
          *            at Syracuse University 1997
          */

import java.io.*;
import java.awt.*;
import java.applet.*;
import java.util.zip.*;
import java.util.Vector;
import java.beans.*;

public class TextEditor extends TextArea {
     
  ///////////////////////////////////////////////////////
  // Private Data Fields (all Java Bean fields should be
  // private, stylistically speaking)
  // ////////////////////////////////////////////////////

  private PropertyChangeSupport changes = new PropertyChangeSupport(this);
  private static Dimension zero = new Dimension(0,0);
  private Font textFont;
  private Color textColor, canvasColor;
  private String fontName="TimesRoman";
  private int fontSize=12;
  private int fontStyle = Font.PLAIN;
  private boolean debug = false;

  ////////////////////////////////////////////////////
  // End of Bean-relevant Data Fields
  ////////////////////////////////////////////////////


  Graphics g;

  ////////////////////////////////////////////////////
  ////        START OF JAVA BEAN RELATED METHODS     
  ////           FOR PROPERTIES & RESIZE OF
  ////              THE TEXT-EDITOR                  
  ////////////////////////////////////////////////////



  /* Inorder to demonstrate another concept in Beans , the boolean property
     why dont we have a boolean flag for the debugging information.
     Essentially any System.out.println's should take place only if this flag
     is true */

  public void setDebug(boolean b) {
    boolean oldDebug = debug;
    debug= b;
    changes.firePropertyChange("Debug", new Boolean(oldDebug),
                               new Boolean(debug));
  }

  public boolean getDebug() {
    return debug;
  }
  

  /*  End of the boolean property */
  
  /////////////////////////////////////////////////////////////////////
  /////////////////////////////////////////////////////////////////////


  /*We want FontName to also appear in the Bean Property sheet, The getter
    and setter methods along with the firing of property changes 
    ensures us that this property behaves as desired i.e. to change the
    FontName */
  
  public void setFontName(String fName) {
    String oldFontName= fontName;
    fontName = fName;
    textFont = new Font(fontName, fontStyle, fontSize);
    this.setFont(textFont);
    changes.firePropertyChange("FontName",   oldFontName, fontName);
  }

  public String getFontName() {
    return fontName;
  }

  /*End of getter/setter methods for the FontName property.... */

  
  ///////////////////////////////////////////////////////////////
  ///////////////////////////////////////////////////////////////
  
  /*We want FontStyle to also appear in the Bean Property sheet, The getter
    and setter methods along with the firing of property changes 
    ensures us that this property behaves as desired i.e. to change the
    FontStyle */
  
  /*Theres something you gotta remeber here,
    a) For plain styles ===>0
    b) for bold         ===>1
    c) for italics      ===>2
    d)for bold+italics  ===>3
  */
  
  public void setFontStyle(int fStyle) {
    int oldFontStyle = fontStyle;
    fontStyle = fStyle;
    textFont = new Font(fontName, fontStyle, fontSize);
    this.setFont(textFont);
    changes.firePropertyChange("FontStyle",  new Integer(oldFontStyle), 
                               new Integer(fontStyle));     
  }
  
  public int getFontStyle() {
    return fontStyle;    
  }
  
  /*End of getter/setter methods for the FontStyle Property */
  
  ///////////////////////////////////////////////////////////////
  ///////////////////////////////////////////////////////////////
  
  /*We want FontSizee to also appear in the Bean Property sheet, The getter
    and setter methods along with the firing of property changes 
    ensures us that this property behaves as desired i.e. to change the
    FontSize */

  public void setFontSize(int fSize) {
      int oldFontSize = fontSize;
      fontSize = fSize;
      if(debug)
        System.out.println("FontSizes" + fontSize);
      textFont = new Font(fontName, fontStyle, fontSize);
      this.setFont(textFont);
      changes.firePropertyChange("FontSize", new Integer(oldFontSize), 
                                 new Integer(fontSize));   
  }

  public int getFontSize() {
    return fontSize;
  }
  
  /*End of getter/setter methods for the FontSize property */

  ///////////////////////////////////////////////////////////////
  ///////////////////////////////////////////////////////////////

  /**
    * Adds a PropertyListener object to a list of PropertyChangeListeners
    */     
  public void addPropertyChangeListener(PropertyChangeListener listen) {
    changes.addPropertyChangeListener(listen);
  }
  
  /** 
    * Removes a PropertyChangeListener from our listener list.
    */     
  public void removePropertyChangeListener(PropertyChangeListener listen) {
    changes.removePropertyChangeListener(listen);
  }

  public Dimension getPreferredSize() {
    Dimension current = getSize();
    /*
     * This method exists as a hack to ensure that when the TextArea is
     * resized by the user that it in fact does resize properly.
     */
    return (current.equals(zero) ? super.getPreferredSize() : current);    
  }

  ////////////////////////////////////////////////////////
  // END OF BEAN-REALTED METHODS AS FAR AS PROPERTIES
  //           ARE CONCERNED
  ////////////////////////////////////////////////////////


  public Insets insets() {
    return new Insets(5, 20, 5, 20);
  }


  /*Now since these methods donot take an argument, they would visible 
    when you try and connect another components event ---- lets say
    mouse clicked to this TextEditor */

  public void loadSerialized() {
    Frame frame0 = new Frame();
    FileDialog fd = new FileDialog(frame0, "Load Serialized", FileDialog.LOAD);
    fd.show();
    String filename = fd.getFile();
    if (filename != null) {
      try {
        FileInputStream fiss = new FileInputStream(filename);
        ObjectInputStream oiss = new ObjectInputStream(fiss);
        String str = (String)oiss.readObject();
        this.setText(str);
      }
      catch (Exception e) {}
    }
  }
  
  public void save() {
    Frame frame1=new Frame();
    //create a file dialog
    FileDialog fd = new FileDialog(frame1, "Save Scribble", FileDialog.SAVE);
    fd.show();
    String filename = fd.getFile();
    if (filename != null) {
      try {
        FileOutputStream fos = new FileOutputStream(filename);
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        String str = this.getText();
        oos.writeObject(str);
        oos.flush();
        oos.close();
      }
      catch (IOException e) {
        System.out.println(e);
          }
    }
  }
  
  // Opens a file
  public void load() {
    Frame frame = new Frame();
    FileDialog fd = new FileDialog(frame, "Load Scribble", FileDialog.LOAD);
    fd.show();
    String filename = fd.getFile();
    File f = new File(filename);
    int size = (int)f.length();
    int bytes_read = 0;
    if (filename != null) {
      try {
        FileInputStream fis = new FileInputStream(filename);
        byte[] data = new byte[size];
        while (bytes_read < size) 
          bytes_read += fis.read(data, bytes_read, size-bytes_read);
        this.setText(new String(data));
      }
      catch (Exception e) {
        System.out.println(e);
      }
    }
  }
  
}


TextEditorBeanInfo - Source Code

A class that provides explicit information about a bean must implement the BeanInfo interface or extend a class that implements it. This interface identifies all of the methods that a framework needs in order to introspect a bean.

You specify the name of the bean info class by adding BeanInfo to the name of the bean. For example, the bean info class associated to the class TextEditor must be named TextEditorBeanInfo. The bean info class must be part of the same package as the bean itself.

The getIcon() method returns an icon for the bean, which might be used as a graphical representation of the bean in a palette. You can override the getIcon() method to specify the different icons associated with your bean. Icon images typically are in the GIF format, although Java Beans may support other formats in future. The BeanInfo interface defines constant values to identify four types of icons: ICON_COLOR_16x16, ICON_COLOR_32x32, ICON_MONO_16x16 and ICON_MONO_32x32.

package sunw.demo.TextEditor;

import java.beans.*;

/**
 *  TextEditorBeanInfo.java
 *  

*/ public class TextEditorBeanInfo extends SimpleBeanInfo { public java.awt.Image getIcon(int iconType) { if (iconType == BeanInfo.ICON_COLOR_16x16) { java.awt.Image img = loadImage("faces.gif"); return img; } if (iconType == BeanInfo.ICON_COLOR_32x32) { java.awt.Image img = loadImage("ImageScaleIconColor32.gif"); return img; } if (iconType == BeanInfo.ICON_MONO_16x16) { java.awt.Image img = loadImage("ImageScaleIconMono16.gif"); return img; } if (iconType == BeanInfo.ICON_MONO_32x32) { java.awt.Image img = loadImage("ImageScaleIconMono32.gif"); return img; } return null; } }


Makefile

Compiling a bean is very similar to compiling a Java class. A bean, however, usually consists of more than one class: it can have an icon, a customizer, a BeanInfo class, and so on. Therefore, all of the bean class files and all other resource files must be packaged and delivered as a unit. JDK1.1 provides a utility, called Java archive (JAR), that supports the ZIP format and can bundle a number of files into one flat JAR file. Another complication when compiling a bean is the configuration management. Because a bean comprises more than one file, we need to ensure that proper versions of files are packaged together and that the JAR file is recreated whenever any of the bean's files changes. The best way to manage this complexity is through the use of makefiles.

# Makefile for the TextEditor Java Bean.

CLASSFILES= \
        sunw/demo/TextEditor/TextEditor.class \
        sunw/demo/TextEditor/TextEditorBeanInfo.class 
DATAFILES= \
        sunw/demo/TextEditor/ImageScaleIconColor16.gif \
        sunw/demo/TextEditor/ImageScaleIconColor32.gif \
        sunw/demo/TextEditor/ImageScaleIconMono16.gif \
        sunw/demo/TextEditor/ImageScaleIconMono32.gif \
        sunw/demo/TextEditor/faces.gif

JARFILE= ../jars/TextEditor.jar

all: $(JARFILE)

# Build a new JAR file with an appropriate manifest.

$(JARFILE): $(CLASSFILES) $(DATAFILES)
        echo "Name: sunw/demo/TextEditor/TextEditor.class">> manifest.tmp
        echo "Java-Bean: True" >> manifest.tmp
        jar cfm $(JARFILE) manifest.tmp sunw/demo/TextEditor/*.class $(DATAFILES)
        @/bin/rm manifest.tmp

.SUFFIXES: .java .class

{sunw/demo/TextEditor}.java{sunw/demo/TextEditor}.class :
%.class: %.java
        export CLASSPATH; CLASSPATH=.:$(HOME):$(HOME)/visibroker/classes:$(HOME)/visibroker/testers/Imaging:$(HOME)/beans/demo/sunw/demo/ImageEditor; \
        javac $<

clean:
        /bin/rm -f sunw/demo/TextEditor/*.class
        /bin/rm -f $(JARFILE)

Meryem Ispirli
Last modified: Fri Apr 2 12:55:55 EST 1999