com.bdaum.zoom.gps.internal.dialogs.TrackpointDialog.java Source code

Java tutorial

Introduction

Here is the source code for com.bdaum.zoom.gps.internal.dialogs.TrackpointDialog.java

Source

/*
 * This file is part of the ZoRa project: http://www.photozora.org.
 *
 * ZoRa is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * ZoRa is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with ZoRa; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * (c) 2009 Berthold Daum  
 */
package com.bdaum.zoom.gps.internal.dialogs;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.ColumnLabelProvider;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;

import com.bdaum.zoom.core.Constants;
import com.bdaum.zoom.gps.internal.GpsActivator;
import com.bdaum.zoom.gps.internal.HelpContextIds;
import com.bdaum.zoom.gps.widgets.IMapComponent;
import com.bdaum.zoom.ui.dialogs.ZTitleAreaDialog;
import com.bdaum.zoom.ui.gps.Trackpoint;
import com.bdaum.zoom.ui.widgets.DateInput;

public class TrackpointDialog extends ZTitleAreaDialog {

    public class EditDialog extends ZTitleAreaDialog implements Listener {

        private final SubTrack track;
        private final boolean split;
        private final String message;
        private DateInput startField;
        private DateInput endField;
        private Date start;
        private Date end;
        private final String title;
        private final List<SubTrack> subtracks;

        public EditDialog(Shell shell, List<SubTrack> subtracks, SubTrack track, boolean split, String title,
                String message) {
            super(shell);
            this.subtracks = subtracks;
            this.track = track;
            this.split = split;
            this.title = title;
            this.message = message;
        }

        @Override
        public void create() {
            super.create();
            getShell().setText(Constants.APPLICATION_NAME);
            setTitle(title);
            setMessage(message);
            fillValues();
            validate();
            getShell().pack();
        }

        private void fillValues() {
            if (split) {
                long median = (track.getStart() + track.getEnd()) / 2;
                long dur = (track.getEnd() - track.getStart()) / 6;
                startField.setDate(new Date(median - dur));
                endField.setDate(new Date(median + dur));
            } else {
                startField.setDate(new Date(track.getStart()));
                endField.setDate(new Date(track.getEnd()));
            }
        }

        @Override
        protected Control createDialogArea(Composite parent) {
            Composite area = (Composite) super.createDialogArea(parent);
            Composite composite = new Composite(area, SWT.NONE);
            composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
            composite.setLayout(new GridLayout(2, false));
            new Label(composite, SWT.NONE).setText(Messages.TrackpointDialog_start);
            startField = new DateInput(composite, SWT.DATE | SWT.TIME | SWT.MEDIUM);
            startField.addListener(this);
            new Label(composite, SWT.NONE).setText(Messages.TrackpointDialog_end);
            endField = new DateInput(composite, SWT.DATE | SWT.TIME | SWT.MEDIUM);
            endField.addListener(this);
            return area;
        }

        private void validate() {
            String errorMessage = null;
            long s = startField.getDate().getTime();
            long e = endField.getDate().getTime();
            if (s >= e)
                errorMessage = Messages.TrackpointDialog_end_after_start;
            else if (split) {
                if (s <= track.getStart())
                    errorMessage = NLS.bind(split ? Messages.TrackpointDialog_wrong_gap_start_value
                            : Messages.TrackpointDialog_start_after_x, formatDate(track.getStart()));
                else if (e >= track.getEnd())
                    errorMessage = NLS.bind(split ? Messages.TrackpointDialog_wrong_gap_end_value
                            : Messages.TrackpointDialog_end_before_x, formatDate(track.getEnd()));
            } else {
                for (SubTrack t : subtracks)
                    if (s >= t.getStart() && s < t.getEnd() || e >= t.getStart() && e < t.getEnd()) {
                        errorMessage = NLS.bind(Messages.TrackpointDialog_subtrack_overlaps, formatTrack(t));
                        break;
                    }
            }
            setErrorMessage(errorMessage);
            getButton(OK).setEnabled(errorMessage == null);
        }

        public long getStart() {
            return start.getTime();
        }

        public long getEnd() {
            return end.getTime();
        }

        public void handleEvent(Event e) {
            validate();
        }

        @Override
        protected void okPressed() {
            start = startField.getDate();
            end = endField.getDate();
            super.okPressed();
        }

    }

    public class SubTrack {
        private long start, end;

        public SubTrack(long time) {
            start = time;
        }

        /**
         * @return start
         */
        public long getStart() {
            return start;
        }

        /**
         * @param start
         *            das zu setzende Objekt start
         */
        public void setStart(long start) {
            this.start = start;
        }

        /**
         * @return end
         */
        public long getEnd() {
            return end;
        }

        /**
         * @param end
         *            das zu setzende Objekt end
         */
        public void setEnd(long end) {
            this.end = end;
        }
    }

    SimpleDateFormat sd = new SimpleDateFormat(Messages.TrackpointDialog_tracktimeformat);
    private final List<SubTrack> subtracks = new LinkedList<TrackpointDialog.SubTrack>();
    private TableViewer viewer;
    private Button editButton;
    private Button removeButton;
    private Button joinButton;
    private Button splitButton;
    private final Trackpoint[] trackpoints;
    private List<Trackpoint> result;
    private IMapComponent mapComponent;
    private final long tolerance;

    public TrackpointDialog(Shell shell, Trackpoint[] trackpoints, long tolerance) {
        super(shell, HelpContextIds.TRACKPOINTS);
        this.trackpoints = trackpoints;
        this.tolerance = tolerance;
        SubTrack subtrack = null;
        Trackpoint previous = null;
        for (Trackpoint trackpoint : trackpoints) {
            if (previous == null || subtrack == null)
                subtrack = new SubTrack(trackpoint.getTime() - tolerance);
            else if (previous.isSegmentEnd() || trackpoint.getTime() - previous.getTime() > 2 * tolerance) {
                subtrack.setEnd(previous.getTime() + tolerance);
                subtracks.add(subtrack);
                subtrack = new SubTrack(trackpoint.getTime() - tolerance);
            }
            previous = trackpoint;
        }
        if (subtrack != null && previous != null) {
            subtrack.setEnd(previous.getTime() + tolerance);
            subtracks.add(subtrack);
        }
    }

    @Override
    public void create() {
        super.create();
        getShell().setText(Constants.APPLICATION_NAME);
        setTitle(Messages.TrackpointDialog_edit_trackpoints);
        setMessage(NLS.bind(Messages.TrackpointDialog_initial_message, formatTime(tolerance)));
        updateButtons();
    }

    @Override
    protected Control createDialogArea(Composite parent) {
        Composite area = (Composite) super.createDialogArea(parent);
        Composite comp = new Composite(area, SWT.NONE);
        comp.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
        comp.setLayout(new GridLayout(3, false));
        createViewer(comp);
        createButtons(comp);
        createMapArea(comp);
        return area;
    }

    private void createMapArea(Composite comp) {
        mapComponent = GpsActivator.getMapComponent(GpsActivator.findCurrentMappingSystem());
        if (mapComponent != null) {
            mapComponent.createComponent(comp, false);
            GridData layoutData = new GridData(GridData.FILL_BOTH);
            layoutData.widthHint = layoutData.heightHint = 500;
            mapComponent.getControl().setLayoutData(layoutData);
            mapComponent.setInput(null, 12, null, null, null, IMapComponent.BLANK);
        }
    }

    private void createButtons(Composite comp) {
        Composite composite = new Composite(comp, SWT.NONE);
        composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
        composite.setLayout(new GridLayout(1, false));
        editButton = new Button(composite, SWT.PUSH);
        editButton.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
        editButton.setText(Messages.TrackpointDialog_edit);
        editButton.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                SubTrack track = (SubTrack) viewer.getStructuredSelection().getFirstElement();
                EditDialog dialog = new EditDialog(getShell(), subtracks, track, false,
                        Messages.TrackpointDialog_edit_subtrack,
                        NLS.bind(Messages.TrackpointDialog_modify_start_end, formatTrack(track)));
                if (dialog.open() == EditDialog.OK) {
                    track.setStart(dialog.getStart());
                    track.setEnd(dialog.getEnd());
                    viewer.update(track, null);
                }
            }
        });
        removeButton = new Button(composite, SWT.PUSH);
        removeButton.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
        removeButton.setText(Messages.TrackpointDialog_remove);
        removeButton.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                Iterator<?> it = viewer.getStructuredSelection().iterator();
                while (it.hasNext()) {
                    Object next = it.next();
                    subtracks.remove(next);
                    viewer.remove(next);
                }
            }
        });
        joinButton = new Button(composite, SWT.PUSH);
        joinButton.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
        joinButton.setText(Messages.TrackpointDialog_join);
        joinButton.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                SubTrack first = null;
                Iterator<?> it = viewer.getStructuredSelection().iterator();
                while (it.hasNext()) {
                    SubTrack t = (SubTrack) it.next();
                    if (first == null)
                        first = t;
                    else {
                        first.setEnd(t.getEnd());
                        subtracks.remove(t);
                        viewer.remove(t);
                    }
                }
                if (first != null)
                    viewer.update(first, null);
            }
        });
        splitButton = new Button(composite, SWT.PUSH);
        splitButton.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
        splitButton.setText(Messages.TrackpointDialog_split);
        splitButton.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                SubTrack track = (SubTrack) viewer.getStructuredSelection().getFirstElement();
                EditDialog dialog = new EditDialog(getShell(), subtracks, track, true,
                        Messages.TrackpointDialog_spli_subtrack,
                        NLS.bind(Messages.TrackpointDialog_split_subtrack_msg, formatTrack(track)));
                if (dialog.open() == EditDialog.OK) {
                    int index = subtracks.indexOf(track);
                    SubTrack newTrack = new SubTrack(dialog.getEnd());
                    newTrack.setEnd(track.getEnd());
                    track.setEnd(dialog.getStart());
                    subtracks.add(index + 1, newTrack);
                    viewer.setInput(subtracks);
                    viewer.setSelection(new StructuredSelection(new Object[] { track, newTrack }));
                }
            }
        });
    }

    public void createViewer(Composite comp) {
        viewer = new TableViewer(comp, SWT.V_SCROLL | SWT.FULL_SELECTION | SWT.BORDER | SWT.MULTI);
        GridData layoutData = new GridData(SWT.FILL, SWT.FILL, true, true);
        layoutData.widthHint = 410;
        layoutData.heightHint = 500;
        viewer.getControl().setLayoutData(layoutData);
        viewer.getTable().setLinesVisible(true);
        viewer.getTable().setHeaderVisible(true);
        viewer.setContentProvider(ArrayContentProvider.getInstance());
        TableViewerColumn col1 = new TableViewerColumn(viewer, SWT.NONE);
        col1.getColumn().setWidth(170);
        col1.getColumn().setText(Messages.TrackpointDialog_start);
        col1.setLabelProvider(new ColumnLabelProvider() {
            @Override
            public String getText(Object element) {
                if (element instanceof SubTrack)
                    return formatDate(((SubTrack) element).getStart());
                return super.getText(element);
            }
        });
        TableViewerColumn col2 = new TableViewerColumn(viewer, SWT.NONE);
        col2.getColumn().setWidth(170);
        col2.getColumn().setText(Messages.TrackpointDialog_end);
        col2.setLabelProvider(new ColumnLabelProvider() {
            @Override
            public String getText(Object element) {
                if (element instanceof SubTrack)
                    return formatDate(((SubTrack) element).getEnd());
                return super.getText(element);
            }
        });
        TableViewerColumn col3 = new TableViewerColumn(viewer, SWT.NONE);
        col3.getColumn().setWidth(70);
        col3.getColumn().setAlignment(SWT.RIGHT);
        col3.getColumn().setText(Messages.TrackpointDialog_duration);
        col3.setLabelProvider(new ColumnLabelProvider() {
            @Override
            public String getText(Object element) {
                if (element instanceof SubTrack) {
                    SubTrack subTrack = (SubTrack) element;
                    return formatTime((subTrack.getEnd() - subTrack.getStart() + 30000L) / 60000L);
                }
                return super.getText(element);
            }
        });
        viewer.addSelectionChangedListener(new ISelectionChangedListener() {
            public void selectionChanged(SelectionChangedEvent event) {
                updateButtons();
                updateMap();
            }
        });
        viewer.setInput(subtracks);
    }

    protected void updateMap() {
        IStructuredSelection selection = viewer.getStructuredSelection();
        double minLat = Double.MAX_VALUE, maxLat = Double.MIN_VALUE, minLng = Double.MAX_VALUE,
                maxLng = Double.MIN_VALUE;
        Object[] tracks = selection.toArray();
        LinkedList<Trackpoint> pnts = new LinkedList<Trackpoint>();
        int start = 0;
        for (Trackpoint trackpoint : trackpoints) {
            long time = trackpoint.getTime();
            for (int i = start; i < tracks.length; i++)
                if (time >= ((SubTrack) tracks[i]).getStart()) {
                    start = i;
                    if (time <= ((SubTrack) tracks[i]).getEnd()) {
                        pnts.add(trackpoint);
                        double latitude = trackpoint.getLatitude();
                        double longitude = trackpoint.getLongitude();
                        if (latitude > maxLat)
                            maxLat = latitude;
                        if (latitude < minLat)
                            minLat = latitude;
                        if (longitude > maxLng)
                            maxLng = longitude;
                        if (longitude < minLng)
                            minLng = longitude;
                        break;
                    }
                }
        }
        double latDist = Math.abs(maxLat - minLat) / 100;
        double lngDist = Math.abs(maxLng - minLng) / 100;
        boolean done = false;
        while (!done) {
            done = true;
            Trackpoint previous = null;
            Iterator<Trackpoint> it = pnts.iterator();
            while (it.hasNext()) {
                Trackpoint pnt = it.next();
                if (previous != null && Math.abs(previous.getLatitude() - pnt.getLatitude()) < latDist
                        && Math.abs(previous.getLongitude() - pnt.getLongitude()) < lngDist) {
                    it.remove();
                    done = false;
                    continue;
                }
                previous = pnt;
            }
        }
        mapComponent.setInput(null, 12, null, null, pnts.toArray(new Trackpoint[pnts.size()]), IMapComponent.TRACK);
    }

    protected void updateButtons() {
        IStructuredSelection selection = viewer.getStructuredSelection();
        int size = selection.size();
        boolean single = size == 1;
        boolean any = size > 0;
        editButton.setEnabled(single);
        removeButton.setEnabled(any);
        int previous = -1;
        boolean join = false;
        if (size > 1) {
            join = true;
            Iterator<?> it = selection.iterator();
            while (it.hasNext()) {
                int index = subtracks.indexOf(it.next());
                if (previous >= 0) {
                    if (index - previous > 1) {
                        join = false;
                        break;
                    }
                }
                previous = index;
            }
        }
        joinButton.setEnabled(join);
        splitButton.setEnabled(single);
    }

    private String formatDate(long time) {
        return sd.format(new Date(time));
    }

    private static String formatTime(long minutes) {
        long hours = minutes / 60;
        minutes -= hours * 60;
        StringBuilder sb = new StringBuilder();
        sb.append(hours).append('h');
        if (minutes < 10)
            sb.append('0');
        sb.append(minutes).append('m');
        return sb.toString();
    }

    private String formatTrack(SubTrack track) {
        return NLS.bind("{0} - {1}", formatDate(track.getStart()), //$NON-NLS-1$
                formatDate(track.getEnd()));
    }

    @Override
    protected void okPressed() {
        SubTrack[] tracks = subtracks.toArray(new SubTrack[subtracks.size()]);
        int start = 0;
        result = new ArrayList<Trackpoint>(trackpoints.length);
        for (Trackpoint trackpoint : trackpoints) {
            long time = trackpoint.getTime();
            for (int i = start; i < tracks.length; i++)
                if (time >= tracks[i].getStart()) {
                    start = i;
                    if (time <= tracks[i].getEnd()) {
                        trackpoint.setMinTime(tracks[i].getStart());
                        trackpoint.setMaxTime(tracks[i].getEnd());
                        result.add(trackpoint);
                        break;
                    }
                }
        }
        super.okPressed();
    }

    public Trackpoint[] getResult() {
        return result.toArray(new Trackpoint[result.size()]);
    }

}