blob: 59b9ca2563621dfa5c69747a564ca13a95d13aef [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2003 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.ui.internal.ide.dialogs;
import java.io.IOException;
import java.util.ArrayList;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.resource.JFaceColors;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyleRange;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.events.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.program.Program;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.internal.ide.AboutItem;
import org.eclipse.ui.internal.ide.IDEWorkbenchMessages;
/**
* Abstract superclass of about dialogs
*/
public abstract class ProductInfoDialog extends Dialog{
private static final String ATT_HTTP = "http://"; //$NON-NLS-1$
private AboutItem item;
private boolean webBrowserOpened;
private String webBrowser = null;
private Cursor handCursor;
private Cursor busyCursor;
private boolean mouseDown = false;
private boolean dragEvent = false;
/**
* Create an instance of this Dialog
*/
public ProductInfoDialog(Shell parentShell) {
super(parentShell);
}
/**
* Adds listeners to the given styled text
*/
protected void addListeners(StyledText styledText) {
styledText.addMouseListener(new MouseAdapter() {
public void mouseDown(MouseEvent e) {
if (e.button != 1) {
return;
}
mouseDown = true;
}
public void mouseUp(MouseEvent e) {
mouseDown = false;
StyledText text = (StyledText)e.widget;
int offset = text.getCaretOffset();
if (dragEvent) {
// don't activate a link during a drag/mouse up operation
dragEvent = false;
if (item != null && item.isLinkAt(offset)) {
text.setCursor(handCursor);
}
} else if (item != null && item.isLinkAt(offset)) {
text.setCursor(busyCursor);
openLink(item.getLinkAt(offset));
StyleRange selectionRange = getCurrentRange(text);
text.setSelectionRange(selectionRange.start, selectionRange.length);
text.setCursor(null);
}
}
});
styledText.addMouseMoveListener(new MouseMoveListener() {
public void mouseMove(MouseEvent e) {
// Do not change cursor on drag events
if (mouseDown) {
if (!dragEvent) {
StyledText text = (StyledText)e.widget;
text.setCursor(null);
}
dragEvent = true;
return;
}
StyledText text = (StyledText)e.widget;
int offset = -1;
try {
offset = text.getOffsetAtLocation(new Point(e.x, e.y));
} catch (IllegalArgumentException ex) {
// leave value as -1
}
if (offset == -1)
text.setCursor(null);
else if (item != null && item.isLinkAt(offset))
text.setCursor(handCursor);
else
text.setCursor(null);
}
});
styledText.addTraverseListener(new TraverseListener() {
public void keyTraversed(TraverseEvent e) {
StyledText text = (StyledText)e.widget;
switch (e.detail) {
case SWT.TRAVERSE_ESCAPE:
e.doit = true;
break;
case SWT.TRAVERSE_TAB_NEXT:
//Previously traverse out in the backward direction?
Point nextSelection = text.getSelection();
int charCount = text.getCharCount();
if ((nextSelection.x == charCount) && (nextSelection.y == charCount)){
text.setSelection(0);
}
StyleRange nextRange = findNextRange(text);
if (nextRange == null) {
// Next time in start at beginning, also used by
// TRAVERSE_TAB_PREVIOUS to indicate we traversed out
// in the forward direction
text.setSelection(0);
e.doit = true;
} else {
text.setSelectionRange(nextRange.start, nextRange.length);
e.doit = true;
e.detail = SWT.TRAVERSE_NONE;
}
break;
case SWT.TRAVERSE_TAB_PREVIOUS:
//Previously traverse out in the forward direction?
Point previousSelection = text.getSelection();
if ((previousSelection.x == 0) && (previousSelection.y == 0))
text.setSelection(text.getCharCount());
StyleRange previousRange = findPreviousRange(text);
if (previousRange == null) {
// Next time in start at the end, also used by
// TRAVERSE_TAB_NEXT to indicate we traversed out
// in the backward direction
text.setSelection(text.getCharCount());
e.doit = true;
}
else {
text.setSelectionRange(previousRange.start, previousRange.length);
e.doit = true;
e.detail = SWT.TRAVERSE_NONE;
}
break;
default:
break;
}
}
});
//Listen for Tab and Space to allow keyboard navigation
styledText.addKeyListener(new KeyAdapter() {
public void keyPressed (KeyEvent event){
StyledText text = (StyledText)event.widget;
if(event.character == ' ' || event.character == SWT.CR){
if(item != null){
//Be sure we are in the selection
int offset = text.getSelection().x + 1;
if (item.isLinkAt(offset)) {
text.setCursor(busyCursor);
openLink(item.getLinkAt(offset));
StyleRange selectionRange = getCurrentRange(text);
text.setSelectionRange(selectionRange.start, selectionRange.length);
text.setCursor(null);
}
}
return;
}
}
});
}
/**
* Gets the busy cursor.
* @return the busy cursor
*/
protected Cursor getBusyCursor() {
return busyCursor;
}
/**
* Sets the busy cursor.
* @param busyCursor the busy cursor
*/
protected void setBusyCursor(Cursor busyCursor) {
this.busyCursor = busyCursor;
}
/**
* Gets the hand cursor.
* @return Returns a hand cursor
*/
protected Cursor getHandCursor() {
return handCursor;
}
/**
* Sets the hand cursor.
* @param handCursor The hand cursor to set
*/
protected void setHandCursor(Cursor handCursor) {
this.handCursor = handCursor;
}
/**
* Gets the about item.
* @return the about item
*/
protected AboutItem getItem() {
return item;
}
/**
* Sets the about item.
* @param item about item
*/
protected void setItem(AboutItem item) {
this.item = item;
}
/**
* Find the range of the current selection.
*/
protected StyleRange getCurrentRange(StyledText text){
StyleRange[] ranges = text.getStyleRanges();
int currentSelectionEnd = text.getSelection().y;
int currentSelectionStart = text.getSelection().x;
for (int i = 0; i < ranges.length; i++) {
if((currentSelectionStart >= ranges[i].start) &&
(currentSelectionEnd <= (ranges[i].start + ranges[i].length))) {
return ranges[i];
}
}
return null;
}
/**
* Find the next range after the current
* selection.
*/
protected StyleRange findNextRange(StyledText text){
StyleRange[] ranges = text.getStyleRanges();
int currentSelectionEnd = text.getSelection().y;
for (int i = 0; i < ranges.length; i++) {
if(ranges[i].start >= currentSelectionEnd)
return ranges[i];
}
return null;
}
/**
* Find the previous range before the current selection.
*/
protected StyleRange findPreviousRange(StyledText text){
StyleRange[] ranges = text.getStyleRanges();
int currentSelectionStart = text.getSelection().x;
for (int i = ranges.length - 1; i > -1; i--) {
if((ranges[i].start + ranges[i].length - 1) < currentSelectionStart)
return ranges[i];
}
return null;
}
//TODO: Move browser support from Help system, remove this method
private Process openWebBrowser(String href) throws IOException{
Process p = null;
if (webBrowser == null) {
try {
webBrowser = "netscape"; //$NON-NLS-1$
p = Runtime.getRuntime().exec(webBrowser + " " + href); //$NON-NLS-1$;
} catch (IOException e) {
p = null;
webBrowser = "mozilla"; //$NON-NLS-1$
}
}
if (p==null) {
try {
p = Runtime.getRuntime().exec(webBrowser + " " + href); //$NON-NLS-1$;
} catch (IOException e) {
p = null;
throw e;
}
}
return p;
}
/**
* display an error message
*/
private void openWebBrowserError(Display display) {
display.asyncExec(new Runnable() {
public void run() {
MessageDialog.openError(getShell(), IDEWorkbenchMessages.getString("ProductInfoDialog.errorTitle"), //$NON-NLS-1$
IDEWorkbenchMessages.getString("ProductInfoDialog.unableToOpenWebBrowser")); //$NON-NLS-1$
}
});
}
/**
* Open a link
*/
protected void openLink(String href) {
// format the href for an html file (file:///<filename.html>
// required for Mac only.
if (href.startsWith("file:")) { //$NON-NLS-1$
href = href.substring(5);
while (href.startsWith("/")) { //$NON-NLS-1$
href = href.substring(1);
}
href = "file:///" + href; //$NON-NLS-1$
}
final String localHref = href;
final Display d = Display.getCurrent();
String platform = SWT.getPlatform();
if ("win32".equals(platform)) { //$NON-NLS-1$
Program.launch(localHref);
} else if ("carbon".equals(platform)) { //$NON-NLS-1$
try {
Runtime.getRuntime().exec("/usr/bin/open " + localHref); //$NON-NLS-1$
} catch (IOException e) {
openWebBrowserError(d);
}
} else {
Thread launcher = new Thread("About Link Launcher") {//$NON-NLS-1$
public void run() {
try {
if (webBrowserOpened) {
Runtime.getRuntime().exec(webBrowser + " -remote openURL(" + localHref + ")"); //$NON-NLS-1$ //$NON-NLS-2$
} else {
Process p = openWebBrowser(localHref);
webBrowserOpened = true;
try {
if (p != null)
p.waitFor();
} catch (InterruptedException e) {
openWebBrowserError(d);
} finally {
webBrowserOpened = false;
}
}
} catch (IOException e) {
openWebBrowserError(d);
}
}
};
launcher.start();
}
}
/**
* Sets the styled text's bold ranges
*/
protected void setBoldRanges(StyledText styledText, int[][] boldRanges) {
for (int i = 0; i < boldRanges.length; i++) {
StyleRange r = new StyleRange(boldRanges[i][0], boldRanges[i][1], null, null, SWT.BOLD);
styledText.setStyleRange(r);
}
}
/**
* Sets the styled text's link (blue) ranges
*/
protected void setLinkRanges(StyledText styledText, int[][] linkRanges) {
Color fg = JFaceColors.getHyperlinkText(styledText.getShell().getDisplay());
for (int i = 0; i < linkRanges.length; i++) {
StyleRange r = new StyleRange(linkRanges[i][0], linkRanges[i][1], fg, null);
styledText.setStyleRange(r);
}
}
/**
* Scan the contents of the about text
*/
protected AboutItem scan(String s) {
int max = s.length();
int i = s.indexOf(ATT_HTTP);
ArrayList linkRanges = new ArrayList();
ArrayList links = new ArrayList();
while (i != -1) {
int start = i;
// look for the first whitespace character
boolean found = false;
i += ATT_HTTP.length();
while (!found && i < max) {
found = Character.isWhitespace(s.charAt(i++));
}
if (i!=max) i--;
linkRanges.add(new int[] {start, i - start});
links.add(s.substring(start, i));
i = s.indexOf(ATT_HTTP, i);
}
return new AboutItem(
s,
(int[][])linkRanges.toArray(new int[linkRanges.size()][2]),
(String[])links.toArray(new String[links.size()]));
}
}