Subversion Repositories public

Rev

Blame | Last modification | View Log | Download | RSS feed

/*
 * ICPropDialog.java - incron table rule properties dialog
 *
 * Copyright (c) 2006 Lukas Jelinek, http://www.aiken.cz
 *
 * ==========================================================================
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License Version 2 as
 * published by the Free Software Foundation.
 *
 * 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 cz.aiken.util.jincron;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.text.*;
import java.io.*;
import java.util.*;

/**
 *
 * @author luk
 */

public class ICPropDialog extends JDialog implements ActionListener, UndoableEditListener {
   
    private static final String title = "Rule properties";
   
    private boolean changed = false;
    private boolean commit = false;
   
    private JTextField path = new JTextField();
    private JButton pathBut = new JButton("Browse...");
    private JPanel events = new JPanel();
    private JPanel cmd = new JPanel();
    private JTextField cmdText = new JTextField();
   
    private InotifyEvent evt = null;
    private HashMap<Integer, JCheckBox> mask = new HashMap<Integer, JCheckBox>();
    private HashMap<Integer, JCheckBox> flags = new HashMap<Integer, JCheckBox>();
   
    /** Creates a new instance of ICPropDialog */
    public ICPropDialog(ICRow row) {
        super();
        init(row);
    }
   
    protected void init(ICRow row) {
        Container c = getContentPane();
        c.setLayout(null);
        setSize(480, 470);
        setLocation(200, 200);
        setModal(true);
        setResizable(false);
        updateTitle();
       
        JLabel lab = new JLabel("Path");
        lab.setSize(55, 20);
        lab.setLocation(20, 20);
        c.add(lab);
       
        path.setSize(280, 20);
        path.setLocation(60, 20);
        path.setText(row.getPath());
        path.getDocument().addUndoableEditListener(this);
        path.setToolTipText("Specify the path to be watched");
        c.add(path);
       
        pathBut.setSize(100, 20);
        pathBut.setLocation(350, 20);
        pathBut.setActionCommand("path");
        pathBut.addActionListener(this);
        pathBut.setToolTipText("Browse the filesystem for a watch path");
        c.add(pathBut);
       
       
        evt = new InotifyEvent(row.getEvent());
       
        events.setSize(435, 200);
        events.setLocation(20, 50);
        events.setLayout(null);
        events.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), "Events"));
        c.add(events);
       
        createCheckbox("all events", 130, 20, 20, 20, "IN_ALL_EVENTS", "Watch all events", events, mask, InotifyEvent.IN_ALL_EVENTS);
       
        createCheckbox("access", 130, 20, 20, 45, "IN_ACCESS", "Watch accesses to file(s)", events, mask, InotifyEvent.IN_ACCESS);
        createCheckbox("modify", 130, 20, 20, 70, "IN_MODIFY", "Watch file(s) modifications", events, mask, InotifyEvent.IN_MODIFY);
        createCheckbox("attr. change", 130, 20, 20, 95, "IN_ATTRIB", "Watch attribute (metadata) changes", events, mask, InotifyEvent.IN_ATTRIB);
        createCheckbox("close", 130, 20, 20, 120, "IN_CLOSE", "Watch close events", events, mask, InotifyEvent.IN_CLOSE);
        createCheckbox("close (write)", 130, 20, 20, 145, "IN_CLOSE_WRITE", "Watch close events with writing", events, mask, InotifyEvent.IN_CLOSE_WRITE);
        createCheckbox("close (no write)", 130, 20, 20, 170, "IN_CLOSE_NOWRITE", "Watch close events without writing", events, mask, InotifyEvent.IN_CLOSE_NOWRITE);

        createCheckbox("open", 130, 20, 160, 45, "IN_OPEN", "Watch open events", events, mask, InotifyEvent.IN_OPEN);
        createCheckbox("move", 130, 20, 160, 70, "IN_MOVE", "Watch file moves", events, mask, InotifyEvent.IN_MOVE);
        createCheckbox("moved from", 130, 20, 160, 95, "IN_MOVED_FROM", "Watch events on file(s) moved out", events, mask, InotifyEvent.IN_MOVED_FROM);
        createCheckbox("moved to", 130, 20, 160, 120, "IN_MOVED_TO", "Watch events on file(s) moved in", events, mask, InotifyEvent.IN_MOVED_TO);
        createCheckbox("create", 130, 20, 160, 145, "IN_CREATE", "Watch creations", events, mask, InotifyEvent.IN_CREATE);
        createCheckbox("delete", 130, 20, 160, 170, "IN_DELETE", "Watch deletions (unlinks)", events, mask, InotifyEvent.IN_DELETE);
       
        createCheckbox("delete self", 130, 20, 300, 45, "IN_DELETE_SELF", "Watch the watched path is destroyed", events, mask, InotifyEvent.IN_DELETE_SELF);
        createCheckbox("dir only", 130, 20, 300, 70, "IN_ONLYDIR", "Watch only directory events", events, mask, InotifyEvent.IN_ONLYDIR);
        createCheckbox("don't follow", 130, 20, 300, 95, "IN_DONT_FOLLOW", "Don't follow symbolic links", events, mask, InotifyEvent.IN_DONT_FOLLOW);
        createCheckbox("oneshot", 130, 20, 300, 120, "IN_ONESHOT", "Watch exactly one event", events, mask, InotifyEvent.IN_ONESHOT);
        createCheckbox("no loop", 130, 20, 300, 170, "IN_NO_LOOP", "Avoid looping", events, flags, InotifyEvent.IN_NO_LOOP);
       
        updateCheckboxes();
       
        cmd.setSize(435, 130);
        cmd.setLocation(20, 260);
        cmd.setLayout(null);
        cmd.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), "Command"));
        c.add(cmd);
       
        cmdText.setSize(390, 20);
        cmdText.setLocation(20, 30);
        cmdText.setText(row.getCommand());
        cmdText.getDocument().addUndoableEditListener(this);
        cmdText.setToolTipText("Specify a command here");
        cmd.add(cmdText);
       
        JButton but = new JButton("Watch path");
        but.setSize(190, 20);
        but.setLocation(20, 60);
        but.setActionCommand("watch_path");
        but.addActionListener(this);
        but.setToolTipText("Insert a symbol for watch path");
        cmd.add(but);
       
        but = new JButton("Event name");
        but.setSize(190, 20);
        but.setLocation(220, 60);
        but.setActionCommand("event_name");
        but.addActionListener(this);
        but.setToolTipText("Insert a symbol for watch name");
        cmd.add(but);
       
        but = new JButton("Mask (symbolic)");
        but.setSize(190, 20);
        but.setLocation(20, 90);
        but.setActionCommand("symbolic_mask");
        but.addActionListener(this);
        but.setToolTipText("Insert a symbol for symbolic event mask");
        cmd.add(but);
       
        but = new JButton("Mask (numeric)");
        but.setSize(190, 20);
        but.setLocation(220, 90);
        but.setActionCommand("numeric_mask");
        but.addActionListener(this);
        but.setToolTipText("Insert a symbol for numeric event mask");
        cmd.add(but);
       
       
        but = new JButton("OK");
        but.setSize(80, 20);
        but.setLocation(150, 400);
        but.setActionCommand("ok");
        but.addActionListener(this);
        but.setToolTipText("Apply changes if any");
        c.add(but);
       
        but = new JButton("Cancel");
        but.setSize(80, 20);
        but.setLocation(240, 400);
        but.setActionCommand("cancel");
        but.addActionListener(this);
        but.setToolTipText("Leave the dialog without applying changes");
        c.add(but);
    }
   
    protected void createCheckbox(String text, int width, int height, int x, int y, String cmd, String tooltip, Container c, HashMap<Integer, JCheckBox> map, int mapVal) {
        JCheckBox cb = new JCheckBox(text);
        cb.setLocation(x, y);
        cb.setSize(width, height);
        cb.addActionListener(this);
        cb.setActionCommand(cmd);
        cb.setToolTipText(tooltip);
        c.add(cb);
        map.put(new Integer(mapVal), cb);
    }
   
    protected void browsePath() {
        JFileChooser fc = new JFileChooser();
        fc.setDialogTitle("Watch path");
        fc.setDialogType(JFileChooser.OPEN_DIALOG);
        fc.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
        fc.setMultiSelectionEnabled(false);
        fc.setSelectedFile(new File(path.getText()));
       
        int res = fc.showDialog(this, "Select");
        if (res == JFileChooser.APPROVE_OPTION) {
            path.setText(fc.getSelectedFile().getAbsolutePath());
        }
    }
   
    protected void addCmdText(String txt) {
        String s = cmdText.getText();
       
        int start = cmdText.getSelectionStart();
        int end = cmdText.getSelectionEnd();
        if (start != -1 || end != -1) {
            cmdText.setText(s.substring(0, start) + txt + s.substring(end));
            cmdText.setCaretPosition(start + txt.length());
        }
        else {
            int pos = cmdText.getCaretPosition();
            if (pos != -1) {
                cmdText.setText(s.substring(0, pos) + txt + s.substring(pos));
                cmdText.setCaretPosition(pos + txt.length());
            }
            else {
                cmdText.setText(s + txt);
                cmdText.setCaretPosition(s.length() + txt.length());
            }
        }
       
        cmdText.requestFocusInWindow();
    }
   
    protected void updateTitle() {
        if (changed)
            setTitle(title + " (modified)");
        else
            setTitle(title);
    }
   
    protected void updateCheckboxes() {
        Iterator<Integer> it = mask.keySet().iterator();
        while (it.hasNext()) {
            Integer i = it.next();
            JCheckBox cb = mask.get(i);
            if (cb != null) {
                cb.getModel().setSelected(evt.hasMask(i.intValue()));
            }
        }
       
        it = flags.keySet().iterator();
        while (it.hasNext()) {
            Integer i = it.next();
            JCheckBox cb = flags.get(i);
            if (cb != null) {
                cb.getModel().setSelected(evt.hasFlags(i.intValue()));
            }
        }
    }
   
    protected void modifyEvent(int val, boolean fl) {
        if (fl) {
            JCheckBox cb = flags.get(val);
            if (cb != null) {
                evt.changeFlags(val, cb.getModel().isSelected());
            }
        }
        else {
            JCheckBox cb = mask.get(val);
            if (cb != null) {
                evt.changeMask(val, cb.getModel().isSelected());
            }
        }
       
        updateCheckboxes();
       
        changed = true;
        updateTitle();
    }
   
    public ICRow getData() {
        return new ICRow(path.getText(), evt, cmdText.getText());
    }
   
    public boolean isModified() {
        return changed;
    }
   
    public boolean isCommitted() {
        return commit;
    }
   
    protected boolean validateData() {
        if (path.getText().length() == 0) {
            JOptionPane.showMessageDialog(this, "The watch path must not be empty.", "Error", JOptionPane.ERROR_MESSAGE);
            return false;
        }
       
        if (!(new File(path.getText())).exists()) {
            JOptionPane.showMessageDialog(this, "The watch path does not exist.\nThis is not an error but incrond will ignore such rules.", "Warning", JOptionPane.WARNING_MESSAGE);
        }
       
        if (evt.getMask() == 0) {
            JOptionPane.showMessageDialog(this, "At least one event type must be watched.", "Error", JOptionPane.ERROR_MESSAGE);
            return false;
        }
       
        if (cmdText.getText().length() == 0) {
            JOptionPane.showMessageDialog(this, "The command must not be empty.", "Error", JOptionPane.ERROR_MESSAGE);
            return false;
        }
       
        return true;
    }
   
    public void actionPerformed(ActionEvent e) {
        String s = e.getActionCommand();
       
        if (s.equals("path")) {
            browsePath();
        }
        else if (s.equals("watch_path")) {
            addCmdText("$@");
        }
        else if (s.equals("event_name")) {
            addCmdText("$#");
        }
        else if (s.equals("symbolic_mask")) {
            addCmdText("$%");
        }
        else if (s.equals("numeric_mask")) {
            addCmdText("$&");
        }
        else if (s.equals("ok")) {
            if (validateData()) {
                commit = true;
                setVisible(false);
            }
        }
        else if (s.equals("cancel")) {
            setVisible(false);
        }
        else {
            int i = InotifyEvent.getMaskByName(s);
            if (i != 0) {
                modifyEvent(i, false);
                return;
            }
           
            i = InotifyEvent.getFlagsByName(s);
            if (i != 0) {
                modifyEvent(i, true);
            }
        }
    }

    public void undoableEditHappened(UndoableEditEvent e) {
        changed = true;
        updateTitle();
    }      
}