/*
* 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.DartToolsPlugin;
import com.google.dart.tools.ui.omni.elements.HeaderElement;
import com.google.dart.tools.ui.omni.elements.TypeProvider_OLD.SearchInProgressPlaceHolder;
import com.google.dart.tools.ui.themes.Fonts;
import org.eclipse.jface.resource.DeviceResourceException;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.resource.ResourceManager;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.graphics.TextLayout;
import org.eclipse.swt.graphics.TextStyle;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.ui.internal.IWorkbenchGraphicConstants;
import org.eclipse.ui.internal.WorkbenchImages;
/**
* Abstract base class of omnibox entries.
*/
@SuppressWarnings("restriction")
public class OmniEntry {
boolean firstInCategory;
boolean lastInCategory;
OmniElement element;
OmniProposalProvider provider;
int[][] elementMatchRegions;
int[][] providerMatchRegions;
public OmniEntry(OmniElement element, OmniProposalProvider provider, int[][] elementMatchRegions,
int[][] providerMatchRegions) {
this.element = element;
this.provider = provider;
this.elementMatchRegions = elementMatchRegions;
this.providerMatchRegions = providerMatchRegions;
}
public void erase(Event event) {
// We are only custom drawing the foreground.
event.detail &= ~SWT.FOREGROUND;
}
public OmniElement getElement() {
return element;
}
public void measure(Event event, TextLayout textLayout, ResourceManager resourceManager,
TextStyle boldStyle) {
Table table = ((TableItem) event.item).getParent();
textLayout.setFont(table.getFont());
event.width = 0;
switch (event.index) {
case 0:
textLayout.setText(""); //$NON-NLS-1$
break;
case 1:
Image image = getImage(element, resourceManager);
Rectangle imageRect = image.getBounds();
event.width += imageRect.width + 4;
event.height = Math.max(event.height, imageRect.height + 2);
textLayout.setText(element.getLabel());
if (boldStyle != null) {
for (int i = 0; i < elementMatchRegions.length; i++) {
int[] matchRegion = elementMatchRegions[i];
textLayout.setStyle(boldStyle, matchRegion[0], matchRegion[1]);
}
}
break;
}
Rectangle rect = textLayout.getBounds();
event.width += rect.width + 4;
event.height = Math.max(event.height, rect.height + 2);
}
public void paint(Event event, TextLayout textLayout, ResourceManager resourceManager,
TextStyle boldStyle, TextStyle grayStyle) {
final Table table = ((TableItem) event.item).getParent();
if (element instanceof SearchInProgressPlaceHolder) {
textLayout.setFont(Fonts.getItalicFont(table.getFont()));
} else {
textLayout.setFont(table.getFont());
}
switch (event.index) {
case 0:
break;
case 1:
String label = element.getLabel();
Image image = null;
int xNudge = 1;
if (!(element instanceof HeaderElement)) {
xNudge = 9; //indent
image = getImage(element, resourceManager);
event.gc.drawImage(image, event.x + xNudge, event.y + 1);
} else {
//a lighter gray
event.gc.setForeground(OmniBoxColors.SEARCH_ENTRY_HEADER_TEXT);
}
textLayout.setText(label);
//match emphasis
if (boldStyle != null) {
for (int i = 0; i < elementMatchRegions.length; i++) {
int[] matchRegion = elementMatchRegions[i];
textLayout.setStyle(boldStyle, matchRegion[0], matchRegion[1]);
}
}
//details emphasis
if (grayStyle != null) {
int detailOffset = element.getDetailOffset();
if (detailOffset != -1) {
textLayout.setStyle(grayStyle, detailOffset, label.length() - 1);
}
}
Rectangle availableBounds = ((TableItem) event.item).getTextBounds(event.index);
Rectangle requiredBounds = textLayout.getBounds();
int imageWidth = image == null ? 0 : image.getBounds().width;
textLayout.draw(event.gc, availableBounds.x + xNudge + imageWidth, availableBounds.y
+ (availableBounds.height - requiredBounds.height) / 2);
break;
}
if (lastInCategory) {
//a lighter gray
event.gc.setForeground(OmniBoxColors.SEARCH_ENTRY_HEADER_TEXT);
Rectangle bounds = ((TableItem) event.item).getBounds(event.index);
event.gc.drawLine(Math.max(0, bounds.x - 1), bounds.y + bounds.height, bounds.x
+ bounds.width, bounds.y + bounds.height);
}
}
Image getImage(OmniElement element, ResourceManager resourceManager) {
Image image = findOrCreateImage(element.getImageDescriptor(), resourceManager);
if (image == null) {
//TODO (pquitslund): replace with a new "generic node" image
image = WorkbenchImages.getImage(IWorkbenchGraphicConstants.IMG_OBJ_ELEMENT);
}
return image;
}
private Image findOrCreateImage(ImageDescriptor imageDescriptor, ResourceManager resourceManager) {
if (imageDescriptor == null) {
return null;
}
Image image = (Image) resourceManager.find(imageDescriptor);
if (image == null) {
try {
image = resourceManager.createImage(imageDescriptor);
} catch (DeviceResourceException e) {
DartToolsPlugin.log(e);
}
}
return image;
}
}