3
JCTabButton and JCTabManager

Introduction · Sample Program Code · Changing the Active Tab

Controlling Tab Display · Tab Button Properties · Events

Property Listing · Example Program


Introduction

Tabbed dialogs enable the programmer to create a "layer" of dialogs which the user can access through a set of tabs. Based on the visual metaphor of a sequence of file folders, users click a tab to display the contents of a specific file folder. Tabbed dialogs provide an easy way to provide users with a convenient and intuitive way of accessing option contained within with a well-organized interface.

The Java Development Kit (JDK) does not implement tab dialogs. JCTabButton dialogs look and behave like their MS Windows 95 equivalents. JCTabButton dialogs are created and controlled by JCTabManager, which is a container that organizes its children into pages to simulate a sequence of file folders. The page components are defined as children of the JCTabManager; a property is then used to associate a page with a particular tab button. Page components can be of any class (including any container). The tabs are subclassed from JCButton, which can contain multiple lines of text, images, or contain both text and images. JCTabButton dialogs uses the new event model to update the tabbed page display.

Behavior

JCTabButton dialogs behave in the following manner:


Sample Program Code

To program tabbed dialogs, you need to create the following:

Together, the JCTabManager and JCTabButton simulate a sequence of file folders. The page components are defined as children of the JCTabManager; a constraint property is then used to associated a page component with a particular JCTabButton. Page components can be of any component or container.

The following illustration illustrates the anatomy of a typical tabbed dialog.

Anatomy of a tabbed dialog

The following code fragment creates a JCTabManager container, then adds several tabs and pages as its children:

package jclass.bwt.examples;
import jclass.bwt.BWTEnum;
import jclass.bwt.JCCheckbox;
import jclass.bwt.JCCheckboxGroup;
import jclass.bwt.JCContainer;
import jclass.bwt.JCGridLayout;
import jclass.bwt.JCItemEvent;
import jclass.bwt.JCItemListener;
import jclass.bwt.JCLabel;
import jclass.bwt.JCTabButton;
import jclass.bwt.JCTabManager;
import jclass.bwt.JCTabManagerEvent;
import jclass.bwt.JCTabManagerListener;
import jclass.contrib.ContribFrame;
import jclass.util.JCString;
import jclass.util.JCUtilConverter;
import java.awt.*;
import java.util.Date;

/**
 * This example creates a JCTabManager which displays some of the other
 * examples.
 */
public class tabManager extends java.applet.Applet
implements Runnable, JCTabManagerListener, JCItemListener {

JCLabel label = new JCLabel();
JCTabManager tab_manager;
transient Thread updater;

// JCItemListener method
public void itemStateChanged(JCItemEvent ev) {
	JCCheckboxGroup group =
		(JCCheckboxGroup) ((Component)ev.getSource()).getParent();

	if (group.getTitle().equals("Shape"))
		tab_manager.setTabShape(group.getValue());
	else if (group.getTitle().equals("Side"))
		tab_manager.setTabSide(group.getValue());
}

/*
 *  JCTabManagerListener methods
 */

// Sets the page when the Date or Vendor tab is clicked
public void tabManagerChangeBegin(JCTabManagerEvent ev) {
	JCTabButton tab = ev.getNextTab();
	if (tab.getName().equals("Date")) {
		label.setLabel(""+new Date());
		start();
		return;
	}

	// Stop date thread if it is running
	stop();
	if (tab.getName().equals("Vendor")) {
		String url = System.getProperty("java.vendor.url");
		JCString s = JCString.parse(this, "[COLOR=blue][href=" + url + " TARGET=_blank]" + url);
		label.setLabel(s);
	}
}
public void tabManagerChangeEnd(JCTabManagerEvent ev) {}

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

static String side_labels[] = { "Top", "Bottom" };
static int side_values[] = { BWTEnum.TOP, BWTEnum.BOTTOM } ;

static String shape_labels[] = { "Rectangular", "Slanted" };
static int shape_values[] = { BWTEnum.RECTANGLE, BWTEnum.SLANTED };

public void init() {
	// Force tab manager to be same size as applet
	setLayout(new GridLayout(1,1));
	tab_manager = new JCTabManager();
	tab_manager.addTabManagerListener(this);
	setBackground(Color.lightGray);

	JCCheckboxGroup sides = JCCheckbox.makeGroup(side_labels, side_values, true);
	sides.setTitle("Side");
	sides.addItemListener(this);
	JCCheckboxGroup shapes = JCCheckbox.makeGroup(shape_labels, shape_values, true);
	shapes.setTitle("Shape");
	shapes.addItemListener(this);

	JCContainer panel = new JCContainer();
	panel.setInsets(new Insets(0, 20, 0, 20));
	panel.setLayout(new JCGridLayout(1, BWTEnum.VARIABLE, 10, 10));
	panel.add(sides);
	panel.add(shapes);
	tab_manager.addPage("Tab Styles", panel);

	labels l = new labels(this);
	l.init();
	l.setBackground(Color.yellow);
	tab_manager.addPage("Labels", l);

	buttons b = new buttons(this);
	b.init();
	tab_manager.addPage("Buttons", b);

	/*
	 * Add tabs which share the same page. The page contents will be set
	 * in the listener method when the tab is clicked.
	 */
	label.setFont(new Font("TimesRoman", Font.BOLD, 20));
	int pos = tab_manager.addPage("Java Vendor", label);
	tab_manager.getTab(pos).setName("Vendor");

	pos = tab_manager.addPage("Current Date", label);
	tab_manager.getTab(pos).setName("Date");

	add(tab_manager);
}

public void start() {
	if (updater == null) {
		updater = new Thread(this);
		updater.start();
	}
}

public void stop() {
	if (updater != null) {
		updater.yield();
		updater.stop();
	}
	updater = null;
}

/** Writes the current time every second. */
public void run() {
	while (true) {
		try {
			Thread.sleep(1000);
		} catch (Exception e) {}

		if (!Thread.currentThread().isAlive() || updater == null)
			return;
		label.setLabel(""+new Date());
	}
}

public static void main(String args[]) {
	ContribFrame frame = new ContribFrame("TabManager");
	tabManager s = new tabManager();

	s.init();
	frame.add(s);
	frame.pack();
	frame.show();
}
}
This creates the following tabbed dialog display:

A sample JCTabManager with child JCTabButtons

This application consists of a Tab Manager, with four JCTabButtons defined as its children. Each JCTabButton has a page associated with it. Each page, in turn, has other BWT components defined as its child; in more complicated real-life applications, additional container components are defined as children of the pages.

To create a multi-level file folder, define another JCTabManager as a page component.

This sample code is incorporated into the example file tabManager.class provided with JClass BWT. For information on how to run this program, see the " Example Program" section at the end of this chapter.


Changing the Active Tab

The JCTabManager component provides two methods to control the display of the tab manager and its children:

Tab Events

JCTabManager can be notified when a page has been changed and can be set at run-time; in other words, a number of tabs could share the same page and JCTabManager could set the page contents after the user has clicked a tab.

The JCTabManagerInfo constructor defines actions to be invoked whenever the value of TABMANAGER changes, which can be set either interactively or programmatically. This enables you to control page display.

Each TABMANAGER property is passed the following structure:

public JCTabManagerInfo(Event ev,
					Component current,
					Component next)
Each event is called both before and after the page change takes place. reason indicates which event is occurring, and is either BEGIN (before page change) or END (after page change).

The new page component and its number are specified by the current_pageand next_page variables. These members can be modified, which allows you to control page changes in a JCTabManager. The doit field provides an easy way to suppress page changes. If doit is set to false if stage is set to BEGIN, the page change does not occur.


Controlling Tab Display

JCTabManager enables you to control the following tab display features:

Tab Resizing

The TabResize property specifies whether all tabs should be resized to the width or height of the largest tab in the same row. If TabResize is true (default), resizing is performed; if false, each tab is only as large as necessary to display its label.


Tab Stretching

The TabStretch property specifies whether all tabs should be stretched if necessary to fill the entire side.

Tab stretching

To ensure that the tabs take up all the available visible space and are of the same size, set TabResize and TabStretch to true.

Tab Shape

The TabShape property sets the shape of the tab. There are two available values: RECTANGLE (default), or SLANTED. The effects of both values are depicted in the following illustration:


The two values of TabShape illustrated

Tab Color

The TabColorPolicy property sets the color for individual tabs within JCTabManager. TabColorPolicy does not directly set the color for an individual tab, instead it either reads the color value from the tabbed page, or sets the tab's color to a value defined within the tab manager. The two values for TabColorPolicy are COLOR_PAGE, which sets the tab's color to the page's color (default), and COLOR_INHERIT, which sets the tab's color to the tab manager's color.

Tab Placement

The TabSide property sets the placement for the displays of tabs within JCTabManager. There are two values for TabSet: TOP and BOTTOM. The effects of both values are depicted in the following illustration:

The two values of TabSide illustrated


Tab Button Properties

The following sections describe how to use the JCTabButton component.

Altering the Tab Button Font

The CurrentTabFont property sets the current tab's font (default: bold version of the default font). It can be altered by specifying a different valid Java font name with the property, as in the following code fragment:

public void init() {
        JCImageCreator im = new JCImageCreator(this, 16, 16);
        im.setColor('X', Color.red);
        im.setColor('o', Color.black);
        im.setColor('.', Color.white);
        siteImage = im.create(site_icon);
        // Force tab manager to be same size as applet
        setLayout(new GridLayout(1,1));
        setBackground(Color.lightGray);
        tab_manager = new JCTabManager();
        tab_manager.setBackground(Color.lightGray);
        tab_manager.addTabManagerListener(this);
        // set the font for the selected Tab.
        Font newFont = new Font("Courier", Font.PLAIN, 16);
        tab_manager.setCurrentTabFont(newFont);
        theFTPPanel = new FTPPanel(this);
        for (int i=0; i<tabName.length; i++) {
                JCString        name = new JCString();
                name.add(siteImage);
                name.add(tabName[i]);
                tab_manager.setTabPage(i+1, name, theFTPPanel);
        }
        setTextFields(tab_manager.getCurrentTab());
        tab_manager.setTabStretch(true);
        add(tab_manager);
}
The result of this code can be seen in the following illustration:

Changing Fonts within the Tabs

This example uses a JCString to insert images within the tab buttons. For more information on JCStrings, see Appendix B: JCString Properties.

Adding an Image to a Tab Button

To specify a image for a JCTabButton, specify an object in the JCTabButton constructor. The JCTabButton constructor can be passed a String, image or JCString.

The following code fragment displays how to add an image file as an object, and a subsequent tab displays a JCString.

/ This example uses a memory image
// Static Variables
static String tabName[] = {
        "Guru", "Gonzo", "KLG's ftp site",
};
static final String site_icon[] = {
"   oooooooooo   ",
"  o..........o  ",
"  o..XXXXXX..o  ",
"  o.X......X.o  ",
"  o.X......X.o  ",
"  o.X......X.o  ",
"  o.X......X.o  ",
"  o.X......X.o  ",
"  o..XXXXXX..o  ",
"  o..........o  ",
"  o....XXXXX.o  ",
"  o..........o  ",
"  oooooooooooo  ",
"   o........o   ",
"   o........o   ",
"   oooooooooo   "};
public void init() {
        JCImageCreator im = new JCImageCreator(this, 16, 16);
        im.setColor('X', Color.red);
        im.setColor('o', Color.black);
        im.setColor('.', Color.white);
        Image siteImage = im.create(site_icon);
        // Force tab manager to be same size as applet
        setLayout(new GridLayout(1,1));
        setBackground(Color.lightGray);
        tab_manager = new JCTabManager();
        tab_manager.setBackground(Color.lightGray);
        tab_manager.addTabManagerListener(this);
        theFTPPanel = new FTPPanel(this);
        for (int i=0; i<tabName.length; i++) {
                JCString        name = new JCString();
                name.add(siteImage);
                name.add(tabName[i]);
                tab_manager.setTabPage(i+1, name, theFTPPanel);
        }
        setTextFields(tab_manager.getCurrentTab());
        tab_manager.setTabStretch(true);
        add(tab_manager);
}
The image is constructed within the code and not via a .GIF image file. The results can be seen in the following illustration .

Inserting images into tab buttons

Text and Pixmap Positioning

Text and images can be aligned within a JCTabButton by using the Alignment property which has nine possible values: TOPLEFT, TOPCENTER, TOPRIGHT, MIDDLELEFT, MIDDLECENTER, MIDDLERIGHT, BOTTOMLEFT, BOTTOMCENTER, and BOTTOMRIGHT. All nine values are used with text strings in the following code sample, whose results can be seen in the following illustration.

Tab Button text and pixmap layouts

The default is MIDDLECENTER.

Text and images can also be aligned using JCStrings. This approach is limited to the three values possible with ALIGN: TOP, BOTTOM and MIDDLE. The following code fragment shows how to insert JCStrings within tab labels.

// Using a JCString with alignment information
                JCString s = JCString.parse(this, "[ALIGN=TOP]"+tabName[i]);
                tab_manager.setTabPage(i+1, s, theFTPPanel);

Specifying Tab Button and Page Colors

Each JCTabButton component obtains its color specifications from the page component with which it is associated. To specify your own JCTabButton colors, change the appropriate color properties (such as foreground) after associating a page component with the JCTabButton.

The shadow colors for each page component are, in turn, obtained from the JCTabButton color specifications.


Events

A class can be notified before and after a new JCTabManager page is displayed by implementing the JCTabManagerListener interface and registering itself with the tabManager via addTabManagerListener, as the following code demonstrates:

public interface JCTabManagerListener {
        // Invoked before the page is changed. The event's values can be modified via its setValue method.
        public void tabManagerChangeBegin(JCTabManagerEvent e);
        // Invoked after the page is changed. Any changes made to the event are ignored.
        public void tabManagerChangeEnd(JCTabManagerEvent e);
}
public class JCTabManagerEvent {
        // Returns the component where the event originated.
        public Object getSource()
        // Returns the event type.
        public int getId()
        // Gets the current page (null at initialization).
        public Component getCurrentPage()
        // Gets the page that will be displayed.
        public Component getNextPage()
        // Gets the current tab (null at initialization).
        public JCTabButton getCurrentTab()
        // Gets the tab that will be displayed.
        public JCTabButton getNextTab()
        // Sets the page that will be displayed.
        public void setNextPage(Component page)
        // Determines whether the page should change.
        public boolean getChangePage()
        // Determines whether the page should change (default: true).
        public void setChangePage(boolean v)
}


Property Listing

The following summarizes the properties of JCTabManager. Complete reference documentation is available online in standard javadoc format in jclass.bwt.JCTabManager.html.

jclass.bwt.JCTabManager

Name

Method

Inherited from

Alignment

setAlignment

jclass.bwt.JCTabManager

Background

setBackground

jclass.bwt.JCContainer

CurrentTabFont

setCurrentTabFont

jclass.bwt.JCTabManager

FirstVisibleTab

setFirstVisibleTab

jclass.bwt.JCTabManager

Font

setFont

jclass.bwt.JCContainer

Foreground

setForeground

jclass.bwt.JCContainer

Insets

setInsets

jclass.bwt.JCContainer

PreferredSize

setPreferredSize

jclass.bwt.JCContainer

TabColorPolicy

setTabColorPolicy

jclass.bwt.JCTabManager

TabResize

setTabResize

jclass.bwt.JCTabManager

TabShape

setTabShape

jclass.bwt.JCTabManager

TabSpacing

setTabSpacing

jclass.bwt.JCTabManager

TabStretch

setTabStretch

jclass.bwt.JCTabManager

UserData

setUserData

jclass.bwt.JCContainer


Example Program

Demonstration programs and example code containing JCTabButtons and JCTabManagers come with JClass BWT. The examples can be viewed in applet form by launching index.html within the /jclass/bwt/examples directory. tabManager.class can also be run as stand-alone Java applications from the command prompt by typing:

     java jclass.bwt.examples.tabManager