/*=============================================================================# # Copyright (c) 2010-2016 Stephan Wahlbrink (WalWare.de) 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: # Stephan Wahlbrink - initial API and implementation #=============================================================================*/ package de.walware.statet.r.internal.ui.intable; import static de.walware.ecommons.waltable.painter.cell.GraphicsUtils.safe; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.graphics.GC; import de.walware.ecommons.waltable.config.CellConfigAttributes; import de.walware.ecommons.waltable.config.IConfigRegistry; import de.walware.ecommons.waltable.coordinate.LRectangle; import de.walware.ecommons.waltable.data.ControlData; import de.walware.ecommons.waltable.data.convert.IDisplayConverter; import de.walware.ecommons.waltable.layer.cell.ILayerCell; import de.walware.ecommons.waltable.painter.cell.AbstractTextPainter; import de.walware.ecommons.waltable.style.CellStyleAttributes; import de.walware.ecommons.waltable.style.CellStyleUtil; import de.walware.ecommons.waltable.style.HorizontalAlignment; import de.walware.ecommons.waltable.style.IStyle; import de.walware.ecommons.waltable.style.VerticalAlignmentEnum; import de.walware.ecommons.waltable.swt.SWTUtil; import de.walware.ecommons.waltable.util.GUIHelper; public class RTextPainter extends AbstractTextPainter { /** * Convert the data value of the cell using the {@link IDisplayConverter} from the {@link IConfigRegistry} */ private static Object getData(final ILayerCell cell, final IConfigRegistry configRegistry) { final IDisplayConverter displayConverter= configRegistry.getConfigAttribute( CellConfigAttributes.DISPLAY_CONVERTER, cell.getDisplayMode(), cell.getConfigLabels().getLabels() ); return (displayConverter != null) ? displayConverter.canonicalToDisplayValue(cell, configRegistry, cell.getDataValue(0, null)) : EMPTY; } private final StringBuilder tempText= new StringBuilder(); private String currentText; private int currentTextWidth; public RTextPainter(final int space) { super(false, true, space, false, false, SWT.DRAW_TRANSPARENT); } @Override public long getPreferredWidth(final ILayerCell cell, final GC gc, final IConfigRegistry configRegistry){ final Object data= getData(cell, configRegistry); setupGCFromConfig(gc, CellStyleUtil.getCellStyle(cell, configRegistry), data); return getWidthFromCache(gc, data.toString()) + (this.spacing * 2); } @Override public long getPreferredHeight(final ILayerCell cell, final GC gc, final IConfigRegistry configRegistry) { final Object data= getData(cell, configRegistry); setupGCFromConfig(gc, CellStyleUtil.getCellStyle(cell, configRegistry), data); // return gc.textExtent(data.toString(), swtDrawStyle).y; return gc.getFontMetrics().getHeight(); } protected void setupGCFromConfig(final GC gc, final IStyle cellStyle, final Object data) { Color fg= cellStyle.getAttributeValue(CellStyleAttributes.FOREGROUND_COLOR); if (fg == null) { fg= GUIHelper.COLOR_LIST_FOREGROUND; } // Color bg= cellStyle.getAttributeValue(CellStyleAttributes.BACKGROUND_COLOR); // if (bg == null) { // bg= GUIHelper.COLOR_LIST_BACKGROUND; // } Font font; if ((!(data instanceof ControlData)) || (font= cellStyle.getAttributeValue(CellStyleAttributes.CONTROL_FONT)) == null) { font= cellStyle.getAttributeValue(CellStyleAttributes.FONT); } // gc.setAntialias(SWT.DEFAULT); gc.setTextAntialias(SWT.DEFAULT); gc.setFont(font); gc.setForeground(fg); // gc.setBackground(bg); } @Override public void paintCell(final ILayerCell cell, final GC gc, final LRectangle lRectangle, final IConfigRegistry configRegistry) { if (this.paintBg) { super.paintCell(cell, gc, lRectangle, configRegistry); } final org.eclipse.swt.graphics.Rectangle originalClipping= gc.getClipping(); gc.setClipping(SWTUtil.toSWT(lRectangle).intersection(originalClipping)); final Object data= getData(cell, configRegistry); final IStyle cellStyle= CellStyleUtil.getCellStyle(cell, configRegistry); setupGCFromConfig(gc, cellStyle, data); // Draw Text String text= data.toString(); final long width= lRectangle.width - (this.spacing * 2); // if (text.length() > width * 4) { // text= text.substring(0, width * 4); // } if (gc.getFont() == null) { gc.setFont(null); } // first get height because https://bugs.eclipse.org/bugs/show_bug.cgi?id=319125 final int contentHeight= gc.getFontMetrics().getHeight(); text= getTextToDisplay(cell, gc, width, text); final int contentWidth= getWidthFromCache(gc, text); gc.drawText( text, safe(lRectangle.x + this.spacing + CellStyleUtil.getHorizontalAlignmentPadding( (data instanceof ControlData) ? HorizontalAlignment.LEFT : cellStyle.getAttributeValue(CellStyleAttributes.HORIZONTAL_ALIGNMENT), width, contentWidth )), safe(lRectangle.y + CellStyleUtil.getVerticalAlignmentPadding(VerticalAlignmentEnum.MIDDLE, lRectangle.height, contentHeight )), this.swtDrawStyle ); gc.setClipping(originalClipping); } private void createCurrentTextToDisplay(final GC gc, final int width, final String originalText) { int textWidth= getWidthFromCache(gc, originalText); if (textWidth <= width + 1) { this.currentText= originalText; this.currentTextWidth= textWidth; return; } int textLength= originalText.length(); int tooLong; String shortedText; do { tooLong= textLength; textLength -= Math.max((width + 1 - textWidth) / gc.getFontMetrics().getAverageCharWidth(), 1 ); if (textLength <= 0) { textLength= 0; shortedText= EMPTY; break; } this.tempText.setLength(0); this.tempText.append(originalText.substring(0, textLength)); this.tempText.append(DOT); shortedText= this.tempText.toString(); textWidth= getWidthFromCache(gc, shortedText); } while (textWidth > width + 1); this.currentText= shortedText; this.currentTextWidth= textWidth; while (++textLength < tooLong) { this.tempText.setLength(0); this.tempText.append(originalText.substring(0, textLength)); this.tempText.append(DOT); shortedText= this.tempText.toString(); textWidth= getWidthFromCache(gc, shortedText); if (textWidth <= width + 1) { this.currentText= shortedText; this.currentTextWidth= textWidth; } else { return; } } } }