package org.gudy.azureus2.ui.swt.views.table.impl; import java.util.Random; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.*; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.SystemTime; import org.gudy.azureus2.plugins.ui.tables.TableColumn; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.components.BufferedGraphicTableItem; import org.gudy.azureus2.ui.swt.components.BufferedTableItem; import org.gudy.azureus2.ui.swt.components.InPaintInfo; import org.gudy.azureus2.ui.swt.shells.GCStringPrinter; import org.gudy.azureus2.ui.swt.views.table.*; import org.gudy.azureus2.ui.swt.views.table.utils.TableColumnSWTUtils; import com.aelitis.azureus.ui.common.table.TableColumnCore; import com.aelitis.azureus.ui.swt.utils.ColorCache; import com.aelitis.azureus.ui.swt.utils.FontUtils; public class TableViewSWT_PaintItem implements Listener { Widget lastItem; int lastRowIndex = -1; private final TableOrTreeSWT table; private TableViewSWTImpl<?> tv; private boolean bSkipFirstColumn; public TableViewSWT_PaintItem(TableViewSWTImpl<?> tv, TableOrTreeSWT table) { this.table = table; this.tv = tv; } private int[] getColumnRange(TableItemOrTreeItem ti, int iMouseX, int width) { int[] columnRange = { -1, -1 }; int numColumns = table.getColumnCount(); if (numColumns <= 0) { return columnRange; } for (int i = bSkipFirstColumn ? 1 : 0; i < numColumns; i++) { Rectangle cellBounds = ti.getBounds(i); if (iMouseX >= cellBounds.x && iMouseX < cellBounds.x + cellBounds.width && cellBounds.width > 0) { columnRange[0] = i; break; } } if (columnRange[0] == -1) { return columnRange; } if (columnRange[0] + 1 == numColumns) { columnRange[1] = columnRange[0]; } else { int end = iMouseX + width; for (int i = columnRange[0] + 1; i < numColumns; i++) { Rectangle cellBounds = ti.getBounds(i); //System.out.println(cellBounds + ";" + end); if (cellBounds.x > end && cellBounds.width > 0) { columnRange[1] = i - 1; break; } } if (columnRange[1] == -1) { columnRange[1] = numColumns - 1; } } return columnRange; } public void handleEvent(Event event) { if (event.gc.getClipping().isEmpty()) { return; } if (!table.isEnabled()) { // added disable affect event.gc.setAlpha(100); } if (event.type == SWT.Paint) { int numPainted = 0; //Color fg = event.gc.getForeground(); //Color bg = event.gc.getBackground(); Region r = new Region(); event.gc.getClipping(r); //System.out.println(r.contains(event.x, event.y)); //event.gc.setForeground(ColorCache.getRandomColor()); //event.gc.drawRectangle(event.x, event.y, event.width - 1, event.height - 1); //event.gc.setForeground(fg); // paint only gets bounds, gotta fill event.item and event.index TableItemOrTreeItem item = table.getItem(new Point(5, event.y)); if (item == null) { return; } event.item = item.getItem(); int[] columnRange = getColumnRange(item, event.x, event.width); if (columnRange[0] == -1) { return; } //int height = tv.getRowDefaultHeight(); //System.out.println("Dirty: " + event.getBounds() + "; +" + height + "; " + event.gc.getClipping()); for (int i = columnRange[0]; i <= columnRange[1]; i++) { event.index = i; for (int y = event.y; y < (event.y + event.height); y += item.getBounds().height) { item = table.getItem(new Point(5, y)); if (item == null) { break; } Rectangle bounds = item.getBounds(i); if (!r.intersects(bounds)) { //event.gc.setForeground(ColorCache.getRandomColor()); //event.gc. continue; } event.item = item.getItem(); //System.out.println(table.indexOf(event.item) + ": " + i); table.setData("inPaintInfo", new InPaintInfo(item.getItem(), event.index, bounds)); if (event.item != lastItem) { table.setData("lastIndex", null); lastRowIndex = table.indexOf(event.item); table.setData("lastIndex", lastRowIndex); } boolean doErase = true; if (Constants.isWindows7OrHigher) { Point location = table.toControl(event.display.getCursorLocation()); if (location.y >= bounds.y && location.y < bounds.y + bounds.height) { doErase = false; } } Font f = event.gc.getFont(); if (doErase) { //TableItemOrTreeItem item = TableOrTreeUtils.getEventItem(event.item); TableViewSWT_EraseItem.eraseItem(event, event.gc, item, event.index, true, bounds, tv, true); } //TableItemOrTreeItem item = TableOrTreeUtils.getEventItem(event.item); paintItem(event.gc, (TableRowSWT) tv.getRow(item), event.index, lastRowIndex, bounds, tv, false); event.gc.setFont(f); event.gc.setClipping(r); numPainted++; lastItem = event.item; } } //System.out.println("# Painted:" + numPainted); } else { TableItemOrTreeItem item = TableOrTreeUtils.getEventItem(event.item); Rectangle bounds = item.getBounds(event.index); table.setData("inPaintInfo", new InPaintInfo((Item) event.item, event.index, bounds)); if (event.item != lastItem) { table.setData("lastIndex", null); lastRowIndex = table.indexOf(event.item); table.setData("lastIndex", lastRowIndex); } //visibleRowsChanged(); paintItem(event.gc, (TableRowSWT) tv.getRow(item), event.index, lastRowIndex, bounds, tv, false); lastItem = event.item; } table.setData("inPaintInfo", null); table.setData("lastIndex", null); } /** * @param event * @param rowIndex */ public static void paintItem(GC gc, TableRowSWT row, int columnIndex, int rowIndex, Rectangle _cellBounds, TableViewSWT<?> tv, boolean skipClipCalc) { //if (columnIndex == 1 && rowIndex == 0) { // System.out.println("paintItem " + gc.getClipping() +":" + rowIndex + ":" + columnIndex + ": " + Debug.getCompressedStackTrace()); //} try { //System.out.println(gc.getForeground().getRGB().toString()); //System.out.println("paintItem " + gc.getClipping()); if (TableViewSWTImpl.DEBUG_CELL_CHANGES) { Random random = new Random(SystemTime.getCurrentTime() / 500); gc.setBackground(ColorCache.getColor(gc.getDevice(), 210 + random.nextInt(45), 210 + random.nextInt(45), 210 + random.nextInt(45))); gc.fillRectangle(gc.getClipping()); } if (row == null || row.isRowDisposed()) { return; } int iColumnNo = columnIndex; //System.out.println(SystemTime.getCurrentTime() + "] paintItem " + rowIndex + ":" + iColumnNo); if ((tv instanceof TableViewSWTImpl) && ((TableViewSWTImpl)tv).bSkipFirstColumn) { if (iColumnNo == 0) { return; } iColumnNo--; } TableColumnCore[] columnsOrdered = tv.getVisibleColumns(); if (iColumnNo >= columnsOrdered.length) { System.out.println("Col #" + iColumnNo + " >= " + columnsOrdered.length + " count"); return; } if (!tv.isColumnVisible(columnsOrdered[iColumnNo])) { System.out.println("col not visible " + iColumnNo); return; } //if (rowIndex < tv.lastTopIndex || rowIndex > tv.lastBottomIndex) { // this refreshes whole row (perhaps multiple), saving the many // cell.refresh calls later because !cell.isUpToDate() //tv.visibleRowsChanged(); //} Rectangle cellBounds = new Rectangle(_cellBounds.x, _cellBounds.y, _cellBounds.width, _cellBounds.height); // item.getBounds(columnIndex); //System.out.println("cb=" + cellBounds + ";b=" + event.getBounds() + ";clip=" + gc.getClipping()); Rectangle origClipping = gc.getClipping(); TableOrTreeSWT table = tv.getTableOrTreeSWT(); if (table != null) { if (origClipping.isEmpty() || (origClipping.width >= cellBounds.width && origClipping.height >= cellBounds.height)) { table.setData("fullPaint", Boolean.TRUE); } else { table.setData("fullPaint", Boolean.FALSE); //System.out.println("not full paint: " + origClipping + ";cellbounds=" + cellBounds); } } if (!tv.isRowVisible(row)) { tv.visibleRowsChanged(); } tv.invokePaintListeners(gc, row, columnsOrdered[iColumnNo], cellBounds); int rowAlpha = row.getAlpha(); int fontStyle = row.getFontStyle(); if (fontStyle == SWT.BOLD) { gc.setFont(FontUtils.getAnyFontBold(gc)); } //if (item.getImage(columnIndex) != null) { // cellBounds.x += 18; // cellBounds.width -= 18; //} if (cellBounds.width <= 0 || cellBounds.height <= 0) { //System.out.println("no bounds"); return; } TableCellSWT cell = row.getTableCellSWT(columnsOrdered[iColumnNo].getName()); if (cell == null) { return; } if (!cell.isUpToDate()) { //System.out.println("R " + rowIndex + ":" + iColumnNo); cell.refresh(true, true); //return; } String text = cell.getText(); if (!skipClipCalc) { Rectangle clipping = new Rectangle(cellBounds.x, cellBounds.y, cellBounds.width, cellBounds.height); // Cocoa calls paintitem while row is below tablearea, and painting there // is valid! if (!Utils.isCocoa && (tv instanceof TableViewSWTImpl)) { int iMinY = ((TableViewSWTImpl) tv).headerHeight + ((TableViewSWTImpl) tv).clientArea.y; if (clipping.y < iMinY) { clipping.height -= iMinY - clipping.y; clipping.y = iMinY; } int iMaxY = ((TableViewSWTImpl) tv).clientArea.height + ((TableViewSWTImpl) tv).clientArea.y; if (clipping.y + clipping.height > iMaxY) { clipping.height = iMaxY - clipping.y + 1; } } if (clipping.width <= 0 || clipping.height <= 0) { //System.out.println(row.getIndex() + " clipping="+clipping + ";" ); return; } if (!origClipping.contains(clipping.x, clipping.y) || !origClipping.contains(clipping.x + clipping.width - 1, clipping.y + clipping.height - 1)) { gc.setClipping(clipping); } } if (rowAlpha < 255) { gc.setAlpha(rowAlpha); } if (cell.needsPainting()) { Image graphicSWT = cell.getGraphicSWT(); if (graphicSWT != null && !graphicSWT.isDisposed()) { int marginWidth = cell.getMarginWidth(); int marginHeight = cell.getMarginHeight(); Rectangle graphicBounds = new Rectangle(cellBounds.x + marginWidth, cellBounds.y + marginHeight, cellBounds.width - (marginWidth * 2), cellBounds.height - (marginHeight * 2)); Rectangle imageBounds = graphicSWT.getBounds(); BufferedTableItem bufferedTableItem = null; if (cell instanceof TableCellImpl) { bufferedTableItem = ((TableCellImpl) cell).getBufferedTableItem(); } if (bufferedTableItem instanceof BufferedGraphicTableItem) { BufferedGraphicTableItem ti = (BufferedGraphicTableItem) bufferedTableItem; int orientation = ti.getOrientation(); if (orientation == SWT.FILL) { if (!graphicBounds.isEmpty()) { gc.setAdvanced(true); //System.out.println(imageBounds + ";" + graphicBounds); gc.drawImage(graphicSWT, 0, 0, imageBounds.width, imageBounds.height, graphicBounds.x, graphicBounds.y, graphicBounds.width, graphicBounds.height); } } else { if (imageBounds.width < graphicBounds.width) { if (orientation == SWT.CENTER) { graphicBounds.x += (graphicBounds.width - imageBounds.width) / 2; } else if (orientation == SWT.RIGHT) { graphicBounds.x = (graphicBounds.x + graphicBounds.width) - imageBounds.width; } } if (imageBounds.height < graphicBounds.height) { graphicBounds.y += (graphicBounds.height - imageBounds.height) / 2; } gc.drawImage(graphicSWT, graphicBounds.x, graphicBounds.y); } } else { gc.drawImage(graphicSWT, graphicBounds.x, graphicBounds.y); } } cell.doPaint(gc); } if (text.length() > 0) { int ofsx = 0; Image image = cell.getIcon(); Rectangle imageBounds = null; if (image != null && !image.isDisposed()) { imageBounds = image.getBounds(); int ofs = imageBounds.width; ofsx += ofs; cellBounds.x += ofs; cellBounds.width -= ofs; } //System.out.println("PS " + rowIndex + ";" + cellBounds + ";" + cell.getText()); int style = TableColumnSWTUtils.convertColumnAlignmentToSWT(columnsOrdered[iColumnNo].getAlignment()); if (cellBounds.height > 20) { style |= SWT.WRAP; } int textOpacity = cell.getTextAlpha(); if (textOpacity < 255) { gc.setTextAntialias(SWT.ON); gc.setAlpha(textOpacity); } else if (textOpacity > 255) { gc.setFont(FontUtils.getAnyFontBold(gc)); gc.setTextAntialias(SWT.ON); gc.setAlpha(textOpacity & 255); } // put some padding on text ofsx += 6; cellBounds.x += 3; cellBounds.width -= 6; cellBounds.y += 2; cellBounds.height -= 4; if (!cellBounds.isEmpty()) { GCStringPrinter sp = new GCStringPrinter(gc, text, cellBounds, true, cellBounds.height > 20, style); boolean fit = sp.printString(); if (fit) { cell.setDefaultToolTip(null); } else { cell.setDefaultToolTip(text); } Point size = sp.getCalculatedSize(); size.x += ofsx; TableColumn tableColumn = cell.getTableColumn(); if (tableColumn != null && tableColumn.getPreferredWidth() < size.x) { tableColumn.setPreferredWidth(size.x); } if (imageBounds != null) { int drawToY = cellBounds.y + (cellBounds.height / 2) - (imageBounds.height / 2); boolean hack_adv = Constants.isWindows8OrHigher && gc.getAdvanced(); if ( hack_adv ){ // problem with icon transparency on win8 gc.setAdvanced( false ); } if ((style & SWT.RIGHT) != 0) { int drawToX = cellBounds.x + cellBounds.width - size.x; gc.drawImage(image, drawToX, drawToY); } else { gc.drawImage(image, cellBounds.x - imageBounds.width - 3, drawToY); } if ( hack_adv ){ gc.setAdvanced( true ); } } } else { cell.setDefaultToolTip(null); } } if (cell instanceof TableCellSWTBase) { ((TableCellSWTBase) cell).clearVisuallyChangedSinceRefresh(); } } catch (Exception e) { e.printStackTrace(); } } }