Skip to content
This repository has been archived by the owner on Feb 2, 2021. It is now read-only.

Commit

Permalink
Implement file opening support for Mac (support for file association …
Browse files Browse the repository at this point in the history
…icons not complete due to javapackager limitations, but double clicking does work).
  • Loading branch information
mikehearn committed Jan 5, 2015
1 parent 60454bc commit 7dd1058
Show file tree
Hide file tree
Showing 7 changed files with 316 additions and 191 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@
target/
deploy
updates
*.iml
*.iml
package/macosx/Info.plist
138 changes: 73 additions & 65 deletions client/src/main/java/lighthouse/Main.java
Original file line number Diff line number Diff line change
@@ -1,74 +1,51 @@
package lighthouse;

import com.google.common.base.Stopwatch;
import com.google.common.util.concurrent.Service;
import com.google.common.util.concurrent.Uninterruptibles;
import com.vinumeris.crashfx.CrashFX;
import com.vinumeris.crashfx.CrashWindow;
import com.vinumeris.updatefx.Crypto;
import com.vinumeris.updatefx.UpdateFX;
import javafx.animation.Animation;
import javafx.application.Application;
import com.google.common.base.*;
import com.google.common.util.concurrent.*;
import com.vinumeris.crashfx.*;
import com.vinumeris.updatefx.*;
import javafx.animation.*;
import javafx.application.*;
import javafx.application.Platform;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXMLLoader;
import javafx.geometry.Insets;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.SnapshotParameters;
import javafx.scene.control.Label;
import javafx.scene.effect.ColorAdjust;
import javafx.scene.effect.GaussianBlur;
import javafx.scene.image.ImageView;
import javafx.scene.image.WritableImage;
import javafx.scene.input.KeyCombination;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.Font;
import javafx.stage.Screen;
import javafx.stage.Stage;
import javafx.util.Duration;
import lighthouse.controls.NotificationBarPane;
import javafx.event.*;
import javafx.fxml.*;
import javafx.geometry.*;
import javafx.scene.*;
import javafx.scene.control.*;
import javafx.scene.effect.*;
import javafx.scene.image.*;
import javafx.scene.input.*;
import javafx.scene.layout.*;
import javafx.scene.shape.*;
import javafx.scene.text.*;
import javafx.stage.*;
import javafx.util.*;
import lighthouse.controls.*;
import lighthouse.files.AppDirectory;
import lighthouse.protocol.LHUtils;
import lighthouse.subwindows.EmbeddedWindow;
import lighthouse.utils.GuiUtils;
import lighthouse.utils.TextFieldValidator;
import lighthouse.wallet.PledgingWallet;
import lighthouse.protocol.*;
import lighthouse.subwindows.*;
import lighthouse.utils.*;
import lighthouse.wallet.*;
import org.bitcoinj.core.*;
import org.bitcoinj.kits.WalletAppKit;
import org.bitcoinj.net.discovery.DnsDiscovery;
import org.bitcoinj.net.discovery.PeerDiscovery;
import org.bitcoinj.net.discovery.PeerDiscoveryException;
import org.bitcoinj.params.MainNetParams;
import org.bitcoinj.params.RegTestParams;
import org.bitcoinj.params.TestNet3Params;
import org.bitcoinj.utils.BriefLogFormatter;
import org.bitcoinj.utils.Threading;
import org.bitcoinj.wallet.DeterministicSeed;
import org.bouncycastle.math.ec.ECPoint;
import org.bitcoinj.kits.*;
import org.bitcoinj.net.discovery.*;
import org.bitcoinj.params.*;
import org.bitcoinj.utils.*;
import org.bitcoinj.wallet.*;
import org.bouncycastle.math.ec.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.Nullable;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.URI;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.logging.FileHandler;

import static lighthouse.LighthouseBackend.Mode.CLIENT;
import static lighthouse.protocol.LHUtils.uncheck;
import static lighthouse.protocol.LHUtils.unchecked;
import org.slf4j.*;

import javax.annotation.*;
import java.io.*;
import java.net.*;
import java.nio.file.*;
import java.util.*;
import java.util.concurrent.*;
import java.util.logging.*;

import static lighthouse.LighthouseBackend.Mode.*;
import static lighthouse.protocol.LHUtils.*;
import static lighthouse.utils.GuiUtils.*;

public class Main extends Application {
Expand Down Expand Up @@ -165,10 +142,41 @@ public void start(Stage stage) throws Exception {
Runnable setup = () -> {
uncheck(() -> initBitcoin(null)); // This will happen mostly async.
loadMainWindow();
// If there is an Apple message queued up asking us to open a file, it'll be queued onto the UI thread
// at this point.
handleFileOpenRequests();
};
runOnGuiThreadAfter(300, setup);
}

private void handleFileOpenRequests() {
// This is only for MacOS, where the OS single instances us by default and sends us a message at startup to ask
// us to open a file. It requires internal APIs.
if (!System.getProperty("os.name").toLowerCase().contains("mac")) return;
com.sun.glass.ui.Application app = com.sun.glass.ui.Application.GetApplication();
com.sun.glass.ui.Application.EventHandler old = app.getEventHandler();
app.setEventHandler(new com.sun.glass.ui.Application.EventHandler() {
@Override public void handleQuitAction(com.sun.glass.ui.Application app, long time) {
old.handleQuitAction(app, time);
}
@Override public boolean handleThemeChanged(String themeName) {
return old.handleThemeChanged(themeName);
}

@Override
public void handleOpenFilesAction(com.sun.glass.ui.Application app, long time, String[] files) {
for (String strPath : files) {
if (strPath.equals("com.intellij.rt.execution.application.AppMain"))
continue; // Only happens in dev environment.
log.info("OS is requesting that we open " + strPath);
Platform.runLater(() -> {
Main.instance.mainWindow.handleOpenedFile(new File(strPath));
});
}
}
});
}

private boolean parseCommandLineArgs() {
if (getParameters().getUnnamed().contains("--help") || getParameters().getUnnamed().contains("-h")) {
System.out.println(String.format(
Expand Down
128 changes: 55 additions & 73 deletions client/src/main/java/lighthouse/MainWindow.java
Original file line number Diff line number Diff line change
@@ -1,68 +1,41 @@
package lighthouse;

import com.google.protobuf.ByteString;
import com.subgraph.orchid.TorClient;
import com.subgraph.orchid.TorInitializationListener;
import com.vinumeris.updatefx.UpdateFX;
import com.vinumeris.updatefx.Updater;
import de.jensd.fx.fontawesome.AwesomeDude;
import de.jensd.fx.fontawesome.AwesomeIcon;
import com.google.protobuf.*;
import com.subgraph.orchid.*;
import com.vinumeris.updatefx.*;
import de.jensd.fx.fontawesome.*;
import javafx.animation.*;
import javafx.application.Platform;
import javafx.beans.InvalidationListener;
import javafx.beans.Observable;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.property.SimpleLongProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.collections.ListChangeListener;
import javafx.collections.MapChangeListener;
import javafx.collections.ObservableList;
import javafx.collections.ObservableMap;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.application.*;
import javafx.beans.*;
import javafx.beans.property.*;
import javafx.collections.*;
import javafx.event.*;
import javafx.fxml.*;
import javafx.scene.control.*;
import javafx.scene.input.DragEvent;
import javafx.scene.input.MouseEvent;
import javafx.scene.input.TransferMode;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.FileChooser;
import javafx.util.Duration;
import lighthouse.controls.ClickableBitcoinAddress;
import lighthouse.controls.NotificationBarPane;
import lighthouse.controls.ProjectOverviewWidget;
import lighthouse.controls.ProjectView;
import javafx.scene.input.*;
import javafx.scene.layout.*;
import javafx.stage.*;
import javafx.util.*;
import lighthouse.controls.*;
import lighthouse.files.AppDirectory;
import lighthouse.files.DiskManager;
import lighthouse.model.BitcoinUIModel;
import lighthouse.protocol.Project;
import lighthouse.subwindows.EditProjectWindow;
import lighthouse.subwindows.EmptyWalletController;
import lighthouse.subwindows.UpdateFXWindow;
import lighthouse.subwindows.WalletSettingsController;
import lighthouse.utils.GuiUtils;
import lighthouse.utils.easing.EasingMode;
import lighthouse.utils.easing.ElasticInterpolator;
import org.bitcoinj.core.Coin;
import org.bitcoinj.core.Sha256Hash;
import org.bitcoinj.params.MainNetParams;
import org.bitcoinj.params.RegTestParams;
import org.bitcoinj.params.TestNet3Params;
import org.bitcoinj.utils.MonetaryFormat;
import org.fxmisc.easybind.EasyBind;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;

import static javafx.beans.binding.Bindings.when;
import static lighthouse.protocol.LHUtils.unchecked;
import static lighthouse.threading.AffinityExecutor.UI_THREAD;
import lighthouse.files.*;
import lighthouse.model.*;
import lighthouse.protocol.*;
import lighthouse.subwindows.*;
import lighthouse.utils.*;
import lighthouse.utils.easing.*;
import org.bitcoinj.core.*;
import org.bitcoinj.params.*;
import org.bitcoinj.utils.*;
import org.fxmisc.easybind.*;
import org.slf4j.*;

import java.io.*;
import java.nio.file.*;

import static javafx.beans.binding.Bindings.*;
import static lighthouse.protocol.LHUtils.*;
import static lighthouse.threading.AffinityExecutor.*;
import static lighthouse.utils.GuiUtils.*;

/**
Expand Down Expand Up @@ -287,19 +260,28 @@ public void dragOver(DragEvent event) {
@FXML
public void dragDropped(DragEvent event) {
log.info("Drop: {}", event);
for (File file : event.getDragboard().getFiles()) {
if (file.toString().endsWith(DiskManager.PROJECT_FILE_EXTENSION)) {
importProject(file);
} else if (file.toString().endsWith(DiskManager.PLEDGE_FILE_EXTENSION)) {
try {
Sha256Hash hash = Sha256Hash.hashFileContents(file);
Files.copy(file.toPath(), AppDirectory.dir().resolve(hash + DiskManager.PLEDGE_FILE_EXTENSION));
} catch (IOException e) {
GuiUtils.informationalAlert("Import failed",
"Could not copy the dropped pledge into the %s application directory: " + e, Main.APP_NAME);
}
} else
log.error("Unknown file type dropped: should not happen: " + file);
for (File file : event.getDragboard().getFiles())
handleOpenedFile(file);
}

public void handleOpenedFile(File file) {
// Can be called either due to a drop, or user double clicking a file in a file explorer.
checkGuiThread();
if (file.toString().endsWith(DiskManager.PROJECT_FILE_EXTENSION)) {
importProject(file);
} else if (file.toString().endsWith(DiskManager.PLEDGE_FILE_EXTENSION)) {
importPledge(file);
} else
log.error("Unknown file type open requested: should not happen: " + file);
}

public static void importPledge(File file) {
try {
Sha256Hash hash = Sha256Hash.hashFileContents(file);
Files.copy(file.toPath(), AppDirectory.dir().resolve(hash + DiskManager.PLEDGE_FILE_EXTENSION));
} catch (IOException e) {
GuiUtils.informationalAlert("Import failed",
"Could not copy the dropped pledge into the %s application directory: " + e, Main.APP_NAME);
}
}

Expand Down
49 changes: 20 additions & 29 deletions client/src/main/java/lighthouse/subwindows/ExportWindow.java
Original file line number Diff line number Diff line change
@@ -1,35 +1,26 @@
package lighthouse.subwindows;

import com.google.common.collect.ImmutableList;
import com.google.protobuf.Message;
import de.jensd.fx.fontawesome.AwesomeDude;
import de.jensd.fx.fontawesome.AwesomeIcon;
import com.google.common.collect.*;
import com.google.protobuf.*;
import de.jensd.fx.fontawesome.*;
import javafx.application.Platform;
import javafx.fxml.FXML;
import javafx.scene.Node;
import javafx.scene.control.Label;
import javafx.fxml.*;
import javafx.scene.*;
import javafx.scene.control.*;
import javafx.scene.input.*;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.stage.FileChooser;
import lighthouse.Main;
import lighthouse.files.DiskManager;
import lighthouse.protocol.LHUtils;
import lighthouse.protocol.Project;
import lighthouse.utils.GuiUtils;
import lighthouse.wallet.PledgingWallet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.Nullable;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import javafx.scene.layout.*;
import javafx.scene.paint.*;
import javafx.stage.*;
import lighthouse.*;
import lighthouse.files.*;
import lighthouse.protocol.*;
import lighthouse.utils.*;
import lighthouse.wallet.*;
import org.slf4j.*;

import javax.annotation.*;
import java.io.*;
import java.nio.file.*;

// TODO: The folder explainer here is actually dead code.

Expand Down Expand Up @@ -69,7 +60,7 @@ public static void openForProject(Project project) {
}
}

public static DataFormat PLEDGE_MIME_TYPE = new DataFormat("application/vnd.vinumeris.lighthouse-pledge");
public static DataFormat PLEDGE_MIME_TYPE = new DataFormat(LHUtils.PLEDGE_MIME_TYPE);
public static DataFormat PROJECT_MIME_TYPE = new DataFormat(LHUtils.PROJECT_MIME_TYPE);

public static class DragData {
Expand Down

0 comments on commit 7dd1058

Please sign in to comment.