Repository for the HealthTool which enables Apple users to analyse their health data from the Apple health app and prepares the data for contributing it for future studies on wearable data.
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

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);
}
}
}