/* * Copyright (c) 2017, MGrossmann * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the jo-widgets.org nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL jo-widgets.org BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. */ package org.jowidgets.nattable.impl.plugin; import org.eclipse.nebula.widgets.nattable.NatTable; import org.eclipse.nebula.widgets.nattable.config.CellConfigAttributes; import org.eclipse.nebula.widgets.nattable.layer.cell.ILayerCell; import org.eclipse.nebula.widgets.nattable.painter.cell.AbstractTextPainter; import org.eclipse.nebula.widgets.nattable.painter.cell.ICellPainter; import org.eclipse.nebula.widgets.nattable.style.CellStyleAttributes; import org.eclipse.nebula.widgets.nattable.style.CellStyleUtil; import org.eclipse.nebula.widgets.nattable.style.DisplayMode; import org.eclipse.nebula.widgets.nattable.style.IStyle; import org.eclipse.nebula.widgets.nattable.tooltip.NatTableContentTooltip; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Shell; import org.jowidgets.common.model.ITableCell; import org.jowidgets.common.model.ITableColumnModelSpi; import org.jowidgets.common.model.ITableColumnSpi; import org.jowidgets.common.model.ITableDataModel; import org.jowidgets.common.types.Markup; import org.jowidgets.nattable.impl.plugin.painter.CellPainterFactory; import org.jowidgets.spi.impl.swt.common.util.FontProvider; import org.jowidgets.util.Assert; import org.jowidgets.util.EmptyCheck; final class NatTableTooltip extends NatTableContentTooltip { private static final String NEW_LINE_REGEX = AbstractTextPainter.NEW_LINE_REGEX; private static final int MAX_CELL_TEXT_TOOLTIP_LENGTH = 2500; private static final int PADDING = CellPainterFactory.CELL_PADDING * 2; private static final int Y_OFFSET = 18; private final ITableDataModel dataModel; private final ITableColumnModelSpi columnModel; private final Shell dummyShell; private final GC graphicContext; NatTableTooltip( final NatTable natTable, final ITableDataModel dataModel, final ITableColumnModelSpi columnModel, final String... tooltipRegions) { super(natTable, tooltipRegions); Assert.paramNotNull(dataModel, "dataModel"); Assert.paramNotNull(columnModel, "columnModel"); this.dataModel = dataModel; this.columnModel = columnModel; this.dummyShell = new Shell(SWT.NONE); this.graphicContext = new GC(new Label(dummyShell, SWT.NONE)); setShift(new Point(0, Y_OFFSET)); } @Override protected String getText(final Event event) { final int col = natTable.getColumnPositionByX(event.x); final int row = natTable.getRowPositionByY(event.y); final ILayerCell cell = natTable.getCellByPosition(col, row); if (cell != null) { // if the registered cell painter is the PasswordCellPainter, there // will be no tooltip final ICellPainter painter = natTable.getConfigRegistry().getConfigAttribute( CellConfigAttributes.CELL_PAINTER, DisplayMode.NORMAL, cell.getConfigLabels().getLabels()); if (isVisibleContentPainter(painter)) { return getToolTipText(event); } } return null; } private String getToolTipText(final Event event) { final int rowPosition = natTable.getRowPositionByY(event.y); final int columnPosition = natTable.getColumnPositionByX(event.x); final int rowIndex = natTable.getRowIndexByPosition(rowPosition); final int columnIndex = natTable.getColumnIndexByPosition(columnPosition); if (rowPosition == 0 && rowIndex >= 0 && columnIndex >= 0) { return getColumnToolTipText(columnIndex); } else if (rowIndex >= 0 && columnIndex >= 0) { return getCellToolTipText(rowPosition, columnPosition, rowIndex, columnIndex); } return null; } private String getCellToolTipText( final int rowPosition, final int columnPosition, final int rowIndex, final int columnIndex) { final ITableCell tableCell = dataModel.getCell(rowIndex, columnIndex); if (tableCell != null) { final String result = tableCell.getToolTipText(); if (!EmptyCheck.isEmpty(result)) { return result; } else { return getTooltipTextIfCellTextTruncated(tableCell, rowPosition, columnPosition, rowIndex, columnIndex); } } return null; } private String getTooltipTextIfCellTextTruncated( final ITableCell tableCell, final int rowPosition, final int columnPosition, final int rowIndex, final int columnIndex) { //at the moment this feature is only supported if no icons are used in the cell if (!EmptyCheck.isEmpty(tableCell.getText()) && tableCell.getIcon() == null) { final ILayerCell layerCell = natTable.getCellByPosition(columnPosition, rowPosition); if (layerCell != null) { return getTooltipTextIfCellTextTruncated(tableCell, layerCell); } } return null; } private String getTooltipTextIfCellTextTruncated(final ITableCell tableCell, final ILayerCell layerCell) { final String cellText = getCellText(tableCell); final IStyle style = CellStyleUtil.getCellStyle(layerCell, natTable.getConfigRegistry()); final Font font = getFont(tableCell, style); graphicContext.setFont(font); final int border = 1;//remove the border final int innerCellWidth = layerCell.getBounds().width - border; final int textWidth = graphicContext.textExtent(cellText).x + PADDING; if (textWidth > innerCellWidth) { return cellText; } else { return null; } } private String getCellText(final ITableCell tableCell) { String result = tableCell.getText(); if (!EmptyCheck.isEmpty(result)) { result = result.replaceAll(NEW_LINE_REGEX, "").trim(); if (result.length() > MAX_CELL_TEXT_TOOLTIP_LENGTH) { result = result.substring(0, MAX_CELL_TEXT_TOOLTIP_LENGTH); } } return result; } private Font getFont(final ITableCell cell, final IStyle style) { final Font result = style.getAttributeValue(CellStyleAttributes.FONT); final Markup markup = cell.getMarkup(); if (markup != null && !Markup.DEFAULT.equals(markup)) { return FontProvider.deriveFont(result, markup); } else { return result; } } private String getColumnToolTipText(final int columnIndex) { final ITableColumnSpi column = columnModel.getColumn(columnIndex); if (column != null) { return column.getToolTipText(); } else { return null; } } void dispose() { graphicContext.dispose(); dummyShell.dispose(); } }