2013-03-16 6 views
2

Je dois créer une table qui présente les caractéristiques suivantes:GWT Tableau affichage des données financières

  • 13 colonnes: 1ère colonne contient du texte non modifiable, les autres contiennent des valeurs numériques qui peuvent être modifiables ou non en fonction de la index de ligne
  • 3 lignes: 1er rang contient int, 2ème ligne contient deux formatés comme #, ## 0.00 et la 3ème ligne contient deux formatés comme #, # 0.0%

le tableau doit aussi comporter les éléments suivants options de validation des données pour les cellules modifiables:

  • booléen positif: true si les nombres positifs sont autorisés
  • négatif booléenne: true si les nombres négatifs sont autorisés
  • booléen maxEnabled: true si la valeur de la cellule doit être inférieure à maxValue
  • à double maxValue : la valeur maximale autorisée (si maxEnabled == true;)

J'ai réussi à la table pour se comporter comme je veux, les seules choses que je ne suis pas parvenu à se mettre au travail sont les suivants:

  • Après une entrée réussie, formater la nouvelle valeur en utilisant mon format numérique
  • Obtenez la table pour redessiner lorsque l'utilisateur clique sur le bouton redessiner

Toute aide qui serait le plus apprécié.

Voici le code que je utilise:

Les cellules, les colonnes et FieldUpdater

public class DataCell2 extends EditTextCell{ 
private TableDTO tableData; 

public DataCell2(TableDTO tableData){ 
    this.tableData=tableData; 
} 

@Override 
public void render(com.google.gwt.cell.client.Cell.Context context, String value, SafeHtmlBuilder sb){ 
    super.render(context,value,sb); 

} 

@Override 
public void onBrowserEvent(Context context, Element parent, String value, NativeEvent event, 
     ValueUpdater<String> valueUpdater){ 

    // If cell non editable exit 
    if(!isEditable(context)){ 
     return; 
    }else{ 
     super.onBrowserEvent(context,parent,value,event,valueUpdater); 

    } 

} 

private boolean isEditable(Context context){ 
    int row=context.getIndex(); 
    // int column=context.getColumn(); 
    return tableData.isRowEditable(row); 
} 




public class DataColumn2<DataCell2> extends Column<RowDTO,String>{ 
public int col; 

public DataColumn2(int col, Cell<String> cell){ 
    super(cell); 
    this.col=col; 
} 

@Override 
public String getValue(RowDTO object){ 
    // TODO Auto-generated method stub 
    return null; 
} 




public class LabelColumn2 extends TextColumn<RowDTO>{ 
public LabelColumn2(){ 
    super(); 
} 

@Override 
public String getValue(RowDTO object){ 
    return object.getLabel(); 
} 





public class DataUpdater2 implements FieldUpdater<RowDTO,String>{ 

private CellTable<RowDTO> table; 
private DataCell2 dataCell; 
// private ProvidesKey<DataItem> KEY_PROVIDER; 
protected int col=0; 

public DataUpdater2(int col, CellTable<RowDTO> table, DataCell2 dataCell){ 
    this.dataCell=dataCell; 
    this.table=table; 
    this.col=col; 
} 

public void clear(int index){ 
    // Clear invalid input 
    dataCell.clearViewData(index); 
    // Redraw the table. 
    table.redraw(); 
} 

@Override 
public void update(int index, RowDTO object, String value){ 
    // TODO Auto-generated method stub 

} 

La classe ligne qui contient une étiquette et la classe rowData et sa validation de données

public class RowDTO{ 
private final int index; 
private Vector<Object> rowData; 
private RowValidation validation; 
private boolean editable; 

public RowDTO(int index, Vector<Object> rowData, int type){ 
    this.index=index; 
    this.rowData=rowData; 
    this.validation=buildValidation(index,type); 
} 

public int getIndex(){ 
    return index; 
} 

public Vector<Object> getRowData(){ 
    return rowData; 
} 

public RowValidation getValidation(){ 
    return validation; 
} 

public String getRowData(int column){ 
    return rowData.get(column).toString(); 
} 

public String getLabel(){ 
    return rowData.get(0).toString(); 
} 

public void setRowData(int column, String newVal){ 
    this.rowData.set(column,newVal); 
} 

/** Assign a vaildation and editing strategy based on the table type and the row */ 
private RowValidation buildValidation(int index, int type){ 
    switch(type){ 
     case TableDTO.FIXEDCOST: 
      switch(index){ 
       case 0: 
        editable=true; 
        return RowValidation.getPositiveDouble(); 
       case 1: 
        editable=true; 
        return RowValidation.getPositiveInt(); 
       case 2: 
        editable=true; 
        return RowValidation.getPositivePercent(); 
       default: 
        editable=true; 
        return RowValidation.getPositiveDouble(); 
      } 
     default: 
      editable=true; 
      return RowValidation.getPositiveDouble(); 
    } 
} 

public boolean isEditable(){ 
    return editable; 
} 




public class RowValidation{ 

/* Is double (else is int) */ 
private boolean digit=true; 
/* Values permitted */ 
private boolean positive=true; 
private boolean negative=true; 
private boolean zero=true; 
private boolean maxEnabled=false; 
private double maxValue=2; 

/** Default constructor: double number, can be positive, negative or zero, no maximum */ 
public RowValidation(){} 

/** 
* @param digit: true if double, false if int 
* @param positive: true if can be positive 
* @param negative: true if can be negative 
* @param zero: true if can be zero 
* @param maxEnabled: true if can has maximum 
* @param maxValue: maximum value if has maximum 
*/ 
public RowValidation(boolean digit, boolean positive, boolean negative, boolean zero, boolean maxEnabled, 
     double maxValue){ 
    this.digit=digit; 
    this.positive=positive; 
    this.negative=negative; 
    this.zero=zero; 
    this.maxEnabled=maxEnabled; 
    this.maxValue=maxValue; 
} 

public boolean isDigit(){ 
    return digit; 
} 

public boolean isPositive(){ 
    return positive; 
} 

public boolean isNegative(){ 
    return negative; 
} 

public boolean isZero(){ 
    return zero; 
} 

public boolean isMaxEnabled(){ 
    return maxEnabled; 
} 

public double getMaxValue(){ 
    return maxValue; 
} 

/** Positive or zero Integer */ 
public static RowValidation getPositiveInt(){ 
    return new RowValidation(false,true,false,true,false,2); 
} 

/** Positive or zero double */ 
public static RowValidation getPositiveDouble(){ 
    return new RowValidation(true,true,false,true,false,2); 
} 

/** Positive double belonging to [0,1] */ 
public static RowValidation getPositivePercent(){ 
    return new RowValidation(true,true,false,true,true,1); 
} 

La classe Table qui contient une liste de lignes:

public class TableDTO{ 
public static final int FIXEDCOST=0; 
private ArrayList<RowDTO> rows; 
private Vector<String> headers; 

public TableDTO(Vector<Vector<Object>> roughData, Vector<String> headers, int type){ 
    this.headers=headers; 
    rows=buildRows(roughData,type); 
} 

private ArrayList<RowDTO> buildRows(Vector<Vector<Object>> roughData, int type){ 
    int nb=roughData.size(); 
    ArrayList<RowDTO> result=new ArrayList<RowDTO>(nb); 
    for(int i=0;i<nb;i++){ 
     result.add(new RowDTO(i,roughData.get(i),type)); 
    } 

    return result; 
} 

public ArrayList<RowDTO> getRows(){ 
    return rows; 
} 

public RowDTO getRow(int index){ 
    return rows.get(index); 
} 

public boolean isRowEditable(int index){ 
    return getRow(index).isEditable(); 
} 

public String getHeader(int column){ 
    return headers.get(column); 
} 

Le panneau qui tient tout ensemble

public class TablePanel extends Composite{ 
private VerticalPanel main=new VerticalPanel(); 
private HorizontalPanel btns=new HorizontalPanel(); 
private Button commitButton=new Button("commit"); 
private Button redrawButton=new Button("redraw"); 
private List<DataChange> pendingChanges=new ArrayList<DataChange>(); 
private CellTable<RowDTO> table; 
private TableDTO dataDTO; 
/** 
* The key provider that allows us to identify data points even if a field changes. 
*/ 
private static final ProvidesKey<RowDTO> KEY_PROVIDER=new ProvidesKey<RowDTO>(){ 
    @Override 
    public Object getKey(RowDTO item){ 
     return item.getIndex(); 
    } 
}; 

@SuppressWarnings({"unchecked"}) 
public TablePanel(Vector<Vector<Object>> roughData, Vector<String> headers, int type){ 
    dataDTO=new TableDTO(roughData,headers,type); 

    // Create a CellTable with a key provider. 
    table=new CellTable<RowDTO>(KEY_PROVIDER); 
    table.setKeyboardSelectionPolicy(KeyboardSelectionPolicy.ENABLED); 

    // Label 
    LabelColumn2 nameColumn=new LabelColumn2(); 
    table.addColumn(nameColumn,"Label"); 

    redrawButton.addClickHandler(new ClickHandler(){ 
     @Override 
     public void onClick(ClickEvent event){ 
      // Delete temporary changes 
      pendingChanges.clear(); 
      // Redraw table 
      table.setRowData(0,dataDTO.getRows()); 
      table.redraw(); 
     } 
    }); 
    commitButton.addClickHandler(new ClickHandler(){ 
     @Override 
     public void onClick(ClickEvent event){ 
      // Commit the changes. 
      for(DataChange pendingChange: pendingChanges){ 
       pendingChange.doCommit(); 
      } 
      pendingChanges.clear(); 

      // Push the changes to the views. 
      table.setRowData(0,dataDTO.getRows()); 

      table.redraw(); 
     } 
    }); 

    // myData.getCol(); 
    for(int i=1;i<5;i++){ 
     // Create cell 
     DataCell2 dataCell=new DataCell2(dataDTO); 
     // Add a column for every data points. 

     @SuppressWarnings({"rawtypes"}) 
     DataColumn2<DataCell2> dataColumn=new DataColumn2(i,dataCell){ 
      @Override 
      public String getValue(RowDTO object){ 
       String newVal=object.getRowData(col); 
       return format(object,newVal); 
      } 
     }; 

     // Add a field updater to be notified when the user enters a new value. 
     dataColumn.setFieldUpdater(new DataUpdater2(i,table,dataCell){ 

      @Override 
      public void update(int index, RowDTO object, String value){ 
       // Called when the user changes the value. 
       if(isValidValue(index,value)){ 
        pendingChanges.add(new DataChange(this.col,object,value)); 

        // TODO kill once ok 
        int s=pendingChanges.size(); 
        String ss=object.getRowData(col); 
        Window.alert("Value in myData="+ss+", nb pending changes="+s); 
       }else{ 
        /* clear the view data and redraw the table */ 
        this.clear(index); 
        // Alert user: TODO restablish once ok 
        // Window.alert("Invalid input"); 

        // TODO kill once ok 
        int s=pendingChanges.size(); 
        String ss=object.getRowData(col); 
        Window.alert("Value in myData="+ss+", nb pending changes="+s); 
       } 
      } 
     }); 
     table.addColumn(dataColumn,dataDTO.getHeader(i)); 

    } 

    // Set the total row count. This isn't strictly necessary, but it affects 
    // paging calculations, so its good habit to keep the row count up to date. 
    table.setRowCount(dataDTO.getRows().size(),true); 

    // Push the data into the widget. 
    table.setRowData(0,dataDTO.getRows()); 

    // Add it to the root panel. 
    main.add(table); 
    btns.add(commitButton); 
    btns.add(redrawButton); 
    main.add(btns); 
    initWidget(main); 
} 

/* Formatting */ 

private String format(RowDTO row, String value){ 
    RowValidation rv=row.getValidation(); 
    if(rv.isDigit()){ 
     if(rv.isMaxEnabled()){ 
      return formatAsPercent(value); 

     }else{ 
      return formatAsDouble(value); 
     } 
    }else{ 
     return formatAsInt(value); 
    } 
} 

private static String formatAsDouble(String val){ 
    try{ 
     double value=Double.parseDouble(val); 
     NumberFormat fmt=NumberFormat.getDecimalFormat(); 
     fmt.overrideFractionDigits(2,2); 
     String formatted=fmt.format(value); 
     return formatted; 
    }catch(NumberFormatException e){ 
     // TODO 
     return val; 
    } 
} 

private static String formatAsInt(String val){ 
    try{ 
     double value=Double.parseDouble(val); 
     NumberFormat fmt=NumberFormat.getDecimalFormat(); 
     fmt.overrideFractionDigits(0,0); 
     String formatted=fmt.format(value); 
     return formatted; 
    }catch(NumberFormatException e){ 
     // TODO 
     return val; 
    } 
} 

private static String formatAsPercent(String val){ 
    try{ 
     double value=Double.parseDouble(val); 
     NumberFormat fmt=NumberFormat.getPercentFormat(); 
     fmt.overrideFractionDigits(2,2); 
     String formatted=fmt.format(value); 
     return formatted; 
    }catch(NumberFormatException e){ 
     // TODO 
     return val; 
    } 
} 

private boolean isValidValue(int index, String data){ 
    /* if data formatted as pct, convert into double */ 
    if(data.endsWith("%")){ 
     data=data.substring(0,data.length()-2); 
     try{ 
      double v=Double.parseDouble(data); 
      v=v/100; 
      data=Double.toString(v); 
     }catch(NumberFormatException e){ 
      return false; 
     } 
    } 
    RowDTO row=dataDTO.getRow(index); 
    RowValidation validation=row.getValidation(); 
    if(validation.isDigit()){ 
     double val; 
     try{ 
      val=Double.parseDouble(data); 
     }catch(Exception e){ 
      return false; 
     } 

     if(val>0&&!validation.isPositive()){ return false; } 
     if(val<0&&!validation.isNegative()){ return false; } 
     if(val==0&&!validation.isZero()){ return false; } 
     if(validation.isMaxEnabled()&&val>validation.getMaxValue()){ return false; } 
    }else{ 
     int val; 
     try{ 
      val=Integer.parseInt(data); 
     }catch(Exception e){ 
      return false; 
     } 

     if(val>0&&!validation.isPositive()){ return false; } 
     if(val<0&&!validation.isNegative()){ return false; } 
     if(val==0&&!validation.isZero()){ return false; } 
     if(validation.isMaxEnabled()&&val>validation.getMaxValue()){ return false; } 
    } 

    return true; 
} 

private class DataChange{ 
    private final RowDTO object; 
    private final String value; 
    private final int col; 

    public DataChange(int col, RowDTO object, String value){ 
     this.object=object; 
     this.value=value; 
     this.col=col; 
    } 

    public void doCommit(){ 
     object.setRowData(col,value); 
    } 
} 

Et la méthode du point d'entrée:

public class Mpp implements EntryPoint{ 

/** Entry point method. */ 

@Override 
public void onModuleLoad(){ 
    int a=3; 
    int b=13; 

    Vector<Vector<Object>> roughData=new Vector<Vector<Object>>(a); 
    Vector<String> headers=new Vector<String>(b); 
    Vector<Object> r0=new Vector<Object>(b); 
    Vector<Object> r1=new Vector<Object>(b); 
    Vector<Object> r2=new Vector<Object>(b); 

    r0.add("Amount (double)"); 
    r1.add("Credit (int)"); 
    r2.add("Advance (%)"); 
    headers.add("Col "); 

    for(int i=1;i<b;i++){ 
     headers.add("Col "+(i)); 
     r0.add(i*1.2); 
     r1.add(i); 
     r2.add(i/100); 
    } 
    roughData.add(r0); 
    roughData.add(r1); 
    roughData.add(r2); 

    TablePanel panel=new TablePanel(roughData,headers,TableDTO.FIXEDCOST); 
    RootPanel.get().add(panel); 

} 
+0

Validation des données? où et quand ?? soyez clair s'il vous plaît. –

+0

Bonjour, j'ai réussi à faire valider les données. Maintenant, les seules parties qui ne fonctionnent pas correctement sont l'actualisation de la table et le formatage des nouvelles valeurs après une modification réussie. (voir mise à jour post) – user2177336

+0

redraw fera l'actualisation ... ce qui se passe ?? –

Répondre

0

De ce que je comprends, votre tâche ici est de ne pas afficher les données d'une base de données ou tel, vous Je veux juste des trucs dans une belle table de 13 x 3, non? Dans ce cas, je recommande de ne pas utiliser CellTable et de créer simplement un tas de widgets que vous pouvez ensuite utiliser en utilisant, disons FlexTable; cela devrait être beaucoup plus facile à contrôler.

+0

Merci pour la suggestion. Les données proviennent d'une base de données mais ne sont pas massives (max 30 lignes et 37 colonnes). J'ai fini par faire une combinaison de ces deux approches (la solution de contournement que j'ai trouvée est de reconstruire la table entière à chaque fois) pour les tables les plus compliquées et d'avoir une table flexible personnalisée pour les plus simples. – user2177336

Questions connexes