/*
* Copyright (c) 2007 BUSINESS OBJECTS SOFTWARE LIMITED
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of Business Objects nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* DrawTest.java
* Creation date: July 4, 2005.
* By: Richard Webster
*/
package org.openquark.cal;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.Collection;
import java.util.Vector;
import javax.swing.DefaultListCellRenderer;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import org.openquark.cal.compiler.CompilerMessage;
import org.openquark.cal.compiler.CompilerMessageLogger;
import org.openquark.cal.compiler.MessageLogger;
import org.openquark.cal.compiler.ModuleName;
import org.openquark.cal.compiler.QualifiedName;
import org.openquark.cal.compiler.Scope;
import org.openquark.cal.compiler.SourceModel;
import org.openquark.cal.compiler.SourceModel.Expr;
import org.openquark.cal.compiler.io.EntryPointSpec;
import org.openquark.cal.runtime.CALExecutorException;
import org.openquark.cal.runtime.ExecutionContext;
import org.openquark.cal.services.BasicCALServices;
import org.openquark.cal.services.GemCompilationException;
import org.openquark.cal.services.GemEntity;
import org.openquark.util.BusinessObjectsException;
/**
* Test for CAL drawing functions.
*/
public class DrawTest extends JFrame {
private static final long serialVersionUID = -5255424946932404551L;
/** CAL service for running code, looking up gems, etc.... */
private final CALServicesHelper calHelper;
/** The current drawing function. */
private Expr currentDrawExpr = Expr.makeGemCall(QualifiedName.make("Cal.Test.Experimental.Graphics.Drawing_Tests", "drawTest1"));
/**
* DrawTest constructor.
*/
DrawTest() throws BusinessObjectsException {
super("Draw Test");
this.calHelper = new CALServicesHelper();
this.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent we) {
System.exit(0);
}
});
// Get the available drawing gems and display these in a combo box.
Collection<GemEntity> drawingGems = calHelper.findGemsOfType("Cal.Experimental.Graphics.Drawing.Graphics -> Cal.Experimental.Graphics.Drawing.Graphics");
final JComboBox drawFnCombo = new JComboBox(new Vector<GemEntity>(drawingGems));
drawFnCombo.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
GemEntity gemEntity = (GemEntity) drawFnCombo.getSelectedItem();
currentDrawExpr = Expr.makeGemCall(gemEntity.getName());
repaint();
}
});
drawFnCombo.setRenderer(new DefaultListCellRenderer() {
private static final long serialVersionUID = -2433581223714718290L;
@Override
public Component getListCellRendererComponent(
JList list,
Object value,
int index,
boolean isSelected,
boolean cellHasFocus) {
JLabel label = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
GemEntity gemEntity = (GemEntity) value;
label.setText(gemEntity.getName().getQualifiedName());
return label;
}
});
// Set the initial drawing gem.
if (drawingGems.isEmpty()) {
throw new BusinessObjectsException("No drawing gems are available.");
}
GemEntity initialDrawGem = drawingGems.iterator().next();
currentDrawExpr = Expr.makeGemCall(initialDrawGem.getName());
this.getContentPane().setLayout(new BorderLayout());
this.getContentPane().add(drawFnCombo, BorderLayout.NORTH);
this.getContentPane().add(new DrawPanel());
this.addWindowListener(new WindowAdapter(){});
}
/**
* Main method for test application.
*/
public static void main(String[] args) {
try {
JFrame frame = new DrawTest();
frame.setSize(400, 400);
frame.setVisible(true);
}
catch (Exception e) {
e.printStackTrace();
System.exit(1);
}
}
/**
* A panel to draw the test output.
*/
private class DrawPanel extends JPanel {
private static final long serialVersionUID = -2535389023763350640L;
/**
* @see java.awt.Component#paint(java.awt.Graphics)
*/
@Override
public void paint(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
g2.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
super.paint(g);
try {
g2 = (Graphics2D) calHelper.runCode(currentDrawExpr, new Object[] { g2 });
}
catch (BusinessObjectsException e) {
e.printStackTrace();
}
}
}
/**
* A wrapper around the cal services to provide additional functionality.
*/
private static class CALServicesHelper {
/** The run module for code common to all users. */
private static final ModuleName COMMON_RUN_MODULE = ModuleName.make("Cal.Test.Experimental.Graphics.Drawing_Tests");
/** A property for overriding the default CAL workspace. */
private static final String WORKSPACE_FILE_PROPERTY = "experimental.drawing_test.workspace";
/** The CAL workspace file. */
private static final String DEFAULT_WORKSPACE_FILE = "cal.libraries.test.cws";
/** The default workspace client id. */
private static final String DEFAULT_WORKSPACE_CLIENT_ID = null;
/** The CAL services. */
private final BasicCALServices calServices;
private ExecutionContext executionContext;
/**
* CALServicesHelper constructor.
*/
public CALServicesHelper() throws BusinessObjectsException {
boolean compilationSuccessful = false;
CompilerMessageLogger messageLogger = new MessageLogger();
BasicCALServices newCalServices = null;
try {
newCalServices = BasicCALServices.make (WORKSPACE_FILE_PROPERTY,
DEFAULT_WORKSPACE_FILE, DEFAULT_WORKSPACE_CLIENT_ID);
if (newCalServices != null) {
// If there's a local cache, the workspace will use it, rather than the modules in the repo
// ...so if the cache is out of date, now's the time to synch
compilationSuccessful = newCalServices.compileWorkspace(null, messageLogger);
}
}
catch (Throwable t) {
t.printStackTrace();
newCalServices = null;
}
if ((newCalServices == null) || !compilationSuccessful){
String message = "";
if (messageLogger.getNErrors() > 0) {
StringBuffer msg = new StringBuffer("Failed to compile workspace:");
for (final CompilerMessage cm : messageLogger.getCompilerMessages()) {
msg.append("\n");
msg.append(cm);
}
message = msg.toString();
System.err.println(message);
}
throw new BusinessObjectsException(message);
}
this.calServices = newCalServices;
// Get an execution context.
this.executionContext = calServices.getWorkspaceManager().makeExecutionContextWithDefaultProperties();
}
/**
* Returns a collection of gems which have the specified type signature.
* @param typeName the type signature of the gems to be found
* @return a collection of the matching gems
*/
public Collection<GemEntity> findGemsOfType(String typeName) {
return calServices.findGemsOfType(COMMON_RUN_MODULE, typeName, true);
}
/**
* Runs the a function with the specified arguments.
* The result will be marshalled to Java using the default output policy.
*/
public Object runCode(Expr code, Object[] arguments) throws BusinessObjectsException {
final String RUN_TARGET_NAME = "runDrawTestCode";
final ModuleName TARGET_MODULE_NAME = ModuleName.make(COMMON_RUN_MODULE + "_Temp"); // TODO: allow this to be specified...
arguments = fixUpArgumentValues(arguments);
try {
SourceModel.FunctionDefn functionDefn = SourceModel.FunctionDefn.Algebraic.make(RUN_TARGET_NAME,
Scope.PUBLIC,
new SourceModel.Parameter[0],
code);
EntryPointSpec entryPointSpec = calServices.addNewModuleWithFunction(TARGET_MODULE_NAME, functionDefn);
Object result = calServices.runFunction(entryPointSpec, executionContext, arguments);
return result;
}
catch (CALExecutorException e) {
throw new BusinessObjectsException(e);
}
catch (GemCompilationException e) {
throw new BusinessObjectsException(e);
}
}
/**
* Replace any InternalCalValueHolder objects with the actual CalValues.
*/
private Object[] fixUpArgumentValues(Object[] arguments) {
if (arguments == null) {
arguments = new Object[0];
} else {
// Make a copy of the array.
arguments = arguments.clone();
}
return arguments;
}
}
}