/*
* Copyright (C) 2007-2009 Christian Bockermann <chris@jwall.org>
*
* This file is part of the AuditViewer. You can get more information
* about AuditViewer on its web page at
*
* http://www.jwall.org/web/audit/viewer.jsp
*
* AuditViewer 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.
*
* AuditViewer 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 org.jwall.app.table;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
import javax.swing.JTree;
import javax.swing.border.EmptyBorder;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.TreePath;
import org.jwall.app.Application;
import org.jwall.app.ui.Dialog;
import org.jwall.app.ui.ImagePanel;
import org.jwall.app.ui.InputDialog;
/**
* <p>
* This dialog provides a user choice for selecting the template to be used for rule set generation. Per default
* there are two templates available: the "weak" and the "strict" one. The list can be extended
* by custom templates later on.
* </p>
*
* @author Christian Bockermann <chris@jwall.org>
*
*/
public class TableViewDialog
extends Dialog
implements TreeSelectionListener, KeyListener, MouseListener
{
/** The unique class version */
private static final long serialVersionUID = -8143243508538302267L;
private final static String ACTION_ADD = "org.jwall.web.audit.viewer.table.TableColumn.add";
private final static String ACTION_DEL = "org.jwall.web.audit.viewer.table.TableColumn.delete";
private final static String ACTION_EDIT = "org.jwall.web.audit.viewer.table.TableColumn.edit";
private final static String ACTION_UP = "org.jwall.web.audit.viewer.table.TableColumn.move-up";
private final static String ACTION_DOWN = "org.jwall.web.audit.viewer.table.TableColumn.move-down";
/** This attribute reflects the users choice, i.e. a negative value means the user hit the cancel button */
int returnStatus = 0;
/** The buttons provided to the user */
JButton ok, cancel;
/** The UI list holding the templates */
JTree columnList;
/** The list model of the templates */
TableColumnListModel lm;
JButton add, delete, edit, moveUp, moveDown;
List<String> variables = new LinkedList<String>();
TableColumnListCellEditor editor = null;
/**
*
* Creates a new dialog which allows for the user to select one of the templates.
*
*/
public TableViewDialog( List<TableColumn> columns, Collection<String> varsAvailable ){
super();
setModal( true );
setResizable( false );
setTitle( "Adjust the Table View" );
variables.addAll( varsAvailable );
getContentPane().setLayout( new BorderLayout() );
ImagePanel i = new ImagePanel(InputDialog.class.getResource("/icons/logo_tall_60x513.jpg"), 0, 0, 60, 513);
i.setHeight( 513 );
i.setWidth( 60 );
i.setBackground( Color.BLACK );
this.getContentPane().add( i, BorderLayout.WEST );
JTextPane msg = new JTextPane();
msg.setBackground( Color.WHITE );
msg.setFont( msg.getFont().deriveFont( Font.PLAIN ) );
JPanel info = new JPanel( new BorderLayout() );
info.setBackground( Color.WHITE );
JLabel l = new JLabel();
l.setAlignmentX( Component.CENTER_ALIGNMENT );
l.setAlignmentY( Component.CENTER_ALIGNMENT );
l.setBorder( new EmptyBorder( 5, 5, 5, 5 ) );
l.setIcon( Application.getIcon("org.jwall.web.audit.viewer.table.TableColumnListDialog") );
info.add( l, BorderLayout.EAST );
info.add( msg, BorderLayout.CENTER );
//msg.setContentType( "text/html" );
msg.setText( // "<html><body style=\"font-family: Verdana,Arial,Sansserif; font-size: 12pt;\"> " +
"This dialog allows you to customize the view of the event table. The event table "
+ "is capable of showing only a subset of all events, which pass through a set of"
+ "filter rules, shown below.\n"
+ "This can be helpful when trying to hide \"annoying\" events, or events that have"
+ "already been investigated."
//+ "</body></html>"
);
msg.setFont( new Font( "SansSerif", Font.PLAIN, 12 ) ); // Font.getFont( Font.DIALOG_INPUT ) );
msg.setEditable( false );
msg.setBorder( new EmptyBorder( 15, 15, 15, 45 ) );
JPanel p = new JPanel( new BorderLayout() );
p.add( info, BorderLayout.NORTH );
JPanel buttons = new JPanel( new FlowLayout( FlowLayout.RIGHT ) );
ArrayList<TableColumn> data = new ArrayList<TableColumn>();
for( TableColumn col : columns )
data.add( new TableColumn( col.getVariable(), col.getColumnName() ) );
lm = new TableColumnListModel( data );
TableColumnListCellRenderer renderer = new TableColumnListCellRenderer( lm );
columnList = new JTree( lm );
columnList.setShowsRootHandles( false );
columnList.setRootVisible( false );
//columnList.setSelectionMode( ListSelectionModel.SINGLE_SELECTION );
//columnList.setSelectionModel( new TreeSelectionModel( ) );
columnList.addTreeSelectionListener( this );
columnList.setCellRenderer( renderer );
editor = new TableColumnListCellEditor( columnList, renderer );
editor.setVariableCompletions( variables );
columnList.setCellEditor( editor );
columnList.setBorder( BorderFactory.createLoweredBevelBorder() );
//templates.setFixedCellHeight( 80 );
columnList.setRowHeight( 40 );
columnList.setOpaque( true );
columnList.setEditable( true );
columnList.addKeyListener( this );
columnList.addMouseListener( this );
JScrollPane sp = new JScrollPane( columnList );
renderer.setJScrollPane( sp );
sp.setHorizontalScrollBarPolicy( JScrollPane.HORIZONTAL_SCROLLBAR_NEVER );
sp.setBorder( new EmptyBorder( 10, 10, 10, 10 ) );
p.add( sp, BorderLayout.CENTER );
JPanel actions = new JPanel( new FlowLayout( FlowLayout.LEFT ) );
columnList.setBackground( actions.getBackground() );
sp.setBackground( actions.getBackground() );
getContentPane().setBackground( actions.getBackground() );
add = new JButton();
add.setActionCommand( ACTION_ADD );
add.addActionListener( new ActionListener(){
public void actionPerformed( ActionEvent e ){
add();
}
});
add.setIcon( Application.getIcon( ACTION_ADD ) );
actions.add( add );
delete = new JButton();
delete.setActionCommand( ACTION_DEL );
delete.addActionListener( new ActionListener(){
public void actionPerformed( ActionEvent e ){
delete();
}
});
delete.setIcon( Application.getIcon( ACTION_DEL ) );
actions.add( delete );
edit = new JButton();
edit.setActionCommand( ACTION_EDIT );
edit.addActionListener( new ActionListener(){
public void actionPerformed( ActionEvent e ){
edit();
}
});
edit.setIcon( Application.getIcon( ACTION_EDIT ) );
edit.setEnabled( getSelectedIndex() >= 0 );
actions.add( edit );
p.add( actions, BorderLayout.SOUTH );
ok = new JButton("Ok");
ok.addActionListener( new ActionListener(){
public void actionPerformed(ActionEvent e){
try {
returnStatus = 1;
close();
} catch (Exception ex){
Application.handleException( ex );
}
}
});
JButton save = new JButton( "Save" );
save.addActionListener( new ActionListener(){
public void actionPerformed( ActionEvent e ) {
try {
returnStatus = 2;
close();
} catch (Exception ex){
Application.handleException( ex );
}
}
});
cancel = new JButton("Cancel");
cancel.addActionListener( new ActionListener(){
public void actionPerformed(ActionEvent e){
try {
returnStatus = -1;
close();
} catch (Exception ex){
Application.handleException( ex );
}
}
});
buttons.add( ok );
buttons.add( save );
buttons.add( cancel );
this.getContentPane().add( p, BorderLayout.CENTER );
this.getContentPane().add( buttons, BorderLayout.SOUTH );
setSize( 740, 500 );
this.center();
}
public ArrayList<TableColumn> getColumnList(){
return lm.columns;
}
public void actionPerformed( ActionEvent e){
String cmd = e.getActionCommand();
if( ACTION_ADD.equals( cmd ) ){
add();
return;
}
if( ACTION_DEL.equals( cmd ) ){
delete();
return;
}
if( ACTION_UP.equals( cmd ) ){
moveUp();
return;
}
if( ACTION_DOWN.equals( cmd ) ){
moveDown();
return;
}
}
public void add(){
int idx = getSelectedIndex();
if( idx < 0 )
idx = lm.getSize();
lm.add( idx, new TableColumn( "variable", "column-name" ) );
setSelectedIndex( idx );
moveUp.setEnabled( getSelectedIndex() > 0 );
columnList.validate();
startEditingRow( idx );
}
public void edit(){
int idx = getSelectedIndex();
startEditingRow( idx );
}
public void startEditingRow( int idx ){
if( idx >= 0 ){
TreePath path = columnList.getPathForRow( idx );
columnList.startEditingAtPath( path );
}
}
public void delete(){
int idx = getSelectedIndex();
if( idx >= 0 )
lm.remove( idx );
if( idx < lm.getSize() )
setSelectedIndex( idx );
moveUp.setEnabled( getSelectedIndex() > 0 );
delete.setEnabled( getSelectedIndex() >= 0 );
columnList.validate();
}
public void moveUp(){
int idx = getSelectedIndex();
lm.swap( idx, idx - 1 );
setSelectedIndex( idx - 1 );
columnList.validate();
moveUp.setEnabled( getSelectedIndex() > 0 );
}
public void moveDown(){
int idx = getSelectedIndex();
lm.swap( idx, idx + 1 );
setSelectedIndex( idx + 1 );
columnList.validate();
moveDown.setEnabled( getSelectedIndex() + 1 < lm.getSize() );
}
/**
* Returns the user action on this dialog, i.e. either a positive value if the user
* hit the OK button or a negative value if the user canceled the selection.
*
* @return Whether the user selected a template or canceled the selection.
*/
public int getReturnStatus(){
return returnStatus;
}
public void valueChanged(TreeSelectionEvent e)
{
moveUp.setEnabled( getSelectedIndex() > 0 );
moveDown.setEnabled( getSelectedIndex() >= 0 && getSelectedIndex() + 1 < lm.getSize() );
delete.setEnabled( getSelectedIndex() >= 0 );
edit.setEnabled( getSelectedIndex() >= 0 );
}
public void setSelectedIndex( int idx ){
if( idx >= 0 && idx < lm.getSize() )
columnList.setSelectionRow( idx );
}
public int getSelectedIndex(){
if( columnList.getSelectionCount() == 0 )
return -1;
return columnList.getSelectionRows()[0];
}
public void close(){
if( editor != null )
editor.close();
setVisible( false );
}
public void keyPressed(KeyEvent e)
{
if( e.getKeyCode() == KeyEvent.VK_2 && getSelectedIndex() >= 0 )
startEditingRow( getSelectedIndex() );
}
public void keyReleased(KeyEvent e)
{
}
public void keyTyped(KeyEvent e)
{
}
public void mouseClicked(MouseEvent e)
{
if( e.getClickCount() == 2 ){
int idx = columnList.getRowForLocation( e.getX(), e.getY() );
startEditingRow( idx );
}
}
public void mouseEntered(MouseEvent e)
{
}
public void mouseExited(MouseEvent e)
{
}
public void mousePressed(MouseEvent e)
{
}
public void mouseReleased(MouseEvent e)
{
}
}