/*
Copyright (C) 2010 maik.jablonski@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package jfix.zk;
import java.util.Comparator;
import java.util.List;
import java.util.Set;
import jfix.search.FullTextIndex;
import jfix.util.I18N;
import jfix.util.Natural;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zk.ui.event.Events;
import org.zkoss.zul.ListModelList;
import org.zkoss.zul.Listbox;
import org.zkoss.zul.Listitem;
public class Picklist extends Column {
private int rows;
private ListModelList choiceModel = new ListModelList();
private ListModelList selectionModel = new ListModelList();
private ListModelList backupModel;
private Listbox choiceListbox = new Listbox();
private Listbox selectionListbox = new Listbox();
private Comparator choiceComparator;
private Comparator selectionComparator;
private Searchbox searchBox = new Searchbox() {
public void searchPerformed(String search) {
try {
Picklist.this.searchPerformed(search);
} catch (Exception e) {
Modal.error(e.getMessage());
}
}
};
public Picklist() {
this(Natural.newComparator(), null);
}
public Picklist(boolean open) {
this(Natural.newComparator(), Natural.newComparator(), open);
}
public Picklist(Comparator comparator) {
this(comparator, comparator);
}
public Picklist(Comparator comparator, boolean open) {
this(comparator, comparator, open);
}
public Picklist(Comparator choiceListComparator,
Comparator selectionListComparator) {
this(choiceListComparator, selectionListComparator, false);
}
public Picklist(Comparator choiceListComparator,
Comparator selectionListComparator, boolean open) {
this.choiceComparator = choiceListComparator;
this.selectionComparator = selectionListComparator;
Button selectButton = new Button("", Images.GoUp);
selectButton.addEventListener(Events.ON_CLICK, new EventListener() {
public void onEvent(Event e) {
actionSelect();
}
});
Button deselectButton = new Button("", Images.GoDown);
deselectButton.addEventListener(Events.ON_CLICK, new EventListener() {
public void onEvent(Event e) {
actionDeselect();
}
});
Button upButton = new Button("", Images.GoUp);
upButton.addEventListener(Events.ON_CLICK, new EventListener() {
public void onEvent(Event e) {
actionMoveUp();
}
});
Button downButton = new Button("", Images.GoDown);
downButton.addEventListener(Events.ON_CLICK, new EventListener() {
public void onEvent(Event e) {
actionMoveDown();
}
});
selectionListbox.setOddRowSclass("null");
selectionListbox.setHflex("1");
selectionListbox.setMultiple(true);
selectionListbox.setModel(selectionModel);
choiceListbox.setOddRowSclass("null");
choiceListbox.setHflex("1");
choiceListbox.setMultiple(true);
choiceListbox.setModel(choiceModel);
setRows(5);
Row selectionControls = new Row();
selectionControls.appendChild(selectionListbox);
if (selectionListComparator == null) {
selectionControls.appendChild(new Div(upButton, new Separator(Separator.HORIZONTAL), downButton));
}
appendChild(selectionControls);
if (open) {
appendChild(new Column(new Row(selectButton, deselectButton,
searchBox), choiceListbox));
} else {
appendChild(new Expander(I18N.get("Selection"), new Column(new Row(
selectButton, deselectButton, searchBox), choiceListbox),
open));
}
}
public void setMaxlength(int cols) {
choiceListbox.setMaxlength(cols);
selectionListbox.setMaxlength(cols);
}
public void setRows(int numrows) {
rows = numrows;
selectionListbox.setRows(rows);
choiceListbox.setRows(rows);
}
public void setItemRenderer(ItemRenderer renderer) {
choiceListbox.setItemRenderer(renderer);
selectionListbox.setItemRenderer(renderer);
}
public void setSearchable(boolean searchable) {
searchBox.setVisible(searchable);
}
public void clearSelection() {
choiceListbox.clearSelection();
selectionListbox.clearSelection();
}
public void setChoices(List elements) {
setChoices(elements.toArray());
}
public void setChoices(Object elements[]) {
backupModel = null;
searchBox.clearSearch();
clearSelection();
choiceModel.clear();
removeFromSelected(elements);
}
public void setSelected(List elements) {
setSelected(elements.toArray());
}
public void setSelected(Object elements[]) {
backupModel = null;
clearSelection();
selectionModel.clear();
addToSelected(elements);
}
public void setSelection(Object[] choices, Object[] selected) {
setChoices(choices);
setSelected(selected);
}
public void setSelection(List choices, Object[] selected) {
setChoices(choices);
setSelected(selected);
}
public void setSelection(Object[] choices, List selected) {
setChoices(choices);
setSelected(selected);
}
public void setSelection(List choices, List selected) {
setChoices(choices);
setSelected(selected);
}
public void addToSelected(Object elements[]) {
if (elements != null) {
for (int i = 0; i < elements.length; i++) {
if (elements[i] != null) {
choiceModel.remove(elements[i]);
selectionModel.add(elements[i]);
}
}
if (choiceComparator != null) {
sortModels(choiceModel, choiceComparator);
}
if (selectionComparator != null) {
sortModels(selectionModel, selectionComparator);
}
}
adjustRows();
}
public void removeFromSelected(Object elements[]) {
if (elements != null) {
for (int i = elements.length - 1; i >= 0; i--) {
if (elements[i] != null) {
selectionModel.remove(elements[i]);
choiceModel.add(elements[i]);
}
}
if (choiceComparator != null) {
sortModels(choiceModel, choiceComparator);
}
if (selectionComparator != null) {
sortModels(selectionModel, selectionComparator);
}
}
adjustRows();
}
private void adjustRows() {
if (isEmpty()) {
selectionListbox.setRows(1);
} else {
int len = getSelected().length;
selectionListbox.setRows(len < rows ? len : rows);
}
}
private void sortModels(ListModelList model, Comparator comparator) {
model.sort(comparator, true);
}
private void moveUp(Object elements[]) {
if (elements != null) {
int[] selectedIndices = new int[elements.length];
for (int i = 0; i < elements.length; i++) {
int index = selectionModel.indexOf(elements[i]);
if (index > 0) {
selectionModel.remove(index);
selectedIndices[i] = index - 1;
selectionModel.add(selectedIndices[i], elements[i]);
} else {
selectedIndices[i] = 0;
}
}
for (int i : selectedIndices) {
selectionListbox.setSelectedIndex(i);
}
}
}
private void moveDown(Object elements[]) {
if (elements != null) {
int[] selectedIndices = new int[elements.length];
for (int i = elements.length - 1; i >= 0; i--) {
int index = selectionModel.indexOf(elements[i]);
if (index < selectionModel.size() - 1) {
selectionModel.remove(index);
selectedIndices[i] = index + 1;
selectionModel.add(selectedIndices[i], elements[i]);
} else {
selectedIndices[i] = selectionModel.size() - 1;
}
}
for (int i : selectedIndices) {
selectionListbox.setSelectedIndex(i);
}
}
}
public Object[] getChoices() {
return convertListModelToArray(choiceModel);
}
public Object[] getSelected() {
return convertListModelToArray(selectionModel);
}
private void actionSelect() {
addToSelected(convertItemSetToArray(choiceListbox.getSelectedItems()));
clearSelection();
}
private void actionDeselect() {
removeFromSelected(convertItemSetToArray(selectionListbox
.getSelectedItems()));
clearSelection();
}
private void actionMoveUp() {
moveUp(convertItemSetToArray(selectionListbox.getSelectedItems()));
choiceListbox.clearSelection();
}
private void actionMoveDown() {
moveDown(convertItemSetToArray(selectionListbox.getSelectedItems()));
choiceListbox.clearSelection();
}
private Object[] convertItemSetToArray(Set listitems) {
int i = 0;
Object[] values = new Object[listitems.size()];
for (Object item : listitems) {
values[i++] = ((Listitem) item).getValue();
}
return values;
}
private Object[] convertListModelToArray(ListModelList model) {
Object[] arr = new Object[model.size()];
for (int i = 0; i < arr.length; i++) {
arr[i] = model.get(i);
}
return arr;
}
public boolean isEmpty() {
if (getSelected() == null || getSelected().length == 0) {
return true;
}
return false;
}
private void searchPerformed(String searchTerm) throws Exception {
if (backupModel == null) {
backupModel = new ListModelList();
for (int i = 0; i < choiceModel.size(); i++) {
backupModel.add(choiceModel.get(i));
}
for (int i = 0; i < selectionModel.size(); i++) {
backupModel.add(selectionModel.get(i));
}
}
choiceModel.clear();
if (searchTerm == null || "".equals(searchTerm)) {
for (int i = 0; i < backupModel.size(); i++) {
Object entity = backupModel.get(i);
if (selectionModel.indexOf(entity) == -1) {
choiceModel.add(entity);
}
}
} else {
FullTextIndex index = new FullTextIndex();
for (int i = 0; i < backupModel.size(); i++) {
Object entity = backupModel.get(i);
if ((choiceListbox.getItemRenderer()) instanceof ItemRenderer) {
index.add(entity, ((ItemRenderer) choiceListbox
.getItemRenderer()).render(entity));
} else {
index.add(entity, String.valueOf(entity));
}
}
index.commit();
for (Object obj : index.search(searchTerm)) {
if (selectionModel.indexOf(obj) == -1) {
choiceModel.add(obj);
}
}
choiceListbox.selectAll();
}
}
}