001 /* 002 Copyright (C) 2003 Renaud Pawlak <renaud@aopsys.com> 003 004 This program is free software; you can redistribute it and/or modify 005 it under the terms of the GNU Lesser General Public License as 006 published by the Free Software Foundation; either version 2 of the 007 License, or (at your option) any later version. 008 009 This program is distributed in the hope that it will be useful, but 010 WITHOUT ANY WARRANTY; without even the implied warranty of 011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 012 Lesser General Public License for more details. 013 014 You should have received a copy of the GNU Lesser General Public 015 License along with this program; if not, write to the Free Software 016 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 017 USA */ 018 019 package org.objectweb.jac.aspects.gui.swing; 020 021 import java.util.Collection; 022 import java.util.Iterator; 023 import java.util.List; 024 import java.util.Vector; 025 import org.apache.log4j.Logger; 026 027 /** 028 * This class must be subclassed to implement specific completion 029 * engines for code editors. 030 */ 031 public abstract class CompletionEngine { 032 static Logger logger = Logger.getLogger("completion"); 033 034 public static final int BACKWARD=-1; 035 public static final int FORWARD=1; 036 037 protected List baseWords = new Vector(); 038 039 /** 040 * Returns the list of the words that are potential completions for 041 * a given context. Implement this methods for specific language 042 * editors. 043 * 044 * @param text the editor's full text 045 * @param position the cursor position 046 * @param writtenText the already written text 047 * @return a list of strings which <b>must not contain duplicates</b> 048 */ 049 public abstract List getContextualChoices(String text, int position, 050 String writtenText); 051 052 /** 053 * Returns a proposal from a current text's state. 054 * 055 * @param text the editor's full text 056 * @param position the cursor position 057 * @param writtenText the already written text of the 058 * completionable word if any 059 * @param currentProposal the proposal that is currently made to 060 * the user ("" if none) 061 * @param direction BACKWARD || FORWARD 062 * @return the proposed completion, starting with writtenText 063 */ 064 public String getProposal(String text, 065 int position, 066 String writtenText, 067 String currentProposal, 068 int direction) { 069 logger.info("getProposal("+position+","+ 070 ","+writtenText+","+currentProposal+","+direction+")"); 071 String ret = ""; 072 List words = getContextualChoices(text,position,writtenText); 073 logger.debug("Proposals = "+words); 074 if (words.size()==0) 075 return ret; 076 if (currentProposal.equals("") && writtenText.equals("")) { 077 ret = (String)words.get(0); 078 } else { 079 // Finds the position of currentProposal in words 080 // We cannot use List.indexOf() because we want case insensitiveness 081 int i = -1; 082 int pos = 0; 083 Iterator it = words.iterator(); 084 while (it.hasNext() && i==-1) { 085 if (currentProposal.compareToIgnoreCase((String)it.next())==0) 086 i = pos; 087 pos++; 088 } 089 if (i!=-1 || currentProposal.equals("")) { 090 if (writtenText.equals("")) { 091 ret = (String) words.get(next(words,i,direction)); 092 } else { 093 int count = 0; 094 logger.debug("before search: "+i); 095 while(count <= words.size() && 096 !((String)words.get(i=next(words,i,direction))).toLowerCase() 097 .startsWith(writtenText.toLowerCase())) { 098 count++; 099 } 100 logger.debug("after search: "+i); 101 if (((String)words.get(i)).toLowerCase() 102 .startsWith(writtenText.toLowerCase())) { 103 ret = ((String)words.get(i));//.substring(writtenText.length()); 104 } 105 } 106 } 107 } 108 return ret; 109 } 110 111 public abstract void runAutomaticCompletion(SHEditor editor, 112 String text, 113 int position, 114 char c); 115 116 public abstract boolean isAutomaticCompletionChar(char c); 117 118 int next(List l,int i, int direction) { 119 if(direction==FORWARD) { 120 if(i==l.size()-1) 121 return 0; 122 else 123 return i+1; 124 } else if (direction==BACKWARD) { 125 if(i==0) 126 return l.size()-1; 127 else 128 return i-1; 129 } else { 130 return i; 131 } 132 } 133 134 public List getBaseWords() { 135 return baseWords; 136 } 137 138 public void addBaseWord(String baseWord) { 139 if (!baseWords.contains(baseWord)) { 140 baseWords.add(baseWord); 141 } 142 } 143 144 public void addBaseWords(Collection baseWords) { 145 logger.debug("addBaseWords "+baseWords); 146 Iterator it = baseWords.iterator(); 147 while (it.hasNext()) { 148 Object cur = it.next(); 149 if (!this.baseWords.contains(cur)) { 150 this.baseWords.add(cur); 151 } 152 } 153 } 154 155 public void clearBaseWords() { 156 baseWords.clear(); 157 } 158 159 }