blob: 3592736a1860aab0c8bea5e2b99d6b4d70addd5c [file] [log] [blame]
package org.eclipse.stem.ui.widgets;
/*******************************************************************************
* Copyright (c) 2010 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.stem.ui.Activator;
import org.eclipse.stem.ui.wizards.Messages;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
public class MatrixEditorWidget extends Composite {
public enum STATUS {
OKAY,
INVALID_VALUE;
}
private short rows;
short dynrows;
short columns;
private String [] rowNames, colNames;
private boolean fixedSize;
private Color colRowHeaderColumns = new Color(null, 200, 200, 200);
private Color textBackgroundColumns = new Color(null, 255, 255, 255);
private Color textBorderColor = new Color(null, 0, 0, 0);
ArrayList<Text> textWidgets = new ArrayList<Text>();
ArrayList<String> textValues = new ArrayList<String>();
MatrixEditorValidator validator = null;
private ArrayList<MatrixEditorListener> listeners = new ArrayList<MatrixEditorListener>();
Label status = null;
Button currentPlusButton;
Button currentMinusButton;
ArrayList<Label>emptyLabels = new ArrayList<Label>();
/**
* Create a new Matrix Editor Widget
*
* @param parent
* @param rows
* @param columns
* @param rownames
* @param columnNames
*/
public MatrixEditorWidget(Composite parent, int style, short rows, short columns, String[] rownames, String [] columnNames, String []existingVals,boolean fixedSize, MatrixEditorValidator validator) {
super(parent, style);
this.rows = rows;
this.dynrows = rows; // dynamically adjusted number of rows
this.columns = columns;
this.rowNames = rownames;
this.colNames = columnNames;
this.validator = validator;
this.fixedSize = fixedSize;
createContents(existingVals);
}
protected void createContents(String []existingVals) {
setBackground(new Color(null, 255, 255, 255));
GridLayout layout = new GridLayout();
layout.numColumns = columns+1;
layout.horizontalSpacing = 0;
layout.verticalSpacing = 0;
layout.marginBottom = 0;
layout.marginLeft = 0;
layout.marginRight = 0;
layout.marginTop = 0;
this.setLayout(layout);
// The status row for error messages etc.
status = new Label(this, SWT.NONE);
status.setForeground(new Color(null, 255, 0, 0));
GridData sgd = new GridData();
if((rowNames != null && rowNames.length > 0) || fixedSize == false)
sgd.horizontalSpan = columns+1;
else
sgd.horizontalSpan = columns;
status.setLayoutData(sgd);
status.setText("");
if((rowNames != null && rowNames.length > 0) || fixedSize == false) {
Label lab = new Label(this, SWT.NONE);
lab.setText("");
GridData gd = new GridData();
//gd.horizontalAlignment = GridData.FILL;
//gd.grabExcessHorizontalSpace = true;
lab.setLayoutData(gd);
}
// Create column headers
if(colNames!=null) for(int c=0;c<colNames.length;++c) {
Label lab = new Label(this, SWT.BORDER);
lab.setText(colNames[c]);
GridData gd = new GridData();
gd.horizontalAlignment = GridData.FILL;
gd.grabExcessHorizontalSpace = true;
gd.grabExcessVerticalSpace = false;
gd.horizontalIndent = 1;
gd.verticalIndent = 1;
gd.minimumWidth = 128;
lab.setLayoutData(gd);
lab.setBackground(colRowHeaderColumns);
addBorder(lab);
}
// Create the text
for(int r=0;r<rows;++r) {
if((rowNames != null && rowNames.length > r) || fixedSize == false) {
Label lab = new Label(this, SWT.BORDER);
if(fixedSize)
lab.setText(rowNames[r]);
else
lab.setText("");
GridData gd = new GridData();
gd.horizontalAlignment = GridData.FILL;
//gd.grabExcessHorizontalSpace = true;
lab.setLayoutData(gd);
if(fixedSize)lab.setBackground(colRowHeaderColumns);
else lab.setBackground(new Color(null, 255, 255, 255));
if(fixedSize)addBorder(lab);
emptyLabels.add(lab);
}
for(int c=0;c<columns;++c) {
Text t = addTextField();
int index = r*columns+c;
if(existingVals != null && existingVals.length > index)
t.setText(existingVals[index]);
}
} // for each row
if(fixedSize == false) {
currentPlusButton = addPlusButton();
currentMinusButton = addMinusButton();
if(rows < 2)currentMinusButton.setEnabled(false);
}
}
Text addTextField() {
final Text text = new Text(this, SWT.NONE);
text.setBackground(textBackgroundColumns);
text.setForeground(textBorderColor);
GridData gd = new GridData();
gd.horizontalAlignment = GridData.FILL;
gd.grabExcessHorizontalSpace = false;
gd.grabExcessVerticalSpace = false;
gd.horizontalIndent = 1;
gd.verticalIndent = 1;
text.setLayoutData(gd);
addBorder(text);
textWidgets.add(text);
textValues.add("");
text.addModifyListener(new ModifyListener() {
public void modifyText(ModifyEvent arg0) {
boolean problem = false;
for(Text t:MatrixEditorWidget.this.textWidgets) {
String val = t.getText().trim();
if(!validator.validateValue(val)) {
problem = true;
status.setText(MessageFormat.format(org.eclipse.stem.ui.wizards.Messages.getString("Matrix.invalid.value"), val));
status.pack(true);
break;
}
}
if(!problem && !validator.validateAllValues(MatrixEditorWidget.this.textWidgets)) {
problem = true;
status.setText(org.eclipse.stem.ui.wizards.Messages.getString("Matrix.invalid.sum"));
status.pack(true);
}
if(!problem) {
status.setText("");
status.pack(true);
fireEvent(new MatrixEditorEvent(STATUS.OKAY));
} else fireEvent(new MatrixEditorEvent(STATUS.INVALID_VALUE));
int index = textWidgets.indexOf(text);
textValues.set(index, text.getText());
}
});
return text;
}
Button addPlusButton() {
Button plusButton = new Button(this, SWT.NONE);
GridData gd = new GridData();
plusButton.setText(Messages.getString("Matrix.dialog.plus"));
plusButton.setLayoutData(gd);
plusButton.addSelectionListener(new SelectionListener() {
public void widgetSelected(SelectionEvent arg0) {
currentMinusButton.setEnabled(true);
++dynrows;
Label lab = new Label(MatrixEditorWidget.this, SWT.BORDER);
lab.setText("");
GridData gd = new GridData();
gd.horizontalAlignment = GridData.FILL;
lab.setLayoutData(gd);
lab.setBackground(new Color(null, 255, 255, 255));
emptyLabels.add(lab);
Text lastText = null;
for(int i=0;i<columns;++i) lastText = addTextField();
currentPlusButton.moveBelow(lastText);
currentMinusButton.moveBelow(currentPlusButton);
lastText.setText(lastText.getText()); // Invoke validator
MatrixEditorWidget.this.layout(true);
MatrixEditorWidget.this.pack(true);
MatrixEditorWidget.this.getParent().pack(true);
}
public void widgetDefaultSelected(SelectionEvent arg0) {
// TODO Auto-generated method stub
}
});
return plusButton;
}
Button addMinusButton() {
Button minusButton = new Button(this, SWT.NONE);
GridData gd = new GridData();
minusButton.setText(Messages.getString("Matrix.dialog.minus"));
minusButton.setLayoutData(gd);
minusButton.addSelectionListener(new SelectionListener() {
public void widgetSelected(SelectionEvent arg0) {
for(int i=(dynrows-1)*columns;i<(dynrows-1)*columns+columns;++i) textWidgets.get(i).dispose();
for(int i=0;i<columns;++i) {textWidgets.remove((dynrows-1)*columns);textValues.remove((dynrows-1)*columns);}
Label elab = emptyLabels.get(dynrows-1);
Text lastText = textWidgets.get((dynrows-2)*columns+columns-1);
currentPlusButton.moveBelow(lastText);
currentMinusButton.moveBelow(currentPlusButton);
elab.dispose();
emptyLabels.remove(elab);
--dynrows;
if(dynrows == 1)
currentMinusButton.setEnabled(false);
lastText.setText(lastText.getText()); // Invoke validator
MatrixEditorWidget.this.layout(true);
MatrixEditorWidget.this.pack(true);
MatrixEditorWidget.this.getParent().pack(true);
}
public void widgetDefaultSelected(SelectionEvent arg0) {
// TODO Auto-generated method stub
}
});
return minusButton;
}
private void addBorder(final Control t) {
// Add a border around the text box
t.addPaintListener( new PaintListener() {
public void paintControl(PaintEvent evt) {
Point s = t.getSize();
Color c = evt.gc.getForeground();
evt.gc.setForeground(t.getDisplay().getSystemColor(SWT.COLOR_BLACK));
evt.gc.drawRectangle(0,0,s.x-1,s.y-1);
evt.gc.setForeground(c);
}
} );
}
public void addListener(MatrixEditorListener listener) {this.listeners.add(listener);}
void fireEvent(MatrixEditorEvent evt) {for(MatrixEditorListener l:listeners) l.eventReceived(evt);}
public ArrayList<String> getTextValues() {
return this.textValues;
}
public static void main(String [] args) {
Display display = new Display();
Shell shell = new Shell(display);
FillLayout fl = new FillLayout();
fl.type = SWT.VERTICAL;
shell.setLayout(fl);
// String [] rn = {"AGE0-10", "AGE11-35","AGE36-100"};
// String [] cn = {"AGE0-10", "AGE11-35","AGE36-100"};
// MatrixEditorWidget m = new MatrixEditorWidget(shell, SWT.PUSH, (short)3, (short)3, rn, cn, true, new MatrixEditorValidator() {
String [] cn = {"Population Group"};
MatrixEditorWidget m = new MatrixEditorWidget(shell, SWT.PUSH, (short)1, (short)1, null, cn, null, false, new MatrixEditorValidator() {
public boolean validateValue(String val) {
if(val == null || val.trim().equals("")) return true;
try {
Double.parseDouble(val.trim());
} catch(NumberFormatException nfe) {
return false;
}
return true;
}
@Override
public boolean validateAllValues(List<Text> vals) {
return true;
}
});
m.addListener(new MatrixEditorWidget.MatrixEditorListener() {
public void eventReceived(MatrixEditorEvent event) {
if(event.status == MatrixEditorWidget.STATUS.OKAY) Activator.logInformation("okay");
else Activator.logInformation("invalid");
}
});
shell.pack();
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) display.sleep();
}
}
public static class MatrixEditorEvent {
public STATUS status;
public MatrixEditorEvent(STATUS s) {this.status = s;}
}
public interface MatrixEditorListener {
public void eventReceived(MatrixEditorEvent event);
}
public interface MatrixEditorValidator {
/**
* Validate. Return false if the value is invalid
* @param val
* @return False if invalid
*/
public boolean validateValue(String val);
/**
* Validate all field
* @param val
* @return False if invalid
*/
public boolean validateAllValues(List<Text> vals);
}
}