package au.com.vaadinutils.dashboard;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Map.Entry;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.vaadin.alump.gridstack.GridStackMoveEvent;
import com.vaadin.data.sort.SortOrder;
import com.vaadin.event.SortEvent;
import com.vaadin.event.SortEvent.SortListener;
import com.vaadin.server.FontAwesome;
import com.vaadin.shared.data.sort.SortDirection;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Button.ClickListener;
import com.vaadin.ui.Grid;
import com.vaadin.ui.Grid.Column;
import com.vaadin.ui.Grid.ColumnReorderEvent;
import com.vaadin.ui.Grid.ColumnReorderListener;
import com.vaadin.ui.Grid.ColumnVisibilityChangeEvent;
import com.vaadin.ui.Grid.ColumnVisibilityChangeListener;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Label;
import com.vaadin.ui.Table;
import com.vaadin.ui.Table.ColumnCollapseEvent;
import com.vaadin.ui.Table.ColumnCollapseListener;
import com.vaadin.ui.Table.ColumnResizeEvent;
import com.vaadin.ui.Table.ColumnResizeListener;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.themes.ValoTheme;
import au.com.vaadinutils.dao.EntityManagerProvider;
import au.com.vaadinutils.dao.JpaBaseDao;
import au.com.vaadinutils.dao.JpaDslBuilder;
public abstract class BasePortal extends VerticalLayout implements Portal
{
private static final String COLUMN_WIDTH = "column-width-";
private static final long serialVersionUID = 1L;
private static final String COLUMN_VISABLE = "column-visable-";
private String guid = null;
private Logger logger = LogManager.getLogger();
private PortalConfigDelgate configDelegate;
protected BasePortal(Tblportal portal, DashBoardController dashBoard, PortalConfigDelgate configDelegate)
{
guid = portal.getGuid();
this.configDelegate = configDelegate;
setSizeFull();
// setMargin(new MarginInfo(false, true, false, true));
HorizontalLayout header = createHeader(configDelegate.getTitle(), dashBoard);
addComponent(header);
}
public String getGuid()
{
return guid;
}
public Tblportal getPortal()
{
return JpaBaseDao.getGenericDao(Tblportal.class).findOneByAttribute(Tblportal_.guid, getGuid());
}
protected PortalConfigDelgate getConfigDelegate()
{
return configDelegate;
}
private HorizontalLayout createHeader(String title, final DashBoardController dashBoard)
{
HorizontalLayout header = new HorizontalLayout();
header.setWidth("100%");
header.setHeight("25");
Label titleLabel = new Label(title);
titleLabel.setStyleName(ValoTheme.LABEL_COLORED);
header.addComponent(titleLabel);
HorizontalLayout controlLayout = new HorizontalLayout();
addCustomHeaderButtons(controlLayout);
Button removeButton = new Button(FontAwesome.CLOSE);
removeButton.setStyleName(ValoTheme.BUTTON_LINK);
removeButton.addClickListener(new ClickListener()
{
private static final long serialVersionUID = 1L;
@Override
public void buttonClick(ClickEvent event)
{
dashBoard.removeComponent(BasePortal.this);
Tblportal portal = JpaBaseDao.getGenericDao(Tblportal.class).findOneByAttribute(Tblportal_.guid, guid);
if (portal != null)
{
portal.getPortalLayout().removePortal(portal);
JpaDslBuilder<Tblportalconfig> q = JpaBaseDao.getGenericDao(Tblportalconfig.class).select();
q.where(q.eq(Tblportalconfig_.portal, portal)).delete();
EntityManagerProvider.remove(portal);
}
}
});
controlLayout.addComponent(removeButton);
header.addComponent(controlLayout);
header.setComponentAlignment(controlLayout, Alignment.MIDDLE_RIGHT);
return header;
}
protected abstract void addCustomHeaderButtons(HorizontalLayout controlLayout);
@Override
public void savePosition(GridStackMoveEvent event)
{
Tblportal portal = JpaBaseDao.getGenericDao(Tblportal.class).findOneByAttribute(Tblportal_.guid, guid);
configDelegate.savePosition(portal, event.getNew());
}
protected TableColumnManager configureSaveColumnWidths(final Table table, String tableId)
{
final Tblportal portal = getPortal();
final String baseKey = tableId + "_" + COLUMN_WIDTH;
for (Entry<String, Integer> value : getConfigDelegate().getValuesLikeInt(portal, baseKey).entrySet())
{
String key = value.getKey().substring(baseKey.length(), value.getKey().length());
table.setColumnWidth(key, value.getValue());
}
table.addColumnResizeListener(new ColumnResizeListener()
{
private static final long serialVersionUID = 4034036880290943146L;
@Override
public void columnResize(ColumnResizeEvent event)
{
final Tblportal portal = getPortal();
final String property = (String) event.getPropertyId();
final int width = event.getCurrentWidth();
getConfigDelegate().setValue(portal, baseKey + property, width);
}
});
table.addColumnCollapseListener(new ColumnCollapseListener()
{
private static final long serialVersionUID = 1L;
@Override
public void columnCollapseStateChange(ColumnCollapseEvent event)
{
final Tblportal portal = getPortal();
final String property = (String) event.getPropertyId();
final boolean isVisible = !table.isColumnCollapsed(property);
}
});
return new TableColumnManager()
{
@Override
public void reset()
{
for (Entry<String, Integer> value : getConfigDelegate().getValuesLikeInt(getPortal(), baseKey)
.entrySet())
{
String key = value.getKey().substring(baseKey.length(), value.getKey().length());
table.setColumnExpandRatio(key, 1);
getConfigDelegate().deleteValuesLike(getPortal(), baseKey);
}
for (Object col : table.getVisibleColumns())
{
table.setColumnExpandRatio(col, 1);
}
}
};
}
protected TableColumnManager configureSaveColumnWidths(final Grid grid, String tableId)
{
grid.setData(tableId);
final String baseWidthKey = tableId + "_" + COLUMN_WIDTH;
final String baseVisableKey = tableId + "_" + COLUMN_VISABLE;
final String keyStub = tableId + "_order";
try
{
setupGridColumnSizing(grid, baseWidthKey);
setupGridColumnVisibility(grid, baseVisableKey);
setupGridColumnReordering(grid, keyStub);
String keySorting = tableId + "_sort";
setupGridSorting(grid, keySorting);
}
catch (Exception e)
{
logger.error(e, e);
}
return new TableColumnManager()
{
@Override
public void reset()
{
for (Column col : grid.getColumns())
{
col.setWidthUndefined();
getConfigDelegate().deleteValuesLike(getPortal(), baseWidthKey + col.getPropertyId());
}
}
};
}
public void setupGridSorting(final Grid grid, final String keySorting)
{
String sorts = getConfigDelegate().getValueString(getPortal(), keySorting);
if (StringUtils.isNotEmpty(sorts))
{
try
{
List<SortOrder> sortList = new LinkedList<>();
String[] sortArray = sorts.split(",");
for (String sort : sortArray)
{
String[] parts = sort.split("=");
sortList.add(new SortOrder(parts[0], SortDirection.valueOf(parts[1])));
}
grid.setSortOrder(sortList);
}
catch (Exception e)
{
logger.error(e);
}
}
grid.addSortListener(new SortListener()
{
private static final long serialVersionUID = 1L;
@Override
public void sort(SortEvent event)
{
String sorts = "";
for (SortOrder sort : event.getSortOrder())
{
sorts += sort.getPropertyId() + "=" + sort.getDirection() + ",";
}
getConfigDelegate().setValue(getPortal(), keySorting, sorts);
}
});
}
private void setupGridColumnSizing(final Grid grid, final String baseWidthKey)
{
for (Entry<String, Integer> value : getConfigDelegate().getValuesLikeInt(getPortal(), baseWidthKey).entrySet())
{
try
{
String key = value.getKey().substring(baseWidthKey.length(), value.getKey().length());
final Double width = value.getValue().doubleValue();
if (width > 0)
{
grid.getColumn(key).setWidth(width);
}
}
catch (Exception e)
{
logger.warn(e);
}
}
grid.addColumnResizeListener(new Grid.ColumnResizeListener()
{
private static final long serialVersionUID = 4034036880290943146L;
@Override
public void columnResize(com.vaadin.ui.Grid.ColumnResizeEvent event)
{
final String propertyId = (String) event.getColumn().getPropertyId();
final double width = event.getColumn().getWidth();
getConfigDelegate().setValue(getPortal(), baseWidthKey + propertyId, "" + (int) width);
}
});
}
private void setupGridColumnVisibility(final Grid grid, final String baseVisableKey)
{
for (Entry<String, Integer> value : getConfigDelegate().getValuesLikeInt(getPortal(), baseVisableKey)
.entrySet())
{
try
{
String key = value.getKey().substring(baseVisableKey.length(), value.getKey().length());
Integer visable = value.getValue();
grid.getColumn(key).setHidden(visable == 0);
}
catch (Exception e)
{
logger.warn(e);
}
}
grid.addColumnVisibilityChangeListener(new ColumnVisibilityChangeListener()
{
private static final long serialVersionUID = -9082974567948595049L;
@Override
public void columnVisibilityChanged(ColumnVisibilityChangeEvent event)
{
final Column column = event.getColumn();
final boolean isVisible = !column.isHidden();
final Tblportal portal = getPortal();
final String property = (String) column.getPropertyId();
int value = 0;
if (isVisible)
{
value = 1;
}
getConfigDelegate().setValue(getPortal(), baseVisableKey + column.getPropertyId(), value);
}
});
}
private void setupGridColumnReordering(final Grid grid, final String keyStub)
{
final List<Column> availableColumns = grid.getColumns();
final String columns = getConfigDelegate().getValueString(getPortal(), keyStub);
if (availableColumns.size() > 0 && columns != null && !columns.isEmpty())
{
final Object[] parsedColumns = columns.split(", ?");
if (parsedColumns.length > 0)
{
grid.setColumns(calculateColumnOrder(availableColumns, parsedColumns));
}
}
grid.addColumnReorderListener(new ColumnReorderListener()
{
private static final long serialVersionUID = -2810298692555333890L;
@Override
public void columnReorder(ColumnReorderEvent event)
{
final List<Column> columns = ((Grid) event.getSource()).getColumns();
if (columns.size() > 0)
{
String parsedColumns = "";
for (Column column : columns)
{
parsedColumns += column.getPropertyId() + ", ";
}
parsedColumns = parsedColumns.substring(0, parsedColumns.length() - 2);
getConfigDelegate().setValue(getPortal(), keyStub, "" + parsedColumns);
}
}
});
}
/**
* If a column order has already been saved for a user, but the columns for
* a grid have been modified, then we need to remove any columns that no
* longer exist and add any new columns to the list of visible columns.
*
* @param availableColumns
* the columns that are available in the table
* @param parsedColumns
* the column order that has been restored from preferences
* @return the calculated order of columns with old removed and new added
*/
private Object[] calculateColumnOrder(final List<Column> availableColumns, final Object[] parsedColumns)
{
final List<Object> availableList = new ArrayList<>(availableColumns.size());
for (Column column : availableColumns)
{
availableList.add(column.getPropertyId());
}
final List<Object> parsedList = new ArrayList<>(Arrays.asList(parsedColumns));
// Remove old columns
parsedList.retainAll(availableList);
// Add new columns in the same index position as they were added to the
// table in
final List<Object> newList = new ArrayList<>(availableList);
newList.removeAll(parsedList);
for (Object column : newList)
{
parsedList.add(availableList.indexOf(column), column);
}
return parsedList.toArray();
}
}