package com.applang.components;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Properties;
import javax.swing.AbstractAction;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.text.JTextComponent;
import javax.swing.text.Segment;
import javax.swing.text.Highlighter.Highlight;
import org.gjt.sp.jedit.IPropertyManager;
import org.gjt.sp.jedit.JEditBeanShellAction;
import org.gjt.sp.jedit.Mode;
import org.gjt.sp.jedit.View;
import org.gjt.sp.jedit.buffer.BufferAdapter;
import org.gjt.sp.jedit.buffer.JEditBuffer;
import org.gjt.sp.jedit.syntax.ModeProvider;
import org.gjt.sp.jedit.syntax.ParserRuleSet;
import org.gjt.sp.jedit.syntax.Token;
import org.gjt.sp.jedit.syntax.TokenHandler;
import org.gjt.sp.jedit.syntax.TokenMarker;
import org.gjt.sp.jedit.syntax.TokenMarker.LineContext;
import org.gjt.sp.jedit.textarea.JEditEmbeddedTextArea;
import org.gjt.sp.jedit.textarea.Selection;
import org.gjt.sp.jedit.textarea.StandaloneTextArea;
import org.gjt.sp.jedit.textarea.TextArea;
import android.util.Log;
import com.applang.PluginUtils;
import com.applang.Util;
import static com.applang.Util.*;
import static com.applang.Util2.*;
import static com.applang.SwingUtil.*;
import static com.applang.PluginUtils.*;
public class TextToggle extends DoubleFeature implements ITextComponent
{
private static final String TAG = TextToggle.class.getSimpleName();
public TextToggle() {
this(new TextEdit());
}
public TextToggle(int rows, int columns) {
this(new TextEdit(rows, columns));
}
public TextToggle(TextEdit textEdit) {
super(null);
setTextEdit(textEdit);
}
protected void setTextEdit(TextEdit textEdit) {
this.textEdit = textEdit;
addNamePart(textEdit.getTaggedComponent(), FOCUS);
setWidget((JComponent) textEdit.getComponent());
this.textEdit.setTextToggle(this);
}
private TextEdit textEdit;
public TextEdit getTextEdit() {
return textEdit;
}
public JTextComponent getTextEditor() {
return getTextEdit().getTextComponent();
}
public TextToggle(View view) {
this();
setView(view);
}
private View view = null;
public View getView() {
return view;
}
private void setView(View vw) {
view = vw;
}
public boolean hasView() {
View view = getView();
return view != null && view.getTextArea() != null;
}
@Override
public Component getUIComponent() {
return super.getFeature();
}
@Override
public TextArea getTextArea() {
return hasView() ? getView().getTextArea() : super.getTextArea();
}
// resizing problems (in BoxLayout) of org.gjt.sp.jedit.textarea.StandaloneTextArea
// no problems in BorderLayout
public TextToggle createBufferedTextArea(String modeName, String modeFileName) {
TextArea textArea;
String settingsDir = PluginUtils.getSettingsDirectory();
boolean useEmbedded = false;
if (useEmbedded && PluginUtils.insideJEdit()) {
textArea = new JEditEmbeddedTextArea() {
{
setRightClickPopupEnabled(true);
}
@Override
public void createPopupMenu(MouseEvent evt) {
popup = new JPopupMenu();
TextToggle.this.createPopupMenu(this, popup);
}
};
}
else {
final Properties props = new Properties();
String keymapDirName = pathCombine(settingsDir, "keymaps");
String keymapFileName = pathCombine(keymapDirName, "imported_keys.props");
if (!fileExists(keymapFileName))
keymapFileName = pathCombine(keymapDirName, "jedit_keys.props");
props.putAll(PluginUtils.loadProperties(keymapFileName));
props.putAll(PluginUtils.loadProperties("/org/gjt/sp/jedit/jedit.props"));
initBufferProperties(props);
String antiAlias = getProperty("view.antiAlias", "standard");
props.setProperty("view.antiAlias", antiAlias);
props.setProperty("view.gutter.borderWidth", "0");
IPropertyManager propsMan = new IPropertyManager() {
public String getProperty(String name)
{
String property = props.getProperty(name);
return property;
}
};
textArea = new StandaloneTextArea(propsMan) {
{
setRightClickPopupEnabled(true);
}
@Override
public void createPopupMenu(MouseEvent evt) {
popup = new JPopupMenu();
TextToggle.this.createPopupMenu(this, popup);
}
};
}
if (notNullOrEmpty(modeName)) {
EditBuffer buffer = new EditBuffer();
TokenMarker tokenMarker = new TokenMarker();
tokenMarker.addRuleSet(new ParserRuleSet("text","MAIN"));
buffer.setTokenMarker(tokenMarker);
textArea.setBuffer(buffer);
Mode mode = new Mode(modeName);
modeFileName = pathCombine(settingsDir, modeFileName);
mode.setProperty("file", modeFileName);
ModeProvider.instance.addMode(mode); // mode.loadIfNecessary();
buffer.setMode(mode);
}
Dimension size = textArea.getPreferredSize();
textArea.setPreferredSize(new Dimension(size.width, size.height / 2));
addNamePart(textArea, FOCUS);
setTextArea(textArea);
getTextEdit().getTaggedComponent().updateUI();
return this;
}
public static void initBufferProperties(final Properties props) {
props.setProperty("buffer.folding", "explicit");
props.setProperty("buffer.tabSize", "4");
props.setProperty("buffer.indentSize", "4");
props.setProperty("buffer.wrap", "soft");
props.setProperty("buffer.maxLineLen", "0");
}
private JMenuItem addMenuItem(final TextArea ta, JPopupMenu popup, String action, String label)
{
final JEditBeanShellAction shellAction = ta.getActionContext().getAction(action);
if (shellAction == null)
return null ;
JMenuItem item = new JMenuItem();
item.setAction(new AbstractAction(label)
{
public void actionPerformed(ActionEvent e) {
shellAction.invoke(ta);
}
});
popup.add(item);
return item;
}
private void createPopupMenu(TextArea ta, JPopupMenu popup)
{
addMenuItem(ta, popup, "undo", "Undo");
addMenuItem(ta, popup, "redo", "Redo");
popup.addSeparator();
addMenuItem(ta, popup, "cut", "Cut");
addMenuItem(ta, popup, "copy", "Copy");
addMenuItem(ta, popup, "paste", "Paste");
}
public class EditBuffer extends JEditBuffer
{
@Override
protected TokenMarker.LineContext markTokens(Segment seg,
TokenMarker.LineContext prevContext,
final TokenHandler _tokenHandler)
{
TokenMarker.LineContext context = tokenMarker.markTokens(prevContext, new TokenHandler() {
public void handleToken(Segment seg, byte id, int offset, int length, LineContext context) {
JTextComponent textEditor = getTextEditor();
if (textEditor != null && spellchecking && id == 0) {
Highlight[] hilites = textEditor.getHighlighter().getHighlights();
int offset2 = offset + length, len;
for (int i = 0; i < hilites.length; i++) {
Highlight hilite = hilites[i];
int start = hilite.getStartOffset();
int end = hilite.getEndOffset();
if (start < offset2 && end > offset) {
// println("token (%d,%d) '%s' hilite %d : (%d,%d) '%s'",
// offset, length, seg.subSequence(offset, offset2),
// 1+i, start, end, getText().substring(start, end));
if (start <= offset) {
len = Math.min(length, end - offset);
_tokenHandler.handleToken(seg,
Token.INVALID,
offset, len, context);
offset += len;
}
else {
len = start - offset;
_tokenHandler.handleToken(seg,
id,
offset, len, context);
offset += len;
len = Math.min(offset2, end) - start;
_tokenHandler.handleToken(seg,
Token.INVALID,
start, len, context);
offset += len;
}
}
}
length = offset2 - offset;
}
_tokenHandler.handleToken(seg, id, offset, length, context);
}
public void setLineContext(LineContext lineContext) {
_tokenHandler.setLineContext(lineContext);
}
}, seg);
return context;
}
}
private boolean spellchecking = false;
@Deprecated
public void spellcheck() {
TextArea textArea = getTextArea();
JTextComponent textEditor = getTextEditor();
if (textEditor != null && textArea != null) {
spellChecking(textEditor, true);
textEditor.setText(textArea.getText());
spellchecking = true;
textArea.setText(textEditor.getText());
spellchecking = false;
spellChecking(textEditor, false);
}
}
@Override
public void setText(String text) {
TextArea textArea = getTextArea();
if (textArea != null)
textArea.setText(text);
else {
JTextComponent textEditor = getTextEditor();
if (textEditor != null)
textEditor.setText(text);
else
Log.w(TAG, "setText not possible");
}
}
@Override
public String getText() {
TextArea textArea = getTextArea();
if (textArea != null)
return textArea.getText();
else {
JTextComponent textEditor = getTextEditor();
if (textEditor != null)
return textEditor.getText();
Log.w(TAG, "getText not possible, returning null");
return null;
}
}
@Override
public void setSelection(int start, int end) {
TextArea textArea = getTextArea();
if (textArea != null) {
textArea.setSelection(new Selection.Range(start, end));
textArea.requestFocus();
} else {
JTextComponent textEditor = getTextEditor();
if (textEditor != null) {
textEditor.setSelectionStart(start);
textEditor.setSelectionEnd(end);
textEditor.requestFocus();
}
else
Log.w(TAG, "setSelection not possible");
}
}
@Override
public void setSelectedText(String text) {
TextArea textArea = getTextArea();
if (textArea != null) {
int start = textArea.getSelection()[0].getStart();
textArea.setSelectedText(text);
if (notNullOrEmpty(text))
setSelection(start, start + text.length());
} else {
JTextComponent textEditor = getTextEditor();
if (textEditor != null) {
int start = textEditor.getSelectionStart();
getTextEdit().replaceRange(text, start, textEditor.getSelectionEnd());
setSelection(start, start + (notNullOrEmpty(text) ? 0 : text.length()));
}
else
Log.w(TAG, "setSelectedText not possible");
}
}
@Override
public String getSelectedText() {
TextArea textArea = getTextArea();
if (textArea != null)
return textArea.getSelectedText();
else {
JTextComponent textEditor = getTextEditor();
if (textEditor != null)
return textEditor.getSelectedText();
Log.w(TAG, "getSelectedText not possible, returning null");
return null;
}
}
private Job<JComponent> onTextChanged = null;
private void textChanged() {
try {
TextArea textArea = getTextArea1();
if (onTextChanged != null)
onTextChanged.perform(textArea, objects());
} catch (Exception e) {
Log.e(TAG, "textChanged", e);
}
}
private TextArea getTextArea1() {
TextArea textArea = getTextArea();
if (textArea == null)
textArea = getTextArea2();
return textArea;
}
public void setOnTextChanged(final Job<JComponent> onTextChanged) {
this.onTextChanged = onTextChanged;
TextArea textArea = getTextArea1();
if (textArea != null) {
textArea.getBuffer().addBufferListener(new BufferAdapter() {
@Override
public void transactionComplete(JEditBuffer buffer) {
}
@Override
public void bufferLoaded(JEditBuffer buffer) {
}
@Override
public void preContentRemoved(JEditBuffer buffer, int startLine,
int offset, int numLines, int length) {
}
@Override
public void preContentInserted(JEditBuffer buffer, int startLine,
int offset, int numLines, int length) {
}
@Override
public void foldLevelChanged(JEditBuffer buffer, int startLine, int endLine) {
}
@Override
public void foldHandlerChanged(JEditBuffer buffer) {
}
@Override
public void contentRemoved(JEditBuffer buffer, int startLine, int offset, int numLines, int length) {
textChanged();
}
@Override
public void contentInserted(JEditBuffer buffer, int startLine, int offset, int numLines, int length) {
textChanged();
}
});
} else {
TextEdit textEdit = getTextEdit();
if (textEdit != null)
textEdit.setOnTextChanged(onTextChanged);
else
Log.w(TAG, "setOnTextChanged not possible");
}
}
@Override
public void addKeyListener(KeyListener keyListener) {
TextArea textArea = getTextArea();
if (textArea != null)
textArea.addKeyListener(keyListener);
else {
JComponent widget = getWidget();
if (widget != null)
widget.addKeyListener(keyListener);
else
Log.w(TAG, "addKeyListener not possible");
}
}
private ScriptManager scriptManager = null;
public JDialog scriptDialog() {
return scriptManager == null ? null : scriptManager.scriptDialog;
}
public void showScriptArea(Component parent, Component relative,
String title, int behavior,
Object...params)
{
scriptManager = new ScriptManager(this);
scriptManager.showScriptDialog(parent, relative, title, behavior, params);
}
public static void main(String...args) throws Exception {
TextToggle textToggle = new TextToggle();
textToggle.createBufferedTextArea("xml", "/modes/xml.xml");
textToggle.showScriptArea(null, null,
"Script",
Behavior.MODAL | Behavior.EXIT_ON_CLOSE,
new Util.Job<TextArea>() {
public void perform(TextArea t, Object[] parms) throws Exception {
t.getPainter().addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
println("mouseClicked", identity(e.getSource()));
}
});
}
}
);
}
}