package de.uni_passau.fim.infosun.prophet.plugin.plugins.codeViewerPlugin.codeViewerPlugins;
import java.io.File;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import javax.swing.event.DocumentListener;
import javax.swing.text.Document;
import de.uni_passau.fim.infosun.prophet.plugin.plugins.codeViewerPlugin.CodeViewer;
import de.uni_passau.fim.infosun.prophet.plugin.plugins.codeViewerPlugin.Plugin;
import de.uni_passau.fim.infosun.prophet.plugin.plugins.codeViewerPlugin.tabbedPane.EditorPanel;
import de.uni_passau.fim.infosun.prophet.util.qTree.Attribute;
import de.uni_passau.fim.infosun.prophet.util.settings.Setting;
import de.uni_passau.fim.infosun.prophet.util.settings.components.CheckBoxSetting;
import org.fife.ui.rsyntaxtextarea.RSyntaxDocument;
import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
import org.fife.ui.rsyntaxtextarea.SyntaxConstants;
import static de.uni_passau.fim.infosun.prophet.util.language.UIElementNames.getLocalized;
/**
* A <code>Plugin</code> that will activate syntax highlighting appropriate for the file type that is opened in an
* <code>EditorPanel</code>.
*/
public class SyntaxHighlightingPlugin implements Plugin {
private static final String KEY = "syntaxhighlighting";
private static final Map<String, String> extensionMap;
static {
Map<String, String> values = new HashMap<>();
values.put("makefile", SyntaxConstants.SYNTAX_STYLE_MAKEFILE);
values.put(".asm", SyntaxConstants.SYNTAX_STYLE_ASSEMBLER_X86);
values.put(".bat", SyntaxConstants.SYNTAX_STYLE_WINDOWS_BATCH);
values.put(".c", SyntaxConstants.SYNTAX_STYLE_C);
values.put(".cpp", SyntaxConstants.SYNTAX_STYLE_CPLUSPLUS);
values.put(".cs", SyntaxConstants.SYNTAX_STYLE_CSHARP);
values.put(".css", SyntaxConstants.SYNTAX_STYLE_CSS);
values.put(".dfm", SyntaxConstants.SYNTAX_STYLE_DELPHI);
values.put(".dpr", SyntaxConstants.SYNTAX_STYLE_DELPHI);
values.put(".h", SyntaxConstants.SYNTAX_STYLE_C);
values.put(".htm", SyntaxConstants.SYNTAX_STYLE_HTML);
values.put(".html", SyntaxConstants.SYNTAX_STYLE_HTML);
values.put(".java", SyntaxConstants.SYNTAX_STYLE_JAVA);
values.put(".js", SyntaxConstants.SYNTAX_STYLE_JAVASCRIPT);
values.put(".pas", SyntaxConstants.SYNTAX_STYLE_DELPHI);
values.put(".php", SyntaxConstants.SYNTAX_STYLE_PHP);
values.put(".py", SyntaxConstants.SYNTAX_STYLE_PYTHON);
values.put(".rb", SyntaxConstants.SYNTAX_STYLE_RUBY);
values.put(".sql", SyntaxConstants.SYNTAX_STYLE_SQL);
values.put(".xml", SyntaxConstants.SYNTAX_STYLE_XML);
extensionMap = Collections.unmodifiableMap(values);
}
@Override
public Setting getSetting(Attribute mainAttribute) {
Attribute attribute = mainAttribute.getSubAttribute(KEY);
Setting setting = new CheckBoxSetting(attribute, getClass().getSimpleName());
setting.setCaption(getLocalized("SYNTAX_HIGHLIGHTING_ENABLE"));
return setting;
}
@Override
public void onCreate(CodeViewer viewer) {
}
@Override
public void onEditorPanelCreate(CodeViewer codeViewer, EditorPanel editorPanel) {
Attribute attr = codeViewer.getAttribute();
boolean enabled = attr.containsSubAttribute(KEY) && Boolean.parseBoolean(attr.getSubAttribute(KEY).getValue());
if (!enabled) {
return;
}
String fileExtension = getExtension(editorPanel.getFile());
String mimeType = extensionMap.getOrDefault(fileExtension, SyntaxConstants.SYNTAX_STYLE_NONE);
RSyntaxTextArea textArea = editorPanel.getTextArea();
Document doc = textArea.getDocument();
DocumentListener[] listeners = removeListeners((RSyntaxDocument) doc);
textArea.setSyntaxEditingStyle(mimeType);
addListeners((RSyntaxDocument) doc, listeners);
}
@Override
public void onEditorPanelClose(CodeViewer codeViewer, EditorPanel editorPanel) {
}
@Override
public void onClose(CodeViewer codeViewer) {
}
/**
* Returns the file extension (including the '.') of the <code>File</code>. If the filename does not contain a dot
* the whole name will be returned.
*
* @param file
* the <code>File</code> whose extension is to be returned
*
* @return the extension or the whole filename
*/
private String getExtension(File file) {
String name = file.getName().toLowerCase();
int index = name.lastIndexOf('.');
return index == -1 ? name : name.substring(index);
}
/**
* Removes all <code>DocumentListener</code>s from the given <code>RSyntaxDocument</code> and returns them.
*
* @param doc
* the <code>RSyntaxDocument</code> to remove listeners from
*
* @return the removed listeners
*/
private DocumentListener[] removeListeners(RSyntaxDocument doc) {
DocumentListener[] listeners = doc.getDocumentListeners();
for (DocumentListener listener : listeners) {
doc.removeDocumentListener(listener);
}
return listeners;
}
/**
* Adds all given <code>DocumentListener</code>s to the <code>RSyntaxDocument</code>.
*
* @param doc
* the <code>RSyntaxDocument</code> to add the <code>DocumentListener</code>s to
* @param listeners
* the <code>DocumentListener</code>s to add
*/
private void addListeners(RSyntaxDocument doc, DocumentListener[] listeners) {
for (DocumentListener listener : listeners) {
doc.addDocumentListener(listener);
}
}
}