se.trixon.toolbox.geotagger.GeotaggerTopComponent.java Source code

Java tutorial

Introduction

Here is the source code for se.trixon.toolbox.geotagger.GeotaggerTopComponent.java

Source

/* 
 * Copyright 2015 Patrik Karlsson.
 *
 * 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 se.trixon.toolbox.geotagger;

import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetDropEvent;
import java.io.File;
import java.io.IOException;
import java.nio.charset.MalformedInputException;
import java.util.List;
import javax.swing.filechooser.FileNameExtensionFilter;
import javax.swing.table.TableColumnModel;
import javax.swing.table.TableRowSorter;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.netbeans.api.settings.ConvertAsProperties;
import org.openide.util.Exceptions;
import org.openide.util.HelpCtx;
import org.openide.util.NbBundle;
import org.openide.windows.*;
import se.trixon.almond.dialogs.Message;
import se.trixon.almond.dialogs.SimpleDialog;
import se.trixon.almond.dictionary.Dict;
import se.trixon.almond.icon.Pict;
import se.trixon.almond.swing.NumericTableCellRenderer;
import se.trixon.toolbox.core.base.ToolTopComponent;
import se.trixon.toolbox.io.file.pxy.Pxy;

/**
 * Top component which displays something.
 */
@ConvertAsProperties(dtd = "-//se.trixon.toolbox.geotagger//Geotagger//EN", autostore = false)
@TopComponent.Description(preferredID = "GeotaggerTopComponent",
        //iconBase="SET/PATH/TO/ICON/HERE", 
        persistenceType = TopComponent.PERSISTENCE_ALWAYS)
@TopComponent.Registration(mode = "editor", openAtStartup = false)
public final class GeotaggerTopComponent extends ToolTopComponent implements OperationListener {

    private static final int ICON_SIZE = TOOLBAR_ICON_SIZE;
    private final GeotaggerController mController;
    private File mSource;
    private GeotagTableModel mTableModel;
    private final Options mOptions = Options.INSTANCE;
    private TableRowSorter<GeotagTableModel> mTableRowSorter;

    public GeotaggerTopComponent() {
        mBundle = NbBundle.getBundle(GeotaggerController.class);
        mToolName = mBundle.getString("Tool-Name");
        initComponents();
        setName(mToolName);
        mController = new GeotaggerController(this);
        init();

        File file = new File(FileUtils.getUserDirectory(), "GeotaggerDemo.csv");
        if (file.exists()) {
            openFile(file);
        }
    }

    @Override
    public HelpCtx getHelpCtx() {
        return new HelpCtx("se.trixon.toolbox.geotagger.about");
    }

    @Override
    public void onOperationFailed(String message) {
        logAppend(message);
    }

    @Override
    public void onOperationFinished(String message) {
        logAppend(message);
        makeBusy(false);

        boolean state = true;
        openButton.setEnabled(state);
        editToggleButton.setEnabled(state);
        saveLogButton.setEnabled(state);
        closeButton.setEnabled(state);
        startButton.setEnabled(state);

        new Thread(() -> {
            Message.information(Dict.OPERATION_COMPLETED.getString(), message);
        }).start();
    }

    @Override
    public void onOperationInterrupted() {
    }

    @Override
    public void onOperationLog(String message) {
        logAppend(message);
    }

    @Override
    public void onOperationProcessingStarted() {
    }

    @Override
    public void onOperationStarted() {
        makeBusy(true);

        boolean state = false;
        openButton.setEnabled(state);
        editToggleButton.setEnabled(state);
        saveLogButton.setEnabled(state);
        closeButton.setEnabled(state);
        startButton.setEnabled(state);
    }

    private void init() {
        openButton.setIcon(Pict.Actions.DOCUMENT_OPEN.get(TOOLBAR_ICON_SIZE));
        editToggleButton.setIcon(Pict.Actions.DOCUMENT_EDIT.get(TOOLBAR_ICON_SIZE));

        closeButton.setIcon(Pict.Actions.WINDOW_CLOSE.get(TOOLBAR_ICON_SIZE));
        closeButton.setEnabled(false);

        startButton.setIcon(Pict.Actions.ARROW_RIGHT.get(ICON_SIZE));
        startButton.setToolTipText(Dict.START.getString());
        startButton.setEnabled(false);

        saveLogButton.setIcon(Pict.Actions.DOCUMENT_SAVE.get(ICON_SIZE));
        saveLogButton.setEnabled(false);

        helpButton.setIcon(Pict.Actions.HELP_CONTENTS.get(ICON_SIZE));
        helpButton.setToolTipText(Dict.HELP.getString());

        DropTarget dropTarget = new DropTarget() {
            @Override
            public synchronized void drop(DropTargetDropEvent evt) {
                try {
                    evt.acceptDrop(DnDConstants.ACTION_COPY);
                    List<File> droppedFiles = (List<File>) evt.getTransferable()
                            .getTransferData(DataFlavor.javaFileListFlavor);
                    if (droppedFiles.get(0).isFile()) {
                        openFile(droppedFiles.get(0));
                    }
                } catch (UnsupportedFlavorException | IOException ex) {
                }
            }
        };

        scrollPane.setDropTarget(dropTarget);

        mTableModel = new GeotagTableModel();
        table.setModel(mTableModel);
        mTableRowSorter = new TableRowSorter<>(mTableModel);
        table.setRowSorter(mTableRowSorter);

        TableColumnModel columnModel = table.getColumnModel();

        NumericTableCellRenderer cooNumericTableCellRenderer = new NumericTableCellRenderer(Double.class, 6);
        NumericTableCellRenderer altNumericTableCellRenderer = new NumericTableCellRenderer(Double.class, 4);

        columnModel.getColumn(GeotagTableModel.COLUMN_LATITUDE).setCellRenderer(cooNumericTableCellRenderer);
        columnModel.getColumn(GeotagTableModel.COLUMN_LONGITUDE).setCellRenderer(cooNumericTableCellRenderer);
        columnModel.getColumn(GeotagTableModel.COLUMN_ALTITUDE).setCellRenderer(altNumericTableCellRenderer);

        columnModel.getColumn(GeotagTableModel.COLUMN_NAME).setPreferredWidth(200);
        columnModel.getColumn(GeotagTableModel.COLUMN_LATITUDE).setPreferredWidth(100);
        columnModel.getColumn(GeotagTableModel.COLUMN_LONGITUDE).setPreferredWidth(100);
        columnModel.getColumn(GeotagTableModel.COLUMN_ALTITUDE).setPreferredWidth(50);
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        toolBar = new javax.swing.JToolBar();
        openButton = new javax.swing.JButton();
        editToggleButton = new javax.swing.JToggleButton();
        saveLogButton = new javax.swing.JButton();
        closeButton = new javax.swing.JButton();
        startButton = new javax.swing.JButton();
        jSeparator1 = new javax.swing.JToolBar.Separator();
        helpButton = new javax.swing.JButton();
        scrollPane = new javax.swing.JScrollPane();
        table = new javax.swing.JTable();

        toolBar.setFloatable(false);
        toolBar.setRollover(true);

        openButton.setToolTipText(Dict.OPEN.getString());
        openButton.setFocusable(false);
        openButton.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        openButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        openButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                openButtonActionPerformed(evt);
            }
        });
        toolBar.add(openButton);

        editToggleButton.setToolTipText(Dict.EDIT.getString());
        editToggleButton.setEnabled(false);
        editToggleButton.setFocusable(false);
        editToggleButton.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        editToggleButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        editToggleButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                editToggleButtonActionPerformed(evt);
            }
        });
        toolBar.add(editToggleButton);

        saveLogButton.setToolTipText(org.openide.util.NbBundle.getMessage(GeotaggerTopComponent.class,
                "GeotaggerTopComponent.saveLogButton.toolTipText")); // NOI18N
        saveLogButton.setFocusable(false);
        saveLogButton.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        saveLogButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        saveLogButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                saveLogButtonActionPerformed(evt);
            }
        });
        toolBar.add(saveLogButton);

        closeButton.setToolTipText(Dict.CLOSE.getString());
        closeButton.setFocusable(false);
        closeButton.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        closeButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        closeButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                closeButtonActionPerformed(evt);
            }
        });
        toolBar.add(closeButton);

        startButton.setFocusable(false);
        startButton.setHorizontalAlignment(javax.swing.SwingConstants.LEADING);
        startButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                startButtonActionPerformed(evt);
            }
        });
        toolBar.add(startButton);
        toolBar.add(jSeparator1);

        helpButton.setFocusable(false);
        helpButton.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        helpButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        helpButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                helpButtonActionPerformed(evt);
            }
        });
        toolBar.add(helpButton);

        scrollPane.setViewportView(table);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addComponent(toolBar, javax.swing.GroupLayout.Alignment.TRAILING,
                        javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addComponent(scrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE));
        layout.setVerticalGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(layout.createSequentialGroup()
                        .addComponent(toolBar, javax.swing.GroupLayout.PREFERRED_SIZE,
                                javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addGap(0, 0, 0)
                        .addComponent(scrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 29, Short.MAX_VALUE)));
    }// </editor-fold>//GEN-END:initComponents

    private void openFile(File file) {
        mSource = file;
        startButton.setEnabled(false);
        closeButton.setEnabled(false);
        editToggleButton.setSelected(false);
        editToggleButton.setEnabled(false);

        mTableModel.clear();
        logClear();

        new Thread(() -> {
            try {
                //Try open the file as pxy, if no valid pxy point, try open it as csv.
                openFilePxy(file);
                if (mTableModel.getRowCount() == 0) {
                    openFileCsv(file);
                }

                if (mTableModel.getRowCount() > 0) {
                    startButton.setEnabled(true);
                    closeButton.setEnabled(true);
                    editToggleButton.setEnabled(true);
                } else {
                }
            } catch (IOException ex) {
                Exceptions.printStackTrace(ex);
            }
        }).start();
    }

    private void openFileCsv(File file) throws IOException {
        List<String> lines = FileUtils.readLines(file);

        lines.stream().forEach((line) -> {
            String[] elements = StringUtils.splitPreserveAllTokens(line, ";");
            if (elements.length < 3 || elements[0].isEmpty() || elements[1].isEmpty() || elements[2].isEmpty()) {
                logAppend(String.format(" - %s: %s", mBundle.getString("invalidGeotag"), line));
            } else {
                String name = elements[GeotagTableModel.COLUMN_NAME];
                double latitude = NumberUtils.toDouble(elements[GeotagTableModel.COLUMN_LATITUDE]);
                double longitude = NumberUtils.toDouble(elements[GeotagTableModel.COLUMN_LONGITUDE]);
                double altitude = 0;

                if (elements.length > GeotagTableModel.COLUMN_ALTITUDE) {
                    altitude = NumberUtils.toDouble(elements[GeotagTableModel.COLUMN_ALTITUDE]);
                }

                Geotag geotag = new Geotag(name, latitude, longitude, altitude);
                mTableModel.addRow(geotag);
            }
        });
    }

    private void openFilePxy(File file) throws IOException {
        Pxy pxy = new Pxy();

        try {
            pxy.read(file);
        } catch (MalformedInputException | NumberFormatException | StringIndexOutOfBoundsException e) {
            return;
        }

        pxy.getPoints().stream().forEach((point) -> {
            Geotag geotag = new Geotag(point.getPointId(), point.getX(), point.getY(), point.getZ());
            mTableModel.addRow(geotag);
        });
    }

    private void startButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_startButtonActionPerformed
        table.setEnabled(false);

        Operation operation = new Operation(this, mTableModel.getDataVector());
        operation.start();
    }//GEN-LAST:event_startButtonActionPerformed

    private void saveLogButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_saveLogButtonActionPerformed
    }//GEN-LAST:event_saveLogButtonActionPerformed

    private void helpButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_helpButtonActionPerformed
        displayHelp("se.trixon.toolbox.geotagger.about");
    }//GEN-LAST:event_helpButtonActionPerformed

    private void openButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_openButtonActionPerformed
        FileNameExtensionFilter filter = new FileNameExtensionFilter(
                Dict.COORDINATE_FILE.getString() + " (*.csv, *.pxy)", "csv", "pxy", "CSV", "PXY");

        SimpleDialog.clearFilters();
        SimpleDialog.addFilter(filter);
        SimpleDialog.setFilter(filter);
        SimpleDialog.setParent(this);

        if (mSource != null) {
            SimpleDialog.setPath(mSource.getParentFile());
        }

        if (SimpleDialog.openFile()) {
            openFile(SimpleDialog.getPath());
        }
    }//GEN-LAST:event_openButtonActionPerformed

    private void closeButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_closeButtonActionPerformed
        mTableModel.clear();
        closeButton.setEnabled(false);
        startButton.setEnabled(false);
        editToggleButton.setEnabled(false);
        editToggleButton.setSelected(false);
    }//GEN-LAST:event_closeButtonActionPerformed

    private void editToggleButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_editToggleButtonActionPerformed
        mTableModel.setEditable(editToggleButton.isSelected());
    }//GEN-LAST:event_editToggleButtonActionPerformed

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton closeButton;
    private javax.swing.JToggleButton editToggleButton;
    private javax.swing.JButton helpButton;
    private javax.swing.JToolBar.Separator jSeparator1;
    private javax.swing.JButton openButton;
    private javax.swing.JButton saveLogButton;
    private javax.swing.JScrollPane scrollPane;
    private javax.swing.JButton startButton;
    private javax.swing.JTable table;
    private javax.swing.JToolBar toolBar;

    // End of variables declaration//GEN-END:variables
    @Override
    public void componentOpened() {
    }

    @Override
    public void componentClosed() {
    }

    void writeProperties(java.util.Properties p) {
        p.setProperty("version", "1.0");
    }

    void readProperties(java.util.Properties p) {
        String version = p.getProperty("version");
    }
}