Java tutorial
/******************************************************************************* * Copyright (C) 2005, 2016 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.ui.views; import java.io.File; import java.io.IOException; import java.net.URISyntaxException; import java.time.ZonedDateTime; import java.util.ArrayList; import java.util.Collections; import java.util.Set; import net.tourbook.Messages; import net.tourbook.application.TourbookPlugin; import net.tourbook.chart.SelectionChartXSliderPosition; import net.tourbook.common.UI; import net.tourbook.common.time.TimeTools; import net.tourbook.common.util.CSS; import net.tourbook.common.util.PostSelectionProvider; import net.tourbook.common.util.StatusUtil; import net.tourbook.common.util.Util; import net.tourbook.data.TourData; import net.tourbook.data.TourMarker; import net.tourbook.database.TourDatabase; import net.tourbook.preferences.ITourbookPreferences; import net.tourbook.tour.DialogMarker; import net.tourbook.tour.DialogQuickEdit; import net.tourbook.tour.ITourEventListener; import net.tourbook.tour.SelectionDeletedTours; import net.tourbook.tour.SelectionTourData; import net.tourbook.tour.SelectionTourId; import net.tourbook.tour.SelectionTourIds; import net.tourbook.tour.SelectionTourMarker; import net.tourbook.tour.TourEvent; import net.tourbook.tour.TourEventId; import net.tourbook.tour.TourManager; import net.tourbook.ui.action.ActionTourBlogMarker; import net.tourbook.ui.tourChart.TourChart; import net.tourbook.ui.views.tourCatalog.SelectionTourCatalogView; import net.tourbook.ui.views.tourCatalog.TVICatalogComparedTour; import net.tourbook.ui.views.tourCatalog.TVICatalogRefTourItem; import net.tourbook.ui.views.tourCatalog.TVICompareResultComparedTour; import net.tourbook.web.WEB; import org.eclipse.jface.action.IToolBarManager; import org.eclipse.jface.dialogs.IDialogSettings; import org.eclipse.jface.layout.GridDataFactory; import org.eclipse.jface.layout.GridLayoutFactory; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.preference.PreferenceConverter; import org.eclipse.jface.util.IPropertyChangeListener; import org.eclipse.jface.util.PropertyChangeEvent; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.window.Window; import org.eclipse.osgi.util.NLS; import org.eclipse.swt.SWT; import org.eclipse.swt.SWTError; import org.eclipse.swt.browser.Browser; import org.eclipse.swt.browser.LocationAdapter; import org.eclipse.swt.browser.LocationEvent; import org.eclipse.swt.browser.ProgressAdapter; import org.eclipse.swt.browser.ProgressEvent; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Text; import org.eclipse.ui.IPartListener2; import org.eclipse.ui.ISelectionListener; import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.IWorkbenchPartReference; import org.eclipse.ui.part.PageBook; import org.eclipse.ui.part.ViewPart; public class TourBlogView extends ViewPart { public static final String ID = "net.tourbook.ui.views.TourBlogView"; //$NON-NLS-1$ private static final String TOUR_BLOG_CSS = "/tourbook/resources/tour-blog.css"; //$NON-NLS-1$ static final String STATE_IS_DRAW_MARKER_WITH_DEFAULT_COLOR = "STATE_IS_DRAW_MARKER_WITH_DEFAULT_COLOR"; //$NON-NLS-1$ static final String STATE_IS_SHOW_HIDDEN_MARKER = "STATE_IS_SHOW_HIDDEN_MARKER"; //$NON-NLS-1$ private static final String EXTERNAL_LINK_URL = "http"; //$NON-NLS-1$ private static final String HREF_TOKEN = "#"; //$NON-NLS-1$ private static final String PAGE_ABOUT_BLANK = "about:blank"; //$NON-NLS-1$ /** * This is necessary otherwise XULrunner in Linux do not fire a location change event. */ private static final String HTTP_DUMMY = "http://dummy"; //$NON-NLS-1$ private static final String ACTION_EDIT_TOUR = "EditTour"; //$NON-NLS-1$ private static final String ACTION_EDIT_MARKER = "EditMarker"; //$NON-NLS-1$ private static final String ACTION_HIDE_MARKER = "HideMarker"; //$NON-NLS-1$ private static final String ACTION_OPEN_MARKER = "OpenMarker"; //$NON-NLS-1$ private static final String ACTION_SHOW_MARKER = "ShowMarker"; //$NON-NLS-1$ private static String HREF_EDIT_TOUR; private static String HREF_EDIT_MARKER; private static String HREF_HIDE_MARKER; private static String HREF_OPEN_MARKER; private static String HREF_SHOW_MARKER; static { HREF_EDIT_TOUR = HREF_TOKEN + ACTION_EDIT_TOUR; HREF_EDIT_MARKER = HREF_TOKEN + ACTION_EDIT_MARKER + HREF_TOKEN; HREF_HIDE_MARKER = HREF_TOKEN + ACTION_HIDE_MARKER + HREF_TOKEN; HREF_OPEN_MARKER = HREF_TOKEN + ACTION_OPEN_MARKER + HREF_TOKEN; HREF_SHOW_MARKER = HREF_TOKEN + ACTION_SHOW_MARKER + HREF_TOKEN; } private static final String HREF_MARKER_ITEM = "#MarkerItem"; //$NON-NLS-1$ private final IPreferenceStore _prefStore = TourbookPlugin.getPrefStore(); private final IDialogSettings _state = TourbookPlugin.getState(ID); private PostSelectionProvider _postSelectionProvider; private ISelectionListener _postSelectionListener; private IPropertyChangeListener _prefChangeListener; private ITourEventListener _tourEventListener; private IPartListener2 _partListener; private TourData _tourData; private String _htmlCss; private String _actionEditImageUrl; private String _actionHideMarkerUrl; private String _actionShowMarkerUrl; private String _cssMarkerDefaultColor; private String _cssMarkerDeviceColor; private String _cssMarkerHiddenColor; private boolean _isDrawWithDefaultColor; private boolean _isShowHiddenMarker; private Long _reloadedTourMarkerId; private ActionTourBlogMarker _actionTourBlogMarker; /* * UI controls */ private PageBook _pageBook; private Composite _pageNoBrowser; private Composite _pageNoData; private Composite _pageContent; private Composite _uiParent; private Browser _browser; private TourChart _tourChart; private Text _txtNoBrowser; private void addPartListener() { _partListener = new IPartListener2() { @Override public void partActivated(final IWorkbenchPartReference partRef) { } @Override public void partBroughtToTop(final IWorkbenchPartReference partRef) { } @Override public void partClosed(final IWorkbenchPartReference partRef) { if (partRef.getPart(false) == TourBlogView.this) { saveState(); } } @Override public void partDeactivated(final IWorkbenchPartReference partRef) { } @Override public void partHidden(final IWorkbenchPartReference partRef) { } @Override public void partInputChanged(final IWorkbenchPartReference partRef) { } @Override public void partOpened(final IWorkbenchPartReference partRef) { } @Override public void partVisible(final IWorkbenchPartReference partRef) { } }; getViewSite().getPage().addPartListener(_partListener); } private void addPrefListener() { _prefChangeListener = new IPropertyChangeListener() { @Override public void propertyChange(final PropertyChangeEvent event) { final String property = event.getProperty(); if (property.equals(ITourbookPreferences.MEASUREMENT_SYSTEM)) { // measurement system has changed } else if (property.equals(ITourbookPreferences.GRAPH_MARKER_IS_MODIFIED)) { updateUI(); } } }; _prefStore.addPropertyChangeListener(_prefChangeListener); } /** * listen for events when a tour is selected */ private void addSelectionListener() { _postSelectionListener = new ISelectionListener() { @Override public void selectionChanged(final IWorkbenchPart part, final ISelection selection) { if (part == TourBlogView.this) { return; } onSelectionChanged(selection); } }; getSite().getPage().addPostSelectionListener(_postSelectionListener); } private void addTourEventListener() { _tourEventListener = new ITourEventListener() { @Override public void tourChanged(final IWorkbenchPart part, final TourEventId eventId, final Object eventData) { if (part == TourBlogView.this) { return; } if ((eventId == TourEventId.TOUR_CHANGED) && (eventData instanceof TourEvent)) { final ArrayList<TourData> modifiedTours = ((TourEvent) eventData).getModifiedTours(); if (modifiedTours != null) { // update modified tour final long viewTourId = _tourData.getTourId(); for (final TourData tourData : modifiedTours) { if (tourData.getTourId() == viewTourId) { // get modified tour _tourData = tourData; // removed old tour data from the selection provider _postSelectionProvider.clearSelection(); updateUI(); // nothing more to do, the view contains only one tour return; } } } } else if (eventId == TourEventId.CLEAR_DISPLAYED_TOUR) { clearView(); } else if ((eventId == TourEventId.TOUR_SELECTION) && eventData instanceof ISelection) { onSelectionChanged((ISelection) eventData); } else if (eventId == TourEventId.MARKER_SELECTION) { if (eventData instanceof SelectionTourMarker) { final TourData tourData = ((SelectionTourMarker) eventData).getTourData(); if (tourData != _tourData) { _tourData = tourData; updateUI(); } } } } }; TourManager.getInstance().addTourEventListener(_tourEventListener); } private void clearView() { _tourData = null; // removed old tour data from the selection provider _postSelectionProvider.clearSelection(); showInvalidPage(); } private String create_10_Head() { final String html = ""// //$NON-NLS-1$ + " <meta http-equiv='Content-Type' content='text/html; charset=UTF-8' />\n" //$NON-NLS-1$ + " <meta http-equiv='X-UA-Compatible' content='IE=edge' />\n" //$NON-NLS-1$ + _htmlCss + "\n"; //$NON-NLS-1$ return html; } private String create_20_Body() { final StringBuilder sb = new StringBuilder(); final Set<TourMarker> tourMarkers = _tourData.getTourMarkers(); final ArrayList<TourMarker> allMarker = new ArrayList<TourMarker>(tourMarkers); Collections.sort(allMarker); create_22_BlogHeader(sb); create_24_Tour(sb); for (final TourMarker tourMarker : allMarker) { // check if marker is hidden and should not be displayed if (tourMarker.isMarkerVisible() == false && _isShowHiddenMarker == false) { continue; } sb.append("<div class='blog-item'>"); //$NON-NLS-1$ sb.append("<div class='action-hover-container'>\n"); //$NON-NLS-1$ { create_30_Marker(sb, tourMarker); create_32_MarkerUrl(sb, tourMarker); } sb.append("</div>\n"); //$NON-NLS-1$ sb.append("</div>\n"); //$NON-NLS-1$ } return sb.toString(); } private void create_22_BlogHeader(final StringBuilder sb) { /* * Date/Time header */ final long recordingTime = _tourData.getTourRecordingTime(); final ZonedDateTime dtTourStart = _tourData.getTourStartTime(); final ZonedDateTime dtTourEnd = dtTourStart.plusSeconds(recordingTime); final String date = dtTourStart.format(TimeTools.Formatter_Date_F); final String time = String.format(// "%s - %s", //$NON-NLS-1$ dtTourStart.format(TimeTools.Formatter_Time_M), dtTourEnd.format(TimeTools.Formatter_Time_M)); sb.append("<div class='date'>" + date + "</div>\n"); //$NON-NLS-1$ //$NON-NLS-2$ sb.append("<div class='time'>" + time + "</div>\n"); //$NON-NLS-1$ //$NON-NLS-2$ sb.append("<div style='clear: both;'></div>\n"); //$NON-NLS-1$ } private void create_24_Tour(final StringBuilder sb) { String tourTitle = _tourData.getTourTitle(); final String tourDescription = _tourData.getTourDescription(); final String tourWeather = _tourData.getWeather(); final boolean isDescription = tourDescription.length() > 0; final boolean isTitle = tourTitle.length() > 0; final boolean isWeather = tourWeather.length() > 0; if (isDescription || isTitle || isWeather) { sb.append("<div class='action-hover-container' style='margin-top:30px; margin-bottom: 5px;'>\n"); //$NON-NLS-1$ { sb.append("<div class='blog-item'>"); //$NON-NLS-1$ { /* * Tour title */ if (isTitle == false) { tourTitle = " "; //$NON-NLS-1$ } final String hoverEdit = NLS.bind(Messages.Tour_Blog_Action_EditTour_Tooltip, tourTitle); final String hrefEditTour = HTTP_DUMMY + HREF_EDIT_TOUR; sb.append("" + // //$NON-NLS-1$ ("<div class='action-container'>" //$NON-NLS-1$ + ("<a class='action' style='background: url(" //$NON-NLS-1$ + _actionEditImageUrl + ") no-repeat;'" //$NON-NLS-1$ + (" href='" + hrefEditTour + "'") //$NON-NLS-1$ //$NON-NLS-2$ + (" title='" + hoverEdit + "'") //$NON-NLS-1$ //$NON-NLS-2$ + ">" // //$NON-NLS-1$ + "</a>") // //$NON-NLS-1$ + " </div>\n") //$NON-NLS-1$ + ("<span class='blog-title'>" + tourTitle + "</span>\n")); //$NON-NLS-1$ //$NON-NLS-2$ /* * Description */ if (isDescription) { sb.append( "<p class='description'>" + WEB.convertHTML_LineBreaks(tourDescription) + "</p>\n"); //$NON-NLS-1$ //$NON-NLS-2$ } /* * Weather */ if (isWeather) { if (isDescription) { // write spacer sb.append("<div> </div>");//$NON-NLS-1$ } sb.append("<div class='title'>" + Messages.tour_editor_section_weather + "</div>\n"); //$NON-NLS-1$ //$NON-NLS-2$ sb.append("<p class='description'>" + WEB.convertHTML_LineBreaks(tourWeather) + "</p>\n"); //$NON-NLS-1$ //$NON-NLS-2$ } } sb.append("</div>\n"); //$NON-NLS-1$ } sb.append("</div>\n"); //$NON-NLS-1$ } else { // there is no tour header, set some spacing sb.append("<div style='margin-top:20px;'></div>\n"); //$NON-NLS-1$ } } /** * Label */ private void create_30_Marker(final StringBuilder sb, final TourMarker tourMarker) { final long markerId = tourMarker.getMarkerId(); final String markerLabel = tourMarker.getLabel(); final String hrefOpenMarker = HTTP_DUMMY + HREF_OPEN_MARKER + markerId; final String hrefEditMarker = HTTP_DUMMY + HREF_EDIT_MARKER + markerId; final String hrefHideMarker = HTTP_DUMMY + HREF_HIDE_MARKER + markerId; final String hrefShowMarker = HTTP_DUMMY + HREF_SHOW_MARKER + markerId; final String hoverEditMarker = NLS.bind(Messages.Tour_Blog_Action_EditMarker_Tooltip, markerLabel); final String hoverHideMarker = NLS.bind(Messages.Tour_Blog_Action_HideMarker_Tooltip, markerLabel); final String hoverOpenMarker = NLS.bind(Messages.Tour_Blog_Action_OpenMarker_Tooltip, markerLabel); final String hoverShowMarker = NLS.bind(Messages.Tour_Blog_Action_ShowMarker_Tooltip, markerLabel); /* * get color by priority */ String cssMarkerColor; if (_isDrawWithDefaultColor) { // force default color cssMarkerColor = _cssMarkerDefaultColor; } else if (tourMarker.isMarkerVisible() == false) { // show hidden color cssMarkerColor = _cssMarkerHiddenColor; } else if (tourMarker.isDeviceMarker()) { // show with device color cssMarkerColor = _cssMarkerDeviceColor; } else { cssMarkerColor = _cssMarkerDefaultColor; } final String htmlMarkerStyle = " style='color:" + cssMarkerColor + "'"; //$NON-NLS-1$ //$NON-NLS-2$ final String htmlActionShowHideMarker = tourMarker.isMarkerVisible() // ? createHtml_Action(hrefHideMarker, hoverHideMarker, _actionHideMarkerUrl) : createHtml_Action(hrefShowMarker, hoverShowMarker, _actionShowMarkerUrl); final String htmlActionContainer = "" // //$NON-NLS-1$ + "<div class='action-container'>" //$NON-NLS-1$ + ("<table><tbody><tr>") //$NON-NLS-1$ + ("<td>" + htmlActionShowHideMarker + "</td>") //$NON-NLS-1$ //$NON-NLS-2$ + ("<td>" + createHtml_Action(hrefEditMarker, hoverEditMarker, _actionEditImageUrl) + "</td>") //$NON-NLS-1$ //$NON-NLS-2$ + "</tr></tbody></table>" // //$NON-NLS-1$ + "</div>\n"; //$NON-NLS-1$ sb.append("<div class='title'>\n" //$NON-NLS-1$ + htmlActionContainer + ("<a class='label-text'" //$NON-NLS-1$ + htmlMarkerStyle + (" href='" + hrefOpenMarker + "'") //$NON-NLS-1$ //$NON-NLS-2$ + (" name='" + createHtml_MarkerName(markerId) + "'") //$NON-NLS-1$ //$NON-NLS-2$ + (" title='" + hoverOpenMarker + "'") //$NON-NLS-1$ //$NON-NLS-2$ + ">" + markerLabel + "</a>\n") //$NON-NLS-1$ //$NON-NLS-2$ + "</div>\n"); //$NON-NLS-1$ /* * Description */ final String description = tourMarker.getDescription(); final String descriptionWithLineBreaks = WEB.convertHTML_LineBreaks(description); sb.append("<a class='label-text' href='" + hrefOpenMarker + "' title='" + hoverOpenMarker + "'>\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ sb.append(" <p class='description'" + htmlMarkerStyle + ">" + descriptionWithLineBreaks + "</p>\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ sb.append("</a>\n"); //$NON-NLS-1$ } /** * Url */ private void create_32_MarkerUrl(final StringBuilder sb, final TourMarker tourMarker) { final String urlText = tourMarker.getUrlText(); final String urlAddress = tourMarker.getUrlAddress(); final boolean isText = urlText.length() > 0; final boolean isAddress = urlAddress.length() > 0; if (isText || isAddress) { String linkText; if (isAddress == false) { // only text is in the link -> this is not a internet address but create a link of it linkText = "<a href='" + urlText + "' title='" + urlText + "'>" + urlText + "</a>\n"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ } else if (isText == false) { linkText = "<a href='" + urlAddress + "' title='" + urlAddress + "'>" + urlAddress + "</a>\n"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ } else { linkText = "<a href='" + urlAddress + "' title='" + urlAddress + "'>" + urlText + "</a>\n"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ } sb.append(linkText); } } private void createActions() { _actionTourBlogMarker = new ActionTourBlogMarker(this, _uiParent); fillActionBars(); } private String createHtml_Action(final String hrefMarker, final String hoverMarker, final String backgroundImage) { return "<a class='action'" // //$NON-NLS-1$ + (" style='background-image: url(" + backgroundImage + ");'") //$NON-NLS-1$ //$NON-NLS-2$ + (" href='" + hrefMarker + "'") //$NON-NLS-1$ //$NON-NLS-2$ + (" title='" + hoverMarker + "'") //$NON-NLS-1$ //$NON-NLS-2$ + ">" // //$NON-NLS-1$ + "</a>"; //$NON-NLS-1$ } private String createHtml_MarkerName(final long markerId) { return HREF_MARKER_ITEM + markerId; } @Override public void createPartControl(final Composite parent) { _uiParent = parent; initUI(); createUI(parent); createActions(); addSelectionListener(); addTourEventListener(); addPrefListener(); addPartListener(); showInvalidPage(); // this part is a selection provider getSite().setSelectionProvider(_postSelectionProvider = new PostSelectionProvider(ID)); // show markers from last selection onSelectionChanged(getSite().getWorkbenchWindow().getSelectionService().getSelection()); if (_tourData == null) { showTourFromTourProvider(); } } private void createUI(final Composite parent) { _pageBook = new PageBook(parent, SWT.NONE); GridDataFactory.fillDefaults().grab(true, true).applyTo(_pageBook); _pageNoData = UI.createUI_PageNoData(_pageBook, Messages.UI_Label_no_chart_is_selected); _pageNoBrowser = new Composite(_pageBook, SWT.NONE); GridDataFactory.fillDefaults().grab(true, true).applyTo(_pageNoBrowser); GridLayoutFactory.swtDefaults().numColumns(1).applyTo(_pageNoBrowser); _pageNoBrowser.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_LIST_BACKGROUND)); { _txtNoBrowser = new Text(_pageNoBrowser, SWT.WRAP | SWT.READ_ONLY); GridDataFactory.fillDefaults()// .grab(true, true).align(SWT.FILL, SWT.BEGINNING).applyTo(_txtNoBrowser); _txtNoBrowser.setText(Messages.UI_Label_BrowserCannotBeCreated); } _pageContent = new Composite(_pageBook, SWT.NONE); GridLayoutFactory.fillDefaults().applyTo(_pageContent); { createUI_10_Browser(_pageContent); } } private void createUI_10_Browser(final Composite parent) { try { try { // use default browser _browser = new Browser(parent, SWT.NONE); } catch (final Exception e) { /* * Use mozilla browser, this is necessary for Linux when default browser fails * however the XULrunner needs to be installed. */ _browser = new Browser(parent, SWT.MOZILLA); } GridDataFactory.fillDefaults().grab(true, true).applyTo(_browser); _browser.addLocationListener(new LocationAdapter() { @Override public void changing(final LocationEvent event) { onBrowserLocationChanging(event); } }); _browser.addProgressListener(new ProgressAdapter() { @Override public void completed(final ProgressEvent event) { onBrowserCompleted(event); } }); } catch (final SWTError e) { _txtNoBrowser.setText(NLS.bind(Messages.UI_Label_BrowserCannotBeCreated_Error, e.getMessage())); } } @Override public void dispose() { TourManager.getInstance().removeTourEventListener(_tourEventListener); getSite().getPage().removePostSelectionListener(_postSelectionListener); getViewSite().getPage().removePartListener(_partListener); _prefStore.removePropertyChangeListener(_prefChangeListener); super.dispose(); } private void fillActionBars() { /* * fill view toolbar */ final IToolBarManager tbm = getViewSite().getActionBars().getToolBarManager(); tbm.add(_actionTourBlogMarker); } private void fireMarkerPosition(final StructuredSelection selection) { final Object[] selectedMarker = selection.toArray(); if (selectedMarker.length > 0) { final ArrayList<TourMarker> allTourMarker = new ArrayList<TourMarker>(); for (final Object object : selectedMarker) { allTourMarker.add((TourMarker) object); } _postSelectionProvider.setSelection(new SelectionTourMarker(_tourData, allTourMarker)); } } private void hrefActionEditMarker(final TourMarker selectedTourMarker) { if (_tourData.isManualTour()) { // a manually created tour do not have time slices -> no markers return; } final DialogMarker markerDialog = new DialogMarker(Display.getCurrent().getActiveShell(), _tourData, selectedTourMarker); if (markerDialog.open() == Window.OK) { saveModifiedTour(); } } private void hrefActionEditTour() { if (new DialogQuickEdit(// Display.getCurrent().getActiveShell(), _tourData).open() == Window.OK) { saveModifiedTour(); } } private void hrefActionHideMarker(final TourMarker selectedTourMarker) { selectedTourMarker.setMarkerVisible(false); prepareBrowserReload(selectedTourMarker); saveModifiedTour(); } /** * Fire a selection for the selected marker(s). */ private void hrefActionOpenMarker(final StructuredSelection selection) { // a chart must be available if (_tourChart == null) { final TourChart tourChart = TourManager.getInstance().getActiveTourChart(); if ((tourChart == null) || tourChart.isDisposed()) { fireMarkerPosition(selection); return; } else { _tourChart = tourChart; } } final Object[] selectedMarker = selection.toArray(); if (selectedMarker.length > 1) { // two or more markers are selected _postSelectionProvider.setSelection( new SelectionChartXSliderPosition(_tourChart, ((TourMarker) selectedMarker[0]).getSerieIndex(), ((TourMarker) selectedMarker[selectedMarker.length - 1]).getSerieIndex())); } else if (selectedMarker.length > 0) { // one marker is selected _postSelectionProvider.setSelection( new SelectionChartXSliderPosition(_tourChart, ((TourMarker) selectedMarker[0]).getSerieIndex(), SelectionChartXSliderPosition.IGNORE_SLIDER_POSITION)); } } private void hrefActionShowMarker(final TourMarker selectedTourMarker) { selectedTourMarker.setMarkerVisible(true); prepareBrowserReload(selectedTourMarker); saveModifiedTour(); } private void initUI() { try { /* * load css from file */ final File cssFile = WEB.getFile(TOUR_BLOG_CSS); final String cssContent = Util.readContentFromFile(cssFile.getAbsolutePath()); _htmlCss = "<style>" + cssContent + "</style>"; //$NON-NLS-1$ //$NON-NLS-2$ /* * set image urls */ _actionEditImageUrl = net.tourbook.ui.UI.getIconUrl(Messages.Image__quick_edit); _actionHideMarkerUrl = net.tourbook.ui.UI.getIconUrl(Messages.Image__Remove); _actionShowMarkerUrl = net.tourbook.ui.UI.getIconUrl(Messages.Image__Eye); } catch (final IOException | URISyntaxException e) { StatusUtil.showStatus(e); } } private void onBrowserCompleted(final ProgressEvent event) { if (_reloadedTourMarkerId == null) { return; } // get local copy final long reloadedTourMarkerId = _reloadedTourMarkerId; /* * This must be run async otherwise an endless loop will happen */ _browser.getDisplay().asyncExec(new Runnable() { @Override public void run() { final String href = "location.href='" + createHtml_MarkerName(reloadedTourMarkerId) + "'"; //$NON-NLS-1$ //$NON-NLS-2$ _browser.execute(href); } }); _reloadedTourMarkerId = null; } private void onBrowserLocationChanging(final LocationEvent event) { final String location = event.location; if (location.contains(HREF_MARKER_ITEM)) { /* * Page is reloaded and is scrolled to the tour marker where the last tour marker action * is done. */ _browser.setRedraw(true); return; } final String[] locationParts = location.split(HREF_TOKEN); if (locationParts.length == 3) { // a tour marker id is selected, fire tour marker selection try { /** * Split location<br> * Part 1: location, e.g. "about"<br> * Part 2: action<br> * Part 3: markerID */ final String markerIdText = locationParts[2]; final long markerId = Long.parseLong(markerIdText); // get tour marker by id TourMarker hrefTourMarker = null; for (final TourMarker tourMarker : _tourData.getTourMarkers()) { if (tourMarker.getMarkerId() == markerId) { hrefTourMarker = tourMarker; break; } } final String action = locationParts[1]; if (hrefTourMarker != null) { switch (action) { case ACTION_EDIT_MARKER: hrefActionEditMarker(hrefTourMarker); break; case ACTION_HIDE_MARKER: hrefActionHideMarker(hrefTourMarker); break; case ACTION_OPEN_MARKER: hrefActionOpenMarker(new StructuredSelection(hrefTourMarker)); break; case ACTION_SHOW_MARKER: hrefActionShowMarker(hrefTourMarker); break; } } } catch (final Exception e) { // ignore } } else if (locationParts.length == 2) { final String action = locationParts[1]; switch (action) { case ACTION_EDIT_TOUR: hrefActionEditTour(); break; } } else if (location.startsWith(HTTP_DUMMY) == false && location.startsWith(EXTERNAL_LINK_URL)) { // open link in the external browser // check if this is a valid web url and not any other protocol WEB.openUrl(location); } if (location.equals(PAGE_ABOUT_BLANK) == false) { // about:blank is the initial page event.doit = false; } } private void onSelectionChanged(final ISelection selection) { long tourId = TourDatabase.ENTITY_IS_NOT_SAVED; if (selection instanceof SelectionTourData) { // a tour was selected, get the chart and update the marker viewer final SelectionTourData tourDataSelection = (SelectionTourData) selection; _tourData = tourDataSelection.getTourData(); if (_tourData == null) { _tourChart = null; } else { _tourChart = tourDataSelection.getTourChart(); tourId = _tourData.getTourId(); } } else if (selection instanceof SelectionTourId) { _tourChart = null; tourId = ((SelectionTourId) selection).getTourId(); } else if (selection instanceof SelectionTourIds) { final ArrayList<Long> tourIds = ((SelectionTourIds) selection).getTourIds(); if ((tourIds != null) && (tourIds.size() > 0)) { _tourChart = null; tourId = tourIds.get(0); } } else if (selection instanceof SelectionTourCatalogView) { final SelectionTourCatalogView tourCatalogSelection = (SelectionTourCatalogView) selection; final TVICatalogRefTourItem refItem = tourCatalogSelection.getRefItem(); if (refItem != null) { _tourChart = null; tourId = refItem.getTourId(); } } else if (selection instanceof StructuredSelection) { _tourChart = null; final Object firstElement = ((StructuredSelection) selection).getFirstElement(); if (firstElement instanceof TVICatalogComparedTour) { tourId = ((TVICatalogComparedTour) firstElement).getTourId(); } else if (firstElement instanceof TVICompareResultComparedTour) { tourId = ((TVICompareResultComparedTour) firstElement).getComparedTourData().getTourId(); } } else if (selection instanceof SelectionDeletedTours) { clearView(); } if (tourId >= TourDatabase.ENTITY_IS_NOT_SAVED) { final TourData tourData = TourManager.getInstance().getTourData(tourId); if (tourData != null) { _tourData = tourData; } } final boolean isTourAvailable = (tourId >= 0) && (_tourData != null); if (isTourAvailable && _browser != null) { updateUI(); } } /** * Keeps the current browser scroll position. * * @param tourMarker */ private void prepareBrowserReload(final TourMarker tourMarker) { _reloadedTourMarkerId = tourMarker.getMarkerId(); _browser.setRedraw(false); } private void saveModifiedTour() { /* * Run async because a tour save will fire a tour change event. */ _uiParent.getDisplay().asyncExec(new Runnable() { @Override public void run() { TourManager.saveModifiedTour(_tourData); } }); } private void saveState() { } @Override public void setFocus() { } private void showInvalidPage() { _pageBook.showPage(_browser == null ? _pageNoBrowser : _pageNoData); } private void showTourFromTourProvider() { showInvalidPage(); // a tour is not displayed, find a tour provider which provides a tour Display.getCurrent().asyncExec(new Runnable() { @Override public void run() { // validate widget if (_pageBook.isDisposed()) { return; } /* * check if tour was set from a selection provider */ if (_tourData != null) { return; } final ArrayList<TourData> selectedTours = TourManager.getSelectedTours(); if ((selectedTours != null) && (selectedTours.size() > 0)) { onSelectionChanged(new SelectionTourData(selectedTours.get(0))); } } }); } /** * Update the UI from {@link #_tourData}. */ void updateUI() { if (_tourData == null || _browser == null) { return; } _pageBook.showPage(_pageContent); _isDrawWithDefaultColor = _state.getBoolean(STATE_IS_DRAW_MARKER_WITH_DEFAULT_COLOR); _isShowHiddenMarker = _state.getBoolean(STATE_IS_SHOW_HIDDEN_MARKER); _cssMarkerDefaultColor = CSS .color(PreferenceConverter.getColor(_prefStore, ITourbookPreferences.GRAPH_MARKER_COLOR_DEFAULT)); _cssMarkerHiddenColor = CSS .color(PreferenceConverter.getColor(_prefStore, ITourbookPreferences.GRAPH_MARKER_COLOR_HIDDEN)); _cssMarkerDeviceColor = CSS .color(PreferenceConverter.getColor(_prefStore, ITourbookPreferences.GRAPH_MARKER_COLOR_DEVICE)); // Force Internet Explorer to not use compatibility mode. Internet Explorer believes that websites under // several domains (including "ibm.com") require compatibility mode. You may see your web application run // normally under "localhost", but then fail when hosted under another domain (e.g.: "ibm.com"). // Setting "IE=Edge" will force the latest standards mode for the version of Internet Explorer being used. // This is supported for Internet Explorer 8 and later. You can also ease your testing efforts by forcing // specific versions of Internet Explorer to render using the standards mode of previous versions. This // prevents you from exploiting the latest features, but may offer you compatibility and stability. Lookup // the online documentation for the "X-UA-Compatible" META tag to find which value is right for you. final String html = "" // //$NON-NLS-1$ + "<!DOCTYPE html>\n" // ensure that IE is using the newest version and not the quirk mode //$NON-NLS-1$ + "<html style='height: 100%; width: 100%; margin: 0px; padding: 0px;'>\n" //$NON-NLS-1$ + ("<head>\n" + create_10_Head() + "\n</head>\n") //$NON-NLS-1$ //$NON-NLS-2$ + ("<body>\n" + create_20_Body() + "\n</body>\n") //$NON-NLS-1$ //$NON-NLS-2$ + "</html>"; //$NON-NLS-1$ _browser.setRedraw(true); _browser.setText(html); } }