/*
* The MIT License (MIT)
*
* Copyright (c) 2007-2015 Broad Institute
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
/*
* TrackPanel.java
*
* Created on Sep 5, 2007, 4:09:39 PM
*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.broad.igv.ui.panel;
//~--- non-JDK imports --------------------------------------------------------
import org.broad.igv.prefs.Constants;
import org.broad.igv.prefs.PreferencesManager;
import org.broad.igv.track.AttributeManager;
import org.broad.igv.ui.FontManager;
import org.broad.igv.ui.IGV;
import javax.swing.*;
import javax.swing.event.MouseInputAdapter;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.geom.AffineTransform;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author jrobinso
*/
public class AttributeHeaderPanel extends JPanel implements Paintable {
final static int MAXIMUM_FONT_SIZE = 10;
public final static int ATTRIBUTE_COLUMN_WIDTH = 10;
public final static int COLUMN_BORDER_WIDTH = 1;
Map<String, Boolean> sortOrder = new HashMap();
public AttributeHeaderPanel() {
setBorder(javax.swing.BorderFactory.createLineBorder(Color.black));
setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
addMouseListener();
}
public int getAttributeColumnWidth() {
return ATTRIBUTE_COLUMN_WIDTH;
}
private String getAttributeHeading(int x) {
int idx = x / (ATTRIBUTE_COLUMN_WIDTH + COLUMN_BORDER_WIDTH);
List<String> keys = AttributeManager.getInstance().getVisibleAttributes();
if (idx < keys.size()) {
return keys.get(idx);
} else {
return null;
}
}
@Override
protected void paintComponent(final Graphics graphics) {
super.paintComponent(graphics);
List<String> keys = AttributeManager.getInstance().getVisibleAttributes();
if (keys != null && keys.size() > 0) {
final Graphics2D graphics2 = (Graphics2D) graphics;
if (PreferencesManager.getPreferences().getAsBoolean(Constants.ENABLE_ANTIALISING)) {
graphics2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
}
// Divide the remaining space to get column widths
int columnWidth = getAttributeColumnWidth();
// Create font and font size
int fontSize = (int) (0.9 * columnWidth);
if (fontSize > MAXIMUM_FONT_SIZE) {
fontSize = MAXIMUM_FONT_SIZE;
}
Font font = FontManager.getFont(fontSize);
// Change the origin for the text
AffineTransform transform = AffineTransform.getTranslateInstance(0, getHeight() - COLUMN_BORDER_WIDTH);
graphics2.transform(transform);
// Now rotate text counter-clockwise 90 degrees
transform = AffineTransform.getQuadrantRotateInstance(-1);
graphics2.transform(transform);
graphics2.setFont(font);
FontMetrics fm = graphics2.getFontMetrics();
int fontAscent = fm.getHeight();
int i = 1;
int x;
for (String key : keys) {
int columnLeftEdge = ((COLUMN_BORDER_WIDTH + ATTRIBUTE_COLUMN_WIDTH) * i++);
x = columnLeftEdge + ((COLUMN_BORDER_WIDTH + ATTRIBUTE_COLUMN_WIDTH) - fontAscent) / 2;
String toDraw = key;
int stringOffset = 2;
graphics2.drawString(toDraw, stringOffset, x);
}
}
}
private void addMouseListener() {
setToolTipText("Click attribute heading to sort");
MouseInputAdapter listener = new MouseInputAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
String attKey = getAttributeHeading(e.getX());
if (attKey != null) {
Boolean tmp = sortOrder.get(attKey);
boolean sortAscending = tmp == null ? true : tmp.booleanValue();
sortTrackByAttribute(attKey, sortAscending);
sortOrder.put(attKey, !sortAscending);
}
}
@Override
public void mouseMoved(MouseEvent e) {
String attKey = getAttributeHeading(e.getX());
if (attKey != null) {
AttributeManager.ColumnMetaData md = AttributeManager.getInstance().getColumnMetaData(attKey);
if (md != null) {
StringBuffer buf = new StringBuffer("<html>" + attKey + "<br>Click to sort");
//buf.append("<br>Is numeric = " + md.isNumeric() + "<br>");
//buf.append("Is diverging = " + md.isDiverging() + "<br>");
//buf.append("getUniqueCount = " + md.getUniqueCount() + "<br>");
//buf.append("getTotalCount = " + md.getTotalCount() + "<br>");
//buf.append("getUniqueRatio = " + md.getUniqueRatio() + "<br>");
// buf.append("# unique = " + md.uniqueValues.size() + "<br>");
// buf.append("# total = " + md.totalCount + "<br>");
// buf.append("# numeric = " + md.numericCount + "<br>");
setToolTipText(buf.toString());
return;
}
setToolTipText("Click attribute heading to sort");
}
}
};
addMouseMotionListener(listener);
addMouseListener(listener);
}
final public void sortTrackByAttribute(String sortKey, boolean isSortAscending) {
if (sortKey != null) {
IGV.getInstance().sortAllTracksByAttributes(new String[]{sortKey}, new boolean[]{isSortAscending});
IGV.getMainFrame().repaint();
}
}
public void paintOffscreen(Graphics2D g, Rectangle rect) {
paintComponent(g);
Color c = g.getColor();
g.setColor(Color.darkGray);
g.drawRect(rect.x, rect.y, rect.width, rect.height);
g.setColor(c); //super.paintBorder(g);
}
}