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

it.tidalwave.geo.viewer.impl.GeoViewerTopComponent Maven / Gradle / Ivy

/***********************************************************************************************************************
 *
 * forceTen - open source geography
 * Copyright (C) 2007-2012 by Tidalwave s.a.s. (http://www.tidalwave.it)
 *
 ***********************************************************************************************************************
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations under the License.
 *
 ***********************************************************************************************************************
 *
 * WWW: http://forceten.tidalwave.it
 * SCM: https://bitbucket.org/tidalwave/forceten-src
 *
 **********************************************************************************************************************/
package it.tidalwave.geo.viewer.impl;

import javax.annotation.Nonnull;
import javax.annotation.PostConstruct;
import javax.inject.Inject;
import javax.inject.Provider;
import java.util.List;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.awt.BorderLayout;
import javax.swing.ActionMap;
import javax.swing.text.DefaultEditorKit;
import org.jdesktop.beansbinding.AutoBinding.UpdateStrategy;
import org.jdesktop.beansbinding.BeanProperty;
import org.jdesktop.beansbinding.BindingGroup;
import org.jdesktop.beansbinding.Bindings;
import org.jdesktop.observablecollections.ObservableList;
import org.jdesktop.observablecollections.ObservableListListener;
import org.openide.explorer.ExplorerManager;
import org.openide.explorer.ExplorerUtils;
import org.openide.windows.TopComponent;
import org.openide.windows.WindowManager;
import org.openide.util.Lookup;
import org.openide.util.NbBundle;
import org.openide.util.lookup.Lookups;
import org.openide.util.lookup.ProxyLookup;
import it.tidalwave.util.logging.Logger;
import it.tidalwave.swing.PropertyManager;
import it.tidalwave.netbeans.windows.EnhancedTopComponent;
import it.tidalwave.netbeans.nodes.role.RootNodeProvider;
import it.tidalwave.netbeans.print.ComponentPrintCookie;
import it.tidalwave.util.NotFoundException;
import it.tidalwave.geo.viewer.GeoViewerPresentation;
import it.tidalwave.geo.viewer.GeoViewProviderManager;
import it.tidalwave.geo.viewer.role.GeoViewerUI;
import it.tidalwave.geo.viewer.spi.GeoViewProvider;

/***********************************************************************************************************************
 *
 * @author  Fabrizio Giudici
 * @version $Id$
 *
 **********************************************************************************************************************/
public final class GeoViewerTopComponent extends EnhancedTopComponent implements GeoViewerPresentation
  {
    private static final long serialVersionUID = 2340598234098234654L;
    private static final String CLASS = GeoViewerTopComponent.class.getName();
    private static final Logger logger = Logger.getLogger(CLASS);
    private static final String PREFERRED_ID = GeoViewerPresentation.ID;
    
    private static GeoViewerTopComponent instance;
    
    private final ExplorerManager explorerManager = new ExplorerManager();

    private final Lookup lookup;

    @Inject
    private Provider geoViewProviderManager;

    @Inject
    private GeoViewerUI geoViewerUI;

    @Inject
    private GeoRendererPanel geoRendererPanel;

    private final ActionMap map = new ActionMap();

    private final BindingGroup bindingGroup = new BindingGroup();

    /*******************************************************************************************************************
     *
     *
     ******************************************************************************************************************/
    private GeoViewerTopComponent()
      {
        setName(NbBundle.getMessage(GeoViewerTopComponent.class, "CTL_GeoViewerTopComponent"));
        installUIResources();

        // FIXME: this should be put in a reusable Role
        try
          {
            map.put(DefaultEditorKit.copyAction, ExplorerUtils.actionCopy(explorerManager));
            map.put(DefaultEditorKit.cutAction, ExplorerUtils.actionCut(explorerManager));
            // The standard paste action gets disabled with multiple nodes selected
            map.put(DefaultEditorKit.pasteAction, ExplorerUtils.actionPaste(explorerManager));
    //        map.put(DefaultEditorKit.pasteAction, SystemAction.get(MultiPasteAction.class));
            map.put("delete", ExplorerUtils.actionDelete(explorerManager, true)); // or false
          }
        catch (Throwable e) // when used outside NetBeans RCP
          {
            logger.info("No default actions");
          }
                        
        lookup = new ProxyLookup(super.getLookup(),
                                 ExplorerUtils.createLookup(explorerManager, map),
                                 Lookups.fixed(new ComponentPrintCookie(this)));
//        associateLookup(lookup);
//        associateLookup(PrintSupport.createPrintingLookup());
      }

    /*******************************************************************************************************************
     *
     *
     *
     ******************************************************************************************************************/
    public void clearSceneFacade() // FIXME: drop this
      {
        logger.fine("clearSceneFacade()");
//        getLookup().lookup(JXMapViewerSupport.class).getSceneFacade().clear();
      }

    /*******************************************************************************************************************
     *
     * {@inheritDoc}
     *
     ******************************************************************************************************************/
    @Override @Nonnull 
    public Lookup getLookup()
      {
        return lookup;
      }

    /*******************************************************************************************************************
     *
     * {@inheritDoc}
     *
     ******************************************************************************************************************/
    @Override
    public int getPersistenceType()
      {
        return TopComponent.PERSISTENCE_ALWAYS;
      }
     
    /*******************************************************************************************************************
     *
     * {@inheritDoc}
     *
     ******************************************************************************************************************/
    @Override @Nonnull
    public String preferredID()
      {
        return PREFERRED_ID;
      }

    /*******************************************************************************************************************
     *
     * {@inheritDoc}
     *
     ******************************************************************************************************************/
    @Override
    public void writeExternal (final @Nonnull ObjectOutput out)
      throws IOException       
      {
        super.writeExternal(out);
        // FIXME: move to a specific role
        final GeoViewProvider selectedGeoViewProvider = geoViewProviderManager.get().getSelectedGeoViewProvider();
        out.writeUTF(selectedGeoViewProvider.getName());
      }

    /*******************************************************************************************************************
     *
     * {@inheritDoc}
     *
     ******************************************************************************************************************/
    @Override
    public void readExternal (final @Nonnull ObjectInput in)
      throws IOException, ClassNotFoundException 
      {
        super.readExternal(in);
        
        // FIXME: move to a specific role
        try
          {
            final String mapProviderName = in.readUTF();

            for (final GeoViewProvider geoViewProvider : geoViewProviderManager.get().getGeoViewProviders())
              {
                if (geoViewProvider.getName().equals(mapProviderName))
                  {
                    geoViewProviderManager.get().setSelectedGeoViewProvider(geoViewProvider);
                    break;
                  }
              }
          }
        catch (IOException e)
          {
            logger.warning("Handling exception in readExternal(): %s", e);
          }
      }

    /*******************************************************************************************************************
     *
     * Finishes the creation of the UI and binds some parts together.
     *
     ******************************************************************************************************************/
    @PostConstruct
    @SuppressWarnings("PMD.UnusedPrivateMethod") @edu.umd.cs.findbugs.annotations.SuppressWarnings("UPM_UNCALLED_PRIVATE_METHOD")
    private void initialize()
      {
        setLayout(new BorderLayout());
        add(geoViewerUI, BorderLayout.CENTER);

        // FIXME But the root node should be returned from the GeoProvider since it should be different for 2D and 3D
        final RootNodeProvider rootNodeProvider = getLookup().lookup(RootNodeProvider.class);

        if (rootNodeProvider != null)
          {
            try
              {
                explorerManager.setRootContext(rootNodeProvider.getRootNode());
              }
            catch (NotFoundException e)
              {
                logger.severe("Can't set root context");
                logger.throwing(CLASS, "initialize()", e);
              }
          }

        // FIXME: you should listen for changes and eventually rebind
        final GeoViewProviderManager gvpm = geoViewProviderManager.get();
        bind(gvpm.getGeoViewProviders(), geoViewerUI.getGeoViewProviders());
        bindingGroup.addBinding(Bindings.createAutoBinding(UpdateStrategy.READ_WRITE, gvpm,
                                         BeanProperty.create(GeoViewProviderManager.PROP_SELECTED_GEO_VIEW_PROVIDER),
                                         geoViewerUI,
                                         BeanProperty.create(GeoViewerUI.PROP_SELECTED_GEO_VIEW_PROVIDER)));
        bindingGroup.addBinding(Bindings.createAutoBinding(UpdateStrategy.READ, gvpm,
                                         BeanProperty.create(GeoViewProviderManager.PROP_SELECTED_GEO_VIEW_PROVIDER),
                                         geoRendererPanel,
                                         BeanProperty.create(GeoRendererPanel.PROP_SELECTED_GEO_VIEW_PROVIDER)));
        bindingGroup.bind();
      }

    /*******************************************************************************************************************
     *
     *
     ******************************************************************************************************************/
    private void installUIResources() 
      {
        PropertyManager.configure(this, "GeoViewerTopComponent"); // FIXME: what's this?
      }
    
    /*******************************************************************************************************************
     *
     * Gets default instance. Do not use directly: reserved for *.settings files only, i.e. deserialization routines;
     * otherwise you could get a non-deserialized instance. To obtain the singleton instance, use {@link findInstance}.
     *
     ******************************************************************************************************************/
    @Nonnull
    public static synchronized GeoViewerTopComponent getDefault()
      {
        if (instance == null)
          {
            instance = new GeoViewerTopComponent();
          }
        
        return instance;
      }
    
    /*******************************************************************************************************************
     *
     * Obtain the MapViewerTopComponent instance. Never call {@link #getDefault} directly!
     *
     ******************************************************************************************************************/
    @Nonnull
    public static synchronized GeoViewerTopComponent findInstance()
      {
        TopComponent component = null;
        
        try
          {
            component = WindowManager.getDefault().findTopComponent(PREFERRED_ID);
          }
        catch (NoClassDefFoundError e)
          {
            logger.info("No WindowManager available");
          }
      
        if (component == null)
          {
            logger.warning("Cannot find Mapping component. It will not be located properly in the window system.");
            return getDefault();
          }
        
        if (component instanceof GeoViewerTopComponent)
          {
            return (GeoViewerTopComponent)component;
          }
        
        logger.warning("There seem to be multiple components with the '%s' ID. That is a potential source of errors " +
                       "and unexpected behavior.", PREFERRED_ID);
        
        return getDefault();
      }

    // FIXME: any smarter way to keep two ObservableLists in sync?
    private static  void bind (final @Nonnull ObservableList source,
                                  final @Nonnull ObservableList target)
      {
        target.clear();
        target.addAll(source);
        source.addObservableListListener(new ObservableListListener()
          {
            @Override
            public void listElementsAdded(ObservableList ol, int i, int i1)
              {
                target.clear();
                target.addAll(source);
              }

            @Override
            public void listElementsRemoved(ObservableList ol, int i, List list)
              {
                target.clear();
                target.addAll(source);
              }

            @Override
            public void listElementReplaced(ObservableList ol, int i, Object o)
              {
                target.clear();
                target.addAll(source);
              }

            @Override
            public void listElementPropertyChanged(ObservableList ol, int i)
              {
                target.clear();
                target.addAll(source);
              }
          });
      }
  }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy