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

eu.limetri.client.mapviewer.nb.jxmap.map.LegendPanel Maven / Gradle / Ivy

There is a newer version: 1.4.4
Show newest version
/**
 * Copyright (C) 2008-2012 AgroSense Foundation.
 *
 * AgroSense 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.
 *
 * There are special exceptions to the terms and conditions of the GPLv3 as it is applied to
 * this software, see the FLOSS License Exception
 * .
 *
 * AgroSense 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 AgroSense.  If not, see .
 */
package eu.limetri.client.mapviewer.nb.jxmap.map;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
import javax.swing.border.BevelBorder;

import net.miginfocom.swing.MigLayout;

import org.jdesktop.swingx.JXPanel;
import org.jdesktop.swingx.painter.CompoundPainter;
import org.jdesktop.swingx.painter.MattePainter;
import org.jdesktop.swingx.painter.PinstripePainter;
import org.openide.explorer.ExplorerManager;
import org.openide.nodes.Node;
import org.openide.nodes.NodeEvent;
import org.openide.nodes.NodeListener;
import org.openide.nodes.NodeMemberEvent;
import org.openide.nodes.NodeReorderEvent;
import org.openide.util.NbBundle;

import eu.limetri.client.mapviewer.api.Layer;
import eu.limetri.client.mapviewer.api.LegendPalette;
import eu.limetri.client.mapviewer.api.RangedLegendPalette;
import eu.limetri.client.mapviewer.nb.jxmap.MapViewerTopComponent;
import javax.swing.JButton;

/**
 * Panel for legends Listens to the {@link ExplorerManager} one of the parents
 * of this component must have if a node is added or removed will use {@link MapViewerTopComponent#getMapDataManager()}
 * to get the datamanager. Will check it's nodes if there is one and only one {@link LegendPalette}
 * as pallete in the nodes. If this is the case will display the legend
 *
 * @author Merijn Zengers 
 */
@NbBundle.Messages("LegendPanel title message=Legend")
//FIXME:Also listen to setPallete changes on layer
public class LegendPanel extends JXPanel {

    private static final Dimension FULL_DIMENSION = new Dimension(200, 600);
    private static final Dimension LEGEND_DIMENSION = new Dimension(120, 200);
    private static final Color COLOR_SHADOW = new Color(150, 150, 150);
    private static final Color COLOR_HIGH = new Color(210, 210, 210);
    private static final Color COLOR_BASE = new Color(225, 225, 225);
    private static final Dimension COLOR_BLOCK_DIMENSION = new Dimension(20, 20);
    private final RootNodeListener rootNodeListener = new RootNodeListener();
    private transient ExplorerManager explorer;
    private JXPanel legendColorPanel;
    private JXPanel legendActionPanel;
    private final JLabel subtitleLabel = new JLabel("");
    private List currentlyShowing = new ArrayList<>();
    private final PaletteListener paletteListener = new PaletteListener();
    private JButton rangeButton;

    public LegendPanel() {
        init();
    }

    private void init() {
        setLayout(new BorderLayout());
        setOpaque(false);
        JPanel mainPanel = new JPanel();
        mainPanel.setOpaque(false);
        mainPanel.setPreferredSize(FULL_DIMENSION);
        mainPanel.setLayout(new MigLayout("wrap, align right"));

        JXPanel legendTitlePanel = new JXPanel(new MigLayout("wrap 2, insets 0 0 0 0"));
        legendTitlePanel.setBackground(COLOR_HIGH);
        legendTitlePanel.setDoubleBuffered(true);
        legendTitlePanel.setAlpha(.8f);


        legendTitlePanel.add(new JLabel(Bundle.LegendPanel_title_message()));
        subtitleLabel.setHorizontalAlignment(SwingConstants.TRAILING);
        legendTitlePanel.add(subtitleLabel);
        
        //TODO:  action/button panel
        // allow customization of range (and maybe later unit as well)
        legendActionPanel = new JXPanel();
        legendActionPanel.setLayout(new MigLayout("wrap 2, insets 0 0 0 0"));
        legendActionPanel.setBackground(COLOR_HIGH);
        legendActionPanel.setAlpha(.8f);
        
        rangeButton = new JButton(Bundle.range_settings_action_name());
        rangeButton.setEnabled(false);
        legendActionPanel.add(rangeButton);

        legendColorPanel = new JXPanel();
        legendColorPanel.setLayout(new MigLayout("wrap 2, insets 0 0 0 0"));
        legendColorPanel.setBackground(COLOR_HIGH);
        legendColorPanel.setDoubleBuffered(true);
        legendColorPanel.setAlpha(.8f);

        PinstripePainter stripes = new PinstripePainter();
        stripes.setPaint(new Color(1.0f, 1.0f, 1.0f, 0.17f));
        stripes.setSpacing(5.0);

        MattePainter matte = new MattePainter(COLOR_BASE);

        JXPanel legendMainPanel = new JXPanel(new MigLayout("wrap"));
        legendMainPanel.setBorder(new BevelBorder(BevelBorder.RAISED, COLOR_HIGH, COLOR_SHADOW));
        legendMainPanel.setBackground(COLOR_HIGH);
        legendMainPanel.setDoubleBuffered(true);
        legendMainPanel.setAlpha(.8f);
        legendMainPanel.setPreferredSize(LEGEND_DIMENSION);
        legendMainPanel.setBackgroundPainter(new CompoundPainter(matte, stripes));
        legendMainPanel.add(legendTitlePanel);
        legendMainPanel.add(legendActionPanel);
        legendMainPanel.add(legendColorPanel);

        mainPanel.add(legendMainPanel);
        this.add(mainPanel, BorderLayout.CENTER);
        this.setVisible(false);
    }
    
    // package private for mocking
    void setSubtitle(String s) {
        subtitleLabel.setText(s);
    }
    
    @Override
    public void addNotify() {
        super.addNotify();
        getExplorerManager().getRootContext().addNodeListener(rootNodeListener);
    }

    ExplorerManager getExplorerManager() {
        if (explorer == null) {
            explorer = ExplorerManager.find(this);
            assert explorer != null : "This component needs a parent wich is an ExplorerManager.Provider";
        }
        return explorer;
    }

    /**
     * 

Activates the legend

Will set the visibility of this component * to true
Will add a property change listener on the palette it is * currently showing

* * @param legendPalette */ void activateLegend(List legendPalettes) { this.setVisible(true); currentlyShowing = legendPalettes; updateLegend(); //Register listeners for (LegendPalette palette : legendPalettes) { palette.addPropertyChangeListener(paletteListener); } } /** *

Deactivate the legend

Will set this components visibility to * false
if this component is currently showing a palette will * unregister property change listener on it

* * @param legendPalette */ void deactivateLegend(List legendPalettes) { this.setVisible(false); //Check if we are not showing if we are unregister listeners if (legendPalettes != null) { for (LegendPalette palette : legendPalettes) { palette.removePropertyChangeListener(paletteListener); } currentlyShowing.clear(); } } /** * Updates the legend Adds all the Legend colors and descriptions to the * legend */ void updateLegend() { if (currentlyShowing != null && !currentlyShowing.isEmpty()) { legendColorPanel.removeAll(); for (LegendPalette.Entry legendColor : currentlyShowing.iterator().next().getEntries()) { JLabel colorLabel = new JLabel("#"); colorLabel.setBackground(legendColor.getColor()); colorLabel.setForeground(legendColor.getColor()); colorLabel.setPreferredSize(COLOR_BLOCK_DIMENSION); legendColorPanel.add(colorLabel); legendColorPanel.add(new JLabel(legendColor.getDescription())); } repaint(); revalidate(); } } /** * Checks if the nodes currently managed have a LegendPalette */ final void palettesChanged() { //First clear everything deactivateLegend(currentlyShowing); //Find out if there are LegendPalette(s) in the lookup of the nodes Set palettes = new HashSet<>(); Node[] existingNodes = getExplorerManager().getRootContext().getChildren().getNodes(); List possibleShowing = new ArrayList<>(); for (Node existingNode : existingNodes) { LegendPalette palette = getLegendPaletteFromNode(existingNode); if (palette != null) { palettes.add(palette); possibleShowing.add(palette); } else { //There is a node without a legend palette we cannot show return; } } //Only activate if there is only one unique LegendPalette in the found nodes if (palettes.size() == 1) { String unit = palettes.iterator().next().getUnit(); setSubtitle(unit == null ? null : "(" + unit+ ")"); activateLegend(possibleShowing); updateRangeButton(possibleShowing); } } void updateRangeButton(List possibleShowing) { List> rangedPalettes = new ArrayList<>(); for (LegendPalette lp : possibleShowing) { if (lp instanceof RangedLegendPalette) { //FIXME: needs better test for generic type (or get rid of it altogether since we use double everywhere anyway) try { RangedLegendPalette rlp = (RangedLegendPalette) lp; rangedPalettes.add(rlp); } catch (ClassCastException cce) {} } } if (!rangedPalettes.isEmpty()) { rangeButton.setAction(new CustomRangeAction(rangedPalettes)); rangeButton.setEnabled(true); } else { rangeButton.setAction(null); rangeButton.setEnabled(false); } } /** * Get the {@link legend palette from the node} * * @param node * @return LegendPalette if found else null */ LegendPalette getLegendPaletteFromNode(Node node) { Layer layer = node.getLookup().lookup(Layer.class); if (layer != null && layer.getPalette() instanceof LegendPalette) { return (LegendPalette) layer.getPalette(); } return null; } private class PaletteListener implements PropertyChangeListener { @Override public void propertyChange(PropertyChangeEvent pce) { palettesChanged(); } } /** * listener for changes in nodes in the explorer manager */ private class RootNodeListener implements NodeListener { @Override public void childrenAdded(NodeMemberEvent ev) { palettesChanged(); } @Override public void childrenRemoved(NodeMemberEvent ev) { palettesChanged(); } @Override public void childrenReordered(NodeReorderEvent ev) { throw new UnsupportedOperationException("Not supported yet."); } @Override public void nodeDestroyed(NodeEvent ev) { throw new UnsupportedOperationException("Not supported yet."); } @Override public void propertyChange(PropertyChangeEvent evt) { throw new UnsupportedOperationException("Not supported yet."); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy