/* (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.Arrays;
import java.util.List;
import com.extjs.gxt.ui.client.Style.SortDir;
import com.extjs.gxt.ui.client.data.BaseListLoader;
import com.extjs.gxt.ui.client.data.BasePagingLoadResult;
import com.extjs.gxt.ui.client.data.ListLoadResult;
import com.extjs.gxt.ui.client.data.LoadEvent;
import com.extjs.gxt.ui.client.data.ModelData;
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.ComboBox;
import com.extjs.gxt.ui.client.widget.form.ComboBox.TriggerAction;
import com.extjs.gxt.ui.client.widget.form.LabelField;
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.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.AccessType;
import org.geoserver.geofence.gui.client.model.data.LayerAttribUI;
import org.geoserver.geofence.gui.client.service.RulesManagerRemoteServiceAsync;
import org.geoserver.geofence.gui.client.widget.GeofenceGridWidget;
/**
* The Class LayerAttributesGridWidget.
*/
public class LayerAttributesGridWidget extends GeofenceGridWidget<LayerAttribUI>
{
/** The rule. */
private RuleModel theRule;
/** The rules service. */
private RulesManagerRemoteServiceAsync rulesService;
/** The proxy. */
private RpcProxy<List<LayerAttribUI>> proxy;
/** The loader. */
private BaseListLoader<ListLoadResult<ModelData>> loader;
/** The tool bar. */
private ToolBar toolBar;
/** The save rule attributes button. */
private Button saveRuleAttributesButton;
/** The cancel rule attributes button. */
private Button cancelButton;
/**
* Instantiates a new layer attributes grid widget.
*
* @param model
* the model
* @param rulesService
* the rules service
*/
public LayerAttributesGridWidget(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);
}
/**
* Clear grid elements.
*/
public void clearGridElements()
{
this.store.removeAll();
this.saveRuleAttributesButton.disable();
}
/*
* (non-Javadoc)
*
* @see org.geoserver.geofence.gui.client.widget.GEOFENCEGridWidget#createStore()
*/
@Override
public void createStore()
{
this.toolBar = new ToolBar();
// /////////////////////////////
// Loader for rulesService
// /////////////////////////////
this.proxy = new RpcProxy<List<LayerAttribUI>>()
{
@Override
protected void load(Object loadConfig, AsyncCallback<List<LayerAttribUI>> callback)
{
rulesService.getLayerAttributes(theRule, callback);
}
};
loader = new BaseListLoader<ListLoadResult<ModelData>>(proxy);
loader.setRemoteSort(false);
store = new ListStore<LayerAttribUI>(loader);
store.sort(BeanKeyValue.ATTR_NAME.getValue(), SortDir.ASC);
this.saveRuleAttributesButton = new Button("Save");
saveRuleAttributesButton.setIcon(Resources.ICONS.save());
saveRuleAttributesButton.disable();
saveRuleAttributesButton.addListener(Events.OnClick, new Listener<ButtonEvent>()
{
public void handleEvent(ButtonEvent be)
{
int storeCount = store.getCount();
if (storeCount > 0)
{
Dispatcher.forwardEvent(GeofenceEvents.SEND_INFO_MESSAGE,
new String[] { "GeoServer Rules: Layer Attributes", "Apply Changes" });
Dispatcher.forwardEvent(GeofenceEvents.ATTRIBUTE_UPDATE_GRID_COMBO, theRule.getId());
}
else
{
Dispatcher.forwardEvent(GeofenceEvents.SEND_ALERT_MESSAGE,
new String[]
{
"GeoServer Rules: Layer Attributes",
"No attribute to save!"
});
}
}
});
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(saveRuleAttributesButton);
this.toolBar.add(cancelButton);
setUpLoadListener();
}
/**
* 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()
});
}
}
});
}
/* (non-Javadoc)
* @see org.geoserver.geofence.gui.client.widget.GeofenceGridWidget#prepareColumnModel()
*/
@Override
public ColumnModel prepareColumnModel()
{
List<ColumnConfig> configs = new ArrayList<ColumnConfig>();
ColumnConfig attributeNameColumn = new ColumnConfig();
attributeNameColumn.setId(BeanKeyValue.ATTR_NAME.getValue());
attributeNameColumn.setHeader("Name");
attributeNameColumn.setWidth(180);
attributeNameColumn.setRenderer(this.createNameTextBox());
attributeNameColumn.setMenuDisabled(true);
attributeNameColumn.setSortable(false);
configs.add(attributeNameColumn);
ColumnConfig attributeTypeColumn = new ColumnConfig();
attributeTypeColumn.setId(BeanKeyValue.ATTR_TYPE.getValue());
attributeTypeColumn.setHeader("Data Type");
attributeTypeColumn.setWidth(180);
attributeTypeColumn.setRenderer(this.createTypeTextBox());
attributeTypeColumn.setMenuDisabled(true);
attributeTypeColumn.setSortable(false);
configs.add(attributeTypeColumn);
ColumnConfig attributeAccessColumn = new ColumnConfig();
attributeAccessColumn.setId(BeanKeyValue.ATTR_ACCESS.getValue());
attributeAccessColumn.setHeader("Access Type");
attributeAccessColumn.setWidth(180);
attributeAccessColumn.setRenderer(this.createAccessTypeComboBox());
attributeAccessColumn.setMenuDisabled(true);
attributeAccessColumn.setSortable(false);
configs.add(attributeAccessColumn);
return new ColumnModel(configs);
}
/**
* Creates the name text box.
*
* @return the grid cell renderer
*/
private GridCellRenderer<LayerAttribUI> createNameTextBox()
{
GridCellRenderer<LayerAttribUI> textRendered = new GridCellRenderer<LayerAttribUI>()
{
private boolean init;
public Object render(final LayerAttribUI model, String property, ColumnData config,
int rowIndex, int colIndex, ListStore<LayerAttribUI> store, Grid<LayerAttribUI> grid)
{
if (!init)
{
init = true;
grid.addListener(Events.ColumnResize, new Listener<GridEvent<LayerAttribUI>>()
{
public void handleEvent(GridEvent<LayerAttribUI> 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);
}
}
}
});
}
LabelField attrName = new LabelField();
attrName.setWidth(150);
attrName.setReadOnly(true);
attrName.setValue(model.getName());
return attrName;
}
};
return textRendered;
}
/**
* Creates the type text box.
*
* @return the grid cell renderer
*/
private GridCellRenderer<LayerAttribUI> createTypeTextBox()
{
GridCellRenderer<LayerAttribUI> textRendered = new GridCellRenderer<LayerAttribUI>()
{
private boolean init;
public Object render(final LayerAttribUI model, String property, ColumnData config,
int rowIndex, int colIndex, ListStore<LayerAttribUI> store, Grid<LayerAttribUI> grid)
{
if (!init)
{
init = true;
grid.addListener(Events.ColumnResize, new Listener<GridEvent<LayerAttribUI>>()
{
public void handleEvent(GridEvent<LayerAttribUI> 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);
}
}
}
});
}
LabelField attrType = new LabelField();
attrType.setWidth(150);
attrType.setReadOnly(true);
attrType.setValue(model.getDataType());
return attrType;
}
};
return textRendered;
}
/**
* Creates the access type combo box.
*
* @return the grid cell renderer
*/
private GridCellRenderer<LayerAttribUI> createAccessTypeComboBox()
{
GridCellRenderer<LayerAttribUI> comboRendered = new GridCellRenderer<LayerAttribUI>()
{
private boolean init;
public Object render(final LayerAttribUI model, String property, ColumnData config,
int rowIndex, int colIndex, ListStore<LayerAttribUI> store, Grid<LayerAttribUI> grid)
{
if (!init)
{
init = true;
grid.addListener(Events.ColumnResize, new Listener<GridEvent<LayerAttribUI>>()
{
public void handleEvent(GridEvent<LayerAttribUI> 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);
}
}
}
});
}
ComboBox<AccessType> typeComboBox = new ComboBox<AccessType>();
typeComboBox.setId("accessCombo");
typeComboBox.setName("accessCombo");
typeComboBox.setDisplayField(BeanKeyValue.ATTR_ACCESS.getValue());
typeComboBox.setEditable(false);
typeComboBox.setStore(getAvailableAccessType());
typeComboBox.setTypeAhead(true);
typeComboBox.setTriggerAction(TriggerAction.ALL);
typeComboBox.setWidth(100);
if (model.getAccessType() != null)
{
typeComboBox.setValue(new AccessType(model.getAccessType()));
typeComboBox.setSelection(Arrays.asList(new AccessType(model.getAccessType())));
}
typeComboBox.setEmptyText("(No access types available)");
typeComboBox.addListener(Events.Select, new Listener<FieldEvent>()
{
public void handleEvent(FieldEvent be)
{
final AccessType accessType = (AccessType) be.getField().getValue();
Dispatcher.forwardEvent(GeofenceEvents.SEND_INFO_MESSAGE,
new String[]
{
"Attribute Access Type",
"Attribute " + model.getName() + ": Attribute access type changed"
});
model.setAccessType(accessType.getType());
saveRuleAttributesButton.enable();
}
});
return typeComboBox;
}
/**
* TODO: Call User Service here!!
*
* @param workspace
* @param rule
*
* @return ListStore<AccessType>
*/
private ListStore<AccessType> getAvailableAccessType()
{
ListStore<AccessType> availableAccessTypes = new ListStore<AccessType>();
List<AccessType> accessType = new ArrayList<AccessType>();
AccessType none = new AccessType("NONE");
AccessType readonly = new AccessType("READONLY");
AccessType readwrite = new AccessType("READWRITE");
accessType.add(none);
accessType.add(readonly);
accessType.add(readwrite);
availableAccessTypes.add(accessType);
return availableAccessTypes;
}
};
return comboRendered;
}
/**
* Gets the loader.
*
* @return the loader
*/
public BaseListLoader<ListLoadResult<ModelData>> getLoader()
{
return loader;
}
/**
* Gets the tool bar.
*
* @return the tool bar
*/
public ToolBar getToolBar()
{
return toolBar;
}
}