001 /* 002 * Copyright (C) 2008-2010 by Holger Arndt 003 * 004 * This file is part of the Universal Java Matrix Package (UJMP). 005 * See the NOTICE file distributed with this work for additional 006 * information regarding copyright ownership and licensing. 007 * 008 * UJMP is free software; you can redistribute it and/or modify 009 * it under the terms of the GNU Lesser General Public License as 010 * published by the Free Software Foundation; either version 2 011 * of the License, or (at your option) any later version. 012 * 013 * UJMP is distributed in the hope that it will be useful, 014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 016 * GNU Lesser General Public License for more details. 017 * 018 * You should have received a copy of the GNU Lesser General Public 019 * License along with UJMP; if not, write to the 020 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, 021 * Boston, MA 02110-1301 USA 022 */ 023 024 package org.ujmp.gui.renderer; 025 026 import java.awt.Color; 027 import java.awt.Component; 028 import java.awt.Graphics; 029 import java.awt.Graphics2D; 030 import java.awt.image.BufferedImage; 031 import java.awt.image.DataBufferInt; 032 import java.util.ConcurrentModificationException; 033 import java.util.logging.Level; 034 import java.util.logging.Logger; 035 036 import javax.swing.JTable; 037 import javax.swing.UIManager; 038 import javax.swing.border.Border; 039 import javax.swing.table.DefaultTableCellRenderer; 040 041 import org.ujmp.core.Coordinates; 042 import org.ujmp.core.Matrix; 043 import org.ujmp.core.util.MathUtil; 044 import org.ujmp.core.util.UJMPFormat; 045 import org.ujmp.gui.MatrixGUIObject; 046 import org.ujmp.gui.util.ColorUtil; 047 import org.ujmp.gui.util.GraphicsUtil; 048 import org.ujmp.gui.util.UIDefaults; 049 050 public class MatrixRenderer extends DefaultTableCellRenderer { 051 private static final long serialVersionUID = 942689931503793487L; 052 053 private static final Logger logger = Logger.getLogger(MatrixRenderer.class 054 .getName()); 055 056 private MatrixGUIObject matrix = null; 057 058 private int width = 0; 059 060 private int height = 0; 061 062 private static int PADDINGX = UIManager.getInt("Table.paddingX"); 063 064 private static int PADDINGY = UIManager.getInt("Table.paddingY"); 065 066 public MatrixRenderer() { 067 } 068 069 public MatrixRenderer(MatrixGUIObject m) { 070 setMatrix(m); 071 } 072 073 public void setMatrix(MatrixGUIObject m) { 074 this.matrix = m; 075 } 076 077 public Component getTableCellRendererComponent(JTable table, Object value, 078 boolean isSelected, boolean hasFocus, int row, int column) { 079 080 if (value instanceof MatrixGUIObject) { 081 matrix = (MatrixGUIObject) value; 082 } else if (value instanceof Matrix) { 083 matrix = (MatrixGUIObject) ((Matrix) value).getGUIObject(); 084 } else { 085 matrix = null; 086 } 087 088 width = table.getColumnModel().getColumn(column).getWidth() - 1; 089 height = table.getRowHeight(row) - 1; 090 091 if (isSelected) { 092 super.setForeground(table.getSelectionForeground()); 093 super.setBackground(table.getSelectionBackground()); 094 } else { 095 super.setForeground(table.getForeground()); 096 super.setBackground(table.getBackground()); 097 } 098 099 setFont(table.getFont()); 100 101 if (hasFocus) { 102 Border border = null; 103 if (isSelected) { 104 border = UIManager 105 .getBorder("Table.focusSelectedCellHighlightBorder"); 106 } 107 if (border == null) { 108 border = UIManager.getBorder("Table.focusCellHighlightBorder"); 109 } 110 setBorder(border); 111 112 if (!isSelected && table.isCellEditable(row, column)) { 113 Color col; 114 col = UIManager.getColor("Table.focusCellForeground"); 115 if (col != null) { 116 super.setForeground(col); 117 } 118 col = UIManager.getColor("Table.focusCellBackground"); 119 if (col != null) { 120 super.setBackground(col); 121 } 122 } 123 } else { 124 setBorder(noFocusBorder); 125 } 126 127 return this; 128 } 129 130 public void paintComponent(Graphics g) { 131 Graphics2D g2d = (Graphics2D) g; 132 133 g2d.setColor(getBackground()); 134 g2d.fillRect(0, 0, width, height); 135 136 try { 137 if (matrix != null) { 138 matrix = (MatrixGUIObject) MathUtil.getMatrix( 139 matrix.getMatrix()).getGUIObject(); 140 141 int width = getWidth(); 142 int height = getHeight(); 143 width = width == 0 ? 1 : width; 144 height = height == 0 ? 1 : height; 145 int totalColumn = matrix.getColumnCount(); 146 int totalRows = matrix.getRowCount(); 147 int xsize = Math.min(totalColumn, width); 148 int ysize = Math.min(totalRows, height); 149 xsize = xsize == 0 ? 1 : xsize; 150 ysize = ysize == 0 ? 1 : ysize; 151 152 double stepsizeX = (double) totalColumn / (double) width; 153 double stepsizeY = (double) totalRows / (double) height; 154 if (stepsizeX < 1.0) { 155 stepsizeX = 1.0; 156 } 157 if (stepsizeY < 1.0) { 158 stepsizeY = 1.0; 159 } 160 161 BufferedImage bufferedImage = new BufferedImage(xsize, ysize, 162 BufferedImage.TYPE_INT_RGB); 163 164 int[] pixels = ((DataBufferInt) bufferedImage.getRaster() 165 .getDataBuffer()).getData(); 166 167 if (stepsizeX != 1.0 || stepsizeY != 1.0) { 168 int pos = 0; 169 for (int y = 0; y < ysize; y++) { 170 for (int x = 0; x < xsize; x++) { 171 int mx = (int) Math.floor(x * stepsizeX); 172 int my = (int) Math.floor(y * stepsizeY); 173 Color col = ColorUtil.fromObject(matrix.getValueAt( 174 my, mx)); 175 pixels[pos++] = (col.getRed() << 16) 176 + (col.getGreen() << 8) + col.getBlue(); 177 } 178 } 179 } else { 180 Iterable<long[]> cos = matrix.coordinates(); 181 if (cos != null) { 182 for (long[] c : cos) { 183 if (c != null) { 184 Color col = ColorUtil.fromObject(matrix 185 .getValueAt(c)); 186 int pos = getPosition(totalColumn, 187 c[Coordinates.ROW], 188 c[Coordinates.COLUMN]); 189 pixels[pos] = (col.getRed() << 16) 190 + (col.getGreen() << 8) + col.getBlue(); 191 } 192 } 193 } 194 } 195 196 g2d.drawImage(bufferedImage, PADDINGX, PADDINGY, width 197 - PADDINGX - PADDINGX, height - PADDINGY - PADDINGY, 198 null); 199 200 if (width > 20 && matrix.isScalar()) { 201 Color col = ColorUtil.fromObject(matrix.getValueAt(0, 0)); 202 g2d.setColor(ColorUtil.contrastBW(col)); 203 String s = UJMPFormat.getSingleLineInstance().format( 204 matrix.getValueAt(0, 0)); 205 if (s != null && s.length() > 25) { 206 s = s.substring(0, 25) + "..."; 207 } 208 GraphicsUtil.drawString(g2d, width / 2.0, 209 height / 2.0 - 1.0, GraphicsUtil.ALIGNCENTER, 210 GraphicsUtil.ALIGNCENTER, s); 211 } 212 213 } else { 214 g2d.setColor(Color.GRAY); 215 g2d.drawLine(PADDINGX, PADDINGY, width - PADDINGX, height 216 - PADDINGY); 217 g2d.drawLine(PADDINGX, height - PADDINGY, width - PADDINGX, 218 0 + PADDINGY); 219 } 220 } catch (ConcurrentModificationException e) { 221 // not too bad 222 } catch (Exception e) { 223 logger.log(Level.WARNING, "could not paint", e); 224 } 225 } 226 227 private static int getPosition(long totalColumn, long currentRow, 228 long currentColumn) { 229 return (int) (totalColumn * currentRow + currentColumn); 230 } 231 232 public static void paintMatrix(Graphics g, Matrix matrix, int width, 233 int height) { 234 if (g == null) 235 return; 236 237 Graphics2D g2d = (Graphics2D) g; 238 g2d.addRenderingHints(UIDefaults.AALIAS); 239 240 if (matrix == null) { 241 g2d.setColor(Color.GRAY); 242 g2d.drawLine(PADDINGX, PADDINGY, width - PADDINGX, height 243 - PADDINGY); 244 g2d.drawLine(width - PADDINGX, PADDINGY, PADDINGX, height 245 - PADDINGY); 246 } else { 247 g2d.translate(PADDINGX, PADDINGX); 248 if (matrix.getColumnCount() > matrix.getRowCount()) { 249 paintMatrixOriginal(g2d, matrix, width - PADDINGX - PADDINGX, 250 height - PADDINGY - PADDINGY); 251 } else { 252 paintMatrixTransposed(g2d, matrix, width - PADDINGX - PADDINGX, 253 height - PADDINGY - PADDINGY); 254 } 255 g2d.translate(-PADDINGX, -PADDINGX); 256 } 257 } 258 259 private static void paintMatrixOriginal(Graphics g, Matrix matrix, 260 int width, int height) { 261 try { 262 int cols = (int) matrix.getColumnCount(); 263 int rows = (int) matrix.getRowCount(); 264 265 width = width < 1 ? 1 : width; 266 height = height < 1 ? 1 : height; 267 int xSize = cols > 0 ? cols : 1; 268 int ySize = rows > 0 ? rows : 1; 269 270 xSize = xSize > 0 ? xSize : 1; 271 ySize = ySize > 0 ? ySize : 1; 272 273 int xStepSize = (int) Math.ceil((double) xSize / (double) width); 274 int yStepSize = (int) Math.ceil((double) ySize / (double) height); 275 276 int imgX = xSize / xStepSize; 277 int imgY = ySize / yStepSize; 278 imgX = imgX > 0 ? imgX : 1; 279 imgY = imgY > 0 ? imgX : 1; 280 281 BufferedImage bufferedImage = new BufferedImage(imgX, imgY, 282 BufferedImage.TYPE_INT_RGB); 283 Graphics2D g2d = (Graphics2D) g; 284 Graphics2D bg = (Graphics2D) bufferedImage.getGraphics(); 285 bg.addRenderingHints(UIDefaults.AALIAS); 286 287 for (int col = 0; col < cols; col += xStepSize) { 288 for (int row = 0; row < rows; row += yStepSize) { 289 bg.setColor(ColorUtil.fromDouble(matrix.getAsDouble(row, 290 col))); 291 bg.fillRect(col / xStepSize, row / yStepSize, 1, 1); 292 } 293 } 294 g2d.drawImage(bufferedImage, 0, 0, width, height, 0, 0, 295 bufferedImage.getWidth(), bufferedImage.getHeight(), null); 296 if (width > 20 && matrix.isScalar()) { 297 String s = UJMPFormat.getSingleLineInstance().format( 298 matrix.getAsObject(0, 0)); 299 if (s != null && s.length() > 25) { 300 s = s.substring(0, 25) + "..."; 301 } 302 g2d.setColor(ColorUtil.contrastBW(bg.getColor())); 303 GraphicsUtil.drawString(g2d, width / 2.0, height / 2.0 - 1.0, 304 GraphicsUtil.ALIGNCENTER, GraphicsUtil.ALIGNCENTER, s); 305 } 306 } catch (Exception e) { 307 logger.log(Level.WARNING, "error painting matrix", e); 308 } 309 } 310 311 private static void paintMatrixSquared(Graphics g, Matrix matrix, 312 int width, int height) { 313 try { 314 long valueCount = matrix.getValueCount(); 315 316 width = width < 1 ? 1 : width; 317 height = height < 1 ? 1 : height; 318 int xSize = (int) Math.floor(Math.sqrt(valueCount)); 319 int ySize = (int) Math.ceil((double) valueCount / (double) xSize); 320 321 xSize = xSize > 0 ? xSize : 1; 322 ySize = ySize > 0 ? ySize : 1; 323 324 int xStepSize = (int) Math.ceil((double) xSize / (double) width); 325 int yStepSize = (int) Math.ceil((double) ySize / (double) height); 326 327 int imgX = xSize / xStepSize; 328 int imgY = ySize / yStepSize; 329 imgX = imgX > 0 ? imgX : 1; 330 imgY = imgY > 0 ? imgX : 1; 331 332 BufferedImage bufferedImage = new BufferedImage(imgX, imgY, 333 BufferedImage.TYPE_INT_RGB); 334 Graphics2D g2d = (Graphics2D) g; 335 Graphics2D bg = (Graphics2D) bufferedImage.getGraphics(); 336 bg.addRenderingHints(UIDefaults.AALIAS); 337 int x = 0; 338 int y = 0; 339 340 for (int i = 0; i < valueCount; i++) { 341 bg.setColor(ColorUtil.fromDouble(matrix.getAsDouble(i 342 % matrix.getRowCount(), i / matrix.getRowCount()))); 343 bg.fillRect(x / xStepSize, y / yStepSize, 1, 1); 344 x++; 345 if (x >= xSize) { 346 x = 0; 347 y++; 348 } 349 } 350 351 g2d.drawImage(bufferedImage, 0, 0, width, height, 0, 0, 352 bufferedImage.getWidth(), bufferedImage.getHeight(), null); 353 if (width > 20 && matrix.isScalar()) { 354 g2d.setColor(ColorUtil.contrastBW(bg.getColor())); 355 GraphicsUtil.drawString(g2d, width / 2.0, height / 2.0 - 1.0, 356 GraphicsUtil.ALIGNCENTER, GraphicsUtil.ALIGNCENTER, 357 UJMPFormat.getSingleLineInstance().format( 358 matrix.getAsObject(0, 0))); 359 } 360 } catch (Exception e) { 361 logger.log(Level.WARNING, "error painting matrix", e); 362 } 363 } 364 365 private static void paintMatrixTransposed(Graphics g, Matrix matrix, 366 int width, int height) { 367 try { 368 int cols = (int) matrix.getColumnCount(); 369 int rows = (int) matrix.getRowCount(); 370 371 width = width < 1 ? 1 : width; 372 height = height < 1 ? 1 : height; 373 int ySize = cols > 0 ? cols : 1; 374 int xSize = rows > 0 ? rows : 1; 375 376 xSize = xSize > 0 ? xSize : 1; 377 ySize = ySize > 0 ? ySize : 1; 378 379 int xStepSize = (int) Math.ceil((double) xSize / (double) width); 380 int yStepSize = (int) Math.ceil((double) ySize / (double) height); 381 382 int imgX = xSize / xStepSize; 383 int imgY = ySize / yStepSize; 384 imgX = imgX > 0 ? imgX : 1; 385 imgY = imgY > 0 ? imgX : 1; 386 387 BufferedImage bufferedImage = new BufferedImage(imgX, imgY, 388 BufferedImage.TYPE_INT_RGB); 389 Graphics2D g2d = (Graphics2D) g; 390 Graphics2D bg = (Graphics2D) bufferedImage.getGraphics(); 391 bg.addRenderingHints(UIDefaults.AALIAS); 392 393 for (int col = 0; col < cols; col += xStepSize) { 394 for (int row = 0; row < rows; row += yStepSize) { 395 bg.setColor(ColorUtil.fromDouble(matrix.getAsDouble(row, 396 col))); 397 bg.fillRect(row / yStepSize, col / xStepSize, 1, 1); 398 } 399 } 400 401 g2d.drawImage(bufferedImage, 0, 0, width, height, 0, 0, 402 bufferedImage.getWidth(), bufferedImage.getHeight(), null); 403 if (width > 20 && matrix.isScalar()) { 404 g2d.setColor(ColorUtil.contrastBW(bg.getColor())); 405 String s = UJMPFormat.getSingleLineInstance().format( 406 matrix.getAsObject(0, 0)); 407 if (s != null && s.length() > 25) { 408 s = s.substring(0, 25) + "..."; 409 } 410 GraphicsUtil.drawString(g2d, width / 2.0, height / 2.0 - 1.0, 411 GraphicsUtil.ALIGNCENTER, GraphicsUtil.ALIGNCENTER, s); 412 } 413 } catch (Exception e) { 414 logger.log(Level.WARNING, "error painting matrix", e); 415 } 416 } 417 418 }