/*
* #%L
* gitools-ui-app
* %%
* Copyright (C) 2013 Universitat Pompeu Fabra - Biomedical Genomics group
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/gpl-3.0.html>.
* #L%
*/
package org.gitools.ui.core.components.boxes;
import com.alee.extended.layout.TableLayout;
import com.alee.extended.panel.GroupPanel;
import com.alee.extended.panel.GroupingType;
import com.alee.laf.label.WebLabel;
import com.alee.laf.panel.WebPanel;
import com.alee.laf.separator.WebSeparator;
import com.alee.managers.language.data.TooltipWay;
import com.alee.managers.tooltip.TooltipManager;
import com.alee.utils.SwingUtils;
import org.apache.commons.lang.StringUtils;
import org.gitools.heatmap.Heatmap;
import org.gitools.heatmap.decorator.DetailsDecoration;
import org.gitools.heatmap.decorator.JComponentDetailsDecoration;
import org.gitools.ui.core.actions.ActionSet;
import org.gitools.ui.platform.icons.IconNames;
import org.jdesktop.swingx.HorizontalLayout;
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.List;
/**
* Create a property table panel
*/
public abstract class DetailsBox extends Box {
private static final int DEFAULT_MARGIN = 20;
private static final int MINIMUM_VALUE_LENGTH = 12;
private WebPanel container;
private JPanel updatingPanel = new JPanel();
/**
* @param id
* @param title Optional title of the details table
*/
public DetailsBox(String id, String title, ActionSet actions, Heatmap heatmap) {
super(id, title, actions, heatmap);
bottomPanels = null;
}
public DetailsBox(String id, String title, ActionSet contextActionSet, ActionSet bottomActionSet, Heatmap heatmap) {
super(id, title, contextActionSet, bottomActionSet, heatmap);
fillUpdatingPanel();
}
protected void fillUpdatingPanel() {
updatingPanel.add(new JLabel("Updating..."));
}
protected abstract void onMouseSingleClick(DetailsDecoration propertyItem);
protected abstract void onMouseDoubleClick(DetailsDecoration propertyItem);
protected abstract void onMouseRightClick(DetailsDecoration propertyItem, MouseEvent e);
public void drawUpdating() {
WebPanel container = getContainer();
container.removeAll();
container.setLayout(new HorizontalLayout());
container.add(updatingPanel);
container.repaint();
}
public void draw(List<DetailsDecoration> details) {
WebPanel container = getContainer();
container.removeAll();
int maxValueLength = convertToCharacters(getWidth() - 15) - maxValueLength(details) - 5;
maxValueLength = (maxValueLength < 8 ? 8 : maxValueLength);
int bottomPanelsAmount = (bottomPanels != null) ? bottomPanels.size() : 0;
double columns[] = {5, TableLayout.PREFERRED, 3, TableLayout.FILL, 5};
double rows[] = new double[3 + (details.size() + bottomPanelsAmount - 1) * 2];
rows[0] = 2;
rows[1] = 2;
for (int i = 2; i < rows.length - 1; i += 2) {
rows[i] = TableLayout.PREFERRED;
rows[i + 1] = 2;
}
rows[rows.length - 1] = DEFAULT_MARGIN;
TableLayout boxLayout = new TableLayout(new double[][]{columns, rows});
boxLayout.setHGap(4);
boxLayout.setVGap(4);
container.setLayout(boxLayout);
container.validate();
container.add(createVerticalSeparator(), "2,1,2," + (rows.length - 2));
int nextDetail = 1;
for (DetailsDecoration detail : details) {
int nextRow = nextDetail * 2;
container.add(createHorizontalSeparator(), "0," + (nextRow - 1) + ",4," + (nextRow - 1));
container.add(createNameLabel(detail), "1," + nextRow);
container.add(createValueLabel(detail, maxValueLength), "3," + nextRow);
nextDetail++;
if (nextDetail > details.size()) {
container.add(createHorizontalSeparator(), "0," + (nextRow + 1) + ",4," + (nextRow + 1));
}
}
if (bottomPanels != null) {
for (JPanel panel : bottomPanels) {
int nextRow = nextDetail * 2;
container.add(panel, "1, " + (nextRow) + ", 4, " + (nextRow));
nextDetail++;
}
}
container.repaint();
}
private static WebSeparator createHorizontalSeparator() {
WebSeparator separator = new WebSeparator(WebSeparator.HORIZONTAL);
separator.setDrawSideLines(false);
return separator;
}
private static WebSeparator createVerticalSeparator() {
WebSeparator separator = new WebSeparator(WebSeparator.VERTICAL);
separator.setDrawSideLines(false);
return separator;
}
private Component createComponentNameLabel(JComponentDetailsDecoration detail) {
if (detail.getDetailsComponent() != null) {
JComponent c = detail.getDetailsComponent();
TooltipManager.setTooltip(c, detail.getDescription(), TooltipWay.down, 0);
return c;
}
return null;
}
private Component createNameLabel(DetailsDecoration detail) {
if (detail instanceof JComponentDetailsDecoration) {
Component c = createComponentNameLabel((JComponentDetailsDecoration) detail);
if (c != null) {
c.setForeground(detail.isVisible() ? Color.BLACK : Color.lightGray);
return c;
}
}
WebLabel label = new WebLabel(StringUtils.capitalize(detail.getName()), JLabel.TRAILING);
label.setDrawShade(true);
SwingUtils.changeFontSize(label, -1);
if (detail.isSelected()) {
SwingUtils.setBoldFont(label);
}
label.setCursor(new Cursor(Cursor.HAND_CURSOR));
label.addMouseListener(new PropertyMouseListener(detail));
if (StringUtils.isNotEmpty(detail.getDescription())) {
String description = "<html><body width=\"300px\">" + detail.getDescription() + "</body></html>";
TooltipManager.setTooltip(label, description, TooltipWay.down, 0);
}
if (!StringUtils.isEmpty(detail.getDescriptionLink())) {
DetailsWebLinkLabel webLabel = new DetailsWebLinkLabel("", JLabel.TRAILING);
webLabel.setIcon(IconNames.INFO_ICON);
webLabel.setLink(detail.getDescriptionLink(), false);
TooltipManager.setTooltip(webLabel, detail.getDescriptionLink(), TooltipWay.down, 0);
return new GroupPanel(GroupingType.fillFirst, 5, webLabel, label);
}
label.setForeground(detail.isVisible() ? Color.BLACK : Color.lightGray);
return label;
}
private Component createValueLabel(DetailsDecoration property, int maxLength) {
String value = property.getFormatedValue();
boolean abbreviate = (value.length() > maxLength);
String abbreviatedValue;
if (value.matches("[0-9\\.]+e-?[0-9]+")) {
value = "<html><body>" + value.replaceAll("e(-?[0-9]+)", "ยท10<sup>$1</sup>") + "</body></html>";
}
if (abbreviate) {
abbreviatedValue = StringUtils.abbreviate(value, maxLength);
} else {
abbreviatedValue = value;
}
WebLabel label;
if (StringUtils.isEmpty(property.getValueLink())) {
label = new WebLabel(abbreviatedValue);
} else {
DetailsWebLinkLabel webLabel = new DetailsWebLinkLabel(abbreviatedValue);
webLabel.setLink(property.getValueLink(), false);
label = webLabel;
}
SwingUtils.changeFontSize(label, -1);
if (abbreviate) {
TooltipManager.setTooltip(label, value, TooltipWay.down, 0);
}
label.setCursor(new Cursor(Cursor.HAND_CURSOR));
label.addMouseListener(new PropertyMouseListener(property));
if (property.isSelected()) {
SwingUtils.setBoldFont(label);
}
if (property.getBgColor() != null) {
WebPanel colorBox = new WebPanel();
colorBox.setPreferredSize(new Dimension(15, 15));
colorBox.setBackground(property.getBgColor());
return new GroupPanel(4, colorBox, label);
}
label.setForeground(property.isVisible() ? Color.BLACK : Color.lightGray);
return label;
}
private static int convertToCharacters(int pixels) {
return Math.round(pixels / 7);
}
private static int maxValueLength(List<DetailsDecoration> details) {
int max = MINIMUM_VALUE_LENGTH;
for (DetailsDecoration property : details) {
int length = property.getName().length();
if (length > max) {
max = length;
}
}
return max;
}
private class PropertyMouseListener extends MouseAdapter {
private DetailsDecoration item;
private PropertyMouseListener(DetailsDecoration item) {
this.item = item;
}
public void mouseReleased(MouseEvent e) {
if ((e.getModifiers() & MouseEvent.BUTTON3_MASK) != 0) {
onMouseRightClick(item, e);
} else {
if (e.getClickCount() > 1) {
onMouseDoubleClick(item);
} else {
onMouseSingleClick(item);
}
}
}
}
@Override
public void initContainer() {
container = new WebPanel();
container.setBackground(Color.WHITE);
container.setBorder(null);
}
@Override
public WebPanel getContainer() {
if (container == null) {
initContainer();
}
return container;
}
@Override
public MouseListener getBottomActionMouseAdapter() {
return null;
}
}