/* * Copyright 2009-2015 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jdal.vaadin.ui.table; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Set; import org.jdal.beans.MessageSourceWrapper; import org.jdal.ui.EditorEvent; import org.jdal.ui.EditorListener; import org.jdal.vaadin.data.ItemUtils; import org.jdal.vaadin.ui.ApplicationContextGuiFactory; import org.jdal.vaadin.ui.FormUtils; import org.jdal.vaadin.ui.GuiFactory; import org.jdal.vaadin.ui.VaadinView; import org.jdal.vaadin.ui.form.ViewDialog; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.context.MessageSource; import org.springframework.util.ClassUtils; import org.springframework.util.ReflectionUtils; import com.vaadin.data.Container; import com.vaadin.data.Item; import com.vaadin.data.util.BeanItemContainer; import com.vaadin.event.ItemClickEvent; import com.vaadin.event.ItemClickEvent.ItemClickListener; import com.vaadin.ui.Button; import com.vaadin.ui.Component; import com.vaadin.ui.CustomComponent; import com.vaadin.ui.HorizontalLayout; import com.vaadin.ui.Table; import com.vaadin.ui.VerticalLayout; /** * Table based editor. * * @author Jose Luis Martin * @since 2.1 */ public class TableComponent<T> extends CustomComponent implements ItemClickListener { /** the table */ private Table table; /** container to use when using external paginator */ private Container container; /** Form editor name */ private String editor; /** View dialog name */ private String dialog = ApplicationContextGuiFactory.VIEW_DIALOG; /** Gui Factory used to get editor instances */ @Autowired private GuiFactory guiFactory; /** TableAction List */ private List<TableButtonListener> actions = new ArrayList<TableButtonListener>(); /** the entity class */ private Class<T> entityClass; /** use native buttons */ private boolean nativeButtons; /** Message Source */ private MessageSourceWrapper messageSource = new MessageSourceWrapper(); /** Container class to use */ private Class<?extends Container> containerClass = BeanItemContainer.class; private VerticalLayout verticalLayout = new VerticalLayout(); private List<EditorListener> editorListeners = new ArrayList<EditorListener>(); public TableComponent() { this(null); } /** * @param entityClass */ public TableComponent(Class<T> entityClass) { this.entityClass = entityClass; this.setCompositionRoot(this.verticalLayout); } /** * Create the BeanContainer to use. * @param beanClass bean type in container * @param data intial data. * @return a new BeanContainer */ protected Container createBeanContainer(Class<T> beanClass, List<T> data) { Constructor<?extends Container> ctor = ClassUtils.getConstructorIfAvailable(this.containerClass, Class.class, Collection.class); if (ctor != null) return BeanUtils.instantiateClass(ctor, beanClass, data); return new BeanItemContainer<T>(beanClass, data); } /** * Create a ButtonBox from TableAction List * @return HorizontalLayout with Buttons */ protected Component createButtonBox() { HorizontalLayout hl = new HorizontalLayout(); hl.setSpacing(true); for (TableButtonListener a : actions) { a.setTable(this); Button b = FormUtils.newButton(a, this.nativeButtons); hl.addComponent(b); } return hl; } /** * Get default form for edit or add models; * @return form editor */ @SuppressWarnings("unchecked") public VaadinView<T> getEditorView() { // If there are a cofigured form editor return it. if (editor != null) { VaadinView<T> view = (VaadinView<T>) guiFactory.getView(editor); return view; } return null; } @SuppressWarnings("unchecked") public Collection<T> getSelected() { Set<T> set = new HashSet<T>(); Object selection = getTable().getValue(); if (selection == null) return set; if (selection instanceof Collection) { return (Collection<T>) selection; } else { set.add((T) selection); return set; } } /** * {@inheritDoc} */ public void itemClick(ItemClickEvent event) { if (event.isDoubleClick()) { VaadinView<T> editor = getEditorView(); if (editor != null) { Item item = event.getItem(); editor.setModel(getBean(item)); editor.refresh(); editor.addEditorListener(new EditorListener() { public void modelChanged(EditorEvent e) { refresh(); fireEditorEvent(e); } }); ViewDialog dlg = this.guiFactory.newViewDialog(editor, this.dialog); dlg.init(); dlg.center(); this.getUI().addWindow(dlg); } } } /** * Get the wrapped bean from item calling to getMethod by reflection. * @param item item * @return wrapped bean */ @SuppressWarnings("unchecked") protected T getBean(Item item) { return (T) ItemUtils.getBean(item); } public void refresh() { // do nothing by default } public void setWidthFull() { this.setWidth("100%"); this.verticalLayout.setWidth("100%"); this.table.setWidth("100%"); } /** * Create default table actinons * @return list with add, refresh and remove actions. */ public List<TableButtonListener> createDefaultActions() { ArrayList<TableButtonListener> defaultActions = new ArrayList<TableButtonListener>(); defaultActions.add(new AddAction()); defaultActions.add(new RefreshAction()); defaultActions.add(new RemoveAction()); return defaultActions; } /** * By default, pageable table handle item clicks to edit items. * This method disable it. */ public void disableEditorListener() { getTable().removeItemClickListener(this); } public void enableEditorListener() { getTable().addItemClickListener(this); } public void addItemClickListener(ItemClickListener listener) { getTable().addItemClickListener(listener); } public void removeItemClickListener(ItemClickListener listener) { getTable().removeItemClickListener(listener); } public void addEditorListener(EditorListener l) { if (!this.editorListeners.contains(l)) this.editorListeners.add(l); } public void removeEditorListener(EditorListener l) { this.editorListeners.remove(l); } protected void fireEditorEvent(EditorEvent e) { for (EditorListener el : this.editorListeners) el.modelChanged(e); } public Table getTable() { return table; } public void setTable(Table table) { this.table = table; } /** * @return the editor * @deprecated use getEditorName instead */ public String getEditor() { return editor; } /** * @param editor the editor to se * @deprecated use getEditorName instead */ public void setEditor(String editor) { this.editor = editor; } /** * @return the editor name */ public String getEditorName() { return editor; } /** * @param editorName the editor to se */ public void setEditorName(String editorName) { this.editor = editorName; } /** * @return the guiFactory */ public GuiFactory getGuiFactory() { return guiFactory; } /** * @param guiFactory the guiFactory to set */ public void setGuiFactory(GuiFactory guiFactory) { this.guiFactory = guiFactory; } /** * @return the actions */ public List<TableButtonListener> getActions() { return actions; } /** * @param actions the actions to set */ public void setActions(List<TableButtonListener> actions) { this.actions = actions; for (TableButtonListener action : this.actions) { action.setTable(this); } } /** * @return the entityClass */ public Class<T> getEntityClass() { return entityClass; } /** * @param entityClass the entityClass to set */ public void setEntityClass(Class<T> entityClass) { this.entityClass = entityClass; } /** * @param selected */ public void delete(Collection<?> selected) { for (Object item : selected) container.removeItem(item); } /** * @return the verticalLayout */ public VerticalLayout getVerticalLayout() { return verticalLayout; } /** * @param verticalLayout the verticalLayout to set */ public void setVerticalLayout(VerticalLayout verticalLayout) { this.verticalLayout = verticalLayout; } public boolean isSelectable() { return this.isSelectable(); } public void setSelectable(boolean selectable) { this.table.setSelectable(selectable); } public boolean isNativeButtons() { return nativeButtons; } public void setNativeButtons(boolean nativeButtons) { this.nativeButtons = nativeButtons; } public Container getContainer() { return container; } public void setContainer(Container container) { this.container = container; } public MessageSource getMessageSource() { return messageSource.getMessageSource(); } @Autowired public void setMessageSource(MessageSource messageSource) { this.messageSource.setMessageSource(messageSource); } public String getMessage(String code) { return this.messageSource.getMessage(code); } /** * @return the containerClass */ public Class<? extends Container> getContainerClass() { return containerClass; } /** * @param containerClass the containerClass to set */ public void setContainerClass(Class<? extends Container> containerClass) { this.containerClass = containerClass; } /** * @return the dialog */ public String getDialog() { return dialog; } /** * @param dialog the dialog to set */ public void setDialog(String dialog) { this.dialog = dialog; } }