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
430
481
ResourceBundle resource = ResourceBundle.getBundle(classPackage + "." + "package");
431
482
String applicationName = resource.getString("SweetHome3D.applicationName");
432
483
System.setProperty("com.apple.mrj.application.apple.menu.about.name", applicationName);
484
System.setProperty("apple.awt.application.name", applicationName);
433
485
// Use Mac OS X screen menu bar for frames menu bar
434
486
System.setProperty("apple.laf.useScreenMenuBar", "true");
435
487
// Force the use of Quartz under Mac OS X for better Java 2D rendering
437
489
System.setProperty("apple.awt.graphics.UseQuartz", "true");
491
// Set User Agent to follow statistics on used operating systems
492
System.setProperty("http.agent", getId() + "/" + getVersion()
493
+ " (" + System.getProperty("os.name") + " " + System.getProperty("os.version") + "; " + System.getProperty("os.arch") + "; " + Locale.getDefault() + ")");
613
668
// Read home file in args [1] if args [0] == "-open" with a dummy controller
614
669
createHomeFrameController(createHome()).getHomeController().open(args [1]);
615
671
} else if (getContentManager().isAcceptable(args [1], ContentManager.ContentType.LANGUAGE_LIBRARY)) {
616
start(new String [0]);
672
showDefaultHomeFrame();
617
673
final String languageLibraryName = args [1];
618
674
EventQueue.invokeLater(new Runnable() {
619
675
public void run() {
632
689
} else if (getContentManager().isAcceptable(args [1], ContentManager.ContentType.FURNITURE_LIBRARY)) {
633
start(new String [0]);
690
showDefaultHomeFrame();
634
691
final String furnitureLibraryName = args [1];
635
692
EventQueue.invokeLater(new Runnable() {
636
693
public void run() {
637
694
// Import furniture library with a dummy controller
638
695
createHomeFrameController(createHome()).getHomeController().importFurnitureLibrary(furnitureLibraryName);
641
699
} else if (getContentManager().isAcceptable(args [1], ContentManager.ContentType.TEXTURES_LIBRARY)) {
642
start(new String [0]);
700
showDefaultHomeFrame();
643
701
final String texturesLibraryName = args [1];
644
702
EventQueue.invokeLater(new Runnable() {
645
703
public void run() {
646
704
// Import textures library with a dummy controller
647
705
createHomeFrameController(createHome()).getHomeController().importTexturesLibrary(texturesLibraryName);
650
709
} else if (getContentManager().isAcceptable(args [1], ContentManager.ContentType.PLUGIN)) {
651
start(new String [0]);
710
showDefaultHomeFrame();
652
711
final String pluginName = args [1];
653
712
EventQueue.invokeLater(new Runnable() {
654
713
public void run() {
657
716
if (homeController instanceof HomePluginController) {
658
717
((HomePluginController)homeController).importPlugin(pluginName);
663
} else if (getHomes().isEmpty()) {
664
if (autoRecoveryManager != null) {
724
showDefaultHomeFrame();
730
* Shows a home frame, either a new one when no home is opened, or the last created home frame.
732
public void showDefaultHomeFrame() {
733
if (getHomes().isEmpty()) {
734
if (this.autoRecoveryManager != null) {
665
735
this.autoRecoveryManager.openRecoveredHomes();
667
737
if (getHomes().isEmpty()) {
693
763
showHomeFrame(home);
768
* Check updates if needed.
770
private void checkUpdates() {
771
if (this.checkUpdatesNeeded) {
772
this.checkUpdatesNeeded = false;
773
// Delay updates checking to let program launch finish
774
new Timer(500, new ActionListener() {
775
public void actionPerformed(ActionEvent ev) {
776
((Timer)ev.getSource()).stop();
777
// Check updates with a dummy controller
778
createHomeFrameController(createHome()).getHomeController().checkUpdates(true);
698
785
* A file content manager that records the last directories for each content
699
786
* in Java preferences.
791
878
private static class StandaloneBasicService implements BasicService {
792
879
public boolean showDocument(URL url) {
881
if (OperatingSystem.isJavaVersionGreaterOrEqual("1.6")) {
795
882
// Call Java SE 6 java.awt.Desktop browse method by reflection to
796
883
// ensure Java SE 5 compatibility
797
Class desktopClass = Class.forName("java.awt.Desktop");
884
Class<?> desktopClass = Class.forName("java.awt.Desktop");
798
885
Object desktopInstance = desktopClass.getMethod("getDesktop").invoke(null);
799
886
desktopClass.getMethod("browse", URI.class).invoke(desktopInstance, url.toURI());
801
} catch (Exception ex) {
802
// For any exception, let's consider simply the showDocument method
805
} else if (OperatingSystem.isMacOSX()) {
889
} catch (Exception ex) {
807
Runtime.getRuntime().exec(new String [] {"open", url.toString()});
809
} catch (IOException ex) {
891
if (OperatingSystem.isMacOSX()) {
892
Runtime.getRuntime().exec(new String [] {"open", url.toString()});
894
} else if (OperatingSystem.isLinux()) {
895
Runtime.getRuntime().exec(new String [] {"xdg-open", url.toString()});
898
} catch (IOException ex2) {
900
// For other cases, let's consider simply the showDocument method failed
824
914
public boolean isWebBrowserSupported() {
915
if (OperatingSystem.isJavaVersionGreaterOrEqual("1.6")) {
827
917
// Call Java SE 6 java.awt.Desktop isSupported(Desktop.Action.BROWSE)
828
// method by reflection to
829
// ensure Java SE 5 compatibility
830
Class desktopClass = Class.forName("java.awt.Desktop");
918
// method by reflection to ensure Java SE 5 compatibility
919
Class<?> desktopClass = Class.forName("java.awt.Desktop");
831
920
Object desktopInstance = desktopClass.getMethod("getDesktop").invoke(null);
832
Class desktopActionClass = Class.forName("java.awt.Desktop$Action");
921
Class<?> desktopActionClass = Class.forName("java.awt.Desktop$Action");
833
922
Object desktopBrowseAction = desktopActionClass.getMethod("valueOf", String.class).invoke(null, "BROWSE");
834
return (Boolean) desktopClass.getMethod("isSupported", desktopActionClass).invoke(desktopInstance,
835
desktopBrowseAction);
923
if ((Boolean)desktopClass.getMethod("isSupported", desktopActionClass).invoke(desktopInstance,
924
desktopBrowseAction)) {
836
927
} catch (Exception ex) {
837
928
// For any exception, let's consider simply the isSupported method failed
840
// For other Java versions, let's support only Mac OS X
841
return OperatingSystem.isMacOSX();
844
private boolean isJava6() {
845
String javaVersion = System.getProperty("java.version");
846
String [] javaVersionParts = javaVersion.split("\\.|_");
847
if (javaVersionParts.length >= 2) {
849
// Return true for Java SE 6 and superior
850
if (Integer.parseInt(javaVersionParts [1]) >= 6) {
853
} catch (NumberFormatException ex) {
931
// For other Java versions, let's support Mac OS X and Linux
932
return OperatingSystem.isMacOSX() || OperatingSystem.isLinux();