+ use RSyntaxTextArea as Groovy editor so we get neat highlighting and bracket matching :)
This commit is contained in:
parent
0408a17ddb
commit
07173fabf0
|
@ -101,6 +101,10 @@
|
|||
<include name="net/miginfocom/**" />
|
||||
</zipfileset>
|
||||
|
||||
<zipfileset src="${dir.lib}/rsyntaxtextarea.jar">
|
||||
<include name="org/fife/**" />
|
||||
</zipfileset>
|
||||
|
||||
<zipfileset src="${dir.lib}/xmlrpc.jar">
|
||||
<include name="redstone/xmlrpc/**" />
|
||||
</zipfileset>
|
||||
|
|
|
@ -60,6 +60,7 @@
|
|||
<jar href="xercesImpl.jar" download="lazy" part="scraper" />
|
||||
<jar href="mediainfo.jar" download="lazy" part="native" />
|
||||
<jar href="sevenzipjbinding.jar" download="lazy" part="native" />
|
||||
<jar href="rsyntaxtextarea.jar" download="eager" />
|
||||
</resources>
|
||||
|
||||
<resources os="Windows" arch="x86">
|
||||
|
|
Binary file not shown.
|
@ -1,94 +0,0 @@
|
|||
|
||||
package net.sourceforge.filebot.ui.rename;
|
||||
|
||||
|
||||
import javax.swing.event.DocumentEvent;
|
||||
import javax.swing.text.AttributeSet;
|
||||
import javax.swing.text.BadLocationException;
|
||||
import javax.swing.text.Document;
|
||||
import javax.swing.text.PlainDocument;
|
||||
|
||||
|
||||
class ExpressionFormatDocument extends PlainDocument {
|
||||
|
||||
private Completion lastCompletion;
|
||||
|
||||
|
||||
@Override
|
||||
public void insertString(int offset, String text, AttributeSet attributes) throws BadLocationException {
|
||||
if (text == null || text.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// ignore user input that matches the last auto-completion
|
||||
if (lastCompletion != null && lastCompletion.didComplete(this, offset, text)) {
|
||||
lastCompletion = null;
|
||||
|
||||
// behave as if something was inserted (e.g. update caret position)
|
||||
fireInsertUpdate(new DefaultDocumentEvent(offset, text.length(), DocumentEvent.EventType.INSERT));
|
||||
return;
|
||||
}
|
||||
|
||||
// try to auto-complete input
|
||||
lastCompletion = Completion.getCompletion(this, offset, text);
|
||||
|
||||
if (lastCompletion != null) {
|
||||
text = lastCompletion.complete(this, offset, text);
|
||||
}
|
||||
|
||||
super.insertString(offset, text, attributes);
|
||||
}
|
||||
|
||||
|
||||
public Completion getLastCompletion() {
|
||||
return lastCompletion;
|
||||
}
|
||||
|
||||
|
||||
public enum Completion {
|
||||
RoundBrackets("()"),
|
||||
SquareBrackets("[]"),
|
||||
CurlyBrackets("{}"),
|
||||
SingleQuoteStringLiteral("''"),
|
||||
DoubleQuoteStringLiteral("\"\"");
|
||||
|
||||
public final String pattern;
|
||||
|
||||
|
||||
private Completion(String pattern) {
|
||||
this.pattern = pattern;
|
||||
}
|
||||
|
||||
|
||||
public boolean canComplete(Document document, int offset, String input) {
|
||||
return pattern.startsWith(input);
|
||||
}
|
||||
|
||||
|
||||
public boolean didComplete(Document document, int offset, String input) {
|
||||
try {
|
||||
return document.getText(0, offset).concat(input).endsWith(pattern);
|
||||
} catch (BadLocationException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public String complete(Document document, int offset, String input) {
|
||||
return pattern;
|
||||
}
|
||||
|
||||
|
||||
public static Completion getCompletion(Document document, int offset, String input) {
|
||||
for (Completion completion : values()) {
|
||||
if (completion.canComplete(document, offset, input)) {
|
||||
return completion;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,7 +1,5 @@
|
|||
|
||||
package net.sourceforge.filebot.ui.rename;
|
||||
|
||||
|
||||
import static java.awt.Font.*;
|
||||
import static javax.swing.BorderFactory.*;
|
||||
import static net.sourceforge.filebot.ui.NotificationLogging.*;
|
||||
|
@ -52,9 +50,13 @@ import javax.swing.JTextField;
|
|||
import javax.swing.KeyStroke;
|
||||
import javax.swing.SwingWorker;
|
||||
import javax.swing.Timer;
|
||||
import javax.swing.border.CompoundBorder;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
import javax.swing.event.DocumentEvent;
|
||||
import javax.swing.event.PopupMenuEvent;
|
||||
import javax.swing.event.PopupMenuListener;
|
||||
import javax.swing.text.AttributeSet;
|
||||
import javax.swing.text.BadLocationException;
|
||||
import javax.swing.text.JTextComponent;
|
||||
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
|
@ -78,232 +80,226 @@ import net.sourceforge.tuned.ui.TunedUtilities;
|
|||
import net.sourceforge.tuned.ui.notification.SeparatorBorder;
|
||||
import net.sourceforge.tuned.ui.notification.SeparatorBorder.Position;
|
||||
|
||||
import org.fife.ui.rsyntaxtextarea.RSyntaxDocument;
|
||||
import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
|
||||
import org.fife.ui.rsyntaxtextarea.SyntaxConstants;
|
||||
|
||||
import com.cedarsoftware.util.io.JsonReader;
|
||||
import com.cedarsoftware.util.io.JsonWriter;
|
||||
|
||||
public class FormatDialog extends JDialog {
|
||||
|
||||
class FormatDialog extends JDialog {
|
||||
|
||||
private boolean submit = false;
|
||||
|
||||
|
||||
private Mode mode;
|
||||
private ExpressionFormat format;
|
||||
|
||||
|
||||
private MediaBindingBean sample;
|
||||
private ExecutorService executor = createExecutor();
|
||||
private RunnableFuture<String> currentPreviewFuture;
|
||||
|
||||
|
||||
private JLabel preview = new JLabel();
|
||||
private JLabel status = new JLabel();
|
||||
|
||||
|
||||
private JTextComponent editor = createEditor();
|
||||
private ProgressIndicator progressIndicator = new ProgressIndicator();
|
||||
|
||||
|
||||
private JLabel title = new JLabel();
|
||||
private JPanel help = new JPanel(new MigLayout("insets 0, nogrid, fillx"));
|
||||
|
||||
|
||||
private static final PreferencesEntry<String> persistentSampleFile = Settings.forPackage(FormatDialog.class).entry("format.sample.file");
|
||||
|
||||
|
||||
|
||||
public enum Mode {
|
||||
Episode, Movie, Music;
|
||||
|
||||
|
||||
public Mode next() {
|
||||
if (ordinal() < values().length - 1)
|
||||
return values()[ordinal() + 1];
|
||||
|
||||
|
||||
return values()[0];
|
||||
}
|
||||
|
||||
|
||||
|
||||
public String key() {
|
||||
return this.name().toLowerCase();
|
||||
}
|
||||
|
||||
|
||||
|
||||
public Format getFormat() {
|
||||
switch (this) {
|
||||
case Episode:
|
||||
return new EpisodeFormat(true, true);
|
||||
case Movie: // case Movie
|
||||
return new MovieFormat(true, true, false);
|
||||
default:
|
||||
return new AudioTrackFormat();
|
||||
case Episode:
|
||||
return new EpisodeFormat(true, true);
|
||||
case Movie: // case Movie
|
||||
return new MovieFormat(true, true, false);
|
||||
default:
|
||||
return new AudioTrackFormat();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public PreferencesEntry<String> persistentSample() {
|
||||
return Settings.forPackage(FormatDialog.class).entry("format.sample." + key());
|
||||
}
|
||||
|
||||
|
||||
|
||||
public PreferencesList<String> persistentFormatHistory() {
|
||||
return Settings.forPackage(FormatDialog.class).node("format.recent." + key()).asList();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public FormatDialog(Window owner) {
|
||||
super(owner, ModalityType.DOCUMENT_MODAL);
|
||||
|
||||
|
||||
// initialize hidden
|
||||
progressIndicator.setVisible(false);
|
||||
|
||||
|
||||
// bold title label in header
|
||||
title.setFont(title.getFont().deriveFont(BOLD));
|
||||
|
||||
|
||||
JPanel header = new JPanel(new MigLayout("insets dialog, nogrid"));
|
||||
|
||||
|
||||
header.setBackground(Color.white);
|
||||
header.setBorder(new SeparatorBorder(1, new Color(0xB4B4B4), new Color(0xACACAC), GradientStyle.LEFT_TO_RIGHT, Position.BOTTOM));
|
||||
|
||||
|
||||
header.add(progressIndicator, "pos 1al 0al, hidemode 3");
|
||||
header.add(title, "wrap unrel:push");
|
||||
header.add(preview, "hmin 16px, gap indent, hidemode 3, wmax 90%");
|
||||
header.add(status, "hmin 16px, gap indent, hidemode 3, wmax 90%, newline");
|
||||
|
||||
|
||||
JPanel content = new JPanel(new MigLayout("insets dialog, nogrid, fill"));
|
||||
|
||||
|
||||
content.add(editor, "w 120px:min(pref, 420px), h 40px!, growx, wrap 4px, id editor");
|
||||
content.add(createImageButton(changeSampleAction), "w 25!, h 19!, pos n editor.y2+1 editor.x2 n");
|
||||
|
||||
|
||||
content.add(help, "growx, wrap 25px:push");
|
||||
|
||||
|
||||
content.add(new JButton(switchEditModeAction), "tag left");
|
||||
content.add(new JButton(approveFormatAction), "tag apply");
|
||||
content.add(new JButton(cancelAction), "tag cancel");
|
||||
|
||||
|
||||
JComponent pane = (JComponent) getContentPane();
|
||||
pane.setLayout(new MigLayout("insets 0, fill"));
|
||||
|
||||
|
||||
pane.add(header, "h 60px, growx, dock north");
|
||||
pane.add(content, "grow");
|
||||
|
||||
|
||||
addPropertyChangeListener("sample", new PropertyChangeListener() {
|
||||
|
||||
|
||||
@Override
|
||||
public void propertyChange(PropertyChangeEvent evt) {
|
||||
checkFormatInBackground();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// focus editor by default
|
||||
addWindowFocusListener(new WindowAdapter() {
|
||||
|
||||
|
||||
@Override
|
||||
public void windowGainedFocus(WindowEvent e) {
|
||||
editor.requestFocusInWindow();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// finish dialog and close window manually
|
||||
addWindowListener(new WindowAdapter() {
|
||||
|
||||
|
||||
@Override
|
||||
public void windowClosing(WindowEvent e) {
|
||||
finish(false);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// install editor suggestions popup
|
||||
editor.setComponentPopupMenu(createRecentFormatPopup());
|
||||
TunedUtilities.installAction(editor, KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0), new AbstractAction("Recent") {
|
||||
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent evt) {
|
||||
// display popup below format editor
|
||||
editor.getComponentPopupMenu().show(editor, 0, editor.getHeight() + 3);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// episode mode by default
|
||||
setMode(Mode.Episode);
|
||||
|
||||
|
||||
// initialize window properties
|
||||
setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
|
||||
setSize(610, 430);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void setMode(Mode mode) {
|
||||
this.mode = mode;
|
||||
|
||||
|
||||
this.setTitle(String.format("%s Format", mode));
|
||||
title.setText(this.getTitle());
|
||||
status.setVisible(false);
|
||||
|
||||
|
||||
switchEditModeAction.putValue(Action.NAME, String.format("Switch to %s Format", mode.next()));
|
||||
updateHelpPanel(mode);
|
||||
|
||||
|
||||
// update preview to current format
|
||||
sample = restoreSample(mode);
|
||||
|
||||
|
||||
// restore editor state
|
||||
editor.setText(mode.persistentFormatHistory().isEmpty() ? "" : mode.persistentFormatHistory().get(0));
|
||||
|
||||
|
||||
// update examples
|
||||
fireSampleChanged();
|
||||
}
|
||||
|
||||
|
||||
|
||||
private JComponent updateHelpPanel(Mode mode) {
|
||||
help.removeAll();
|
||||
|
||||
|
||||
help.add(new JLabel("Syntax"), "gap indent+unrel, wrap 0");
|
||||
help.add(createSyntaxPanel(mode), "gapx indent indent, wrap 8px");
|
||||
|
||||
|
||||
help.add(new JLabel("Examples"), "gap indent+unrel, wrap 0");
|
||||
help.add(createExamplesPanel(mode), "growx, h pref!, gapx indent indent");
|
||||
|
||||
|
||||
return help;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private JTextComponent createEditor() {
|
||||
final JTextComponent editor = new JTextField(new ExpressionFormatDocument(), null, 0);
|
||||
final RSyntaxTextArea editor = new RSyntaxTextArea(new RSyntaxDocument(SyntaxConstants.SYNTAX_STYLE_GROOVY) {
|
||||
@Override
|
||||
public void insertString(int offs, String str, AttributeSet a) throws BadLocationException {
|
||||
super.insertString(offs, str.replaceAll("\\s", " "), a); // FORCE SINGLE LINE
|
||||
}
|
||||
}, null, 1, 80);
|
||||
|
||||
editor.setAntiAliasingEnabled(true);
|
||||
editor.setAnimateBracketMatching(false);
|
||||
editor.setAutoIndentEnabled(false);
|
||||
editor.setClearWhitespaceLinesEnabled(false);
|
||||
editor.setBracketMatchingEnabled(true);
|
||||
editor.setCloseCurlyBraces(false);
|
||||
editor.setCodeFoldingEnabled(false);
|
||||
editor.setHyperlinksEnabled(false);
|
||||
editor.setUseFocusableTips(false);
|
||||
editor.setHighlightCurrentLine(false);
|
||||
editor.setLineWrap(false);
|
||||
|
||||
editor.setBorder(new CompoundBorder(new JTextField().getBorder(), new EmptyBorder(7, 2, 7, 2)));
|
||||
editor.setFont(new Font(MONOSPACED, PLAIN, 14));
|
||||
|
||||
// enable undo/redo
|
||||
installUndoSupport(editor);
|
||||
|
||||
|
||||
// update format on change
|
||||
editor.getDocument().addDocumentListener(new LazyDocumentListener() {
|
||||
|
||||
|
||||
@Override
|
||||
public void update(DocumentEvent e) {
|
||||
checkFormatInBackground();
|
||||
}
|
||||
});
|
||||
|
||||
// improved cursor behaviour, use delayed listener, so we apply our cursor updates, after the text component is finished with its own
|
||||
editor.getDocument().addDocumentListener(new LazyDocumentListener(0) {
|
||||
|
||||
@Override
|
||||
public void update(DocumentEvent evt) {
|
||||
if (evt.getType() == DocumentEvent.EventType.INSERT) {
|
||||
ExpressionFormatDocument document = (ExpressionFormatDocument) evt.getDocument();
|
||||
|
||||
if (document.getLastCompletion() != null) {
|
||||
editor.setCaretPosition(editor.getCaretPosition() - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
return editor;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private JComponent createSyntaxPanel(Mode mode) {
|
||||
JPanel panel = new JPanel(new MigLayout("fill, nogrid"));
|
||||
|
||||
|
||||
panel.setBorder(createLineBorder(new Color(0xACA899)));
|
||||
panel.setBackground(new Color(0xFFFFE1));
|
||||
panel.setOpaque(true);
|
||||
|
||||
|
||||
panel.add(new LinkButton(new AbstractAction(ResourceBundle.getBundle(FormatDialog.class.getName()).getString(mode.key() + ".syntax")) {
|
||||
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent evt) {
|
||||
try {
|
||||
|
@ -313,53 +309,51 @@ class FormatDialog extends JDialog {
|
|||
}
|
||||
}
|
||||
}));
|
||||
|
||||
|
||||
return panel;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private JComponent createExamplesPanel(Mode mode) {
|
||||
JPanel panel = new JPanel(new MigLayout("fill, wrap 3"));
|
||||
|
||||
|
||||
panel.setBorder(createLineBorder(new Color(0xACA899)));
|
||||
panel.setBackground(new Color(0xFFFFE1));
|
||||
|
||||
|
||||
ResourceBundle bundle = ResourceBundle.getBundle(getClass().getName());
|
||||
TreeMap<String, String> examples = new TreeMap<String, String>();
|
||||
|
||||
|
||||
// extract all example entries and sort by key
|
||||
for (String key : bundle.keySet()) {
|
||||
if (key.startsWith(mode.key() + ".example"))
|
||||
examples.put(key, bundle.getString(key));
|
||||
}
|
||||
|
||||
|
||||
for (final String format : examples.values()) {
|
||||
LinkButton formatLink = new LinkButton(new AbstractAction(format) {
|
||||
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
editor.setText(format);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
formatLink.setFont(new Font(MONOSPACED, PLAIN, 11));
|
||||
|
||||
|
||||
// compute format label in background
|
||||
final JLabel formatExample = new JLabel("[evaluate]");
|
||||
|
||||
|
||||
// bind text to preview
|
||||
addPropertyChangeListener("sample", new PropertyChangeListener() {
|
||||
|
||||
|
||||
@Override
|
||||
public void propertyChange(PropertyChangeEvent evt) {
|
||||
new SwingWorker<String, Void>() {
|
||||
|
||||
|
||||
@Override
|
||||
protected String doInBackground() throws Exception {
|
||||
return new ExpressionFormat(format).format(sample);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
protected void done() {
|
||||
try {
|
||||
|
@ -371,20 +365,19 @@ class FormatDialog extends JDialog {
|
|||
}.execute();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
panel.add(formatLink);
|
||||
panel.add(new JLabel("…"));
|
||||
panel.add(formatExample);
|
||||
}
|
||||
|
||||
|
||||
return panel;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private MediaBindingBean restoreSample(Mode mode) {
|
||||
Object info = null;
|
||||
File media = null;
|
||||
|
||||
|
||||
try {
|
||||
// restore sample from user preferences
|
||||
String sample = mode.persistentSample().getValue();
|
||||
|
@ -402,93 +395,90 @@ class FormatDialog extends JDialog {
|
|||
throw new RuntimeException(illegalSample); // won't happen
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// restore media file
|
||||
String path = persistentSampleFile.getValue();
|
||||
|
||||
|
||||
if (path != null && !path.isEmpty()) {
|
||||
media = new File(path);
|
||||
}
|
||||
|
||||
|
||||
return new MediaBindingBean(info, media, null);
|
||||
}
|
||||
|
||||
|
||||
|
||||
private ExecutorService createExecutor() {
|
||||
ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(1), new DefaultThreadFactory("PreviewFormatter")) {
|
||||
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public List<Runnable> shutdownNow() {
|
||||
List<Runnable> remaining = super.shutdownNow();
|
||||
|
||||
|
||||
try {
|
||||
if (!awaitTermination(3, TimeUnit.SECONDS)) {
|
||||
// if the thread has not terminated after 4 seconds, it is probably stuck
|
||||
ThreadGroup threadGroup = ((DefaultThreadFactory) getThreadFactory()).getThreadGroup();
|
||||
|
||||
|
||||
// kill background thread by force
|
||||
threadGroup.stop();
|
||||
|
||||
|
||||
// log access of potentially unsafe method
|
||||
Logger.getLogger(getClass().getName()).warning("Thread was forcibly terminated");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Logger.getLogger(getClass().getName()).log(Level.WARNING, "Thread was not terminated", e);
|
||||
}
|
||||
|
||||
|
||||
return remaining;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// only keep the latest task in the queue
|
||||
executor.setRejectedExecutionHandler(new DiscardOldestPolicy());
|
||||
|
||||
|
||||
return executor;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void checkFormatInBackground() {
|
||||
try {
|
||||
// check syntax in foreground
|
||||
final ExpressionFormat format = new ExpressionFormat(editor.getText().trim());
|
||||
|
||||
|
||||
// activate delayed to avoid flickering when formatting takes only a couple of milliseconds
|
||||
final Timer progressIndicatorTimer = TunedUtilities.invokeLater(400, new Runnable() {
|
||||
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
progressIndicator.setVisible(true);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// cancel old worker later
|
||||
Future<String> obsoletePreviewFuture = currentPreviewFuture;
|
||||
|
||||
|
||||
// create new worker
|
||||
currentPreviewFuture = new SwingWorker<String, Void>() {
|
||||
|
||||
|
||||
@Override
|
||||
protected String doInBackground() throws Exception {
|
||||
return format.format(sample);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
protected void done() {
|
||||
try {
|
||||
preview.setText(get());
|
||||
|
||||
|
||||
// check internal script exception
|
||||
if (format.caughtScriptException() != null) {
|
||||
throw format.caughtScriptException();
|
||||
}
|
||||
|
||||
|
||||
// check empty output
|
||||
if (get().trim().isEmpty()) {
|
||||
throw new RuntimeException("Formatted value is empty");
|
||||
}
|
||||
|
||||
|
||||
// no warning or error
|
||||
status.setVisible(false);
|
||||
} catch (CancellationException e) {
|
||||
|
@ -501,10 +491,10 @@ class FormatDialog extends JDialog {
|
|||
} finally {
|
||||
preview.setVisible(preview.getText().trim().length() > 0);
|
||||
editor.setForeground(preview.getForeground());
|
||||
|
||||
|
||||
// stop progress indicator from becoming visible, if we have been fast enough
|
||||
progressIndicatorTimer.stop();
|
||||
|
||||
|
||||
// hide progress indicator, if this still is the current worker
|
||||
if (this == currentPreviewFuture) {
|
||||
progressIndicator.setVisible(false);
|
||||
|
@ -512,83 +502,76 @@ class FormatDialog extends JDialog {
|
|||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// cancel old worker, after new worker has been created, because done() might be called from within cancel()
|
||||
if (obsoletePreviewFuture != null) {
|
||||
obsoletePreviewFuture.cancel(true);
|
||||
}
|
||||
|
||||
|
||||
// submit new worker
|
||||
executor.execute(currentPreviewFuture);
|
||||
} catch (ScriptException e) {
|
||||
// incorrect syntax
|
||||
// incorrect syntax
|
||||
status.setText(ExceptionUtilities.getRootCauseMessage(e));
|
||||
status.setIcon(ResourceManager.getIcon("status.error"));
|
||||
status.setVisible(true);
|
||||
|
||||
|
||||
preview.setVisible(false);
|
||||
editor.setForeground(Color.red);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public boolean submit() {
|
||||
return submit;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public Mode getMode() {
|
||||
return mode;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public ExpressionFormat getFormat() {
|
||||
return format;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void finish(boolean submit) {
|
||||
this.submit = submit;
|
||||
|
||||
|
||||
// force shutdown
|
||||
executor.shutdownNow();
|
||||
|
||||
|
||||
setVisible(false);
|
||||
dispose();
|
||||
}
|
||||
|
||||
|
||||
|
||||
private JPopupMenu createRecentFormatPopup() {
|
||||
JPopupMenu popup = new JPopupMenu();
|
||||
popup.addPopupMenuListener(new PopupMenuListener() {
|
||||
|
||||
|
||||
@Override
|
||||
public void popupMenuWillBecomeVisible(PopupMenuEvent evt) {
|
||||
// make sure to reset state
|
||||
popupMenuWillBecomeInvisible(evt);
|
||||
|
||||
|
||||
JPopupMenu popup = (JPopupMenu) evt.getSource();
|
||||
for (final String expression : mode.persistentFormatHistory()) {
|
||||
JMenuItem item = popup.add(new AbstractAction(expression) {
|
||||
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent evt) {
|
||||
editor.setText(expression);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
item.setFont(new Font(MONOSPACED, PLAIN, 11));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void popupMenuWillBecomeInvisible(PopupMenuEvent evt) {
|
||||
JPopupMenu popup = (JPopupMenu) evt.getSource();
|
||||
popup.removeAll();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void popupMenuCanceled(PopupMenuEvent evt) {
|
||||
popupMenuWillBecomeInvisible(evt);
|
||||
|
@ -596,93 +579,92 @@ class FormatDialog extends JDialog {
|
|||
});
|
||||
return popup;
|
||||
}
|
||||
|
||||
|
||||
protected final Action changeSampleAction = new AbstractAction("Change Sample", ResourceManager.getIcon("action.variable")) {
|
||||
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent evt) {
|
||||
BindingDialog dialog = new BindingDialog(getWindow(evt.getSource()), String.format("%s Bindings", mode), mode.getFormat());
|
||||
|
||||
|
||||
dialog.setInfoObject(sample.getInfoObject());
|
||||
dialog.setMediaFile(sample.getMediaFile());
|
||||
|
||||
|
||||
// open dialog
|
||||
dialog.setLocationRelativeTo((Component) evt.getSource());
|
||||
dialog.setVisible(true);
|
||||
|
||||
|
||||
if (dialog.submit()) {
|
||||
Object info = dialog.getInfoObject();
|
||||
File file = dialog.getMediaFile();
|
||||
|
||||
|
||||
// change sample
|
||||
sample = new MediaBindingBean(info, file, null);
|
||||
|
||||
|
||||
// remember
|
||||
mode.persistentSample().setValue(info == null ? "" : JsonWriter.toJson(info));
|
||||
persistentSampleFile.setValue(file == null ? "" : sample.getMediaFile().getAbsolutePath());
|
||||
|
||||
|
||||
// reevaluate everything
|
||||
fireSampleChanged();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
protected final Action cancelAction = new AbstractAction("Cancel", ResourceManager.getIcon("dialog.cancel")) {
|
||||
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
finish(false);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
protected final Action switchEditModeAction = new AbstractAction(null, ResourceManager.getIcon("dialog.switch")) {
|
||||
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
setMode(mode.next());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
protected final Action approveFormatAction = new AbstractAction("Use Format", ResourceManager.getIcon("dialog.continue")) {
|
||||
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent evt) {
|
||||
try {
|
||||
// check syntax
|
||||
format = new ExpressionFormat(editor.getText().trim());
|
||||
|
||||
|
||||
if (format.getExpression().isEmpty()) {
|
||||
throw new ScriptException("Expression is empty");
|
||||
}
|
||||
|
||||
|
||||
// create new recent history and ignore duplicates
|
||||
Set<String> recent = new LinkedHashSet<String>();
|
||||
|
||||
|
||||
// add new format first
|
||||
recent.add(format.getExpression());
|
||||
|
||||
|
||||
// save the 8 most recent formats
|
||||
for (String expression : mode.persistentFormatHistory()) {
|
||||
recent.add(expression);
|
||||
|
||||
|
||||
if (recent.size() >= 8) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// update persistent history
|
||||
mode.persistentFormatHistory().set(recent);
|
||||
|
||||
|
||||
finish(true);
|
||||
} catch (ScriptException e) {
|
||||
UILogger.log(Level.WARNING, ExceptionUtilities.getRootCauseMessage(e));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
protected void fireSampleChanged() {
|
||||
firePropertyChange("sample", null, sample);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue