001/*
002 * This library is part of OpenCms -
003 * the Open Source Content Management System
004 *
005 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com)
006 *
007 * This library is free software; you can redistribute it and/or
008 * modify it under the terms of the GNU Lesser General Public
009 * License as published by the Free Software Foundation; either
010 * version 2.1 of the License, or (at your option) any later version.
011 *
012 * This library is distributed in the hope that it will be useful,
013 * but WITHOUT ANY WARRANTY; without even the implied warranty of
014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015 * Lesser General Public License for more details.
016 *
017 * For further information about Alkacon Software, please see the
018 * company website: http://www.alkacon.com
019 *
020 * For further information about OpenCms, please see the
021 * project website: http://www.opencms.org
022 *
023 * You should have received a copy of the GNU Lesser General Public
024 * License along with this library; if not, write to the Free Software
025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
026 */
027
028package org.opencms.ui.apps.modules;
029
030import org.opencms.main.OpenCms;
031import org.opencms.module.CmsModule;
032import org.opencms.ui.A_CmsUI;
033import org.opencms.ui.CmsVaadinUtils;
034import org.opencms.ui.FontOpenCms;
035import org.opencms.ui.apps.A_CmsAttributeAwareApp;
036import org.opencms.ui.apps.Messages;
037import org.opencms.ui.components.CmsBasicDialog;
038import org.opencms.ui.components.CmsBasicDialog.DialogWidth;
039import org.opencms.ui.components.CmsInfoButton;
040import org.opencms.ui.components.CmsToolBar;
041import org.opencms.ui.contextmenu.CmsContextMenu;
042import org.opencms.ui.util.table.CmsBeanTableBuilder;
043
044import java.util.Collections;
045import java.util.LinkedHashSet;
046import java.util.List;
047import java.util.Map;
048import java.util.Set;
049
050import com.google.common.collect.Lists;
051import com.google.common.collect.Maps;
052import com.vaadin.shared.MouseEventDetails.MouseButton;
053import com.vaadin.ui.Button;
054import com.vaadin.ui.Button.ClickEvent;
055import com.vaadin.ui.Button.ClickListener;
056import com.vaadin.ui.Component;
057import com.vaadin.ui.UI;
058import com.vaadin.ui.Window;
059import com.vaadin.ui.themes.ValoTheme;
060import com.vaadin.v7.data.Container;
061import com.vaadin.v7.data.util.BeanItemContainer;
062import com.vaadin.v7.event.FieldEvents.TextChangeEvent;
063import com.vaadin.v7.event.FieldEvents.TextChangeListener;
064import com.vaadin.v7.event.ItemClickEvent;
065import com.vaadin.v7.event.ItemClickEvent.ItemClickListener;
066import com.vaadin.v7.ui.HorizontalLayout;
067import com.vaadin.v7.ui.Table;
068import com.vaadin.v7.ui.TextField;
069
070/**
071 * Overview list for module information.<p>
072 *
073 * @param <T> the row type
074 */
075public class CmsModuleTable<T> extends Table {
076
077    /** The serial version id. */
078    private static final long serialVersionUID = 1L;
079
080    /** The module manager app instance. */
081    protected CmsModuleApp m_app;
082
083    /** The table builder. */
084    protected CmsBeanTableBuilder<T> m_tableBuilder;
085
086    /** The row counter label. */
087    private CmsInfoButton m_counter;
088
089    /** The context menu. */
090    protected CmsContextMenu m_menu = new CmsContextMenu();
091
092    /** The search box. */
093    private TextField m_searchBox = new TextField();
094
095    /**
096     * Creates a new instance.<p>
097     *
098     * @param app the module manager app instance.<p>
099     * @param rowType the row type
100     * @param rows the module rows
101     */
102    public CmsModuleTable(CmsModuleApp app, Class<T> rowType, List<T> rows) {
103
104        m_menu.setAsTableContextMenu(this);
105        m_app = app;
106        addItemClickListener(new ItemClickListener() {
107
108            private static final long serialVersionUID = 1L;
109
110            @Override
111            public void itemClick(ItemClickEvent event) {
112
113                CmsModuleTable.this.onItemClick(event);
114            }
115        });
116        m_searchBox.addTextChangeListener(new TextChangeListener() {
117
118            private static final long serialVersionUID = 1L;
119
120            @Override
121            public void textChange(TextChangeEvent event) {
122
123                String filterString = event.getText();
124                filter(filterString);
125            }
126
127        });
128        m_searchBox.setIcon(FontOpenCms.FILTER);
129        m_searchBox.setInputPrompt(
130            Messages.get().getBundle(UI.getCurrent().getLocale()).key(Messages.GUI_EXPLORER_FILTER_0));
131        m_searchBox.addStyleName(ValoTheme.TEXTFIELD_INLINE_ICON);
132        m_searchBox.setWidth("200px");
133
134        Map<String, Object> attributes = Maps.newHashMap();
135
136        HorizontalLayout hl = new HorizontalLayout();
137        hl.setSpacing(true);
138
139        hl.addComponent(m_searchBox);
140        // hl.setComponentAlignment(m_counter, Alignment.MIDDLE_LEFT);
141        attributes.put(A_CmsAttributeAwareApp.ATTR_INFO_COMPONENT, hl);
142        attributes.put(A_CmsAttributeAwareApp.ATTR_MAIN_HEIGHT_FULL, Boolean.TRUE);
143        List<Component> buttons = Lists.newArrayList();
144        Button addModule = CmsToolBar.createButton(
145            FontOpenCms.WAND,
146            CmsVaadinUtils.getMessageText(Messages.GUI_MODULES_BUTTON_NEW_MODULE_0));
147        addModule.addClickListener(new ClickListener() {
148
149            private static final long serialVersionUID = 1L;
150
151            @Override
152            public void buttonClick(ClickEvent event) {
153
154                m_app.editNewModule(CmsModuleTable.this::reload);
155            }
156        });
157        buttons.add(addModule);
158
159        Button importButton = CmsToolBar.createButton(
160            CmsModuleApp.Icons.IMPORT,
161            CmsVaadinUtils.getMessageText(Messages.GUI_MODULES_BUTTON_IMPORT_0));
162        importButton.addClickListener(new ClickListener() {
163
164            private static final long serialVersionUID = 1L;
165
166            @Override
167            public void buttonClick(ClickEvent event) {
168
169                importModule();
170            }
171        });
172
173        buttons.add(importButton);
174        m_counter = new CmsInfoButton();
175        m_counter.setWindowCaption(CmsVaadinUtils.getMessageText(Messages.GUI_MODULES_STATISTICS_0));
176        m_counter.setDescription(CmsVaadinUtils.getMessageText(Messages.GUI_MODULES_STATISTICS_0));
177        buttons.add(m_counter);
178        attributes.put(CmsModuleApp.Attributes.BUTTONS, buttons);
179        setData(attributes);
180        CmsBeanTableBuilder<T> builder = CmsBeanTableBuilder.newInstance(rowType);
181        m_tableBuilder = builder;
182        builder.buildTable(this, rows);
183        setCellStyleGenerator(builder.getDefaultCellStyleGenerator());
184        setItemIconPropertyId("icon");
185        setRowHeaderMode(RowHeaderMode.ICON_ONLY);
186        setSelectable(true);
187        setMultiSelect(false);
188        sort(new Object[] {"name"}, new boolean[] {true});
189        updateCounter();
190    }
191
192    /**
193     * Applies the given filter.
194     *
195     * @param filterString a filter string
196     */
197    public void filter(String filterString) {
198
199        m_searchBox.setValue(filterString);
200        Container.Filterable container = (Container.Filterable)getContainerDataSource();
201        container.removeAllContainerFilters();
202        container.addContainerFilter(m_tableBuilder.getDefaultFilter(filterString));
203        if ((getValue() != null)) {
204            setCurrentPageFirstItemId(getValue());
205        }
206    }
207
208    /**
209     * Gets the search field.
210     *
211     * @return the search field
212     */
213    public TextField getSearchBox() {
214
215        return m_searchBox;
216    }
217
218    /**
219     * Opens the import module dialog.<p>
220     */
221    public void importModule() {
222
223        Window window = CmsBasicDialog.prepareWindow(DialogWidth.wide);
224        CmsImportTabForm form = new CmsImportTabForm(m_app, this::reload);
225        window.setContent(form);
226        window.setCaption(CmsVaadinUtils.getMessageText(Messages.GUI_MODULES_IMPORT_TITLE_0));
227        A_CmsUI.get().addWindow(window);
228        window.center();
229    }
230
231    /**
232     * Reloads the table data.<p>
233     */
234    public void reload() {
235
236        List<CmsModule> modules = OpenCms.getModuleManager().getAllInstalledModules();
237        @SuppressWarnings("unchecked")
238        BeanItemContainer<CmsModuleRow> container = (BeanItemContainer<CmsModuleRow>)getContainerDataSource();
239        container.removeAllItems();
240        List<CmsModuleRow> newRows = Lists.newArrayList();
241        for (CmsModule module : modules) {
242            CmsModuleRow row = new CmsModuleRow(module);
243            newRows.add(row);
244        }
245        container.addAll(newRows);
246        sort();
247        updateCounter();
248    }
249
250    /**
251     * Handles the table item clicks.<p>
252     *
253     * @param event the click event
254     */
255    protected void onItemClick(ItemClickEvent event) {
256
257        if (!event.isCtrlKey() && !event.isShiftKey()) {
258
259            Set<String> nameSet = new LinkedHashSet<String>();
260
261            CmsModuleRow moduleRow = (CmsModuleRow)(event.getItemId());
262            select(moduleRow);
263            nameSet.add(moduleRow.getModule().getName());
264            if (event.getButton().equals(MouseButton.RIGHT) || (event.getPropertyId() == null)) {
265                select(moduleRow);
266                m_menu.setEntries(m_app.getMenuEntries(), nameSet);
267                m_menu.openForTable(event, this);
268            } else if (event.getButton().equals(MouseButton.LEFT) && "name".equals(event.getPropertyId())) {
269
270                m_app.openModuleInfo(nameSet);
271            }
272
273        }
274    }
275
276    /**
277     * Updates the row counter.<p>
278     */
279    private void updateCounter() {
280
281        m_counter.replaceData(
282            Collections.singletonMap(
283                CmsVaadinUtils.getMessageText(Messages.GUI_MODULES_STATISTICS_ROW_COUNT_0),
284                String.valueOf(getContainerDataSource().size())));
285    }
286
287}