teichmann@5861: /* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde teichmann@5861: * Software engineering by Intevation GmbH teichmann@5861: * teichmann@5993: * This file is Free Software under the GNU AGPL (>=v3) teichmann@5861: * and comes with ABSOLUTELY NO WARRANTY! Check out the teichmann@5993: * documentation coming with Dive4Elements River for details. teichmann@5861: */ teichmann@5861: teichmann@5835: package org.dive4elements.river.client.client.ui; raimund@256: gernotbelger@9064: import java.util.List; gernotbelger@9171: import java.util.Map; gernotbelger@9171: import java.util.TreeMap; gernotbelger@9064: gernotbelger@9064: import org.dive4elements.river.client.client.Config; gernotbelger@9064: import org.dive4elements.river.client.client.FLYSConstants; gernotbelger@9064: import org.dive4elements.river.client.client.services.CSVExportService; gernotbelger@9064: import org.dive4elements.river.client.client.services.CSVExportServiceAsync; gernotbelger@9064: raimund@256: import com.google.gwt.core.client.GWT; christian@4184: import com.google.gwt.i18n.client.NumberFormat; gernotbelger@9314: import com.google.gwt.safehtml.shared.SafeHtmlUtils; raimund@256: import com.google.gwt.user.client.rpc.AsyncCallback; gernotbelger@9167: import com.smartgwt.client.data.Record; christian@4184: import com.smartgwt.client.types.ListGridFieldType; ingo@550: import com.smartgwt.client.util.SC; raimund@256: import com.smartgwt.client.widgets.Canvas; raimund@256: import com.smartgwt.client.widgets.grid.ListGrid; raimund@256: import com.smartgwt.client.widgets.grid.ListGridField; christian@4184: import com.smartgwt.client.widgets.layout.VLayout; gernotbelger@9167: import com.smartgwt.client.widgets.tab.Tab; gernotbelger@9167: import com.smartgwt.client.widgets.tab.TabSet; raimund@256: raimund@256: /** raimund@256: * This UIProvider creates a widget that displays calculated data in a table. raimund@256: * raimund@256: * @author Raimund Renkert raimund@256: */ gernotbelger@9064: public class TableDataPanel { felix@810: /** The message class that provides i18n strings. */ raimund@256: protected FLYSConstants MESSAGES = GWT.create(FLYSConstants.class); raimund@256: gernotbelger@9064: protected CSVExportServiceAsync exportService = GWT.create(CSVExportService.class); raimund@256: felix@810: /** A container that will contain the location or the distance panel. */ raimund@256: protected VLayout container; raimund@256: felix@810: /** The export type. */ raimund@256: protected String name; raimund@256: felix@810: /** The UUID of the collection. */ raimund@256: protected String uuid; raimund@256: felix@810: /** The table. */ raimund@256: protected ListGrid dataTable; raimund@256: gernotbelger@9167: private final TabSet tabSet; gernotbelger@9167: raimund@256: /** felix@7616: * Creates a new TableDataPanel instance. raimund@256: */ raimund@256: public TableDataPanel() { gernotbelger@9064: this.container = new VLayout(); gernotbelger@9064: this.dataTable = new ListGrid(); gernotbelger@9167: this.tabSet = new TabSet(); gernotbelger@9064: this.name = ""; raimund@256: } raimund@256: raimund@256: /** felix@810: * This method creates a widget that contains a table. raimund@256: * raimund@256: * @return a panel. raimund@256: */ raimund@256: public Canvas create() { gernotbelger@9064: final Config config = Config.getInstance(); gernotbelger@9064: final String locale = config.getLocale(); gernotbelger@9064: this.dataTable.setEmptyMessage(this.MESSAGES.empty_table()); gernotbelger@9064: this.dataTable.setShowHeaderContextMenu(false); gernotbelger@9064: this.dataTable.setCanDragSelectText(true); raimund@256: gernotbelger@9064: this.exportService.getCSV(locale, this.uuid, this.name, new AsyncCallback>() { gernotbelger@9064: @Override gernotbelger@9064: public void onFailure(final Throwable caught) { gernotbelger@9064: GWT.log("Could not receive csv."); gernotbelger@9064: SC.warn(caught.getMessage()); gernotbelger@9064: } raimund@256: gernotbelger@9064: @Override gernotbelger@9064: public void onSuccess(final List l) { gernotbelger@9064: GWT.log("Recieved csv with " + l.size() + " lines."); gernotbelger@9064: setData(l); raimund@256: } gernotbelger@9064: }); gernotbelger@9064: this.container.addMember(this.dataTable); raimund@256: gernotbelger@9064: return this.container; raimund@256: } raimund@256: gernotbelger@9064: public void setName(final String name) { gernotbelger@9064: this.name = name; raimund@256: } raimund@256: gernotbelger@9064: public void setUuid(final String uuid) { gernotbelger@9064: this.uuid = uuid; raimund@256: } raimund@256: raimund@259: /** christian@4184: * This method sets the data to a dynamic table. raimund@259: * gernotbelger@9064: * @param list gernotbelger@9064: * List of String[] containing the data. raimund@259: */ gernotbelger@9167: gernotbelger@9064: public void setData(final List list) { ingo@1289: if (list == null || list.size() < 2) { gernotbelger@9064: this.dataTable.setEmptyMessage(this.MESSAGES.error_no_calc_result()); gernotbelger@9064: this.dataTable.redraw(); ingo@1289: return; ingo@1289: } ingo@1289: gernotbelger@9064: final Config config = Config.getInstance(); gernotbelger@9064: final String locale = config.getLocale(); ingo@1486: ingo@1486: NumberFormat nf; ingo@1486: if (locale.equals("de")) { ingo@1486: nf = NumberFormat.getFormat("#,##"); gernotbelger@9064: } else { ingo@1486: nf = NumberFormat.getFormat("#.##"); ingo@1486: } gernotbelger@9171: final Map> tabData = getTabData(list); gernotbelger@9167: if (tabData.size() == 1) { gernotbelger@9326: createTable(this.dataTable, tabData.get(tabData.keySet().iterator().next()), nf); gernotbelger@9167: gernotbelger@9167: } else if (tabData.size() > 1) { gernotbelger@9167: gernotbelger@9171: for (final String key : tabData.keySet()) { gernotbelger@9171: final List items = tabData.get(key); gernotbelger@9167: gernotbelger@9167: final ListGrid table = new ListGrid(); gernotbelger@9167: gernotbelger@9326: createTable(table, items, nf); gernotbelger@9167: final Tab tab = new Tab(); gernotbelger@9171: tab.setTitle(key); gernotbelger@9167: tab.setPane(table); gernotbelger@9167: this.tabSet.addTab(tab); gernotbelger@9167: } gernotbelger@9167: this.tabSet.selectTab(0); gernotbelger@9167: this.container.removeChild(this.dataTable); gernotbelger@9167: this.container.addChild(this.tabSet); gernotbelger@9167: this.tabSet.setWidth100(); gernotbelger@9167: this.tabSet.setHeight100(); gernotbelger@9167: } gernotbelger@9167: } gernotbelger@9167: gernotbelger@9326: private void createTable(final ListGrid dataTableTab, final List list, final NumberFormat nf) { ingo@1486: gernotbelger@9064: final String[] header = list.get(0); gernotbelger@9064: final String[] displayField = new String[header.length]; ingo@1289: gernotbelger@9064: final ListGridField[] fields = new ListGridField[header.length]; ingo@1486: gernotbelger@9064: for (int i = 0; i < header.length; i++) { gernotbelger@9064: final ListGridField f = new ListGridField(String.valueOf(i)); raimund@259: fields[i] = f; raimund@259: f.setTitle(header[i]); raimund@906: raimund@906: try { gernotbelger@9064: /* gernotbelger@9064: * Try to determine the type with the first gernotbelger@9167: * non empty element. -> WARUM??! OK, nur Formatierung/Sortierung gernotbelger@9064: */ andre@8632: for (int j = 1; j < list.size(); j++) { andre@8632: if (!list.get(j)[i].isEmpty()) { andre@8632: nf.parse(list.get(j)[i]); andre@8632: f.setType(ListGridFieldType.FLOAT); gernotbelger@9167: andre@8632: break; andre@8632: } andre@8632: } raimund@906: } gernotbelger@9064: catch (final NumberFormatException nfe) { raimund@906: f.setType(ListGridFieldType.TEXT); raimund@906: } felix@7617: felix@7602: // To keep server-side formatting and i18n also of felix@7602: // float values, we will store the value once formatted 'as is' felix@7602: // to be displayed and once as e.g. float to allow functions like felix@7602: // sorting on it. gernotbelger@9167: displayField[i] = "$" + i + "_displayField"; felix@7602: f.setDisplayField(displayField[i]); felix@7602: f.setValueField(String.valueOf(i)); felix@7602: f.setSortByDisplayField(false); gernotbelger@9167: } gernotbelger@9167: dataTableTab.setFields(fields); raimund@259: gernotbelger@9167: for (int i = 1; i < list.size(); i++) { // index bei 1, da erster Eintrag Header ist gernotbelger@9167: gernotbelger@9064: final String[] sItem = list.get(i); gernotbelger@9167: final Record r = new Record(); gernotbelger@9064: for (int j = 0; j < sItem.length; j++) { felix@7602: // See above, display 'as is' from server, but keep value felix@7602: // in machine-usable way (float), to allow numeric sorting. gernotbelger@9353: final String item = sItem[j]; gernotbelger@9353: final String encodedText = SafeHtmlUtils.htmlEscapeAllowEntities(item); gernotbelger@9353: gernotbelger@9314: r.setAttribute(displayField[j], encodedText); felix@7602: if (fields[j].getType() == ListGridFieldType.TEXT) { gernotbelger@9314: r.setAttribute(String.valueOf(j), item); gernotbelger@9064: } else { felix@7617: try { gernotbelger@9314: final Float valueFloatSortable = (float) nf.parse(item); gernotbelger@9167: r.setAttribute(String.valueOf(j), valueFloatSortable); felix@7617: } gernotbelger@9064: catch (final NumberFormatException nfe) { gernotbelger@9314: r.setAttribute(String.valueOf(j), item); felix@7617: } felix@7602: } gernotbelger@9167: raimund@256: } gernotbelger@9167: gernotbelger@9167: dataTableTab.addData(r); raimund@256: } raimund@256: } gernotbelger@9167: gernotbelger@9171: private Map> getTabData(final List raw) { gernotbelger@9171: // Condition: tableTitle must be first gernotbelger@9171: final Map> tabs = new TreeMap>(); // auto-sort gernotbelger@9167: gernotbelger@9171: if (raw.get(0)[0].startsWith(this.MESSAGES.export_csv_title())) { gernotbelger@9171: // Bedingung für Tabs gernotbelger@9171: int lastIndex = 0; gernotbelger@9171: String lastTableTitle = ""; gernotbelger@9171: gernotbelger@9171: for (int i = 0; i < raw.size(); i++) { gernotbelger@9171: gernotbelger@9171: final String[] row = raw.get(i); gernotbelger@9171: if (row[0].startsWith(this.MESSAGES.export_csv_title())) { gernotbelger@9171: gernotbelger@9171: if (i > 0) { gernotbelger@9171: tabs.put(makeKeyTitle(lastTableTitle, tabs.size()), raw.subList((lastIndex + 1), (i))); // toIndex exclusive (without gernotbelger@9171: // tabTitle-Line of the next tab, which is gernotbelger@9171: // stored in the current row (raw.get(i)); gernotbelger@9171: // fromIndex gernotbelger@9171: // inclusive -> gernotbelger@9171: // without tabTitle from the past tab -> gernotbelger@9171: // lastindex+1 gernotbelger@9171: } gernotbelger@9171: lastTableTitle = row[0].replace(this.MESSAGES.export_csv_title(), ""); gernotbelger@9171: lastIndex = i; gernotbelger@9171: } gernotbelger@9171: gernotbelger@9171: if (i == (raw.size() - 1)) { gernotbelger@9171: tabs.put(makeKeyTitle(lastTableTitle, tabs.size()), raw.subList((lastIndex + 1), i + 1)); gernotbelger@9171: // last result-tab: gernotbelger@9171: // toIndex exclusive -> last i + 1 gernotbelger@9171: // fromIndex inclusive: lastInde +1 -> no title-line included gernotbelger@9171: } gernotbelger@9171: gernotbelger@9167: } gernotbelger@9171: } else { gernotbelger@9171: // plainOld Table, no TABS gernotbelger@9171: tabs.put("", raw); gernotbelger@9167: } gernotbelger@9167: gernotbelger@9167: return tabs; gernotbelger@9167: } gernotbelger@9171: gernotbelger@9171: private String makeKeyTitle(final String title, final int index) { gernotbelger@9171: return new StringBuilder().append("(").append((index + 1)).append(") ").append(title).toString(); gernotbelger@9171: } raimund@256: } raimund@256: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :