package com.applang;
import java.awt.Component;
import java.awt.Container;
import java.awt.Image;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.Closeable;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.InputStream;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashSet;
import java.util.Properties;
import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import javax.swing.AbstractButton;
import javax.swing.Action;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.SwingUtilities;
import javax.swing.text.JTextComponent;
import org.gjt.sp.jedit.Buffer;
import org.gjt.sp.jedit.EditAction;
import org.gjt.sp.jedit.EditPane;
import org.gjt.sp.jedit.GUIUtilities;
import org.gjt.sp.jedit.View;
import org.gjt.sp.jedit.jEdit;
import org.gjt.sp.jedit.gui.RolloverButton;
import org.gjt.sp.jedit.io.VFS;
import org.gjt.sp.jedit.io.VFSManager;
import org.gjt.sp.jedit.textarea.TextArea;
import org.gjt.sp.jedit.visitors.JEditVisitorAdapter;
import org.gjt.sp.util.IOUtilities;
import org.gjt.sp.util.Log;
import com.inet.jortho.FileUserDictionary;
import com.inet.jortho.SpellChecker;
import static com.applang.Util.*;
import static com.applang.Util1.*;
import static com.applang.Util2.*;
import static com.applang.SwingUtil.*;
public class PluginUtils {
public static boolean insideJEdit() {
try {
jEdit.getProperty("tip.show");
return true;
} catch (NullPointerException ex) {
return false;
}
}
public static String getSettingsDirectory() {
if (insideJEdit())
return jEdit.getSettingsDirectory();
else
return System.getProperty("jedit.settings.dir");
}
public static Properties loadProperties(String fileName) {
diag_println(DIAG_OFF, ".props : ", fileName);
Properties props = new Properties();
if (notNullOrEmpty(fileName)) {
InputStream in = null;
try {
JarFile jarFile = null;
if (isJarUri(fileName)) {
URL url = new URL(fileName);
url = new URL(url.getFile());
String[] parts = url.getFile().split("!/");
jarFile = new JarFile(new File(parts[0]));
JarEntry jarEntry = jarFile.getJarEntry(parts[1]);
in = jarFile.getInputStream(jarEntry);
}
else {
File file = new File(fileName);
if (file.isFile()) {
in = new FileInputStream(file);
} else {
in = PluginUtils.class.getResourceAsStream(fileName);
}
}
props.load(in);
if (jarFile != null)
jarFile.close();
} catch (Exception e) {
Log.log(Log.ERROR, PluginUtils.class + ".loadProperties", e);
} finally {
IOUtilities.closeQuietly((Closeable) in);
}
}
return props;
}
// NOTE used in scripts
public static String getProperty(String name) {
return getProperty(name, null);
}
public static String getProperty(String name, String defaultValue) {
String prop;
if (insideJEdit())
prop = jEdit.getProperty(name, defaultValue);
else
prop = properties.getProperty(name, defaultValue);
if (nullOrEmpty(prop) && (name.endsWith("_COMMAND") || name.endsWith("_SDK")))
prop = getSetting(name, "");
return prop;
}
public static Properties properties = null;
static {
if (!insideJEdit()) {
String part = System.getProperty("plugin.props");
String fileName = pathCombine(relativePath(), part);
if (!fileExists(fileName)) {
fileName = resourceUrlOf(part, Constraint.END).toString();
}
properties = loadProperties(fileName);
}
messageRedirection();
}
// NOTE used in scripts
public static void setProperty(String name, String value) {
if (insideJEdit())
jEdit.setProperty(name, value);
else
properties.setProperty(name, value);
}
public static void saveSettings() {
if (insideJEdit())
jEdit.saveSettings();
}
public static void setStatusMessage(String msg) {
View view = jEdit.getActiveView();
if (view != null)
view.getStatus().setMessageAndClear(msg);
else
longToast(msg);
}
public static void messageRedirection() {
messRedirection = new Function<String>() {
public String apply(Object... params) {
String message = param("", 0, params);
setStatusMessage(message);
return message;
}
};
}
// NOTE used in scripts
public static void invokeAction(View view, String actionName) {
EditAction action = jEdit.getAction(actionName);
if (action != null)
action.invoke(view);
}
// NOTE used in scripts
public static ImageIcon loadIcon(String path) {
if (path != null && path.endsWith(".icon"))
path = getProperty(path);
if (nullOrEmpty(path))
return null;
try {
if (path.startsWith("/"))
return iconFrom(path);
else if (!insideJEdit()) {
path = pathCombine("/org/gjt/sp/jedit/icons/themes/tango", path);
return iconFrom(path);
}
else
return (ImageIcon) GUIUtilities.loadIcon(path);
} catch (Exception e) {
path = "/org/gjt/sp/jedit/icons/themes/tango/22x22/emblems/emblem-unreadable.png";
return iconFrom(path);
}
}
public static AbstractButton makeCustomButton(String name, ActionListener listener, boolean flip) {
String toolTip = getProperty(name.concat(".label"));
ImageIcon icon = loadIcon(name + ".icon");
if (flip && icon != null) {
Image img = icon.getImage();
BufferedImage bimg = horizontalflip(img);
icon = new ImageIcon(bimg);
}
AbstractButton b = new RolloverButton(icon);
if (listener != null) {
b.addActionListener(listener);
b.setEnabled(true);
} else {
b.setEnabled(false);
}
b.setToolTipText(toolTip);
return b;
}
public static AbstractButton makeCustomButton(CustomAction customAction, boolean flip) {
AbstractButton btn;
CustomActionType type = customAction.getType();
if (type != null) {
btn = makeCustomButton(type.resourceName(), null, flip);
btn.setEnabled(true);
}
else {
btn = new RolloverButton();
String name = customAction.getValue(Action.NAME).toString();
btn.setName(name);
btn.setText(name);
}
btn.setAction(customAction);
return btn;
}
public static void jEditDebugLogging() {
org.gjt.sp.util.Log.init(true,org.gjt.sp.util.Log.DEBUG);
org.gjt.sp.jedit.Debug.TOKEN_MARKER_DEBUG = true;
org.gjt.sp.jedit.Debug.CHUNK_CACHE_DEBUG = true;
}
// NOTE leaves standard-out going to log
public static <T> T suppressJEditErrorLog(Function<T> func, Object...params) {
try {
org.gjt.sp.util.Log.init(true,org.gjt.sp.util.Log.ERROR + 1);
return func.apply(params);
}
finally {
org.gjt.sp.util.Log.init(false,org.gjt.sp.util.Log.WARNING);
}
}
public static void setupSpellChecker(String path) {
if (!fileExists(new File(path, "dictionaries.cnf")))
return;
SpellChecker.setUserDictionaryProvider( new FileUserDictionary(path) );
try {
SpellChecker.registerDictionaries( new URL("file", null, path + "/"), null );
} catch (MalformedURLException e) {
Log.log(Log.ERROR, PluginUtils.class + ".setupSpellChecker", e);
}
}
public static void spellChecking(JTextComponent jtc, boolean register) {
if (register)
SpellChecker.register(jtc);
else
SpellChecker.unregister(jtc);
}
public static final String FEATURE = "feature";
public static String featureFile(String name, String feature, Properties props) {
String path = tempPath() + PATH_SEP + name;
try {
Writer writer = write(new StringWriter(), ":");
writer = write_assoc(writer, FEATURE, feature);
writer = write(writer, ":");
writer = write_assoc(writer, "wrap", "none");
writer = write(writer, ":");
String comment = writer.toString();
FileWriter fileWriter = new FileWriter(path);
props.store(fileWriter, comment);
fileWriter.close();
}
catch (Exception e) {
Log.log(Log.ERROR, PluginUtils.class + ".featureFile", e);
}
return path;
}
public static String getNextFeatureTemp() {
int featureTitledCount = 0;
for (String name : new File(tempPath()).list())
if (name.startsWith(FEATURE))
try {
featureTitledCount = Math.max(
featureTitledCount,
Integer.parseInt(name
.substring(FEATURE.length())));
}
catch(NumberFormatException nf) {}
return FEATURE + "_" + (featureTitledCount + 1);
}
public static Buffer createFeatureBuffer() {
View view = jEdit.getActiveView();
String parent = null;
if (view != null) {
Buffer buffer = view.getBuffer();
parent = buffer.getDirectory();
}
if (parent == null) {
parent = System.getProperty("user.home");
}
VFS vfs = VFSManager.getVFSForPath(parent);
if ((vfs.getCapabilities() & VFS.WRITE_CAP) == 0) {
// cannot write on that VFS, creating untitled buffer in home directory
parent = System.getProperty("user.home");
}
Buffer buffer = jEdit.openTemporary(view, tempPath(), getNextFeatureTemp(),true, null);
jEdit.commitTemporary(buffer);
return buffer;
}
public static void parseBufferLocalProperties(Buffer buffer) {
try {
Class<?> cl = Class.forName("org.gjt.sp.jedit.buffer.JEditBuffer");
Method method = cl.getDeclaredMethod("parseBufferLocalProperties");
method.setAccessible(true);
method.invoke(buffer);
}
catch (Exception e) {
Log.log(Log.ERROR, PluginUtils.class + ".parseBufferLocalProperties", e);
}
}
@SuppressWarnings("unchecked")
public static EditPane[] getEditPanesFor(final Buffer buffer) {
try {
JEditVisitorAdapter visitor = new JEditVisitorAdapter() {
public Set<EditPane> editPanes = new HashSet<EditPane>();
@Override
public void visit(EditPane editPane) {
if (buffer.equals(editPane.getBuffer()))
editPanes.add(editPane);
}
};
jEdit.visit(visitor);
return ((Set<EditPane>) visitor.getClass().getField("editPanes").get(visitor))
.toArray(new EditPane[0]);
}
catch (Exception e) {
return null;
}
}
public static void setEditPane(EditPane editPane) {
View view = editPane.getView();
try {
Class<?> cl = Class.forName("org.gjt.sp.jedit.View");
Method method = cl.getDeclaredMethod("setEditPane", EditPane.class);
method.setAccessible(true);
method.invoke(view, editPane);
}
catch (Exception e) {
Log.log(Log.ERROR, PluginUtils.class + ".setEditPane", e);
}
}
public static class DoubleFeature
{
private JComponent widget = null;
public void setWidget(JComponent widget) {
this.widget = widget;
}
public JComponent getWidget() {
return widget;
}
public DoubleFeature(TextArea textArea) {
setTextArea(textArea);
}
@Override
public String toString() {
Writer writer = write(new StringWriter(), identity(this));
String t = "";
for (int i = 0; i < textAreas.length; i++) {
t += textAreas[i] == null ? "-" : "+";
}
writer = write_assoc(writer, "textAreas", t, 1);
writer = write_assoc(writer, "widget",
functionValueOrElse("null",
new Function<String>() {
public String apply(Object...params) {
return widget.getClass().getSimpleName();
}
}
),
1);
Container container = getFeature().getParent();
if (container instanceof EditPane) {
EditPane editPane = (EditPane)container;
Buffer buffer = editPane.getBuffer();
if (buffer != null)
writer = write_assoc(writer, "buffer", buffer, 1);
}
return writer.toString();
}
protected TextArea[] textAreas = {null,null};
public void setTextArea(TextArea textArea) {
textAreas[0] = textArea;
}
public TextArea getTextArea() {
return textAreas[0];
}
public TextArea getTextArea2() {
return textAreas[1];
}
public Component getFeature() {
return textAreas[0] != null ? textAreas[0] : widget;
}
public void addFeatureTo(Container container) {
addCenterComponent(getFeature(), container);
container.validate();
container.repaint();
}
protected boolean isolate(Object...params) {
Component target = getFeature();
Container container = target.getParent();
if (container == null) {
Log.log(Log.ERROR, getClass().getName() + ".isolate", String.format("%s cannot be isolated", identity(target)));
return false;
}
container.remove(target);
if (params.length > 0)
params[0] = container;
return true;
}
protected void integrate(Container container, boolean featured) {
if (container != null) {
if (featured) {
if (textAreas[0] != null) {
textAreas[1] = textAreas[0];
setTextArea(null);
}
}
else {
if (textAreas[1] != null) {
setTextArea(textAreas[1]);
textAreas[1] = null;
}
}
addFeatureTo(container);
container = null;
}
}
public void toggle(boolean featured, Job<Container> inIsolation, Object...args) {
Object[] params = {null};
if (isolate(params)) {
Container container = (Container) params[0];
if (inIsolation != null)
try {
inIsolation.perform(container, args);
} catch (Exception e) {
Log.log(Log.ERROR, getClass().getName() + ".toggle", e);
}
integrate(container, featured);
}
}
public static final String FOCUS = "focus";
public static final String REQUEST = "request";
public boolean focused = false;
public static Component[] focusRequestComponents(Container container) {
final Component[] focused = findComponents(container, new Predicate<Component>() {
public boolean apply(Component c) {
String name = stringValueOf(c.getName());
return check(name, Constraint.AMONG, DoubleFeature.FOCUS) ||
check(name, Constraint.AMONG, DoubleFeature.REQUEST);
}
});
no_println("focusRequest", identity(asList(focused).toArray()));
return focused;
}
public void requestFocus() {
TextArea textArea = getTextArea();
if (textArea != null)
textArea.requestFocus();
else if (widget != null) {
Component component = findFirstComponent(widget, FOCUS, Constraint.AMONG);
if (component != null) {
component.requestFocusInWindow();
diag_println(DIAG_OFF, "focus",
identity(component),
identity(SwingUtilities.getAncestorOfClass(EditPane.class, component)));
}
}
}
}
}