/*
* Copyright (c) 2012, the Dart project authors.
*
* Licensed under the Eclipse Public License v1.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.eclipse.org/legal/epl-v10.html
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.dart.tools.ui.omni;
import com.google.dart.tools.ui.instrumentation.UIInstrumentation;
import com.google.dart.tools.ui.instrumentation.UIInstrumentationBuilder;
import com.google.dart.tools.ui.omni.util.CamelUtil;
import org.eclipse.jface.resource.ImageDescriptor;
public abstract class OmniElement {
protected static final String separator = " - "; //$NON-NLS-1$
protected static final int[][] EMPTY_INDICES = new int[0][0];
private final OmniProposalProvider provider;
private boolean duplicate;
protected int detailOffset = -1;
/**
* Create an element.
*
* @param provider the proposal provider
*/
public OmniElement(OmniProposalProvider provider) {
super();
this.provider = provider;
}
/**
* Executes the associated action for this element.
*
* @param text the current string in the search box
*/
public void execute(String text) {
UIInstrumentationBuilder instrumentation = UIInstrumentation.builder(this.getClass());
instrumentation.data("text", text);
try {
doExecute(text, instrumentation);
} finally {
instrumentation.log();
}
}
/**
* Returns a detailed label (used for disambiguating duplicate matches)
*/
public String getDetailedLabel() {
return getLabel();
}
/**
* Get the offset of the detail portion of this element's label (if there is one). The default
* value is <code>-1</code>.
*
* @return the detail offset, or <code>-1</code> if there is none.
*/
public int getDetailOffset() {
return detailOffset;
}
/**
* Returns the id for this element. The id has to be unique within the OmniProposalProvider that
* provided this element.
*
* @return the id
*/
public abstract String getId();
/**
* Returns the image descriptor for this element.
*
* @return an image descriptor, or null if no image is available
*/
public abstract ImageDescriptor getImageDescriptor();
/**
* Returns an in info label, that used with the detailed label can further disambiguate duplicate
* matches. In the UI this label is used in the "info" area at the bottom of the omni box.
*/
public String getInfoLabel() {
return "";
}
/**
* Returns the label to be displayed to the user.
*
* @return the label
*/
public abstract String getLabel();
/**
* Returns the text for matching. (This may be a substring of what is returned by
* {@link OmniElement#getLabel()}.)
*
* @return the text for matching
*/
public String getMatchText() {
return getLabel();
}
/**
* Get the offset of the match text into the full label.
*
* @return match text offset
*/
public int getMatchTextOffset() {
//default is 0, assuming the entire label should be matched
return 0;
}
/**
* @return Returns a storable version of this element
*/
public OmniElement getMemento() {
return this;
}
/**
* @return Returns the provider.
*/
public OmniProposalProvider getProvider() {
return provider;
}
/**
* Return the label to be used for sorting and matching elements.
*
* @return the sort label
*/
public String getSortLabel() {
return getLabel();
}
/**
* Check if this element has been marked a duplicate (requiring disambiguation in the UI).
*/
public boolean isDuplicate() {
return duplicate;
}
/**
* Tests for equivalency ("equalness" without the contract of {@link Object#equals(Object)}.
*
* @param that the element to test against
* @return <code>true</code> if this element is the "same as" or "equivalent to" the other,
* <code>false</code> otherwise
*/
public boolean isSameAs(OmniElement that) {
if (that == null) {
return false;
}
if (this == that) {
return true;
}
if (this.getProvider() == that.getProvider()) {
return this.getLabel() == that.getLabel();
}
return false;
}
public OmniEntry match(String filter, OmniProposalProvider providerForMatching) {
String sortLabel = getMatchText();
filter = filter.toLowerCase();
int index = sortLabel.toLowerCase().indexOf(filter);
if (index != -1) {
index += getMatchTextOffset();
return new OmniEntry(this, providerForMatching, new int[][] {{
index, index + filter.length() - 1}}, EMPTY_INDICES);
}
//TODO (pquitslund): we are no longer combining provider and labels into filters
//with an eye towards more formal query support
//String combinedLabel = (providerForMatching.getName() + " " + getLabel()); //$NON-NLS-1$
String combinedLabel = (getMatchText()); //$NON-NLS-1$
index = combinedLabel.toLowerCase().indexOf(filter);
if (index != -1) {
int lengthOfElementMatch = index + filter.length() - providerForMatching.getName().length()
- 1;
if (lengthOfElementMatch > 0) {
return new OmniEntry(
this,
providerForMatching,
new int[][] {{0, lengthOfElementMatch - 1}},
new int[][] {{index, index + filter.length() - 1}});
}
return new OmniEntry(this, providerForMatching, EMPTY_INDICES, new int[][] {{
index, index + filter.length() - 1}});
}
String camelCase = CamelUtil.getCamelCase(sortLabel);
index = camelCase.indexOf(filter);
if (index != -1) {
int[][] indices = CamelUtil.getCamelCaseIndices(sortLabel, index, filter.length());
return new OmniEntry(this, providerForMatching, indices, EMPTY_INDICES);
}
String combinedCamelCase = CamelUtil.getCamelCase(combinedLabel);
index = combinedCamelCase.indexOf(filter);
if (index != -1) {
String providerCamelCase = CamelUtil.getCamelCase(providerForMatching.getName());
int lengthOfElementMatch = index + filter.length() - providerCamelCase.length();
if (lengthOfElementMatch > 0) {
return new OmniEntry(this, providerForMatching, CamelUtil.getCamelCaseIndices(
sortLabel,
0,
lengthOfElementMatch), CamelUtil.getCamelCaseIndices(
providerForMatching.getName(),
index,
filter.length() - lengthOfElementMatch));
}
return new OmniEntry(this, providerForMatching, EMPTY_INDICES, CamelUtil.getCamelCaseIndices(
providerForMatching.getName(),
index,
filter.length()));
}
return null;
}
/**
* Flag this element as a duplicate requiring disambiguation in the UI.
*/
public void setIsDuplicate(boolean isDuplicate) {
this.duplicate = isDuplicate;
}
protected abstract void doExecute(String text, UIInstrumentationBuilder instrumentation);
}