net.tourbook.tour.DialogExtractTour.java Source code

Java tutorial

Introduction

Here is the source code for net.tourbook.tour.DialogExtractTour.java

Source

/*******************************************************************************
 * Copyright (C) 2005, 2011  Wolfgang Schramm and Contributors
 *
 * This program 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 version 2 of the License.
 *
 * This program 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
 * this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
 *******************************************************************************/
package net.tourbook.tour;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

import net.tourbook.Messages;
import net.tourbook.application.TourbookPlugin;
import net.tourbook.data.TourData;
import net.tourbook.data.TourMarker;
import net.tourbook.data.TourPerson;
import net.tourbook.data.TourTag;
import net.tourbook.data.TourType;
import net.tourbook.data.TourWayPoint;
import net.tourbook.database.PersonManager;
import net.tourbook.database.TourDatabase;
import net.tourbook.preferences.ITourbookPreferences;
import net.tourbook.tag.TagMenuManager;
import net.tourbook.ui.ITourProvider2;
import net.tourbook.ui.UI;
import net.tourbook.ui.action.ActionOpenPrefDialog;
import net.tourbook.ui.action.ActionSetTourTypeMenu;
import net.tourbook.ui.views.tourDataEditor.TourDataEditorView;
import net.tourbook.util.StatusUtil;
import net.tourbook.util.Util;

import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.dialogs.TitleAreaDialog;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.layout.GridLayoutFactory;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CLabel;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.MenuEvent;
import org.eclipse.swt.events.MenuListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
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.Link;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.joda.time.DateTime;

/**
 * Split tour at a time slice position and save extracted time slices as a new tour
 */
public class DialogExtractTour extends TitleAreaDialog implements ITourProvider2 {

    private static final String STATE_TOUR_TITLE = "TourTitle"; //$NON-NLS-1$
    private static final String STATE_PERSON_ID = "PersonId"; //$NON-NLS-1$
    private static final String STATE_TOUR_TYPE_ID = "TourTypeId"; //$NON-NLS-1$

    private static final String STATE_IS_KEEP_ORIGINAL_TIME = "isKeepOriginalTime"; //$NON-NLS-1$
    private static final String STATE_IS_INCLUDE_DESCRIPTION = "isIncludeDescription"; //$NON-NLS-1$
    private static final String STATE_IS_INCLUDE_MARKER_WAYPOINTS = "isIncludeMarkerWaypoints"; //$NON-NLS-1$

    private static final String STATE_TOUR_TITLE_SOURCE = "TourTitleSource"; //$NON-NLS-1$
    private static final String STATE_TOUR_TITLE_SOURCE_FROM_TOUR = "fromTour"; //$NON-NLS-1$
    private static final String STATE_TOUR_TITLE_SOURCE_FROM_MARKER = "fromFirstMarker"; //$NON-NLS-1$
    private static final String STATE_TOUR_TITLE_SOURCE_CUSTOM = "custom"; //$NON-NLS-1$

    private static final String STATE_EXTRACT_METHOD = "ExtractMethod"; //$NON-NLS-1$
    private static final String STATE_EXTRACT_METHOD_REMOVE = "remove"; //$NON-NLS-1$
    private static final String STATE_EXTRACT_METHOD_KEEP = "keep"; //$NON-NLS-1$

    private static final String STATE_TYPE_SOURCE = "TourTypeSource"; //$NON-NLS-1$
    private static final String STATE_TYPE_SOURCE_FROM_SELECTED_TOURS = "fromTour"; //$NON-NLS-1$
    private static final String STATE_TYPE_SOURCE_FROM_PREVIOUS_TOUR = "previous"; //$NON-NLS-1$
    private static final String STATE_TYPE_SOURCE_CUSTOM = "custom"; //$NON-NLS-1$

    /**
     * state: tour title
     */
    private static final String[] ALL_STATES_TOUR_TILE_SOURCE = new String[] { STATE_TOUR_TITLE_SOURCE_FROM_TOUR,
            STATE_TOUR_TITLE_SOURCE_FROM_MARKER, //
            STATE_TOUR_TITLE_SOURCE_CUSTOM, //
    };
    private static final String[] STATE_COMBO_TEXT_TOUR_TITLE_SOURCE = new String[] {
            Messages.Dialog_SplitTour_ComboText_TourTitleFromTour,
            Messages.Dialog_SplitTour_ComboText_TourTitleFromFirstMarker,
            Messages.Dialog_SplitTour_ComboText_TourTileCustom,
            //
    };
    /**
     * state: split/extract method
     */
    private static final String[] ALL_STATES_EXTRACT_METHOD = new String[] { STATE_EXTRACT_METHOD_KEEP,
            STATE_EXTRACT_METHOD_REMOVE,
            //
    };
    private static final String[] STATE_COMBO_TEXT_EXTRACT_METHOD = new String[] {
            Messages.Dialog_SplitTour_ComboText_KeepSlices, Messages.Dialog_SplitTour_ComboText_RemoveSlices,
            //
    };

    /**
     * state: tour type splitted tour
     */
    private static final String[] ALL_STATES_TOUR_TYPE = new String[] { STATE_TYPE_SOURCE_FROM_SELECTED_TOURS,
            STATE_TYPE_SOURCE_FROM_PREVIOUS_TOUR, STATE_TYPE_SOURCE_CUSTOM //
    };
    private static final String[] STATE_TEXT_TOUR_TYPE_SOURCE = new String[] {
            Messages.Dialog_SplitTour_ComboText_TourTypeFromTour,
            Messages.Dialog_SplitTour_ComboText_TourTypePrevious, Messages.Dialog_SplitTour_ComboText_TourTypeCustom //
    };

    private final IDialogSettings _state = TourbookPlugin.getDefault() //
            .getDialogSettingsSection("DialogSplit"); //$NON-NLS-1$

    private TourDataEditorView _tourDataEditor;

    private TourData _tourDataSource;
    private TourData _tourDataTarget;
    private ArrayList<TourData> _tourDataTargetList;

    private String _tourTitleFromTour;
    private String _tourTitleFromCustom;
    private String _tourTitleFromMarker;

    private long _tourTypeIdFromSelectedTours = TourDatabase.ENTITY_IS_NOT_SAVED;
    private long _tourTypeIdPreviousSplittedTour = TourDatabase.ENTITY_IS_NOT_SAVED;
    private long _tourTypeIdCustom = TourDatabase.ENTITY_IS_NOT_SAVED;

    private ITourEventListener _tourEventListener;

    private int _extractStartIndex;

    /**
     * Last index in the data serie when tour is extracted. This is set to -1 when the tour is
     * splitted which extract the tour from the {@link #_extractStartIndex} until the last data
     * serie index.
     */
    private int _extractEndIndex;

    /**
     * Is <code>true</code> when tour is splitted otherwise it is extracted and
     * {@link #_extractEndIndex} contains the last data serie index.
     */
    private boolean _isSplitTour;

    /**
     * is <code>true</code> when tour slices can be deleted
     */
    private boolean _canRemoveTimeSlices;

    private DateTime _extractedTourStartTime;

    /*
     * UI controls
     */
    private Composite _dlgInnerContainer;

    private Text _txtTourTitle;
    private Combo _cboTourTitleSource;

    private Combo _cboSplitMethod;

    private Button _chkKeepOriginalDateTime;
    private Label _lblTourStartDate;
    private Label _lblTourStartTime;
    private org.eclipse.swt.widgets.DateTime _dtTourDate;
    private org.eclipse.swt.widgets.DateTime _dtTourTime;

    private Combo _cboTourTypeSource;
    private Link _linkTourType;
    private CLabel _lblTourType;

    private Link _linkTag;
    private Label _lblTourTags;

    private Combo _cboPerson;

    private Button _chkIncludeDescription;
    private Button _chkIncludeMarkerWaypoints;

    private ActionOpenPrefDialog _actionOpenTourTypePrefs;

    /*
     * end of UI controls
     */

    private TourPerson[] _people;
    protected Point _shellDefaultSize;
    private TagMenuManager _tagMenuMgr;

    /**
     * Split or extract a tour
     *
     * @param parentShell
     * @param tourData
     * @param extractStartIndex
     * @param extractEndIndex
     *            when -1 the tour is splitted at {@link #_extractStartIndex} otherwise it is
     *            extracted
     * @param tourDataEditor
     */
    public DialogExtractTour(final Shell parentShell, final TourData tourData, final int extractStartIndex,
            final int extractEndIndex, final TourDataEditorView tourDataEditor) {

        super(parentShell);

        _isSplitTour = extractEndIndex == -1 ? true : false;

        _extractStartIndex = extractStartIndex;
        _extractEndIndex = extractEndIndex;

        _tourDataEditor = tourDataEditor;
        _tourDataSource = tourData;

        setDefaultImage(TourbookPlugin.getImageDescriptor(Messages.Image__MyTourbook16).createImage());

        _canRemoveTimeSlices = _tourDataEditor.getTourData().isContainReferenceTour() == false;

        // make dialog resizable
        setShellStyle(getShellStyle() | SWT.RESIZE);
    }

    @Override
    protected void configureShell(final Shell shell) {

        super.configureShell(shell);

        shell.setText(_isSplitTour ? //
                Messages.Dialog_SplitTour_DlgArea_Title : Messages.Dialog_ExtractTour_DlgArea_Title);

        shell.addDisposeListener(new DisposeListener() {
            @Override
            public void widgetDisposed(final DisposeEvent e) {
                onDispose();
            }
        });

        shell.addListener(SWT.Resize, new Listener() {
            @Override
            public void handleEvent(final Event event) {

                // allow resizing the width but not the height

                if (_shellDefaultSize == null) {
                    _shellDefaultSize = shell.computeSize(SWT.DEFAULT, SWT.DEFAULT);
                }

                final Point shellSize = shell.getSize();

                /*
                 * this is not working, the shell is flickering when the shell size is below min
                 * size and I found no way to prevent a resize :-(
                 */
                //            if (shellSize.x < _shellDefaultSize.x) {
                //               event.doit = false;
                //            }

                shellSize.x = shellSize.x < _shellDefaultSize.x ? _shellDefaultSize.x : shellSize.x;
                shellSize.y = _shellDefaultSize.y;

                shell.setSize(shellSize);
            }
        });
    }

    @Override
    public void create() {

        super.create();

        setTitle(_isSplitTour ? //
                Messages.Dialog_SplitTour_DlgArea_Title : Messages.Dialog_ExtractTour_DlgArea_Title);
        setMessage(_isSplitTour ? //
                Messages.Dialog_SplitTour_DlgArea_Message : Messages.Dialog_ExtractTour_DlgArea_Message);
    }

    private void createActions() {

        _tagMenuMgr = new TagMenuManager(this, false);

        _actionOpenTourTypePrefs = new ActionOpenPrefDialog(Messages.action_tourType_modify_tourTypes,
                ITourbookPreferences.PREF_PAGE_TOUR_TYPE);
    }

    @Override
    protected Control createDialogArea(final Composite parent) {

        final Composite dlgContainer = (Composite) super.createDialogArea(parent);

        initTargetTourData();

        createUI(dlgContainer);
        createActions();
        createMenus();

        restoreState();

        updateUITourTypeTags();
        updateUIFromModel();

        enableControls();

        return dlgContainer;
    }

    /**
     * create the drop down menus, this must be created after the parent control is created
     */
    private void createMenus() {

        /*
         * tour type menu
         */
        final MenuManager typeMenuMgr = new MenuManager();

        typeMenuMgr.setRemoveAllWhenShown(true);
        typeMenuMgr.addMenuListener(new IMenuListener() {
            @Override
            public void menuAboutToShow(final IMenuManager menuMgr) {

                // set menu items

                ActionSetTourTypeMenu.fillMenu(menuMgr, DialogExtractTour.this, false);

                menuMgr.add(new Separator());
                menuMgr.add(_actionOpenTourTypePrefs);
            }
        });

        // set menu for the tag item
        _linkTourType.setMenu(typeMenuMgr.createContextMenu(_linkTourType));

        /*
         * tag menu
         */
        final MenuManager menuMgr = new MenuManager();

        menuMgr.setRemoveAllWhenShown(true);
        menuMgr.addMenuListener(new IMenuListener() {
            @Override
            public void menuAboutToShow(final IMenuManager menuMgr) {

                final Set<TourTag> targetTourTags = _tourDataTarget.getTourTags();
                final boolean isTagInTour = targetTourTags != null && targetTourTags.size() > 0;

                _tagMenuMgr.fillTagMenu(menuMgr);
                _tagMenuMgr.enableTagActions(true, isTagInTour, targetTourTags);
            }
        });

        // set menu for the tag item

        final Menu tagContextMenu = menuMgr.createContextMenu(_linkTag);
        tagContextMenu.addMenuListener(new MenuListener() {

            @Override
            public void menuHidden(final MenuEvent e) {
                _tagMenuMgr.onHideMenu();
            }

            @Override
            public void menuShown(final MenuEvent e) {

                final Rectangle rect = _linkTag.getBounds();
                Point pt = new Point(rect.x, rect.y + rect.height);
                pt = _linkTag.getParent().toDisplay(pt);

                _tagMenuMgr.onShowMenu(e, _linkTag, pt, null);
            }
        });

        _linkTag.setMenu(tagContextMenu);

    }

    private void createUI(final Composite parent) {

        final SelectionAdapter defaultSelectionAdapter = new SelectionAdapter() {
            @Override
            public void widgetSelected(final SelectionEvent e) {
                enableControls();
            }
        };

        _dlgInnerContainer = new Composite(parent, SWT.NONE);
        GridDataFactory.fillDefaults().grab(true, true).applyTo(_dlgInnerContainer);
        GridLayoutFactory.swtDefaults().margins(10, 10).numColumns(3).spacing(10, 8).applyTo(_dlgInnerContainer);
        //      _dlgInnerContainer.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_BLUE));
        {
            createUI10SplitMethod(_dlgInnerContainer);
            createUI20Title(_dlgInnerContainer);
            createUI22TourTime(_dlgInnerContainer, defaultSelectionAdapter);
            createUI30TypeTags(_dlgInnerContainer);
            createUI40Person(_dlgInnerContainer);
            createUI50DescriptionMarker(_dlgInnerContainer, defaultSelectionAdapter);
        }
    }

    /**
     * split method
     */
    private void createUI10SplitMethod(final Composite parent) {

        // label
        final Label label = new Label(parent, SWT.NONE);
        GridDataFactory.fillDefaults()//
                .align(SWT.FILL, SWT.CENTER).applyTo(label);
        label.setText(_isSplitTour ? Messages.Dialog_SplitTour_Label_SplitMethod
                : Messages.Dialog_ExtractTour_Label_SplitMethod);

        _cboSplitMethod = new Combo(parent, SWT.READ_ONLY);
        GridDataFactory.fillDefaults().grab(true, false).span(2, 1).applyTo(_cboSplitMethod);

        // fill combo
        for (final String timeText : STATE_COMBO_TEXT_EXTRACT_METHOD) {
            _cboSplitMethod.add(timeText);
        }
    }

    /**
     * tour title
     */
    private void createUI20Title(final Composite parent) {

        // label: title
        final Label label = new Label(parent, SWT.NONE);
        label.setText(Messages.Dialog_SplitTour_Label_TourTitle);
        label.setToolTipText(Messages.Dialog_SplitTour_Label_TourTitle_Tooltip);

        // combo: title source
        _cboTourTitleSource = new Combo(parent, SWT.READ_ONLY);
        GridDataFactory.fillDefaults()//
                .grab(true, false).span(2, 1).applyTo(_cboTourTitleSource);
        _cboTourTitleSource.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(final SelectionEvent e) {
                onSelectTourTitleSource();
            }
        });

        // fill combo
        for (final String comboText : STATE_COMBO_TEXT_TOUR_TITLE_SOURCE) {
            _cboTourTitleSource.add(comboText);
        }

        // spacer
        new Label(parent, SWT.NONE);

        // text: title
        _txtTourTitle = new Text(parent, SWT.BORDER);
        GridDataFactory.fillDefaults()//
                .grab(true, false).span(2, 1).indent(0, -5).applyTo(_txtTourTitle);
        _txtTourTitle.setToolTipText(Messages.Dialog_SplitTour_Label_TourTitle_Tooltip);
    }

    /**
     * tour time
     */
    private void createUI22TourTime(final Composite parent, final SelectionAdapter defaultSelectionAdapter) {

        final SelectionAdapter dateTimeUpdateListener = new SelectionAdapter() {
            @Override
            public void widgetSelected(final SelectionEvent e) {
                enableControls();
            }
        };

        /*
         * keep original time
         */
        final Label label = new Label(parent, SWT.NONE);
        GridDataFactory.fillDefaults()//
                .align(SWT.FILL, SWT.CENTER).applyTo(label);
        label.setText(Messages.Dialog_SplitTour_Label_TourStartDateTime);

        _chkKeepOriginalDateTime = new Button(parent, SWT.CHECK);
        GridDataFactory.fillDefaults().span(2, 1).applyTo(_chkKeepOriginalDateTime);
        _chkKeepOriginalDateTime.setText(Messages.Dialog_SplitTour_Checkbox_KeepTime);
        _chkKeepOriginalDateTime.addSelectionListener(defaultSelectionAdapter);

        //spacer
        new Label(parent, SWT.NONE);

        /*
         * tour start date/time
         */
        final Composite dateContainer = new Composite(parent, SWT.NONE);
        GridDataFactory.fillDefaults()//
                .span(2, 1).indent(0, -5).applyTo(dateContainer);
        GridLayoutFactory.fillDefaults().numColumns(4).applyTo(dateContainer);
        {
            /*
             * tour start: date
             */
            _lblTourStartDate = new Label(dateContainer, SWT.NONE);
            _lblTourStartDate.setText(Messages.Dialog_JoinTours_Label_TourDate);

            _dtTourDate = new org.eclipse.swt.widgets.DateTime(dateContainer,
                    SWT.DATE | SWT.DROP_DOWN | SWT.BORDER);
            GridDataFactory.fillDefaults().align(SWT.END, SWT.FILL).applyTo(_dtTourDate);
            _dtTourDate.addSelectionListener(dateTimeUpdateListener);

            /*
             * tour start: time
             */
            _lblTourStartTime = new Label(dateContainer, SWT.NONE);
            GridDataFactory.fillDefaults().indent(20, 0).align(SWT.FILL, SWT.CENTER).applyTo(_lblTourStartTime);
            _lblTourStartTime.setText(Messages.Dialog_JoinTours_Label_TourTime);

            _dtTourTime = new org.eclipse.swt.widgets.DateTime(dateContainer,
                    SWT.TIME | SWT.DROP_DOWN | SWT.BORDER);
            GridDataFactory.fillDefaults().align(SWT.END, SWT.FILL).applyTo(_dtTourTime);
            _dtTourTime.addSelectionListener(dateTimeUpdateListener);
        }
    }

    /**
     * tour type & tags
     *
     * @param defaultSelectionAdapter
     */
    private void createUI30TypeTags(final Composite parent) {

        /*
         * tour type
         */
        final Label label = new Label(parent, SWT.NONE);
        GridDataFactory.fillDefaults()//
                .align(SWT.FILL, SWT.CENTER).applyTo(label);
        label.setText(Messages.Dialog_JoinTours_Label_TourType);

        _cboTourTypeSource = new Combo(parent, SWT.READ_ONLY);
        GridDataFactory.fillDefaults().grab(true, false).span(2, 1).applyTo(_cboTourTypeSource);
        _cboTourTypeSource.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(final SelectionEvent e) {
                onSelectTourTypeSource();
            }
        });

        // fill combo
        for (final String tourTypeText : STATE_TEXT_TOUR_TYPE_SOURCE) {
            _cboTourTypeSource.add(tourTypeText);
        }

        // spacer
        new Label(parent, SWT.NONE);

        final Composite tourTypeContainer = new Composite(parent, SWT.NONE);
        GridDataFactory.fillDefaults().grab(true, false)//
                .indent(0, -8).span(2, 1).applyTo(tourTypeContainer);
        GridLayoutFactory.fillDefaults().numColumns(2).applyTo(tourTypeContainer);
        {
            _linkTourType = new Link(tourTypeContainer, SWT.NONE);
            _linkTourType.setText(Messages.Dialog_JoinTours_Link_TourType);
            _linkTourType.addSelectionListener(new SelectionAdapter() {
                @Override
                public void widgetSelected(final SelectionEvent e) {
                    net.tourbook.util.UI.openControlMenu(_linkTourType);
                }
            });

            _lblTourType = new CLabel(tourTypeContainer, SWT.NONE);
            GridDataFactory.swtDefaults().grab(true, false).applyTo(_lblTourType);
        }

        /*
         * tags
         */
        _linkTag = new Link(parent, SWT.NONE);
        _linkTag.setText(Messages.tour_editor_label_tour_tag);
        GridDataFactory.fillDefaults()//
                .align(SWT.BEGINNING, SWT.FILL).applyTo(_linkTag);
        _linkTag.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(final SelectionEvent e) {
                net.tourbook.util.UI.openControlMenu(_linkTag);
            }
        });

        _lblTourTags = new Label(parent, SWT.WRAP);
        GridDataFactory.fillDefaults()//
                .grab(true, false)
                // hint is necessary that the width is not expanded when the text is very long
                .hint(200, SWT.DEFAULT).span(2, 1).applyTo(_lblTourTags);
    }

    /**
     * person
     */
    private void createUI40Person(final Composite parent) {

        // label
        final Label label = new Label(parent, SWT.NONE);
        GridDataFactory.fillDefaults()//
                .align(SWT.FILL, SWT.CENTER).applyTo(label);
        label.setText(Messages.Dialog_SplitTour_Label_Person);
        label.setToolTipText(Messages.Dialog_SplitTour_Label_Person_Tooltip);

        // combo: person
        _cboPerson = new Combo(parent, SWT.READ_ONLY);
        GridDataFactory.fillDefaults().grab(true, false).span(2, 1).applyTo(_cboPerson);
        _cboPerson.setVisibleItemCount(20);
        _cboPerson.setToolTipText(Messages.Dialog_SplitTour_Label_Person_Tooltip);
    }

    /**
     * checkbox: set marker for each tour
     */
    private void createUI50DescriptionMarker(final Composite parent,
            final SelectionAdapter defaultSelectionAdapter) {

        /*
         * checkbox: description
         */
        _chkIncludeDescription = new Button(parent, SWT.CHECK);
        GridDataFactory.fillDefaults().span(3, 1).indent(0, 10).applyTo(_chkIncludeDescription);
        _chkIncludeDescription.setText(Messages.Dialog_SplitTour_Checkbox_IncludeDescription);

        /*
         * checkbox: include existing tour marker
         */
        _chkIncludeMarkerWaypoints = new Button(parent, SWT.CHECK);
        GridDataFactory.fillDefaults().span(3, 1).indent(0, -5).applyTo(_chkIncludeMarkerWaypoints);
        _chkIncludeMarkerWaypoints.setText(Messages.Dialog_JoinTours_Checkbox_IncludeMarkerWaypoints);
    }

    private void enableControls() {

        final boolean isCustomTime = _chkKeepOriginalDateTime.getSelection() == false;
        final boolean isCustomTourType = getStateTourTypeSource().equals(STATE_TYPE_SOURCE_CUSTOM);
        final boolean isCustomTourTitle = getStateTourTitleSource().equals(STATE_TOUR_TITLE_SOURCE_CUSTOM);

        _txtTourTitle.setEditable(isCustomTourTitle);

        _dtTourDate.setEnabled(isCustomTime);
        _dtTourTime.setEnabled(isCustomTime);
        _lblTourStartDate.setEnabled(isCustomTime);
        _lblTourStartTime.setEnabled(isCustomTime);

        _linkTourType.setEnabled(isCustomTourType);
        _lblTourType.setEnabled(isCustomTourType);

        // enable/disable actions for tags/tour types
        //      TagManager.enableRecentTagActions(true, _tourDataTarget.getTourTags());
    }

    //   /**
    //    * info
    //    */
    //   private void createUI60Info(final Composite container) {
    //
    //      final Label label = new Label(container, SWT.NONE);
    //      GridDataFactory.fillDefaults().align(SWT.FILL, SWT.BEGINNING).indent(0, 10).applyTo(label);
    //      label.setText(Messages.Dialog_JoinTours_Label_OtherFields);
    //
    //      // use a bulleted list to display this info
    //      final StyleRange style = new StyleRange();
    //      style.metrics = new GlyphMetrics(0, 0, 10);
    //      final Bullet bullet = new Bullet(style);
    //
    //      final String infoText = Messages.Dialog_SplitTour_Label_OtherFieldsInfo;
    //      final int lineCount = Util.countCharacter(infoText, '\n');
    //
    //      final StyledText styledText = new StyledText(container, SWT.READ_ONLY);
    //      GridDataFactory.fillDefaults()//
    //            .align(SWT.FILL, SWT.BEGINNING)
    //            .indent(0, 10)
    //            .span(2, 1)
    //            .applyTo(styledText);
    //      styledText.setText(infoText);
    //      styledText.setBackground(container.getDisplay().getSystemColor(SWT.COLOR_WIDGET_BACKGROUND));
    //      styledText.setLineBullet(0, lineCount + 1, bullet);
    //   }

    /**
     * Create a new tour with the extracted time slices
     */
    private boolean extractTour() {

        /*
         * get data series
         */
        final int[] tourAltitudeSerie = _tourDataSource.altitudeSerie;
        final int[] tourCadenceSerie = _tourDataSource.cadenceSerie;
        final int[] tourDistanceSerie = _tourDataSource.distanceSerie;
        final double[] tourLatitudeSerie = _tourDataSource.latitudeSerie;
        final double[] tourLongitudeSerie = _tourDataSource.longitudeSerie;
        final int[] tourPulseSerie = _tourDataSource.pulseSerie;
        final int[] tourTemperatureSerie = _tourDataSource.temperatureSerie;
        final int[] tourTimeSerie = _tourDataSource.timeSerie;

        final boolean isTourAltitude = (tourAltitudeSerie != null) && (tourAltitudeSerie.length > 0);
        final boolean isTourCadence = (tourCadenceSerie != null) && (tourCadenceSerie.length > 0);
        final boolean isTourDistance = (tourDistanceSerie != null) && (tourDistanceSerie.length > 0);
        final boolean isTourLat = (tourLatitudeSerie != null) && (tourLatitudeSerie.length > 0);
        final boolean isTourLon = (tourLongitudeSerie != null) && (tourLongitudeSerie.length > 0);
        final boolean isTourPulse = (tourPulseSerie != null) && (tourPulseSerie.length > 0);
        final boolean isTourTemperature = (tourTemperatureSerie != null) && (tourTemperatureSerie.length > 0);
        final boolean isTourTime = (tourTimeSerie != null) && (tourTimeSerie.length > 0);

        /*
         * get speed/power data when data are created by the device
         */
        int[] tourPowerSerie = null;
        int[] tourSpeedSerie = null;
        final boolean isTourPower = _tourDataSource.isPowerSerieFromDevice();
        final boolean isTourSpeed = _tourDataSource.isSpeedSerieFromDevice();
        if (isTourPower) {
            tourPowerSerie = _tourDataSource.getPowerSerie();
        }
        if (isTourSpeed) {
            tourSpeedSerie = _tourDataSource.getSpeedSerie();
        }

        int dataSerieLength = -1;

        if (isTourAltitude) {
            dataSerieLength = tourAltitudeSerie.length;
        } else if (isTourCadence) {
            dataSerieLength = tourCadenceSerie.length;
        } else if (isTourDistance) {
            dataSerieLength = tourDistanceSerie.length;
        } else if (isTourLat) {
            dataSerieLength = tourLatitudeSerie.length;
        } else if (isTourLon) {
            dataSerieLength = tourLongitudeSerie.length;
        } else if (isTourPower) {
            dataSerieLength = tourPowerSerie.length;
        } else if (isTourPulse) {
            dataSerieLength = tourPulseSerie.length;
        } else if (isTourSpeed) {
            dataSerieLength = tourSpeedSerie.length;
        } else if (isTourTemperature) {
            dataSerieLength = tourTemperatureSerie.length;
        } else if (isTourTime) {
            dataSerieLength = tourTimeSerie.length;
        }

        if (dataSerieLength == -1) {
            StatusUtil.showStatus(Messages.NT001_DialogExtractTour_InvalidTourData);
            return false;
        }

        if (_isSplitTour) {
            // _extractEndIndex contains -1, set end index to the last time slice
            _extractEndIndex = dataSerieLength - 1;
        }

        final int extractSerieLength = _extractEndIndex - _extractStartIndex + 1;

        final int[] extractAltitudeSerie = new int[extractSerieLength];
        final int[] extractCadenceSerie = new int[extractSerieLength];
        final int[] extractDistanceSerie = new int[extractSerieLength];
        final double[] extractLatitudeSerie = new double[extractSerieLength];
        final double[] extractLongitudeSerie = new double[extractSerieLength];
        final int[] extractPowerSerie = new int[extractSerieLength];
        final int[] extractPulseSerie = new int[extractSerieLength];
        final int[] extractSpeedSerie = new int[extractSerieLength];
        final int[] extractTemperatureSerie = new int[extractSerieLength];
        final int[] extractTimeSerie = new int[extractSerieLength];

        final HashSet<TourMarker> extractedTourMarker = new HashSet<TourMarker>();
        final ArrayList<TourWayPoint> extractedWayPoints = new ArrayList<TourWayPoint>();

        /*
         * get start date/time
         */
        DateTime extractedTourStart = null;
        final boolean isOriginalTime = _chkKeepOriginalDateTime.getSelection();
        if (isOriginalTime) {
            extractedTourStart = _extractedTourStartTime;
        } else {
            extractedTourStart = new DateTime(_dtTourDate.getYear(), _dtTourDate.getMonth() + 1,
                    _dtTourDate.getDay(), _dtTourTime.getHours(), _dtTourTime.getMinutes(),
                    _dtTourTime.getSeconds(), 0);
        }

        int relTourStartTime = 0;
        int extractedRecordingTime = 0;
        if (isTourTime) {
            relTourStartTime = tourTimeSerie[_extractStartIndex];
            extractedRecordingTime = tourTimeSerie[_extractEndIndex] - relTourStartTime;
        }

        // get distance
        int extractedDistance = 0;
        int relTourStartDistance = 0;
        if (isTourDistance) {
            relTourStartDistance = tourDistanceSerie[_extractStartIndex];
            extractedDistance = tourDistanceSerie[_extractEndIndex] - relTourStartDistance;
        }

        /*
         * copy existing data series
         */
        int extractedSerieIndex = 0;
        for (int sourceSerieIndex = _extractStartIndex; sourceSerieIndex <= _extractEndIndex; sourceSerieIndex++) {

            if (isTourTime) {
                extractTimeSerie[extractedSerieIndex] = tourTimeSerie[sourceSerieIndex] - relTourStartTime;
            }

            if (isTourAltitude) {
                extractAltitudeSerie[extractedSerieIndex] = tourAltitudeSerie[sourceSerieIndex];
            }
            if (isTourCadence) {
                extractCadenceSerie[extractedSerieIndex] = tourCadenceSerie[sourceSerieIndex];
            }

            if (isTourDistance) {
                extractDistanceSerie[extractedSerieIndex] = tourDistanceSerie[sourceSerieIndex]
                        - relTourStartDistance;
            }

            if (isTourPulse) {
                extractPulseSerie[extractedSerieIndex] = tourPulseSerie[sourceSerieIndex];
            }
            if (isTourLat) {
                extractLatitudeSerie[extractedSerieIndex] = tourLatitudeSerie[sourceSerieIndex];
            }
            if (isTourLon) {
                extractLongitudeSerie[extractedSerieIndex] = tourLongitudeSerie[sourceSerieIndex];
            }
            if (isTourTemperature) {
                extractTemperatureSerie[extractedSerieIndex] = tourTemperatureSerie[sourceSerieIndex];
            }
            if (isTourPower) {
                extractPowerSerie[extractedSerieIndex] = tourPowerSerie[sourceSerieIndex];
            }
            if (isTourSpeed) {
                extractSpeedSerie[extractedSerieIndex] = tourSpeedSerie[sourceSerieIndex];
            }

            extractedSerieIndex++;
        }

        /*
         * get tour markers, way points
         */
        final Set<TourMarker> tourMarkers = _tourDataSource.getTourMarkers();
        if (_chkIncludeMarkerWaypoints.getSelection()) {

            for (final TourMarker tourMarker : tourMarkers) {

                final int markerSerieIndex = tourMarker.getSerieIndex();

                // skip marker which are not within the extracted time slices
                if (markerSerieIndex < _extractStartIndex || markerSerieIndex > _extractEndIndex) {
                    continue;
                }

                final int extractedMarkerIndex = markerSerieIndex - _extractStartIndex;

                final TourMarker extractedMarker = tourMarker.clone(_tourDataTarget);

                // adjust marker position, position is relativ to the tour start
                extractedMarker.setSerieIndex(extractedMarkerIndex);

                if (isTourTime) {
                    tourMarker.setTime(extractTimeSerie[extractedMarkerIndex]);
                }
                if (isTourDistance) {
                    tourMarker.setDistance(extractDistanceSerie[extractedMarkerIndex]);
                }

                extractedTourMarker.add(extractedMarker);
            }

            /*
             * copy all way points, they can be independant of the tour
             */
            for (final TourWayPoint wayPoint : _tourDataSource.getTourWayPoints()) {
                extractedWayPoints.add((TourWayPoint) wayPoint.clone());
            }
        }

        // get description
        String extractedDescription = UI.EMPTY_STRING;
        if (_chkIncludeDescription.getSelection()) {
            extractedDescription = _tourDataSource.getTourDescription();
        }

        /*
         * get calories
         */
        int extractedCalories = 0;
        if (_extractStartIndex == 0 && _extractEndIndex == (dataSerieLength - 1)) {

            // tour is copied, the calories can also be copied
            extractedCalories = _tourDataSource.getCalories();

        } else {
            // TODO calories should be set when they are computed
        }

        /*
         * set target tour data
         */
        _tourDataTarget.setStartYear((short) extractedTourStart.getYear());
        _tourDataTarget.setStartMonth((short) extractedTourStart.getMonthOfYear());
        _tourDataTarget.setStartDay((short) extractedTourStart.getDayOfMonth());
        _tourDataTarget.setStartHour((short) extractedTourStart.getHourOfDay());
        _tourDataTarget.setStartMinute((short) extractedTourStart.getMinuteOfHour());
        _tourDataTarget.setStartSecond((short) extractedTourStart.getSecondOfMinute());

        _tourDataTarget.setWeek(extractedTourStart);

        // tour id must be created after the tour date/time is set
        _tourDataTarget.createTourId();

        _tourDataTarget.setTourTitle(_txtTourTitle.getText());
        _tourDataTarget.setTourDescription(extractedDescription.toString());

        _tourDataTarget.setTourMarkers(extractedTourMarker);
        _tourDataTarget.setWayPoints(extractedWayPoints);
        _tourDataTarget.setDeviceName(_isSplitTour ? Messages.Dialog_SplitTour_Label_DeviceName
                : Messages.Dialog_ExtractTour_Label_DeviceName);

        _tourDataTarget.setIsDistanceFromSensor(_tourDataSource.isDistanceSensorPresent());
        _tourDataTarget.setDeviceTimeInterval(_tourDataSource.getDeviceTimeInterval());

        _tourDataTarget.setTourRecordingTime(extractedRecordingTime);
        _tourDataTarget.setTourDistance(extractedDistance);

        _tourDataTarget.setWeather(_tourDataSource.getWeather());
        _tourDataTarget.setWeatherClouds(_tourDataSource.getWeatherClouds());
        _tourDataTarget.setWeatherWindDir(_tourDataSource.getWeatherWindDir());
        _tourDataTarget.setWeatherWindSpeed(_tourDataSource.getWeatherWindSpeed());

        _tourDataTarget.setRestPulse(_tourDataSource.getRestPulse());
        _tourDataTarget.setCalories(extractedCalories);

        _tourDataTarget.setDpTolerance(_tourDataSource.getDpTolerance());

        if (isTourAltitude) {
            _tourDataTarget.altitudeSerie = extractAltitudeSerie;
        }
        if (isTourDistance) {
            _tourDataTarget.distanceSerie = extractDistanceSerie;
        }
        if (isTourCadence) {
            _tourDataTarget.cadenceSerie = extractCadenceSerie;
        }
        if (isTourLat) {
            _tourDataTarget.latitudeSerie = extractLatitudeSerie;
        }
        if (isTourLon) {
            _tourDataTarget.longitudeSerie = extractLongitudeSerie;
        }
        if (isTourPower) {
            _tourDataTarget.setPowerSerie(extractPowerSerie);
        }
        if (isTourPulse) {
            _tourDataTarget.pulseSerie = extractPulseSerie;
        }
        if (isTourSpeed) {
            _tourDataTarget.setSpeedSerie(extractSpeedSerie);
        }
        if (isTourTemperature) {
            _tourDataTarget.temperatureSerie = extractTemperatureSerie;
        }
        if (isTourTime) {
            _tourDataTarget.timeSerie = extractTimeSerie;
        }

        _tourDataTarget.setTemperatureScale(_tourDataSource.getTemperatureScale());

        _tourDataTarget.computeAltitudeUpDown();
        _tourDataTarget.computeTourDrivingTime();
        _tourDataTarget.computeComputedValues();

        // set person which is required to save a tour
        _tourDataTarget.setTourPerson(getSelectedPerson());

        /*
         * check size of the fields
         */
        if (_tourDataTarget.isValidForSave() == false) {
            return false;
        }

        TourManager.saveModifiedTour(_tourDataTarget);

        // check if time slices should be removed
        if (getStateSplitMethod().equals(STATE_EXTRACT_METHOD_REMOVE)) {

            TourManager.removeTimeSlices(_tourDataSource, _extractStartIndex, _extractEndIndex, true);

            _tourDataEditor.updateUI(_tourDataSource, true);

            TourManager.fireEvent(TourEventId.TOUR_CHANGED, new TourEvent(_tourDataSource));
        }

        return true;
    }

    @Override
    protected IDialogSettings getDialogBoundsSettings() {

        // keep window size and position
        return _state;
        //      return null;
    }

    private TourPerson getSelectedPerson() {

        final int selectedIndex = _cboPerson.getSelectionIndex();
        final TourPerson person = _people[selectedIndex];

        return person;
    }

    @Override
    public ArrayList<TourData> getSelectedTours() {

        // return extracted tour

        return _tourDataTargetList;
    }

    private String getStateSplitMethod() {
        return Util.getStateFromCombo(_cboSplitMethod, ALL_STATES_EXTRACT_METHOD, STATE_EXTRACT_METHOD_REMOVE);
    }

    private String getStateTourTitleSource() {
        return Util.getStateFromCombo(_cboTourTitleSource, ALL_STATES_TOUR_TILE_SOURCE,
                STATE_TOUR_TITLE_SOURCE_FROM_TOUR);
    }

    private String getStateTourTypeSource() {
        return Util.getStateFromCombo(_cboTourTypeSource, ALL_STATES_TOUR_TYPE,
                STATE_TYPE_SOURCE_FROM_SELECTED_TOURS);
    }

    /**
     * Create {@link TourData} for the splitted/extracted tour
     */
    private void initTargetTourData() {

        _tourDataTarget = new TourData();

        /*
         * create a dummy tour id because setting of the tags and tour type works requires it
         * otherwise it would cause a NPE when a tour has no id
         */
        _tourDataTarget.createTourIdDummy();

        _tourDataTargetList = new ArrayList<TourData>();
        _tourDataTargetList.add(_tourDataTarget);

        /*
         * set tour title
         */
        _tourTitleFromTour = _tourDataSource.getTourTitle();
        _tourTitleFromMarker = UI.EMPTY_STRING;

        // get title from first marker which is within the splitted tour
        final ArrayList<TourMarker> sortedMarker = new ArrayList<TourMarker>(_tourDataSource.getTourMarkers());
        Collections.sort(sortedMarker);

        for (final TourMarker tourMarker : sortedMarker) {
            if (tourMarker.getSerieIndex() >= _extractStartIndex) {
                _tourTitleFromMarker = tourMarker.getLabel();
                break;
            }
        }
        // set default custom marker
        _tourTitleFromCustom = _tourTitleFromMarker;

        /*
         * get all tags
         */
        final Set<TourTag> extractedTourTags = new HashSet<TourTag>();
        final Set<TourTag> tourTags = _tourDataSource.getTourTags();
        extractedTourTags.addAll(tourTags);
        _tourDataTarget.setTourTags(extractedTourTags);

        /*
         * set tour type
         */
        // get tour type id
        final TourType tourType = _tourDataSource.getTourType();
        if (tourType != null) {
            _tourTypeIdFromSelectedTours = tourType.getTypeId();
        }

        _tourTypeIdCustom = //
                _tourTypeIdPreviousSplittedTour = Util.getStateLong(_state, STATE_TOUR_TYPE_ID,
                        TourDatabase.ENTITY_IS_NOT_SAVED);

        final String stateTourTypeSource = Util.getStateString(_state, STATE_TYPE_SOURCE,
                STATE_TYPE_SOURCE_FROM_SELECTED_TOURS);

        long extractedTourTypeId = TourDatabase.ENTITY_IS_NOT_SAVED;

        if (stateTourTypeSource.equals(STATE_TYPE_SOURCE_FROM_SELECTED_TOURS)) {
            extractedTourTypeId = _tourTypeIdFromSelectedTours;
        } else if (stateTourTypeSource.equals(STATE_TYPE_SOURCE_FROM_PREVIOUS_TOUR)
                || stateTourTypeSource.equals(STATE_TYPE_SOURCE_CUSTOM)) {
            extractedTourTypeId = _tourTypeIdPreviousSplittedTour;
        }

        _tourDataTarget.setTourType(TourDatabase.getTourType(extractedTourTypeId));
    }

    @Override
    protected void okPressed() {

        if (extractTour() == false) {
            return;
        }

        // state must be set after the tour is saved because the tour type id is set when the tour is saved
        saveState();

        super.okPressed();
    }

    private void onDispose() {

        TourManager.getInstance().removeTourEventListener(_tourEventListener);
    }

    private void onSelectTourTitleSource() {

        updateUITourTitle();
        enableControls();
    }

    private void onSelectTourTypeSource() {

        final String stateTourTypeSource = getStateTourTypeSource();

        long extractedTourTypeId = TourDatabase.ENTITY_IS_NOT_SAVED;

        if (stateTourTypeSource.equals(STATE_TYPE_SOURCE_FROM_SELECTED_TOURS)) {
            extractedTourTypeId = _tourTypeIdFromSelectedTours;
        } else if (stateTourTypeSource.equals(STATE_TYPE_SOURCE_FROM_PREVIOUS_TOUR)) {
            extractedTourTypeId = _tourTypeIdPreviousSplittedTour;
        } else if (stateTourTypeSource.equals(STATE_TYPE_SOURCE_CUSTOM)) {
            extractedTourTypeId = _tourTypeIdCustom;
        }

        _tourDataTarget.setTourType(TourDatabase.getTourType(extractedTourTypeId));

        updateUITourTypeTags();

        enableControls();
    }

    private void restoreState() {

        _txtTourTitle.setText(
                Util.getStateString(_state, STATE_TOUR_TITLE, Messages.Dialog_SplitTour_Label_DefaultTitle));

        // tour title source
        Util.selectStateInCombo(_state, STATE_TOUR_TITLE_SOURCE, ALL_STATES_TOUR_TILE_SOURCE,
                STATE_TOUR_TITLE_SOURCE_FROM_TOUR, _cboTourTitleSource);

        // split method
        Util.selectStateInCombo(_state, STATE_EXTRACT_METHOD, ALL_STATES_EXTRACT_METHOD,
                STATE_EXTRACT_METHOD_REMOVE, _cboSplitMethod);

        // tour type source
        Util.selectStateInCombo(_state, STATE_TYPE_SOURCE, ALL_STATES_TOUR_TYPE,
                STATE_TYPE_SOURCE_FROM_SELECTED_TOURS, _cboTourTypeSource);

        // tour start date/time
        _chkKeepOriginalDateTime.setSelection(Util.getStateBoolean(_state, STATE_IS_KEEP_ORIGINAL_TIME, true));

        // description/marker/waypoints
        _chkIncludeDescription.setSelection(Util.getStateBoolean(_state, STATE_IS_INCLUDE_DESCRIPTION, true));
        _chkIncludeMarkerWaypoints
                .setSelection(Util.getStateBoolean(_state, STATE_IS_INCLUDE_MARKER_WAYPOINTS, true));

        /*
         * update UI from selected tours
         */

        final DateTime tourStartTime = new DateTime(_tourDataSource.getStartYear(), _tourDataSource.getStartMonth(),
                _tourDataSource.getStartDay(), _tourDataSource.getStartHour(), _tourDataSource.getStartMinute(),
                _tourDataSource.getStartSecond(), 0);

        int relativeExtractedStartTime = 0;

        final int[] tourTimeSerie = _tourDataSource.timeSerie;
        final boolean isTourTime = (tourTimeSerie != null) && (tourTimeSerie.length > 0);
        if (isTourTime) {
            relativeExtractedStartTime = tourTimeSerie[_extractStartIndex];
        }
        _extractedTourStartTime = tourStartTime.plusSeconds(relativeExtractedStartTime);

        // date/time
        _dtTourDate.setDate(_extractedTourStartTime.getYear(), _extractedTourStartTime.getMonthOfYear() - 1,
                _extractedTourStartTime.getDayOfMonth());

        _dtTourTime.setTime(_extractedTourStartTime.getHourOfDay(), _extractedTourStartTime.getMinuteOfHour(),
                _extractedTourStartTime.getSecondOfMinute());

        /*
         * fill person combo and reselect previous person
         */
        final long statePersonId = Util.getStateLong(_state, STATE_PERSON_ID, -1);

        if (_people == null) {
            final ArrayList<TourPerson> people = PersonManager.getTourPeople();
            _people = people.toArray(new TourPerson[people.size()]);
        }

        int index = 0;
        int personIndex = 0;

        for (final TourPerson person : _people) {

            _cboPerson.add(person.getName());

            if (person.getPersonId() == statePersonId) {
                personIndex = index;
            }

            index++;
        }

        _cboPerson.select(personIndex);

    }

    private void saveState() {

        // tour title
        _state.put(STATE_TOUR_TITLE, _txtTourTitle.getText());
        _state.put(STATE_TOUR_TITLE_SOURCE, getStateTourTitleSource());

        // tour type
        final TourType tourType = _tourDataTarget.getTourType();
        _state.put(STATE_TOUR_TYPE_ID, tourType == null ? TourDatabase.ENTITY_IS_NOT_SAVED : tourType.getTypeId());
        _state.put(STATE_TYPE_SOURCE, getStateTourTypeSource());

        // split method
        _state.put(STATE_EXTRACT_METHOD, getStateSplitMethod());

        // tour start date/time
        _state.put(STATE_IS_KEEP_ORIGINAL_TIME, _chkKeepOriginalDateTime.getSelection());

        // description/marker
        _state.put(STATE_IS_INCLUDE_DESCRIPTION, _chkIncludeDescription.getSelection());
        _state.put(STATE_IS_INCLUDE_MARKER_WAYPOINTS, _chkIncludeMarkerWaypoints.getSelection());

        // person
        _state.put(STATE_PERSON_ID, getSelectedPerson().getPersonId());
    }

    @Override
    public void toursAreModified(final ArrayList<TourData> modifiedTours) {

        if ((modifiedTours != null) && (modifiedTours.size() > 0)) {

            // check if it's the correct tour
            if (_tourDataTarget == modifiedTours.get(0)) {

                // update custom tour type id
                final String stateTourTypeSource = getStateTourTypeSource();

                if (stateTourTypeSource.equals(STATE_TYPE_SOURCE_CUSTOM)) {

                    final TourType tourType = _tourDataTarget.getTourType();

                    _tourTypeIdCustom = tourType == null ? //
                            TourDatabase.ENTITY_IS_NOT_SAVED : tourType.getTypeId();
                }

                // tour type or tags can have been changed within this dialog
                updateUITourTypeTags();

                // enable/disable tag/type context menu
                enableControls();
            }
        }
    }

    private void updateUIFromModel() {

        updateUITourTitle();

        if (_canRemoveTimeSlices == false) {

            // select option that time slices cannot be removed

            Util.selectStateInCombo(_state, STATE_EXTRACT_METHOD, ALL_STATES_EXTRACT_METHOD,
                    STATE_EXTRACT_METHOD_KEEP, _cboSplitMethod);

            _cboSplitMethod.setEnabled(false);
        }
    }

    /**
     * update tour title
     */
    private void updateUITourTitle() {

        final String stateTourTitleSource = getStateTourTitleSource();

        String tourTitle = _txtTourTitle.getText();

        if (stateTourTitleSource.equals(STATE_TOUR_TITLE_SOURCE_FROM_TOUR)) {
            tourTitle = _tourTitleFromTour;
        } else if (stateTourTitleSource.equals(STATE_TOUR_TITLE_SOURCE_FROM_MARKER)) {
            tourTitle = _tourTitleFromMarker;
        } else if (stateTourTitleSource.equals(STATE_TOUR_TITLE_SOURCE_CUSTOM)) {
            tourTitle = _tourTitleFromCustom;
        }

        // update ui
        _txtTourTitle.setText(tourTitle);
    }

    private void updateUITourTypeTags() {

        // tour type/tags
        UI.updateUITourType(_tourDataTarget, _lblTourType, true);
        UI.updateUITags(_tourDataTarget, _lblTourTags);

        // reflow layout that the tags are aligned correctly
        _dlgInnerContainer.layout(true);
    }

}