package cli_fmw.utils;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.LayoutManager;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.Arrays;
import java.util.Collection;
import javax.swing.AbstractCellEditor;
import javax.swing.ComboBoxEditor;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JPopupMenu.Separator;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.ListModel;
import javax.swing.ListSelectionModel;
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;
import javax.swing.plaf.basic.BasicComboBoxEditor;
import javax.swing.table.TableCellEditor;
public class CheckComboEditor extends AbstractCellEditor implements TableCellEditor {
private JList list;
private JComboBox box;
private JPopupMenu jPopupMenu;
private int maxRowCount = 10;
private int height;
private JCheckBox chbAll = null;
private class SpecListener0 implements ListSelectionListener{
private int index;
private JCheckBox jcb;
public SpecListener0(int index, JCheckBox jcb) {
this.index = index;
this.jcb = jcb;
}
public void valueChanged(ListSelectionEvent e) {
if (e.getFirstIndex() <= index && e.getLastIndex() >= index){
JList jList = (JList)e.getSource();
jcb.setSelected(jList.isSelectedIndex(index));
}
}
}
private class SpecListener1 implements ActionListener{
private int index;
private ListSelectionModel model;
public SpecListener1(int index, ListSelectionModel model) {
model.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
this.index = index;
this.model = model;
}
public void actionPerformed(ActionEvent e) {
JCheckBox checkBox = (JCheckBox)e.getSource();
if (checkBox.isSelected()){
model.addSelectionInterval(index, index);
}else{
model.removeSelectionInterval(index, index);
}
}
}
public CheckComboEditor(ListModel listModel) {
this(listModel, true);
}
/**
* Редактор ячейки: комбобокс в котором лежат чекбоксы.
* Из модели таблицы принимает список элементов или одиночный элемент,
* возвращает в модель список выделенных элементов
* @param listModel модель листа с полным списком возможных элементов
* @param useAll флаг для добавления в список пункта "все"
*/
public CheckComboEditor(ListModel listModel, boolean useAll) {
this.list = new JList(listModel);
JPanel pnlItems = new JPanel(new GridLayout(0, 1));
JPanel pnlMain = new JPanel(new BorderLayout(0, 0));
pnlMain.setBorder(new EmptyBorder(0, 0, 0, 0));
box = new JComboBox();
box.setEnabled(false);
jPopupMenu = new JPopupMenu();
if (listModel.getSize() > 0 && useAll){
chbAll = new JCheckBox("Все");
chbAll.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JCheckBox checkBox = (JCheckBox)e.getSource();
if (checkBox.isSelected()){
list.setSelectionInterval(0, list.getModel().getSize()-1);
}else{
list.clearSelection();
}
}
});
list.addListSelectionListener(new ListSelectionListener() {
public void valueChanged(ListSelectionEvent e) {
chbAll.setSelected(list.getSelectedIndices().length == list.getModel().getSize());
}
});
}
for (int i = 0; i < listModel.getSize(); i++) {
JCheckBox jCheckBox = new JCheckBox("" + listModel.getElementAt(i));
jCheckBox.addActionListener(new SpecListener1(i, list.getSelectionModel()));
list.addListSelectionListener(new SpecListener0(i, jCheckBox));
pnlItems.add(jCheckBox);
}
JScrollPane jsp = new JScrollPane(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
if (chbAll != null){
pnlMain.add(chbAll, BorderLayout.NORTH);
Separator separator = new JPopupMenu.Separator();
pnlMain.add(separator, BorderLayout.CENTER);
pnlMain.add(pnlItems, BorderLayout.SOUTH);
jsp.getViewport().add(pnlMain);
height += chbAll.getPreferredSize().height + separator.getPreferredSize().height;
}else{
jsp.getViewport().add(pnlItems);
}
jPopupMenu.add(jsp);
jPopupMenu.setBorder(new LineBorder(Color.BLACK));
int count = pnlItems.getComponentCount();
for (int i = 0; i < count && i < maxRowCount; i++) {
height += pnlItems.getComponent(i).getPreferredSize().height;
}
jsp.setAutoscrolls(true);
box.addMouseListener(new MouseListener() {
public void mouseClicked(MouseEvent e) {
if (jPopupMenu.isVisible()){
jPopupMenu.setVisible(false);
stopCellEditing();
}
}
public void mousePressed(MouseEvent e) {
}
public void mouseReleased(MouseEvent e) {
}
public void mouseEntered(MouseEvent e) {
}
public void mouseExited(MouseEvent e) {
}
});
jPopupMenu.addPopupMenuListener(new PopupMenuListener() {
public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
//throw new UnsupportedOperationException("Not supported yet.");
}
public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
stopCellEditing();
}
public void popupMenuCanceled(PopupMenuEvent e) {
stopCellEditing();
}
});
}
@Override
public Object getCellEditorValue() {
Object[] selectedValues = list.getSelectedValues();
return Arrays.asList(selectedValues);
}
private void selectObject(Object object){
for (int i = 0; i < list.getModel().getSize(); i++) {
Object elementAt = list.getModel().getElementAt(i);
if (elementAt.equals(object)){
list.addSelectionInterval(i, i);
}
}
}
@Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
list.removeSelectionInterval(0, list.getModel().getSize());
if (value instanceof Collection){
Collection c = (Collection)value;
for (Object object : c) {
selectObject(object);
}
}else{
selectObject(value);
}
Rectangle cellRect = table.getCellRect(row, column, true);
Point location = cellRect.getLocation();
Dimension size = cellRect.getSize();
jPopupMenu.setPopupSize(size.width, height);
jPopupMenu.show(table, location.x, location.y + size.height);
return box;
}
public int getMaxRowCount() {
return maxRowCount;
}
public void setMaxRowCount(int maxRowCount) {
this.maxRowCount = maxRowCount;
}
}