package krasa.grepconsole.gui;
import com.centerkey.utils.BareBonesBrowserLaunch;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.ui.DialogBuilder;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.JBPopupMenu;
import com.intellij.ui.CheckedTreeNode;
import com.intellij.ui.JBColor;
import com.intellij.ui.treeStructure.treetable.TreeTableTree;
import com.intellij.util.ArrayUtil;
import com.intellij.util.ui.tree.TreeUtil;
import krasa.grepconsole.gui.table.CheckboxTreeTable;
import krasa.grepconsole.gui.table.GrepExpressionGroupTreeNode;
import krasa.grepconsole.gui.table.GrepExpressionItemTreeNode;
import krasa.grepconsole.gui.table.TableUtils;
import krasa.grepconsole.model.GrepColor;
import krasa.grepconsole.model.GrepExpressionGroup;
import krasa.grepconsole.model.GrepExpressionItem;
import krasa.grepconsole.model.Profile;
import krasa.grepconsole.plugin.DefaultState;
import krasa.grepconsole.plugin.GrepConsoleApplicationComponent;
import krasa.grepconsole.plugin.PluginState;
import krasa.grepconsole.tail.TailIntegrationForm;
import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.text.NumberFormatter;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
import java.awt.event.*;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.List;
import static krasa.grepconsole.Cloner.deepClone;
public class SettingsDialog {
private static final Logger log = Logger.getInstance(SettingsDialog.class);
private final SettingsContext settingsContext;
private JPanel rootComponent;
private CheckboxTreeTable table;
private JButton addNewButton;
private JButton resetToDefaultButton;
private JCheckBox enableHighlightingCheckBox;
private JFormattedTextField maxLengthToMatch;
private JCheckBox enableMaxLength;
private JButton duplicateButton;
private JButton deleteButton;
private JCheckBox enableFiltering;
private JCheckBox multilineOutput;
private JButton DONATEButton;
private JCheckBox showStatsInConsole;
private JCheckBox showStatsInStatusBar;
private JButton fileTailSettings;
private JButton addNewGroup;
private JLabel contextSpecificText;
private JCheckBox enableFoldings;
private JFormattedTextField maxProcessingTime;
private JCheckBox filterOutBeforeGreppingToASubConsole;
// private JCheckBox synchronous;
private PluginState settings;
public SettingsDialog(PluginState settings) {
this(settings, SettingsContext.NONE);
}
public SettingsDialog(PluginState settings, SettingsContext settingsContext) {
// int version = Integer.parseInt(ApplicationInfo.getInstance().getMajorVersion());
// if (version < 163) {
// synchronous.setVisible(false);
// }
this.settingsContext = settingsContext;
this.settings = settings;
DONATEButton.setBorder(null);
DONATEButton.setContentAreaFilled(false);
DONATEButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
BareBonesBrowserLaunch.openURL("https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=75YN7U7H7D7XU&lc=CZ&item_name=Grep%20Console%20%2d%20IntelliJ%20plugin¤cy_code=USD&bn=PP%2dDonationsBF%3abtn_donateCC_LG%2egif%3aNonHostedGuest");
}
});
addNewButton.addActionListener(new AddNewItemAction());
addNewGroup.addActionListener(new AddNewGroupAction());
resetToDefaultButton.addActionListener(new ResetToDefaultAction());
duplicateButton.addActionListener(new DuplicateAction());
deleteButton.addActionListener(new DeleteAction());
table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent e) {
if (!e.getValueIsAdjusting()) {
Object source = e.getSource();
if (source instanceof DefaultListSelectionModel) {
setSelectedRow(((DefaultListSelectionModel) source).getLeadSelectionIndex());
}
}
}
});
table.addMouseListener(rightClickMenu());
table.addKeyListener(new DeleteListener());
disableCopyDeleteButton();
fileTailSettings.addActionListener(new FileTailSettings());
if (settingsContext == SettingsContext.CONSOLE) {
contextSpecificText.setText("Select items for which statistics should be displayed ('"
+ SettingsTableBuilder.CONSOLE_COUNT + "' column)");
} else if (settingsContext == SettingsContext.STATUS_BAR) {
contextSpecificText.setText("Select items for which statistics should be displayed ('"
+ SettingsTableBuilder.STATUS_BAR_COUNT + "' column)");
} else {
contextSpecificText.setVisible(false);
}
}
public MouseAdapter rightClickMenu() {
return new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
if (SwingUtilities.isLeftMouseButton(e)) {
} else if (SwingUtilities.isRightMouseButton(e)) {
if (getSelectedNode() == null) {
return;
}
JPopupMenu popup = new JBPopupMenu();
GrepExpressionItem selectedGrepExpressionItem = getSelectedGrepExpressionItem();
if (selectedGrepExpressionItem != null) {
popup.add(getConvertAction(selectedGrepExpressionItem));
}
popup.add(newMenuItem("Add New Item", new AddNewItemAction()));
popup.add(newMenuItem("Duplicate", new DuplicateAction()));
popup.add(newMenuItem("Delete", new DeleteAction()));
popup.show(e.getComponent(), e.getX(), e.getY());
}
}
private JMenuItem newMenuItem(String name, ActionListener l) {
final JMenuItem item = new JMenuItem(name);
item.addActionListener(l);
return item;
}
private JMenuItem getConvertAction(final GrepExpressionItem item) {
final boolean highlightOnlyMatchingText = item.isHighlightOnlyMatchingText();
final JMenuItem convert = new JMenuItem(highlightOnlyMatchingText ? "Convert to whole line"
: "Convert to words only");
try {
convert.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (!highlightOnlyMatchingText) {
getSelectedGrepExpressionItem().setHighlightOnlyMatchingText(true);
getSelectedGrepExpressionItem().setContinueMatching(true);
if (item.getGrepExpression().startsWith(".*")) {
item.grepExpression(item.getGrepExpression().substring(2));
}
if (item.getGrepExpression().endsWith(".*")) {
item.grepExpression(item.getGrepExpression().substring(0,
item.getGrepExpression().length() - 2));
}
} else {
getSelectedGrepExpressionItem().setHighlightOnlyMatchingText(false);
getSelectedGrepExpressionItem().setContinueMatching(false);
if (!item.getGrepExpression().startsWith(".*")) {
item.grepExpression(".*" + item.getGrepExpression());
}
if (!item.getGrepExpression().endsWith(".*")) {
item.grepExpression(item.getGrepExpression() + ".*");
}
}
reloadNode(SettingsDialog.this.getSelectedNode());
}
});
} catch (Exception e) {
e.printStackTrace();
}
return convert;
}
};
}
private void reloadNode(final DefaultMutableTreeNode selectedNode) {
DefaultTreeModel model = (DefaultTreeModel) table.getTree().getModel();
model.nodeChanged(selectedNode);
}
private GrepExpressionItem getSelectedGrepExpressionItem() {
DefaultMutableTreeNode selectedNode = getSelectedNode();
GrepExpressionItem item = null;
if (selectedNode instanceof GrepExpressionItemTreeNode) {
item = (GrepExpressionItem) selectedNode.getUserObject();
}
return item;
}
public DefaultMutableTreeNode getSelectedNode() {
return (DefaultMutableTreeNode) table.getTree().getLastSelectedPathComponent();
}
private void disableCopyDeleteButton() {
deleteButton.setEnabled(false);
duplicateButton.setEnabled(false);
}
private void setSelectedRow(Integer selectedRow) {
deleteButton.setEnabled(selectedRow != null && selectedRow >= 0);
duplicateButton.setEnabled(selectedRow != null && selectedRow >= 0);
}
public JPanel getRootComponent() {
return rootComponent;
}
public PluginState getSettings() {
getData(getProfile());
return settings;
}
public Profile getProfile() {
return settings.getDefaultProfile();
}
public void importFrom(PluginState settings) {
this.settings = settings;
setData(settings.getDefaultProfile());
resetTreeModel();
}
private void resetTreeModel() {
CheckedTreeNode root = (CheckedTreeNode) table.getTree().getModel().getRoot();
root.removeAllChildren();
for (GrepExpressionGroup group : getProfile().getGrepExpressionGroups()) {
GrepExpressionGroupTreeNode newChild = new GrepExpressionGroupTreeNode(group);
for (GrepExpressionItem grepExpressionItem : group.getGrepExpressionItems()) {
newChild.add(new GrepExpressionItemTreeNode(grepExpressionItem));
}
root.add(newChild);
}
TableUtils.reloadTree(table);
TreeUtil.expandAll(table.getTree());
}
public boolean isSettingsModified(PluginState data) {
getData(getProfile());
return !this.settings.equals(data);
}
private void createUIComponents() {
fileTailSettings = new JButton();
NumberFormatter numberFormatter = new NumberFormatter();
numberFormatter.setMinimum(0);
maxLengthToMatch = new JFormattedTextField(numberFormatter);
maxProcessingTime = new JFormattedTextField(numberFormatter);
table = new SettingsTableBuilder(this).getTable();
}
private GrepExpressionItem newItem() {
GrepExpressionItem item = new GrepExpressionItem();
item.setGrepExpression("foo");
item.setEnabled(true);
item.setContinueMatching(true);
item.setHighlightOnlyMatchingText(true);
item.getStyle().setBackgroundColor(new GrepColor(true, JBColor.CYAN));
return item;
}
private GrepExpressionGroup getGrepExpressionGroup(DefaultMutableTreeNode selectedNode) {
return (GrepExpressionGroup) selectedNode.getUserObject();
}
private GrepExpressionItem getSelectedGrepExpressionItem(DefaultMutableTreeNode selectedNode) {
return (GrepExpressionItem) selectedNode.getUserObject();
}
public void rebuildProfile() {
List<GrepExpressionGroup> grepExpressionGroups = getProfile().getGrepExpressionGroups();
grepExpressionGroups.clear();
DefaultMutableTreeNode model = (DefaultMutableTreeNode) table.getTree().getModel().getRoot();
Enumeration children = model.children();
while (children.hasMoreElements()) {
DefaultMutableTreeNode o = (DefaultMutableTreeNode) children.nextElement();
if (o instanceof GrepExpressionGroupTreeNode) {
GrepExpressionGroup grepExpressionGroup = ((GrepExpressionGroupTreeNode) o).getGrepExpressionGroup();
grepExpressionGroup.getGrepExpressionItems().clear();
Enumeration children1 = o.children();
while (children1.hasMoreElements()) {
Object o1 = children1.nextElement();
if (o1 instanceof GrepExpressionItemTreeNode) {
GrepExpressionItem grepExpressionItem = ((GrepExpressionItemTreeNode) o1).getGrepExpressionItem();
grepExpressionGroup.add(grepExpressionItem);
} else {
throw new IllegalStateException("unexpected tree node" + o1);
}
}
grepExpressionGroups.add(grepExpressionGroup);
} else {
throw new IllegalStateException("unexpected tree node" + o);
}
}
}
public void setData(Profile data) {
enableMaxLength.setSelected(data.isEnableMaxLengthLimit());
enableHighlightingCheckBox.setSelected(data.isEnabledHighlighting());
enableFiltering.setSelected(data.isEnabledInputFiltering());
multilineOutput.setSelected(data.isMultiLineOutput());
maxProcessingTime.setText(data.getMaxProcessingTime());
showStatsInConsole.setSelected(data.isShowStatsInConsoleByDefault());
showStatsInStatusBar.setSelected(data.isShowStatsInStatusBarByDefault());
enableFoldings.setSelected(data.isEnableFoldings());
filterOutBeforeGreppingToASubConsole.setSelected(data.isFilterOutBeforeGrep());
maxLengthToMatch.setText(data.getMaxLengthToMatch());
}
public void getData(Profile data) {
data.setEnableMaxLengthLimit(enableMaxLength.isSelected());
data.setEnabledHighlighting(enableHighlightingCheckBox.isSelected());
data.setEnabledInputFiltering(enableFiltering.isSelected());
data.setMultiLineOutput(multilineOutput.isSelected());
data.setMaxProcessingTime(maxProcessingTime.getText());
data.setShowStatsInConsoleByDefault(showStatsInConsole.isSelected());
data.setShowStatsInStatusBarByDefault(showStatsInStatusBar.isSelected());
data.setEnableFoldings(enableFoldings.isSelected());
data.setFilterOutBeforeGrep(filterOutBeforeGreppingToASubConsole.isSelected());
data.setMaxLengthToMatch(maxLengthToMatch.getText());
}
public boolean isModified(Profile data) {
if (enableMaxLength.isSelected() != data.isEnableMaxLengthLimit()) return true;
if (enableHighlightingCheckBox.isSelected() != data.isEnabledHighlighting()) return true;
if (enableFiltering.isSelected() != data.isEnabledInputFiltering()) return true;
if (multilineOutput.isSelected() != data.isMultiLineOutput()) return true;
if (maxProcessingTime.getText() != null ? !maxProcessingTime.getText().equals(data.getMaxProcessingTime()) : data.getMaxProcessingTime() != null)
return true;
if (showStatsInConsole.isSelected() != data.isShowStatsInConsoleByDefault()) return true;
if (showStatsInStatusBar.isSelected() != data.isShowStatsInStatusBarByDefault()) return true;
if (enableFoldings.isSelected() != data.isEnableFoldings()) return true;
if (filterOutBeforeGreppingToASubConsole.isSelected() != data.isFilterOutBeforeGrep()) return true;
if (maxLengthToMatch.getText() != null ? !maxLengthToMatch.getText().equals(data.getMaxLengthToMatch()) : data.getMaxLengthToMatch() != null)
return true;
return false;
}
private class DeleteListener extends KeyAdapter {
@Override
public void keyPressed(KeyEvent e) {
final int keyCode = e.getKeyCode();
if (keyCode == KeyEvent.VK_DELETE) {
delete();
}
}
}
private void delete() {
TreeNode selectNode = null;
TreeTableTree tree = table.getTree();
int[] selectionRows = tree.getSelectionRows();
if (selectionRows == null) {
return;
}
Arrays.sort(selectionRows);
selectionRows = ArrayUtil.reverseArray(selectionRows);
for (int selectionRow : selectionRows) {
TreePath treePath = tree.getPathForRow(selectionRow);
DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode) treePath.getLastPathComponent();
DefaultMutableTreeNode parent = (DefaultMutableTreeNode) selectedNode.getParent();
if (selectNode == null || selectNode == selectedNode || selectNode.getParent() == selectedNode) {
int index = parent.getIndex(selectedNode);
if (index + 1 < parent.getChildCount()) {
selectNode = parent.getChildAt(index + 1);
} else if (index > 0) {
selectNode = parent.getChildAt(index - 1);
} else {
selectNode = parent;
}
}
parent.remove(selectedNode);
}
rebuildProfile();
TableUtils.reloadTree(this.table);
TableUtils.selectNode((DefaultMutableTreeNode) selectNode, table);
DefaultMutableTreeNode root = (DefaultMutableTreeNode) table.getTree().getModel().getRoot();
if (root.getChildCount() == 0) {
disableCopyDeleteButton();
}
}
private class AddNewItemAction implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
DefaultMutableTreeNode selectedNode = getSelectedNode();
CheckedTreeNode newChild;
if (selectedNode == null) {
DefaultMutableTreeNode root = (DefaultMutableTreeNode) table.getTree().getModel().getRoot();
GrepExpressionGroupTreeNode aNew = new GrepExpressionGroupTreeNode(new GrepExpressionGroup("new"));
newChild = new GrepExpressionItemTreeNode(newItem());
aNew.add(newChild);
root.add(aNew);
} else if (selectedNode.getUserObject() instanceof GrepExpressionGroup) {
newChild = new GrepExpressionItemTreeNode(newItem());
selectedNode.add(newChild);
} else {
GrepExpressionGroupTreeNode parent = (GrepExpressionGroupTreeNode) selectedNode.getParent();
newChild = new GrepExpressionItemTreeNode(newItem());
parent.insert(newChild, parent.getIndex(selectedNode) + 1);
}
rebuildProfile();
TableUtils.reloadTree(table);
TableUtils.selectNode(newChild, table);
}
}
private class AddNewGroupAction implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
DefaultMutableTreeNode root = (DefaultMutableTreeNode) table.getTree().getModel().getRoot();
GrepExpressionGroupTreeNode aNew = new GrepExpressionGroupTreeNode(new GrepExpressionGroup("new"));
root.add(aNew);
rebuildProfile();
TableUtils.reloadTree(table);
TableUtils.selectNode(aNew, table);
}
}
private class ResetToDefaultAction implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
SettingsDialog.this.settings.setProfiles(DefaultState.createDefault());
disableCopyDeleteButton();
importFrom(SettingsDialog.this.settings);
}
}
private class DuplicateAction implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
DefaultMutableTreeNode selectedNode = getSelectedNode();
if (selectedNode instanceof GrepExpressionItemTreeNode) {
GrepExpressionItemTreeNode newChild = new GrepExpressionItemTreeNode(copy(selectedNode));
DefaultMutableTreeNode parent = (DefaultMutableTreeNode) selectedNode.getParent();
parent.insert(newChild, parent.getIndex(selectedNode) + 1);
TableUtils.reloadTree(SettingsDialog.this.table);
TableUtils.selectNode(newChild, SettingsDialog.this.table);
} else if (selectedNode instanceof GrepExpressionGroupTreeNode) {
GrepExpressionGroup group = copy((GrepExpressionGroup) selectedNode.getUserObject());
GrepExpressionGroupTreeNode newChild = new GrepExpressionGroupTreeNode(group);
for (GrepExpressionItem grepExpressionItem : group.getGrepExpressionItems()) {
newChild.add(new GrepExpressionItemTreeNode(grepExpressionItem));
}
DefaultMutableTreeNode parent = (DefaultMutableTreeNode) selectedNode.getParent();
parent.insert(newChild, parent.getIndex(selectedNode) + 1);
TableUtils.reloadTree(SettingsDialog.this.table);
TableUtils.expand(newChild, SettingsDialog.this.table);
TableUtils.selectNode(newChild, SettingsDialog.this.table);
}
rebuildProfile();
}
private GrepExpressionGroup copy(final GrepExpressionGroup grepExpressionGroup) {
GrepExpressionGroup group = deepClone(grepExpressionGroup);
for (GrepExpressionItem grepExpressionItem : group.getGrepExpressionItems()) {
grepExpressionItem.generateNewId();
}
return group;
}
private GrepExpressionItem copy(DefaultMutableTreeNode selectedNode) {
GrepExpressionItem expressionItem = deepClone((GrepExpressionItem) selectedNode.getUserObject());
expressionItem.generateNewId();
return expressionItem;
}
}
private class DeleteAction implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
delete();
}
}
private class FileTailSettings implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
final TailIntegrationForm form = new TailIntegrationForm();
form.setData(settings.getTailSettings());
DialogBuilder builder = new DialogBuilder(SettingsDialog.this.getRootComponent());
builder.setCenterPanel(form.getRoot());
builder.setDimensionServiceKey("GrepConsoleTailFileDialog");
builder.setTitle("Tail File settings");
builder.removeAllActions();
builder.addOkAction();
builder.addCancelAction();
boolean isOk = builder.show() == DialogWrapper.OK_EXIT_CODE;
if (isOk) {
form.getData(settings.getTailSettings());
GrepConsoleApplicationComponent.getInstance().getState().setTailSettings(settings.getTailSettings());
form.rebind(settings.getTailSettings());
}
}
}
}