Dienstag, 25. Dezember 2012

GWT: Cell in Celltable dynamisch verändern

GWT 2.5

Wenn die Anforderung laute je nach Cell Value Veränderungen z.B. in der Farbe der Schrift vorzunehmen habe ich eine Lösung gefunden, die wahrscheinlich nicht ideal ist, die ich nichtsdestotrotz hier vorstellen möchte.

Als erstes möchte ich die TextInputCell etwas erweitern, in diesem Fall zum zweiten Mal, da ich vorher schon Ausbauten brauchte, der wichtige Punkt ist in jedem Fall dass ein eigenes Template gestaltet werden kann:


public class MyTextInputCell extends ExtendendedBrowserEventsTextInputCell {

 interface Template extends SafeHtmlTemplates {
  @Template(<input type=\"text\" value=\"{0}\" tabindex=\"-1\" size=\"{1}\" maxlength=\"{1}\" style=\"color:{2}\"></input>")
  SafeHtml input(String value, String size, String textColor);
 }

Zu beachten ist, das die Farbe über style geändert wurde, einfach die color reinzuschreiben reichte aus irgend einem Grund nicht.
Das Ganze kommt dann in der überschriebenen Methode render zum Tragen:


@Override
 public void render(com.google.gwt.cell.client.Cell.Context context, String value, SafeHtmlBuilder sb) {
  // Get the view data.
  Object key = context.getKey();
  ViewData viewData = getViewData(key);
  if (viewData != null && viewData.getCurrentValue().equals(value)) {
   clearViewData(key);
   viewData = null;
  }

  String s = (viewData != null) ? viewData.getCurrentValue() : value;
  if (s != null) {
   sb.append(myTemplate.input(s, size, textColor));
  } else {
   sb.appendHtmlConstant("<input type=\"text\" tabindex=\"-1\"></input>");
  }
 }
textColor ist dabei eine Instanzvariable, doch wann verändere ich diese entsprechend?
Ich greife da in der Column Implementierung in der Methode getValue, hier kann man schön Wertabhängig die InstanzVariable textColor verändern. Gewählt habe ich diesen Weg, weil ich ein großes Array an Namen brauche um die Farbe des Textes zu bestimmen und mir es am geschicktesten schien dieses Array der Column mitzugeben.

private static final class MyColumn extends Column<String[], String> {

  int index;
  Name[] names;

  public MyColumn(Cell<String> cell, int index, Name[] names) {
   super(cell);
   this.index = index;
   this.names = names;
  }

  @Override
  public String getValue(String[] data) {
   if (this.getCell() instanceof MyTextInputCell) {
    MyTextInputCell cell = (MyTextInputCell) this.getCell();
    if ((cell.isUserid || cell.isUseridStrict) && !Utils.isUseridInNames(data[index], this.names)) {
     cell.textColor = "red";
    } else {
     cell.textColor = "black";
    }
   }
   return data[index];
  }
 }

Es gibt sicher elegantere Methoden, ich würde mich freuen wenn jemand mir eine zeigt.

Links:
Frage dazu auf stackoverflow

Samstag, 15. Dezember 2012

GWT: SuggestBox in einer CellTable

GWT 2.5

Hat man sich einmal entschlossen eine CellTable zu verwenden und stößt dann auf Anforderungen die die CellTable nicht von vornherein vorgesehen hat kann das sehr ärgerlich werden. Mir ging es so bei der Anforderung eine SuggestBox in der Table zu verwenden.
Schlußendlich stellte sich heraus daß das Ganze gar nicht so eine Zauberei ist, muß aber auch dazusagen, daß die Lösung noch nicht wirklich den Praxistest erlebt hat.

Meine Lösung besteht darin, einfach die TextInputCell zu extenden und so eine SuggestBox reinzuschummeln:


public class SuggestBoxTextInputCell extends TextInputCell {

 MySuggestBox suggestBox;

 private class MyTextBox extends TextBox {
  public MyTextBox(Element element) {
   super(element);
  }
 }

 private class MySuggestBox extends SuggestBox {
  public MySuggestBox(SuggestOracle suggestOracle, TextBox textBox) {
   super(suggestOracle, textBox);
  }

  @Override
  public void onAttach() {
   super.onAttach();
  }
 }

 public SuggestBoxTextInputCell() {
  super();
 }


 @Override
 public void onBrowserEvent(Context context, Element parent, String value, NativeEvent event,
   ValueUpdater<String> valueUpdater) {
  super.onBrowserEvent(context, parent, value, event, valueUpdater);
  String eventType = event.getType();
  if (BrowserEvents.FOCUS.equals(eventType)) {
   TextBox textBox = new MyTextBox(getInputElement(parent));
   suggestBox = new MySuggestBox(getSuggestOracle(), textBox);
   suggestBox.onAttach();
  }
 }

 private SuggestOracle getSuggestOracle() {
        //this does not work without implementation
        return null;
 }
}

Die Methode gestSuggestOracle muss natürlich noch implementiert werden um den Beispielcode lauffähig zu bekommen.
Links:
Google Groups Beitrag
Stackoverflow Beitrag zum Thema