All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.ujmp.gui.panels.MatrixHeatmapPanel Maven / Gradle / Ivy

/*
 * Copyright (C) 2008-2015 by Holger Arndt
 *
 * This file is part of the Universal Java Matrix Package (UJMP).
 * See the NOTICE file distributed with this work for additional
 * information regarding copyright ownership and licensing.
 *
 * UJMP is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * UJMP is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with UJMP; if not, write to the
 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
 * Boston, MA  02110-1301  USA
 */

package org.ujmp.gui.panels;

import java.awt.AlphaComposite;
import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.image.BufferedImage;

import javax.swing.Action;
import javax.swing.BorderFactory;
import javax.swing.JComponent;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.ToolTipManager;
import javax.swing.UIManager;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.event.TableModelEvent;

import org.ujmp.core.Matrix;
import org.ujmp.core.interfaces.HasToolTip;
import org.ujmp.gui.MatrixGUIObject;
import org.ujmp.gui.actions.MatrixActions;
import org.ujmp.gui.interfaces.CanBeRepainted;
import org.ujmp.gui.menu.MatrixPopupMenu;
import org.ujmp.gui.renderer.MatrixHeatmapRenderer;
import org.ujmp.gui.table.TableModelEvent64;
import org.ujmp.gui.table.TableModelListener64;
import org.ujmp.gui.util.GraphicsExecutor;
import org.ujmp.gui.util.Preloader;
import org.ujmp.gui.util.TooltipUtil;

public class MatrixHeatmapPanel extends JPanel implements ComponentListener, TableModelListener64, MouseListener,
		KeyListener, MouseMotionListener, CanBeRepainted, HasToolTip, ListSelectionListener {
	private static final long serialVersionUID = 843653796010276950L;

	private final MatrixGUIObject matrixGUIObject;
	private final MatrixHeatmapRenderer renderer = new MatrixHeatmapRenderer();
	private final Preloader preloader = new Preloader();

	private boolean isPreloaderVisible = true;

	private BufferedImage bufferedImage = null;

	private long startRow = 0;
	private long startCol = 0;

	public MatrixHeatmapPanel(MatrixGUIObject matrixGUIObject, boolean showBorder) {
		this.matrixGUIObject = matrixGUIObject;
		if (matrixGUIObject == null) {
			throw new IllegalArgumentException("matrixGUIObject is null");
		}

		if (showBorder) {
			setBorder(BorderFactory.createTitledBorder("Matrix Heatmap"));
		}

		setPreferredSize(new Dimension(600, 400));
		setLayout(new BorderLayout());
		add(preloader, BorderLayout.CENTER);

		addComponentListener(this);
		addMouseListener(this);
		addMouseMotionListener(this);
		addKeyListener(this);

		matrixGUIObject.addTableModelListener(this);
		matrixGUIObject.getRowSelectionModel().addListSelectionListener(this);
		matrixGUIObject.getColumnSelectionModel().addListSelectionListener(this);

		ToolTipManager.sharedInstance().registerComponent(this);

		registerKeyboardActions();
	}

	private void registerKeyboardActions() {
		for (JComponent c : new MatrixActions(this, matrixGUIObject, null)) {
			if (c instanceof JMenuItem) {
				registerKeyboardAction(((JMenuItem) c).getAction());
			}
		}
	}

	private void registerKeyboardAction(Action a) {
		// KeyStroke keyStroke = (KeyStroke) a.getValue(Action.ACCELERATOR_KEY);
		// getActionMap().put(a.getValue(Action.NAME), a);
		// getInputMap(WHEN_IN_FOCUSED_WINDOW).put(keyStroke,
		// a.getValue(Action.NAME));
	}

	public void componentHidden(ComponentEvent e) {
	}

	public void componentMoved(ComponentEvent e) {
	}

	public void componentResized(ComponentEvent e) {
		renderer.setSize(getSize());
		GraphicsExecutor.scheduleUpdate(this);
	}

	public void componentShown(ComponentEvent e) {
		GraphicsExecutor.scheduleUpdate(this);
	}

	public void tableChanged(TableModelEvent64 e) {
		GraphicsExecutor.scheduleUpdate(this);
	}

	public void tableChanged(TableModelEvent e) {
		GraphicsExecutor.scheduleUpdate(this);
	}

	public void mouseClicked(MouseEvent e) {
		long newRow = getRowPos(e.getY());
		long newCol = getColPos(e.getX());

		if (e.getButton() == MouseEvent.BUTTON3) {
			newRow = newRow < 0 ? 0 : newRow;
			newCol = newCol < 0 ? 0 : newCol;
			newRow = newRow >= matrixGUIObject.getRowCount() ? matrixGUIObject.getRowCount() - 1 : newRow;
			newCol = newCol >= matrixGUIObject.getColumnCount() ? matrixGUIObject.getColumnCount() - 1 : newCol;

			JPopupMenu popup = new MatrixPopupMenu(this, matrixGUIObject, newRow, newCol);
			popup.show(this, e.getX(), e.getY());
		} else if (e.getButton() == MouseEvent.BUTTON1) {
			// left click: show new window if value is a matrix
			Object o = matrixGUIObject.getValueAt(newRow, newCol);
			if (o instanceof Matrix) {
				((Matrix) o).showGUI();
			}
		}
	}

	public void mouseEntered(MouseEvent e) {
	}

	public void mouseExited(MouseEvent e) {
	}

	public void mousePressed(MouseEvent e) {
		if (e.getButton() == MouseEvent.BUTTON1) {
			requestFocus();
			startRow = getRowPos(e.getY());
			startCol = getColPos(e.getX());
			startRow = startRow < 0 ? 0 : startRow;
			startCol = startCol < 0 ? 0 : startCol;
			startRow = startRow >= matrixGUIObject.getRowCount() ? matrixGUIObject.getRowCount() - 1 : startRow;
			startCol = startCol >= matrixGUIObject.getColumnCount() ? matrixGUIObject.getColumnCount() - 1 : startCol;
			matrixGUIObject.getRowSelectionModel().setValueIsAdjusting(true);
			matrixGUIObject.getColumnSelectionModel().setValueIsAdjusting(true);
			matrixGUIObject.getRowSelectionModel().setSelectionInterval(startRow, startRow);
			matrixGUIObject.getColumnSelectionModel().setSelectionInterval(startCol, startCol);
		}
		repaint(100);
	}

	private long getRowPos(int y) {
		return matrixGUIObject.getRowCount64() * y / getHeight();
	}

	private long getColPos(int x) {
		return matrixGUIObject.getColumnCount64() * x / getWidth();
	}

	public void mouseReleased(MouseEvent e) {
		if (e.getButton() == MouseEvent.BUTTON1) {
			long newRow = getRowPos(e.getY());
			long newCol = getColPos(e.getX());
			newRow = newRow < 0 ? 0 : newRow;
			newCol = newCol < 0 ? 0 : newCol;
			newRow = newRow >= matrixGUIObject.getRowCount() ? matrixGUIObject.getRowCount() - 1 : newRow;
			newCol = newCol >= matrixGUIObject.getColumnCount() ? matrixGUIObject.getColumnCount() - 1 : newCol;
			matrixGUIObject.getRowSelectionModel().setValueIsAdjusting(false);
			matrixGUIObject.getColumnSelectionModel().setValueIsAdjusting(false);
			matrixGUIObject.getRowSelectionModel().setSelectionInterval(startRow, newRow);
			matrixGUIObject.getColumnSelectionModel().setSelectionInterval(startCol, newCol);
			repaint(100);
		}
	}

	public MatrixGUIObject getMatrix() {
		return matrixGUIObject;
	}

	public String getToolTipText(MouseEvent e) {
		// only generate tool text when a matrix with size >0 is available
		if (matrixGUIObject.getRowCount() > 0 && matrixGUIObject.getColumnCount() > 0) {
			long r = getRowPos(e.getY());
			long c = getColPos(e.getX());
			r = r < 0 ? 0 : r;
			c = c < 0 ? 0 : c;
			r = r >= matrixGUIObject.getRowCount() ? matrixGUIObject.getRowCount() - 1 : r;
			c = c >= matrixGUIObject.getColumnCount() ? matrixGUIObject.getColumnCount() - 1 : c;

			String toolTip = TooltipUtil.getTooltip(matrixGUIObject, r, c);
			return toolTip;
		} else {
			return null;
		}
	}

	protected void finalize() throws Throwable {
		super.finalize();
		if (matrixGUIObject != null) {
			matrixGUIObject.removeTableModelListener(this);
		}
		ToolTipManager.sharedInstance().unregisterComponent(this);
	}

	protected void paintComponent(Graphics g) {
		if (bufferedImage == null) {
			super.paintComponent(g);
		} else {
			if (isPreloaderVisible) {
				remove(preloader);
				isPreloaderVisible = false;
			}
			Graphics2D g2d = (Graphics2D) g;
			g2d.drawImage(bufferedImage, 0, 0, getWidth(), getHeight(), null);

			if (!matrixGUIObject.getRowSelectionModel().isSelectionEmpty()) {
				int paddingX = UIManager.getInt("Table.paddingX");
				int paddingY = UIManager.getInt("Table.paddingY");
				g2d.setColor(Color.BLUE);
				g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 0.3f));
				long x1 = matrixGUIObject.getColumnSelectionModel().getMinSelectionIndex64();
				long x2 = matrixGUIObject.getColumnSelectionModel().getMaxSelectionIndex64();
				long y1 = matrixGUIObject.getRowSelectionModel().getMinSelectionIndex64();
				long y2 = matrixGUIObject.getRowSelectionModel().getMaxSelectionIndex64();
				double scaleX = (double) (getWidth() - paddingX - paddingX) / (double) matrixGUIObject.getColumnCount();
				double scaleY = (double) (getHeight() - paddingY - paddingY) / (double) matrixGUIObject.getRowCount();
				g2d.setStroke(new BasicStroke(2.0f));
				g2d.drawRect((int) Math.floor(paddingX + x1 * scaleX), (int) Math.floor(paddingY + y1 * scaleY),
						(int) Math.ceil(scaleX + (x2 - x1) * scaleX), (int) Math.ceil(scaleY + (y2 - y1) * scaleY));
				g2d.fillRect((int) Math.floor(paddingX + x1 * scaleX), (int) Math.floor(paddingY + y1 * scaleY),
						(int) Math.ceil(scaleX + (x2 - x1) * scaleX), (int) Math.ceil(scaleY + (y2 - y1) * scaleY));
			}
		}
	}

	public void repaintUI() {
		if (getWidth() > 0 && getHeight() > 0 && matrixGUIObject.getRowCount() >= 0
				&& matrixGUIObject.getColumnCount() >= 0) {
			BufferedImage tempBufferedImage = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_RGB);
			renderer.setSize(getWidth(), getHeight());
			renderer.setMatrix(matrixGUIObject);
			Graphics2D g2d = (Graphics2D) tempBufferedImage.getGraphics();
			renderer.paintComponent(g2d);
			g2d.dispose();
			bufferedImage = tempBufferedImage;
		}
	}

	public void mouseDragged(MouseEvent e) {
		if (matrixGUIObject.getRowSelectionModel().getValueIsAdjusting()) {
			long newRow = getRowPos(e.getY());
			long newCol = getColPos(e.getX());
			newRow = newRow < 0 ? 0 : newRow;
			newCol = newCol < 0 ? 0 : newCol;
			newRow = newRow >= matrixGUIObject.getRowCount() ? matrixGUIObject.getRowCount() - 1 : newRow;
			newCol = newCol >= matrixGUIObject.getColumnCount() ? matrixGUIObject.getColumnCount() - 1 : newCol;
			matrixGUIObject.getRowSelectionModel().setSelectionInterval(startRow, newRow);
			matrixGUIObject.getColumnSelectionModel().setSelectionInterval(startCol, newCol);
			repaint(100);
		}
	}

	public void mouseMoved(MouseEvent e) {
		final long row = getRowPos(e.getY());
		final long col = getColPos(e.getX());
		matrixGUIObject.setMouseOverCoordinates(row, col);
	}

	public void valueChanged(ListSelectionEvent e) {
		repaint(100);
	}

	public void keyTyped(KeyEvent e) {
	}

	public void keyPressed(KeyEvent e) {
		long rows = matrixGUIObject.getRowCount64();
		long cols = matrixGUIObject.getColumnCount64();
		long minRow = matrixGUIObject.getRowSelectionModel().getMinSelectionIndex64();
		long maxRow = matrixGUIObject.getRowSelectionModel().getMaxSelectionIndex64();
		long minCol = matrixGUIObject.getColumnSelectionModel().getMinSelectionIndex64();
		long maxCol = matrixGUIObject.getColumnSelectionModel().getMaxSelectionIndex64();
		if ((e.getKeyCode() == KeyEvent.VK_A) && ((e.getModifiers() & KeyEvent.CTRL_MASK) != 0)) {
			matrixGUIObject.getColumnSelectionModel().setSelectionInterval(0, cols - 1);
			matrixGUIObject.getRowSelectionModel().setSelectionInterval(0, rows - 1);
		} else if (e.getKeyCode() == KeyEvent.VK_UP && minRow > 0) {
			matrixGUIObject.getRowSelectionModel().setSelectionInterval(minRow - 1, maxRow - 1);
		} else if (e.getKeyCode() == KeyEvent.VK_DOWN && maxRow < rows - 1) {
			matrixGUIObject.getRowSelectionModel().setSelectionInterval(minRow + 1, maxRow + 1);
		} else if (e.getKeyCode() == KeyEvent.VK_LEFT && minCol > 0) {
			matrixGUIObject.getColumnSelectionModel().setSelectionInterval(minCol - 1, maxCol - 1);
		} else if (e.getKeyCode() == KeyEvent.VK_RIGHT && maxCol < cols - 1) {
			matrixGUIObject.getColumnSelectionModel().setSelectionInterval(minCol + 1, maxCol + 1);
		}
	}

	public void keyReleased(KeyEvent e) {
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy