Skip to content

Commit

Permalink
Changing of GPS information is now possible
Browse files Browse the repository at this point in the history
Added custom GPS information during export is now possible to overwrite possible information from the mediafile
  • Loading branch information
cleme authored and cleme committed Jan 4, 2022
1 parent d9d11d7 commit 12bb30e
Show file tree
Hide file tree
Showing 16 changed files with 1,495 additions and 117 deletions.
9 changes: 9 additions & 0 deletions PhotoSlide/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,10 @@
<repository>
<id>OpenIMAJ maven releases repository</id>
<url>https://maven.openimaj.org</url>
</repository>
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
</repositories>

Expand Down Expand Up @@ -220,6 +224,11 @@
<artifactId>faces</artifactId>
<version>1.3.10</version>
</dependency>
<dependency>
<groupId>fr.dudie</groupId>
<artifactId>nominatim-api</artifactId>
<version>3.4</version>
</dependency>

<!-- This downloads the platform specific JavaFX libraries used by the project. -->
<!-- For the final installable, the JavaFX dependencies are provided via modules, but by including these here
Expand Down
128 changes: 127 additions & 1 deletion PhotoSlide/src/main/java/org/photoslide/ExportDialogController.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,28 +5,42 @@
*/
package org.photoslide;

import com.sothawo.mapjfx.Coordinate;
import com.sothawo.mapjfx.MapType;
import com.sothawo.mapjfx.MapView;
import com.sothawo.mapjfx.Marker;
import java.io.File;
import java.net.URL;
import java.util.Collection;
import java.util.ResourceBundle;
import javafx.beans.binding.Bindings;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.concurrent.Task;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.control.ProgressIndicator;
import javafx.scene.control.Slider;
import javafx.scene.control.TextField;
import javafx.scene.control.Tooltip;
import javafx.scene.effect.ColorAdjust;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.FlowPane;
import javafx.scene.layout.VBox;
import javafx.stage.DirectoryChooser;
import javafx.stage.Stage;
import javafx.util.Duration;
import org.controlsfx.control.textfield.AutoCompletionBinding;
import org.controlsfx.control.textfield.CustomTextField;
import org.controlsfx.control.textfield.TextFields;
import org.kordamp.ikonli.javafx.FontIcon;
import org.photoslide.browsermetadata.GeoCoding;
import org.photoslide.browsermetadata.Tag;

/**
Expand Down Expand Up @@ -76,6 +90,20 @@ public class ExportDialogController implements Initializable {
private TextField titleTextBox;
@FXML
private Button plusButton;
@FXML
private CheckBox replaceGPSCheckBox;
@FXML
private MapView mapView;
private GeoCoding geoCoding;
@FXML
private CustomTextField customField;
@FXML
private Button searchButton;
private Marker markerPos;
@FXML
private VBox mapSelectionPane;
@FXML
private CustomTextField heightTextField;

@Override
public void initialize(URL url, ResourceBundle rb) {
Expand Down Expand Up @@ -160,7 +188,24 @@ public void initialize(URL url, ResourceBundle rb) {
addKeywordTextField.setDisable(true);
}
});
replaceGPSCheckBox.setOnAction((t) -> {
if (replaceGPSCheckBox.isSelected()) {
mapSelectionPane.setDisable(false);
} else {
mapSelectionPane.setDisable(true);
}
});
keywordList = FXCollections.observableArrayList();
geoCoding = new GeoCoding();
customField.setRight(new FontIcon("ti-close"));
mapView.setMapType(MapType.OSM);
mapView.setPrefSize(350, 90);
mapView.setMaxSize(350, 90);
mapView.initialize();
Coordinate c = new Coordinate(48.135125, 11.581981);
mapView.setCenter(c);
markerPos = new Marker(getClass().getResource("/org/photoslide/img/map_marker.png"), -16, -32);
mapView.setEffect(new ColorAdjust(0, -0.5, 0, 0));
}

@FXML
Expand Down Expand Up @@ -225,8 +270,8 @@ private void addKeywordAction(KeyEvent event) {
if (event.getCode() == KeyCode.ENTER) {
keywordText.getChildren().add(new Tag(addKeywordTextField.getText()));
addKeywordTextField.clear();
event.consume();
}
event.consume();
}

public Collection<String> getKeywordList() {
Expand Down Expand Up @@ -264,4 +309,85 @@ private void plusButtonAction(ActionEvent event) {
addKeywordTextField.clear();
}

@FXML
private void searchButtonAction(ActionEvent event) {
String name = customField.getText();

Task<ObservableList<String>> task = new Task<>() {
@Override
protected ObservableList<String> call() throws Exception {
return geoCoding.geoSearchForNameAsStrings(name);
}
};
task.setOnScheduled((t) -> {
ProgressIndicator ind = new ProgressIndicator();
ind.setPrefSize(10, 10);
ind.setMinSize(10, 10);
ind.setMaxSize(10, 10);
customField.setRight(ind);
});
task.setOnSucceeded((t) -> {
customField.setRight(null);
ObservableList<String> geoSearchForNameAsStrings = (ObservableList<String>) t.getSource().getValue();
//set autocomplete
AutoCompletionBinding<String> autoComp = TextFields.bindAutoCompletion(customField, geoSearchForNameAsStrings);
customField.setText(geoSearchForNameAsStrings.get(0));
customField.requestFocus();
autoComp.setUserInput(name);
autoComp.setOnAutoCompleted((o) -> {
int index = geoSearchForNameAsStrings.indexOf(customField.getText());
if (index == -1) {
index = 0;
}
geoCoding.setLastSearchGPSResult(geoCoding.getLastSearchResult().get(index));
Coordinate c = new Coordinate(geoCoding.getLastSearchResult().get(index).getLatitude(), geoCoding.getLastSearchResult().get(index).getLongitude());
mapView.setCenter(c);
markerPos.setPosition(c).setVisible(true);
mapView.addMarker(markerPos);
});
});
task.setOnFailed((t) -> {
customField.setRight(null);
});
new Thread(task).start();
}

@FXML
private void searchTFPressed(KeyEvent event) {
if (event.getCode() == KeyCode.ENTER) {
searchButtonAction(null);
}
event.consume();
}

public CheckBox getReplaceGPSCheckBox() {
return replaceGPSCheckBox;
}

public String getSelectedGPSPos(){
if (replaceGPSCheckBox.isSelected()){
return geoCoding.getLastSearchGPSResult().getLatitude()+";"+geoCoding.getLastSearchGPSResult().getLongitude();
}
return "";
}

public double getSelectedGPSPosLat(){
if (replaceGPSCheckBox.isSelected()){
return geoCoding.getLastSearchGPSResult().getLatitude();
}
return -1;
}

public double getSelectedGPSPosLon(){
if (replaceGPSCheckBox.isSelected()){
return geoCoding.getLastSearchGPSResult().getLongitude();
}
return -1;
}

public CustomTextField getHeightTextField() {
return heightTextField;
}


}
18 changes: 15 additions & 3 deletions PhotoSlide/src/main/java/org/photoslide/MainViewController.java
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@
import org.kordamp.ikonli.javafx.FontIcon;
import org.photoslide.bookmarksboard.BMBIcon;
import org.photoslide.bookmarksboard.BookmarkBoardController;
import org.photoslide.browsermetadata.GeoCoding;
import org.photoslide.datamodel.FileTypes;
import org.photoslide.editormedia.EditorMediaViewController;
import org.photoslide.editormetadata.EditorMetadataController;
Expand Down Expand Up @@ -374,7 +375,6 @@ protected Boolean call() throws Exception {
break;
}
String outFileStr;
System.out.println("Option: " + diag.getController().getFilename());
if (diag.getController().getFilename().equalsIgnoreCase("<Original>_")) {
outFileStr = outputDir + File.separator + mediaItem.getName() + (i + 1) + "." + imageType.getExtension();
} else {
Expand Down Expand Up @@ -457,7 +457,13 @@ protected Boolean call() throws Exception {
if (diag.getController().getReplaceKeywordChoiceBox().isSelected()) {
mediaItem.setKeywords(diag.getController().getKeywordsAsString());
}
metadataPaneController.exportCompleteMetdata(mediaItem, outFileStr, imageType.getExtension());
if (diag.getController().getReplaceGPSCheckBox().isSelected()) {
if (!diag.getController().getHeightTextField().getText().equalsIgnoreCase("")) {
mediaItem.setGpsHeight(Double.parseDouble(diag.getController().getHeightTextField().getText()));
}
mediaItem.setGpsPositionFromDegree(diag.getController().getSelectedGPSPos());
}
metadataPaneController.exportCompleteMetdata(mediaItem, outFileStr, imageType.getExtension(), diag.getController().getReplaceGPSCheckBox().isSelected());
}
if (diag.getController().getExportBasicMetadataBox().isSelected()) {
metadataPaneController.readBasicMetadata(this, mediaItem);
Expand All @@ -467,7 +473,13 @@ protected Boolean call() throws Exception {
if (diag.getController().getReplaceKeywordChoiceBox().isSelected()) {
mediaItem.setKeywords(diag.getController().getKeywordsAsString());
}
metadataPaneController.exportBasicMetadata(mediaItem, outFileStr);
if (!diag.getController().getHeightTextField().getText().equalsIgnoreCase("")) {
mediaItem.setGpsHeight(Double.parseDouble(diag.getController().getHeightTextField().getText()));
}
if (diag.getController().getReplaceGPSCheckBox().isSelected()) {
mediaItem.setGpsPositionFromDegree(diag.getController().getSelectedGPSPos());
}
metadataPaneController.exportBasicMetadata(mediaItem, outFileStr, diag.getController().getReplaceGPSCheckBox().isSelected());
}
} catch (FileNotFoundException ex) {
Logger.getLogger(MainViewController.class.getName()).log(Level.SEVERE, null, ex);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
/*
* BSD 3-Clause License
*
* Copyright (c) 2018, Grum Ltd (Romain Gallet)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of Geocalc nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

package org.photoslide.browsermetadata;



/**
* Represents an area (rectangular shape projected onto Earth), defined by its top left and bottom right
* coordinates.
* <p>
* Allows for fast geo-spatial search of all points within this rectangular area.
*/
public class BoundingArea {
public final Point northEast, southWest;
public final Point southEast, northWest;

private BoundingArea(Point northEast, Point southWest) {
this.northEast = northEast;
this.southWest = southWest;

southEast = Point.at(Coordinate.fromDegrees(southWest.latitude), Coordinate.fromDegrees(northEast.longitude));
northWest = Point.at(Coordinate.fromDegrees(northEast.latitude), Coordinate.fromDegrees(southWest.longitude));
}

public static BoundingArea at(Point northEast, Point southWest) {
return new BoundingArea(northEast, southWest);
}

@Override
public String toString() {
return "BoundingArea{" + "northEast=" + northEast + ", southWest=" + southWest + '}';
}

/**
* @return true if Point point is contained withing this bounding area
* @deprecated use contains(Point point)
*/
@Deprecated
public boolean isContainedWithin(Point point) {
return contains(point);
}

/**
* @param point point to check
* @return true if Point point is contained withing this bounding area
*/
public boolean contains(Point point) {
boolean predicate1 = point.latitude >= this.southWest.latitude && point.latitude <= this.northEast.latitude;

if (!predicate1) {
return false;
}

boolean predicate2;

if (southWest.longitude > northEast.longitude) { //area is going across the max/min longitude boundaries (ie. sort of back of the Earth)
//we "split" the area in 2, longitude-wise, point only needs to be in one or the other.
boolean predicate3 = point.longitude <= northEast.longitude && point.longitude >= -180;
boolean predicate4 = point.longitude >= southWest.longitude && point.longitude <= 180;

predicate2 = predicate3 || predicate4;
} else {
predicate2 = point.longitude >= southWest.longitude && point.longitude <= northEast.longitude;
}

return predicate2;
}
}
Loading

0 comments on commit 12bb30e

Please sign in to comment.