Java tutorial
/* * Copyright (C) 2017 Google Inc. * * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0 * * 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.gapid.widgets; import com.google.gapid.views.Formatter.LinkableStyledString; import com.google.gapid.views.Formatter.StylingString; import org.eclipse.jface.viewers.ColumnViewer; import org.eclipse.jface.viewers.StyledCellLabelProvider; import org.eclipse.jface.viewers.StyledString; import org.eclipse.jface.viewers.ViewerCell; import org.eclipse.swt.custom.StyleRange; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.graphics.TextLayout; import org.eclipse.swt.widgets.Widget; import java.util.Arrays; /** * A {@link StyledCellLabelProvider} that can be used to measure the size of the label to correctly * determine if the the mouse pointer is hovering over a link in the {@link StylingString}. */ public abstract class MeasuringViewLabelProvider extends StyledCellLabelProvider { private final ColumnViewer viewer; private final Theme theme; private final TextLayout layout; public MeasuringViewLabelProvider(ColumnViewer viewer, Theme theme) { this.viewer = viewer; this.theme = theme; this.layout = new TextLayout(viewer.getControl().getDisplay()); } @Override public void dispose() { super.dispose(); layout.dispose(); } @Override public void update(ViewerCell cell) { // Adjusted from the DelegatingStyledCellLabelProvider implementation. StyledString styledString = format(cell.getItem(), cell.getElement(), LinkableStyledString.ignoring(theme)) .getString(); String newText = styledString.toString(); StyleRange[] oldStyleRanges = cell.getStyleRanges(); StyleRange[] newStyleRanges = styledString.getStyleRanges(); if (!Arrays.equals(oldStyleRanges, newStyleRanges)) { cell.setStyleRanges(newStyleRanges); if (cell.getText().equals(newText)) { cell.setText(""); } } Color bgcolor = getBackgroundColor(cell.getElement()); if (bgcolor != null) { cell.setBackground(bgcolor); } cell.setImage(getImage(cell.getElement())); cell.setText(newText); } protected Image getImage(@SuppressWarnings("unused") Object element) { return null; } protected Color getBackgroundColor(@SuppressWarnings("unused") Object element) { return null; } protected abstract <S extends StylingString> S format(Widget item, Object element, S string); public Object getFollow(Point point) { ViewerCell cell = viewer.getCell(point); if (cell == null || !isFollowable(cell.getElement())) { return null; } LinkableStyledString string = format(cell.getItem(), cell.getElement(), LinkableStyledString.create(theme)); string.endLink(); string.append("dummy", string.defaultStyle()); updateLayout(cell, string.getString()); Rectangle bounds = cell.getTextBounds(); int offset = layout.getOffset(point.x - bounds.x, point.y - bounds.y, null); return string.getLinkTarget(offset); } protected abstract boolean isFollowable(Object element); private void updateLayout(ViewerCell cell, StyledString string) { // Adjusted from similar method from super class. layout.setStyle(null, 0, Integer.MAX_VALUE); layout.setText(string.toString()); for (StyleRange range : cell.getStyleRanges()) { layout.setStyle(range, range.start, range.start + range.length - 1); } } }