Package org.enclojure.ide.nb.editor.completion

Source Code of org.enclojure.ide.nb.editor.completion.AtomicChange

/*
(comment
*******************************************************************************
*    Copyright (c) ThorTech, L.L.C.. All rights reserved.
*    The use and distribution terms for this software are covered by the
*    GNU General Public License, version 2
*    (http://www.gnu.org/licenses/old-licenses/gpl-2.0.html) with classpath
*    exception (http://www.gnu.org/software/classpath/license.html)
*    which can be found in the file GPL-2.0+ClasspathException.txt at the root
*    of this distribution.
*    By using this software in any fashion, you are agreeing to be bound by
*    the terms of this license.
*    You must not remove this notice, or any other, from this software.
*******************************************************************************
*    Author:Paul Wade
*******************************************************************************
)
*/

package org.enclojure.ide.nb.editor.completion;

/**
*
* @author pwade
*/
import clojure.lang.Keyword;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import javax.swing.ImageIcon;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.text.JTextComponent;
import javax.swing.text.StyledDocument;
import org.netbeans.api.editor.completion.Completion;
import org.netbeans.spi.editor.completion.CompletionItem;
import org.netbeans.spi.editor.completion.CompletionResultSet;
import org.netbeans.spi.editor.completion.CompletionTask;
import org.netbeans.spi.editor.completion.support.AsyncCompletionQuery;
import org.netbeans.spi.editor.completion.support.AsyncCompletionTask;
import org.netbeans.spi.editor.completion.support.CompletionUtilities;
import org.openide.text.NbDocument;
import java.util.Hashtable;
import clojure.lang.RT;
import clojure.lang.Var;
import clojure.lang.Symbol;
import clojure.lang.PersistentArrayMap;
import java.awt.Container;
import java.util.Iterator;
import java.util.ArrayList;
import javax.swing.JOptionPane;
import javax.swing.JViewport;
import org.openide.util.Exceptions;
import java.util.logging.Level;
import org.enclojure.ide.core.LogAdapter;


@SuppressWarnings("unchecked")
public class ClojureCodeCompletionItem implements CompletionItem {

    private static final LogAdapter LOG = new LogAdapter(ClojureCodeCompletionItem.class.getName());

    final static Var getalljavaclassesfn = RT.var("org.enclojure.ide.nb.editor.completion.cljcodecompletion", "get-all-java-classes-with-ns");
    final static Var getallclojurenamespacesfn = RT.var("org.enclojure.ide.nb.editor.completion.cljcodecompletion", "get-all-clojure-namespaces-within-nsnode");
    final static Var addimportlistfn = RT.var("org.enclojure.ide.nb.editor.completion.cljcodecompletion", "add-import-list-new");

    private static Color fieldColor = Color.decode("0x0000B2");
    private static ImageIcon fieldIcon = null;
    private ImageIcon  _icon;
    private int _type;
    private int _carretOffset;
    private int _dotOffset;
    private int _layout=-1;
    private String _text;
    private String _doc;

    private static final int LowercaseAfterParen = 0;
    private static final int UppercaseAfterParen = 1;
    private static final int LowercaseAfterParenWithDot = 2;
    private static final int UppercaseAfterParenWithDot = 3;
    private static final int LowercaseNoParen = 4;
    private static final int UppercaseNoParen = 5;
    private static final int LowercaseNoParenWithDot = 6;
    private static final int UppercaseNoParenWithDot = 7;
    private static final int FirstDotAfterParen = 8;
    private static final int FirstDotNoParen = 9;
    private static final int backSlashAfterParen = 10;
    private static final int backSlashNoParen = 11;
    private boolean _isStatic;
    public boolean _isClojure;
    private int _priority;
    public boolean _isMethodOrFunction;
    public boolean _isNamespaceOrPkg;
    public boolean _isConstructor;
    public String _fullclassname;
    private Hashtable _pInfo;
    public String _source;
    private boolean hasPkg= false;

    public String getText()
    {
   
        int pos=_text.indexOf("(");

        int staticPos=_text.indexOf("-->static");

        if (staticPos > -1)
            _isStatic=true;
        else
            _isStatic=false;

        if (_isClojure==true)
            _isStatic=true;


        if (pos > -1)
            return _text.substring(0,pos);
        else
            return _text;



    }

    public ClojureCodeCompletionItem(String text, int dotOffset, int carretOffset)
    {
    _text = text;
    _dotOffset = dotOffset;
    _carretOffset = carretOffset;
    }

     public ClojureCodeCompletionItem(String text, int dotOffset, int carretOffset,int layout)
    {
    _text = text;
    _dotOffset = dotOffset;
    _carretOffset = carretOffset;
    _layout=layout;
    }

        public ClojureCodeCompletionItem(String text, int dotOffset, int carretOffset,Hashtable processInfo)
    {
    _text = text;
    _dotOffset = dotOffset;
    _carretOffset = carretOffset;

    _pInfo=processInfo;
    _layout=(Integer)processInfo.get("layout");
    _isClojure=(Boolean)processInfo.get("isClojure");
    _priority=(Integer)processInfo.get("priority");
    _isMethodOrFunction=(Boolean)processInfo.get("isMethodOrFunction");
    _isNamespaceOrPkg=(Boolean)processInfo.get("isNamespaceOrPackage");
    _fullclassname=(String)processInfo.get("fullclassname");
    _source=(String)processInfo.get("source");
    _isConstructor=(Boolean)processInfo.get("isConstructor");
    }



    private void doSubstitute(final JTextComponent component, final String toAdd, final int backOffset) {

        final StyledDocument doc = (StyledDocument) component.getDocument();

        class AtomicChange implements Runnable {

            public void run() {

                int caretOffset = component.getCaretPosition();
                String cname= component.getClass().getName();
               
                Boolean _isReplPanel=false;

                if (cname.equals("javax.swing.JEditorPane"))
                    _isReplPanel=true;
              
                String value = getText();
                String javaList="";

                if (toAdd != null) {
                    value += toAdd;
                }
               
                try {

                    String c=component.getText(caretOffset-1,1);

                    if (!_isClojure && _isNamespaceOrPkg) //java package containing the Class at the end
                    {
                        value=setValueForClass(value,component);
                        javaList=getJavaImportListStr(value);

                       

                        if ((javaList.contains("(")) && (! _isReplPanel))
                        {
                            int messageret=(JOptionPane.showConfirmDialog(component, "Do you want to add the import " + value + " to your ns imports?", "add import ?",0));

                            if (messageret==0)
                            {
                                PersistentArrayMap entry= addImportList(component, javaList);
                                //component.setCaretPosition(caretOffset + javaList.length());
                                value=getClassPart(value);
                               
                                if (entry!=null)
                                {
                                    String origNS=(String)entry.get(Keyword.intern(Symbol.create("orignodestr")));
                                    String newNS=(String)entry.get(Keyword.intern(Symbol.create("newnodestr")));

                                    int insertOffset=newNS.length()-origNS.length();

                                   
                                    _carretOffset = _carretOffset + insertOffset;
                                    _dotOffset=_dotOffset + insertOffset;

                                }
                            }
                        }

                    }

                       
                    if (! c.equals("/") && (_layout!=backSlashAfterParen) && (_layout!=backSlashNoParen))
                    {
                       
                      

                        switch(_layout)
                        {

                        case LowercaseAfterParen:
                            doc.remove(_dotOffset, _carretOffset - _dotOffset );
                            break;
                        case UppercaseAfterParen:
                            doc.remove(_dotOffset, _carretOffset - _dotOffset );
                            break;
                        case UppercaseAfterParenWithDot:
                           if (_isMethodOrFunction && (!_isClojure)) //java method
                            {
                                if (_isConstructor) {
                                    value = "";
                                } else if (Character.isLetter(value.charAt(0))) {
                                    {
                                        doc.remove(_dotOffset, _carretOffset - _dotOffset );
                                        value = "." + value;

                                    }
                                }
                            }
                            else
                               doc.remove(_dotOffset, _carretOffset - _dotOffset );
                            break;
                       case LowercaseAfterParenWithDot:
                            if (_isMethodOrFunction && (!_isClojure)) //java method
                            {
                                if (_isConstructor) {
                                    value = "";
                                } else if (Character.isLetter(value.charAt(0))) {
                                    {
                                        doc.remove(_dotOffset, _carretOffset - _dotOffset );
                                        value = "." + value;

                                    }
                                }
                            }
                            else
                               doc.remove(_dotOffset, _carretOffset - _dotOffset );
                            break;
                       case backSlashAfterParen:
                            doc.remove(_dotOffset, _carretOffset - _dotOffset );
                            break;
                        case FirstDotAfterParen:
                            doc.remove(_dotOffset, _carretOffset - _dotOffset );
                            break;
                        case FirstDotNoParen:
                            doc.remove(_dotOffset, _carretOffset - _dotOffset );
                            break;
                        case UppercaseNoParen:
                            doc.remove(_dotOffset, _carretOffset - _dotOffset );
                            break;
                        case UppercaseNoParenWithDot:
                          if (_isMethodOrFunction && (!_isClojure)) //java method
                            {
                                if (_isConstructor) {
                                    value = "";
                                } else if (Character.isLetter(value.charAt(0))) {
                                    {
                                        doc.remove(_dotOffset, _carretOffset - _dotOffset );
                                        value = "." + value;

                                    }
                                }
                            }
                            else
                               doc.remove(_dotOffset, _carretOffset - _dotOffset );
                            break;
                        case LowercaseNoParenWithDot:
                            if (_isMethodOrFunction && (!_isClojure)) //java method
                            {
                                if (_isConstructor) {
                                    value = "";
                                } else if (Character.isLetter(value.charAt(0))) {
                                    {
                                        doc.remove(_dotOffset, _carretOffset - _dotOffset );
                                        value = "." + value;

                                    }
                                }
                            }
                            else
                               doc.remove(_dotOffset, _carretOffset - _dotOffset );
                            break;
                         case LowercaseNoParen:
                            doc.remove(_dotOffset, _carretOffset - _dotOffset );
                            break;

                        }



                        doc.insertString(_dotOffset, value, null);
                    }
                    else
                    {
                        if (! c.equals("/"))
                        {
                            int backSlashOffset=indexOfBackSlash(component);
                            if (backSlashOffset==-1)
                                backSlashOffset=caretOffset;

                            if (_isStatic || _layout==backSlashAfterParen || _layout==backSlashNoParen )
                            {
                                if (_isClojure && _isMethodOrFunction)
                                {
                                    if (isInCurrentNamespace(_fullclassname, component))
                                    {
                                        doc.remove(_dotOffset, _carretOffset - _dotOffset );
                                        doc.insertString(_dotOffset,setValue(value), null);
                                    }
                                    else
                                    {
                                        doc.remove(backSlashOffset + 1, caretOffset - backSlashOffset-1);
                                        doc.insertString(backSlashOffset+1, value, null);
                                    }
                                }
                                else
                                    {
                                        doc.remove(backSlashOffset + 1, caretOffset - backSlashOffset-1);
                                        doc.insertString(backSlashOffset+1, value, null);
                                    }
                            }
                            else
                            {
                                doc.remove(_dotOffset, _carretOffset - _dotOffset );
                                doc.insertString(_dotOffset,setValue(value), null);
                            }

                        }
                        else
                            if (_isStatic || _layout==backSlashAfterParen || _layout==backSlashNoParen )

                                if (_isClojure && _isMethodOrFunction)
                                {
                                    if (isInCurrentNamespace(_fullclassname, component))
                                    {
                                        doc.remove(_dotOffset, _carretOffset - _dotOffset );
                                        doc.insertString(_dotOffset,setValue(value), null);
                                    }
                                    else
                                         doc.insertString(_carretOffset, value, null);
                                }
                                else
                                    doc.insertString(_carretOffset, value, null);
                            else
                            {
                                doc.remove(_dotOffset, _carretOffset - _dotOffset );
                                doc.insertString(_dotOffset,setValue(value), null);

                            }
                    }


                   
                    component.setCaretPosition(component.getCaretPosition() - backOffset);

                } catch (BadLocationException e) {
                    LOG.log(Level.FINEST, e.getMessage());
                }

            }
        }

         AtomicChange change = new AtomicChange();
            try {
                NbDocument.runAtomicAsUser(doc, change);
            } catch (BadLocationException ex) {
                LOG.log(Level.FINEST, ex.getMessage());
            }

    }


    private String getJavaImportListStr (String fullclassstr)
    {
         Integer dotPos=fullclassstr.lastIndexOf(".");
         String clsstr="";
         String pkgstr="";

        if (dotPos > -1)
        {
            clsstr= fullclassstr.substring(dotPos + 1);
            pkgstr=fullclassstr.substring(0,dotPos);

            return "(" + pkgstr + " " + clsstr + ")\n";

        }
        else
            return fullclassstr;


    }

    private String setValueForClass(String value,JTextComponent component)
    {

      Iterator iter=getAllJavaClasses(component);
        ArrayList<String> li=new ArrayList<String>();
        Hashtable ht=new Hashtable();



        String entry="";

        if (iter != null)
        {
            while (iter.hasNext())
            {
                entry=(String)iter.next();

                if (entry !=null)
                    ht.put(entry, getPkgPart(entry));

            }
        }

        if (ht.containsKey(value))
            value=getClassPart(value);

        if (ht.containsValue(getPkgPart(value)))
            hasPkg=true;

        return value;

    }

    private Boolean isInCurrentNamespace(String value,JTextComponent component)
    {

      //value will have format of namespace/function
        Integer slashPos=value.indexOf("/");
       
        if (slashPos > -1)
            value=value.substring(0,slashPos);
       
        Iterator iter=getAllClojureNamespacesWithinNSnode(component);
        ArrayList<String> li=new ArrayList<String>();

        String entry="";

        if (iter != null)
        {
            while (iter.hasNext())
            {
                entry=(String)iter.next();

                if (entry !=null)
                    li.add(entry);
            }
        }

        if (li.contains(value))
            return true;
        else
            return false;

    }

    private String getClassPart(String fullclassstr)
    {

        Integer dotPos=fullclassstr.lastIndexOf(".");

        if (dotPos > -1)
            return fullclassstr.substring(dotPos + 1);
        else
            return fullclassstr;

    }

    private String getPkgPart(String fullclassstr)
    {

        Integer dotPos=fullclassstr.lastIndexOf(".");

        if (dotPos > -1)
            return fullclassstr.substring(0,dotPos);
        else
            return fullclassstr;
    }

    private String setValue(String value)
    {



        if (_isClojure)
            return value;
        else
            return "." + value;

    }



    private Iterator getAllJavaClasses(JTextComponent component)
    {
            try {
                return ((Iterable)getalljavaclassesfn.invoke(component)).iterator();

            } catch (Exception ex) {
                //Exceptions.printStackTrace(ex);
                return null;
            }

    }

    private Iterator getAllClojureNamespacesWithinNSnode(JTextComponent component)
    {
            try {
                return ((Iterable)getallclojurenamespacesfn.invoke(component)).iterator();

            } catch (Exception ex) {
                //Exceptions.printStackTrace(ex);
                return null;
            }

    }

    private PersistentArrayMap addImportList(JTextComponent component,String javaList)
    {
            try {
                return (PersistentArrayMap)addimportlistfn.invoke(component,javaList);

            } catch (Exception ex) {
                //Exceptions.printStackTrace(ex);
                    return null;
            }

    }

    public void defaultAction(JTextComponent jTextComponent) {
        Completion.get().hideAll();
        doSubstitute(jTextComponent, null, 0);
    }

    public void processKeyEvent(KeyEvent arg0) {

//        boolean blnShift =arg0.isShiftDown();
//        char c=arg0.getKeyChar();
//        int keyCode=arg0.getKeyCode();

    }

    public int getPreferredWidth(Graphics graphics, Font font) {
         return CompletionUtilities.getPreferredWidth(encodeHTML(_text), null, graphics, font);
    }

    public void render(Graphics g, Font defaultFont, Color defaultColor, Color backgroundColor, int width,
            int height, boolean selected) {
        CompletionUtilities.renderHtml(_icon, encodeHTML(_text), null, g, defaultFont,
            (selected ? Color.white : fieldColor), width, height, selected);
    }

    public CompletionTask createDocumentationTask() {

        //return null;

        return new AsyncCompletionTask( new AsyncCompletionQuery() {

        protected void query(CompletionResultSet completionResultSet, Document document, int i)
        {
           completionResultSet.setDocumentation(new ClojureCodeCompletionDocumentation(ClojureCodeCompletionItem.this));
           completionResultSet.finish();
        }

        });

    }

    public CompletionTask createToolTipTask() {
        return null;
    }

    public boolean instantSubstitution(JTextComponent arg0) {
        return false;
    }

    public int getSortPriority() {
        return _priority;
    }

    public CharSequence getSortText() {
        return getText();
    }

    public CharSequence getInsertPrefix() {
        return getText();
    }

    public static String encodeHTML(String s)
{
    StringBuffer out = new StringBuffer();
    for(int i=0; i<s.length(); i++)
    {
        char c = s.charAt(i);
        if(c > 127 || c=='"' || c=='<' || c=='>')
        {
           out.append("&#"+(int)c+";");
        }
        else
        {
            out.append(c);
        }
    }
    return out.toString();
}

    static int indexOfBackSlash(final JTextComponent component) {

        int caretOffset = component.getCaretPosition();

        String c;

        int i = caretOffset-1;

        try
        {
        while (--i > -1)
        {
            c = component.getText(i,1);
            if (c.equals("/"))
            {
               return i;
            }
        }
        return -1;
        }
        catch (BadLocationException ex)
        {
                return -1;
        }
    }

}
TOP

Related Classes of org.enclojure.ide.nb.editor.completion.AtomicChange

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.