package eu.hgross.blaubot.blaubotcam.server.ui; import java.awt.Color; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.Image; import javax.swing.ImageIcon; import javax.swing.JLabel; import javax.swing.JLayeredPane; import javax.swing.JPanel; import javax.swing.SwingUtilities; import eu.hgross.blaubot.blaubotcam.server.model.ImageMessage; import eu.hgross.blaubot.core.State; import eu.hgross.blaubot.ui.Util; /** * Displays an Image received from another blaubot device. */ public class VideoViewerItemPane extends JLayeredPane { private static final int RECEIVED_DATE_LABEL_HEIGHT = 20; private static final Color TRANSPARENT_COLOR = new Color(0,0,0,0); private static final Color OVERLAY_BACKGROUND = new Color(255,255,255,55); private static final Dimension STATE_IMAGE_SIZE = new Dimension(40, 40); /** * The max height for the displayed images */ public static final int DEFAULT_IMAGE_MAX_HEIGHT = 300; private JLabel uniqueDeviceIdAndStateLabel; private JLabel stateImageContainer; private JLabel receivedDateLabel; /** * Holds the uniqueDeviceID and state image of the device where the image was received from */ private JPanel overlayPanel; /** * The actual received image */ private JLabel imageContainer; /** * Last state, that we set for the image container */ private State lastSetState; /** * Max height of received images. * Images with greater height will be scaled down. */ private int maxImageHeight = DEFAULT_IMAGE_MAX_HEIGHT; public VideoViewerItemPane() { uniqueDeviceIdAndStateLabel = new JLabel(); stateImageContainer = new JLabel(); stateImageContainer.setBackground(TRANSPARENT_COLOR); stateImageContainer.setSize(STATE_IMAGE_SIZE); stateImageContainer.setPreferredSize(STATE_IMAGE_SIZE); stateImageContainer.setMaximumSize(STATE_IMAGE_SIZE); receivedDateLabel = new JLabel(); imageContainer = new JLabel(); overlayPanel = new JPanel(); overlayPanel.setLayout(new FlowLayout(FlowLayout.LEFT)); overlayPanel.setBackground(OVERLAY_BACKGROUND); overlayPanel.add(stateImageContainer); overlayPanel.add(uniqueDeviceIdAndStateLabel); add(overlayPanel); add(receivedDateLabel); add(imageContainer); } public VideoViewerItemPane(ImageMessage imageMessage, State lastKnownState) { this(); setImageMessage(imageMessage, lastKnownState); } /** * The max height for received images. * Images with greater height will be downscaled. * @param maxImageHeight the max height */ public void setMaxImageHeight(int maxImageHeight) { this.maxImageHeight = maxImageHeight; } /** * Sets the image message to be displayed. * @param imageMessage the image message * @param lastKnownState the last known state of the sender of the imageMessage */ public void setImageMessage(ImageMessage imageMessage, State lastKnownState) { updateViews(imageMessage, lastKnownState); } private void updateViews(final ImageMessage imageMessage, final State lastKnownState) { ImageIcon icon = imageMessage.toImageIcon(); final Dimension iconDimensions;// = new Dimension(icon.getIconWidth(), icon.getIconHeight()); final int maxImageHeight = this.maxImageHeight; if (icon.getIconHeight() > maxImageHeight) { double factor = ((double) maxImageHeight) / ((double) icon.getIconHeight()); iconDimensions = new Dimension((int) (icon.getIconWidth() * factor), (int) (icon.getIconHeight() * factor)); Image img = icon.getImage(); Image scaledImg = img.getScaledInstance((int)iconDimensions.getWidth(), (int)iconDimensions.getHeight(), Image.SCALE_FAST); icon.setImage(scaledImg); } else { iconDimensions = new Dimension(icon.getIconWidth(), icon.getIconHeight()); } final ImageIcon fIcon = icon; final Dimension overlayPanelDimensions = new Dimension((int)iconDimensions.getWidth(), STATE_IMAGE_SIZE.height + 10); // pre-process stateIcon final boolean stateChanged = this.lastSetState != null ? !this.lastSetState.equals(lastKnownState) : lastKnownState != null; final ImageIcon stateIcon; if (stateChanged) { Image imageForState = Util.getImageForState(lastKnownState); imageForState = imageForState.getScaledInstance(STATE_IMAGE_SIZE.width, STATE_IMAGE_SIZE.height, Image.SCALE_DEFAULT); stateIcon = new ImageIcon(imageForState); lastSetState = lastKnownState; } else { stateIcon = null; } // pre-process unique device id icons StringBuilder sb = new StringBuilder("<html>"); if (lastKnownState != null) { sb.append(lastKnownState.name()); sb.append("<br>"); } sb.append("<small>"); sb.append(imageMessage.getUniqueDeviceId()); sb.append("</small></html>"); final String labelText = sb.toString(); // update the pre-processed values SwingUtilities.invokeLater(new Runnable() { @Override public void run() { if (imageMessage == null) { return; } receivedDateLabel.setText("<html><small>" + imageMessage.getTime().toString() + "</small></html>"); // dimensions of components setSize(iconDimensions); setPreferredSize(iconDimensions); setMinimumSize(iconDimensions); setMaximumSize(iconDimensions); overlayPanel.setSize(overlayPanelDimensions); overlayPanel.setPreferredSize(overlayPanelDimensions); overlayPanel.setMinimumSize(overlayPanelDimensions); overlayPanel.setMaximumSize(overlayPanelDimensions); imageContainer.setSize(iconDimensions); imageContainer.setPreferredSize(iconDimensions); imageContainer.setMinimumSize(iconDimensions); imageContainer.setMaximumSize(iconDimensions); // positioning receivedDateLabel.setBounds(5, ((int)iconDimensions.getHeight()) - RECEIVED_DATE_LABEL_HEIGHT, (int)iconDimensions.getWidth(), RECEIVED_DATE_LABEL_HEIGHT); // maintain the senders name uniqueDeviceIdAndStateLabel.setText(labelText); // the sender's state icon if (stateChanged && stateIcon != null) { stateImageContainer.setIcon(stateIcon); } // the actual image imageContainer.setIcon(fIcon); } }); } }