
net.vectorpublish.desktop.vp.impl.AskDialog Maven / Gradle / Ivy
The newest version!
/*
* Copyright (c) 2016, Peter Rader. All rights reserved.
* ___ ___ __ ______ __ __ __ __
* | | |.-----..----.| |_ .-----..----.| __ \.--.--.| |--.| ||__|.-----.| |--.
* | | || -__|| __|| _|| _ || _|| __/| | || _ || || ||__ --|| |
* \_____/ |_____||____||____||_____||__| |___| |_____||_____||__||__||_____||__|__|
*
* http://www.gnu.org/licenses/gpl-3.0.html
*/
package net.vectorpublish.desktop.vp.impl;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dialog.ModalExclusionType;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Objects;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JColorChooser;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSpinner;
import javax.swing.JTextArea;
import javax.swing.SpinnerNumberModel;
import javax.swing.SwingConstants;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.BadLocationException;
import javax.swing.text.DefaultHighlighter;
import net.vectorpublish.desktop.vp.system.LayoutAdapter;
public class AskDialog extends JFrame {
public final static int SPACING_BETWEEN_COMPONENTS = 5;
public final static int BUTTON_HEIGHT = 36;
public final static int COLOR_CHOOSER_HEIGHT = 200;
public static final int FILTER_MINIMUM_SIZE = 8;
private final class LayoutAskDialog extends LayoutAdapter {
@Override
public void layoutContainer(final Container parent) {
if (parent == scrollablePanel) {
parent.setSize(getContentPane().getWidth(), 10);
}
final int width = parent.getWidth();
final int height = parent.getHeight();
final int halfWidth = (width - SPACING_BETWEEN_COMPONENTS * 3) / 2;
if (parent == scrollablePanel) {
int yPos = 0;
final int minusWidth = scroll.getVerticalScrollBar().getWidth() + 20;
Iterator iterator = rows.iterator();
while (iterator.hasNext()) {
AskDialog.Row row = (AskDialog.Row) iterator.next();
if (row == filterRow) {
if (!showFilter()) {
continue;
}
}
int rowHeight = BUTTON_HEIGHT;
if (row.component instanceof JColorChooser) {
rowHeight = COLOR_CHOOSER_HEIGHT;
}
row.label.setBounds(SPACING_BETWEEN_COMPONENTS, yPos, halfWidth, rowHeight);
row.component.setBounds(SPACING_BETWEEN_COMPONENTS * 2 + halfWidth, yPos, halfWidth - minusWidth,
rowHeight);
yPos += rowHeight + SPACING_BETWEEN_COMPONENTS;
}
scroll.setBounds(0, 0, contentPane.getWidth(), contentPane.getHeight() - BUTTON_HEIGHT);
final Dimension s = new Dimension(getContentPane().getWidth() - minusWidth, yPos);
parent.setSize(s);
parent.setPreferredSize(s);
} else {
cancel.setBounds(SPACING_BETWEEN_COMPONENTS, height - SPACING_BETWEEN_COMPONENTS - BUTTON_HEIGHT,
halfWidth, BUTTON_HEIGHT);
ok.setBounds(width - halfWidth - SPACING_BETWEEN_COMPONENTS,
height - SPACING_BETWEEN_COMPONENTS - BUTTON_HEIGHT, halfWidth, BUTTON_HEIGHT);
}
}
}
private class Row {
protected final JLabel label;
protected final T component;
public final String question;
private Row(final String ask, final T comp) {
question = ask;
component = comp;
label = new JLabel(question);
label.setVerticalAlignment(SwingConstants.CENTER);
label.setHorizontalTextPosition(SwingConstants.RIGHT);
scrollablePanel.add(label);
scrollablePanel.add(comp);
}
public R getValue() {
if (component instanceof JSpinner) {
final JSpinner number = (JSpinner) component;
return (R) number.getValue();
} else if (component instanceof JTextArea) {
final JTextArea text = (JTextArea) component;
return (R) text.getText();
} else if (component instanceof JCheckBox) {
final JCheckBox check = (JCheckBox) component;
return (R) (Boolean) check.isSelected();
} else if (component instanceof JColorChooser) {
final JColorChooser color = (JColorChooser) component;
return (R) color.getColor();
} else if (component instanceof JComboBox) {
final JComboBox box = (JComboBox) component;
return (R) box.getSelectedItem();
} else
return null;
}
protected void unregister() {
scrollablePanel.remove(label);
scrollablePanel.remove(component);
}
}
private class RegexFilterRow extends Row implements DocumentListener {
public RegexFilterRow() {
super("Filter", new JTextArea());
component.setHighlighter(new DefaultHighlighter());
component.getBackground();
component.getDocument().addDocumentListener(this);
}
@Override
@Deprecated
protected void unregister() {
super.unregister();
}
public void revalidate() {
synchronized (this) {
boolean visible = showFilter();
component.setVisible(visible);
label.setVisible(visible);
}
}
@Override
public void insertUpdate(DocumentEvent e) {
update();
}
private void update() {
Pattern compile = null;
try {
compile = Pattern.compile(component.getText());
component.getHighlighter().removeAllHighlights();
} catch (PatternSyntaxException e) {
try {
component.getHighlighter().addHighlight(e.getIndex(), 1, DefaultHighlighter.DefaultPainter);
} catch (BadLocationException range) {
try {
component.getHighlighter().addHighlight(0, 0, DefaultHighlighter.DefaultPainter);
} catch (BadLocationException e2) {
throw new RuntimeException(e2);
}
}
}
for (Row row : rows) {
if (row == this) {
continue;
}
if (compile != null) {
boolean mark = compile.matcher(row.question).matches();
row.label.setForeground(mark ? Color.BLACK : Color.LIGHT_GRAY);
} else {
row.label.setForeground(Color.BLACK);
}
}
repaint();
}
@Override
public void removeUpdate(DocumentEvent e) {
update();
}
@Override
public void changedUpdate(DocumentEvent e) {
update();
}
}
private boolean showFilter() {
return rows.size() >= FILTER_MINIMUM_SIZE;
}
private final LinkedHashSet rows = new LinkedHashSet<>();
private final JButton cancel = new JButton(new AbstractAction("Cancel") {
@Override
public void actionPerformed(ActionEvent event) {
synchronized (rows) {
Iterator rowIter = rows.iterator();
while (rowIter.hasNext()) {
Row row = rowIter.next();
if (row != filterRow) {
row.unregister();
rowIter.remove();
}
}
filterRow.revalidate();
}
setVisible(false);
doLayout();
}
});
private final JButton ok = new JButton(new AbstractAction("OK") {
@Override
public void actionPerformed(ActionEvent event) {
setVisible(false);
}
});
private final JPanel scrollablePanel = new JPanel();
private final JScrollPane scroll = new JScrollPane(scrollablePanel);
private final Container contentPane = getContentPane();
private final RegexFilterRow filterRow = new RegexFilterRow();
public AskDialog() {
super();
setAlwaysOnTop(true);
final LayoutAskDialog layout = new LayoutAskDialog();
contentPane.setLayout(layout);
setModalExclusionType(ModalExclusionType.TOOLKIT_EXCLUDE);
contentPane.add(cancel);
contentPane.add(scroll);
scrollablePanel.setLayout(layout);
contentPane.add(ok);
setBackground(Color.red);
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent closeEvent) {
AskDialog.this.setVisible(false);
}
});
rows.add(filterRow);
}
public synchronized void addQuestion(final String title, final String question, A... values) {
Objects.requireNonNull(question);
final JLabel label = new JLabel(question, JLabel.RIGHT);
label.setVerticalAlignment(SwingConstants.CENTER);
final JComponent input;
A proposal;
if (values.length == 1) {
proposal = values[0];
if (proposal instanceof Double) {
final double number = (Double) proposal;
input = new JSpinner(new SpinnerNumberModel(number, Double.MIN_VALUE, Double.MAX_VALUE, 0.1));
} else if (proposal instanceof Number) {
final Number number = (Number) proposal;
input = new JSpinner(
new SpinnerNumberModel(number.intValue(), Integer.MIN_VALUE, Integer.MAX_VALUE, 1));
} else if (proposal instanceof String) {
input = new JTextArea(proposal + "");
} else if (proposal instanceof Boolean) {
input = new JCheckBox(title, (Boolean) proposal);
} else if (proposal instanceof Color) {
final JColorChooser chooser = new JColorChooser((Color) proposal);
chooser.setPreviewPanel(new JPanel());
input = chooser;
} else {
throw new RuntimeException("Type not supported yet:" + proposal.getClass());
}
} else if (values.length > 1) {
final JComboBox box = new JComboBox(values);
box.setEditable(false);
input = box;
} else {
throw new RuntimeException("Size not supported:" + values.length);
}
synchronized (rows) {
rows.add(new Row(question, input));
}
filterRow.revalidate();
doLayout();
}
/**
* This method is threadsafe.
*/
@SuppressWarnings("unchecked")
public A removeResult(String question) {
synchronized (rows) {
for (final Row row : rows) {
if (row.question.equals(question)) {
final A value = (A) row.getValue();
row.unregister();
rows.remove(row);
filterRow.revalidate();
return value;
}
}
}
return null;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy