You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1750 lines
54 KiB
1750 lines
54 KiB
package application;
|
|
|
|
import java.io.BufferedInputStream;
|
|
import java.io.BufferedOutputStream;
|
|
import java.io.File;
|
|
import java.io.FileOutputStream;
|
|
import java.net.MalformedURLException;
|
|
import java.net.URL;
|
|
import java.nio.file.Files;
|
|
import java.util.ArrayList;
|
|
import java.util.HashMap;
|
|
import java.util.List;
|
|
import java.util.function.Predicate;
|
|
import java.util.zip.ZipEntry;
|
|
import java.util.zip.ZipFile;
|
|
|
|
import application.customviews.EntryView;
|
|
import application.customviews.FileView;
|
|
import application.customviews.SubEntryView;
|
|
import application.enums.EntryType;
|
|
import application.enums.NavState;
|
|
import application.helpers.ChangeViewCallback;
|
|
import application.helpers.Utils;
|
|
import application.helpers.WorkWhileProgressThread;
|
|
import application.helpers.wrappers.Element;
|
|
import application.helpers.wrappers.Occupation;
|
|
import application.helpers.wrappers.WrappedException;
|
|
import application.helpers.wrappers.WriteSelection;
|
|
import application.parsing.ParsingWrapper;
|
|
import application.parsing.ReadHandler;
|
|
import application.res.Backgrounds;
|
|
import application.res.Colors;
|
|
import application.res.Occupations;
|
|
import application.res.PrivacyStatementText;
|
|
import application.res.Text;
|
|
import javafx.application.HostServices;
|
|
import javafx.beans.binding.Bindings;
|
|
import javafx.beans.value.ChangeListener;
|
|
import javafx.beans.value.ObservableValue;
|
|
import javafx.collections.ObservableList;
|
|
import javafx.event.Event;
|
|
import javafx.event.EventHandler;
|
|
import javafx.geometry.Insets;
|
|
import javafx.geometry.Point2D;
|
|
import javafx.scene.Cursor;
|
|
import javafx.scene.Node;
|
|
import javafx.scene.Scene;
|
|
import javafx.scene.control.CheckBox;
|
|
import javafx.scene.control.ComboBox;
|
|
import javafx.scene.control.Label;
|
|
import javafx.scene.control.ProgressIndicator;
|
|
import javafx.scene.control.ScrollPane;
|
|
import javafx.scene.control.TextArea;
|
|
import javafx.scene.control.Tooltip;
|
|
import javafx.scene.image.Image;
|
|
import javafx.scene.image.ImageView;
|
|
import javafx.scene.input.Clipboard;
|
|
import javafx.scene.input.ClipboardContent;
|
|
import javafx.scene.input.DataFormat;
|
|
import javafx.scene.input.DragEvent;
|
|
import javafx.scene.input.Dragboard;
|
|
import javafx.scene.input.MouseEvent;
|
|
import javafx.scene.input.TransferMode;
|
|
import javafx.scene.layout.BorderPane;
|
|
import javafx.scene.layout.GridPane;
|
|
import javafx.scene.layout.HBox;
|
|
import javafx.scene.layout.Pane;
|
|
import javafx.scene.layout.Priority;
|
|
import javafx.scene.layout.VBox;
|
|
import javafx.scene.paint.Color;
|
|
import javafx.scene.shape.Line;
|
|
import javafx.stage.DirectoryChooser;
|
|
import javafx.stage.Stage;
|
|
import javafx.util.Duration;
|
|
|
|
/**
|
|
* Main class of the application. Changes the views, commands the work and
|
|
* manages the navigation
|
|
*
|
|
* @author Bianca
|
|
*
|
|
*/
|
|
public class UICoordinator implements ChangeListener<Boolean>
|
|
{
|
|
/** Callback for interaction during the progressView**/
|
|
private ChangeViewCallback cb;
|
|
/** Scene of the application**/
|
|
private Scene scene;
|
|
/** The frame of the application**/
|
|
private BorderPane frame;
|
|
/** The name of the file containing the health data**/
|
|
private String filename;
|
|
/** The label for interaction with the drag and drop of the health data file **/
|
|
private Label ddlabel;
|
|
/** A label where text can be written (in the intro view) about the file not being correct **/
|
|
private Label wrong_file;
|
|
/** contains all data found in the health file to be displayed **/
|
|
private VBox datalist;
|
|
/** The stage of the application **/
|
|
private Stage stage;
|
|
/** Worker for all kinds of parsing**/
|
|
private ParsingWrapper worker;
|
|
/** Directory for saving the files which will be created**/
|
|
private File dirForSaving;
|
|
/** The filename of the file to be created **/
|
|
private File fileForSaving;
|
|
/** All files created in temp directory. Keys are the readable filenames**/
|
|
private HashMap<String, File> filesInTempWithDesc;
|
|
/** Checkbox for agreeing to the privacy policy (intro view)**/
|
|
private CheckBox privAgree;
|
|
/** count of elements selected in the overview**/
|
|
private int selectCount = 0;
|
|
/** The label for setting the filepath on where to save the created file **/
|
|
private Label path;
|
|
/** Handler which directs the user to the privacy view **/
|
|
private EventHandler<MouseEvent> toPrivacyView;
|
|
/** Host services of the system**/
|
|
private HostServices hostServices;
|
|
/** The job given by the user.**/
|
|
private Occupation occupation;
|
|
|
|
/** Text containing the information if files could not be written **/
|
|
private String errorWritingFiles = "";
|
|
|
|
// Navigation
|
|
/** navigation element for the intro view**/
|
|
private BorderPane start;
|
|
/** navigation element for the overview view**/
|
|
private BorderPane select;
|
|
/** navigation element for the inspect view**/
|
|
private BorderPane inspect;
|
|
/** navigation element for the result view**/
|
|
private BorderPane result;
|
|
/** navigation element for the privacy view**/
|
|
private BorderPane privacy;
|
|
|
|
/**
|
|
* Constructor which initializes the scene. It creates and sets the first view,
|
|
* loads the stylesheet and creates the frame.
|
|
*/
|
|
public UICoordinator()
|
|
{
|
|
cb = new ChangeViewCallback(this);
|
|
datalist = new VBox();
|
|
datalist.setId("datalist");
|
|
datalist.setBorder(Utils.darkBlueBorder);
|
|
ddlabel = new Label(Text.SELECT_FILE);
|
|
wrong_file = new Label();
|
|
wrong_file.setId("error");
|
|
|
|
frame = setUpFrame();
|
|
scene = new Scene(frame, 800, 650);
|
|
frame.minHeightProperty().bind(Bindings.createDoubleBinding(() -> scene.getHeight(), scene.heightProperty()));
|
|
frame.minWidthProperty().bind(Bindings.createDoubleBinding(() -> scene.getWidth(), scene.widthProperty()));
|
|
|
|
changeView(getIntroView());
|
|
|
|
String css = this.getClass().getResource("style.css").toExternalForm();
|
|
scene.getStylesheets().add(css);
|
|
}
|
|
|
|
/**
|
|
* Sets the attribute of the HostServices for this object
|
|
* @param hs the hostServices of the system
|
|
*/
|
|
public void setHostServices(HostServices hs)
|
|
{
|
|
this.hostServices = hs;
|
|
}
|
|
|
|
/**
|
|
* Method initializes the frame: sets title, logo and the navigation bar
|
|
*
|
|
* @return initialized frame (left and top are frame)
|
|
*/
|
|
private BorderPane setUpFrame()
|
|
{
|
|
BorderPane frame = new BorderPane();
|
|
frame.setId("frame");
|
|
//header
|
|
BorderPane header = new BorderPane();
|
|
Label title = new Label(Text.TITLE);
|
|
header.setCenter(title);
|
|
ImageView logo = new ImageView(new Image(this.getClass().getResourceAsStream("RI_Logo_weiss_en.png")));
|
|
logo.setFitWidth(172.2 * 1.5); //these sizes are related to the image
|
|
logo.setFitHeight(49.55 * 1.5);
|
|
header.setLeft(logo);
|
|
header.setId("frameheader");
|
|
frame.setTop(header);
|
|
|
|
|
|
//Navigation, labels on the right needed for tooltips
|
|
VBox nav = new VBox();
|
|
nav.setMinWidth(100);
|
|
nav.setId("navigation");
|
|
nav.setFillWidth(true);
|
|
|
|
int buttonCount = 5;
|
|
|
|
privacy = new BorderPane();
|
|
privacy.minHeightProperty()
|
|
.bind(Bindings.createDoubleBinding(() -> nav.getHeight() / buttonCount, nav.heightProperty()));
|
|
ImageView dsgvoImage = new ImageView(new Image(this.getClass().getResourceAsStream("dsgvo.png")));
|
|
privacy.setCenter(dsgvoImage);
|
|
privacy.setRight(new Label());
|
|
privacy.setUserData(Text.MENU_PRIVACY_POLICY);
|
|
nav.getChildren().add(privacy);
|
|
|
|
start = new BorderPane();
|
|
ImageView startImage = new ImageView(new Image(this.getClass().getResourceAsStream("start2.png")));
|
|
start.setCenter(startImage);
|
|
start.minHeightProperty()
|
|
.bind(Bindings.createDoubleBinding(() -> nav.getHeight() / buttonCount, nav.heightProperty()));
|
|
start.setCenter(startImage);
|
|
start.setRight(new Label());
|
|
start.setUserData(Text.MENU_DATA_IMPORT);
|
|
nav.getChildren().add(start);
|
|
|
|
select = new BorderPane();
|
|
select.minHeightProperty()
|
|
.bind(Bindings.createDoubleBinding(() -> nav.getHeight() / buttonCount, nav.heightProperty()));
|
|
ImageView selectImage = new ImageView(new Image(this.getClass().getResourceAsStream("select.png")));
|
|
select.setCenter(selectImage);
|
|
select.setRight(new Label());
|
|
select.setUserData(Text.MENU_DATA_SELECTION);
|
|
nav.getChildren().add(select);
|
|
|
|
inspect = new BorderPane();
|
|
inspect.minHeightProperty()
|
|
.bind(Bindings.createDoubleBinding(() -> nav.getHeight() / buttonCount, nav.heightProperty()));
|
|
ImageView inspectImage = new ImageView(new Image(this.getClass().getResourceAsStream("inspect.png")));
|
|
inspect.setCenter(inspectImage);
|
|
inspect.setRight(new Label());
|
|
inspect.setUserData(Text.MENU_REVIEW);
|
|
nav.getChildren().add(inspect);
|
|
|
|
result = new BorderPane();
|
|
result.minHeightProperty()
|
|
.bind(Bindings.createDoubleBinding(() -> nav.getHeight() / buttonCount, nav.heightProperty()));
|
|
ImageView resultImage = new ImageView(new Image(this.getClass().getResourceAsStream("result.png")));
|
|
result.setCenter(resultImage);
|
|
result.setRight(new Label());
|
|
result.setUserData(Text.MENU_DATA_UPLOAD);
|
|
nav.getChildren().add(result);
|
|
|
|
frame.setLeft(nav);
|
|
updateNav(NavState.INIT);
|
|
|
|
//Footer
|
|
BorderPane footer = new BorderPane();
|
|
footer.setId("framefooter");
|
|
footer.setCenter(new Label(Text.FOOTER_TEXT));
|
|
frame.setBottom(footer);
|
|
nav.minHeightProperty().bind(Bindings.createDoubleBinding(() -> frame.getHeight() - header.getHeight()
|
|
- footer.getHeight() - Utils.darkBlueBorder.getInsets().getBottom() * 2, frame.heightProperty()));
|
|
|
|
return frame;
|
|
}
|
|
|
|
/**
|
|
* Adjusts the navigation to the state wanted
|
|
* @param state new navigation state
|
|
*/
|
|
public void updateNav(NavState state)
|
|
{
|
|
//handlers which will be used more than once
|
|
//those are handlers for going to these views the *first* time with the current data
|
|
EventHandler<MouseEvent> toOverview = new EventHandler<MouseEvent>()
|
|
{
|
|
@Override
|
|
public void handle(MouseEvent arg0)
|
|
{
|
|
changeView(getProgressView(Text.WIP_READING_FILE));
|
|
WorkWhileProgressThread t = new WorkWhileProgressThread(cb, true);
|
|
t.start();
|
|
}
|
|
};
|
|
EventHandler<MouseEvent> toIntroView = new EventHandler<MouseEvent>()
|
|
{
|
|
@Override
|
|
public void handle(MouseEvent arg0)
|
|
{
|
|
changeView(getIntroView());
|
|
updateNav(NavState.INIT);
|
|
if (filename == null)
|
|
{
|
|
ddlabel.setText(Text.SELECT_FILE);
|
|
}
|
|
else
|
|
{
|
|
ddlabel.setText(String.format(Text.FOUND_FILE, filename));
|
|
}
|
|
|
|
}
|
|
};
|
|
EventHandler<MouseEvent> toInspectView = new EventHandler<MouseEvent>()
|
|
{
|
|
@Override
|
|
public void handle(MouseEvent arg0)
|
|
{
|
|
changeView(getProgressView(Text.WIP_CREATE_FILE));
|
|
WorkWhileProgressThread t = new WorkWhileProgressThread(cb, false);
|
|
t.start();
|
|
}
|
|
};
|
|
EventHandler<MouseEvent> toResultView = new EventHandler<MouseEvent>()
|
|
{
|
|
@Override
|
|
public void handle(MouseEvent arg0)
|
|
{
|
|
fileForSaving = worker.writeToZipFile(filesInTempWithDesc, dirForSaving);
|
|
changeView(getResultView());
|
|
updateNav(NavState.RESULT);
|
|
}
|
|
};
|
|
toPrivacyView = new EventHandler<MouseEvent>()
|
|
{
|
|
@Override
|
|
public void handle(MouseEvent arg0)
|
|
{
|
|
changeView(getPrivacyView());
|
|
updateNav(NavState.PRIVACY_STATEMENT);
|
|
}
|
|
};
|
|
//these handlers are used for returning to a previous state
|
|
EventHandler<MouseEvent> returnToIntroView = new EventHandler<MouseEvent>()
|
|
{
|
|
@Override
|
|
public void handle(MouseEvent arg0)
|
|
{
|
|
changeView(getIntroView());
|
|
updateNav(NavState.IMPORT_GIVEN);
|
|
privAgree.setSelected(true);
|
|
ddlabel.setText(String.format(Text.FOUND_FILE, filename));
|
|
}
|
|
};
|
|
EventHandler<MouseEvent> returnToOverview = new EventHandler<MouseEvent>()
|
|
{
|
|
@Override
|
|
public void handle(MouseEvent event)
|
|
{
|
|
changeView(getOverviewView());
|
|
updateNav(NavState.DATA_AND_PATH_SELECTED);
|
|
path.setText(String.format(Text.F_SAVE_AT,dirForSaving.getAbsolutePath()));
|
|
}
|
|
};
|
|
|
|
//always active
|
|
setNavElemActive(privacy, toPrivacyView);
|
|
|
|
if (state == NavState.PRIVACY_STATEMENT)
|
|
{
|
|
setNavElemSelected(privacy, toPrivacyView);
|
|
setNavElemDeselected(start);
|
|
setNavElemDeselected(select);
|
|
setNavElemDeselected(inspect);
|
|
setNavElemDeselected(result);
|
|
}
|
|
if (state == NavState.INIT)
|
|
{
|
|
//first statment for tooltip
|
|
setNavElemActive(start, returnToIntroView);
|
|
setNavElemSelected(start, toIntroView);
|
|
setNavElemInactive(select);
|
|
setNavElemInactive(inspect);
|
|
setNavElemInactive(result);
|
|
}
|
|
if (state == NavState.IMPORT_GIVEN)
|
|
{
|
|
setNavElemSelected(start, returnToIntroView);
|
|
setNavElemActive(select, toOverview);
|
|
setNavElemInactive(inspect);
|
|
setNavElemInactive(result);
|
|
}
|
|
if (state == NavState.SELECT_DATA)
|
|
{
|
|
setNavElemActive(start, returnToIntroView);
|
|
setNavElemSelected(select, toOverview);
|
|
setNavElemInactive(inspect);
|
|
setNavElemInactive(result);
|
|
}
|
|
if (state == NavState.DATA_AND_PATH_SELECTED)
|
|
{
|
|
setNavElemActive(start, returnToIntroView);
|
|
setNavElemSelected(select, returnToOverview);
|
|
setNavElemActive(inspect, toInspectView);
|
|
setNavElemInactive(result);
|
|
}
|
|
if (state == NavState.START_AGAIN)
|
|
{
|
|
setNavElemSelected(start, returnToIntroView);
|
|
setNavElemDeselected(select);
|
|
setNavElemDeselected(inspect);
|
|
setNavElemDeselected(result);
|
|
}
|
|
if (state == NavState.INSPECT)
|
|
{
|
|
setNavElemActive(start, returnToIntroView);
|
|
setNavElemActive(select, returnToOverview);
|
|
setNavElemSelected(inspect, toInspectView);
|
|
setNavElemActive(result, toResultView);
|
|
}
|
|
if (state == NavState.INSPECT_WITH_ERROR)
|
|
{
|
|
setNavElemActive(start, returnToIntroView);
|
|
setNavElemActive(select, returnToOverview);
|
|
setNavElemSelected(inspect, toInspectView);
|
|
setNavElemDeselected(result);
|
|
}
|
|
if (state == NavState.RESULT)
|
|
{
|
|
setNavElemActive(start, returnToIntroView);
|
|
setNavElemActive(select, returnToOverview);
|
|
setNavElemActive(inspect, toInspectView);
|
|
setNavElemSelected(result, toResultView);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Sets a navigation element to be active. That makes it clickable.
|
|
* @param element Element to be set active
|
|
* @param onClick action to be done when it is clicked.
|
|
*/
|
|
private void setNavElemActive(BorderPane element, EventHandler<MouseEvent> onClick)
|
|
{
|
|
element.setBackground(Backgrounds.darkBlueBackground);
|
|
element.setBorder(null);
|
|
Tooltip tooltip = new Tooltip(element.getUserData().toString());
|
|
element.setOnMouseEntered(new EventHandler<MouseEvent>()
|
|
{
|
|
@Override
|
|
public void handle(MouseEvent event)
|
|
{
|
|
Point2D p = element.localToScreen(element.getLayoutBounds().getMaxX(),
|
|
element.getLayoutBounds().getMinY());
|
|
((Label)element.getRight()).setTooltip(tooltip);
|
|
tooltip.show(((Label)element.getRight()), p.getX(), p.getY());
|
|
tooltip.setAutoHide(true);
|
|
}
|
|
});
|
|
element.setOnMouseExited(new EventHandler<MouseEvent>()
|
|
{
|
|
@Override
|
|
public void handle(MouseEvent event)
|
|
{
|
|
tooltip.hide();
|
|
}
|
|
});
|
|
|
|
element.setOnMouseClicked(onClick);
|
|
}
|
|
|
|
/**
|
|
* Sets a navigation element as inactive
|
|
* @param element the element which will be inactive
|
|
*/
|
|
private void setNavElemInactive(BorderPane element)
|
|
{
|
|
element.setBackground(Backgrounds.greyBackground);
|
|
element.setOnMouseEntered(null);
|
|
element.setBorder(null);
|
|
element.setOnMouseClicked(null);
|
|
}
|
|
|
|
/**
|
|
* Selects a navigation element. It indicates the currently active view
|
|
* @param element Navigation element to be selected
|
|
* @param onClick Handler which should be executed in case it was clicked on
|
|
*/
|
|
private void setNavElemSelected(BorderPane element, EventHandler<MouseEvent> onClick)
|
|
{
|
|
element.setBackground(Backgrounds.darkBlueBackground);
|
|
element.setBorder(Utils.redBorder);
|
|
element.setOnMouseClicked(onClick);
|
|
}
|
|
|
|
/**
|
|
* Deselects a navigation element
|
|
* @param element the element to be deselected
|
|
*/
|
|
private void setNavElemDeselected(BorderPane element)
|
|
{
|
|
element.setBorder(null);
|
|
}
|
|
|
|
/**
|
|
* Initialized the stage
|
|
* @param stage
|
|
*/
|
|
public void setStage(Stage stage)
|
|
{
|
|
this.stage = stage;
|
|
stage.setScene(scene);
|
|
stage.setTitle(Text.TITLE);
|
|
stage.getIcons().add(new Image(this.getClass().getResourceAsStream("RI_Logo_blau_en_short.png")));
|
|
stage.show();
|
|
|
|
}
|
|
|
|
/**
|
|
* Switches the displayed view (always in a ScrollPane)
|
|
* @param view The new view to be shown
|
|
*/
|
|
public void changeView(Pane view)
|
|
{
|
|
ScrollPane scroll = new ScrollPane();
|
|
scroll.setContent(view);
|
|
scroll.setId("scroll");
|
|
frame.setCenter(scroll);
|
|
scroll.getStyleClass().add("edge-to-edge");
|
|
view.minWidthProperty()
|
|
.bind(Bindings.createDoubleBinding(() -> frame.getCenter().minWidth(0), frame.widthProperty()));
|
|
scroll.setFitToWidth(true);
|
|
}
|
|
|
|
/**
|
|
* Returns the scene
|
|
* @return the described value
|
|
*/
|
|
public Scene getScene()
|
|
{
|
|
return scene;
|
|
}
|
|
|
|
/**
|
|
* Creates the first view which is shown after starting the application. It
|
|
* allows the user to insert a health file and check the privacy policy
|
|
*
|
|
* @return the created view
|
|
*/
|
|
private VBox getIntroView()
|
|
{
|
|
VBox container = new VBox();
|
|
container.setId("container");
|
|
|
|
container.getChildren().add(new Label(Text.MAIN_INFO));
|
|
Label appleLink = new Label(Text.APPLE_LINK_EXPORT);
|
|
container.getChildren().add(appleLink);
|
|
appleLink.setTextFill(Colors.grey);
|
|
appleLink.setOnMouseEntered(new EventHandler<Event>()
|
|
{
|
|
@Override
|
|
public void handle(Event event)
|
|
{
|
|
appleLink.setTextFill(Colors.blue);
|
|
}
|
|
});
|
|
appleLink.setOnMouseExited(new EventHandler<Event>()
|
|
{
|
|
@Override
|
|
public void handle(Event event)
|
|
{
|
|
appleLink.setTextFill(Colors.grey);
|
|
}
|
|
});
|
|
appleLink.setOnMouseClicked(new EventHandler<Event>()
|
|
{
|
|
@Override
|
|
public void handle(Event event)
|
|
{
|
|
try
|
|
{
|
|
hostServices.showDocument(new URL(Text.APPLE_LINK_EXPORT).toExternalForm());
|
|
}
|
|
catch (MalformedURLException e)
|
|
{
|
|
//do nth
|
|
}
|
|
|
|
}
|
|
});
|
|
|
|
//Allow drag and drop for the health file
|
|
HBox ddTarget = new HBox();
|
|
ddTarget.setId("ddTarget");
|
|
ddlabel.setId("ddLabel");
|
|
ddTarget.minWidthProperty()
|
|
.bind(Bindings.createDoubleBinding(() -> container.getWidth(), container.widthProperty()));
|
|
ddlabel.minWidthProperty()
|
|
.bind(Bindings.createDoubleBinding(() -> ddTarget.getWidth(), ddTarget.widthProperty()));
|
|
|
|
ddTarget.getChildren().add(ddlabel);
|
|
ddTarget.setOnDragOver(new EventHandler<DragEvent>()
|
|
{
|
|
@Override
|
|
public void handle(DragEvent event)
|
|
{
|
|
if (event.getGestureSource() != ddTarget && event.getDragboard().hasFiles())
|
|
{
|
|
event.acceptTransferModes(TransferMode.COPY_OR_MOVE);
|
|
}
|
|
event.consume();
|
|
}
|
|
});
|
|
ddTarget.setOnDragDropped(new EventHandler<DragEvent>()
|
|
{
|
|
@Override
|
|
public void handle(DragEvent event)
|
|
{
|
|
Dragboard db = event.getDragboard();
|
|
boolean success = false;
|
|
if (db.hasFiles())
|
|
{
|
|
filename = db.getFiles().toString().replace("[", "").replace("]", "");
|
|
ddlabel.setText(String.format(Text.FOUND_FILE, filename));
|
|
checkFile(filename);
|
|
success = true;
|
|
}
|
|
event.setDropCompleted(success);
|
|
event.consume();
|
|
}
|
|
});
|
|
container.getChildren().add(ddTarget);
|
|
container.getChildren().add(wrong_file);
|
|
|
|
//check privacy policy
|
|
privAgree = new CheckBox();
|
|
privAgree.setText(Text.PRIVACY_STATEMENT_ACCEPTED);
|
|
privAgree.setWrapText(true);
|
|
privAgree.setStyle("-fx-font-family: \"Arial\"");
|
|
privAgree.selectedProperty().addListener(new ChangeListener<Boolean>()
|
|
{
|
|
@Override
|
|
public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue)
|
|
{
|
|
checkFile(filename);
|
|
}
|
|
});
|
|
privAgree.minWidthProperty()
|
|
.bind(Bindings.createDoubleBinding(() -> container.getWidth(), container.widthProperty()));
|
|
container.getChildren().add(privAgree);
|
|
|
|
//Button to be directed to the privacy view
|
|
HBox gotToPrivacyView = new HBox();
|
|
gotToPrivacyView.setPrefHeight(50);
|
|
gotToPrivacyView.setId("goToPriv");
|
|
BorderPane button = new BorderPane();
|
|
button.setCenter(new Label(Text.GO_TO_PRIVACY_STATEMENT));
|
|
button.setOnMouseClicked(toPrivacyView);
|
|
button.setId("goToPrivButton");
|
|
|
|
gotToPrivacyView.getChildren().addAll(button);
|
|
HBox.setHgrow(button, Priority.ALWAYS);
|
|
container.getChildren().add(gotToPrivacyView);
|
|
return container;
|
|
}
|
|
|
|
/**
|
|
* checks on a superficial level whether the input health file is correct
|
|
* (fileType) and adjusts the navigation
|
|
*
|
|
* @param filename Filename to check
|
|
*/
|
|
private void checkFile(String filename)
|
|
{
|
|
if (filename != null && (filename.endsWith(".xml") || filename.endsWith(".zip")))
|
|
{
|
|
if (privAgree.isSelected())
|
|
{
|
|
updateNav(NavState.IMPORT_GIVEN);
|
|
|
|
}
|
|
else
|
|
{
|
|
updateNav(NavState.INIT);
|
|
}
|
|
wrong_file.setText("");
|
|
}
|
|
else if (filename != null)
|
|
{
|
|
updateNav(NavState.INIT);
|
|
wrong_file.setText(Text.NO_VALID_FILE);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Creates a progress view to be shown when the application needs some time
|
|
* working
|
|
*
|
|
* @param text Text to be displayed in the view
|
|
* @return the created view
|
|
*/
|
|
public VBox getProgressView(String text)
|
|
{
|
|
VBox container = new VBox();
|
|
container.setId("container");
|
|
|
|
Label l = new Label(text);
|
|
container.getChildren().add(l);
|
|
|
|
ProgressIndicator PI = new ProgressIndicator();
|
|
container.getChildren().add(PI);
|
|
return container;
|
|
}
|
|
|
|
/**
|
|
* This creates the third view which shows the created files in temp dir and
|
|
* allows the user to inspect them. Don't change any widths and heights here!!!
|
|
*
|
|
* @return the created view
|
|
*/
|
|
public VBox getInspectView()
|
|
{
|
|
VBox container = new VBox();
|
|
container.setId("container");
|
|
container.setPadding(new Insets(0, 0, 5, 0));
|
|
|
|
Label l = new Label(Text.PLEASE_INSPECT);
|
|
container.getChildren().add(l);
|
|
|
|
GridPane files = new GridPane();
|
|
files.setBorder(Utils.darkBlueBorder);
|
|
int oneFileViewWidth = FileView.WIDTH;
|
|
int filesBorderWidth = (int) (files.getBorder().getInsets().getLeft()
|
|
+ files.getBorder().getInsets().getRight());
|
|
|
|
container.getChildren().add(files);
|
|
files.maxWidthProperty().bind(Bindings.createDoubleBinding(() ->
|
|
// windowWidth - (border*2) = width for fileViews
|
|
// floor(width for fileViews/Fileview.width) = number of possible views
|
|
// number of possible views*FileView.width = needed width for fileViews
|
|
// needed width for fileViews+ borders = complete width
|
|
(Math.floor((container.getWidth() - filesBorderWidth) / oneFileViewWidth) * oneFileViewWidth)
|
|
// borders of the FlowPane
|
|
+ filesBorderWidth, container.widthProperty()));
|
|
|
|
// if the container width changes, the number of views should also change
|
|
container.widthProperty().addListener(new ChangeListener<Number>()
|
|
{
|
|
@Override
|
|
public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue)
|
|
{
|
|
int oneFileViewWidth = FileView.WIDTH;
|
|
int filesBorderWidth = (int) (files.getBorder().getInsets().getLeft()
|
|
+ files.getBorder().getInsets().getRight());
|
|
|
|
int col = 0;
|
|
int row = 0;
|
|
int colElems = (int) ((container.getWidth() - filesBorderWidth) / oneFileViewWidth);
|
|
if (filesInTempWithDesc != null)
|
|
{
|
|
files.getChildren().clear();
|
|
for (String desc : filesInTempWithDesc.keySet())
|
|
{
|
|
files.add(new FileView(filesInTempWithDesc.get(desc), desc, hostServices), col, row);
|
|
col++;
|
|
if (col == colElems)
|
|
{
|
|
row++;
|
|
col = 0;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
files.getChildren().add(new Label(errorWritingFiles));
|
|
}
|
|
|
|
}
|
|
});
|
|
return container;
|
|
}
|
|
|
|
/**
|
|
* Creates the second view which contains all the information of the health data
|
|
*
|
|
* @return created view
|
|
*/
|
|
public VBox getOverviewView()
|
|
{
|
|
VBox container = new VBox();
|
|
container.setId("container");
|
|
|
|
// Label selectText = new Label(Text.SELECT_CATEGORIES);
|
|
// container.getChildren().add(selectText);
|
|
//
|
|
container.getChildren().add(new Label(Text.SELECT_INTRO));
|
|
|
|
// input the job
|
|
container.getChildren().add(getJobSelection(container));
|
|
|
|
// View for clicking and setting the path for saving the resulting data
|
|
BorderPane selectSavePath = new BorderPane();
|
|
String currentUsersHomeDir = System.getProperty("user.home");
|
|
if(dirForSaving==null)
|
|
{
|
|
dirForSaving= new File(currentUsersHomeDir);
|
|
}
|
|
path = new Label(String.format(Text.F_LABEL_SAVE_PATH, currentUsersHomeDir));
|
|
|
|
selectSavePath.setCenter(path);
|
|
path.minWidthProperty()
|
|
.bind(Bindings.createDoubleBinding(() -> container.getWidth(), container.widthProperty()));
|
|
path.setOnMouseClicked(new EventHandler<MouseEvent>()
|
|
{
|
|
@Override
|
|
public void handle(MouseEvent event)
|
|
{
|
|
DirectoryChooser dirChooser = new DirectoryChooser();
|
|
dirChooser.setTitle("Save Data");
|
|
File var = dirChooser.showDialog(stage);
|
|
|
|
if (var != null)
|
|
{
|
|
dirForSaving = var;
|
|
path.setText(String.format(Text.F_SAVE_AT, dirForSaving.getPath()));
|
|
if (selectCount > 0)
|
|
{
|
|
updateNav(NavState.DATA_AND_PATH_SELECTED);
|
|
}
|
|
}
|
|
}
|
|
|
|
});
|
|
path.setOnMouseEntered(new EventHandler<Event>()
|
|
{
|
|
@Override
|
|
public void handle(Event event)
|
|
{
|
|
path.setTextFill(Colors.blue);
|
|
}
|
|
});
|
|
path.setOnMouseExited(new EventHandler<Event>()
|
|
{
|
|
@Override
|
|
public void handle(Event event)
|
|
{
|
|
path.setTextFill(Color.BLACK);
|
|
}
|
|
});
|
|
container.getChildren().add(selectSavePath);
|
|
|
|
|
|
container.getChildren().add(new Label(Text.SELECT_HOW_TO));
|
|
|
|
// These are the buttons to help selection
|
|
HBox selectButtons = new HBox();
|
|
VBox.setVgrow(selectButtons, Priority.ALWAYS);
|
|
selectButtons.setId("selectButtons");
|
|
|
|
BorderPane selectAll = new BorderPane();
|
|
selectAll.setCenter(new Label(Text.SELECT_ALL));
|
|
selectAll.setOnMouseClicked(new EventHandler<MouseEvent>()
|
|
{
|
|
@Override
|
|
public void handle(MouseEvent arg0)
|
|
{
|
|
for (Node n : datalist.getChildren())
|
|
{
|
|
if (n instanceof EntryView)
|
|
{
|
|
EntryView i = (EntryView) n;
|
|
i.setSelected(true, true);
|
|
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
BorderPane deselectAll = new BorderPane();
|
|
deselectAll.setCenter(new Label(Text.DESELECT_ALL));
|
|
deselectAll.setOnMouseClicked(new EventHandler<MouseEvent>()
|
|
{
|
|
@Override
|
|
public void handle(MouseEvent arg0)
|
|
{
|
|
updateNav(NavState.SELECT_DATA);
|
|
for (Node n : datalist.getChildren())
|
|
{
|
|
if (n instanceof EntryView)
|
|
{
|
|
EntryView i = (EntryView) n;
|
|
i.setSelected(false, true);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
BorderPane selectCurrentResearchMinimum = new BorderPane();
|
|
Label l = new Label(Text.SELECT_BASIC_FIELD_OF_INTEREST);
|
|
l.setWrapText(true);
|
|
|
|
selectCurrentResearchMinimum.minHeightProperty()
|
|
.bind(Bindings.createDoubleBinding(() -> l.getMaxHeight(), l.maxHeightProperty()));
|
|
selectCurrentResearchMinimum.maxHeightProperty()
|
|
.bind(Bindings.createDoubleBinding(() -> l.getMaxHeight(), l.maxHeightProperty()));
|
|
selectCurrentResearchMinimum.minWidthProperty()
|
|
.bind(Bindings.createDoubleBinding(() -> l.getWidth(), l.widthProperty()));
|
|
|
|
selectCurrentResearchMinimum.setCenter(l);
|
|
selectCurrentResearchMinimum.setOnMouseClicked(new EventHandler<MouseEvent>()
|
|
{
|
|
@Override
|
|
public void handle(MouseEvent arg0)
|
|
{
|
|
for (Node n : datalist.getChildren())
|
|
{
|
|
if (n instanceof EntryView)
|
|
{
|
|
EntryView i = (EntryView) n;
|
|
i.setSelected(false, true);
|
|
}
|
|
}
|
|
for (Node n : datalist.getChildren())
|
|
{
|
|
if (n instanceof EntryView)
|
|
{
|
|
EntryView i = (EntryView) n;
|
|
// Top level
|
|
// biologicalSex, regionCode
|
|
if (i.getEntryType().equals(EntryType.BIOLOGICAL_SEX)
|
|
|| i.getEntryType().equals(EntryType.REGION_CODE))
|
|
{
|
|
i.setSelected(true, true);
|
|
}
|
|
// sub elements
|
|
// year of birth, stepCount,
|
|
if (i.getEntryType().equals(EntryType.DATE_OF_BIRTH))
|
|
{
|
|
i.selectSubelement(Text.YEAR);
|
|
}
|
|
if (i.getEntryType().equals(EntryType.RECORD))
|
|
{
|
|
i.selectSubelement("StepCount");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
BorderPane selectCurrentResearchAdvanced = new BorderPane();
|
|
Label lAdvanced = new Label(Text.SELECT_ADVANCED_FIELD_OF_INTEREST);
|
|
lAdvanced.setWrapText(true);
|
|
selectCurrentResearchAdvanced.minWidthProperty()
|
|
.bind(Bindings.createDoubleBinding(() -> lAdvanced.getWidth(), lAdvanced.widthProperty()));
|
|
selectCurrentResearchAdvanced.setCenter(lAdvanced);
|
|
selectCurrentResearchAdvanced.setOnMouseClicked(new EventHandler<MouseEvent>()
|
|
{
|
|
@Override
|
|
public void handle(MouseEvent arg0)
|
|
{
|
|
for (Node n : datalist.getChildren())
|
|
{
|
|
if (n instanceof EntryView)
|
|
{
|
|
EntryView i = (EntryView) n;
|
|
i.setSelected(false, true);
|
|
}
|
|
}
|
|
for (Node n : datalist.getChildren())
|
|
{
|
|
if (n instanceof EntryView)
|
|
{
|
|
EntryView i = (EntryView) n;
|
|
// Top level
|
|
if (i.getEntryType().equals(EntryType.BIOLOGICAL_SEX)
|
|
|| i.getEntryType().equals(EntryType.REGION_CODE))
|
|
{
|
|
i.setSelected(true, true);
|
|
}
|
|
// sub elements
|
|
if (i.getEntryType().equals(EntryType.DATE_OF_BIRTH))
|
|
{
|
|
i.selectSubelement(Text.YEAR);
|
|
}
|
|
if (i.getEntryType().equals(EntryType.RECORD))
|
|
{
|
|
i.selectSubelement("StepCount");
|
|
i.selectSubelement("RestingHeartRate");
|
|
i.selectSubelement("BodyMass");
|
|
i.selectSubelement("Height");
|
|
i.selectSubelement("RespiratoryRate");
|
|
i.selectSubelement("SwimmingStrokeCount");
|
|
i.selectSubelement("DistanceSwimming");
|
|
i.selectSubelement("SleepAnalysis");
|
|
i.selectSubelement("DistanceWalkingRunning");
|
|
i.selectSubelement("HeartRate");
|
|
i.selectSubelement("DistanceCycling");
|
|
i.selectSubelement("HeartRateVariabilitySDNN");
|
|
}
|
|
if (i.getEntryType().equals(EntryType.WORKOUT))
|
|
{
|
|
i.selectSubelement("Cycling");
|
|
i.selectSubelement("Walking");
|
|
i.selectSubelement("Running");
|
|
i.selectSubelement("Swimming");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
|
|
selectButtons.getChildren().addAll(selectAll, selectCurrentResearchAdvanced, selectCurrentResearchMinimum,deselectAll);
|
|
//-30 here needed because of padding and spacing etc.
|
|
selectAll.minWidthProperty()
|
|
.bind(Bindings.createDoubleBinding(() ->(selectButtons.getWidth()-30)/4, selectButtons.widthProperty()));
|
|
deselectAll.minWidthProperty()
|
|
.bind(Bindings.createDoubleBinding(() ->(selectButtons.getWidth()-30)/4, selectButtons.widthProperty()));
|
|
selectCurrentResearchAdvanced.minWidthProperty()
|
|
.bind(Bindings.createDoubleBinding(() ->(selectButtons.getWidth()-30)/4, selectButtons.widthProperty()));
|
|
selectCurrentResearchMinimum.minWidthProperty()
|
|
.bind(Bindings.createDoubleBinding(() ->(selectButtons.getWidth()-30)/4, selectButtons.widthProperty()));
|
|
|
|
//Fix for apple: boxes are too big on init without this
|
|
selectAll.maxHeightProperty()
|
|
.bind(Bindings.createDoubleBinding(() ->80.0, selectAll.heightProperty()));
|
|
selectCurrentResearchMinimum.maxHeightProperty()
|
|
.bind(Bindings.createDoubleBinding(() ->80.0, selectCurrentResearchMinimum.heightProperty()));
|
|
selectCurrentResearchAdvanced.maxHeightProperty()
|
|
.bind(Bindings.createDoubleBinding(() ->80.0, selectCurrentResearchAdvanced.heightProperty()));
|
|
deselectAll.maxHeightProperty()
|
|
.bind(Bindings.createDoubleBinding(() ->80.0, deselectAll.heightProperty()));
|
|
|
|
container.getChildren().add(selectButtons);
|
|
deselectAll.requestFocus();
|
|
|
|
|
|
// Here is the data, but its only drawn here. Loading of the data is done
|
|
// somewhere else
|
|
BorderPane datacontainer = new BorderPane();
|
|
datacontainer.setPadding(new Insets(5));
|
|
datacontainer.setId("datacontainer");
|
|
datacontainer.setCenter(datalist);
|
|
container.getChildren().add(datacontainer);
|
|
datacontainer.minWidthProperty()
|
|
.bind(Bindings.createDoubleBinding(() -> container.getWidth(), container.widthProperty()));
|
|
datacontainer.maxWidthProperty()
|
|
.bind(Bindings.createDoubleBinding(() -> container.getWidth(), container.widthProperty()));
|
|
datalist.minWidthProperty()
|
|
.bind(Bindings.createDoubleBinding(() -> container.getWidth(), container.widthProperty()));
|
|
datalist.maxWidthProperty()
|
|
.bind(Bindings.createDoubleBinding(() -> container.getWidth(), container.widthProperty()));
|
|
|
|
|
|
return container;
|
|
}
|
|
|
|
|
|
/**
|
|
* Returns the matching occupation list from {@link Occupations}, inserts
|
|
* {@code Text.NOT_SET} and selects a subset from the prefix (if level >2)
|
|
* @param prefix The prefix of the string (number combination)
|
|
* to define the subset. The code of the super group.
|
|
* @return The described value, {@code null} if value < 0 or > 4
|
|
*/
|
|
private ObservableList<String> getOccupationList( String prefix)
|
|
{
|
|
Predicate<String> prefixPred = new Predicate<String>()
|
|
{
|
|
@Override
|
|
public boolean test(String t)
|
|
{
|
|
return t.startsWith(prefix)||t.equals(Text.NOT_SET);
|
|
}
|
|
};
|
|
|
|
if(prefix.length()==0)
|
|
{
|
|
return Occupations.JOBS_LEVEL_1;
|
|
}
|
|
else if(prefix.length()==1)
|
|
{
|
|
return Occupations.JOBS_LEVEL_2.filtered(prefixPred);
|
|
}
|
|
else if(prefix.length()==2)
|
|
{
|
|
return Occupations.JOBS_LEVEL_3.filtered(prefixPred);
|
|
}
|
|
else if(prefix.length()==3)
|
|
{
|
|
return Occupations.JOBS_LEVEL_4.filtered(prefixPred);
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* This method creates a styled comboBox for the occupations
|
|
* @param container For the width binding
|
|
* @return the created comboBox
|
|
*/
|
|
private ComboBox<String> getComboBox(Pane container)
|
|
{
|
|
ComboBox<String> box= new ComboBox<>();
|
|
box.setDisable(true);
|
|
box.setBackground(Backgrounds.lightGreyBackground);
|
|
box.minWidthProperty()
|
|
.bind(Bindings.createDoubleBinding(() -> container.getWidth()-(2*container.getBorder().getInsets().getRight()), container.widthProperty()));
|
|
box.maxWidthProperty()
|
|
.bind(Bindings.createDoubleBinding(() -> container.getWidth()-(2*container.getBorder().getInsets().getRight()), container.widthProperty()));
|
|
|
|
return box;
|
|
}
|
|
|
|
/**
|
|
* Method creates and prepares the dropdown selections for the jobs.
|
|
* @param container Container for binding the width to
|
|
* @return A pane containing the dropdowns and info texts
|
|
*/
|
|
private Pane getJobSelection(Pane container)
|
|
{
|
|
Label addJob = new Label(Text.ADD_JOB);
|
|
VBox comboContainer = new VBox();
|
|
comboContainer.setBorder(Utils.darkBlueBorder);
|
|
ComboBox<String> levelOne = getComboBox(comboContainer);
|
|
ComboBox<String> levelTwo = getComboBox(comboContainer);
|
|
ComboBox<String> levelThree = getComboBox(comboContainer);
|
|
ComboBox<String> levelFour = getComboBox(comboContainer);
|
|
levelOne.setStyle("-fx-font-family :\"Arial\"");
|
|
levelTwo.setStyle("-fx-font-family :\"Arial\"");
|
|
levelThree.setStyle("-fx-font-family :\"Arial\"");
|
|
levelFour.setStyle("-fx-font-family :\"Arial\"");
|
|
|
|
levelOne.setItems(getOccupationList(""));
|
|
levelOne.setDisable(false);
|
|
levelOne.setValue(Text.NOT_SET);
|
|
|
|
levelOne.valueProperty().addListener(new ChangeListener<String>()
|
|
{
|
|
@Override
|
|
public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue)
|
|
{
|
|
occupation.setLevelOne(newValue);
|
|
if(newValue.equals(Text.NOT_SET))
|
|
{
|
|
levelTwo.setDisable(true);
|
|
occupation.setLevelTwo(null);
|
|
levelTwo.setItems(null);
|
|
}
|
|
else
|
|
{
|
|
String prefix = ""+newValue.charAt(0);
|
|
levelTwo.setItems(getOccupationList(prefix));
|
|
levelTwo.setDisable(false);
|
|
levelTwo.setValue(Text.NOT_SET);
|
|
}
|
|
}
|
|
});
|
|
|
|
levelTwo.valueProperty().addListener(new ChangeListener<String>()
|
|
{
|
|
@Override
|
|
public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue)
|
|
{
|
|
occupation.setLevelTwo(newValue);
|
|
if(newValue==null ||newValue.equals(Text.NOT_SET))
|
|
{
|
|
levelThree.setItems(null);
|
|
occupation.setLevelThree(null);
|
|
levelThree.setDisable(true);
|
|
}
|
|
else
|
|
{
|
|
String prefix = ""+newValue.substring(0,2);
|
|
levelThree.setItems(getOccupationList( prefix));
|
|
levelThree.setDisable(false);
|
|
levelThree.setValue(Text.NOT_SET);
|
|
}
|
|
}
|
|
});
|
|
|
|
levelThree.valueProperty().addListener(new ChangeListener<String>()
|
|
{
|
|
@Override
|
|
public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue)
|
|
{
|
|
occupation.setLevelThree(newValue);
|
|
if(newValue==null ||newValue.equals(Text.NOT_SET))
|
|
{
|
|
occupation.setLevelFour(null);
|
|
levelFour.setItems(null);
|
|
levelFour.setDisable(true);
|
|
}
|
|
else
|
|
{
|
|
String prefix = newValue.substring(0,3);
|
|
levelFour.setItems(getOccupationList( prefix));
|
|
levelFour.setDisable(false);
|
|
levelFour.setValue(Text.NOT_SET);
|
|
}
|
|
}
|
|
});
|
|
|
|
levelFour.valueProperty().addListener(new ChangeListener<String>(){
|
|
|
|
@Override
|
|
public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue)
|
|
{
|
|
occupation.setLevelFour(newValue);
|
|
|
|
}});
|
|
|
|
comboContainer.getChildren().add(levelOne);
|
|
comboContainer.getChildren().add(levelTwo);
|
|
comboContainer.getChildren().add(levelThree);
|
|
comboContainer.getChildren().add(levelFour);
|
|
|
|
if(occupation==null)
|
|
{
|
|
occupation= new Occupation(Text.NOT_SET);
|
|
}
|
|
else
|
|
{
|
|
String lTwo=occupation.getLevelTwo();
|
|
String lThree=occupation.getLevelThree();
|
|
String lFour=occupation.getLevelFour();
|
|
levelOne.setValue(occupation.getLevelOne());
|
|
levelTwo.setValue(lTwo);
|
|
levelThree.setValue(lThree);
|
|
levelFour.setValue(lFour);
|
|
}
|
|
|
|
HBox jobInfo = new HBox();
|
|
jobInfo.setId("jobInfo");
|
|
jobInfo.minWidthProperty()
|
|
.bind(Bindings.createDoubleBinding(() -> container.getWidth(), container.widthProperty()));
|
|
jobInfo.maxWidthProperty()
|
|
.bind(Bindings.createDoubleBinding(() -> container.getWidth(), container.widthProperty()));
|
|
jobInfo.maxHeightProperty()
|
|
.bind(Bindings.createDoubleBinding(() -> jobInfo.getPrefHeight(), jobInfo.prefHeightProperty()));
|
|
|
|
comboContainer.minHeightProperty()
|
|
.bind(Bindings.createDoubleBinding(() -> addJob.getHeight(), addJob.heightProperty()));
|
|
|
|
addJob.maxWidthProperty()
|
|
.bind(Bindings.createDoubleBinding(() -> container.getWidth()/2, container.widthProperty()));
|
|
|
|
HBox.setHgrow(comboContainer,Priority.ALWAYS);
|
|
jobInfo.getChildren().add(comboContainer);
|
|
jobInfo.getChildren().add(addJob);
|
|
|
|
// VBox occupationSelection = new VBox();
|
|
// occupationSelection.setBorder(Utils.darkBlueBorder);
|
|
// occupationSelection.getChildren().add(jobInfo);
|
|
// occupationSelection.getChildren().add(new OccupationSelectionView(1, getOccupationList("")));
|
|
return jobInfo;
|
|
}
|
|
|
|
/**
|
|
* The health data file is read and the overview of all found data is included
|
|
* in the datalist
|
|
*
|
|
* @throws WrappedException if the file coulnd't be read
|
|
*/
|
|
public void fillDataList() throws WrappedException
|
|
{
|
|
datalist.getChildren().clear();
|
|
File file;
|
|
if (filename.contains(".zip"))
|
|
{ // a zip file can't be read just like this and so the containing file needs to
|
|
// be copied into temp
|
|
try
|
|
{
|
|
ZipFile f = new ZipFile(filename);
|
|
String xmlFileName = "apple_health_export/Export.xml";
|
|
file = Files.createTempFile("health_data", "__Export.xml").toFile();
|
|
file.deleteOnExit();
|
|
ZipEntry xml = f.getEntry(xmlFileName);
|
|
if (xml == null)
|
|
{
|
|
xml = f.getEntry(xmlFileName.toLowerCase());
|
|
}
|
|
try (BufferedInputStream is = new BufferedInputStream(f.getInputStream(xml));
|
|
BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(file)))
|
|
{
|
|
byte[] b = new byte[1024];
|
|
int res = is.read(b);
|
|
while (res > -1)
|
|
{
|
|
out.write(b, 0, res);
|
|
res = is.read(b);
|
|
}
|
|
}
|
|
f.close();
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
// The zip-File couldn't be read, maybe it was the wrong file or error
|
|
throw new WrappedException(e, Text.E_READ_ZIP_FILE);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
file = new File(filename);
|
|
}
|
|
try
|
|
{
|
|
worker = new ParsingWrapper(file);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
throw new WrappedException(e, Text.E_READ_XML_FILE);
|
|
}
|
|
ReadHandler read = worker.getRead();
|
|
// an EntryView is created per EntryType (ME)
|
|
for (EntryType type : EntryType.ALL_ME_ONES)
|
|
{
|
|
EntryView ev;
|
|
if (type.equals(EntryType.EXPORT_DATE))
|
|
{
|
|
ev = new EntryView(new Element(type, read.getExportDate()));
|
|
}
|
|
else if (type.equals(EntryType.REGION_CODE))
|
|
{
|
|
ev = new EntryView(new Element(type, read.getRegionCode()));
|
|
}
|
|
else if (type == EntryType.DATE_OF_BIRTH)
|
|
{
|
|
String value = read.getDateOfBirth();
|
|
if (value == null || value.equals("") || value.equals(Text.NOT_SET))
|
|
{ // Don't add an element when there is no data given
|
|
continue;
|
|
}
|
|
ev = new EntryView(new Element(type, read.getDateOfBirth()), read.getSplitDateOfBirth());
|
|
}
|
|
else
|
|
{
|
|
String value = read.getMeInfo(type);
|
|
if (value == null || value.equals("") || value.equals(Text.NOT_SET))
|
|
{ // Don't add an element when there is no data given
|
|
continue;
|
|
}
|
|
ev = new EntryView(new Element(type, value));
|
|
}
|
|
ev.maxWidthProperty()
|
|
.bind(Bindings.createDoubleBinding(
|
|
() -> datalist.getWidth() - datalist.getBorder().getInsets().getRight() * 2,
|
|
datalist.widthProperty()));
|
|
ev.minWidthProperty()
|
|
.bind(Bindings.createDoubleBinding(
|
|
() -> datalist.getWidth() - datalist.getBorder().getInsets().getRight() * 2,
|
|
datalist.widthProperty()));
|
|
|
|
datalist.getChildren().add(ev);
|
|
datalist.getChildren().add(getSeparator(datalist));
|
|
ev.addCheckListener(this);
|
|
}
|
|
|
|
// an EntryView is created per EntryType (not ME)
|
|
for (EntryType type : EntryType.ALL_SEPARATE_ONES)
|
|
{
|
|
int n = read.getTypeNumber(type);
|
|
if (n > 0)
|
|
{
|
|
EntryView ev;
|
|
if (type == EntryType.WORKOUT)
|
|
{
|
|
ev = new EntryView(new Element(type, n + ""), read.getSubWorkouts());
|
|
}
|
|
else if (type == EntryType.RECORD)
|
|
{
|
|
ev = new EntryView(new Element(type, n + ""), read.getSubRecords());
|
|
}
|
|
else
|
|
{
|
|
ev = new EntryView(new Element(type, n + ""));
|
|
}
|
|
ev.addCheckListener(this);
|
|
ev.maxWidthProperty()
|
|
.bind(Bindings.createDoubleBinding(
|
|
() -> datalist.getWidth() - datalist.getBorder().getInsets().getRight() * 2,
|
|
datalist.widthProperty()));
|
|
ev.minWidthProperty()
|
|
.bind(Bindings.createDoubleBinding(
|
|
() -> datalist.getWidth() - datalist.getBorder().getInsets().getRight() * 2,
|
|
datalist.widthProperty()));
|
|
|
|
datalist.getChildren().add(ev);
|
|
datalist.getChildren().add(getSeparator(datalist));
|
|
}
|
|
}
|
|
if (datalist.getChildren().size() > 0) // something inside, so there is a separator too much
|
|
{
|
|
datalist.getChildren().remove(datalist.getChildren().size() - 1);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Used to display in the overview when the initial health file couldn't be
|
|
* read. Consists of a BorderPane with a text in its center
|
|
*
|
|
* @param text Text to be displayed
|
|
* @return the created BorderPane
|
|
*/
|
|
private BorderPane getEmptyFileView(String text)
|
|
{
|
|
BorderPane p = new BorderPane();
|
|
p.setCenter(new Label(text));
|
|
return p;
|
|
}
|
|
|
|
/**
|
|
* In case there was an error reading the inital health file, the overview will
|
|
* only show an information text regarding the error
|
|
*
|
|
* @param text Text to be displayed
|
|
*/
|
|
public void setErrorReadingFile(String text)
|
|
{
|
|
datalist.getChildren().add(getEmptyFileView(text));
|
|
}
|
|
|
|
/**
|
|
* Saves the error which occurred when the temp files are created
|
|
*
|
|
* @param text Details on why it didn't work
|
|
*/
|
|
public void setErrorWritingTempFiles(String text)
|
|
{
|
|
filesInTempWithDesc = null;
|
|
errorWritingFiles = text;
|
|
}
|
|
|
|
/**
|
|
* Creates a horizontal separator line to be used in lists
|
|
*
|
|
* @param toBind The view it should be bound to (length wise)
|
|
* @return The created separator
|
|
*/
|
|
private BorderPane getSeparator(Pane toBind)
|
|
{
|
|
BorderPane p = new BorderPane();
|
|
Line line = new Line();
|
|
line.setStartX(0);
|
|
line.setStartY(0);
|
|
line.setEndY(0);
|
|
line.endXProperty().bind(Bindings.createDoubleBinding(
|
|
() -> toBind.getWidth() - toBind.getBorder().getInsets().getRight() * 2, toBind.widthProperty()));
|
|
line.setStroke(Colors.darkGrey);
|
|
p.setCenter(line);
|
|
return p;
|
|
}
|
|
|
|
/**
|
|
* Creates the last view showing the overview of all saved data and the help to
|
|
* upload the created zip file
|
|
**/
|
|
public VBox getResultView()
|
|
{
|
|
VBox container = new VBox();
|
|
container.setId("container");
|
|
|
|
Label done = new Label(Text.SUCCESS);
|
|
container.getChildren().add(done);
|
|
|
|
// buttons for easier access to nextcloud
|
|
HBox nextcloudHelp = new HBox();
|
|
nextcloudHelp.setId("nextcloudHelp");
|
|
nextcloudHelp.minWidthProperty()
|
|
.bind(Bindings.createDoubleBinding(() -> container.getWidth(), container.widthProperty()));
|
|
|
|
// open in browser
|
|
BorderPane goToNextcloud = new BorderPane();
|
|
goToNextcloud.setId("goToNextcloud");
|
|
Label nextcloudText = new Label(Text.NEXTCLOUD);
|
|
goToNextcloud.setCenter(nextcloudText);
|
|
goToNextcloud.setLeft(new ImageView(
|
|
new Image(this.getClass().
|
|
getResourceAsStream("internet.png"),64.0,64.0, true, true)));
|
|
goToNextcloud.setOnMouseClicked(new EventHandler<MouseEvent>()
|
|
{ // open in browser if possible
|
|
@Override
|
|
public void handle(MouseEvent arg0)
|
|
{
|
|
try
|
|
{
|
|
hostServices.showDocument(new URL(Text.NEXTCLOUD_ADDRESS).toExternalForm());
|
|
}
|
|
catch (MalformedURLException e)
|
|
{ // otherwise do nothing
|
|
|
|
}
|
|
}
|
|
});
|
|
nextcloudHelp.getChildren().add(goToNextcloud);
|
|
|
|
List<File> clipboardFiles = new ArrayList<>();
|
|
clipboardFiles.add(fileForSaving);
|
|
|
|
// copy filepath to clipboard
|
|
BorderPane copyToClipboard = new BorderPane();
|
|
copyToClipboard.setId("copyToClipboard");
|
|
Label clipBoardText = new Label(Text.COPY_FILE_PATH);
|
|
copyToClipboard.setCenter(clipBoardText);
|
|
copyToClipboard.setLeft(new ImageView(
|
|
new Image(this.getClass().
|
|
getResourceAsStream("filepath.png"),64.0,64.0, true, true)));
|
|
copyToClipboard.setOnMouseClicked(new EventHandler<MouseEvent>()
|
|
{
|
|
@Override
|
|
public void handle(MouseEvent arg0)
|
|
{
|
|
final Clipboard clipboard = Clipboard.getSystemClipboard();
|
|
final ClipboardContent content = new ClipboardContent();
|
|
content.putString(fileForSaving.getAbsolutePath());
|
|
clipboard.setContent(content);
|
|
|
|
Point2D p = clipBoardText.localToScreen(clipBoardText.getLayoutBounds().getCenterX(),
|
|
clipBoardText.getLayoutBounds().getCenterY());
|
|
Tooltip copied = new Tooltip(Text.FILE_PATH_IN_CLIPBOARD);
|
|
clipBoardText.setTooltip(copied);
|
|
copied.show(clipBoardText, p.getX(), p.getY());
|
|
copied.setHideDelay(Duration.seconds(5));
|
|
copied.autoHideProperty().set(true);
|
|
}
|
|
});
|
|
|
|
// drag file to browser
|
|
BorderPane dragToNextcloud = new BorderPane();
|
|
dragToNextcloud.setId("dragToServer");
|
|
dragToNextcloud.setCenter(new Label(Text.DRAG_FILE));
|
|
dragToNextcloud.setLeft(new ImageView(
|
|
new Image(this.getClass().
|
|
getResourceAsStream("archive.png"),64.0,64.0, true, true)));
|
|
dragToNextcloud.setOnMouseEntered(new EventHandler<MouseEvent>()
|
|
{
|
|
@Override
|
|
public void handle(MouseEvent event)
|
|
{
|
|
scene.setCursor(Cursor.OPEN_HAND);
|
|
}
|
|
});
|
|
dragToNextcloud.setOnMouseExited(new EventHandler<MouseEvent>()
|
|
{
|
|
@Override
|
|
public void handle(MouseEvent event)
|
|
{
|
|
scene.setCursor(Cursor.DEFAULT);
|
|
}
|
|
});
|
|
dragToNextcloud.setOnDragDetected(new EventHandler<MouseEvent>()
|
|
{
|
|
@Override
|
|
public void handle(MouseEvent event)
|
|
{
|
|
/* drag was detected, start a drag-and-drop gesture */
|
|
/* allow any transfer mode */
|
|
Dragboard db = dragToNextcloud.startDragAndDrop(TransferMode.ANY);
|
|
|
|
/* Put a string on a dragboard */
|
|
ClipboardContent content = new ClipboardContent();
|
|
content.put(DataFormat.FILES, clipboardFiles);
|
|
// content.putString(source.getText());
|
|
db.setContent(content);
|
|
|
|
event.consume();
|
|
}
|
|
});
|
|
|
|
HBox.setHgrow(copyToClipboard, Priority.ALWAYS);
|
|
HBox.setHgrow(dragToNextcloud, Priority.ALWAYS);
|
|
HBox.setHgrow(goToNextcloud, Priority.ALWAYS);
|
|
nextcloudHelp.getChildren().add(dragToNextcloud);
|
|
nextcloudHelp.getChildren().add(copyToClipboard);
|
|
container.getChildren().add(nextcloudHelp);
|
|
|
|
TextArea copyable = new TextArea(String.format(Text.F_RAW_UPLOAD_DATA, fileForSaving.getAbsolutePath(),Text.NEXTCLOUD_ADDRESS));
|
|
copyable.setEditable(false);
|
|
copyable.setWrapText(true);
|
|
copyable.setStyle("-fx-font-family :\"Arial\"");
|
|
copyable.setId("buttonProblems");
|
|
copyable.setFocusTraversable(false);
|
|
copyable.setPrefHeight(70);
|
|
container.getChildren().add(copyable);
|
|
|
|
// table to show all saved data
|
|
VBox overview = new VBox();
|
|
overview.minWidthProperty()
|
|
.bind(Bindings.createDoubleBinding(() -> container.getWidth(), container.widthProperty()));
|
|
container.getChildren().add(overview);
|
|
overview.setId("savedOverview");
|
|
overview.setBorder(Utils.darkBlueBorder);
|
|
|
|
// header
|
|
Label savedOverview = new Label(Text.DATA_OVERVIEW);
|
|
savedOverview.minWidthProperty()
|
|
.bind(Bindings.createDoubleBinding(() -> overview.getWidth(), overview.widthProperty()));
|
|
overview.getChildren().add(savedOverview);
|
|
savedOverview.setStyle("-fx-font-weight: bold");
|
|
|
|
// add job
|
|
if (!occupation.getLevelOne().equals(Text.NOT_SET))
|
|
{
|
|
|
|
Label x = new Label(String.format(Text.F_SAVED_DATA_VALUE_SUBCATEGORY,
|
|
EntryType.JOB.getValue(), Text.OCCUPATION_LEVEL_ONE, occupation.getLevelOne()));
|
|
x.minWidthProperty()
|
|
.bind(Bindings.createDoubleBinding(() -> overview.getWidth(), overview.widthProperty()));
|
|
overview.getChildren().add(x);
|
|
overview.getChildren().add(getSeparator(overview));
|
|
|
|
if (!occupation.getLevelTwo().equals(Text.NOT_SET))
|
|
{
|
|
Label x2 = new Label(String.format(Text.F_SAVED_DATA_VALUE_SUBCATEGORY,
|
|
EntryType.JOB.getValue(), Text.OCCUPATION_LEVEL_TWO, occupation.getLevelTwo()));
|
|
x2.minWidthProperty()
|
|
.bind(Bindings.createDoubleBinding(() -> overview.getWidth(), overview.widthProperty()));
|
|
overview.getChildren().add(x2);
|
|
overview.getChildren().add(getSeparator(overview));
|
|
|
|
if (!occupation.getLevelThree().equals(Text.NOT_SET))
|
|
{
|
|
Label x3 = new Label(String.format(Text.F_SAVED_DATA_VALUE_SUBCATEGORY,
|
|
EntryType.JOB.getValue(), Text.OCCUPATION_LEVEL_THREE, occupation.getLevelThree()));
|
|
x3.minWidthProperty()
|
|
.bind(Bindings.createDoubleBinding(() -> overview.getWidth(), overview.widthProperty()));
|
|
overview.getChildren().add(x3);
|
|
overview.getChildren().add(getSeparator(overview));
|
|
|
|
if (!occupation.getLevelFour().equals(Text.NOT_SET))
|
|
{
|
|
Label x4 = new Label(String.format(Text.F_SAVED_DATA_VALUE_SUBCATEGORY,
|
|
EntryType.JOB.getValue(), Text.OCCUPATION_LEVEL_FOUR, occupation.getLevelFour()));
|
|
x4.minWidthProperty()
|
|
.bind(Bindings.createDoubleBinding(() -> overview.getWidth(), overview.widthProperty()));
|
|
overview.getChildren().add(x4);
|
|
overview.getChildren().add(getSeparator(overview));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// add all selected Data
|
|
for (Node n : datalist.getChildren())
|
|
{
|
|
if (n instanceof EntryView) // this should always be true
|
|
{
|
|
EntryView i = (EntryView) n;
|
|
EntryType type = i.getEntryType();
|
|
if (i.getSelected())
|
|
{
|
|
if (type.equals(EntryType.WORKOUT) || type.equals(EntryType.RECORD)
|
|
|| type.equals(EntryType.DATE_OF_BIRTH))
|
|
{ // selected ones with subelements
|
|
for (SubEntryView s : i.getSelectedSubElements())
|
|
{
|
|
Label x = new Label(String.format(Text.F_SAVED_DATA_VALUE_SUBCATEGORY_ENTRIES,
|
|
type.getValue(), Utils.shortenHKStrings(s.getName()), s.getValue()));
|
|
if (type.equals(EntryType.DATE_OF_BIRTH))
|
|
{
|
|
x = new Label(String.format(Text.F_SAVED_DATA_VALUE_SUBCATEGORY, type.getValue(),
|
|
s.getName(), s.getValue()));
|
|
}
|
|
x.minWidthProperty().bind(
|
|
Bindings.createDoubleBinding(() -> overview.getWidth(), overview.widthProperty()));
|
|
overview.getChildren().add(x);
|
|
overview.getChildren().add(getSeparator(overview));
|
|
}
|
|
}
|
|
else
|
|
{ // selected ones without subelements
|
|
String value = i.getValue();
|
|
Label x = new Label(String.format(Text.F_SAVED_DATA_VALUE, type.getValue(), value));
|
|
if (type.equals(EntryType.ACTIVITY_SUMMARY))
|
|
{
|
|
x = new Label(String.format(Text.F_SAVED_DATA_ENTRIES, type.getValue(), value));
|
|
}
|
|
x.minWidthProperty().bind(
|
|
Bindings.createDoubleBinding(() -> overview.getWidth(), overview.widthProperty()));
|
|
overview.getChildren().add(x);
|
|
overview.getChildren().add(getSeparator(overview));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return container;
|
|
}
|
|
|
|
/**
|
|
* creates the view to show the privacy policy
|
|
*
|
|
* @return
|
|
*/
|
|
public VBox getPrivacyView()
|
|
{
|
|
VBox container = new VBox();
|
|
container.setId("container");
|
|
|
|
container.getChildren().add(getHeaderLabel(PrivacyStatementText.heading,22));
|
|
container.getChildren().add(getContentLabel(PrivacyStatementText.responsibleParty, container));
|
|
container.getChildren().add(getContentLabel(PrivacyStatementText.introText, container));
|
|
container.getChildren().add(getHeaderLabel(PrivacyStatementText.headingSec1, 16));
|
|
container.getChildren().add(getContentLabel(PrivacyStatementText.contentSec1, container));
|
|
container.getChildren().add(getHeaderLabel(PrivacyStatementText.headingSec2, 16));
|
|
container.getChildren().add(getContentLabel(PrivacyStatementText.contentSec2, container));
|
|
container.getChildren().add(getHeaderLabel(PrivacyStatementText.headingSec3, 16));
|
|
container.getChildren().add(getContentLabel(PrivacyStatementText.contentSec3, container));
|
|
container.getChildren().add(getHeaderLabel(PrivacyStatementText.headingSec4, 16));
|
|
container.getChildren().add(getContentLabel(PrivacyStatementText.contentSec4, container));
|
|
container.getChildren().add(getHeaderLabel(PrivacyStatementText.headingSec5, 16));
|
|
container.getChildren().add(getContentLabel(PrivacyStatementText.contentSec5, container));
|
|
|
|
return container;
|
|
}
|
|
|
|
private Label getHeaderLabel(String text, int size)
|
|
{
|
|
Label res = new Label(text);
|
|
res.setStyle("-fx-font-weight: bold; -fx-font-size: "+size+"px;");
|
|
return res;
|
|
}
|
|
|
|
/**
|
|
* Creates a label for the Privacy view which is used for normal text content. Fills the whole width of its parent
|
|
* @param text Text to be displayed
|
|
* @param container Parent to set the width
|
|
* @return created label
|
|
*/
|
|
private Label getContentLabel(String text, Pane container)
|
|
{
|
|
Label res = new Label(text);
|
|
res.minWidthProperty()
|
|
.bind(Bindings.createDoubleBinding(() -> container.getWidth(), container.widthProperty()));
|
|
|
|
return res;
|
|
}
|
|
|
|
/**
|
|
* Creates the files in the temp directory
|
|
*
|
|
* @throws WrappedException
|
|
*/
|
|
public void createTempFiles() throws WrappedException
|
|
{
|
|
filesInTempWithDesc = worker.writeSelectedDataToFiles(new WriteSelection(datalist), occupation);
|
|
}
|
|
|
|
@Override
|
|
public void changed(ObservableValue<? extends Boolean> checkbox, Boolean oldValue, Boolean newValue)
|
|
{
|
|
if (newValue)
|
|
{
|
|
selectCount++;
|
|
}
|
|
else
|
|
{
|
|
selectCount--;
|
|
}
|
|
if (selectCount > 0 && dirForSaving != null)
|
|
{
|
|
updateNav(NavState.DATA_AND_PATH_SELECTED);
|
|
}
|
|
else
|
|
{
|
|
updateNav(NavState.SELECT_DATA);
|
|
}
|
|
|
|
}
|
|
|
|
}
|