package vg.userInterface.attributePanel;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Observable;
import java.util.Observer;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.table.TableColumn;
import javax.swing.table.TableRowSorter;
import vg.core.AUserInterfaceElement;
import vg.core.IGraphView;
import vg.core.VisualGraph;
import vg.core.event.AUIEvent;
import vg.core.event.UIEventChangeView;
import vg.core.storableGraph.StorableAttribute;
import vg.userInterface.attributePanel.components.AttributeTableCellEditor;
import vg.userInterface.attributePanel.components.AttributeTableCellRenderer;
import vg.userInterface.attributePanel.components.AttributeTableModel;
import vg.userInterface.attributePanel.components.data.AttributeRow;
import vg.userInterface.attributePanel.components.data.AttributeShower;
import vg.userInterface.attributePanel.components.data.AttributeValue;
import vg.userInterface.swingComponents.TableCellTooltipRender;
/**
* This class is a filter attribute panel for vertexes and edges.
* @author tzolotuhin
*/
public class AttributePanel extends AUserInterfaceElement {
private static final long serialVersionUID = 1000L;
// Defines
private final static int DEF_ROW_HEIGHT = 22;
// Data
private AttributeTableModel tableModel = null;
private JTable table;
private IGraphView graphView;
private Observer listener;
private Map<StorableAttribute,Boolean> vertexAttributes;
private Map<StorableAttribute,Boolean> edgeAttributes;
// Components
private JScrollPane scroll;
private JButton applyButton;
private JPanel view;
private JCheckBox selectAll;
private JLabel selectAllLabel;
// Mutex
private Object theMutexObject;
/**
* Constructor.
*/
public AttributePanel() {
super("Attribute panel", null);
this.theMutexObject = new Object();
initUI();
this.listener = new Observer() {
public void update(Observable o, Object arg) {
synchronized (theMutexObject) {
if(graphView != null) {
vertexAttributes = graphView.getVertexAttributes();
edgeAttributes = graphView.getEdgeAttributes();
if(SwingUtilities.isEventDispatchThread()) {
buildPanel();
} else {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
synchronized (theMutexObject) {
buildPanel();
}
}
});
}
} else {
VisualGraph.log.printError("[" + this.getClass().getName() + ".AttributePanel.run] [BAD] IGraphView = null");
}
}
}
};
}
public void update(Observable o, Object arg) {
if(arg instanceof AUIEvent) {
AUIEvent event = (AUIEvent)arg;
switch(event.getType()) {
case DEF_CHANGE_VIEW:
{
UIEventChangeView bufEvent = (UIEventChangeView)event;
setGraphView(bufEvent.getView());
break;
}
case DEF_CHANGE_UI_STYLE:
{
updateUITheme();
break;
}
}
}
}
public JComponent getView() {
synchronized (theMutexObject) {
return(this.view);
}
}
/**
* This method updates UI theme.
*/
public void updateUITheme() {
if(SwingUtilities.isEventDispatchThread()) {
synchronized (theMutexObject) {
buildPanel();
}
} else {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
synchronized (theMutexObject) {
buildPanel();
}
}
});
}
}
///////////////////////////////////////////////////////////////////////////
// PRIVATE METHODS
///////////////////////////////////////////////////////////////////////////
/**
* This method sets new graph view to attributes panel.
*/
private void setGraphView(IGraphView graphView) {
synchronized (theMutexObject) {
// Remove all listeners from old graph view
if(this.graphView != null) this.graphView.deleteAllObservers();
// Set new graph view
this.graphView = graphView;
if(this.graphView != null) {
this.vertexAttributes = this.graphView.getVertexAttributes();
this.edgeAttributes = this.graphView.getEdgeAttributes();
this.graphView.addObserver(this.listener);
} else {
this.vertexAttributes = new HashMap<StorableAttribute, Boolean>();
this.edgeAttributes = new HashMap<StorableAttribute, Boolean>();
}
// Rebuild panel
if(SwingUtilities.isEventDispatchThread()) {
buildPanel();
} else {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
synchronized (theMutexObject) {
buildPanel();
}
}
});
}
}
}
/**
* This method creates new tab with out subgraph.
* Note: Call this method from EDT.
*/
private void apply() {
HashSet<String>list_v = new HashSet<String>();
HashSet<String>list_e = new HashSet<String>();
for (int i = 0 ; i < this.tableModel.getRowCount() ; i++) {
AttributeShower shower = (AttributeShower)this.tableModel.getValueAt(i, 0);
if(shower.isShow() && this.tableModel.getValueAt(i, 3).equals("V")) {
list_v.add((String)this.tableModel.getValueAt(i, 1));
}
if(shower.isShow() && this.tableModel.getValueAt(i, 3).equals("E")) {
list_e.add((String)this.tableModel.getValueAt(i, 1));
}
}
if(this.graphView != null) {
this.graphView.showAttributes(list_v, list_e);
this.vertexAttributes = AttributePanel.this.graphView.getVertexAttributes();
this.edgeAttributes = AttributePanel.this.graphView.getEdgeAttributes();
buildPanel();
} else {
VisualGraph.log.printError("[" + this.getClass().getName() + ".AttributePanel.run] [BAD] IGraphView = null");
}
}
/**
* This method rebuilds attributes panel.
* Note: Call this method from EDT.
*/
private void buildPanel() {
this.view.removeAll();
//---------------------------------------
HashMap<String, AttributeRow>data = new HashMap<String, AttributeRow>();
boolean checkAll = true;
// Finding of attributes and their values
if(this.vertexAttributes != null) {
for(StorableAttribute bufAttr : this.vertexAttributes.keySet()) {
if(bufAttr.getName() != null && bufAttr.getValue() != null) {
AttributeRow value = null;
value = data.get(bufAttr.getName());
boolean visible = this.vertexAttributes.get(bufAttr);
if(value == null) {
value = new AttributeRow(bufAttr.getName(), visible, "V", new AttributeValue());
data.put(bufAttr.getName(), value);
}
switch(value.getShow()) {
case AttributeShower.DEF_UNSHOW_GREEN:
{
checkAll = false;
if(visible) {
value.getShower().setYellowShow();
}
break;
}
case AttributeShower.DEF_SHOW_GREEN:
{
if(!visible) {
value.getShower().setYellowShow();
}
break;
}
}
value.addValue(bufAttr.getValue());
} else {
VisualGraph.log.printError("[" + this.getClass().getName() + ".buildPanel]" + " Error in attribute panel. Attribute name or attribute value = null(Vertex)");
}
}
}
//-----------------------------------
if(this.edgeAttributes != null) {
for(StorableAttribute bufAttr : this.edgeAttributes.keySet()) {
if(bufAttr.getName() != null && bufAttr.getValue() != null) {
AttributeRow value = null;
value = data.get(bufAttr.getName());
boolean visible = this.edgeAttributes.get(bufAttr);
if(value == null) {
value = new AttributeRow(bufAttr.getName(), visible, "E", new AttributeValue());
data.put(bufAttr.getName(), value);
}
switch(value.getShow()) {
case AttributeShower.DEF_UNSHOW_GREEN:
{
checkAll = false;
if(visible) {
value.getShower().setYellowShow();
}
break;
}
case AttributeShower.DEF_SHOW_GREEN:
{
if(!visible) {
value.getShower().setYellowShow();
}
break;
}
}
value.addValue(bufAttr.getValue());
} else {
VisualGraph.log.printError("[" + this.getClass().getName() + ".buildPanel]" + " Error in attribute panel. Attribute name or attribute value = null(Edge)");
}
}
}
//Creating components of the filter window
this.tableModel = new AttributeTableModel(data.values(), this.selectAll);
//---------------------------------------
GridBagConstraints gbc = new GridBagConstraints();
this.table = new JTable(this.tableModel);
this.table.setOpaque(true);
this.table.setFillsViewportHeight(true);
this.table.setRowHeight(DEF_ROW_HEIGHT);
TableRowSorter<AttributeTableModel> sorter = new TableRowSorter<AttributeTableModel>(this.tableModel);
sorter.setSortable(0, true);
sorter.setSortable(1, true);
sorter.setSortable(2, false);
sorter.setSortable(3, true);
this.table.setRowSorter(sorter);
this.table.setShowGrid(true);
this.table.setDefaultRenderer(String.class, new TableCellTooltipRender());
this.table.getTableHeader().setReorderingAllowed(false);
//---------------------------------------
AttributeTableCellRenderer renderer = new AttributeTableCellRenderer();
TableColumn col0 = this.table.getColumnModel().getColumn(0);
TableColumn col2 = this.table.getColumnModel().getColumn(2);
col0.setCellRenderer(renderer);
col2.setCellRenderer(renderer);
//---------------------------------------
AttributeTableCellEditor editor = new AttributeTableCellEditor(this.tableModel, renderer);
col0.setCellEditor(editor);
col2.setCellEditor(editor);
// Package of interface
if(this.graphView != null) {
this.scroll = new JScrollPane(this.table);
gbc = new GridBagConstraints(0,0, 3,1, 1,1, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(5, 5, 5, 5), 0,0);
this.view.add(scroll,gbc);
gbc = new GridBagConstraints(0,1, 1,1, 0,0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0,0);
this.view.add(this.selectAllLabel,gbc);
gbc = new GridBagConstraints(1,1, 1,1, 0,0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0,0);
this.view.add(this.selectAll,gbc);
this.selectAll.setSelected(checkAll);
gbc = new GridBagConstraints(2,1, 1,1, 1,0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(5, 50, 5, 50), 0,0);
this.view.add(this.applyButton,gbc);
}
this.view.updateUI();
}
/**
* Init UI.
* Note: Call this method from EDT.
*/
private void initUI() {
this.view = new JPanel(new GridBagLayout());
this.applyButton = new JButton("Apply");
this.selectAll = new JCheckBox();
this.selectAllLabel = new JLabel("Select all :");
this.applyButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
synchronized (theMutexObject) {
if(SwingUtilities.isEventDispatchThread()) {
apply();
} else {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
synchronized (theMutexObject) {
apply();
}
}
});
}
}
}
});
this.selectAll.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
synchronized (theMutexObject) {
boolean check = AttributePanel.this.selectAll.isSelected();
for(int i = 0 ; i < AttributePanel.this.tableModel.getRowCount() ; i++) {
AttributeShower shower = (AttributeShower)AttributePanel.this.tableModel.getValueAt(i, 0);
if(check) {
shower.show();
} else {
shower.unshow();
}
}
if(SwingUtilities.isEventDispatchThread()) {
table.editingStopped(null);
view.updateUI();
} else {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
synchronized (theMutexObject) {
table.editingStopped(null);
view.updateUI();
}
}
});
}
}
}
});
this.view.setVisible(true);
}
}