package com.applang.components;
import java.awt.event.ActionEvent;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.MouseListener;
import java.lang.reflect.Field;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JDialog;
import javax.swing.JPopupMenu;
import javax.swing.JTextArea;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.UndoableEditEvent;
import javax.swing.event.UndoableEditListener;
import javax.swing.text.JTextComponent;
import javax.swing.undo.CannotRedoException;
import javax.swing.undo.CannotUndoException;
import javax.swing.undo.UndoManager;
import android.content.Context;
import android.content.SharedPreferences;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.EditText;
import com.inet.jortho.PopupListener;
import com.applang.UserContext;
import com.applang.berichtsheft.BerichtsheftActivity;
import static com.applang.Util.*;
import static com.applang.SwingUtil.*;
import static com.applang.PluginUtils.*;
public class TextEdit extends EditText
{
private static final String TAG = TextEdit.class.getSimpleName();
public TextEdit() {
super(new JTextArea());
setHorizontallyScrolling((JTextArea) getComponent(), false);
setContext(BerichtsheftActivity.getInstance());
}
public TextEdit(int rows, int columns) {
super(new JTextArea(rows, columns));
setHorizontallyScrolling((JTextArea) getComponent(), true);
setContext(BerichtsheftActivity.getInstance());
}
public TextEdit(Context context) {
super(context);
}
public TextEdit(Context context, AttributeSet attrs) {
super(context, attrs);
if (hasFeature("spellchecking"))
installSpellChecker(getTextComponent());
if (hasFeature("togglable")) {
setTextToggle(new TextToggle(this));
textToggle.createBufferedTextArea(
attributeSet.getAttributeValue("mode"),
attributeSet.getAttributeValue("modeFile"));
installToggle(getTextComponent());
}
}
@Override
protected void create() {
super.create();
if (getComponent() instanceof JTextArea) {
setHorizontallyScrolling((JTextArea) getComponent(), false);
}
}
private void setHorizontallyScrolling(JTextArea textArea, boolean whether) {
textArea.setLineWrap(!whether);
textArea.setWrapStyleWord(!whether);
textArea.setTabSize(4);
}
private TextToggle textToggle = null;
public void setTextToggle(TextToggle textToggle) {
this.textToggle = textToggle;
}
public TextToggle getTextToggle() {
return textToggle;
}
public void showScriptArea(boolean hide) {
if (textToggle != null) {
if (textToggle.scriptDialog() == null)
textToggle.showScriptArea(getParent().getComponent(), getComponent(),
"Script",
Behavior.HIDDEN);
textToggle.scriptDialog().setVisible(!hide);
}
}
public String getScript() {
if (textToggle != null)
return textToggle.getTextArea().getText();
else
return null;
}
public void setScript(String script) {
if (textToggle != null)
textToggle.getTextArea().setText(script);
}
@Override
public void setText(String text) {
super.setText(textToggle != null ?
UserContext.toPlainText(text) :
text);
}
@Override
protected void finalize() throws Throwable {
if ("spellchecking".equals(feature))
uninstallSpellChecker();
super.finalize();
}
class UndoAction extends AbstractAction
{
public UndoAction() {
super("Undo");
setEnabled(false);
}
public void actionPerformed(ActionEvent ev) {
try {
undoManager.undo();
}
catch (CannotUndoException e) {
message("textedit.no-undo.message", e.getMessage());
}
updateUndoState();
redoAction.updateRedoState();
}
protected void updateUndoState() {
if (undoManager.canUndo()) {
putValue(Action.NAME, undoManager.getUndoPresentationName());
} else {
putValue(Action.NAME, "Undo");
}
setEnabled(undoManager.canUndo());
}
}
class RedoAction extends AbstractAction
{
public RedoAction() {
super("Redo");
setEnabled(false);
}
public void actionPerformed(ActionEvent ev) {
try {
undoManager.redo();
}
catch (CannotRedoException e) {
message("textedit.no-redo.message", e.getMessage());
}
updateRedoState();
undoAction.updateUndoState();
}
protected void updateRedoState() {
if (undoManager.canRedo()) {
putValue(Action.NAME, undoManager.getRedoPresentationName());
} else {
putValue(Action.NAME, "Redo");
}
setEnabled(undoManager.canRedo());
}
}
protected UndoAction undoAction = new UndoAction();
protected RedoAction redoAction = new RedoAction();
public UndoManager undoManager = new UndoManager();
private void installUndoRedo(JTextComponent jtc) {
jtc.getDocument().addUndoableEditListener(new UndoableEditListener() {
public void undoableEditHappened(UndoableEditEvent e) {
undoManager.addEdit(e.getEdit());
undoAction.updateUndoState();
redoAction.updateRedoState();
}
});
installContextMenu(jtc, undoAction, redoAction);
}
private JPopupMenu popupMenu(JTextComponent jtc) {
for (MouseListener listener : jtc.getMouseListeners()) {
if (listener instanceof PopupListener) {
try {
Field f = listener.getClass().getDeclaredField("menu");
f.setAccessible(true);
return (JPopupMenu) f.get(listener);
} catch (Exception e) {
Log.e(TAG, "popupMenu", e);
}
}
}
return null;
}
private void insertMenuItems(JPopupMenu menu, Action...actions) {
int index = 0;
for (Action action : actions)
menu.insert(action, index++);
}
private void installContextMenu(JTextComponent jtc, Action...actions) {
JPopupMenu menu = popupMenu(jtc);
if (menu != null) {
insertMenuItems(menu, actions);
menu.insert(new JPopupMenu.Separator(), actions.length);
}
else {
menu = (JPopupMenu) new JPopupMenu();
insertMenuItems(menu, actions);
jtc.addMouseListener(new PopupAdapter(menu));
}
}
public void installUndoRedo() {
installUndoRedo(getTextComponent());
}
private void installSpellChecker(JTextComponent jtc) {
spellChecking(jtc, true);
installUndoRedo(jtc);
}
public void installSpellChecker() {
installSpellChecker(getTextComponent());
}
public void uninstallSpellChecker() {
spellChecking(getTextComponent(), false);
}
private void installToggle(JTextComponent jtc) {
JPopupMenu menu = popupMenu(jtc);
if (menu != null) {
menu.insert(new JPopupMenu.Separator(), 0);
}
else {
menu = (JPopupMenu) new JPopupMenu();
jtc.addMouseListener(new PopupAdapter(menu));
}
final JCheckBoxMenuItem menuItem = new JCheckBoxMenuItem(toggleType.name(2));
menuItem.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent ev) {
boolean hide = ev.getStateChange() == ItemEvent.DESELECTED;
showScriptArea(hide);
}
});
menu.insert(menuItem, 0);
menu.addPopupMenuListener(new PopupMenuAdapter() {
@Override
public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
JDialog dialog = getTextToggle().scriptDialog();
boolean visible = dialog != null && dialog.isVisible();
menuItem.setSelected(visible);
}
});
}
private CustomActionType toggleType =
new CustomActionType() {
public int index() {
return 0;
}
public String resourceName() {
return "textedit.action-toggle";
}
public String iconName() {
SharedPreferences prefs = getContext().getSharedPreferences();
return prefs.getString(resourceName() + ".icon", null);
}
public String name(int state) {
SharedPreferences prefs = getContext().getSharedPreferences();
return prefs.getString(resourceName().concat(".label") + "." + state, "");
}
public String description() {
SharedPreferences prefs = getContext().getSharedPreferences();
return prefs.getString(resourceName().concat(".label"), "");
}
};
public Job<Boolean> toggler = new Job<Boolean>() {
public void perform(Boolean isText, Object[] parms) throws Exception {
String script = getScript();
textToggle.toggle(isText, null);
if (isText) {
setText(script);
}
}
};
/* public CustomAction toggleAction =
new CustomAction(toggleType) {
{
putValue(NAME, toggleType.name(2));
}
@Override
protected void action_Performed(ActionEvent ae) {
switch (getType().index()) {
case 0:
toggle(this, toggler);
break;
}
}
};
*/
}