package org.drools.guvnor.client.factmodel;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.drools.guvnor.client.common.FormStylePopup;
import org.drools.guvnor.client.common.ImageButton;
import org.drools.guvnor.client.common.LoadingPopup;
import org.drools.guvnor.client.common.SmallLabel;
import org.drools.guvnor.client.messages.Constants;
import org.drools.guvnor.client.packages.SuggestionCompletionCache;
import org.drools.guvnor.client.rpc.RuleAsset;
import org.drools.guvnor.client.rpc.RuleContentText;
import org.drools.guvnor.client.ruleeditor.DefaultRuleContentWidget;
import org.drools.guvnor.client.ruleeditor.RuleViewer;
import org.drools.guvnor.client.ruleeditor.SaveEventListener;
import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.ChangeListener;
import com.google.gwt.user.client.ui.ClickListener;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.HasVerticalAlignment;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.KeyboardListener;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.user.client.ui.FlexTable.FlexCellFormatter;
import com.gwtext.client.util.Format;
import com.gwtext.client.widgets.form.FormPanel;
/**
* The editor for fact models (drl declared types).
*
* @author Michael Neale
*/
public class FactModelWidget extends Composite
implements
SaveEventListener {
private RuleAsset asset;
private VerticalPanel layout;
private int editingFact = -1;
private static Constants constants = ((Constants) GWT.create( Constants.class ));
private static Map<String, String> TYPE_DESCRIPTIONS = new HashMap<String, String>() {
private static final long serialVersionUID = 6673195099559934035L;
{
put( "Integer",
constants.WholeNumberInteger() );
put( "Boolean",
constants.TrueOrFalse() );
put( "java.util.Date",
constants.Date() );
put( "java.math.BigDecimal",
constants.DecimalNumber() );
put( "String",
constants.Text() );
}
};
public FactModelWidget(RuleAsset asset,
RuleViewer viewer) {
this( asset );
}
public FactModelWidget(final RuleAsset asset) {
this.asset = asset;
this.layout = new VerticalPanel();
if ( asset.content instanceof RuleContentText ) {
layout.add( new DefaultRuleContentWidget( asset ) );
} else {
//loadTestData(asset);
if ( asset.content == null ) {
asset.content = new FactModels();
}
renderEditor();
}
layout.setWidth( "100%" );
initWidget( layout );
setStyleName( "model-builder-Background" ); //NON-NLS
}
private void renderEditor() {
layout.clear();
final FactModels m = (FactModels) asset.content;
String factHeaderStyle = "modeller-fact-TypeHeader"; //NON-NLS
for ( int i = 0; i < m.models.size(); i++ ) {
final FactMetaModel mm = (FactMetaModel) m.models.get( i );
FormPanel config = new FormPanel();
config.setTitle( mm.name );
config.setCollapsible( true );
config.setCollapsed( !(editingFact == i) );
FlexTable tb = new FlexTable();
config.add( tb );
tb.setStyleName( "modeller-fact-pattern-Widget" ); //NON-NLS
tb.setWidth( "100%" );
//layout.add(tb);
layout.add( config );
final HorizontalPanel headerPanel = new HorizontalPanel();
//headerPanel.add(new HTML("<b><small>" + mm.name + "</small></b>"));
headerPanel.setVerticalAlignment( HasVerticalAlignment.ALIGN_MIDDLE );
headerPanel.add( getMovePanel( m.models,
mm,
m.models.indexOf( mm ) ) );
//ImageButton addField = new ImageButton("images/add_field_to_fact.gif");
Button addField = new Button( constants.AddField() );
addField.addClickListener( new ClickListener() {
public void onClick(Widget arg0) {
showFieldEditor( m,
mm,
null );
}
} );
headerPanel.add( addField );
Button changeName = new Button( constants.ChangeFactName() );
changeName.addClickListener( new ClickListener() {
public void onClick(Widget arg0) {
final FormStylePopup pop = new FormStylePopup();
HorizontalPanel changeName = new HorizontalPanel();
final TextBox name = new TextBox();
name.setText( mm.name );
changeName.add( name );
Button nameBut = new Button( constants.ChangeName() );
nameBut.addKeyboardListener( noSpaceListener() );
nameBut.addClickListener( new ClickListener() {
public void onClick(Widget w) {
if ( !uniqueName( name.getText(),
m.models ) ) {
Window.alert( Format.format( constants.NameTakenForModel(),
name.getText() ) );
return;
}
if ( Window.confirm( constants.ModelNameChangeWarning() ) ) {
mm.name = name.getText();
pop.hide();
renderEditor();
}
}
} );
changeName.add( nameBut );
pop.addAttribute( constants.ChangeFactName(),
changeName );
pop.show();
}
} );
headerPanel.add( changeName );
Button deleteFact = new Button( constants.Delete() );
deleteFact.addClickListener( new ClickListener() {
public void onClick(Widget arg0) {
final FormStylePopup pop = new FormStylePopup();
Button delFact = new Button( constants.Delete() );
delFact.addClickListener( new ClickListener() {
public void onClick(Widget w) {
if ( Window.confirm( constants.AreYouSureYouWantToRemoveThisFact() ) ) {
m.models.remove( mm );
pop.hide();
renderEditor();
}
}
} );
pop.addAttribute( constants.RemoveThisFactType(),
delFact );
pop.show();
}
} );
headerPanel.add( deleteFact );
tb.setWidget( 0,
0,
new VerticalPanel() {
{
add( headerPanel );
setStyleName( "fact-model-fact-edit-selections" );
setWidth( "100%" );
}
} );
FlexCellFormatter formatter = tb.getFlexCellFormatter();
formatter.setColSpan( 0,
0,
2 );
formatter.setStyleName( 0,
0,
factHeaderStyle );
formatter.setHorizontalAlignment( 0,
0,
HasHorizontalAlignment.ALIGN_LEFT );
for ( int j = 0; j < mm.fields.size(); j++ ) {
final FieldMetaModel fm = (FieldMetaModel) mm.fields.get( j );
String ms = Format.format( constants.FieldName(),
fm.name );
tb.setWidget( j + 1,
0,
new HTML( ms ) );
formatter.setHorizontalAlignment( j + 1,
0,
HasHorizontalAlignment.ALIGN_RIGHT );
HorizontalPanel type = new HorizontalPanel();
type.setVerticalAlignment( HasVerticalAlignment.ALIGN_MIDDLE );
type.add( new SmallLabel( getDesc( fm ) ) );
ImageButton del = new ImageButton( "images/delete_item_small.gif" ); //NON-NLS
del.addClickListener( new ClickListener() {
public void onClick(Widget w) {
if ( Window.confirm( Format.format( constants.AreYouSureYouWantToRemoveTheField0(),
fm.name ) ) ) {
mm.fields.remove( fm );
editingFact = m.models.indexOf( mm );
renderEditor();
}
}
} );
ImageButton edit = new ImageButton( "images/edit.gif" ); //NON-NLS
edit.addClickListener( new ClickListener() {
public void onClick(Widget arg0) {
showFieldEditor( m,
mm,
fm );
}
} );
type.add( edit );
type.add( del );
tb.setWidget( j + 1,
1,
type );
formatter.setHorizontalAlignment( j + 1,
1,
HasHorizontalAlignment.ALIGN_LEFT );
}
}
final Button addNewFact = new Button( constants.AddNewFactType() );
addNewFact.addClickListener( new ClickListener() {
public void onClick(Widget w) {
String type = Window.prompt( constants.NewType(),
constants.EnterNewTypeName() );
if ( type != null ) {
if ( uniqueName( type,
m.models ) ) {
m.models.add( new FactMetaModel( type,
new ArrayList() ) );
editingFact = m.models.size() - 1;
renderEditor();
} else {
Window.alert( Format.format( constants.TypeNameExistsWarning(),
type ) );
addNewFact.click();
}
}
}
} );
layout.add( addNewFact );
}
private VerticalPanel getMovePanel(final List< ? extends Object> list,
final Object object,
final int editingFactIndex) {
final int index = list.indexOf( object );
VerticalPanel arrows = new VerticalPanel();
ImageButton up = new ImageButton( "images/arrow-up.gif",
constants.MoveUp() );
// Topmost item can not be moved up. So hide the button.
up.setVisible( index != 0 );
up.addClickListener( new ClickListener() {
public void onClick(Widget arg0) {
Collections.swap( list,
index,
index - 1 );
if ( object instanceof FactMetaModel ) {
editingFact = index - 1;
} else {
editingFact = editingFactIndex;
}
renderEditor();
}
} );
arrows.add( up );
ImageButton down = new ImageButton( "images/arrow-down.gif",
constants.MoveDown() );
// Last item can not be moved down. So hide the button.
down.setVisible( index != (list.size() - 1) );
down.addClickListener( new ClickListener() {
public void onClick(Widget arg0) {
Collections.swap( list,
index,
index + 1 );
if ( object instanceof FactMetaModel ) {
editingFact = index + 1;
} else {
editingFact = editingFactIndex;
}
renderEditor();
}
} );
arrows.add( down );
return arrows;
}
private boolean uniqueName(String type,
List<FactMetaModel> models) {
for ( FactMetaModel m : models ) {
if ( m.name.equals( type ) ) {
return false;
}
}
return true;
}
private String getDesc(FieldMetaModel fm) {
if ( TYPE_DESCRIPTIONS.containsKey( fm.type ) ) {
return TYPE_DESCRIPTIONS.get( fm.type );
}
return fm.type;
}
/**
* Display the field editor.
*/
private void showFieldEditor(final FactModels models,
final FactMetaModel mm,
final FieldMetaModel field) {
final FormStylePopup pop = new FormStylePopup();
final TextBox fieldName = new TextBox();
final TextBox fieldType = new TextBox();
fieldName.addKeyboardListener( noSpaceListener() );
fieldType.addKeyboardListener( noSpaceListener() );
if ( field != null ) {
fieldName.setText( field.name );
fieldType.setText( field.type );
}
HorizontalPanel typeP = new HorizontalPanel();
typeP.add( fieldType );
final ListBox typeChoice = new ListBox();
typeChoice.addItem( constants.chooseType() );
for ( String k : TYPE_DESCRIPTIONS.keySet() ) {
typeChoice.addItem( TYPE_DESCRIPTIONS.get( k ),
k );
}
int idx = models.models.indexOf( mm );
for ( int i = 0; i < idx; i++ ) {
FactMetaModel mm_ = (FactMetaModel) models.models.get( i );
typeChoice.addItem( mm_.name );
}
typeChoice.setSelectedIndex( 0 );
typeChoice.addChangeListener( new ChangeListener() {
public void onChange(Widget w) {
fieldType.setText( typeChoice.getValue( typeChoice.getSelectedIndex() ) );
}
} );
typeP.add( typeChoice );
pop.addAttribute( constants.FieldNameAttribute(),
fieldName );
pop.addAttribute( constants.Type(),
typeP );
Button ok = new Button( constants.OK() );
ok.addClickListener( new ClickListener() {
public void onClick(Widget arg0) {
FieldMetaModel fld = field;
if ( field == null ) {
fld = new FieldMetaModel();
mm.fields.add( fld );
}
fld.name = fieldName.getText();
fld.type = fieldType.getText();
editingFact = models.models.indexOf( mm );
renderEditor();
pop.hide();
}
} );
pop.addAttribute( "",
ok );
pop.show();
}
private KeyboardListener noSpaceListener() {
return new KeyboardListener() {
public void onKeyDown(Widget arg0,
char arg1,
int arg2) {
}
public void onKeyPress(Widget w,
char c,
int i) {
if ( c == ' ' ) {
((TextBox) w).cancelKey();
}
}
public void onKeyUp(Widget arg0,
char arg1,
int arg2) {
}
};
}
public void onAfterSave() {
LoadingPopup.showMessage( constants.RefreshingModel() );
SuggestionCompletionCache.getInstance().loadPackage( this.asset.metaData.packageName,
new Command() {
public void execute() {
LoadingPopup.close();
}
} );
}
public void onSave() {
//not needed.
}
}