StyledCellLabelProvider with Nebula GridTableViewer

431 Views Asked by At

I have custom rendering needs when using a Nebula GridTableViewer. Is this something I can achieve using a StyledCellLabelProvider ? The following link seem to have a snippet but it's showing up for me as junk characters. Styledlabelprovider snippet

1

There are 1 best solutions below

3
On

/*******************************************************************************
 * 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 is not supported by nebula grid. https://www.eclipse.org/forums/index.php?t=msg&th=19535&goto=62677&

You will need to implement a CellRenderer.