/*
* Licensed Materials - Property of Rogue Wave Software, Inc.
* © Copyright Rogue Wave Software, Inc. 2014, 2017
* © Copyright IBM Corp. 2009, 2014
* © Copyright ILOG 1996, 2009
* All Rights Reserved.
*
* Note to U.S. Government Users Restricted Rights:
* The Software and Documentation were developed at private expense and
* are "Commercial Items" as that term is defined at 48 CFR 2.101,
* consisting of "Commercial Computer Software" and
* "Commercial Computer Software Documentation", as such terms are
* used in 48 CFR 12.212 or 48 CFR 227.7202-1 through 227.7202-4,
* as applicable.
*/
package accessibility;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Container;
import java.awt.Font;
import java.awt.KeyboardFocusManager;
import java.awt.event.ActionEvent;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.print.PageFormat;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URL;
import javax.swing.AbstractAction;
import javax.swing.AbstractButton;
import javax.swing.Action;
import javax.swing.ButtonGroup;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JPanel;
import javax.swing.JRadioButtonMenuItem;
import javax.swing.JToolBar;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
import javax.swing.border.BevelBorder;
import javax.swing.table.TableModel;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import ilog.views.chart.IlvChart;
import ilog.views.chart.IlvChartRenderer;
import ilog.views.chart.IlvScale;
import ilog.views.chart.accessibility.IlvAccessibleDataObject;
import ilog.views.chart.accessibility.IlvAccessibleDataPoint;
import ilog.views.chart.accessibility.IlvAccessibleDataSet;
import ilog.views.chart.accessibility.IlvChartAreaAccessible;
import ilog.views.chart.accessibility.IlvChartAreaAccessibleHierarchy;
import ilog.views.chart.accessibility.IlvDefaultChartAreaAccessibleHierarchy;
import ilog.views.chart.data.IlvDataSet;
import ilog.views.chart.data.IlvDataSetPoint;
import ilog.views.chart.data.IlvTreeTableDataSource;
import ilog.views.chart.datax.IlvColumnUtilities;
import ilog.views.chart.datax.IlvDataColumnInfo;
import ilog.views.chart.datax.IlvDefaultDataColumnInfo;
import ilog.views.chart.datax.adapter.partition.IlvPartitionerFactory;
import ilog.views.chart.datax.adapter.partition.IlvStringPartitionerFactory;
import ilog.views.chart.datax.flat.table.IlvDefaultFlatTableModel;
import ilog.views.chart.graphic.IlvDataLabelAnnotation;
import ilog.views.chart.interactor.IlvChartAreaNavigationMode;
import ilog.views.chart.interactor.IlvChartAreaSelectionManager;
import ilog.views.chart.interactor.IlvChartCycleSelectInteractor;
import ilog.views.chart.print.IlvChartPrintableDocument;
import ilog.views.chart.renderer.IlvSimpleValueColorScheme;
import ilog.views.chart.renderer.IlvTreemapChartRenderer;
import ilog.views.util.IlvImageUtil;
import ilog.views.util.data.IlvCSVReader;
import ilog.views.util.internal.IlvURLUtil;
import ilog.views.util.styling.IlvStylingException;
import ilog.views.util.swing.border.IlvEtchedLineBorder;
import ilog.views.util.swing.layout.IlvBetterFlowLayout;
import shared.AbstractChartExample;
import shared.PDFGenerator;
/**
* A class that demonstrates accessibility features, such as - keyboard
* navigation, - redundant colors.
*/
public class AccessibilityDemo extends AbstractChartExample {
/**
* The chart at the center of the frame.
*/
IlvChart chart;
/**
* True if keyboard navigation can select the x scale.
*/
boolean xScaleSelectable;
/**
* True if keyboard navigation can select the y scale.
*/
boolean yScaleSelectable;
/**
* The hierarchy of selectable elements of the chart area.
*/
IlvDefaultChartAreaAccessibleHierarchy hierarchy;
/**
* The manager that keeps track of and displays the current selection.
*/
IlvChartAreaSelectionManager selectionManager;
/**
* The chart interactor that reacts on keyboard events by moving around the
* current selection or the focus.
*/
IlvChartCycleSelectInteractor interactor;
/**
* The name of the project that the chart displays.
*/
String project;
/**
* The status bar at the bottom of the frame. In this sample, it displays the
* currently focused component and, inside the chart area, the currently
* selected element.
*/
JLabel statusBar;
// ========================== Keyboard Navigation ==========================
/**
* Specifies whether keyboard navigation can select the x scale.
*/
private void setXScaleSelectable(boolean selectable) {
IlvScale scale = chart.getXScale();
if (scale != null)
hierarchy.setSelectable(scale, selectable);
}
/**
* Specifies whether keyboard navigation can select the y scale.
*/
private void setYScaleSelectable(boolean selectable) {
IlvScale scale = chart.getYScale(0);
if (scale != null)
hierarchy.setSelectable(scale, selectable);
}
/**
* Creates the keyboard navigation interactor that uses the given mode and
* makes use of the <code>hierarchy</code> and <code>selectionManager</code>
* objects.
*/
private IlvChartCycleSelectInteractor createInteractor(IlvChartAreaNavigationMode mode) {
// This sample uses a customized hierarchy.
// Therefore, instead of letting the interactor create its own, new
// hierarchy object, reuse the customized one.
IlvChartCycleSelectInteractor interactor = new IlvChartCycleSelectInteractor(mode) {
Override
public IlvChartAreaAccessibleHierarchy createAccessibleHierarchy(IlvChart chart) {
return hierarchy;
}
};
interactor.setSelectionManager(selectionManager);
return interactor;
}
/**
* Installs a custom focus traversal on the given component. This means that:
* - The user can assign the focus to the component, by repeatedly pressing
* Tab or Shift-Tab. - The component has its own way of managing "focus"
* inside itself. - The user needs to press Ctrl-Tab or Shift-Ctrl-Tab instead
* of Tab or Shift-Tab in order to move the focus outside the component.
*/
private void installCustomFocusTraversal(Component component) {
// So that the user can assign the focus to the component, it must
// be enabled.
// This statement is not needed in this sample, because the components
// are enabled anyway.
// component.setEnabled(true);
// So that the user can assign the focus to the component, it must
// be focusable.
component.setFocusable(true);
// If the component is a Container, and the user should use Ctrl-Tab
// or Shift-Ctrl-Tab instead of Tab or Shift-Tab in order to leave
// the component, you would have to designate it as a "focus cycle root".
// component.setFocusCycleRoot(true);
// Disable the AWT default actions for Tab and Shift-Tab on the component.
component.setFocusTraversalKeysEnabled(false);
// Enable similar actions for Ctrl-Tab and Shift-Ctrl-Tab instead.
component.addKeyListener(new KeyAdapter() {
private KeyStroke CTRL_TAB = KeyStroke.getKeyStroke(KeyEvent.VK_TAB, KeyEvent.CTRL_MASK);
private KeyStroke SHIFT_CTRL_TAB = KeyStroke.getKeyStroke(KeyEvent.VK_TAB,
KeyEvent.SHIFT_MASK | KeyEvent.CTRL_MASK);
// Override keyPressed, not keyTyped, because these two KeyStrokes
// are defined through a key code, not through a key char.
Override
public void keyPressed(KeyEvent event) {
KeyStroke key = KeyStroke.getKeyStrokeForEvent(event);
if (CTRL_TAB.equals(key)) {
// Moves the focus outside of the chart area component, to the
// next focusable component.
KeyboardFocusManager.getCurrentKeyboardFocusManager().focusNextComponent();
event.consume();
} else if (SHIFT_CTRL_TAB.equals(key)) {
// Moves the focus outside of the chart area component, to the
// previous focusable component.
KeyboardFocusManager.getCurrentKeyboardFocusManager().focusPreviousComponent();
event.consume();
}
}
});
}
// ---------------------- Displaying the current focus ----------------------
/**
* Displays the currently focused GUI element in the status bar.
*/
private void updateFocusOwnerDisplay() {
Component focusOwner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();
String text = "<none>";
if (focusOwner != null) {
// First piece of text: The class name of the focus owner.
Class<?> focusOwnerClass = focusOwner.getClass();
while (focusOwnerClass.isAnonymousClass()) // such as
// javax.swing.JToolBar$1.class
focusOwnerClass = focusOwnerClass.getSuperclass();
text = focusOwnerClass.getName();
text = text.substring(text.lastIndexOf('.') + 1).replace('$', '.');
// More detailed information for buttons.
if (focusOwner instanceof AbstractButton) {
AbstractButton button = (AbstractButton) focusOwner;
if (button.getText() != null) {
text += "(\"" + button.getText() + "\")";
} else if (button.getAction() != null) {
String name = (String) button.getAction().getValue(Action.NAME);
String shortDescription = (String) button.getAction().getValue(Action.SHORT_DESCRIPTION);
text += "(\"" + (shortDescription != null ? shortDescription : name) + "\")";
}
}
// For the chart area, add details about the selected element.
else if (focusOwner instanceof IlvChart.Area) {
IlvChartAreaAccessible selection = selectionManager.getSelection();
if (selection != null) {
if (selection instanceof IlvScale) {
text += " " + (((IlvScale) selection).getAxis().isXAxis() ? "X scale" : "Y scale");
} else if (selection instanceof IlvChartRenderer) {
text += " " + selection;
} else if (selection instanceof IlvAccessibleDataSet) {
IlvDataSet ds = ((IlvAccessibleDataSet) selection).getDataSet();
text += " Data Set: " + ds.getName();
} else if (selection instanceof IlvAccessibleDataPoint) {
IlvDataSetPoint dp = ((IlvAccessibleDataPoint) selection).getDataPoint();
text += " Data Point: " + dp.getDataSet().getName() + ", Point #" + dp.getIndex() + " (" + dp.getXData()
+ "," + dp.getYData() + ")";
} else if (selection instanceof IlvAccessibleDataObject) {
text += " Data Object: " + ((IlvAccessibleDataObject) selection).getObject();
} else {
text += " " + selection;
}
}
}
statusBar.setText("Focus: " + System.currentTimeMillis() + " " + text);
}
}
/**
* Installs a notification that makes sure that the focus owner display gets
* updated when the focus owner changes.
*/
private void installFocusOwnerListener() {
// Get notified when the focus owner changes.
KeyboardFocusManager.getCurrentKeyboardFocusManager().addPropertyChangeListener("focusOwner",
new PropertyChangeListener() {
Override
public void propertyChange(PropertyChangeEvent event) {
updateFocusOwnerDisplay();
}
});
}
/**
* Creates an IlvChartAreaSelectionManager that makes sure that the focus
* owner (and selection) display gets updated when the selection in the chart
* area changes.
*/
private IlvChartAreaSelectionManager createSelectionManager() {
return new IlvChartAreaSelectionManager() {
Override
public void setSelection(IlvChartAreaAccessible selection) {
super.setSelection(selection);
// After the selection has changed, update the focus owner display.
updateFocusOwnerDisplay();
}
};
}
// ------------------- Keyboard Navigation Initialization -------------------
/**
* Initializes the keyboard navigation.
*/
private void initKeyboardNavigation() {
xScaleSelectable = true;
yScaleSelectable = true;
hierarchy = new IlvDefaultChartAreaAccessibleHierarchy(chart);
setXScaleSelectable(xScaleSelectable);
setYScaleSelectable(yScaleSelectable);
selectionManager = createSelectionManager();
interactor = createInteractor(IlvChartCycleSelectInteractor.TRAVERSE_ALL);
chart.addInteractor(interactor);
// Enable custom handling of Tab, Shift-Tab, etc. in the chart area.
// Optionally you could do the same thing for the legend as well.
// The chart component itself can stay non-focusable.
installCustomFocusTraversal(chart.getChartArea());
installFocusOwnerListener();
}
// ============================ Several Projects ============================
/**
* The list of projects that can be displayed in this sample.
*/
static String[] allProjects = { "data/influenza-by-year.icpr -- polyline chart",
// "../gallery/data/wheat-by-year.icpr -- polyline chart",
"data/french-parliament.icpr -- clustered bar chart", "data/influenza-by-age.icpr -- stacked area chart",
"data/wheat-by-state.icpr -- pie chart", "data/income-per-county.csv -- treemap chart",
// "../gallery/data/countries.icpr -- radar chart",
// "../gallery/data/currency-exchange.icpr -- high-low chart",
// "../gallery/data/earthquakes-alaska.icpr -- bubble chart",
// "../gallery/data/hertzsprung-russell.icpr -- scatter chart",
// "../gallery/data/xor-circuit.icpr -- stair chart",
// "../gallery/data/yagi-antenna.icpr -- polar chart",
};
/**
* Loads the specified project.
*
* @param projectLabel
* A string from <code>allProjects</code>.
*/
private void loadProject(String projectLabel) {
String filename = projectLabel.substring(0, projectLabel.indexOf(" -- "));
URL url = getResourceURL(filename);
URL projectUrl = (filename.endsWith(".icpr") ? url : null);
try {
// Put the chart's type into a default state. When the chart's
// configuration was read from a CSS file, this is automatic.
// But when we have changed the chart type through the API, we
// have to do it explicitly.
if (chart.getType() == IlvChart.TREEMAP)
chart.setType(IlvChart.CARTESIAN);
chart.setProject(projectUrl);
} catch (IOException e) {
System.err.println("Cannot load " + filename);
e.printStackTrace();
} catch (IlvStylingException e) {
System.err.println("Cannot load the style of " + filename);
e.printStackTrace();
}
// Treemap projects need special handling because here they are not
// specified through a .icpr file.
if (projectLabel.endsWith(" -- treemap chart"))
loadTreemapProject(url);
// Remember the chosen project, for the display of the menu.
project = projectLabel;
}
/**
* Loads the treemap project.
*
* @param url
* The URL of the data file.
*/
private void loadTreemapProject(URL url) {
// Read the CSV file into memory.
TableModel tableModel;
try {
InputStream stream = IlvURLUtil.openStream(url);
Reader reader = new InputStreamReader(new BufferedInputStream(stream), "ASCII");
try {
tableModel = IlvCSVReader.getInstance(IlvCSVReader.COMMA, 0).read(reader);
} finally {
reader.close();
}
} catch (IOException e) {
e.printStackTrace();
chart.setDataSource(null);
return;
}
// Information about the columns in the CSV file (name and type).
String[] columnNames = { "State", "County code", "State Abbrev", "County name", "Returns", "Exemptions",
"Adjusted gross income", "Wages and salaries", "Dividends", "Interest",
// Extra, computed columns.
"Wages and salaries percentage", "Dividends percentage", "Interest percentage" };
Class<?>[] columnTypes = { String.class, String.class, String.class, String.class, Double.class, Double.class,
Double.class, Double.class, Double.class, Double.class };
final int County_code_COLUMN = 1;
final int County_name_COLUMN = 3;
final int Adjusted_gross_income_COLUMN = 6;
final int Wages_and_salaries_COLUMN = 7;
final int Dividends_COLUMN = 8;
final int Interest_COLUMN = 9;
final int Wages_and_salaries_percentage_COLUMN = 10;
final int Dividends_percentage_COLUMN = 11;
final int Interest_percentage_COLUMN = 12;
// Copy the data into an IlvFlatTableModel, with appropriate
// conversion of values.
int numColumns = tableModel.getColumnCount();
IlvDataColumnInfo[] columns = new IlvDataColumnInfo[columnNames.length];
for (int col = 0; col < numColumns; col++) {
columns[col] = new IlvDefaultDataColumnInfo(columnNames[col], columnTypes[col]);
}
for (int col = numColumns; col < columnNames.length; col++) {
columns[col] = new IlvDefaultDataColumnInfo(columnNames[col], Double.class);
}
int numRows = tableModel.getRowCount();
IlvDefaultFlatTableModel tableData = new IlvDefaultFlatTableModel(numRows, columns);
for (int col = 0; col < numColumns; col++) {
if (columnTypes[col] == Double.class) {
for (int row = 0; row < numRows; row++) {
double value = Double.parseDouble(tableModel.getValueAt(row, col).toString());
tableData.setDoubleAt(value, row, col);
}
} else if (columnTypes[col] == Integer.class) {
for (int row = 0; row < numRows; row++) {
int value = (int) Double.parseDouble(tableModel.getValueAt(row, col).toString());
tableData.setValueAt(new Integer(value), row, col);
}
} else if (columnTypes[col] == String.class) {
for (int row = 0; row < numRows; row++) {
String value = tableModel.getValueAt(row, col).toString();
tableData.setValueAt(value, row, col);
}
} else {
for (int row = 0; row < numRows; row++) {
Object value = tableModel.getValueAt(row, col);
tableData.setValueAt(value, row, col);
}
}
}
// Remove the suffix " County" from the county names.
for (int row = 0; row < numRows; row++) {
String countyName = (String) tableData.getValueAt(row, County_name_COLUMN);
if (countyName.endsWith(" County"))
tableData.setValueAt(countyName.substring(0, countyName.length() - 7), row, County_name_COLUMN);
}
// Fill the computed column values.
for (int row = 0; row < numRows; row++) {
double agi = ((Double) tableData.getValueAt(row, Adjusted_gross_income_COLUMN)).doubleValue();
double wd = ((Double) tableData.getValueAt(row, Wages_and_salaries_COLUMN)).doubleValue();
double d = ((Double) tableData.getValueAt(row, Dividends_COLUMN)).doubleValue();
double i = ((Double) tableData.getValueAt(row, Interest_COLUMN)).doubleValue();
tableData.setValueAt(new Double(wd / agi), row, Wages_and_salaries_percentage_COLUMN);
tableData.setValueAt(new Double(d / agi), row, Dividends_percentage_COLUMN);
tableData.setValueAt(new Double(i / agi), row, Interest_percentage_COLUMN);
}
// Remove the rows with county code 0, because these are per-state
// summary rows.
for (int row = 0; row < tableData.getRowCount();) {
if ("0".equals(tableData.getValueAt(row, County_code_COLUMN)))
tableData.removeRow(row);
else
row++;
}
// Create a data source taking the model as input.
IlvTreeTableDataSource dataSource = new IlvTreeTableDataSource(tableData);
dataSource.setPartitionerFactories(new IlvPartitionerFactory[] {
new IlvStringPartitionerFactory(IlvColumnUtilities.getColumnByName(tableData, "State")) });
/*
* Customize the chart.
*/
chart.setType(IlvChart.TREEMAP);
// Add a header label.
chart.setHeaderText("Income from interests in the U.S. 2008");
chart.getHeader().setFont(new Font("Dialog", Font.PLAIN, 30));
chart.setDataSource(dataSource);
IlvTreemapChartRenderer renderer = (IlvTreemapChartRenderer) chart.getRenderer(0);
renderer.setAreaColumnName("Adjusted gross income");
// Customize the color of the objects.
// Set the column which determines the color.
renderer.setColorColumnName("Interest percentage");
renderer.setColorScheme(
IlvSimpleValueColorScheme.createAdjustedColorScheme(IlvTreemapChartRenderer.COLORSCHEME_AVERAGE_BLUE_YELLOW));
// Add a label to each rectangle, and arrange to avoid label overlaps.
renderer.setLabelColumnName("County name");
renderer.setAnnotation(new IlvDataLabelAnnotation());
renderer.setClippedAnnotationVisibility(false);
renderer.setAnnotationVisibility(IlvTreemapChartRenderer.VISIBILITY_SMART);
}
// ================================ Printing ================================
/**
* Creates the document to be printed.
*/
Override
protected IlvChartPrintableDocument createPrintableDocument() {
return new IlvChartPrintableDocument("accessibility", chart, PageFormat.LANDSCAPE, null);
}
// ============================= PDF Generation =============================
/**
* Creates the XSL-FO element to be shown in the PDF.
*/
Override
protected Element createFOElement(Document document, PDFGenerator pdfgen) {
return createFOElementForChart(chart, document, pdfgen);
}
// =========================== GUI Initialization ===========================
private AbstractAction exitAction;
/**
* Initializes the user interface of the sample's frame.
*/
Override
public void init(Container container) {
super.init(container);
// Allocate the components.
chart = new IlvChart();
initKeyboardNavigation();
loadProject(allProjects[0]);
JToolBar toolbar = createToolBar();
exitAction = new AbstractAction("Exit") {
Override
public void actionPerformed(ActionEvent event) {
quit();
System.exit(0);
}
};
JButton exitButton = new JButton(exitAction);
statusBar = new JLabel(" ");
statusBar.setBorder(new BevelBorder(BevelBorder.LOWERED));
// Put them together.
container.setLayout(new BorderLayout());
container.add(toolbar, BorderLayout.NORTH);
{
JPanel middlePanel = new JPanel();
middlePanel.setLayout(new BorderLayout());
middlePanel.add(chart, BorderLayout.CENTER);
{
JPanel buttonBar = new JPanel();
buttonBar.setLayout(new IlvBetterFlowLayout());
buttonBar.setBorder(new IlvEtchedLineBorder());
buttonBar.add(exitButton);
middlePanel.add(buttonBar, BorderLayout.SOUTH);
}
container.add(middlePanel, BorderLayout.CENTER);
}
container.add(statusBar, BorderLayout.SOUTH);
// Add a menu bar.
{
JMenuBar menuBar = new JMenuBar();
menuBar.add(createFileMenu());
menuBar.add(createSelectableElementsMenu());
menuBar.add(createNavigationModeMenu());
menuBar.add(createRenderingMenu());
menuBar.add(createLAFMenu());
setMenuBar(menuBar);
}
}
// -------------------------------- Tool Bar --------------------------------
/**
* Populates the specified toolbar.
*/
Override
protected void populateToolBar(JToolBar toolbar) {
super.populateToolBar(toolbar);
addPrintingToToolBar(toolbar);
}
// ---------------------------------- Menu ----------------------------------
private JMenu createFileMenu() {
JMenu menu = new JMenu("File");
menu = createProjectChooserMenu(menu);
if (isPrintingConfigured()) {
menu.addSeparator();
ImageIcon icon;
try {
icon = new ImageIcon(IlvImageUtil.loadImageFromFile(AbstractChartExample.class, "PrintPreview24.gif"));
} catch (java.io.IOException e) {
System.err.println("Cannot load PrintPreview24.gif");
icon = null;
}
initPrinting();
Action action = new AbstractAction("Print...", icon) {
Override
public void actionPerformed(ActionEvent event) {
printPreview();
}
};
menu.add(action);
}
menu.addSeparator();
menu.add(exitAction);
return menu;
}
private JMenu createProjectChooserMenu(JMenu menu) {
ButtonGroup group = new ButtonGroup();
for (final String projectLabel : allProjects) {
String labelWithoutDirectory = projectLabel.substring(projectLabel.lastIndexOf('/') + 1);
JRadioButtonMenuItem item = new JRadioButtonMenuItem(labelWithoutDirectory);
item.setSelected(projectLabel.equals(project));
item.addItemListener(new ItemListener() {
Override
public void itemStateChanged(ItemEvent event) {
if (((JRadioButtonMenuItem) event.getSource()).isSelected()) {
loadProject(projectLabel);
}
}
});
group.add(item);
menu.add(item);
}
return menu;
}
private JMenu createSelectableElementsMenu() {
JMenu menu = new JMenu("Selectable Elements");
{
JCheckBoxMenuItem item = new JCheckBoxMenuItem("X Scale");
item.setSelected(xScaleSelectable);
item.addItemListener(new ItemListener() {
Override
public void itemStateChanged(ItemEvent event) {
boolean checked = ((JCheckBoxMenuItem) event.getSource()).isSelected();
setXScaleSelectable(checked);
}
});
menu.add(item);
}
{
JCheckBoxMenuItem item = new JCheckBoxMenuItem("Y Scale");
item.setSelected(yScaleSelectable);
item.addItemListener(new ItemListener() {
Override
public void itemStateChanged(ItemEvent event) {
boolean checked = ((JCheckBoxMenuItem) event.getSource()).isSelected();
setYScaleSelectable(checked);
}
});
menu.add(item);
}
return menu;
}
private JMenu createNavigationModeMenu() {
JMenu menu = new JMenu("Navigation Mode");
ButtonGroup group = new ButtonGroup();
IlvChartAreaNavigationMode[] modes = { IlvChartCycleSelectInteractor.TRAVERSE_ALL,
IlvChartCycleSelectInteractor.BY_LEVEL };
String[] labels = { "Traverse all", "By level" };
for (int i = 0; i < modes.length; i++) {
final IlvChartAreaNavigationMode mode = modes[i];
JRadioButtonMenuItem item = new JRadioButtonMenuItem(labels[i]);
item.setSelected(interactor.getMode() == mode);
item.addItemListener(new ItemListener() {
Override
public void itemStateChanged(ItemEvent event) {
if (((JRadioButtonMenuItem) event.getSource()).isSelected()) {
// We cannot change the mode of a IlvChartCycleSelectInteractor.
// Instead, we have to create a new instance.
chart.removeInteractor(interactor);
interactor = createInteractor(mode);
chart.addInteractor(interactor);
chart.repaint();
}
}
});
group.add(item);
menu.add(item);
}
return menu;
}
private JMenu createRenderingMenu() {
JMenu menu = new JMenu("Selection Rendering");
ButtonGroup group = new ButtonGroup();
int[] renderingModes = { IlvChartAreaSelectionManager.SHOW_HANDLES, IlvChartAreaSelectionManager.SHOW_HIGHLIGHT };
String[] labels = { "Handles", "Highlight" };
for (int i = 0; i < renderingModes.length; i++) {
final int renderingMode = renderingModes[i];
JRadioButtonMenuItem item = new JRadioButtonMenuItem(labels[i]);
item.setSelected(selectionManager.getRenderingMode() == renderingMode);
item.addItemListener(new ItemListener() {
Override
public void itemStateChanged(ItemEvent event) {
if (((JRadioButtonMenuItem) event.getSource()).isSelected()) {
selectionManager.setRenderingMode(renderingMode);
chart.repaint();
}
}
});
group.add(item);
menu.add(item);
}
return menu;
}
// ============================== Main Program ==============================
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
Override
public void run() {
JFrame frame = new JFrame("Accessibility in a Chart");
AccessibilityDemo demo = new AccessibilityDemo();
demo.init(frame.getContentPane());
demo.setFrameGeometry(800, 600, true);
frame.setVisible(true);
}
});
}
}