/*******************************************************************************
* This file is part of logisim-evolution.
*
* logisim-evolution 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.
*
* logisim-evolution 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 logisim-evolution. If not, see <http://www.gnu.org/licenses/>.
*
* Original code by Carl Burch (http://www.cburch.com), 2011.
* Subsequent modifications by :
* + Haute École Spécialisée Bernoise
* http://www.bfh.ch
* + Haute École du paysage, d'ingénierie et d'architecture de Genève
* http://hepia.hesge.ch/
* + Haute École d'Ingénierie et de Gestion du Canton de Vaud
* http://www.heig-vd.ch/
* The project is currently maintained by :
* + REDS Institute - HEIG-VD
* Yverdon-les-Bains, Switzerland
* http://reds.heig-vd.ch
*******************************************************************************/
package com.cburch.logisim.std.hdl;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dialog;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.io.IOException;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
import org.fife.ui.rsyntaxtextarea.SyntaxConstants;
import org.fife.ui.rtextarea.RTextScrollPane;
import com.cburch.hdl.HdlFile;
import com.cburch.hdl.HdlModel;
import com.cburch.hdl.HdlModelListener;
import com.cburch.logisim.proj.Project;
import com.cburch.logisim.util.FileUtil;
import com.cburch.logisim.util.JFileChoosers;
import com.cburch.logisim.util.JInputDialog;
import com.cburch.logisim.util.LocaleListener;
import com.cburch.logisim.util.LocaleManager;
public class HdlContentEditor extends JDialog implements JInputDialog {
private class EditorListener implements DocumentListener {
@Override
public void changedUpdate(DocumentEvent de) {
}
@Override
public void insertUpdate(DocumentEvent de) {
validate.setEnabled(!editor.getText().equals(model.getContent()));
}
@Override
public void removeUpdate(DocumentEvent de) {
validate.setEnabled(!editor.getText().equals(model.getContent()));
}
}
private class FrameListener extends WindowAdapter implements
ActionListener, LocaleListener {
@Override
public void actionPerformed(ActionEvent event) {
Object source = event.getSource();
if (source == open) {
if (!editor.getText().equals(model.getContent()))
if (!confirmImport(HdlContentEditor.this))
return;
JFileChooser chooser = JFileChoosers
.createAt(getDefaultImportFile(null));
chooser.setDialogTitle(Strings.get("openButton"));
int choice = chooser.showOpenDialog(HdlContentEditor.this);
if (choice == JFileChooser.APPROVE_OPTION) {
File f = chooser.getSelectedFile();
try {
HdlFile.open(f, HdlContentEditor.this);
} catch (IOException e) {
JOptionPane.showMessageDialog(HdlContentEditor.this,
e.getMessage(),
Strings.get("hexOpenErrorTitle"),
JOptionPane.ERROR_MESSAGE);
}
}
}
if (source == save) {
JFileChooser chooser = JFileChoosers
.createSelected(getDefaultExportFile(null));
chooser.setDialogTitle(Strings.get("saveButton"));
int choice = chooser.showSaveDialog(HdlContentEditor.this);
if (choice == JFileChooser.APPROVE_OPTION) {
File f = chooser.getSelectedFile();
try {
HdlFile.save(f, HdlContentEditor.this);
} catch (IOException e) {
JOptionPane.showMessageDialog(HdlContentEditor.this,
e.getMessage(),
Strings.get("hexSaveErrorTitle"),
JOptionPane.ERROR_MESSAGE);
}
}
}
if (source == validate) {
model.setContent(editor.getText());
}
if (source == close) {
close();
}
}
@Override
public void localeChanged() {
setTitle(Strings.get("hdlFrameTitle"));
open.setText(Strings.get("openButton"));
save.setText(Strings.get("saveButton"));
validate.setText(Strings.get("validateButton"));
close.setText(Strings.get("closeButton"));
}
@Override
public void windowClosing(WindowEvent e) {
close();
}
}
private class ModelListener implements HdlModelListener {
@Override
public void contentSet(HdlModel source) {
validate.setEnabled(false);
}
}
public static boolean confirmImport(Component parent) {
String[] options = { Strings.get("importOption"),
Strings.get("cancelOption") };
return JOptionPane.showOptionDialog(parent,
Strings.get("importMessage"), Strings.get("importTitle"), 0,
JOptionPane.QUESTION_MESSAGE, null, options, options[0]) == 0;
}
private static final long serialVersionUID = 1L;
private static final int ROWS = 40;
private static final int COLUMNS = 100;
private static final String EXPORT_DIR = "hdl_export";
private FrameListener frameListener = new FrameListener();
private ModelListener modelListener = new ModelListener();
private EditorListener editorListener = new EditorListener();
private RSyntaxTextArea editor;
private HdlModel model;
private Project project;
private JButton open = new JButton();
private JButton save = new JButton();
private JButton validate = new JButton();
private JButton close = new JButton();
public HdlContentEditor(Dialog parent, Project proj, HdlModel model) {
super(parent, Strings.get("hdlFrameTitle"), true);
configure(proj, model);
}
public HdlContentEditor(Frame parent, Project proj, HdlModel model) {
super(parent, Strings.get("hdlFrameTitle"), true);
configure(proj, model);
}
private void close() {
if (editor.getText().equals(model.getContent())) {
dispose();
return;
}
if (model.setContent(editor.getText())) {
dispose();
return;
}
Object[] options = { Strings.get("confirmCloseYes"),
Strings.get("confirmCloseNo"),
Strings.get("confirmCloseBackup") };
int n = JOptionPane.showOptionDialog(this,
Strings.get("confirmCloseMessage"),
Strings.get("confirmCloseTitle"),
JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE,
null, options, options[0]);
switch (n) {
case JOptionPane.YES_OPTION:
dispose();
break;
case JOptionPane.CANCEL_OPTION:
save.doClick();
dispose();
break;
}
}
private void configure(Project proj, HdlModel model) {
this.project = proj;
this.model = model;
this.model.addHdlModelListener(modelListener);
this.addWindowListener(frameListener);
JPanel buttonsPanel = new JPanel();
buttonsPanel.add(open);
buttonsPanel.add(save);
buttonsPanel.add(validate);
buttonsPanel.add(close);
open.addActionListener(frameListener);
save.addActionListener(frameListener);
close.addActionListener(frameListener);
validate.addActionListener(frameListener);
editor = new RSyntaxTextArea(ROWS, COLUMNS);
editor.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_DELPHI);
editor.setCodeFoldingEnabled(true);
editor.setAntiAliasingEnabled(true);
editor.getDocument().addDocumentListener(editorListener);
RTextScrollPane sp = new RTextScrollPane(editor);
sp.setFoldIndicatorEnabled(true);
add(sp, BorderLayout.CENTER);
add(buttonsPanel, BorderLayout.SOUTH);
LocaleManager.addLocaleListener(frameListener);
frameListener.localeChanged();
pack();
Dimension size = getSize();
Dimension screen = getToolkit().getScreenSize();
if (size.width > screen.width || size.height > screen.height) {
size.width = Math.min(size.width, screen.width);
size.height = Math.min(size.height, screen.height);
setSize(size);
}
}
private File getDefaultExportFile(File defaultFile) {
File projectFile = project.getLogisimFile().getLoader().getMainFile();
if (projectFile == null) {
if (defaultFile == null)
return new File(model.getName() + ".vhd");
return defaultFile;
}
File compFolder;
try {
compFolder = new File(FileUtil.correctPath(projectFile
.getParentFile().getCanonicalPath()) + EXPORT_DIR);
if (!compFolder.exists()
|| (compFolder.exists() && !compFolder.isDirectory()))
compFolder.mkdir();
return new File(FileUtil.correctPath(compFolder.getCanonicalPath())
+ model.getName() + ".vhd");
} catch (IOException ex) {
return defaultFile;
}
}
private File getDefaultImportFile(File defaultFile) {
File projectFile = project.getLogisimFile().getLoader().getMainFile();
if (projectFile == null)
return defaultFile;
File compFolder;
try {
compFolder = new File(FileUtil.correctPath(projectFile
.getParentFile().getCanonicalPath()) + EXPORT_DIR);
if (!compFolder.exists()
|| (compFolder.exists() && !compFolder.isDirectory()))
compFolder.mkdir();
return new File(FileUtil.correctPath(compFolder.getCanonicalPath()));
} catch (IOException ex) {
return defaultFile;
}
}
public String getText() {
return editor.getText();
}
@Override
public Object getValue() {
return model;
}
public void setText(String content) {
editor.setText(content);
editor.discardAllEdits();
}
@Override
public void setValue(Object value) {
model = (HdlModel) value;
}
@Override
public void setVisible(boolean b) {
if (b) {
editor.setText(model.getContent());
editor.discardAllEdits();
}
super.setVisible(b);
}
}