22
22
import java.awt.EventQueue;
23
23
import java.awt.KeyboardFocusManager;
24
import java.awt.event.ActionEvent;
25
import java.awt.event.ActionListener;
24
26
import java.beans.PropertyChangeEvent;
25
27
import java.beans.PropertyChangeListener;
26
28
import java.io.BufferedReader;
36
38
import java.net.URL;
37
39
import java.util.ArrayList;
38
40
import java.util.Arrays;
41
import java.util.Collections;
39
42
import java.util.HashMap;
40
43
import java.util.List;
44
import java.util.Locale;
41
45
import java.util.Map;
42
46
import java.util.ResourceBundle;
43
47
import java.util.concurrent.Executor;
55
59
import javax.swing.JFrame;
56
60
import javax.swing.JOptionPane;
57
61
import javax.swing.SwingUtilities;
62
import javax.swing.Timer;
58
63
import javax.swing.UIManager;
60
65
import com.eteks.sweethome3d.io.AutoRecoveryManager;
66
71
import com.eteks.sweethome3d.model.Home;
67
72
import com.eteks.sweethome3d.model.HomeApplication;
68
73
import com.eteks.sweethome3d.model.HomeRecorder;
74
import com.eteks.sweethome3d.model.Library;
69
75
import com.eteks.sweethome3d.model.RecorderException;
70
76
import com.eteks.sweethome3d.model.UserPreferences;
71
77
import com.eteks.sweethome3d.plugin.HomePluginController;
138
144
private ViewFactory viewFactory;
139
145
private PluginManager pluginManager;
140
146
private boolean pluginManagerInitialized;
147
private boolean checkUpdatesNeeded;
141
148
private AutoRecoveryManager autoRecoveryManager;
142
149
private final Map<Home, JFrame> homeFrames;
199
206
applicationFolders = null;
201
this.userPreferences = new FileUserPreferences(preferencesFolder, applicationFolders,
203
public void execute(Runnable command) {
204
EventQueue.invokeLater(command);
208
Executor eventQueueExecutor = new Executor() {
209
public void execute(Runnable command) {
210
EventQueue.invokeLater(command);
213
this.userPreferences = new FileUserPreferences(preferencesFolder, applicationFolders, eventQueueExecutor) {
215
public List<Library> getLibraries() {
216
if (pluginManager != null) {
217
List<Library> pluginLibraries = pluginManager.getPluginLibraries();
218
if (!pluginLibraries.isEmpty()) {
219
// Add plug-ins to the list returned by user preferences
220
ArrayList<Library> libraries = new ArrayList<Library>(super.getLibraries());
221
libraries.addAll(pluginLibraries);
222
return Collections.unmodifiableList(libraries);
225
return super.getLibraries();
229
public void deleteLibraries(List<Library> libraries) throws RecorderException {
230
super.deleteLibraries(libraries);
231
List<Library> plugins = new ArrayList<Library>();
232
for (Library library : libraries) {
233
if (PluginManager.PLUGIN_LIBRARY_TYPE.equals(library.getType())) {
234
plugins.add(library);
237
pluginManager.deletePlugins(plugins);
240
this.checkUpdatesNeeded = this.userPreferences.isCheckUpdatesEnabled();
208
242
return this.userPreferences;
286
* Returns Sweet Home 3D application read from resources.
289
public String getId() {
290
String applicationId = System.getProperty("com.eteks.sweethome3d.applicationId");
291
if (applicationId != null && applicationId.length() > 0) {
292
return applicationId;
295
return getUserPreferences().getLocalizedString(SweetHome3D.class, "applicationId");
296
} catch (IllegalArgumentException ex) {
297
return super.getId();
252
303
* Returns the name of this application read from resources.
260
311
* Returns information about the version of this application.
262
313
public String getVersion() {
263
String applicationVersion = getUserPreferences().getLocalizedString(SweetHome3D.class, "applicationVersion");
264
String versionInformation = System.getProperty("com.eteks.sweethome3d.deploymentInformation");
265
if (versionInformation != null) {
266
applicationVersion += " " + versionInformation;
314
String applicationVersion = System.getProperty("com.eteks.sweethome3d.applicationVersion");
315
if (applicationVersion != null) {
316
return applicationVersion;
318
return getUserPreferences().getLocalizedString(SweetHome3D.class, "applicationVersion");
268
return applicationVersion;
340
391
// Add a listener that opens a frame when a home is added to application
341
392
addHomesListener(new CollectionListener<Home>() {
342
private boolean firstApplicationHomeAdded;
393
private boolean firstApplicationHomeAdded;
344
395
public void collectionChanged(CollectionEvent<Home> ev) {
345
396
switch (ev.getType()) {
349
400
HomeFrameController controller = createHomeFrameController(home);
350
401
controller.displayView();
351
402
if (!this.firstApplicationHomeAdded) {
403
this.firstApplicationHomeAdded = true;
352
404
addNewHomeCloseListener(home, controller.getHomeController());
353
this.firstApplicationHomeAdded = true;
356
JFrame homeFrame = (JFrame) SwingUtilities.getRoot((JComponent) controller.getView());
407
JFrame homeFrame = (JFrame)SwingUtilities.getRoot((JComponent) controller.getView());
357
408
homeFrames.put(home, homeFrame);
358
409
} catch (IllegalStateException ex) {
359
410
// Check exception by class name to avoid a mandatory bind to Java 3D
431
482
ResourceBundle resource = ResourceBundle.getBundle(classPackage + "." + "package");
432
483
String applicationName = resource.getString("SweetHome3D.applicationName");
433
484
System.setProperty("com.apple.mrj.application.apple.menu.about.name", applicationName);
485
System.setProperty("apple.awt.application.name", applicationName);
434
486
// Use Mac OS X screen menu bar for frames menu bar
435
487
System.setProperty("apple.laf.useScreenMenuBar", "true");
436
488
// Force the use of Quartz under Mac OS X for better Java 2D rendering
438
490
System.setProperty("apple.awt.graphics.UseQuartz", "true");
492
// Set User Agent to follow statistics on used operating systems
493
System.setProperty("http.agent", getId() + "/" + getVersion()
494
+ " (" + System.getProperty("os.name") + " " + System.getProperty("os.version") + "; " + System.getProperty("os.arch") + "; " + Locale.getDefault() + ")");
614
669
// Read home file in args [1] if args [0] == "-open" with a dummy controller
615
670
createHomeFrameController(createHome()).getHomeController().open(args [1]);
616
672
} else if (getContentManager().isAcceptable(args [1], ContentManager.ContentType.LANGUAGE_LIBRARY)) {
617
start(new String [0]);
673
showDefaultHomeFrame();
618
674
final String languageLibraryName = args [1];
619
675
EventQueue.invokeLater(new Runnable() {
620
676
public void run() {
633
690
} else if (getContentManager().isAcceptable(args [1], ContentManager.ContentType.FURNITURE_LIBRARY)) {
634
start(new String [0]);
691
showDefaultHomeFrame();
635
692
final String furnitureLibraryName = args [1];
636
693
EventQueue.invokeLater(new Runnable() {
637
694
public void run() {
638
695
// Import furniture library with a dummy controller
639
696
createHomeFrameController(createHome()).getHomeController().importFurnitureLibrary(furnitureLibraryName);
642
700
} else if (getContentManager().isAcceptable(args [1], ContentManager.ContentType.TEXTURES_LIBRARY)) {
643
start(new String [0]);
701
showDefaultHomeFrame();
644
702
final String texturesLibraryName = args [1];
645
703
EventQueue.invokeLater(new Runnable() {
646
704
public void run() {
647
705
// Import textures library with a dummy controller
648
706
createHomeFrameController(createHome()).getHomeController().importTexturesLibrary(texturesLibraryName);
651
710
} else if (getContentManager().isAcceptable(args [1], ContentManager.ContentType.PLUGIN)) {
652
start(new String [0]);
711
showDefaultHomeFrame();
653
712
final String pluginName = args [1];
654
713
EventQueue.invokeLater(new Runnable() {
655
714
public void run() {
658
717
if (homeController instanceof HomePluginController) {
659
718
((HomePluginController)homeController).importPlugin(pluginName);
664
} else if (getHomes().isEmpty()) {
665
if (autoRecoveryManager != null) {
725
showDefaultHomeFrame();
731
* Shows a home frame, either a new one when no home is opened, or the last created home frame.
733
public void showDefaultHomeFrame() {
734
if (getHomes().isEmpty()) {
735
if (this.autoRecoveryManager != null) {
666
736
this.autoRecoveryManager.openRecoveredHomes();
668
738
if (getHomes().isEmpty()) {
694
764
showHomeFrame(home);
769
* Check updates if needed.
771
private void checkUpdates() {
772
if (this.checkUpdatesNeeded) {
773
this.checkUpdatesNeeded = false;
774
// Delay updates checking to let program launch finish
775
new Timer(500, new ActionListener() {
776
public void actionPerformed(ActionEvent ev) {
777
((Timer)ev.getSource()).stop();
778
// Check updates with a dummy controller
779
createHomeFrameController(createHome()).getHomeController().checkUpdates(true);
699
786
* A file content manager that records the last directories for each content
700
787
* in Java preferences.
792
879
private static class StandaloneBasicService implements BasicService {
793
880
public boolean showDocument(URL url) {
882
if (OperatingSystem.isJavaVersionGreaterOrEqual("1.6")) {
796
883
// Call Java SE 6 java.awt.Desktop browse method by reflection to
797
884
// ensure Java SE 5 compatibility
798
Class desktopClass = Class.forName("java.awt.Desktop");
885
Class<?> desktopClass = Class.forName("java.awt.Desktop");
799
886
Object desktopInstance = desktopClass.getMethod("getDesktop").invoke(null);
800
887
desktopClass.getMethod("browse", URI.class).invoke(desktopInstance, url.toURI());
802
} catch (Exception ex) {
803
// For any exception, let's consider simply the showDocument method
806
} else if (OperatingSystem.isMacOSX()) {
890
} catch (Exception ex) {
808
Runtime.getRuntime().exec(new String [] {"open", url.toString()});
810
} catch (IOException ex) {
892
if (OperatingSystem.isMacOSX()) {
893
Runtime.getRuntime().exec(new String [] {"open", url.toString()});
895
} else if (OperatingSystem.isLinux()) {
896
Runtime.getRuntime().exec(new String [] {"xdg-open", url.toString()});
899
} catch (IOException ex2) {
901
// For other cases, let's consider simply the showDocument method failed
825
915
public boolean isWebBrowserSupported() {
916
if (OperatingSystem.isJavaVersionGreaterOrEqual("1.6")) {
828
918
// Call Java SE 6 java.awt.Desktop isSupported(Desktop.Action.BROWSE)
829
// method by reflection to
830
// ensure Java SE 5 compatibility
831
Class desktopClass = Class.forName("java.awt.Desktop");
919
// method by reflection to ensure Java SE 5 compatibility
920
Class<?> desktopClass = Class.forName("java.awt.Desktop");
832
921
Object desktopInstance = desktopClass.getMethod("getDesktop").invoke(null);
833
Class desktopActionClass = Class.forName("java.awt.Desktop$Action");
922
Class<?> desktopActionClass = Class.forName("java.awt.Desktop$Action");
834
923
Object desktopBrowseAction = desktopActionClass.getMethod("valueOf", String.class).invoke(null, "BROWSE");
835
return (Boolean) desktopClass.getMethod("isSupported", desktopActionClass).invoke(desktopInstance,
836
desktopBrowseAction);
924
if ((Boolean)desktopClass.getMethod("isSupported", desktopActionClass).invoke(desktopInstance,
925
desktopBrowseAction)) {
837
928
} catch (Exception ex) {
838
929
// For any exception, let's consider simply the isSupported method failed
841
// For other Java versions, let's support only Mac OS X
842
return OperatingSystem.isMacOSX();
845
private boolean isJava6() {
846
String javaVersion = System.getProperty("java.version");
847
String [] javaVersionParts = javaVersion.split("\\.|_");
848
if (javaVersionParts.length >= 2) {
850
// Return true for Java SE 6 and superior
851
if (Integer.parseInt(javaVersionParts [1]) >= 6) {
854
} catch (NumberFormatException ex) {
932
// For other Java versions, let's support Mac OS X and Linux
933
return OperatingSystem.isMacOSX() || OperatingSystem.isLinux();