/*
* ALMA - Atacama Large Millimiter Array
* (c) European Southern Observatory, 2002
* Copyright by ESO (in the framework of the ALMA collaboration)
* and Cosylab 2002, All rights reserved
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
package com.cosylab.logging.settings;
import java.awt.BorderLayout;
import java.awt.Dialog;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.io.IOException;
import java.util.List;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;
import javax.swing.JToolBar;
import javax.swing.WindowConstants;
import javax.swing.filechooser.FileFilter;
import alma.acs.gui.widgets.CheckList;
import alma.acs.gui.widgets.CheckList.CheckListTableEntry;
import com.cosylab.logging.LoggingClient;
import com.cosylab.logging.engine.Filter;
import com.cosylab.logging.engine.Filterable;
import com.cosylab.logging.engine.FiltersVector;
/**
* Serves the purpose of selecting the right filters.
* Filters are used to display logs in the table according to the user's preferences.
* They are used by the engine too.
* <P>
* The existing filter are set by {@link #setFilters(FiltersVector)} and will be used for restoring
* if the user discards the changes.
* <BR>
* The list of fields defined/edited by the user is in the {@link CheckList} widget that stores
* the filter and its activation state.
*
* Creation date: (1/2/2002 22:53:33)
*
* @author: Ales Pucelj (ales.pucelj@kgb.ijs.si)
*/
public class FilterChooserDialog extends JDialog {
// The table of filters with their activation state
private CheckList filterList;
private JLabel description = null;
private JButton buttonClose = null;
private JButton buttonApply = null;
private JButton buttonRestore = null;
// The toolbar with its buttons
private JToolBar toolBar = new JToolBar();
private JButton buttonAdd = null;
private JButton buttonRemove = null;
private JButton buttonModify = null;
// The menu bar with its items
private JMenuBar menuBar = new JMenuBar();
private JMenuItem loadMI=new JMenuItem("Load");
private JMenuItem saveMI=new JMenuItem("Save");
private JMenuItem saveAsMI=new JMenuItem("Save as");
private JMenuItem closeMI=new JMenuItem("Close");
private JMenuItem activateAllMI=new JMenuItem("Activate all");
private JMenuItem deactivateAllMI=new JMenuItem("Deactivate all");
private JMenuItem clearAllMI=new JMenuItem("Clear all");
// The listener
private ButtonListener bl = new ButtonListener();
// The logging client
private LoggingClient loggingClient;
// The Filterable object to apply filters to
private Filterable filterable=null;
/**
* The filters defined at startup (used to implement the restore)
*/
private FiltersVector initialFilters = new FiltersVector();
// true if the vector of filters has been modified
private boolean modified=false;
/**
* The name of the last save/load filter file
* (to implement the save as option)
*/
private String filterFileName = null;
/**
* The cobject that receives the events generated
* by the button
*
* @author acaproni
*
*/
private class ButtonListener implements ActionListener {
private FilterChooserDialog fcd = FilterChooserDialog.this;
private Filter editFilter(Filter f) {
FilterParameterDialog fpd = new FilterParameterDialog(FilterChooserDialog.this);
fpd.setFilter(f);
fpd.setVisible(true);
if (fpd.okPressed()) {
return fpd.getFilter();
}
return null;
}
/**
* @see <code>ActionListener</code>
* @see <code>ActionEvent</code>
*/
public void actionPerformed(ActionEvent e) {
if (e.getSource() == buttonClose || e.getSource() == closeMI) { // Close
if (modified) {
int ret = JOptionPane.showConfirmDialog(FilterChooserDialog.this,
"<HTML>You have modified the filters withouth saving/applying.<BR>Do you really want to close?</HTML>",
"Close confimation", JOptionPane.YES_NO_OPTION);
if (ret != JOptionPane.YES_OPTION) {
return;
}
}
setVisible(false);
loggingClient.enableFiltersWidgets(true);
return;
} else if (e.getSource() == buttonModify) { // Modify/Edit
CheckListTableEntry selectedEntry=filterList.getSelectedEntry();
if (selectedEntry!=null) {
Filter editedFilter=editFilter((Filter)selectedEntry.getItem());
if (editedFilter!=null) {
modified=true;
selectedEntry.setItem(editedFilter);
filterList.updateSelectedEntry();
}
} else {
JOptionPane.showMessageDialog(FilterChooserDialog.this,
"Invalid item to modify", "Error",
JOptionPane.ERROR_MESSAGE);
}
} else if (e.getSource() == buttonAdd) { // Add
Filter f = editFilter(null);
if (f != null) {
filterList.addElement(true,f);
modified=true;
}
} else if (e.getSource() == buttonRemove) { // Remove
CheckListTableEntry removedEntry=filterList.removeSelectedEntry();
if (removedEntry!=null) {
// An entry has been really removed
modified=true;
}
} else if (e.getSource() == activateAllMI) {
filterList.activateAll(true);
modified=true;
} else if (e.getSource() == deactivateAllMI) { // Deactivate All
filterList.activateAll(false);
modified=true;
} else if (e.getSource() == clearAllMI) { // Delete all
if (filterList.getItemsSize()>0) {
int ret = JOptionPane.showConfirmDialog(FilterChooserDialog.this,
"Do you really want to delete all the filters?",
"Delete all filters", JOptionPane.YES_NO_OPTION);
if (ret == JOptionPane.YES_OPTION) {
filterList.clear();
modified=true;
}
}
} else if (e.getSource() == buttonApply) { // Apply
applyFilters();
modified=false;
} else if (e.getSource() == loadMI) { // Load
loadFilters();
} else if (e.getSource() == saveMI) { // Save
saveFilters(filterFileName);
} else if (e.getSource() == saveAsMI) { // Save as
saveAsFilters();
} else if (e.getSource() == buttonRestore) { // Restore
restoreFilters();
} else {
System.out.println("Unhandled event: " + e);
}
FilterChooserDialog.this.updateButtons();
}
}
/**
* The filter to load save filters as xml files
* The filter checks for the extension .xml in the name
*
* @author acaproni
*/
private static class XmlFileFilter extends FileFilter {
public boolean accept(File f) {
// Check if the name has the extension .xml at the end and is readable
boolean pass = f.isFile() && f.getName().toUpperCase().endsWith(".XML") && f.canRead();
// Check if the file is a directory
pass = pass || f.isDirectory();
// Check if f is a hidden file
pass = pass && !f.isHidden();
return pass;
}
public String getDescription() {
return "xml file";
}
}
/**
* FilterChooserDialog constructor.
*
* @param title The tile of the window
* @param logLci The loggingClient showing this dialog
* @param model The table model
*/
public FilterChooserDialog(String title, LoggingClient logCli, Filterable filterable) {
super((Dialog)null,title);
if (filterable == null) {
throw new IllegalArgumentException(
"Invalid null LogTableDataModel in constructor");
}
if (logCli == null) {
throw new IllegalArgumentException(
"Invalid null LoggingClient in constructor");
}
loggingClient = logCli;
this.filterable=filterable;
setModal(false);
ImageIcon filterIcon = new ImageIcon(FilterChooserDialog.class.getResource("/filters.png"));
setIconImage(filterIcon.getImage());
initialize();
setDefaultCloseOperation(WindowConstants.HIDE_ON_CLOSE);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
loggingClient.enableFiltersWidgets(true);
}
});
}
/**
* Set the filters
*
* @param flts The filters to set in the table
*/
public void setFilters(FiltersVector flts) {
if (flts==null) {
throw new IllegalArgumentException("Invalid null filter vector");
}
initialFilters.setFilters(flts);
setupFields(flts,false);
}
/**
* Init the GUI
*/
private void initialize() {
setLocation(50, 50);
// Add the toolbars
initMenubar();
initToolbar();
JPanel panel = new JPanel(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
description = new JLabel("Select filter to apply");
c = newConstraints(0, 0, 0, 4);
c.gridwidth = 3;
panel.add(description, c);
c = newConstraints(0, 1, 0, 4);
c.gridwidth = 3;
c.weighty = 1.0;
c.fill = GridBagConstraints.BOTH;
filterList =new CheckList();
panel.add(new JScrollPane(filterList), c);
JSeparator sep = new JSeparator();
GridBagConstraints constr = newConstraints(0, 2, 4, 4);
constr.gridwidth = 3;
panel.add(sep, constr);
buttonApply = new JButton("Apply");
buttonApply.addActionListener(bl);
panel.add(buttonApply, newConstraints(0, 3, 4, 4));
buttonRestore= new JButton("Restore");
buttonRestore.addActionListener(bl);
panel.add(buttonRestore, newConstraints(1, 3, 4, 4));
buttonClose = new JButton("Close");
buttonClose.addActionListener(bl);
panel.add(buttonClose, newConstraints(2, 3, 4, 4));
getContentPane().add(panel,BorderLayout.CENTER);
pack();
}
/**
* Insert the method's description here. Creation date: (2/7/02 4:30:09 PM)
*
* @return java.awt.GridBagConstraints
* @param x
* int
* @param y
* int
* @param top
* int
* @param bottom
* int
*/
protected GridBagConstraints newConstraints(int x, int y, int top,
int bottom) {
GridBagConstraints constraints = new GridBagConstraints();
constraints.gridx = x;
constraints.gridy = y;
constraints.insets = new Insets(top, 4, bottom, 4);
constraints.weightx = 1.0;
constraints.fill = GridBagConstraints.HORIZONTAL;
constraints.gridheight = 1;
constraints.gridwidth = 1;
return constraints;
}
/**
* Set the entries in the list of filters
* (one row per each filter)
*
* @param filters The list of filters
* @param append If <code>true</code> the filters are appended to the existing filters
*/
private void setupFields(FiltersVector filters, boolean append) {
if (filters==null) {
throw new IllegalArgumentException("The FiltersVector can't be null");
}
if (!append) {
filterList.clear();
}
for (int i = 0; i < filters.size(); i++) {
filterList.addElement(filters.isActive(i),filters.get(i));
}
updateButtons();
}
/**
* Insert the method's description here.
* <p>
* Creation date: (2/13/2002 18:35:12)
*/
protected void updateButtons() {
boolean hasEntries = (filterList.getItemsSize()>0);
buttonRemove.setEnabled(hasEntries);
buttonModify.setEnabled(hasEntries);
activateAllMI.setEnabled(hasEntries);
deactivateAllMI.setEnabled(hasEntries);
clearAllMI.setEnabled(hasEntries);
saveMI.setEnabled(filterFileName!=null && hasEntries);
saveAsMI.setEnabled(hasEntries);
}
/**
* Load filters from a XML file The user chooses if the loaded filters
* substitutes the existing ones or merges with them
*/
private void loadFilters() {
boolean eraseOldFilters;
// Check if already exists filters
if (filterList.getItemsSize()>0) {
int ret = JOptionPane.showConfirmDialog(this,
"Do you want do discard existing filters?",
"Merge filters?",
JOptionPane.YES_NO_CANCEL_OPTION);
if (ret == JOptionPane.CANCEL_OPTION) {
return;
}
eraseOldFilters = (ret == JOptionPane.YES_OPTION);
} else {
eraseOldFilters = false; // We have no filters so.. nothing to
// delete ;-)
}
// Show the dialog to choose the file to load
JFileChooser fileChooserDlg = new JFileChooser();
fileChooserDlg.setMultiSelectionEnabled(false);
fileChooserDlg.setDialogTitle("Load filters");
XmlFileFilter fileFilter = new XmlFileFilter();
fileChooserDlg.setFileFilter(fileFilter);
if (fileChooserDlg.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
// Load filters from file
File fileToLoad = fileChooserDlg.getSelectedFile();
if (fileToLoad != null) {
FiltersVector filters=new FiltersVector();
try {
filters.loadFilters(fileToLoad, eraseOldFilters, null);
} catch (Throwable t) {
JOptionPane.showMessageDialog(this, "Error: "+t.getMessage(), "Error loading filters", JOptionPane.ERROR_MESSAGE);
}
setupFields(filters,!eraseOldFilters);
modified=true;
filterFileName = fileToLoad.getAbsolutePath();
}
}
}
/**
* Save the filters in a new XML file
*
*/
private void saveAsFilters() {
// Check if there are filters in use
if (filterList.getItemsSize()==0) {
JOptionPane.showMessageDialog(this, "No filters to save",
"Warning", JOptionPane.INFORMATION_MESSAGE);
return;
}
// Show the dialog to choose the file to save
JFileChooser fileChooserDlg = new JFileChooser();
fileChooserDlg.setMultiSelectionEnabled(false);
fileChooserDlg.setDialogTitle("Save filters");
XmlFileFilter fileFilter = new XmlFileFilter();
fileChooserDlg.setFileFilter(fileFilter);
if (fileChooserDlg.showSaveDialog(this) == JFileChooser.APPROVE_OPTION) {
// Get the selected file
File fileToSave = fileChooserDlg.getSelectedFile();
if (!fileToSave.getAbsolutePath().toUpperCase().endsWith(".XML")) {
fileToSave = new File(fileToSave.getAbsolutePath() + ".xml");
}
if (fileToSave != null) {
filterFileName = fileToSave.getAbsolutePath();
saveFilters(fileToSave.getAbsolutePath());
}
}
}
/**
* Save the filters to a XML files with a given name It create the File
* object then call overloaded method
*
* @param fileName The name of the xml file
*/
private void saveFilters(String fileName) {
if (fileName==null || fileName.length()==0) {
throw new IllegalArgumentException("Inavlid file name: "+fileName);
}
// Check if the name terminate with xml
if (!fileName.toUpperCase().endsWith(".XML")) {
fileName = fileName + ".xml";
}
List<CheckListTableEntry> entries=filterList.getEntries();
FiltersVector filters=new FiltersVector();
for (CheckListTableEntry entry: entries) {
filters.addFilter((Filter)entry.getItem(), entry.isActive());
}
File f = new File(fileName);
try {
filters.saveFilters(f);
filterFileName = f.getAbsolutePath();
System.out.println("Saved " + filterFileName);
} catch (IOException e) {
System.err.println("Error opening " + fileName);
}
}
/**
* Apply the filters in the table of logs
*
*/
private void applyFilters() {
FiltersVector newFilters = new FiltersVector();
for (CheckListTableEntry entry: filterList.getEntries()) {
newFilters.addFilter((Filter)entry.getItem(),entry.isActive());
}
filterable.setFilters(newFilters,false);
}
/**
* Restore the initial filters in the list
*
*
*/
private void restoreFilters() {
if (modified) {
int ret = JOptionPane.showConfirmDialog(this,
"Do you really want to restore the original filters?",
"Restore filters", JOptionPane.YES_NO_OPTION);
if (ret != JOptionPane.YES_OPTION) {
return;
}
}
setupFields(initialFilters,false);
}
/**
* Initialize the toolbar
*
*/
private void initToolbar() {
ImageIcon addIcon=new ImageIcon(FilterChooserDialog.class.getResource("/page_add.png"));
buttonAdd = new JButton("Add",addIcon);
buttonAdd.addActionListener(bl);
toolBar.add(buttonAdd);
ImageIcon removeIcon=new ImageIcon(FilterChooserDialog.class.getResource("/page_delete.png"));
buttonRemove = new JButton("Remove",removeIcon);
buttonRemove.addActionListener(bl);
toolBar.add(buttonRemove);
ImageIcon editIcon=new ImageIcon(FilterChooserDialog.class.getResource("/page_edit.png"));
buttonModify = new JButton("Modify",editIcon);
buttonModify.addActionListener(bl);
toolBar.add(buttonModify);
getContentPane().add(toolBar,BorderLayout.NORTH);
}
/**
* Initialize the menubar
*
*/
private void initMenubar() {
JMenu fileMenu = new JMenu("File");
fileMenu.add(loadMI);
fileMenu.add(saveMI);
fileMenu.add(saveAsMI);
fileMenu.add(new JSeparator());
fileMenu.add(closeMI);
JMenu editMenu = new JMenu("Edit");
editMenu.add(activateAllMI);
editMenu.add(deactivateAllMI);
editMenu.add(new JSeparator());
editMenu.add(clearAllMI);
menuBar.add(fileMenu);
menuBar.add(editMenu);
setJMenuBar(menuBar);
// Add the event listeners
loadMI.addActionListener(bl);
saveMI.addActionListener(bl);
saveAsMI.addActionListener(bl);
closeMI.addActionListener(bl);
activateAllMI.addActionListener(bl);
deactivateAllMI.addActionListener(bl);
clearAllMI.addActionListener(bl);
}
/**
* Override <code>JDialog.setVisible</code> to show this dialog over
* the <code>LogsingClient</code> component.
*/
@Override
public void setVisible(boolean visible) {
setLocationRelativeTo(loggingClient);
pack();
super.setVisible(visible);
toFront();
}
}