Java tutorial
/******************************************************************************* * Copyright (c) 2014 Ministry of Transport and Communications (Finland). * 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: * Semantum Oy - initial API and implementation *******************************************************************************/ package fi.semantum.strategia.widget; import java.io.IOException; import java.math.BigDecimal; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.UUID; import com.vaadin.data.Property.ValueChangeEvent; import com.vaadin.data.Property.ValueChangeListener; import com.vaadin.event.LayoutEvents.LayoutClickEvent; import com.vaadin.event.LayoutEvents.LayoutClickListener; import com.vaadin.event.MouseEvents; import com.vaadin.server.Page; import com.vaadin.server.ThemeResource; import com.vaadin.server.UserError; import com.vaadin.shared.ui.label.ContentMode; import com.vaadin.ui.AbstractComponent; import com.vaadin.ui.AbstractField; import com.vaadin.ui.Alignment; import com.vaadin.ui.Button; import com.vaadin.ui.Button.ClickEvent; import com.vaadin.ui.ComboBox; import com.vaadin.ui.Component; import com.vaadin.ui.HorizontalLayout; import com.vaadin.ui.Image; import com.vaadin.ui.Label; import com.vaadin.ui.Notification; import com.vaadin.ui.Table; import com.vaadin.ui.TextArea; import com.vaadin.ui.TextField; import com.vaadin.ui.VerticalLayout; import com.vaadin.ui.Window; import com.vaadin.ui.themes.ValoTheme; import fi.semantum.strategia.Dialogs; import fi.semantum.strategia.Lucene; import fi.semantum.strategia.Main; import fi.semantum.strategia.Updates; import fi.semantum.strategia.Utils; import fi.semantum.strategia.Utils.AbstractCommentCallback; import fi.semantum.strategia.Utils.CommentCallback; import fi.semantum.strategia.Wiki; public class Indicator extends Base { private static final long serialVersionUID = -5122160460824254403L; private double value = 0; public TimeSeries values; public String unit = ""; public static Indicator create(Database database, String text, Datatype datatype) { Indicator p = new Indicator("", text, datatype); database.register(p); return p; } private Indicator(String id, String text, Datatype datatype) { super(UUID.randomUUID().toString(), id, text); this.value = Double.NaN; values = new TimeSeries(datatype); } public Object getValue(boolean forecast) { if (forecast) return getForecast(); else return getValue(); } public Object getValue() { if (values != null) { return values.getLastValue(); } else return value; } public Object getForecast() { if (values != null) { return values.getLastForecast(); } else return value; } public String getValueShortComment() { if (values != null) { TimeSeriesEntry entry = values.getLastValueEntry(); if (entry == null) return ""; String shortComment = entry.getShortComment(); return shortComment != null ? shortComment : ""; } else return ""; } public String getUnitAndComment() { return getUnit() + " " + getValueShortComment(); } public String getUnit() { return unit; } public static List<Indicator> enumerate(Database database) { ArrayList<Indicator> result = new ArrayList<Indicator>(); for (Base b : database.objects.values()) { if (b instanceof Indicator) result.add((Indicator) b); } return result; } public void update(Main main, Base owner, Object value, boolean forecast, String shortComment, String comment) { final Database database = main.getDatabase(); Account account = main.getAccountDefault(); if (!value.equals(forecast ? getForecast() : getValue())) { modified(main); values.addValue(forecast ? getValue() : value, forecast ? value : getForecast(), account, shortComment, comment); try { Lucene.set(database.getDatabaseId(), uuid, searchText(database)); } catch (IOException e) { e.printStackTrace(); } } } private static class IndicatorDescription { public String caption; public Indicator indicator; public IndicatorDescription(Indicator indicator, String caption) { this.indicator = indicator; this.caption = caption; } } private static void fillIndicatorDescriptions(Main main, Base base, String indent, List<IndicatorDescription> result) { final Database database = main.getDatabase(); List<Indicator> indicators = base.getIndicatorsActive(main); for (int i = 0; i < indicators.size(); i++) { Indicator indicator = indicators.get(i); String desc = indent + Integer.toString(i + 1) + ". " + indicator.getCaption(database); result.add(new IndicatorDescription(indicator, desc)); fillIndicatorDescriptions(main, indicator, makeIndent(indent, i), result); } } private static void makeIndicatorTable(Main main, Base base, final Table table) { @SuppressWarnings("unchecked") Collection<Indicator> selection = (Collection<Indicator>) table.getValue(); table.removeAllItems(); List<IndicatorDescription> descs = new ArrayList<IndicatorDescription>(); fillIndicatorDescriptions(main, base, "", descs); fillIndicatorTable(main, base, table, descs); for (Indicator i : selection) table.select(i); } private static void fillIndicatorTable(Main main, Base base, final Table table, List<IndicatorDescription> descs) { boolean showYears = main.getUIState().time.equals(Property.AIKAVALI_KAIKKI); final Database database = main.getDatabase(); Property aika = Property.find(database, Property.AIKAVALI); for (int i = 0; i < descs.size(); i++) { IndicatorDescription desc = descs.get(i); Indicator meter = desc.indicator; Label text = new Label(desc.caption); text.setContentMode(ContentMode.HTML); String year = aika.getPropertyValue(meter); if (showYears) table.addItem(new Object[] { text, year }, meter); else table.addItem(new Object[] { text }, meter); } } private static String makeIndent(String indent, int index) { return " " + indent + Integer.toString(index + 1) + "."; } public static void manageIndicators(final Main main, final Base base) { String currentTime = main.getUIState().time; boolean showYears = currentTime.equals(Property.AIKAVALI_KAIKKI); final Database database = main.getDatabase(); VerticalLayout content = new VerticalLayout(); content.setSizeFull(); content.setSpacing(true); final Table table = new Table(); table.setSelectable(true); table.setMultiSelect(true); table.addStyleName(ValoTheme.TABLE_SMALL); table.addStyleName(ValoTheme.TABLE_COMPACT); table.addContainerProperty("Indikaattori", Label.class, null); if (showYears) table.addContainerProperty("Vuosi", String.class, null); table.setWidth("100%"); table.setHeight("100%"); table.setNullSelectionAllowed(true); table.setEditable(false); table.setColumnExpandRatio("Indikaattori", 2.0f); if (showYears) table.setColumnExpandRatio("Vuosi", 0.0f); makeIndicatorTable(main, base, table); content.addComponent(table); content.setExpandRatio(table, 1.0f); abstract class IndicatorButtonListener implements Button.ClickListener { private static final long serialVersionUID = -7551250112503063540L; protected Indicator getPossibleSelection() { Object selection = table.getValue(); Collection<?> selected = (Collection<?>) selection; if (selected.size() != 1) return null; return (Indicator) selected.iterator().next(); } @SuppressWarnings("unchecked") protected Collection<Indicator> getSelection() { return (Collection<Indicator>) table.getValue(); } protected Map<Base, List<Indicator>> getSelectionByParent(Database database) { return indicatorsByParent(database, getSelection()); } } final Button removeIndicators = new Button("Poista", new IndicatorButtonListener() { private static final long serialVersionUID = -2538054127519468282L; public void buttonClick(ClickEvent event) { Collection<Indicator> selection = getSelection(); for (Indicator i : selection) { Base owner = i.getOwner(database); if (owner == null) continue; owner.removeIndicator(i); } final Set<Base> bases = new HashSet<Base>(); final Strategiakartta map = database.getMap(base); bases.add(map); for (Tavoite t : map.tavoitteet) { bases.add(t); for (Painopiste p : t.painopisteet) { bases.add(p); } } for (Base b : bases) { for (Meter meter : b.getMeters(database)) { Indicator indicator = meter.getPossibleIndicator(database); if (selection.contains(indicator)) { b.removeMeter(meter); } } } makeIndicatorTable(main, base, table); Updates.update(main, true); } }); removeIndicators.addStyleName(ValoTheme.BUTTON_TINY); final Button moveUp = new Button("Siirr ylemms", new IndicatorButtonListener() { private static final long serialVersionUID = -635232943884881464L; public void buttonClick(ClickEvent event) { for (Map.Entry<Base, List<Indicator>> entry : getSelectionByParent(database).entrySet()) { entry.getKey().moveIndicatorsUp(entry.getValue()); } makeIndicatorTable(main, base, table); Updates.update(main, true); } }); moveUp.addStyleName(ValoTheme.BUTTON_TINY); final Button moveDown = new Button("Siirr alemmas", new IndicatorButtonListener() { private static final long serialVersionUID = 2779521990166604444L; public void buttonClick(ClickEvent event) { for (Map.Entry<Base, List<Indicator>> entry : getSelectionByParent(database).entrySet()) { entry.getKey().moveIndicatorsDown(entry.getValue()); } makeIndicatorTable(main, base, table); Updates.update(main, true); } }); moveDown.addStyleName(ValoTheme.BUTTON_TINY); final Button modify = new Button("Mrit"); modify.addClickListener(new IndicatorButtonListener() { private static final long serialVersionUID = 5149432436059288486L; public void buttonClick(ClickEvent event) { Indicator indicator = getPossibleSelection(); if (indicator == null) return; editIndicator(main, base, indicator); } }); modify.addStyleName(ValoTheme.BUTTON_TINY); final TextField indicatorText = new TextField(); indicatorText.setWidth("100%"); indicatorText.addStyleName(ValoTheme.TEXTFIELD_TINY); indicatorText.setCaption("Tunniste"); List<Datatype> types = Datatype.enumerate(database); final ComboBox datatypeSelect = new ComboBox(); datatypeSelect.setWidth("100%"); datatypeSelect.setNullSelectionAllowed(false); datatypeSelect.addStyleName(ValoTheme.COMBOBOX_TINY); datatypeSelect.setCaption("Tietotyyppi"); for (Datatype dt : types) datatypeSelect.addItem(dt); final Button addIndicator = new Button("Lis ptasolle", new Button.ClickListener() { private static final long serialVersionUID = -2395147866745115337L; public void buttonClick(ClickEvent event) { String text = indicatorText.getValue(); Object dt = datatypeSelect.getValue(); if (text.isEmpty() || dt == null || dt.equals(datatypeSelect.getNullSelectionItemId())) return; base.addIndicator(Indicator.create(database, text, (Datatype) dt)); makeIndicatorTable(main, base, table); Updates.update(main, true); } }); addIndicator.addStyleName(ValoTheme.BUTTON_TINY); final Button addSubIndicator = new Button("Lis valitun alle", new IndicatorButtonListener() { private static final long serialVersionUID = -2395147866745115337L; public void buttonClick(ClickEvent event) { Indicator indicator = getPossibleSelection(); if (indicator == null) return; String text = indicatorText.getValue(); Object dt = datatypeSelect.getValue(); if (text.isEmpty() || dt == null || dt.equals(datatypeSelect.getNullSelectionItemId())) return; indicator.addIndicator(Indicator.create(database, text, (Datatype) dt)); makeIndicatorTable(main, base, table); Updates.update(main, true); } }); addSubIndicator.addStyleName(ValoTheme.BUTTON_TINY); final Runnable setStates = new Runnable() { @Override public void run() { Object selection = table.getValue(); Collection<?> selected = (Collection<?>) selection; if (!selected.isEmpty()) { removeIndicators.setEnabled(true); moveUp.setEnabled(true); moveDown.setEnabled(true); if (selected.size() == 1) { modify.setEnabled(true); addSubIndicator.setEnabled(true); } else { addSubIndicator.setEnabled(false); modify.setEnabled(false); } } else { moveUp.setEnabled(false); moveDown.setEnabled(false); removeIndicators.setEnabled(false); addSubIndicator.setEnabled(false); modify.setEnabled(false); } } }; table.addValueChangeListener(new ValueChangeListener() { private static final long serialVersionUID = 1188285609779556446L; @Override public void valueChange(ValueChangeEvent event) { setStates.run(); } }); setStates.run(); HorizontalLayout hl2 = new HorizontalLayout(); hl2.setSpacing(true); hl2.setWidthUndefined(); hl2.addComponent(modify); hl2.setComponentAlignment(modify, Alignment.BOTTOM_LEFT); hl2.setExpandRatio(modify, 0.0f); hl2.addComponent(removeIndicators); hl2.setComponentAlignment(removeIndicators, Alignment.BOTTOM_LEFT); hl2.setExpandRatio(removeIndicators, 0.0f); hl2.addComponent(moveUp); hl2.setComponentAlignment(moveUp, Alignment.TOP_LEFT); hl2.setExpandRatio(moveUp, 0.0f); hl2.addComponent(moveDown); hl2.setComponentAlignment(moveDown, Alignment.TOP_LEFT); hl2.setExpandRatio(moveDown, 0.0f); HorizontalLayout hl3 = new HorizontalLayout(); hl3.setSpacing(true); hl3.setWidth("100%"); hl3.addComponent(addIndicator); hl3.setComponentAlignment(addIndicator, Alignment.BOTTOM_LEFT); hl3.setExpandRatio(addIndicator, 0.0f); hl3.addComponent(addSubIndicator); hl3.setComponentAlignment(addSubIndicator, Alignment.BOTTOM_LEFT); hl3.setExpandRatio(addSubIndicator, 0.0f); hl3.addComponent(indicatorText); hl3.setComponentAlignment(indicatorText, Alignment.BOTTOM_LEFT); hl3.setExpandRatio(indicatorText, 1.0f); hl3.addComponent(datatypeSelect); hl3.setComponentAlignment(datatypeSelect, Alignment.BOTTOM_LEFT); hl3.setExpandRatio(datatypeSelect, 2.0f); content.addComponent(hl2); content.setComponentAlignment(hl2, Alignment.BOTTOM_LEFT); content.setExpandRatio(hl2, 0.0f); content.addComponent(hl3); content.setComponentAlignment(hl3, Alignment.BOTTOM_LEFT); content.setExpandRatio(hl3, 0.0f); HorizontalLayout buttons = new HorizontalLayout(); buttons.setSpacing(true); buttons.setMargin(false); final Window dialog = Dialogs.makeDialog(main, "650px", "800px", "Hallitse indikaattoreita", "Sulje", content, buttons); } public Datatype getDatatype(Database database) { return values.getDatatype(); } public void setDatatype(Datatype datatype) { if (!datatype.equals(values.getDatatype())) values = new TimeSeries(datatype); } private static TextField makeUnit(Database database, HorizontalLayout hl, Indicator indicator) { if (!(indicator.getDatatype(database) instanceof NumberDatatype)) return null; final TextField unit = new TextField("Yksikk"); unit.setValue(indicator.getUnit()); unit.setWidth("100%"); unit.addStyleName(ValoTheme.TEXTFIELD_SMALL); hl.addComponent(unit); hl.setComponentAlignment(unit, Alignment.MIDDLE_CENTER); hl.setExpandRatio(unit, 1.0f); return unit; } public static Label makeHistory(Database database, Indicator indicator, boolean forecast) { Label ta2 = new Label("Historia"); ta2.setContentMode(ContentMode.HTML); ta2.setWidth("100%"); ta2.setHeight("100%"); StringBuilder sb = new StringBuilder(); sb.append("<b>Historia</b><br><br>"); for (Map.Entry<Date, TimeSeriesEntry> entry : indicator.values.list()) { TimeSeriesEntry tse = entry.getValue(); Account account = tse.getAccount(); Date date = entry.getKey(); String user = account != null ? account.getId(database) : "Jrjestelm"; sb.append("<b>"); sb.append(user); sb.append("</b> pivitti "); sb.append(forecast ? " ennustetta" : " toteumaa"); sb.append(" <b>"); sb.append(Utils.describeDate(date)); sb.append("</b><br><hr>"); sb.append(" Uusi arvo on <b>"); sb.append(forecast ? tse.getForecast() : tse.getValue() + " " + indicator.getUnitAndComment()); sb.append("</b><br>"); String comment = tse.getComment(); if (comment != null) sb.append("<p>" + tse.getComment() + "</p>"); sb.append("<br>"); } ta2.setValue(sb.toString()); return ta2; } public static void editIndicator(final Main main, final Base base, final Indicator indicator) { final Database database = main.getDatabase(); VerticalLayout content = new VerticalLayout(); content.setSizeFull(); content.setHeightUndefined(); content.setSpacing(true); HorizontalLayout hl = new HorizontalLayout(); hl.setSpacing(true); hl.setWidth("100%"); content.addComponent(hl); content.setExpandRatio(hl, 0.0f); final TextField tf = new TextField("Tunniste"); tf.setValue(indicator.getId(database)); tf.setWidth("100%"); tf.addStyleName(ValoTheme.TEXTFIELD_SMALL); hl.addComponent(tf); hl.setComponentAlignment(tf, Alignment.MIDDLE_CENTER); hl.setExpandRatio(tf, 2.0f); final TextField tf1 = new TextField("Teksti"); tf1.setValue(indicator.getText(database)); tf1.setWidth("100%"); tf1.addStyleName(ValoTheme.TEXTFIELD_SMALL); hl.addComponent(tf1); hl.setComponentAlignment(tf1, Alignment.MIDDLE_CENTER); hl.setExpandRatio(tf1, 2.0f); final TextField unit = makeUnit(database, hl, indicator); final TextField tf2 = new TextField(); tf2.setCaption("Voimassaolo"); tf2.setValue(Utils.getValidity(database, indicator)); tf2.addStyleName(ValoTheme.TEXTFIELD_TINY); tf2.setWidth("100%"); hl.addComponent(tf2); hl.setComponentAlignment(tf2, Alignment.MIDDLE_CENTER); hl.setExpandRatio(tf2, 1.0f); final TextArea ta = new TextArea("Mritys"); ta.setValue(indicator.getText(database)); ta.setWidth("100%"); ta.setHeight("100px"); content.addComponent(ta); content.setComponentAlignment(ta, Alignment.MIDDLE_CENTER); content.setExpandRatio(ta, 0.0f); final Label ta2 = makeHistory(database, indicator, main.getUIState().forecastMeters); content.addComponent(ta2); content.setComponentAlignment(ta2, Alignment.MIDDLE_CENTER); content.setExpandRatio(ta2, 1.0f); HorizontalLayout buttons = new HorizontalLayout(); buttons.setSpacing(true); buttons.setMargin(false); Button ok = new Button("Tallenna", new Button.ClickListener() { private static final long serialVersionUID = 1992235622970234624L; public void buttonClick(ClickEvent event) { indicator.modifyId(main, tf.getValue()); Utils.modifyValidity(main, indicator, tf2.getValue()); indicator.modifyText(main, tf1.getValue()); indicator.modifyDescription(main, ta.getValue()); if (unit != null) { indicator.modifyUnit(main, unit.getValue()); } Updates.update(main, true); manageIndicators(main, main.getUIState().currentItem); } }); buttons.addComponent(ok); Button close = new Button("Sulje"); buttons.addComponent(close); final Window dialog = Dialogs.makeDialog(main, "650px", "800px", "Muokkaa indikaattoria", null, content, buttons); close.addClickListener(new Button.ClickListener() { private static final long serialVersionUID = 1992235622970234624L; public void buttonClick(ClickEvent event) { main.removeWindow(dialog); manageIndicators(main, main.getUIState().currentItem); } }); } public void modifyUnit(Main main, String text) { Account account = main.getAccountDefault(); modifyUnit(main, account, text); } void modifyUnit(Main main, Account account, String text) { final Database database = main.getDatabase(); if (!this.unit.equals(text)) { modified(main); this.unit = text; try { Lucene.set(database.getDatabaseId(), uuid, searchText(database)); } catch (IOException e) { e.printStackTrace(); } } } public static String updateIndicatorValue(final Main main, HorizontalLayout hl, final Base base, final Indicator indicator, boolean canWrite) { final Database database = main.getDatabase(); Datatype dt = indicator.getDatatype(database); if (dt != null) { final AbstractField<?> field = dt.getEditor(main, base, indicator, false, null); field.setWidth("150px"); field.setReadOnly(!canWrite); hl.addComponent(field); hl.setComponentAlignment(field, Alignment.MIDDLE_LEFT); Object value = field.getValue(); return value != null ? value.toString() : ""; } else { Object value = indicator.getValue(); final String formatted = value != null ? value.toString() : ""; final TextField tf = new TextField(); tf.setValue(formatted); tf.addValueChangeListener(new ValueChangeListener() { private static final long serialVersionUID = 3547126051252580446L; @Override public void valueChange(ValueChangeEvent event) { try { double value = Double.parseDouble(tf.getValue()); indicator.updateWithComment(main, base, value, main.getUIState().forecastMeters, new AbstractCommentCallback() { public void canceled() { tf.setValue(formatted); } }); } catch (NumberFormatException e) { tf.setComponentError(new UserError("Arvon tulee olla numero")); } } }); tf.setWidth("150px"); tf.setReadOnly(!canWrite); hl.addComponent(tf); hl.setComponentAlignment(tf, Alignment.MIDDLE_LEFT); return tf.getValue(); } } public static void updateIndicators(final Main main, final Base base, boolean canWrite) { final Database database = main.getDatabase(); List<IndicatorDescription> descs = new ArrayList<IndicatorDescription>(); fillIndicatorDescriptions(main, base, "", descs); boolean isMap = base instanceof Strategiakartta; if (isMap && (!descs.isEmpty() || canWrite)) { HorizontalLayout indiHeader = new HorizontalLayout(); indiHeader.setSpacing(true); Label header = new Label("Indikaattorit (ennuste)"); main.propertyCells.add(Utils.excelRow(header.getValue())); header.setHeight("32px"); header.addStyleName(ValoTheme.LABEL_HUGE); header.addStyleName(ValoTheme.LABEL_BOLD); indiHeader.addComponent(header); indiHeader.setComponentAlignment(header, Alignment.BOTTOM_CENTER); if (canWrite) { final Image editIndicators = new Image(null, new ThemeResource("chart_line_edit.png")); editIndicators.setHeight("24px"); editIndicators.setWidth("24px"); editIndicators.addClickListener(new MouseEvents.ClickListener() { private static final long serialVersionUID = 2661060702097338722L; @Override public void click(com.vaadin.event.MouseEvents.ClickEvent event) { Utils.loseFocus(editIndicators); manageIndicators(main, main.getUIState().currentItem); } }); indiHeader.addComponent(editIndicators); indiHeader.setComponentAlignment(editIndicators, Alignment.BOTTOM_CENTER); } main.properties.addComponent(indiHeader); main.properties.setComponentAlignment(indiHeader, Alignment.MIDDLE_CENTER); VerticalLayout indicators = new VerticalLayout(); boolean showYears = main.getUIState().time.equals(Property.AIKAVALI_KAIKKI); Property time = Property.find(database, Property.AIKAVALI); int index = 0; for (final IndicatorDescription desc : descs) { ArrayList<String> excelRow = new ArrayList<String>(); Indicator indicator = desc.indicator; final HorizontalLayout hl = new HorizontalLayout(); hl.addStyleName((((index++) & 1) == 0) ? "evenProperty" : "oddProperty"); hl.setSpacing(true); Label l = new Label(desc.caption); excelRow.add(l.getValue().replace("%nbsp", "")); l.setContentMode(ContentMode.HTML); l.setWidth("450px"); l.addStyleName("propertyName"); l.setData(desc); hl.addComponent(l); hl.setComponentAlignment(l, Alignment.MIDDLE_LEFT); String value = updateIndicatorValue(main, hl, base, indicator, canWrite); excelRow.add(value); Label unit = new Label(indicator.getUnit()); unit.setWidth("100px"); hl.addComponent(unit); hl.setComponentAlignment(unit, Alignment.MIDDLE_LEFT); excelRow.add(unit.getValue()); Label comment = new Label(indicator.getValueShortComment()); comment.setWidth("150px"); hl.addComponent(comment); hl.setComponentAlignment(comment, Alignment.MIDDLE_LEFT); excelRow.add(comment.getValue()); if (showYears) { HorizontalLayout hl2 = new HorizontalLayout(); hl2.setWidth("70px"); hl2.setHeight("100%"); hl.addComponent(hl2); hl.setComponentAlignment(hl2, Alignment.MIDDLE_LEFT); String years = time.getPropertyValue(indicator); if (years == null) years = Property.AIKAVALI_KAIKKI; final Label region = new Label(years); region.setWidthUndefined(); excelRow.add(region.getValue()); hl2.addComponent(region); hl2.setComponentAlignment(region, Alignment.MIDDLE_CENTER); } final Image wiki = new Image(); wiki.setSource(new ThemeResource("table_edit.png")); wiki.setHeight("24px"); wiki.setWidth("24px"); wiki.addClickListener(new MouseEvents.ClickListener() { private static final long serialVersionUID = 2661060702097338722L; @Override public void click(com.vaadin.event.MouseEvents.ClickEvent event) { Wiki.openWiki(main, desc.indicator); } }); hl.addComponent(wiki); hl.setComponentAlignment(wiki, Alignment.MIDDLE_CENTER); indicators.addComponent(hl); indicators.setComponentAlignment(hl, Alignment.MIDDLE_CENTER); main.propertyCells.add(excelRow); } indicators.addLayoutClickListener(new LayoutClickListener() { private static final long serialVersionUID = 3295743025581923380L; private String extractData(Component c) { if (c instanceof AbstractComponent) { Object data = ((AbstractComponent) c).getData(); if (data instanceof IndicatorDescription) { IndicatorDescription desc = (IndicatorDescription) data; return desc.indicator.getDescription(database); } } return null; } @Override public void layoutClick(LayoutClickEvent event) { String desc = extractData(event.getClickedComponent()); if (desc == null) return; String content = "<div style=\"width: 700px; border: 2px solid; padding: 5px\">"; content += "<div style=\"text-align: center; white-space:normal; font-size: 36px; padding: 10px\">" + desc + "</div>"; content += "</div>"; Notification n = new Notification(content, Notification.Type.HUMANIZED_MESSAGE); n.setHtmlContentAllowed(true); n.show(Page.getCurrent()); } }); main.properties.addComponent(indicators); main.properties.setComponentAlignment(indicators, Alignment.MIDDLE_CENTER); } } @Override public boolean migrate(Main main) { Database database = main.getDatabase(); boolean result = false; if (description == null) { modifyDescription(main, getText(database)); modifyText(main, getId(database)); modifyId(main, ""); result = true; } if (unit == null) { unit = ""; result = true; } if (values == null && value != Double.NaN) { Datatype datatype = Datatype.find(database, NumberDatatype.ID); values = new TimeSeries(datatype); values.addValue(BigDecimal.valueOf(value), BigDecimal.valueOf(value), null, null, null); value = Double.NaN; result = true; } result |= super.migrate(main); return result; } @Override public Base getOwner(Database database) { for (Base b : database.enumerate()) { if (b.getIndicators(database).contains(this)) return b; } return null; } public static Map<Base, List<Indicator>> indicatorsByParent(Database database, Collection<Indicator> indicators) { Map<Base, List<Indicator>> result = new HashMap<Base, List<Indicator>>(); for (Indicator i : indicators) { Base owner = i.getOwner(database); List<Indicator> exist = result.get(owner); if (exist == null) { exist = new ArrayList<Indicator>(); result.put(owner, exist); } exist.add(i); } return result; } public void updateWithComment(final Main main, final Base base, final Object value, final boolean forecast, final CommentCallback callback) { Dialogs.commentDialog(main, "Pivitykseen littyvt listiedot", "Tee muutokset", new CommentCallback() { @Override public void runWithComment(String shortComment, String comment) { update(main, base, value, forecast, shortComment, comment); Updates.update(main, true); if (callback != null) callback.runWithComment(shortComment, comment); } @Override public void canceled() { if (callback != null) callback.canceled(); } }); } }