Java tutorial
/* * Copyright 2003 - 2016 The eFaps Team * * 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.efaps.ui.wicket.components.gridx; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.RandomStringUtils; import org.apache.commons.lang3.StringEscapeUtils; import org.apache.commons.lang3.StringUtils; import org.apache.wicket.Page; import org.apache.wicket.RestartResponseException; import org.apache.wicket.ajax.AbstractDefaultAjaxBehavior; import org.apache.wicket.ajax.AjaxRequestTarget; import org.apache.wicket.ajax.attributes.CallbackParameter; import org.apache.wicket.markup.ComponentTag; import org.apache.wicket.markup.MarkupStream; import org.apache.wicket.markup.head.CssHeaderItem; import org.apache.wicket.markup.head.IHeaderResponse; import org.apache.wicket.markup.html.WebComponent; import org.apache.wicket.markup.html.form.Form; import org.apache.wicket.markup.html.link.ILinkListener; import org.apache.wicket.model.IModel; import org.apache.wicket.request.mapper.parameter.PageParameters; import org.apache.wicket.request.resource.CssResourceReference; import org.apache.wicket.request.resource.ResourceReference; import org.apache.wicket.util.string.StringValue; import org.apache.wicket.util.string.StringValueConversionException; import org.apache.wicket.util.visit.IVisit; import org.apache.wicket.util.visit.IVisitor; import org.efaps.admin.ui.AbstractCommand; import org.efaps.admin.ui.AbstractCommand.Target; import org.efaps.admin.ui.AbstractMenu; import org.efaps.admin.ui.Menu; import org.efaps.api.ui.FilterBase; import org.efaps.api.ui.FilterType; import org.efaps.db.Context; import org.efaps.ui.wicket.behaviors.dojo.AbstractDojoBehavior; import org.efaps.ui.wicket.components.gridx.behaviors.OpenModalBehavior; import org.efaps.ui.wicket.components.gridx.behaviors.SubmitBehavior; import org.efaps.ui.wicket.components.gridx.behaviors.SubmitModalBehavior; import org.efaps.ui.wicket.models.objects.UIGrid; import org.efaps.ui.wicket.models.objects.UIGrid.Cell; import org.efaps.ui.wicket.models.objects.UIGrid.Column; import org.efaps.ui.wicket.pages.content.structurbrowser.StructurBrowserPage; import org.efaps.ui.wicket.pages.contentcontainer.ContentContainerPage; import org.efaps.ui.wicket.pages.error.ErrorPage; import org.efaps.ui.wicket.util.DojoClass; import org.efaps.ui.wicket.util.DojoClasses; import org.efaps.ui.wicket.util.DojoWrapper; import org.efaps.util.EFapsException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * TODO comment! * * @author The eFaps Team */ public class GridXComponent extends WebComponent implements ILinkListener { /** * Reference to the stylesheet. */ public static final ResourceReference CSS = new CssResourceReference(AbstractDojoBehavior.class, "gridx/resources/claro/Gridx.css"); /** The Constant serialVersionUID. */ private static final long serialVersionUID = 1L; /** * Logger for this class. */ private static final Logger LOG = LoggerFactory.getLogger(GridXComponent.class); /** * Instantiates a new grid component. * * @param _wicketId the wicket id * @param _model the model */ public GridXComponent(final String _wicketId, final IModel<UIGrid> _model) { super(_wicketId, _model); setOutputMarkupId(true); add(new PersistAjaxBehavior()); } @Override public void renderHead(final IHeaderResponse _response) { super.renderHead(_response); _response.render(CssHeaderItem.forReference(GridXComponent.CSS)); } @Override public void onComponentTagBody(final MarkupStream _markupStream, final ComponentTag _openTag) { try { final UIGrid uiGrid = (UIGrid) getDefaultModelObject(); final Set<DojoClass> dojoClasses = new HashSet<>(); Collections.addAll(dojoClasses, DojoClasses.array, DojoClasses.lang, DojoClasses.json, DojoClasses.aspect, DojoClasses.query, DojoClasses.domConstruct, DojoClasses.win, DojoClasses.domStyle, DojoClasses.ready, DojoClasses.on, DojoClasses.registry, DojoClasses.Memory, DojoClasses.Grid, DojoClasses.VirtualVScroller, DojoClasses.ColumnResizer, DojoClasses.HScroller, DojoClasses.SingleSort, DojoClasses.SyncCache, DojoClasses.HeaderDialog, DojoClasses.MoveColumn, DojoClasses.SelectColumn, DojoClasses.SelectCell, DojoClasses.DnDColumn, DojoClasses.HiddenColumns, DojoClasses.GridConfig, DojoClasses.GridSort, DojoClasses.Summary, DojoClasses.QuickFilter, DojoClasses.Bar, DojoClasses.Persist, DojoClasses.Filter, DojoClasses.FilterBar, DojoClasses.DropDownButton, DojoClasses.TextBox, DojoClasses.TooltipDialog, DojoClasses.ready, DojoClasses.domGeom); final StringBuilder js = new StringBuilder().append("var cp = function(_attr, _itemA, _itemB) {\n") .append("var strA = _itemA.hasOwnProperty(_attr + '_sort')") .append(" ? _itemA[_attr + '_sort'] : _itemA[_attr];\n") .append("var strB = _itemB.hasOwnProperty(_attr + '_sort') ") .append("? _itemB[_attr + '_sort'] : _itemB[_attr];\n") .append("return strA < strB ? -1 : (strA > strB ? 1 : 0);\n").append("}\n") .append("var store = new Memory({\n").append("data: ").append(GridXComponent.getDataJS(uiGrid)) .append("});\n").append("var structure = [\n"); boolean first = true; int j = 0; for (final Column header : uiGrid.getColumns()) { if (first) { first = false; } else { js.append(","); } js.append("{ id:'").append(header.getField().getId()).append("',").append(" field:'") .append(header.getFieldName()).append("',").append(" name:'").append(header.getLabel()) .append("'\n"); if (!"left".equals(header.getField().getAlign())) { js.append(", style:'text-align:right'"); } js.append(", comparator: cp\n"); if (header.getFieldConfig().getField().getReference() != null) { js.append(", decorator: function(data, rowId, visualIndex, cell){\n") .append("return '<a href=\"") .append(urlFor(ILinkListener.INTERFACE, new PageParameters())).append("&rowId=") .append("' + rowId + '").append("&colId=").append(j).append("\">' + data + '</a>';\n") .append("}\n"); } if (FilterBase.DATABASE.equals(header.getFilter().getBase())) { js.append(", dialog: 'fttd_").append(header.getField().getId()) .append("', headerClass:'eFapsFiltered'\n"); } else if (FilterType.PICKLIST.equals(header.getFilter().getType())) { js.append(", dataType: 'enum'\n"); final List<String> picklist = uiGrid.getFilterPickList(header); if (CollectionUtils.isNotEmpty(picklist)) { js.append(", enumOptions: ['").append(StringUtils.join(picklist, "','")).append("']"); } } else { // js.append(", filterable: false\n"); } js.append("}"); j++; } js.append("];\n").append("").append(getMenu(dojoClasses)).append("var grid = Grid({") .append("id: 'grid',").append("cacheClass: Cache,").append("store: store,") .append("structure: structure,\n").append("barTop: [\n"); if (dojoClasses.contains(DojoClasses.MenuBar)) { js.append("{plugin: pMenuBar, style: 'text-align: left;'}, \n"); } js.append("{pluginClass: QuickFilter, style: 'text-align: center;'}, \n") .append("{pluginClass: GridConfig, style: 'text-align: right;'} \n").append("],\n") .append("barBottom: [\n").append("Summary\n").append("],\n").append("modules: [\n") .append("VirtualVScroller,\n").append("ColumnResizer,\n").append("SingleSort,\n") .append("MoveColumn,\n").append("SelectColumn,\n").append("SelectCell,\n") .append("DnDColumn,\n").append("HeaderDialog,\n").append("Bar,\n").append("Filter,\n") .append("FilterBar,\n").append("HScroller,\n").append("HiddenColumns,\n").append("Persist\n"); if (uiGrid.isShowCheckBoxes()) { Collections.addAll(dojoClasses, DojoClasses.IndirectSelect, DojoClasses.RowHeader, DojoClasses.SelectRow); js.append(", IndirectSelect,\n").append("SelectRow,\n").append("RowHeader,\n"); } js.append("],\n").append("persistGet: function(_key) {"); if (Context.getThreadContext().containsUserAttribute(uiGrid.getCacheKey(UIGrid.CacheKey.GRIDX))) { js.append("return ").append( Context.getThreadContext().getUserAttribute(uiGrid.getCacheKey(UIGrid.CacheKey.GRIDX))); } js.append("},\n").append("persistPut: function(_key, _value, _options) {\n").append("var value;") .append("if(_value && lang.isObject(_value)){\n").append("value = json.toJson(_value);\n") .append("}else{\n").append("value = {expires: -1};\n").append("}\n") .append(getBehaviors(PersistAjaxBehavior.class).get(0) .getCallbackFunctionBody(CallbackParameter.explicit("value"))) .append("},\n").append("modelExtensions: [\n").append("GridSort\n").append("]\n").append("});") .append("grid.placeAt('").append(getMarkupId(true)).append("');\n").append("grid.startup();\n") .append("ready(function(){").append("var bar = query('.eFapsFrameTitle') [0];\n") .append("var pos = domGeom.position(bar);\n").append("var vs = win.getBox();\n") .append("var hh = vs.h - pos.h -pos.y;\n").append("registry.byId('grid').resize({h:hh});") .append("});").append("on(window, 'resize', function() {\n") .append("var bar = query('.eFapsFrameTitle') [0];\n") .append("var pos = domGeom.position(bar);\n").append("var vs = win.getBox();\n") .append("var hh = vs.h - pos.h -pos.y;\n").append("registry.byId('grid').resize({h:hh});") .append("});\n"); if (uiGrid.isShowCheckBoxes()) { js.append("aspect.after(grid.select.row, 'onSelectionChange', function (_defferd) {\n") .append("query(\"input[name='selectedRow']\").forEach(domConstruct.destroy);\n") .append("array.forEach(registry.byId('grid').select.row.getSelected(), function (_item) {\n") .append("domConstruct.create('input', {\n").append("type: 'hidden',\n") .append("name:'selectedRow',\n").append("value: _item\n").append("},\n").append("'") .append(findParent(Form.class).getMarkupId(true)).append("');\n").append("});\n") .append("});\n").append("grid.prevSelected = [];\n").append("var ftb = function () {\n") .append("registry.byId('grid').prevSelected = registry.byId('grid').select.row.getSelected();\n") .append("};\n").append("var fta = function () {\n") .append("array.forEach(registry.byId('grid').prevSelected, function (_item) {\n") .append("registry.byId('grid').select.row.selectById(_item);\n").append("});\n") .append("};\n").append("aspect.before(grid.filter, 'setFilter', ftb);\n") .append("aspect.before(grid.filter, 'clearFilter', ftb);\n") .append("aspect.after(grid.filter, 'setFilter', fta);\n") .append("aspect.after(grid.filter, 'clearFilter', fta);\n"); } final StringBuilder html = new StringBuilder().append("<script type=\"text/javascript\">") .append(DojoWrapper.require(js, dojoClasses.toArray(new DojoClass[dojoClasses.size()]))) .append("\n</script>"); replaceComponentTagBody(_markupStream, _openTag, html); } catch (final EFapsException e) { GridXComponent.LOG.error("Catched error", e); } } protected CharSequence getMenu(final Set<DojoClass> _dojoClasses) throws EFapsException { final StringBuilder ret = new StringBuilder(); final UIGrid uiGrid = (UIGrid) getDefaultModelObject(); if (uiGrid.getCommand().getTargetMenu() != null) { Collections.addAll(_dojoClasses, DojoClasses.MenuBar, DojoClasses.DropDownMenu, DojoClasses.MenuItem, DojoClasses.PopupMenuBarItem, DojoClasses.MenuBarItem); ret.append("var pMenuBar = new MenuBar({});\n"); for (final AbstractCommand child : uiGrid.getCommand().getTargetMenu().getCommands()) { if (child instanceof AbstractMenu) { ret.append(getSubMenu((AbstractMenu) child, "pMenuBar")); } else { ret.append("pMenuBar.addChild(").append(getMenuItem(child, true)).append(");\n"); } } } return ret; } protected CharSequence getSubMenu(final AbstractMenu _menu, final String _parent) { final String var = RandomStringUtils.randomAlphabetic(4); final StringBuilder js = new StringBuilder(); js.append("var ").append(var).append(" = new DropDownMenu({});\n"); for (final AbstractCommand child : _menu.getCommands()) { if (child instanceof AbstractMenu) { js.append(getSubMenu((AbstractMenu) child, var)); } else { js.append(var).append(".addChild(").append(getMenuItem(child, false)).append(");\n"); } } js.append(_parent).append(".addChild(new PopupMenuBarItem({\n").append("label: \"") .append(StringEscapeUtils.escapeEcmaScript(_menu.getLabelProperty())).append("\",\n") .append(" popup: ").append(var).append("\n").append(" }));\n"); return js; } protected CharSequence getMenuItem(final AbstractCommand _cmd, final boolean _menuBar) { final UIGrid uiGrid = (UIGrid) getDefaultModelObject(); final String rid = uiGrid.getRandom4ID(_cmd.getId()); final StringBuilder js = new StringBuilder(); if (_menuBar) { js.append("new MenuBarItem({\n"); } else { js.append("new MenuItem({\n"); } js.append(" label: \"").append(StringEscapeUtils.escapeEcmaScript(_cmd.getLabelProperty())).append("\",\n") .append("onClick: function(event) {\n").append("var rid = \"").append(rid).append("\";\n"); final GridXPanel panel = (GridXPanel) getParent(); panel.visitChildren(MenuItem.class, new IVisitor<MenuItem, Void>() { @Override public void component(final MenuItem _item, final IVisit<Void> visit) { if (Target.MODAL.equals(_cmd.getTarget())) { if (_cmd.isSubmit()) { js.append(_item.getBehaviors(SubmitModalBehavior.class).get(0) .getCallbackFunctionBody(CallbackParameter.explicit("rid"))); } else { js.append(_item.getBehaviors(OpenModalBehavior.class).get(0) .getCallbackFunctionBody(CallbackParameter.explicit("rid"))); } } else if (_cmd.isSubmit()) { js.append(_item.getBehaviors(SubmitBehavior.class).get(0) .getCallbackFunctionBody(CallbackParameter.explicit("rid"))); } } }); js.append("}\n").append("})\n"); return js; } @Override public void onLinkClicked() { final StringValue rowId = getRequest().getRequestParameters().getParameterValue("rowId"); final StringValue colId = getRequest().getRequestParameters().getParameterValue("colId"); try { final UIGrid uiGrid = (UIGrid) getDefaultModelObject(); final List<Cell> row = uiGrid.getValues().get(rowId.toInt()); final Cell cell = row.get(colId.toInt()); if (cell.getInstance() != null) { Menu menu = null; try { menu = Menu.getTypeTreeMenu(cell.getInstance().getType()); } catch (final EFapsException e) { throw new RestartResponseException(new ErrorPage(e)); } if (menu == null) { final Exception ex = new Exception( "no tree menu defined for type " + (cell.getInstance()) == null ? "??" : cell.getInstance().getType().getName()); throw new RestartResponseException(new ErrorPage(ex)); } Page page; try { page = new ContentContainerPage(menu.getUUID(), cell.getInstance().getKey(), getPage() instanceof StructurBrowserPage); } catch (final EFapsException e) { page = new ErrorPage(e); } this.setResponsePage(page); } } catch (final StringValueConversionException | EFapsException e) { GridXComponent.LOG.error("Catched error", e); } } /** * Gets the data JS. * * @param _uiTable the ui table * @return the data JS * @throws EFapsException on error */ public static CharSequence getDataJS(final UIGrid _uiGrid) throws EFapsException { final StringBuilder ret = new StringBuilder().append(" [\n"); int i = 0; for (final List<Cell> row : _uiGrid.getValues()) { if (i > 0) { ret.append(",\n"); } ret.append("{ id:").append(i); for (final Cell cell : row) { ret.append(",").append(cell.getFieldConfig().getName()).append(":").append("'") .append(StringEscapeUtils.escapeEcmaScript(StringEscapeUtils.escapeHtml4(cell.getValue()))) .append("'"); final Comparable<?> orderObject = (Comparable<?>) cell.getSortValue(); if (orderObject != null) { final String orderVal; final boolean ps; if (orderObject instanceof Number) { orderVal = ((Number) orderObject).toString(); ps = false; } else { orderVal = String.valueOf(orderObject); ps = true; } if (cell.getValue() != null && !cell.getValue().equals(orderVal)) { ret.append(",").append(cell.getFieldConfig().getName()).append("_sort:") .append(ps ? "'" : "").append(StringEscapeUtils.escapeEcmaScript(orderVal)) .append(ps ? "'" : ""); } } } ret.append("}"); i++; } ret.append("]\n"); return ret; } /** * The Class AjaxBehavior. * * @author The eFaps Team */ public static class PersistAjaxBehavior extends AbstractDefaultAjaxBehavior { /** The Constant serialVersionUID. */ private static final long serialVersionUID = 1L; @Override protected void respond(final AjaxRequestTarget _target) { try { final StringValue value = getComponent().getRequest().getRequestParameters() .getParameterValue("value"); if (!value.isEmpty()) { final UIGrid uiGrid = (UIGrid) getComponent().getDefaultModelObject(); Context.getThreadContext().setUserAttribute(uiGrid.getCacheKey(UIGrid.CacheKey.GRIDX), value.toString()); } } catch (final EFapsException e) { GridXComponent.LOG.error("Catched error", e); } } } }