package au.com.vaadinutils.fields;
import java.util.ArrayList;
import java.util.List;
import com.vaadin.addon.jpacontainer.JPAContainer;
import com.vaadin.data.Item;
import com.vaadin.data.Property;
import com.vaadin.data.Property.ValueChangeListener;
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.CustomComponent;
import com.vaadin.ui.GridLayout;
import com.vaadin.ui.ListSelect;
import com.vaadin.ui.VerticalLayout;
@SuppressWarnings("serial")
public class OrderingListSelect<T> extends CustomComponent
{
public enum Direction
{
UP, DOWN
}
private ListSelect listSelect;
private Button upButton;
private Button downButton;
private JPAContainer<T> container;
private List<OrderingListSelectItem> listItems = new ArrayList<>();
private String pkProperty;
private String captionProperty;
private String sortProperty;
private boolean modified = false;
protected ValueChangeListener listener;
public OrderingListSelect(String caption)
{
final GridLayout layout = new GridLayout(2, 1);
listSelect = new ListSelect();
final VerticalLayout buttonLayout = new VerticalLayout();
buttonLayout.setSpacing(true);
layout.addComponent(listSelect, 0, 0);
layout.addComponent(buttonLayout, 1, 0);
layout.setComponentAlignment(buttonLayout, Alignment.MIDDLE_CENTER);
upButton = new Button("▲");
downButton = new Button("▼");
buttonLayout.addComponent(upButton);
buttonLayout.addComponent(downButton);
setButtonClickListeners();
listSelect.setCaption(caption);
setCompositionRoot(layout);
}
public OrderingListSelect()
{
this(null);
}
private void setButtonClickListeners()
{
upButton.addClickListener(new ClickListener()
{
@Override
public void buttonClick(ClickEvent event)
{
if (listSelect != null && !listSelect.isEmpty())
{
moveItem((Long) listSelect.getValue(), Direction.UP);
}
}
});
downButton.addClickListener(new ClickListener()
{
@Override
public void buttonClick(ClickEvent event)
{
if (listSelect != null && !listSelect.isEmpty())
{
moveItem((Long) listSelect.getValue(), Direction.DOWN);
}
}
});
}
public void build()
{
// Populate list select and build internal list of items
listSelect.removeAllItems();
listItems.clear();
for (Object itemId : container.getItemIds())
{
Item item = container.getItem(itemId);
Long pk = (Long) item.getItemProperty(pkProperty).getValue();
String caption = (String) item.getItemProperty(captionProperty).getValue();
OrderingListSelectItem newItem = new OrderingListSelectItem(pk, caption);
listItems.add(newItem);
listSelect.addItem(pk);
listSelect.setItemCaption(pk, caption);
}
listSelect.setWidth("300");
}
private void moveItem(Long selectedPk, Direction direction)
{
if (listener != null)
{
listSelect.addValueChangeListener(listener);
}
// Work out the corresponding item in our internal list
int index = getIndex(selectedPk);
// Remove the item from our internal list
OrderingListSelectItem movedItem = listItems.remove(index);
// And reposition it based on the direction given
int newIndex = -1;
if (direction.equals(Direction.UP))
{
newIndex = index == 0 ? index : --index;
}
else if (direction.equals(Direction.DOWN))
{
newIndex = index == listItems.size() ? index : ++index;
}
listItems.add(newIndex, movedItem);
// movedItem.setId(newIndex);
// Repopulate the list select based on the new order
listSelect.removeAllItems();
for (OrderingListSelectItem listItem : listItems)
{
final Long pk = listItem.getPk();
Item item = container.getItem(pk);
String caption = (String) item.getItemProperty(captionProperty).getValue();
listSelect.addItem(pk);
listSelect.setItemCaption(pk, caption);
}
// Reselect the existing selected item
listSelect.setValue(selectedPk);
setModified(true);
}
private int getIndex(Long pk)
{
int index = -1;
for (int i = 0; i < listItems.size(); i++)
{
OrderingListSelectItem item = listItems.get(i);
if (pk.equals(item.getPk()))
{
index = i;
break;
}
}
return index;
}
@SuppressWarnings(
{ "unchecked", "deprecation" })
public void save()
{
for (Object itemId : container.getItemIds())
{
Item item = container.getItem(itemId);
Long pk = (Long) item.getItemProperty(pkProperty).getValue();
Property<Long> sortOrder = item.getItemProperty(sortProperty);
int index = getIndex(pk);
sortOrder.setValue(new Long(index));
}
container.commit();
setModified(false);
if (listener != null)
{
listSelect.removeListener(listener);
}
}
public ListSelect getListSelect()
{
return listSelect;
}
public void setContainerDataSource(JPAContainer<T> container)
{
this.container = container;
}
public JPAContainer<T> getContainerDataSource()
{
return container;
}
public void setPkProperty(String pkProperty)
{
this.pkProperty = pkProperty;
}
public String getPkProperty()
{
return pkProperty;
}
public void setCaptionProperty(String captionProperty)
{
this.captionProperty = captionProperty;
}
public String getCaptionProperty()
{
return captionProperty;
}
public void setSortProperty(String sortProperty)
{
this.sortProperty = sortProperty;
}
public String getSortProperty()
{
return sortProperty;
}
public void setNullSelectionAllowed(boolean b)
{
listSelect.setNullSelectionAllowed(b);
}
public void setModified(boolean modified)
{
this.modified = modified;
}
public boolean isModified()
{
return modified;
}
public void addValueChangeListener(ValueChangeListener listener)
{
this.listener = listener;
}
}