Package com.eteks.sweethome3d.applet

Source Code of com.eteks.sweethome3d.applet.ViewerHelper

/*
* ViewerHelper.java 31 mars 2009
*
* Sweet Home 3D, Copyright (c) 2009 Emmanuel PUYBARET / eTeks <info@eteks.com>
*
* 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 2 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, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/
package com.eteks.sweethome3d.applet;

import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.io.IOException;
import java.io.InterruptedIOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.concurrent.Callable;

import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JApplet;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRootPane;
import javax.swing.KeyStroke;
import javax.swing.UIManager;

import com.eteks.sweethome3d.io.DefaultHomeInputStream;
import com.eteks.sweethome3d.j3d.Component3DManager;
import com.eteks.sweethome3d.j3d.ModelManager;
import com.eteks.sweethome3d.j3d.TextureManager;
import com.eteks.sweethome3d.model.BackgroundImage;
import com.eteks.sweethome3d.model.CatalogPieceOfFurniture;
import com.eteks.sweethome3d.model.CatalogTexture;
import com.eteks.sweethome3d.model.FurnitureCatalog;
import com.eteks.sweethome3d.model.Home;
import com.eteks.sweethome3d.model.InterruptedRecorderException;
import com.eteks.sweethome3d.model.RecorderException;
import com.eteks.sweethome3d.model.UserPreferences;
import com.eteks.sweethome3d.swing.HomeComponent3D;
import com.eteks.sweethome3d.swing.ThreadedTaskPanel;
import com.eteks.sweethome3d.tools.OperatingSystem;
import com.eteks.sweethome3d.viewcontroller.BackgroundImageWizardController;
import com.eteks.sweethome3d.viewcontroller.CompassController;
import com.eteks.sweethome3d.viewcontroller.DialogView;
import com.eteks.sweethome3d.viewcontroller.FurnitureCatalogController;
import com.eteks.sweethome3d.viewcontroller.FurnitureController;
import com.eteks.sweethome3d.viewcontroller.HelpController;
import com.eteks.sweethome3d.viewcontroller.HelpView;
import com.eteks.sweethome3d.viewcontroller.Home3DAttributesController;
import com.eteks.sweethome3d.viewcontroller.HomeController;
import com.eteks.sweethome3d.viewcontroller.HomeController3D;
import com.eteks.sweethome3d.viewcontroller.HomeFurnitureController;
import com.eteks.sweethome3d.viewcontroller.HomeView;
import com.eteks.sweethome3d.viewcontroller.ImportedFurnitureWizardController;
import com.eteks.sweethome3d.viewcontroller.ImportedFurnitureWizardStepsView;
import com.eteks.sweethome3d.viewcontroller.ImportedTextureWizardController;
import com.eteks.sweethome3d.viewcontroller.LabelController;
import com.eteks.sweethome3d.viewcontroller.VideoController;
import com.eteks.sweethome3d.viewcontroller.PageSetupController;
import com.eteks.sweethome3d.viewcontroller.PhotoController;
import com.eteks.sweethome3d.viewcontroller.PlanController;
import com.eteks.sweethome3d.viewcontroller.PlanView;
import com.eteks.sweethome3d.viewcontroller.PrintPreviewController;
import com.eteks.sweethome3d.viewcontroller.RoomController;
import com.eteks.sweethome3d.viewcontroller.TextureChoiceController;
import com.eteks.sweethome3d.viewcontroller.TextureChoiceView;
import com.eteks.sweethome3d.viewcontroller.ThreadedTaskController;
import com.eteks.sweethome3d.viewcontroller.ThreadedTaskView;
import com.eteks.sweethome3d.viewcontroller.UserPreferencesController;
import com.eteks.sweethome3d.viewcontroller.View;
import com.eteks.sweethome3d.viewcontroller.ViewFactory;
import com.eteks.sweethome3d.viewcontroller.WallController;
import com.eteks.sweethome3d.viewcontroller.WizardController;

/**
* Helper for {@link SweetHome3DViewer SweetHome3DViewer}. This class is public
* because it's loaded by applet viewer class loader as a start point.
* @author Emmanuel Puybaret
*/
public final class ViewerHelper {
  private static final String HOME_URL_PARAMETER     = "homeURL";
  private static final String IGNORE_CACHE_PARAMETER = "ignoreCache";
  private static final String NAVIGATION_PANEL       = "navigationPanel";
 
  public ViewerHelper(final JApplet applet) {
    // Create default user preferences with no catalog
    final UserPreferences preferences = new UserPreferences() {
        @Override
        public void addLanguageLibrary(String languageLibraryName) throws RecorderException {
          throw new UnsupportedOperationException();
        }
 
        @Override
        public boolean languageLibraryExists(String languageLibraryName) throws RecorderException {
          throw new UnsupportedOperationException();
        }

        @Override
        public void addFurnitureLibrary(String furnitureLibraryName) throws RecorderException {
          throw new UnsupportedOperationException();
        }
 
        @Override
        public boolean furnitureLibraryExists(String furnitureLibraryName) throws RecorderException {
          throw new UnsupportedOperationException();
        }
 
        @Override
        public boolean texturesLibraryExists(String name) throws RecorderException {
          throw new UnsupportedOperationException();
        }

        @Override
        public void addTexturesLibrary(String name) throws RecorderException {
          throw new UnsupportedOperationException();
        }

        @Override
        public void write() throws RecorderException {
          throw new UnsupportedOperationException();
        }
       
        @Override
        public boolean isNavigationPanelVisible() {
          return "true".equalsIgnoreCase(applet.getParameter(NAVIGATION_PANEL));
        }
      };
   
    // Create a view factory able to instantiate only a 3D view and a threaded task view
    final ViewFactory viewFactory = new ViewFactory() {
        public View createBackgroundImageWizardStepsView(BackgroundImage backgroundImage, UserPreferences preferences,
                                                         BackgroundImageWizardController backgroundImageWizardController) {
          throw new UnsupportedOperationException();
        }

        public View createFurnitureCatalogView(FurnitureCatalog catalog, UserPreferences preferences,
                                               FurnitureCatalogController furnitureCatalogController) {
          throw new UnsupportedOperationException();
        }

        public View createFurnitureView(Home home, UserPreferences preferences, FurnitureController furnitureController) {
          throw new UnsupportedOperationException();
        }

        public HelpView createHelpView(UserPreferences preferences, HelpController helpController) {
          throw new UnsupportedOperationException();
        }

        public DialogView createHome3DAttributesView(UserPreferences preferences,
                                                     Home3DAttributesController home3DAttributesController) {
          throw new UnsupportedOperationException();
        }

        public DialogView createHomeFurnitureView(UserPreferences preferences,
                                                  HomeFurnitureController homeFurnitureController) {
          throw new UnsupportedOperationException();
        }

        public HomeView createHomeView(Home home, UserPreferences preferences, HomeController homeController) {
          throw new UnsupportedOperationException();
        }

        public ImportedFurnitureWizardStepsView createImportedFurnitureWizardStepsView(CatalogPieceOfFurniture piece,
                    String modelName, boolean importHomePiece, UserPreferences preferences,
                    ImportedFurnitureWizardController importedFurnitureWizardController) {
          throw new UnsupportedOperationException();
        }

        public View createImportedTextureWizardStepsView(CatalogTexture texture, String textureName,
                                                         UserPreferences preferences,
                                                         ImportedTextureWizardController importedTextureWizardController) {
          throw new UnsupportedOperationException();
        }

        public DialogView createLabelView(boolean modification, UserPreferences preferences,
                                          LabelController labelController) {
          throw new UnsupportedOperationException();
        }

        public DialogView createPageSetupView(UserPreferences preferences, PageSetupController pageSetupController) {
          throw new UnsupportedOperationException();
        }

        public PlanView createPlanView(Home home, UserPreferences preferences, PlanController planController) {
          throw new UnsupportedOperationException();
        }

        public DialogView createPrintPreviewView(Home home, UserPreferences preferences, HomeController homeController,
                                                 PrintPreviewController printPreviewController) {
          throw new UnsupportedOperationException();
        }

        public DialogView createRoomView(UserPreferences preferences, RoomController roomController) {
          throw new UnsupportedOperationException();
        }

        public TextureChoiceView createTextureChoiceView(UserPreferences preferences,
                                                         TextureChoiceController textureChoiceController) {
          throw new UnsupportedOperationException();
        }

        public ThreadedTaskView createThreadedTaskView(String taskMessage, UserPreferences preferences,
                                                       ThreadedTaskController controller) {
          return new ThreadedTaskPanel(taskMessage, preferences, controller) {
              private boolean taskRunning;
 
              public void setTaskRunning(boolean taskRunning, View executingView) {
                if (taskRunning && !this.taskRunning) {
                  // Display task panel directly at applet center if it's empty
                  this.taskRunning = taskRunning;
                  JPanel contentPane = new JPanel(new GridBagLayout());
                  contentPane.add(this, new GridBagConstraints());
                  applet.setContentPane(contentPane);
                  applet.getRootPane().revalidate();
                }
              }
            };
        }

        public DialogView createUserPreferencesView(UserPreferences preferences,
                                                    UserPreferencesController userPreferencesController) {
          throw new UnsupportedOperationException();
        }

        public View createView3D(final Home home, UserPreferences preferences, final HomeController3D controller) {
          HomeComponent3D homeComponent3D = new HomeComponent3D(home, preferences, controller);
          // Add tab key to input map to change camera
          InputMap inputMap = homeComponent3D.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
          inputMap.put(KeyStroke.getKeyStroke("SPACE"), "changeCamera");
          ActionMap actionMap = homeComponent3D.getActionMap();
          actionMap.put("changeCamera", new AbstractAction() {
              public void actionPerformed(ActionEvent ev) {
                if (home.getCamera() == home.getTopCamera()) {
                  controller.viewFromObserver();
                } else {
                  controller.viewFromTop();
                }
              }
            });
          return homeComponent3D;
        }

        public DialogView createWallView(UserPreferences preferences, WallController wallController) {
          throw new UnsupportedOperationException();
        }

        public DialogView createWizardView(UserPreferences preferences, WizardController wizardController) {
          throw new UnsupportedOperationException();
        }

        public DialogView createPhotoView(Home home, UserPreferences preferences, PhotoController photoController) {
          throw new UnsupportedOperationException();
        }

        public DialogView createVideoView(Home home, UserPreferences preferences, VideoController videoController) {
          throw new UnsupportedOperationException();
        }

        public DialogView createCompassView(UserPreferences preferences, CompassController compassController) {
          throw new UnsupportedOperationException();
        }
      };

    // Force offscreen in 3D view under Plugin 2 and Mac OS X
    System.setProperty("com.eteks.sweethome3d.j3d.useOffScreen3DView",
        String.valueOf(OperatingSystem.isMacOSX()           
            && applet.getAppletContext() != null
            && applet.getAppletContext().getClass().getName().startsWith("sun.plugin2.applet.Plugin2Manager")));

    initLookAndFeel();

    addComponent3DRenderingErrorObserver(applet.getRootPane(), preferences);

    // Retrieve displayed home
    String homeUrlParameter = applet.getParameter(HOME_URL_PARAMETER);
    if (homeUrlParameter == null) {
      homeUrlParameter = "default.sh3d";
    }
    // Retrieve ignoreCache parameter value
    String ignoreCacheParameter = applet.getParameter(IGNORE_CACHE_PARAMETER);
    final boolean ignoreCache = ignoreCacheParameter != null
        && "true".equalsIgnoreCase(ignoreCacheParameter);
    try {
      final URL homeUrl = new URL(applet.getDocumentBase(), homeUrlParameter);
      // Read home in a threaded task
      Callable<Void> openTask = new Callable<Void>() {
            public Void call() throws RecorderException {
              // Read home with application recorder
              Home openedHome = readHome(homeUrl, ignoreCache);
              displayHome(applet.getRootPane(), openedHome, preferences, viewFactory);
              return null;
            }
          };
      ThreadedTaskController.ExceptionHandler exceptionHandler =
          new ThreadedTaskController.ExceptionHandler() {
            public void handleException(Exception ex) {
              if (!(ex instanceof InterruptedRecorderException)) {
                if (ex instanceof RecorderException) {
                  showError(applet.getRootPane(),
                      preferences.getLocalizedString(ViewerHelper.class, "openError", homeUrl));
                } else {
                  ex.printStackTrace();
                }
              }
            }
          };
      new ThreadedTaskController(openTask,
          preferences.getLocalizedString(ViewerHelper.class, "openMessage"), exceptionHandler,
          null, viewFactory).executeTask(null);
    } catch (MalformedURLException ex) {
      showError(applet.getRootPane(),
          preferences.getLocalizedString(ViewerHelper.class, "openError", homeUrlParameter));
      return;
    }
  }
 
  /**
   * Clears all the resources used by the applet.
   * This method is called when an applet is destroyed. 
   */
  public void destroy() {
    // Collect deleted objects (seems to be required under Mac OS X when the applet is being reloaded)
    System.gc();
    // Stop managers threads
    TextureManager.getInstance().clear();
    ModelManager.getInstance().clear();
  }
 
  private void initLookAndFeel() {
    try {
      // Apply current system look and feel
      UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
      // Enable applets to update their content while window resizing
      Toolkit.getDefaultToolkit().setDynamicLayout(true);
    } catch (Exception ex) {
      // Too bad keep current look and feel
    }
  }

  /**
   * Sets the rendering error listener bound to Java 3D
   * to avoid default System exit in case of error during 3D rendering.
   */
  private void addComponent3DRenderingErrorObserver(final JRootPane rootPane,
                                                    final UserPreferences preferences) {
    // Instead of adding a RenderingErrorListener directly to VirtualUniverse,
    // we add it through Canvas3DManager, because offscreen rendering needs to check
    // rendering errors with its own RenderingErrorListener
    Component3DManager.getInstance().setRenderingErrorObserver(
        new Component3DManager.RenderingErrorObserver() {
          public void errorOccured(int errorCode, String errorMessage) {
            System.err.print("Error in Java 3D : " + errorCode + " " + errorMessage);
            EventQueue.invokeLater(new Runnable() {
                public void run() {
                  String message = preferences.getLocalizedString(
                      ViewerHelper.class, "3DErrorMessage");
                  showError(rootPane, message);
                }
              });
          }
        });
  }

  /**
   * Shows the given text in a label.
   */
  private static void showError(final JRootPane rootPane, String text) {
    JLabel label = new JLabel(text, JLabel.CENTER);
    rootPane.setContentPane(label);
    rootPane.revalidate();
  }

  /**
   * Reads a home from its URL.
   */
  private Home readHome(URL homeUrl, boolean ignoreCache) throws RecorderException {
    URLConnection connection = null;
    DefaultHomeInputStream in = null;
    try {
      // Open a home input stream to server
      connection = homeUrl.openConnection();
      connection.setRequestProperty("Content-Type", "charset=UTF-8");
      connection.setUseCaches(!ignoreCache);
      in = new DefaultHomeInputStream(connection.getInputStream());
      // Read home with HomeInputStream
      Home home = in.readHome();
      return home;
    } catch (InterruptedIOException ex) {
      throw new InterruptedRecorderException("Read " + homeUrl + " interrupted");
    } catch (IOException ex) {
      throw new RecorderException("Can't read home from " + homeUrl, ex);
    } catch (ClassNotFoundException ex) {
      throw new RecorderException("Missing classes to read home from " + homeUrl, ex);
    } finally {
      try {
        if (in != null) {
          in.close();
        }
      } catch (IOException ex) {
        throw new RecorderException("Can't close stream", ex);
      }
    }
  }
 
  /**
   * Displays the given <code>home</code> in the main pane of <code>rootPane</code>.
   */
  private void displayHome(final JRootPane rootPane, final Home home,
                           final UserPreferences preferences,
                           final ViewFactory viewFactory) {
    EventQueue.invokeLater(new Runnable() {
        public void run() {
          HomeController3D controller =
              new HomeController3D(home, preferences, viewFactory, null, null);
          rootPane.setContentPane((JComponent)controller.getView());
          rootPane.revalidate();
        }
      });
  }
}
TOP

Related Classes of com.eteks.sweethome3d.applet.ViewerHelper

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.