/* (c) 2014 Open Source Geospatial Foundation - all rights reserved * This code is licensed under the GPL 2.0 license, available at the root * application directory. */ package org.geoserver.geofence.gui.client.widget.rule.detail; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import com.extjs.gxt.ui.client.data.BasePagingLoadResult; import com.extjs.gxt.ui.client.data.BasePagingLoader; import com.extjs.gxt.ui.client.data.LoadEvent; import com.extjs.gxt.ui.client.data.ModelData; import com.extjs.gxt.ui.client.data.PagingLoadConfig; import com.extjs.gxt.ui.client.data.PagingLoadResult; import com.extjs.gxt.ui.client.data.PagingLoader; import com.extjs.gxt.ui.client.data.RpcProxy; import com.extjs.gxt.ui.client.event.ButtonEvent; import com.extjs.gxt.ui.client.event.Events; import com.extjs.gxt.ui.client.event.FieldEvent; import com.extjs.gxt.ui.client.event.GridEvent; import com.extjs.gxt.ui.client.event.Listener; import com.extjs.gxt.ui.client.event.LoadListener; import com.extjs.gxt.ui.client.mvc.Dispatcher; import com.extjs.gxt.ui.client.store.ListStore; import com.extjs.gxt.ui.client.widget.BoxComponent; import com.extjs.gxt.ui.client.widget.ComponentManager; import com.extjs.gxt.ui.client.widget.button.Button; import com.extjs.gxt.ui.client.widget.form.TextField; import com.extjs.gxt.ui.client.widget.grid.ColumnConfig; import com.extjs.gxt.ui.client.widget.grid.ColumnData; import com.extjs.gxt.ui.client.widget.grid.ColumnModel; import com.extjs.gxt.ui.client.widget.grid.Grid; import com.extjs.gxt.ui.client.widget.grid.GridCellRenderer; import com.extjs.gxt.ui.client.widget.toolbar.FillToolItem; import com.extjs.gxt.ui.client.widget.toolbar.SeparatorToolItem; import com.extjs.gxt.ui.client.widget.toolbar.ToolBar; import com.google.gwt.user.client.rpc.AsyncCallback; import org.geoserver.geofence.gui.client.GeofenceEvents; import org.geoserver.geofence.gui.client.Resources; import org.geoserver.geofence.gui.client.i18n.I18nProvider; import org.geoserver.geofence.gui.client.model.BeanKeyValue; import org.geoserver.geofence.gui.client.model.RuleModel; import org.geoserver.geofence.gui.client.model.data.LayerCustomProps; import org.geoserver.geofence.gui.client.service.RulesManagerRemoteServiceAsync; import org.geoserver.geofence.gui.client.widget.GeofenceGridWidget; // TODO: Auto-generated Javadoc /** * The Class LayerCustomPropsGridWidget. */ public class LayerCustomPropsGridWidget extends GeofenceGridWidget<LayerCustomProps> { /** The rules service. */ private RulesManagerRemoteServiceAsync rulesService; /** The proxy. */ private RpcProxy<PagingLoadResult<LayerCustomProps>> proxy; /** The loader. */ private PagingLoader<PagingLoadResult<ModelData>> loader; /** The tool bar. */ private ToolBar toolBar; /** The rule. */ private RuleModel theRule; /** * Instantiates a new layer custom props grid widget. * * @param model * the model * @param rulesService * the rules service */ public LayerCustomPropsGridWidget(RuleModel model, RulesManagerRemoteServiceAsync rulesService) { super(); this.theRule = model; this.rulesService = rulesService; } /* * (non-Javadoc) * * @see org.geoserver.geofence.gui.client.widget.GEOFENCEGridWidget#setGridProperties () */ @Override public void setGridProperties() { grid.setLoadMask(true); grid.setAutoWidth(true); } /* (non-Javadoc) * @see org.geoserver.geofence.gui.client.widget.GeofenceGridWidget#prepareColumnModel() */ @Override public ColumnModel prepareColumnModel() { List<ColumnConfig> configs = new ArrayList<ColumnConfig>(); ColumnConfig layerPropKeyColumn = new ColumnConfig(); layerPropKeyColumn.setId(BeanKeyValue.PROP_KEY.getValue()); layerPropKeyColumn.setHeader("Key"); layerPropKeyColumn.setWidth(210); layerPropKeyColumn.setRenderer(this.createPropKeyTextBox()); layerPropKeyColumn.setMenuDisabled(true); layerPropKeyColumn.setSortable(false); configs.add(layerPropKeyColumn); ColumnConfig layerPropValueColumn = new ColumnConfig(); layerPropValueColumn.setId(BeanKeyValue.PROP_VALUE.getValue()); layerPropValueColumn.setHeader("Value"); layerPropValueColumn.setWidth(260); layerPropValueColumn.setRenderer(this.createPropValueTextBox()); layerPropValueColumn.setMenuDisabled(true); layerPropValueColumn.setSortable(false); configs.add(layerPropValueColumn); ColumnConfig removeActionColumn = new ColumnConfig(); removeActionColumn.setId("removeLayerCustomProp"); removeActionColumn.setWidth(30); removeActionColumn.setRenderer(this.createDeleteButton()); removeActionColumn.setMenuDisabled(true); removeActionColumn.setSortable(false); configs.add(removeActionColumn); return new ColumnModel(configs); } /** * Creates the prop key text box. * * @return the grid cell renderer */ private GridCellRenderer<LayerCustomProps> createPropKeyTextBox() { GridCellRenderer<LayerCustomProps> textRendered = new GridCellRenderer<LayerCustomProps>() { private boolean init; public Object render(final LayerCustomProps model, String property, ColumnData config, int rowIndex, int colIndex, ListStore<LayerCustomProps> store, Grid<LayerCustomProps> grid) { if (!init) { init = true; grid.addListener(Events.ColumnResize, new Listener<GridEvent<LayerCustomProps>>() { public void handleEvent(GridEvent<LayerCustomProps> be) { for (int i = 0; i < be.getGrid().getStore().getCount(); i++) { if ((be.getGrid().getView().getWidget(i, be.getColIndex()) != null) && (be.getGrid().getView().getWidget(i, be.getColIndex()) instanceof BoxComponent)) { ((BoxComponent) be.getGrid().getView().getWidget(i, be.getColIndex())).setWidth(be.getWidth() - 10); } } } }); } // TODO: generalize this! final TextField<String> propKey = new TextField<String>(); propKey.setWidth(200); propKey.setAllowBlank(false); propKey.setValue(model.getPropKey()); propKey.addListener(Events.Change, new Listener<FieldEvent>() { public void handleEvent(FieldEvent be) { Dispatcher.forwardEvent(GeofenceEvents.SEND_INFO_MESSAGE, new String[] { "GeoServer Rules: Layer Custom Properties", "Key " + model.getPropKey() + ": Key changed -> " + be.getField().getValue() }); // Map<String, LayerCustomProps> updateDTO = new HashMap<String, LayerCustomProps>(); // LayerCustomProps newModel = new LayerCustomProps(); // newModel.setPropKey((String) be.getField().getValue()); // newModel.setPropValue(model.getPropValue()); // updateDTO.put(model.getPropKey(), newModel); // Dispatcher.forwardEvent(GeofenceEvents.RULE_CUSTOM_PROP_UPDATE_KEY, updateDTO); model.setPropKey((String) be.getField().getValue()); } }); propKey.addListener(Events.OnKeyPress, new Listener<FieldEvent>() { public void handleEvent(FieldEvent be) { int keycode = be.getKeyCode(); if (keycode == 36) { // HOME KEY PRESSED propKey.setCursorPos(0); } else if (keycode == 35) { // END KEY PRESSED propKey.setCursorPos(propKey.getValue().length()); } } }); return propKey; } }; return textRendered; } /** * Creates the prop value text box. * * @return the grid cell renderer */ private GridCellRenderer<LayerCustomProps> createPropValueTextBox() { GridCellRenderer<LayerCustomProps> textRendered = new GridCellRenderer<LayerCustomProps>() { private boolean init; public Object render(final LayerCustomProps model, String property, ColumnData config, int rowIndex, int colIndex, ListStore<LayerCustomProps> store, Grid<LayerCustomProps> grid) { if (!init) { init = true; grid.addListener(Events.ColumnResize, new Listener<GridEvent<LayerCustomProps>>() { public void handleEvent(GridEvent<LayerCustomProps> be) { for (int i = 0; i < be.getGrid().getStore().getCount(); i++) { if ((be.getGrid().getView().getWidget(i, be.getColIndex()) != null) && (be.getGrid().getView().getWidget(i, be.getColIndex()) instanceof BoxComponent)) { ((BoxComponent) be.getGrid().getView().getWidget(i, be.getColIndex())).setWidth(be.getWidth() - 10); } } } }); } final TextField<String> propValue = new TextField<String>(); propValue.setWidth(250); propValue.setAllowBlank(true); propValue.setValue(model.getPropValue()); propValue.addListener(Events.Change, new Listener<FieldEvent>() { public void handleEvent(FieldEvent be) { Dispatcher.forwardEvent(GeofenceEvents.SEND_INFO_MESSAGE, new String[] { "GeoServer Rules: Layer Custom Properties", "Key " + model.getPropKey() + ": Value changed -> " + be.getField().getValue() }); // Map<String, LayerCustomProps> updateDTO = new HashMap<String, LayerCustomProps>(); // LayerCustomProps newModel = new LayerCustomProps(); // newModel.setPropKey(model.getPropKey()); // newModel.setPropValue((String) be.getField().getValue()); // updateDTO.put(model.getPropKey(), newModel); // Dispatcher.forwardEvent(GeofenceEvents.RULE_CUSTOM_PROP_UPDATE_VALUE, updateDTO); model.setPropValue((String) be.getField().getValue()); } }); propValue.addListener(Events.OnKeyPress, new Listener<FieldEvent>() { public void handleEvent(FieldEvent be) { int keycode = be.getKeyCode(); if (keycode == 36) { // HOME KEY PRESSED propValue.setCursorPos(0); } else if (keycode == 35) { // END KEY PRESSED propValue.setCursorPos(propValue.getValue().length()); } } }); return propValue; } }; return textRendered; } /** * Creates the delete button. * * @return the grid cell renderer */ private GridCellRenderer<LayerCustomProps> createDeleteButton() { GridCellRenderer<LayerCustomProps> buttonRendered = new GridCellRenderer<LayerCustomProps>() { private boolean init; public Object render(final LayerCustomProps model, String property, ColumnData config, int rowIndex, int colIndex, ListStore<LayerCustomProps> store, Grid<LayerCustomProps> grid) { if (!init) { init = true; grid.addListener(Events.ColumnResize, new Listener<GridEvent<LayerCustomProps>>() { public void handleEvent(GridEvent<LayerCustomProps> be) { for (int i = 0; i < be.getGrid().getStore().getCount(); i++) { if ((be.getGrid().getView().getWidget(i, be.getColIndex()) != null) && (be.getGrid().getView().getWidget(i, be.getColIndex()) instanceof BoxComponent)) { ((BoxComponent) be.getGrid().getView().getWidget(i, be.getColIndex())).setWidth(be.getWidth() - 10); } } } }); } // TODO: generalize this! Button removeButton = new Button(); removeButton.setBorders(false); removeButton.setIcon(Resources.ICONS.delete()); // TODO: add correct tooltip text here! removeButton.setEnabled(true); removeButton.addListener(Events.OnClick, new Listener<ButtonEvent>() { public void handleEvent(ButtonEvent be) { Dispatcher.forwardEvent(GeofenceEvents.SEND_INFO_MESSAGE, new String[] { "GeoServer Rules: Layer Custom Properties", "Remove Property" }); Map<Long, LayerCustomProps> updateDTO = new HashMap<Long, LayerCustomProps>(); updateDTO.put(theRule.getId(), model); Dispatcher.forwardEvent(GeofenceEvents.RULE_CUSTOM_PROP_DEL, updateDTO); } }); return removeButton; } }; return buttonRendered; } /* * (non-Javadoc) * * @see org.geoserver.geofence.gui.client.widget.GEOFENCEGridWidget#createStore() */ @Override public void createStore() { this.toolBar = new ToolBar(); // Loader fro rulesService this.proxy = new RpcProxy<PagingLoadResult<LayerCustomProps>>() { @Override protected void load(Object loadConfig, AsyncCallback<PagingLoadResult<LayerCustomProps>> callback) { // rulesService.getLayerCustomProps(((PagingLoadConfig) loadConfig).getOffset(), ((PagingLoadConfig) loadConfig).getLimit(), theRule, callback); } }; loader = new BasePagingLoader<PagingLoadResult<ModelData>>(proxy); loader.setRemoteSort(true); store = new ListStore<LayerCustomProps>(loader); // Apply Changes button Button addRuleCustomPropertyButton = new Button("Add Property"); addRuleCustomPropertyButton.setIcon(Resources.ICONS.add()); addRuleCustomPropertyButton.addListener(Events.OnClick, new Listener<ButtonEvent>() { public void handleEvent(ButtonEvent be) { Map<Long, LayerCustomProps> updateDTO = new HashMap<Long, LayerCustomProps>(); updateDTO.put(theRule.getId(), null); Dispatcher.forwardEvent(GeofenceEvents.RULE_CUSTOM_PROP_ADD, updateDTO); } }); Button saveRuleCustomPropertiesButton = new Button("Save"); saveRuleCustomPropertiesButton.setIcon(Resources.ICONS.save()); saveRuleCustomPropertiesButton.addListener(Events.OnClick, new Listener<ButtonEvent>() { public void handleEvent(ButtonEvent be) { Dispatcher.forwardEvent(GeofenceEvents.SEND_INFO_MESSAGE, new String[] { "GeoServer Rules: Layer Custom Properties", "Apply Changes" }); Dispatcher.forwardEvent(GeofenceEvents.RULE_CUSTOM_PROP_APPLY_CHANGES, theRule.getId()); } }); Button cancelButton = new Button("Cancel"); cancelButton.addListener(Events.OnClick, new Listener<ButtonEvent>() { public void handleEvent(ButtonEvent be) { // ///////////////////////////////////////////////////////// // Getting the Rule details edit dialogs and hiding this // ///////////////////////////////////////////////////////// ComponentManager.get().get(I18nProvider.getMessages().ruleDialogId()).hide(); } }); this.toolBar.add(new FillToolItem()); this.toolBar.add(addRuleCustomPropertyButton); this.toolBar.add(new SeparatorToolItem()); this.toolBar.add(saveRuleCustomPropertiesButton); this.toolBar.add(cancelButton); setUpLoadListener(); } /** * Gets the loader. * * @return the loader */ public PagingLoader<PagingLoadResult<ModelData>> getLoader() { return loader; } /** * Gets the tool bar. * * @return the tool bar */ public ToolBar getToolBar() { return toolBar; } /** * Clear grid elements. */ public void clearGridElements() { this.store.removeAll(); this.toolBar.disable(); } /** * Sets the up load listener. */ private void setUpLoadListener() { loader.addLoadListener(new LoadListener() { @Override public void loaderBeforeLoad(LoadEvent le) { if (!toolBar.isEnabled()) { toolBar.enable(); } } @Override public void loaderLoad(LoadEvent le) { // TODO: change messages here!! BasePagingLoadResult<?> result = le.getData(); if (!result.getData().isEmpty()) { int size = result.getData().size(); String message = ""; if (size == 1) { message = I18nProvider.getMessages().recordLabel(); } else { message = I18nProvider.getMessages().recordPluralLabel(); } Dispatcher.forwardEvent(GeofenceEvents.SEND_INFO_MESSAGE, new String[] { I18nProvider.getMessages().remoteServiceName(), I18nProvider.getMessages().foundLabel() + " " + result.getData().size() + " " + message }); } else { Dispatcher.forwardEvent(GeofenceEvents.SEND_INFO_MESSAGE, new String[] { I18nProvider.getMessages().remoteServiceName(), I18nProvider.getMessages().recordNotFoundMessage() }); } } }); } }