Java tutorial
/* * Autopsy Forensic Browser * * Copyright 2013 Basis Technology Corp. * Contact: carrier <at> sleuthkit <dot> org * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.sleuthkit.autopsy.imageanalyzer.gui; import java.io.IOException; import java.net.URL; import java.util.Arrays; import java.util.Collection; import java.util.ResourceBundle; import java.util.logging.Level; import java.util.stream.Collectors; import javafx.application.Platform; import javafx.beans.property.SimpleObjectProperty; import javafx.beans.property.SimpleStringProperty; import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; import javafx.collections.ObservableList; import javafx.fxml.FXML; import javafx.fxml.FXMLLoader; import javafx.scene.control.Label; import javafx.scene.control.TableCell; import javafx.scene.control.TableColumn; import javafx.scene.control.TableView; import javafx.scene.image.Image; import javafx.scene.image.ImageView; import javafx.scene.layout.AnchorPane; import javafx.scene.layout.BorderPane; import javafx.scene.layout.Region; import static javafx.scene.layout.Region.USE_COMPUTED_SIZE; import javafx.scene.text.Text; import javafx.util.Pair; import org.apache.commons.lang3.StringUtils; import org.openide.util.Exceptions; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.imageanalyzer.ImageAnalyzerController; import org.sleuthkit.autopsy.imageanalyzer.TagUtils; import org.sleuthkit.autopsy.imageanalyzer.datamodel.Category; import org.sleuthkit.autopsy.imageanalyzer.datamodel.DrawableAttribute; import org.sleuthkit.autopsy.imageanalyzer.datamodel.DrawableFile; import org.sleuthkit.datamodel.TagName; import org.sleuthkit.datamodel.TskCoreException; /** * */ public class MetaDataPane extends AnchorPane implements Category.CategoryListener, TagUtils.TagListener, DrawableView { private static final Logger LOGGER = Logger.getLogger(MetaDataPane.class.getName()); private final ImageAnalyzerController controller; private Long fileID; @FXML private ImageView imageView; @FXML private ResourceBundle resources; @FXML private URL location; @FXML private TableColumn<Pair<DrawableAttribute<?>, ? extends Object>, DrawableAttribute<?>> attributeColumn; @FXML private TableView<Pair<DrawableAttribute<?>, ? extends Object>> tableView; @FXML private TableColumn<Pair<DrawableAttribute<?>, ? extends Object>, String> valueColumn; @FXML private BorderPane imageBorder; private DrawableFile<?> file; @Override public Long getFileID() { return fileID; } @FXML void initialize() { assert attributeColumn != null : "fx:id=\"attributeColumn\" was not injected: check your FXML file 'MetaDataPane.fxml'."; assert imageView != null : "fx:id=\"imageView\" was not injected: check your FXML file 'MetaDataPane.fxml'."; assert tableView != null : "fx:id=\"tableView\" was not injected: check your FXML file 'MetaDataPane.fxml'."; assert valueColumn != null : "fx:id=\"valueColumn\" was not injected: check your FXML file 'MetaDataPane.fxml'."; TagUtils.registerListener(this); Category.registerListener(this); tableView.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY); tableView.setPlaceholder(new Label("Select a file to show its details here.")); attributeColumn.setCellValueFactory((param) -> new SimpleObjectProperty<>(param.getValue().getKey())); attributeColumn.setCellFactory( (param) -> new TableCell<Pair<DrawableAttribute<?>, ? extends Object>, DrawableAttribute<?>>() { @Override protected void updateItem(DrawableAttribute<?> item, boolean empty) { super.updateItem(item, empty); //To change body of generated methods, choose Tools | Templates. if (item != null) { setText(item.getDisplayName()); setGraphic(new ImageView(item.getIcon())); } else { setGraphic(null); setText(null); } } }); attributeColumn.setPrefWidth(USE_COMPUTED_SIZE); valueColumn.setCellValueFactory((p) -> { if (p.getValue().getKey() == DrawableAttribute.TAGS) { return new SimpleStringProperty( ((Collection<TagName>) p.getValue().getValue()).stream().map(TagName::getDisplayName) .filter((String t) -> t.startsWith(Category.CATEGORY_PREFIX) == false) .collect(Collectors.joining(" ; ", "", ""))); } else { return new SimpleStringProperty(StringUtils.join((Collection<?>) p.getValue().getValue(), " ; ")); } }); valueColumn.setPrefWidth(USE_COMPUTED_SIZE); valueColumn.setCellFactory((p) -> new TableCell<Pair<DrawableAttribute<?>, ? extends Object>, String>() { @Override public void updateItem(String item, boolean empty) { super.updateItem(item, empty); if (!isEmpty()) { Text text = new Text(item); text.wrappingWidthProperty().bind(getTableColumn().widthProperty()); setGraphic(text); } else { setGraphic(null); } } }); tableView.getColumns().setAll(Arrays.asList(attributeColumn, valueColumn)); //listen for selection change controller.getSelectionModel().lastSelectedProperty().addListener((observable, oldFileID, newFileID) -> { setFile(newFileID); }); // MetaDataPane.this.visibleProperty().bind(controller.getMetaDataCollapsed().not()); // MetaDataPane.this.managedProperty().bind(controller.getMetaDataCollapsed().not()); } @Override public DrawableFile<?> getFile() { if (fileID != null) { if (file == null || file.getId() != fileID) { try { file = controller.getFileFromId(fileID); } catch (TskCoreException ex) { LOGGER.log(Level.WARNING, "failed to get DrawableFile for obj_id" + fileID, ex); return null; } } } else { return null; } return file; } @Override public void setFile(Long fileID) { this.fileID = fileID; if (fileID == null) { Platform.runLater(() -> { imageView.setImage(null); tableView.getItems().clear(); getBorderable().setBorder(null); }); } else { try { file = controller.getFileFromId(fileID); updateUI(); file.categoryProperty().addListener(new ChangeListener<Category>() { @Override public void changed(ObservableValue<? extends Category> ov, Category t, final Category t1) { updateUI(); } }); } catch (TskCoreException ex) { Exceptions.printStackTrace(ex); } } } public MetaDataPane(ImageAnalyzerController controller) { this.controller = controller; FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("MetaDataPane.fxml")); fxmlLoader.setRoot(this); fxmlLoader.setController(this); try { fxmlLoader.load(); } catch (IOException exception) { throw new RuntimeException(exception); } } public void updateUI() { final Image icon = getFile().getThumbnail(); final ObservableList<Pair<DrawableAttribute<?>, ? extends Object>> attributesList = getFile() .getAttributesList(); Platform.runLater(() -> { imageView.setImage(icon); tableView.getItems().setAll(attributesList); }); updateCategoryBorder(); } @Override public Region getBorderable() { return imageBorder; } @Override public void handleCategoryChanged(Collection<Long> ids) { if (getFile() != null && ids.contains(getFileID())) { updateUI(); } } @Override public void handleTagsChanged(Collection<Long> ids) { if (getFile() != null && ids.contains(getFileID())) { updateUI(); } } }