/*
* JBoss, Home of Professional Open Source
* Copyright 2005, JBoss Inc., and individual contributors as indicated
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.hibernate.eclipse.console.common;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.contentassist.ICompletionProposal;
import org.eclipse.jface.text.contentassist.ICompletionProposalExtension;
import org.eclipse.jface.text.contentassist.IContextInformation;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.hibernate.eclipse.HibernatePlugin;
/**
* Generic completion proposal to be used as is, or as base for other completion proposals.
*
* @author Max Rydahl Andersen
*
*/
public class CompletionProposal implements ICompletionProposal, ICompletionProposalExtension {
private String displayString;
private String replacementString;
private int replacementOffset;
private int documentOffset = -1;
private int replacementLength;
private int cursorPosition;
private Image image;
private IContextInformation contextInformation;
private int contextInformationPosition;
private char[] triggerCharacters;
private String additionalProposalInfo;
/**
* Creates a new completion proposal. All fields are initialized based on
* the provided information.
*
* @param additionalInfo additional information about the completion proposal
* @param replacementString the actual string to be inserted into the document
* @param replacementOffset offset of the text to be replaced
* @param documentOffset offset of the document
* @param replacementLength length of the text to be replaced
* @param image the image to display for this proposal
* @param displayString the string to be displayed for the proposal If set
* to <code>null</code>, the replacement string will be taken
* as display string.
*/
public CompletionProposal( String additionalInfo, String replacementString, int replacementOffset,
int documentOffset, int replacementLength, Image image, String displayString,
IContextInformation contextInformation ) {
this.replacementString = replacementString;
this.replacementOffset = replacementOffset;
this.documentOffset = documentOffset;
this.replacementLength = replacementLength;
this.image = image;
this.displayString = displayString != null ? displayString : replacementString;
this.cursorPosition = replacementString.length();
this.contextInformation = contextInformation;
this.triggerCharacters = null;
this.additionalProposalInfo = additionalInfo;
}
/**
* Creates a new completion proposal. All fields are initialized based on
* the provided information.
*
* @param replacementString the actual string to be inserted into the document
* @param replacementOffset the offset of the text to be replaced
* @param replacementLength the length of the text to be replaced
* @param cursorPosition the position of the cursor following the insert
* relative to replacementOffset
* @param image the image to display for this proposal
* @param displayString the string to be displayed for the proposal
* @param contentInformation the context information associated with this proposal
* @param additionalProposalInfo the additional information associated with
* this proposal
*/
public CompletionProposal( String replacementString, int replacementOffset, int replacementLength,
int cursorPosition, Image image, String displayString, IContextInformation contextInformation,
String additionalProposalInfo ) {
this.replacementString = replacementString;
this.replacementOffset = replacementOffset;
this.documentOffset = replacementOffset;
this.replacementLength = replacementLength;
this.cursorPosition = cursorPosition;
this.image = image;
this.displayString = displayString;
this.contextInformation = contextInformation;
this.additionalProposalInfo = additionalProposalInfo;
}
public void setContextInformation( IContextInformation contextInformation ) {
this.contextInformation = contextInformation;
contextInformationPosition = (contextInformation != null ? cursorPosition : -1);
}
/**
* Sets the trigger characters.
*
* @param triggerCharacters The set of characters which can trigger the
* application of this completion proposal
*/
public void setTriggerCharacters( char[] triggerCharacters ) {
this.triggerCharacters = triggerCharacters;
}
/**
* Sets the cursor position relative to the insertion offset. By default
* this is the length of the completion string (Cursor positioned after the
* completion)
*
* @param cursorPosition The cursorPosition to set
*/
public void setCursorPosition( int cursorPosition ) {
if (cursorPosition >= 0) {
this.cursorPosition = cursorPosition;
this.contextInformationPosition = (contextInformation != null ? cursorPosition : -1);
}
}
public void apply( IDocument document, char trigger, int offset ) {
try {
// patch replacement length
int delta = offset - (documentOffset + replacementLength);
if (delta > 0)
replacementLength += delta;
if (trigger == (char) 0) {
replace( document, documentOffset, replacementLength, replacementString );
}
else {
StringBuffer buffer = new StringBuffer( replacementString );
if ((replacementLength < buffer.length() && buffer.charAt( replacementLength ) != trigger)) {
buffer.insert( cursorPosition, trigger );
++cursorPosition;
}
replace( document, documentOffset, replacementLength, buffer.toString() );
}
int oldLen = document.getLength();
documentOffset += document.getLength() - oldLen;
}
catch (BadLocationException e) {
HibernatePlugin.getDefault().log( e );
}
}
/**
* Replaces the document content at the specified offset and length with the
* specified string.
*
* @param document the document opened in the editor
* @param offset offset to the document content to be replaced
* @param length length of text to be replaced
* @param string replacement string
* @throws BadLocationException
*/
private void replace( IDocument document, int offset, int length, String string ) throws BadLocationException {
if (document != null && string != null && offset >= 0 && length >= 0) {
if (!document.get( offset, length ).equals( string ))
document.replace( offset, length, string );
}
}
public void apply( IDocument document ) {
apply( document, (char) 0, documentOffset + replacementLength );
}
public Point getSelection( IDocument document ) {
return new Point( documentOffset + cursorPosition, 0 );
}
public IContextInformation getContextInformation() {
return contextInformation;
}
public Image getImage() {
return image;
}
public String getDisplayString() {
return displayString;
}
public String getAdditionalProposalInfo() {
return additionalProposalInfo;
}
public char[] getTriggerCharacters() {
return triggerCharacters;
}
public int getContextInformationPosition() {
return replacementOffset + contextInformationPosition;
}
public int getReplacementOffset() {
return replacementOffset;
}
public void setReplacementOffset( int replacementOffset ) {
if (replacementOffset >= 0) {
this.replacementOffset = replacementOffset;
}
}
public int getReplacementLength() {
return replacementLength;
}
public void setReplacementLength( int replacementLength ) {
if (replacementLength >= 0) {
this.replacementLength = replacementLength;
}
}
public String getReplacementString() {
return replacementString;
}
public void setReplacementString( String replacementString ) {
this.replacementString = replacementString;
}
public void setImage( Image image ) {
this.image = image;
}
public boolean isValidFor( IDocument document, int offset ) {
if (offset < replacementOffset)
return false;
int replacementLength = replacementString == null ? 0 : replacementString.length();
if (offset >= replacementOffset + replacementLength)
return false;
try {
int length = offset - replacementOffset;
String start = document.get( replacementOffset, length );
return replacementString.substring( 0, length ).equalsIgnoreCase( start );
}
catch (BadLocationException x) {
}
return false;
}
}