package org.docear.plugin.core.ui; import java.awt.AlphaComposite; import java.awt.Component; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.LayoutManager; import java.awt.Point; import java.awt.event.ContainerEvent; import java.awt.event.ContainerListener; import java.util.ArrayList; import java.util.List; import javax.swing.JComponent; import javax.swing.JViewport; import javax.swing.SwingUtilities; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import org.docear.plugin.core.ui.IViewportOverlay.VIEW_CHANGE; public class OverlayViewport extends JViewport { private static final long serialVersionUID = 1L; private final OverlayLayoutManager layoutManager; private final List<IViewportOverlay> overlayComponents = new ArrayList<IViewportOverlay>(); /*********************************************************************************** * CONSTRUCTORS **********************************************************************************/ public OverlayViewport(JViewport viewport) { this.layoutManager = new OverlayLayoutManager(viewport.getLayout()); super.setLayout(this.layoutManager); super.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { paintOverlays(getGraphics()); } }); } }); super.addContainerListener(new ContainerListener() { @Override public void componentRemoved(ContainerEvent e) { dispatchChangeEvent(VIEW_CHANGE.REMOVE, e); } @Override public void componentAdded(ContainerEvent e) { dispatchChangeEvent(VIEW_CHANGE.ADD,e); } }); } protected void dispatchChangeEvent(VIEW_CHANGE changeType, ContainerEvent e) { synchronized (overlayComponents) { for (IViewportOverlay overlay : overlayComponents) { overlay.viewChanged(changeType, e); } } } public void enableOverlays(boolean b) { synchronized (overlayComponents) { for (IViewportOverlay overlay : overlayComponents) { Component comp = overlay.getComponent(); comp.setVisible(b); } } } /*********************************************************************************** * METHODS **********************************************************************************/ public void addOverlay(IViewportOverlay overlay) { synchronized (overlayComponents) { this.overlayComponents.add(overlay); overlay.setParent(this); Component comp = overlay.getComponent(); if(comp == null) { throw new RuntimeException("IViewportOverlay.getComponent() must not return NULL"); } this.layoutManager.addLayoutComponent(overlay.getPositionConstraints(), comp); fireStateChanged(); } } public void removeOverlay(IViewportOverlay overlay) { synchronized (overlayComponents) { this.overlayComponents.remove(overlay); overlay.setParent(null); Component comp = overlay.getComponent(); if(comp == null) { throw new RuntimeException("IViewportOverlay.getComponent() must not return NULL"); } this.layoutManager.removeLayoutComponent(comp); fireStateChanged(); } } public IViewportOverlay[] getOverlays() { synchronized (overlayComponents) { return overlayComponents.toArray(new IViewportOverlay[0]); } } public void paint(Graphics g) { super.paint(g); } public JComponent getIntersectingOverlay(Point point) { synchronized (overlayComponents) { for (IViewportOverlay overlay : overlayComponents) { Component comp = overlay.getComponent(); if(comp.getBounds().contains(point) && comp.isVisible()) { return (JComponent) comp; } } } return null; } private void paintOverlays(Graphics gr) { if (this.isShowing()) { prepareAreas(); Graphics2D g = (Graphics2D) getGraphics(); AlphaComposite ac = AlphaComposite.getInstance(AlphaComposite.SRC_OVER,0.5F); g.setComposite(ac); int width = getWidth(); int height = getHeight(); if ((width <= 0) || (height <= 0)) { return; } for (IViewportOverlay overlay : getOverlays()) { Component comp = overlay.getComponent(); if(comp.isVisible()) { g.translate(comp.getX(), comp.getY()); comp.paint(g); } } } } private void prepareAreas() { synchronized (overlayComponents) { } } protected void paintChildren(Graphics g) { super.paintChildren(g); paintOverlays(g); } public void setLayout(LayoutManager layout) { } /*********************************************************************************** * REQUIRED METHODS FOR INTERFACES **********************************************************************************/ }