package org.aperteworkflow.util.vaadin; import com.vaadin.Application; import com.vaadin.data.Container; import com.vaadin.data.Property; import com.vaadin.data.util.MethodProperty; import com.vaadin.event.ItemClickEvent.ItemClickListener; import com.vaadin.service.ApplicationContext; import com.vaadin.terminal.ClassResource; import com.vaadin.terminal.FileResource; import com.vaadin.terminal.Resource; import com.vaadin.terminal.Sizeable; import com.vaadin.terminal.gwt.server.PortletApplicationContext2; import com.vaadin.ui.*; import com.vaadin.ui.Table.ColumnGenerator; import com.vaadin.ui.Window.Notification; import com.vaadin.ui.themes.Reindeer; import org.aperteworkflow.util.vaadin.ui.table.LocalizedPagedTable; import org.vaadin.dialogs.ConfirmDialog; import pl.net.bluesoft.rnd.processtool.ProcessToolContextFactory; import pl.net.bluesoft.rnd.processtool.plugins.ProcessToolRegistry; import pl.net.bluesoft.rnd.processtool.ui.widgets.ProcessToolDataWidget; import pl.net.bluesoft.rnd.processtool.ui.widgets.impl.BaseProcessToolWidget; import pl.net.bluesoft.rnd.util.i18n.I18NSource; import pl.net.bluesoft.util.lang.StringUtil; import java.io.File; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Collection; import java.util.List; import java.util.Map; import static com.vaadin.ui.Window.Notification.*; import static org.aperteworkflow.util.vaadin.VaadinExceptionHandler.Util.withErrorHandling; /** * @author tlipski@bluesoft.net.pl */ public class VaadinUtility { public static final String SIMPLE_DATE_FORMAT_STRING = "yyyy-MM-dd"; public static final String FULL_DATE_FORMAT_STRING = "yyyy-MM-dd HH:mm:ss"; private static final String REGISTER_CLOSE_WARNING = " registerCloseHandler(function() { return \"%s\"; }); "; private static final String UNREGISTER_CLOSE_WARNING = " clearCloseHandler(); "; public static DateFormat simpleDateFormat() { return new SimpleDateFormat(SIMPLE_DATE_FORMAT_STRING); } public static DateFormat fullDateFormat() { return new SimpleDateFormat(FULL_DATE_FORMAT_STRING); } public static ProcessToolContextFactory getProcessToolContext(ApplicationContext applicationContext) { ProcessToolRegistry factory = null; if (applicationContext instanceof PortletApplicationContext2) { PortletApplicationContext2 portletCtx = (PortletApplicationContext2) applicationContext; factory = (ProcessToolRegistry) portletCtx.getPortletConfig() .getPortletContext() .getAttribute(ProcessToolRegistry.class.getName()); } return factory != null ? factory.getProcessToolContextFactory() : null; } public static HorizontalLayout horizontalLayout(String width, com.vaadin.ui.Component... components) { HorizontalLayout hl = new HorizontalLayout(); hl.setSpacing(true); hl.setWidth(width); if (components != null) { for (com.vaadin.ui.Component c : components) { hl.addComponent(c); } } return hl; } public static HorizontalLayout fullHorizontalLayout(com.vaadin.ui.Component... components) { return horizontalLayout("100%", components); } public static VerticalLayout verticalLayout(com.vaadin.ui.Component... components) { VerticalLayout vl = new VerticalLayout(); vl.setSpacing(true); vl.setWidth(100, Sizeable.UNITS_PERCENTAGE); if (components != null) { for (com.vaadin.ui.Component c : components) { if (c != null) { vl.addComponent(c); } } } return vl; } public static CheckBox checkBox(String caption) { CheckBox cb = new CheckBox(); if (caption != null) { cb.setCaption(caption); } cb.setValue(false); cb.setImmediate(true); cb.setWidth(100, Sizeable.UNITS_PERCENTAGE); return cb; } public static Select select(String caption, Container container, String itemCaptionPropertyId) { Select select = new Select(caption); select.setNullSelectionAllowed(true); select.setNullSelectionItemId(null); select.setImmediate(true); select.setContainerDataSource(container); select.setItemCaptionMode(Select.ITEM_CAPTION_MODE_PROPERTY); select.setItemCaptionPropertyId(itemCaptionPropertyId); select.setSizeUndefined(); select.setFilteringMode(AbstractSelect.Filtering.FILTERINGMODE_CONTAINS); return select; } public static Panel panel(String title, com.vaadin.ui.Component... components) { Panel p = new Panel(); p.setWidth(100, Sizeable.UNITS_PERCENTAGE); p.setCaption(title); for (com.vaadin.ui.Component c : components) { p.addComponent(c); } return p; } public static Label label(String message, int width) { Label l = new Label(message); l.setWidth(width, Sizeable.UNITS_PIXELS); return l; } public static HorizontalLayout horizontalLayout(com.vaadin.ui.Component c1, com.vaadin.ui.Component c2) { HorizontalLayout hl = new HorizontalLayout(); hl.setWidth(100, Sizeable.UNITS_PERCENTAGE); hl.setSpacing(true); hl.addComponent(c1); hl.addComponent(c2); hl.setComponentAlignment(c2, Alignment.TOP_RIGHT); hl.setExpandRatio(c1, 1.0f); return hl; } public static HorizontalLayout horizontalLayout(Alignment alignment, com.vaadin.ui.Component... components) { HorizontalLayout hl = new HorizontalLayout(); hl.setWidth(100, Sizeable.UNITS_PERCENTAGE); hl.setSpacing(true); if (components != null && components.length > 0) { for (com.vaadin.ui.Component c : components) { hl.addComponent(c); hl.setComponentAlignment(c, alignment); } if (alignment.isRight()) { hl.setExpandRatio(hl.getComponent(0), 1.0f); } else if (alignment.isLeft()) { hl.setExpandRatio(hl.getComponent(hl.getComponentCount() - 1), 1.0f); } } return hl; } public static Notification validationNotification(String caption, String description) { Notification notification = new Notification(caption, description, Notification.TYPE_ERROR_MESSAGE); notification.setStyleName("invalid"); return notification; } public static Table simpleTable(Container dataSource, Object[] visiblePropertyIds, Map<String, ColumnGenerator> customColumns) { Table table = new Table(); table.addStyleName("big striped borderless"); table.setSizeFull(); table.setPageLength(0); table.setImmediate(false); table.setSelectable(false); table.setColumnHeaderMode(Table.COLUMN_HEADER_MODE_HIDDEN); table.setColumnCollapsingAllowed(false); table.setSortDisabled(true); if (customColumns != null) { for (Map.Entry<String, ColumnGenerator> entry : customColumns.entrySet()) { table.addGeneratedColumn(entry.getKey(), entry.getValue()); } } table.setContainerDataSource(dataSource); table.setVisibleColumns(visiblePropertyIds); table.setColumnExpandRatio(visiblePropertyIds[visiblePropertyIds.length - 1], 1.0f); return table; } public static LocalizedPagedTable pagedTable(final Container container, String[] visibleViewColumns, String[] columnViewHeaders, Map<String, ColumnGenerator> customViewColumns, ItemClickListener itemClickListener) { LocalizedPagedTable table = new LocalizedPagedTable(); table.addStyleName("striped strong"); table.setSizeFull(); table.setPageLength(10); table.setImmediate(true); table.setSelectable(true); table.setContainerDataSource(container); if (itemClickListener != null) { table.addListener(itemClickListener); } if (customViewColumns != null && !customViewColumns.isEmpty()) { for (Map.Entry<String, ColumnGenerator> entry : customViewColumns.entrySet()) { table.addGeneratedColumn(entry.getKey(), entry.getValue()); } } table.setVisibleColumns(visibleViewColumns); table.setColumnHeaders(columnViewHeaders); table.setSortAscending(true); table.setSortContainerPropertyId(visibleViewColumns[0]); return table; } public static VerticalLayout wrapPagedTable(I18NSource messageSource, LocalizedPagedTable table) { VerticalLayout tableCarrier = new VerticalLayout(); tableCarrier.setWidth(100, Sizeable.UNITS_PERCENTAGE); tableCarrier.addComponent(table); tableCarrier.addComponent(tableControls(messageSource, table)); return tableCarrier; } public static HorizontalLayout tableControls(I18NSource messageSource, LocalizedPagedTable table) { return table.createControls(messageSource); } public static Label boldLabel(String text) { return new Label("<b>" + text + "</b>", Label.CONTENT_XHTML); } public static Label hr() { return new Label("<hr/>", Label.CONTENT_XHTML); } public static Button smallButton(String caption) { Button button = new Button(caption); button.setImmediate(true); button.setStyleName("default small"); return button; } public static Button link(String caption, Resource icon, Button.ClickListener listener) { Button b = button(caption, null, "link", listener); b.setIcon(icon); b.setWidth(b.getWidth() + 10, Sizeable.UNITS_PIXELS); return b; } public static Button link(String caption, Button.ClickListener listener) { return button(caption, null, "link", listener); } public static Button link(String caption) { return link(caption, null); } public static Button button(String caption, String description, String style) { return button(caption, description, style, null); } public static Button button(String caption, String description, String style, Button.ClickListener listener) { Button button = new Button(caption); if (description != null) { button.setDescription(description); } if(style != null) button.setStyleName(style); if (listener != null) { button.addListener(listener); } button.setImmediate(true); button.setWidth(haxWidth(caption, (style != null ? style.contains("link") : false))); return button; } /* * IE7 be doomed!!! */ private static String haxWidth(String base, boolean link) { //linear regression: button 7.5x + 35, link: 6.75x + 10 return (StringUtil.hasText(base) ? base.length() * (link ? 6.75 : 7.5) + (link ? 10 : 40) : -1) + "px"; } public static Window modalWindow(String title, ComponentContainer content) { Window window = new Window(title, content); window.setClosable(false); window.setModal(true); window.setSizeUndefined(); return window; } public static void informationNotification(Application application, String message) { informationNotification(application, message, 3000); } public static void informationNotification(Application application, String message, int delay) { Notification notification = new Notification("<b>" + message + "</b>", TYPE_HUMANIZED_MESSAGE); notification.setPosition(POSITION_CENTERED); notification.setDelayMsec(delay); application.getMainWindow().showNotification(notification); } public static void validationNotification(Application application, I18NSource messageSource, String errorMessage) { Notification notification = new Notification(messageSource.getMessage("process.data.data-error"), "<br/>" + errorMessage, Notification.TYPE_ERROR_MESSAGE); notification.setStyleName("invalid"); application.getMainWindow().showNotification(notification); } public static Button addIcon(Application application) { return icon(application, "add.png"); } public static Button deleteIcon(Application application) { return icon(application, "delete.png"); } public static Button copyIcon(Application application) { return icon(application, "copy.png"); } public static Button refreshIcon(Application application) { return icon(application, "view_refresh.png"); } public static Button refreshIcon(final Application application, final Refreshable refreshable) { Button b = refreshIcon(application); b.setWidth(18, Sizeable.UNITS_PIXELS); b.addListener(new Button.ClickListener() { @Override public void buttonClick(Button.ClickEvent event) { withErrorHandling(application, new Runnable() { @Override public void run() { refreshable.refreshData(); } }); } }); return b; } public static interface Refreshable { void refreshData(); } public static Button icon(Application application, String fileName) { return icon(application, fileName, null); } public static Button icon(Application application, String fileName, Button.ClickListener listener) { return icon(imageResource(application, fileName), listener); } public static Button icon(Resource icon, Button.ClickListener listener) { return icon(null, icon, listener); } public static Button icon(String description, Resource icon, Button.ClickListener listener) { Button b = new Button(); b.setStyleName("link"); b.setIcon(icon); b.setImmediate(true); b.setDescription(description); if (listener != null) { b.addListener(listener); } return b; } public static ClassResource imageResource(Application application, String fileName) { return new ClassResource(VaadinUtility.class, "/img/" + fileName, application); } public static Embedded embedded(Application application, String fileName) { return new Embedded(null, new ClassResource(VaadinUtility.class, fileName, application)); } public static String widgetsErrorMessage(I18NSource i18NSource, Map<ProcessToolDataWidget, Collection<String>> errorMap) { StringBuilder errorMessage = new StringBuilder("<ul>"); for (Map.Entry<ProcessToolDataWidget, Collection<String>> entry : errorMap.entrySet()) { ProcessToolDataWidget w = entry.getKey(); Collection<String> col = entry.getValue(); String caption = null; if (w instanceof BaseProcessToolWidget) { caption = ((BaseProcessToolWidget) w).getAttributeValue("caption"); } if (caption != null) { errorMessage.append("<li>").append(i18NSource.getMessage(caption)).append("<ul>"); } for (String m : col) { errorMessage.append("<li>").append(i18NSource.getMessage(m)).append("</li>\n"); } if (caption != null) { errorMessage.append("</ul></li>"); } } errorMessage.append("</ul>"); return errorMessage.toString(); } public static String formErrorMessage(Collection<String> errorMap) { StringBuilder errorMessage = new StringBuilder("<ul>"); for (String msg : errorMap) { errorMessage.append("<li>").append(msg).append("</li>\n"); } errorMessage.append("</ul>"); return errorMessage.toString(); } public static void displayConfirmationWindow(Application application, I18NSource i18NSource, String title, String question, final EventHandler okEvent, final EventHandler cancelEvent) { displayConfirmationWindow(application, i18NSource, title, question, okEvent, cancelEvent, i18NSource.getMessage("button.ok"), i18NSource.getMessage("button.cancel")); } public static void displayConfirmationWindow(Application application, I18NSource i18NSource, String title, String question, final EventHandler okEvent, final EventHandler cancelEvent, String okButtonLabel, String cancelButtonLabel) { final Window newConfirmationWindow = new Window(title); newConfirmationWindow.setModal(true); newConfirmationWindow.setBorder(0); newConfirmationWindow.setClosable(false); newConfirmationWindow.setWidth(500, Sizeable.UNITS_PIXELS); VerticalLayout vl = new VerticalLayout(); vl.setSpacing(true); HorizontalLayout hl = new HorizontalLayout(); hl.setSpacing(true); Button okButton = button(i18NSource.getMessage(okButtonLabel), null, "default", new Button.ClickListener() { @Override public void buttonClick(Button.ClickEvent event) { newConfirmationWindow.getParent().removeWindow(newConfirmationWindow); if (okEvent != null) { okEvent.onEvent(); } } }); hl.addComponent(okButton); Button cancelButton = button(i18NSource.getMessage(cancelButtonLabel), null, "default", new Button.ClickListener() { @Override public void buttonClick(Button.ClickEvent event) { newConfirmationWindow.getParent().removeWindow(newConfirmationWindow); if (cancelEvent != null) { cancelEvent.onEvent(); } } }); if (cancelEvent != null) { newConfirmationWindow.addListener(new Window.CloseListener() { @Override public void windowClose(Window.CloseEvent e) { cancelEvent.onEvent(); } }); } hl.addComponent(cancelButton); vl.addComponent(new Label(question)); vl.addComponent(hl); vl.setComponentAlignment(hl, Alignment.BOTTOM_CENTER); newConfirmationWindow.addComponent(vl); application.getMainWindow().addWindow(newConfirmationWindow); } public static void displayConfirmationWindow(Application application, I18NSource i18NSource, String title, String question, final String[] labels, final EventHandler[] events, final EventHandler cancelEvent) { final Window newConfirmationWindow = new Window(title); newConfirmationWindow.setModal(true); newConfirmationWindow.setBorder(0); newConfirmationWindow.setClosable(false); newConfirmationWindow.setWidth(500, Sizeable.UNITS_PIXELS); VerticalLayout vl = new VerticalLayout(); vl.setSpacing(true); HorizontalLayout hl = new HorizontalLayout(); hl.setSpacing(true); for (int i = 0; i < events.length; ++i) { final EventHandler buttonEvent = events[i]; final String buttonLabel = labels[i]; if (buttonLabel != null) { Button button = button(i18NSource.getMessage(buttonLabel), null, "default", new Button.ClickListener() { @Override public void buttonClick(Button.ClickEvent event) { newConfirmationWindow.getParent().removeWindow(newConfirmationWindow); if (buttonEvent != null) { buttonEvent.onEvent(); } } }); hl.addComponent(button); } } if (cancelEvent != null) { newConfirmationWindow.addListener(new Window.CloseListener() { @Override public void windowClose(Window.CloseEvent e) { cancelEvent.onEvent(); } }); } vl.addComponent(new Label(question)); vl.addComponent(hl); vl.setComponentAlignment(hl, Alignment.BOTTOM_CENTER); newConfirmationWindow.addComponent(vl); application.getMainWindow().addWindow(newConfirmationWindow); } public static HorizontalLayout labelWithIcon(Resource image, String caption, String style, String description) { Embedded img = new Embedded(null, image); img.setDescription(description); Label label = new Label(caption, Label.CONTENT_XHTML); label.setDescription(description); if (style != null) { label.setStyleName(style); } HorizontalLayout hl = VaadinUtility.horizontalLayout(Alignment.MIDDLE_LEFT, img, label); hl.setWidth(-1, Sizeable.UNITS_PIXELS); return hl; } public static void registerClosingWarning(Window window, String warningMessage) { String msg = String.format(REGISTER_CLOSE_WARNING, warningMessage); window.executeJavaScript(msg); } public static void unregisterClosingWarning(Window window) { window.executeJavaScript(UNREGISTER_CLOSE_WARNING); } ///////////////////////////////////////////////////// ///////////////////////////////////////////////////// public static void errorNotification(Application application, I18NSource messageSource, String message) { Notification notification = new Notification(messageSource.getMessage("notification.error"), "<br/><b>" + message + "</b>", TYPE_ERROR_MESSAGE); notification.setPosition(POSITION_CENTERED); notification.setStyleName("error"); application.getMainWindow().showNotification(notification); } public static Label htmlLabel(String message, int width) { Label l = new Label(message, Label.CONTENT_XHTML); l.setWidth(width, Sizeable.UNITS_PIXELS); return l; } public static Label htmlLabel(String message) { return new Label(message, Label.CONTENT_XHTML); } public static HorizontalLayout hl(com.vaadin.ui.Component... components) { HorizontalLayout hl = new HorizontalLayout(); hl.setWidth(100, Sizeable.UNITS_PERCENTAGE); hl.setSpacing(true); for (Component c : components) { hl.addComponent(c); } return hl; } public static Embedded embedded(Application application, File file) { return new Embedded(null, new FileResource(file, application)); } public static String getLocalizedMessage(String key) { return I18NSource.ThreadUtil.getLocalizedMessage(key); } public static <T extends Component> T styled(T c, String style) { c.addStyleName(style); return c; } public static Runnable confirmable(final Application app, final String windowCaption, final String message, final Runnable runnable) { return new Runnable() { @Override public void run() { ConfirmDialog.show(app.getMainWindow(), windowCaption, message, getLocalizedMessage("confirm.yes"), getLocalizedMessage("confirm.no"), new ConfirmDialog.Listener() { @Override public void onClose(ConfirmDialog confirmDialog) { if (confirmDialog.isConfirmed()) { runnable.run(); } } }); } }; } public static Button linkButton(String caption, final Runnable onClick) { Button b = button(caption, onClick); b.setStyleName(Reindeer.BUTTON_LINK); return b; } public static Button button(String caption, final Runnable onClick) { Button b = new Button(caption); b.addListener(new Button.ClickListener() { @Override public void buttonClick(Button.ClickEvent event) { onClick.run(); } }); return b; } public static <T extends Component> T width(T c, String width) { c.setWidth(width); return c; } public static <C extends Component> Component joinHorizontally(List<C> components) { switch (components.size()) { case 0: return null; case 1: return components.get(0); default: HorizontalLayout hl = new HorizontalLayout(); for (Component c : components) { hl.addComponent(c); } return hl; } } public static <V extends Property.Viewer, T> V bindProperty(V viewer, T object, String property) { viewer.setPropertyDataSource(new MethodProperty(object, property)); return viewer; } }