/*
* (C) Copyright 2015 by fr3ts0n <erwin.scheuch-heilig@gmx.at>
*
* 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 2 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, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
package com.fr3ts0n.pvs.gui;
import com.fr3ts0n.pvs.ProcessVar;
import com.fr3ts0n.pvs.PvChangeEvent;
import com.fr3ts0n.pvs.PvChangeListener;
import java.awt.Color;
import java.awt.Component;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Toolkit;
import java.awt.event.*;
import java.beans.Customizer;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import javax.swing.*;
import javax.swing.border.LineBorder;
import javax.swing.text.*;
/**
* panel class to display / edit a parocess variable and all it's attributes
*
* @author $Author: erwin $
*/
public class PvDetailPanel extends JPanel
implements ActionListener, PvChangeListener, Customizer
{
/**
*
*/
private static final long serialVersionUID = 740664204205911504L;
// field background colors
static Color unchangedColor = Color.white;
static Color changedColor = Color.lightGray;
static Color labelColor = Color.lightGray;
static LineBorder lineBorder = new LineBorder(Color.BLACK);
HashMap<Object, JComponent> fields = new HashMap<Object, JComponent>();
ProcessVar dataSource = null;
boolean editable = false;
public PvDetailPanel()
{
setLayout(new GridBagLayout());
setBackground(labelColor);
setBorder(lineBorder);
}
/**
* create a panel of detailed information on current process variable
*/
public PvDetailPanel(ProcessVar data)
{
this();
setProcessVar(data);
}
/**
* create a panel of detailed information on current process variable
*/
public PvDetailPanel(ProcessVar data, boolean allowEdit)
{
this();
setEditable(allowEdit);
setProcessVar(data);
}
/**
* set the process var which is assigned to this editor panel
* this creates all corresponding data fields
*/
@SuppressWarnings({"unchecked", "rawtypes"})
public void setProcessVar(ProcessVar data)
{
if (dataSource == null || !dataSource.equals(data))
{
// remove all child components, if they have been set already
if (dataSource != null && !dataSource.equals(data))
{
dataSource.removePvChangeListener(this);
fields.clear();
removeAll();
}
// update data source variable
dataSource = data;
// if data source is anything real ...
if (data != null)
{
Object currKey = null;
Object currVal = null;
JLabel hdrCmp = null;
JComponent dataCmp = null;
GridBagConstraints attr = new GridBagConstraints();
// ... fill content panel with data
ArrayList keys = new ArrayList(data.keySet());
// sort list alphabetically
Collections.sort(keys);
Iterator it = keys.iterator();
// loop through all attributes
while (it.hasNext())
{
/* set default attributes */
attr.gridwidth = 1;
attr.gridheight = 1;
attr.weightx = 0.0;
attr.fill = GridBagConstraints.BOTH;
if ((currKey = it.next()) != null)
{
hdrCmp = new JLabel(currKey.toString());
hdrCmp.setBackground(labelColor);
hdrCmp.setBorder(lineBorder);
// setup data component based on it's value
if ((currVal = data.get(currKey)) == null)
{
dataCmp = new JLabel();
} else
{
if (currVal instanceof ProcessVar)
{
dataCmp = new PvDetailPanel((ProcessVar) currVal, editable);
} else
{
dataCmp = new JTextField(data.get(currKey).toString());
((JTextField) dataCmp).setEditable(editable);
((JTextField) dataCmp).addActionListener(this);
}
}
dataCmp.setName(currKey.toString());
// add the components
add(hdrCmp, attr);
attr.gridwidth = GridBagConstraints.REMAINDER;
attr.weightx = 1.0;
add(dataCmp, attr);
// add data component to Hashmap of fields
fields.put(currKey, dataCmp);
}
}
// add 'this' panel as PvChangeListener to Process variable
data.addPvChangeListener(this, PvChangeEvent.PV_ADDED | PvChangeEvent.PV_MODIFIED);
}
validate();
}
}
/** Implementation of Customizer interface */
public void setObject(Object bean)
{
setEditable(true);
setProcessVar((ProcessVar) bean);
}
/** return the process var which is assigned to this editor panel */
public ProcessVar getProcessVar()
{
return (dataSource);
}
/** return if the process this editor panel is editable */
public boolean getEditable()
{
return (editable);
}
/** set this editor panel to be non-/editable */
public void setEditable(boolean newEditable)
{
editable = newEditable;
}
/**
* action handler for edit fields within panel
* this handler also temporarily changes the color of the edit field to
* visibly indicate the update action.
*/
public void actionPerformed(ActionEvent e)
{
// find out which field sends the event
JTextField edit = (JTextField) e.getSource();
// update the corresponding process var
dataSource.put(edit.getName(), edit.getText(), PvChangeEvent.PV_MANUAL_MOD);
// indicate change by changing field's background color
edit.setBackground(changedColor);
Toolkit.getDefaultToolkit().beep();
}
protected void finalize() throws Throwable
{
dataSource.removePvChangeListener(this);
fields.clear();
removeAll();
super.finalize();
}
/**
* handler for process variable changes
* update dialog element from process variable
*/
public void pvChanged(PvChangeEvent event)
{
// only update panel if it is displayable
if (isDisplayable())
{
Component edit = (Component) fields.get(event.getKey());
Object value = event.getValue();
// if we have found the corresponding editor field ...
if (edit != null)
{
// set the value and background for it
edit.setBackground(event.getType() == PvChangeEvent.PV_MANUAL_MOD ? changedColor : unchangedColor);
if (edit instanceof JTextComponent)
{
((JTextComponent) edit).setText(value != null ? value.toString() : "");
} else if (edit instanceof JLabel)
{
((JLabel) edit).setText(value != null ? value.toString() : "");
} else if (edit instanceof PvDetailPanel)
{
((PvDetailPanel) edit).setProcessVar((ProcessVar) value);
}
}
}
}
}