StyledCellLabelProvider с Nebula GridTableViewer

У меня есть потребности в пользовательском рендеринге при использовании Nebula GridTableViewer. Это то, чего я могу добиться, используя StyledCellLabelProvider ? В следующей ссылке есть фрагмент, но он отображается для меня как ненужные символы. Фрагмент Styledlabelprovider


person ssdimmanuel    schedule 19.08.2015    source источник


Ответы (1)


/*******************************************************************************
 * Copyright (c) 2006 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    [email protected] - initial API and implementation
 *******************************************************************************/
package org.eclipse.nebula.jface.gridviewer;

import org.eclipse.jface.viewers.ColumnViewer;
import org.eclipse.jface.viewers.IBaseLabelProvider;
import org.eclipse.jface.viewers.StyledString;
import org.eclipse.jface.viewers.ViewerCell;
import org.eclipse.jface.viewers.ViewerColumn;
import org.eclipse.jface.viewers.ViewerRow;
import org.eclipse.jface.viewers.DelegatingStyledCellLabelProvider.IStyledLabelProvider;
import org.eclipse.nebula.widgets.grid.Grid;
import org.eclipse.nebula.widgets.grid.GridCellRenderer;
import org.eclipse.nebula.widgets.grid.GridItem;
import org.eclipse.nebula.widgets.grid.IInternalWidget;
import org.eclipse.nebula.widgets.grid.internal.BranchRenderer;
import org.eclipse.nebula.widgets.grid.internal.CheckBoxRenderer;
import org.eclipse.nebula.widgets.grid.internal.TextUtils;
import org.eclipse.nebula.widgets.grid.internal.ToggleRenderer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyleRange;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.graphics.TextLayout;

/**
 * The renderer for a cell in Grid.
 * 
 * @author [email protected]
 * @since 2.0.0
 */
public class StyledTextCellRenderer extends GridCellRenderer {

	int leftMargin = 4;

	int rightMargin = 4;

	int topMargin = 0;

	int bottomMargin = 0;

	int textTopMargin = 1;

	int textBottomMargin = 2;

	private int insideMargin = 3;

	int treeIndent = 20;

	private ToggleRenderer toggleRenderer;

	private BranchRenderer branchRenderer;

	private CheckBoxRenderer checkRenderer;

	private TextLayout textLayout;

	private GridTableViewer viewer;

	/**
	 * A new cell renderer instance able to deal with styled text information
	 * 
	 * @param viewer
	 *            the viewer
	 */
	public StyledTextCellRenderer(GridTableViewer viewer) {
		this.viewer = viewer;
	}

	/**
	 * {@inheritDoc}
	 */
	public void paint(GC gc, Object value) {
		GridItem item = (GridItem) value;

		gc.setFont(item.getFont(getColumn()));

		boolean drawAsSelected = isSelected();

		boolean drawBackground = true;

		if (isCellSelected()) {
			drawAsSelected = true;// (!isCellFocus());
		}

		if (drawAsSelected) {
			gc.setBackground(getDisplay().getSystemColor(
					SWT.COLOR_LIST_SELECTION));
			gc.setForeground(getDisplay().getSystemColor(
					SWT.COLOR_LIST_SELECTION_TEXT));
		} else {
			if (item.getParent().isEnabled()) {
				Color back = item.getBackground(getColumn());

				if (back != null) {
					gc.setBackground(back);
				} else {
					drawBackground = false;
				}
			} else {
				gc.setBackground(getDisplay().getSystemColor(
						SWT.COLOR_WIDGET_BACKGROUND));
			}
			gc.setForeground(item.getForeground(getColumn()));
		}

		if (drawBackground)
			gc.fillRectangle(getBounds().x, getBounds().y, getBounds().width,
					getBounds().height);

		int x = leftMargin;

		if (isTree()) {
			boolean renderBranches = item.getParent().getTreeLinesVisible();
			if (renderBranches) {
				branchRenderer.setBranches(getBranches(item));
				branchRenderer.setIndent(treeIndent);
				branchRenderer.setBounds(getBounds().x + x, getBounds().y,
						getToggleIndent(item), getBounds().height + 1); // Take
																		// into
																		// account
																		// border
			}

			x += getToggleIndent(item);

			toggleRenderer.setExpanded(item.isExpanded());

			toggleRenderer.setHover(getHoverDetail().equals("toggle"));

			toggleRenderer.setLocation(getBounds().x + x,
					(getBounds().height - toggleRenderer.getBounds().height)
							/ 2 + getBounds().y);
			if (item.hasChildren())
				toggleRenderer.paint(gc, null);

			if (renderBranches) {
				branchRenderer.setToggleBounds(toggleRenderer.getBounds());
				branchRenderer.paint(gc, null);
			}

			x += toggleRenderer.getBounds().width + insideMargin;

		}

		if (isCheck()) {
			checkRenderer.setChecked(item.getChecked(getColumn()));
			checkRenderer.setGrayed(item.getGrayed(getColumn()));
			if (!item.getParent().isEnabled()) {
				checkRenderer.setGrayed(true);
			}
			checkRenderer.setHover(getHoverDetail().equals("check"));

			if (isCenteredCheckBoxOnly(item)) {
				// Special logic if this column only has a checkbox and is
				// centered
				checkRenderer.setBounds(
						getBounds().x
								+ ((getBounds().width - checkRenderer
										.getBounds().width) / 2),
						(getBounds().height - checkRenderer.getBounds().height)
								/ 2 + getBounds().y,
						checkRenderer.getBounds().width, checkRenderer
								.getBounds().height);
			} else {
				checkRenderer.setBounds(getBounds().x + x,
						(getBounds().height - checkRenderer.getBounds().height)
								/ 2 + getBounds().y,
						checkRenderer.getBounds().width, checkRenderer
								.getBounds().height);

				x += checkRenderer.getBounds().width + insideMargin;
			}

			checkRenderer.paint(gc, null);
		}

		Image image = item.getImage(getColumn());
		if (image != null) {
			int y = getBounds().y;

			y += (getBounds().height - image.getBounds().height) / 2;

			gc.drawImage(image, getBounds().x + x, y);

			x += image.getBounds().width + insideMargin;
		}

		int width = getBounds().width - x - rightMargin;

		if (drawAsSelected) {
			gc.setForeground(getDisplay().getSystemColor(
					SWT.COLOR_LIST_SELECTION_TEXT));
		} else {
			gc.setForeground(item.getForeground(getColumn()));
		}

		IBaseLabelProvider lp = viewer.getLabelProvider(getColumn());
		
		if( lp instanceof IStyledLabelProvider ) {
			IStyledLabelProvider styledLp = (IStyledLabelProvider) lp;
			StyledString styledString = styledLp.getStyledText(item.getData());
			
			if (textLayout == null) {
				textLayout = new TextLayout(gc.getDevice());
				item.getParent().addDisposeListener(new DisposeListener() {
					public void widgetDisposed(DisposeEvent e) {
						textLayout.dispose();
					}
				});
			}
			
			StyleRange[] styleRanges = styledString.getStyleRanges();
			
			textLayout.setText(item.getText(getColumn()));
			textLayout.setFont(item.getFont(getColumn()));
			
			for (int i= 0; i < styleRanges.length; i++) {
				StyleRange curr = prepareStyleRange(styleRanges[i], true);
				textLayout.setStyle(curr, curr.start, curr.start + curr.length - 1);
			}
			
			textLayout.draw(gc, x, getBounds().y + textTopMargin + topMargin);
			
		} else if (!isWordWrap()) {
			String text = TextUtils.getShortString(gc, item
					.getText(getColumn()), width);

			if (getAlignment() == SWT.RIGHT) {
				int len = gc.stringExtent(text).x;
				if (len < width) {
					x += width - len;
				}
			} else if (getAlignment() == SWT.CENTER) {
				int len = gc.stringExtent(text).x;
				if (len < width) {
					x += (width - len) / 2;
				}
			}

			gc.drawString(text, getBounds().x + x, getBounds().y
					+ textTopMargin + topMargin, true);
		} else {
			if (textLayout == null) {
				textLayout = new TextLayout(gc.getDevice());
				item.getParent().addDisposeListener(new DisposeListener() {
					public void widgetDisposed(DisposeEvent e) {
						textLayout.dispose();
					}
				});
			}
			textLayout.setFont(gc.getFont());
			textLayout.setText(item.getText(getColumn()));
			textLayout.setAlignment(getAlignment());
			textLayout.setWidth(width < 1 ? 1 : width);

			textLayout.draw(gc, getBounds().x + x, getBounds().y
					+ textTopMargin + topMargin);
		}

		if (item.getParent().getLinesVisible()) {
			if (isCellSelected()) {
				// XXX: should be user definable?
				gc.setForeground(getDisplay().getSystemColor(
						SWT.COLOR_WIDGET_DARK_SHADOW));
			} else {
				gc.setForeground(item.getParent().getLineColor());
			}
			gc.drawLine(getBounds().x, getBounds().y + getBounds().height,
					getBounds().x + getBounds().width - 1, getBounds().y
							+ getBounds().height);
			gc.drawLine(getBounds().x + getBounds().width - 1, getBounds().y,
					getBounds().x + getBounds().width - 1, getBounds().y
							+ getBounds().height);
		}

		if (isCellFocus()) {
			Rectangle focusRect = new Rectangle(getBounds().x - 1,
					getBounds().y - 1, getBounds().width,
					getBounds().height + 1);

			gc.setForeground(getDisplay().getSystemColor(
					SWT.COLOR_LIST_FOREGROUND));
			gc.drawRectangle(focusRect);

			if (isFocus()) {
				focusRect.x++;
				focusRect.width -= 2;
				focusRect.y++;
				focusRect.height -= 2;

				gc.drawRectangle(focusRect);
			}
		}
	}
	
	private StyleRange prepareStyleRange(StyleRange styleRange, boolean applyColors) {
		// if no colors apply or font is set, create a clone and clear the
		// colors and font
		if (!applyColors && (styleRange.foreground != null || styleRange.background != null)) {
			styleRange = (StyleRange) styleRange.clone();
			if (!applyColors) {
				styleRange.foreground = null;
				styleRange.background = null;
			}
		}
		return styleRange;
	}

	/**
	 * Calculates the sequence of branch lines which should be rendered for the
	 * provided item
	 * 
	 * @param item
	 * @return an array of integers composed using the constants in
	 *         {@link BranchRenderer}
	 */
	private int[] getBranches(GridItem item) {
		int[] branches = new int[item.getLevel() + 1];
		GridItem[] roots = item.getParent().getRootItems();

		// Is this a node or a leaf?
		if (item.getParentItem() == null) {
			// Add descender if not last item
			if (!item.isExpanded() && roots[roots.length - 1].equals(item)) {
				if (item.hasChildren())
					branches[item.getLevel()] = BranchRenderer.LAST_ROOT;
				else
					branches[item.getLevel()] = BranchRenderer.SMALL_L;
			} else {
				if (item.hasChildren())
					branches[item.getLevel()] = BranchRenderer.ROOT;
				else
					branches[item.getLevel()] = BranchRenderer.SMALL_T;
			}

		} else if (item.hasChildren())
			if (item.isExpanded())
				branches[item.getLevel()] = BranchRenderer.NODE;
			else
				branches[item.getLevel()] = BranchRenderer.NONE;
		else
			branches[item.getLevel()] = BranchRenderer.LEAF;

		// Branch for current item
		GridItem parent = item.getParentItem();
		if (parent == null)
			return branches;

		// Are there siblings below this item?
		if (parent.indexOf(item) < parent.getItemCount() - 1)
			branches[item.getLevel() - 1] = BranchRenderer.T;

		// Is the next node a root?
		else if (parent.getParentItem() == null
				&& !parent.equals(roots[roots.length - 1]))
			branches[item.getLevel() - 1] = BranchRenderer.T;

		// This must be the last element at this level
		else
			branches[item.getLevel() - 1] = BranchRenderer.L;

		Grid grid = item.getParent();
		item = parent;
		parent = item.getParentItem();

		// Branches for parent items
		while (item.getLevel() > 0) {
			if (parent.indexOf(item) == parent.getItemCount() - 1) {
				if (parent.getParentItem() == null
						&& !grid.getRootItem(grid.getRootItemCount() - 1)
								.equals(parent))
					branches[item.getLevel() - 1] = BranchRenderer.I;
				else
					branches[item.getLevel() - 1] = BranchRenderer.NONE;
			} else
				branches[item.getLevel() - 1] = BranchRenderer.I;
			item = parent;
			parent = item.getParentItem();
		}
		// item should be null at this point
		return branches;
	}

	/**
	 * {@inheritDoc}
	 */
	public Point computeSize(GC gc, int wHint, int hHint, Object value) {
		GridItem item = (GridItem) value;

		gc.setFont(item.getFont(getColumn()));

		int x = 0;

		x += leftMargin;

		if (isTree()) {
			x += getToggleIndent(item);

			x += toggleRenderer.getBounds().width + insideMargin;

		}

		if (isCheck()) {
			x += checkRenderer.getBounds().width + insideMargin;
		}

		int y = 0;

		Image image = item.getImage(getColumn());
		if (image != null) {
			y = topMargin + image.getBounds().height + bottomMargin;

			x += image.getBounds().width + insideMargin;
		}

		// MOPR-DND
		// MOPR: replaced this code (to get correct preferred height for cells
		// in word-wrap columns)
		//
		// x += gc.stringExtent(item.getText(getColumn())).x + rightMargin;
		//
		// y = Math.max(y,topMargin + gc.getFontMetrics().getHeight() +
		// bottomMargin);
		//
		// with this code:

		int textHeight = 0;
		if (!isWordWrap()) {
			x += gc.textExtent(item.getText(getColumn())).x + rightMargin;

			textHeight = topMargin + textTopMargin
					+ gc.getFontMetrics().getHeight() + textBottomMargin
					+ bottomMargin;
		} else {
			int plainTextWidth;
			if (wHint == SWT.DEFAULT)
				plainTextWidth = gc.textExtent(item.getText(getColumn())).x;
			else
				plainTextWidth = wHint - x - rightMargin;

			TextLayout currTextLayout = new TextLayout(gc.getDevice());
			currTextLayout.setFont(gc.getFont());
			currTextLayout.setText(item.getText(getColumn()));
			currTextLayout.setAlignment(getAlignment());
			currTextLayout.setWidth(plainTextWidth < 1 ? 1 : plainTextWidth);

			x += plainTextWidth + rightMargin;

			textHeight += topMargin + textTopMargin;
			for (int cnt = 0; cnt < currTextLayout.getLineCount(); cnt++)
				textHeight += currTextLayout.getLineBounds(cnt).height;
			textHeight += textBottomMargin + bottomMargin;

			currTextLayout.dispose();
		}

		y = Math.max(y, textHeight);

		return new Point(x, y);
	}

	/**
	 * {@inheritDoc}
	 */
	public boolean notify(int event, Point point, Object value) {

		GridItem item = (GridItem) value;

		if (isCheck()) {
			if (event == IInternalWidget.MouseMove) {
				if (overCheck(item, point)) {
					setHoverDetail("check");
					return true;
				}
			}

			if (event == IInternalWidget.LeftMouseButtonDown) {
				if (overCheck(item, point)) {
					if (!item.getCheckable(getColumn())) {
						return false;
					}

					item.setChecked(getColumn(), !item.getChecked(getColumn()));
					item.getParent().redraw();

					item.fireCheckEvent(getColumn());

					return true;
				}
			}
		}

		if (isTree() && item.hasChildren()) {
			if (event == IInternalWidget.MouseMove) {
				if (overToggle(item, point)) {
					setHoverDetail("toggle");
					return true;
				}
			}

			if (event == IInternalWidget.LeftMouseButtonDown) {
				if (overToggle(item, point)) {
					item.setExpanded(!item.isExpanded());
					item.getParent().redraw();

					if (item.isExpanded()) {
						item.fireEvent(SWT.Expand);
					} else {
						item.fireEvent(SWT.Collapse);
					}

					return true;
				}
			}
		}

		return false;
	}

	private boolean overCheck(GridItem item, Point point) {
		if (isCenteredCheckBoxOnly(item)) {
			point = new Point(point.x, point.y);
			point.x -= getBounds().x;
			point.y -= getBounds().y;

			Rectangle checkBounds = new Rectangle(0, 0, 0, 0);
			checkBounds.x = (getBounds().width - checkRenderer.getBounds().width) / 2;
			checkBounds.y = ((getBounds().height - checkRenderer.getBounds().height) / 2);
			checkBounds.width = checkRenderer.getBounds().width;
			checkBounds.height = checkRenderer.getBounds().height;

			return checkBounds.contains(point);
		} else {
			point = new Point(point.x, point.y);
			point.x -= getBounds().x;
			point.y -= getBounds().y;

			int x = leftMargin;
			if (isTree()) {
				x += getToggleIndent(item);
				x += toggleRenderer.getSize().x + insideMargin;
			}

			if (point.x >= x && point.x < (x + checkRenderer.getSize().x)) {
				int yStart = ((getBounds().height - checkRenderer.getBounds().height) / 2);
				if (point.y >= yStart
						&& point.y < yStart + checkRenderer.getSize().y) {
					return true;
				}
			}

			return false;
		}
	}

	private int getToggleIndent(GridItem item) {
		return item.getLevel() * treeIndent;
	}

	private boolean overToggle(GridItem item, Point point) {

		point = new Point(point.x, point.y);

		point.x -= getBounds().x - 1;
		point.y -= getBounds().y - 1;

		int x = leftMargin;
		x += getToggleIndent(item);

		if (point.x >= x && point.x < (x + toggleRenderer.getSize().x)) {
			// return true;
			int yStart = ((getBounds().height - toggleRenderer.getBounds().height) / 2);
			if (point.y >= yStart
					&& point.y < yStart + toggleRenderer.getSize().y) {
				return true;
			}
		}

		return false;
	}

	/**
	 * {@inheritDoc}
	 */
	public void setTree(boolean tree) {
		super.setTree(tree);

		if (tree) {
			toggleRenderer = new ToggleRenderer();
			toggleRenderer.setDisplay(getDisplay());

			branchRenderer = new BranchRenderer();
			branchRenderer.setDisplay(getDisplay());
		}
	}

	/**
	 * {@inheritDoc}
	 */
	public void setCheck(boolean check) {
		super.setCheck(check);

		if (check) {
			checkRenderer = new CheckBoxRenderer();
			checkRenderer.setDisplay(getDisplay());
		} else {
			checkRenderer = null;
		}
	}

	/**
	 * {@inheritDoc}
	 */
	public Rectangle getTextBounds(GridItem item, boolean preferred) {
		int x = leftMargin;

		if (isTree()) {
			x += getToggleIndent(item);

			x += toggleRenderer.getBounds().width + insideMargin;

		}

		if (isCheck()) {
			x += checkRenderer.getBounds().width + insideMargin;
		}

		Image image = item.getImage(getColumn());
		if (image != null) {
			x += image.getBounds().width + insideMargin;
		}

		Rectangle bounds = new Rectangle(x, topMargin + textTopMargin, 0, 0);

		GC gc = new GC(item.getParent());
		gc.setFont(item.getFont(getColumn()));
		Point size = gc.stringExtent(item.getText(getColumn()));

		bounds.height = size.y;

		if (preferred) {
			bounds.width = size.x - 1;
		} else {
			bounds.width = getBounds().width - x - rightMargin;
		}

		gc.dispose();

		return bounds;
	}

	private boolean isCenteredCheckBoxOnly(GridItem item) {
		return !isTree() && item.getImage(getColumn()) == null
				&& item.getText(getColumn()).equals("")
				&& getAlignment() == SWT.CENTER;
	}
}

StyledCellLabelProvider не поддерживается сеткой туманности. https://www.eclipse.org/forums/index.php?t=msg&th=19535&goto=62677&

Вам нужно будет реализовать CellRenderer.

person user3174599    schedule 20.08.2015
comment
Это именно та ссылка, которую я вставил в свой вопрос. если у кого-то есть этот фрагмент, я хотел бы использовать его в качестве отправной точки - person ssdimmanuel; 21.08.2015
comment
извините, не увидел ссылку - person user3174599; 21.08.2015
comment
Я добавил класс к ответу, надеюсь, это поможет - person user3174599; 21.08.2015