View | Details | Raw Unified | Return to bug 167941 | Differences between
and this patch

Collapse All | Expand All

(-)src/org/eclipse/mylyn/tasks/ui/AbstractRepositoryConnectorUi.java (+40 lines)
Lines 260-263 Link Here
260
	public boolean forceSubtaskHierarchy() {
260
	public boolean forceSubtaskHierarchy() {
261
		return false;
261
		return false;
262
	}
262
	}
263
264
265
	/**
266
	 * class that used to pass Hyperlink Regular Expression Info
267
	 * @since 2.3
268
	 */
269
	public class HyperlinkRegularExpression {
270
		private String regularExpressionString;
271
		
272
		private int regularExpressionGroup;
273
274
		public HyperlinkRegularExpression(String regularExpressionString, int regularExpressionGroup) {
275
			this.regularExpressionGroup = regularExpressionGroup;
276
			this.regularExpressionString = regularExpressionString;
277
		}
278
279
		public String getRegularExpressionString() {
280
			return regularExpressionString;
281
		}
282
283
		public int getRegularExpressionGroup() {
284
			return regularExpressionGroup;
285
		}
286
	}
287
	
288
	/**
289
	 * Use this method to define the Regular Expression Info
290
	 * 
291
	 * @param forRepositoryTextScanner  <br>true &ensp; -> if you want to color the text <br>
292
	 * 									false &ensp;-> for use in HyperlinkDetector
293
	 * @return Regular Expression Info
294
	 * 
295
	 * @since 2.3
296
	 */
297
	public HyperlinkRegularExpression getHyperlinkRegularExpression(boolean forRepositoryTextScanner) {
298
		if (forRepositoryTextScanner) {
299
			return new HyperlinkRegularExpression("(duplicate of |bug|task)+(\\s#|#|#\\s|\\s|)(\\s\\d+|\\d+)", 3);
300
		}
301
		return new HyperlinkRegularExpression("(duplicate of )?(bug|task)+(\\s#|#|#\\s|\\s|)(\\s\\d+|\\d+)", 4);
302
	}
263
}
303
}
(-)src/org/eclipse/mylyn/tasks/ui/editors/TaskTextViewerConfiguration.java (-24 / +218 lines)
Lines 11-20 Link Here
11
import java.util.HashMap;
11
import java.util.HashMap;
12
import java.util.Iterator;
12
import java.util.Iterator;
13
import java.util.Map;
13
import java.util.Map;
14
import java.util.regex.Matcher;
15
import java.util.regex.Pattern;
14
16
15
import org.eclipse.core.runtime.IAdaptable;
17
import org.eclipse.core.runtime.IAdaptable;
16
import org.eclipse.jface.preference.JFacePreferences;
18
import org.eclipse.jface.preference.JFacePreferences;
17
import org.eclipse.jface.resource.JFaceResources;
19
import org.eclipse.jface.resource.JFaceResources;
20
import org.eclipse.jface.text.BadLocationException;
18
import org.eclipse.jface.text.IDocument;
21
import org.eclipse.jface.text.IDocument;
19
import org.eclipse.jface.text.IRegion;
22
import org.eclipse.jface.text.IRegion;
20
import org.eclipse.jface.text.TextAttribute;
23
import org.eclipse.jface.text.TextAttribute;
Lines 26-34 Link Here
26
import org.eclipse.jface.text.presentation.PresentationReconciler;
29
import org.eclipse.jface.text.presentation.PresentationReconciler;
27
import org.eclipse.jface.text.reconciler.IReconciler;
30
import org.eclipse.jface.text.reconciler.IReconciler;
28
import org.eclipse.jface.text.rules.DefaultDamagerRepairer;
31
import org.eclipse.jface.text.rules.DefaultDamagerRepairer;
32
import org.eclipse.jface.text.rules.ICharacterScanner;
33
import org.eclipse.jface.text.rules.IPredicateRule;
29
import org.eclipse.jface.text.rules.IRule;
34
import org.eclipse.jface.text.rules.IRule;
30
import org.eclipse.jface.text.rules.IToken;
35
import org.eclipse.jface.text.rules.IToken;
31
import org.eclipse.jface.text.rules.MultiLineRule;
32
import org.eclipse.jface.text.rules.RuleBasedScanner;
36
import org.eclipse.jface.text.rules.RuleBasedScanner;
33
import org.eclipse.jface.text.rules.SingleLineRule;
37
import org.eclipse.jface.text.rules.SingleLineRule;
34
import org.eclipse.jface.text.rules.Token;
38
import org.eclipse.jface.text.rules.Token;
Lines 38-49 Link Here
38
import org.eclipse.mylyn.tasks.core.AbstractTask;
42
import org.eclipse.mylyn.tasks.core.AbstractTask;
39
import org.eclipse.mylyn.tasks.core.TaskList;
43
import org.eclipse.mylyn.tasks.core.TaskList;
40
import org.eclipse.mylyn.tasks.core.TaskRepository;
44
import org.eclipse.mylyn.tasks.core.TaskRepository;
45
import org.eclipse.mylyn.tasks.ui.AbstractRepositoryConnectorUi;
41
import org.eclipse.mylyn.tasks.ui.TaskHyperlink;
46
import org.eclipse.mylyn.tasks.ui.TaskHyperlink;
42
import org.eclipse.mylyn.tasks.ui.TasksUiPlugin;
47
import org.eclipse.mylyn.tasks.ui.TasksUiPlugin;
48
import org.eclipse.mylyn.tasks.ui.AbstractRepositoryConnectorUi.HyperlinkRegularExpression;
43
import org.eclipse.swt.SWT;
49
import org.eclipse.swt.SWT;
44
import org.eclipse.swt.custom.StyleRange;
50
import org.eclipse.swt.custom.StyleRange;
45
import org.eclipse.swt.graphics.Color;
51
import org.eclipse.swt.graphics.Color;
46
import org.eclipse.swt.widgets.Control;
52
import org.eclipse.swt.widgets.Control;
53
import org.eclipse.swt.widgets.Display;
47
import org.eclipse.ui.editors.text.EditorsUI;
54
import org.eclipse.ui.editors.text.EditorsUI;
48
import org.eclipse.ui.editors.text.TextSourceViewerConfiguration;
55
import org.eclipse.ui.editors.text.TextSourceViewerConfiguration;
49
56
Lines 61-70 Link Here
61
	private RepositoryTextScanner scanner = null;
68
	private RepositoryTextScanner scanner = null;
62
69
63
	private boolean spellcheck = false;
70
	private boolean spellcheck = false;
71
	
72
	private TaskRepository repository;
64
73
65
	public TaskTextViewerConfiguration(boolean spellchecking) {
74
	public TaskTextViewerConfiguration(boolean spellchecking, TaskRepository repository) {
66
		super(EditorsUI.getPreferenceStore());
75
		super(EditorsUI.getPreferenceStore());
67
		this.spellcheck = spellchecking;
76
		this.spellcheck = spellchecking;
77
		this.repository = repository;
68
	}
78
	}
69
79
70
	@Override
80
	@Override
Lines 81-87 Link Here
81
91
82
	private RepositoryTextScanner getDefaultScanner() {
92
	private RepositoryTextScanner getDefaultScanner() {
83
		if (scanner == null) {
93
		if (scanner == null) {
84
			scanner = new RepositoryTextScanner();
94
			scanner = new RepositoryTextScanner(repository);
85
		}
95
		}
86
		return scanner;
96
		return scanner;
87
	}
97
	}
Lines 199-204 Link Here
199
			super.hideHyperlinks();
209
			super.hideHyperlinks();
200
		}
210
		}
201
211
212
		@Override
202
		public void uninstall() {
213
		public void uninstall() {
203
			// ignore
214
			// ignore
204
			super.uninstall();
215
			super.uninstall();
Lines 206-238 Link Here
206
	}
217
	}
207
218
208
	private static class RepositoryTextScanner extends RuleBasedScanner {
219
	private static class RepositoryTextScanner extends RuleBasedScanner {
220
		private int undefinedTokenLength;
221
222
		private int minundefinedTokenLength;
223
224
		private class TaskRule implements IPredicateRule {
225
226
			/** The token to be returned on success */
227
			protected IToken fToken;
228
229
			private TaskRepository repository;
230
231
			protected IToken fTokenCompleted;
232
233
			protected IToken fTokenNotFound;
234
235
			private Pattern fPattern;
236
237
			private int taskNumberGroupNumber;
238
239
			public TaskRule(TaskRepository repository, String regexp, int taskNumberGroupNumber, IToken token,
240
					IToken tokenCompleted, IToken tokenNotFound) {
241
				this.repository = repository;
242
				fToken = token;
243
				fTokenCompleted = tokenCompleted;
244
				fTokenNotFound = tokenNotFound;
245
				this.taskNumberGroupNumber = taskNumberGroupNumber;
246
				fPattern = Pattern.compile(regexp, Pattern.CASE_INSENSITIVE);
247
			}
248
249
			public IToken evaluate(ICharacterScanner scanner, boolean resume) {
250
251
				String text = ((RepositoryTextScanner) scanner).getLineTextFromPos();
252
				if (text == null) {
253
					((RepositoryTextScanner) scanner).setUndefinedTokenLength(0);
254
					return Token.UNDEFINED;
255
				}
256
				Matcher m = fPattern.matcher(text);
257
				if (m.find()) {
258
					if (m.start() > 0) {
259
						((RepositoryTextScanner) scanner).setUndefinedTokenLength(m.start());
260
						return Token.UNDEFINED;
261
					}
262
					String taskNumber = m.group(taskNumberGroupNumber);
263
					taskNumber = taskNumber.trim();
264
					if (!taskNumber.equals("")) {
265
						((RepositoryTextScanner) scanner).addToOffset(m.end());
266
						TaskList taskList = TasksUiPlugin.getTaskListManager().getTaskList();
267
						String repositoryUrl = repository.getUrl();
268
269
						AbstractTask task = taskList.getTask(repositoryUrl, taskNumber);
270
						if (task == null) {
271
							task = taskList.getTaskByKey(repositoryUrl, taskNumber);
272
						}
273
						if (task != null) {
274
							if (task.isCompleted()) {
275
								return fTokenCompleted;
276
							} else {
277
								return fToken;
278
							}
279
						} else {
280
							return fTokenNotFound;
281
						}
282
					}
283
				}
284
285
				((RepositoryTextScanner) scanner).setUndefinedTokenLength(text.length());
286
				return Token.UNDEFINED;
287
			}
288
289
			public IToken getSuccessToken() {
290
				return fToken;
291
			}
292
293
			public IToken evaluate(ICharacterScanner scanner) {
294
				return evaluate(scanner, false);
295
			}
296
		}
297
298
		private class RegExprRule implements IPredicateRule {
299
300
			/** The token to be returned on success */
301
			protected IToken fToken;
302
303
			private Pattern fPattern;
304
305
			public RegExprRule(String regExpr, IToken token) {
306
				fToken = token;
307
				fPattern = Pattern.compile(regExpr, Pattern.CASE_INSENSITIVE);
308
			}
309
310
			public IToken evaluate(ICharacterScanner scanner, boolean resume) {
311
				String text = ((RepositoryTextScanner) scanner).getLineTextFromPos();
312
				if (text == null) {
313
					((RepositoryTextScanner) scanner).setUndefinedTokenLength(0);
314
					return Token.UNDEFINED;
315
				}
316
				Matcher m = fPattern.matcher(text);
317
				if (m.find()) {
318
					if (m.start() > 0) {
319
						((RepositoryTextScanner) scanner).setUndefinedTokenLength(m.start());
320
						return Token.UNDEFINED;
321
					}
322
					((RepositoryTextScanner) scanner).addToOffset(m.end());
323
					return fToken;
324
				}
325
326
				((RepositoryTextScanner) scanner).setUndefinedTokenLength(text.length());
327
				return Token.UNDEFINED;
328
			}
329
330
			public IToken getSuccessToken() {
331
				return fToken;
332
			}
333
334
			public IToken evaluate(ICharacterScanner scanner) {
335
				return evaluate(scanner, false);
336
			}
209
337
210
		public RepositoryTextScanner() {
338
		}
339
340
		public RepositoryTextScanner(TaskRepository repository) {
341
			IToken urlToken = new Token(new TextAttribute(JFaceResources.getColorRegistry().get(
342
					JFacePreferences.ACTIVE_HYPERLINK_COLOR)));
211
			IToken bugToken = new Token(new TextAttribute(JFaceResources.getColorRegistry().get(
343
			IToken bugToken = new Token(new TextAttribute(JFaceResources.getColorRegistry().get(
212
					JFacePreferences.ACTIVE_HYPERLINK_COLOR)));
344
					JFacePreferences.ACTIVE_HYPERLINK_COLOR)));
345
			IToken bugTokenCompleted = new Token(new TextAttribute(JFaceResources.getColorRegistry().get(
346
					JFacePreferences.ACTIVE_HYPERLINK_COLOR), new Color(Display.getDefault(), 255, 255, 255),
347
					TextAttribute.STRIKETHROUGH));
348
			IToken bugTokenNotFound = new Token(new TextAttribute(JFaceResources.getColorRegistry().get(
349
					JFacePreferences.HYPERLINK_COLOR), new Color(Display.getDefault(), 255, 255, 255),
350
					TextAttribute.STRIKETHROUGH));
213
			IToken quoteToken = new Token(new TextAttribute(TaskListColorsAndFonts.COLOR_QUOTED_TEXT));
351
			IToken quoteToken = new Token(new TextAttribute(TaskListColorsAndFonts.COLOR_QUOTED_TEXT));
214
			IRule[] rules = new IRule[16];
352
215
			rules[0] = (new SingleLineRule("http://", " ", bugToken));
353
			AbstractRepositoryConnectorUi connectorUi = TasksUiPlugin.getConnectorUi(repository.getConnectorKind());
216
			rules[1] = (new SingleLineRule("https://", " ", bugToken));
354
			if (connectorUi != null) {
217
			rules[2] = (new SingleLineRule("bug#", " ", bugToken));
355
				HyperlinkRegularExpression hyperlinkData = connectorUi.getHyperlinkRegularExpression(true);
218
			rules[3] = (new SingleLineRule("bug#", "", bugToken));
356
				IRule[] rules = new IRule[4];
219
			rules[4] = (new SingleLineRule("bug #", "", bugToken));
357
				rules[1] = new RegExprRule("(http://){1}(\\S)*", urlToken);
220
			rules[5] = (new SingleLineRule("http://", "\n", bugToken));
358
				rules[2] = new RegExprRule("(https://){1}(\\S)*", urlToken);
221
			rules[6] = (new SingleLineRule("https://", "\n", bugToken));
359
				rules[3] = (new TaskRule(repository, hyperlinkData.getRegularExpressionString(),
222
			rules[7] = (new SingleLineRule("task#", " ", bugToken));
360
						hyperlinkData.getRegularExpressionGroup(), bugToken, bugTokenCompleted, bugTokenNotFound));
223
			rules[8] = (new MultiLineRule("task#", "\n", bugToken));
361
				SingleLineRule quoteRule = new SingleLineRule(">", null, quoteToken, (char) 0, true);
224
			rules[9] = (new MultiLineRule("task# ", " ", bugToken));
362
				quoteRule.setColumnConstraint(0);
225
			rules[10] = (new SingleLineRule("task #", "\n", bugToken));
363
				rules[0] = quoteRule;
226
			rules[11] = (new SingleLineRule("*** This bug has been ", "***", bugToken));
364
				setRules(rules);
227
			rules[12] = (new SingleLineRule("http://", "", bugToken));
365
			} else {
228
			rules[13] = (new SingleLineRule("https://", "", bugToken));
366
				IRule[] rules = new IRule[3];
229
			rules[14] = (new MultiLineRule("task #", " ", bugToken));
367
				rules[1] = new RegExprRule("(http://){1}(\\S)*", urlToken);
230
			SingleLineRule quoteRule = new SingleLineRule(">", null, quoteToken, (char) 0, true);
368
				rules[2] = new RegExprRule("(https://){1}(\\S)*", urlToken);
231
			quoteRule.setColumnConstraint(0);
369
				SingleLineRule quoteRule = new SingleLineRule(">", null, quoteToken, (char) 0, true);
232
			rules[15] = quoteRule;
370
				quoteRule.setColumnConstraint(0);
233
			setRules(rules);
371
				rules[0] = quoteRule;
372
				setRules(rules);
373
			}
374
		}
375
376
		public void addToOffset(int length) {
377
			fOffset += length;
234
		}
378
		}
235
379
380
		public String getLineTextFromPos() {
381
			try {
382
				int line = fDocument.getLineOfOffset(fOffset);
383
				int start = fDocument.getLineOffset(line);
384
				int length = fDocument.getLineLength(line);
385
386
				String erg = fDocument.get(fOffset, length - (fOffset - start));
387
				return erg;
388
			} catch (BadLocationException ex) {
389
			}
390
			return null;
391
		}
392
393
		/*
394
		 * @see ITokenScanner#nextToken()
395
		 */
396
		public IToken nextToken() {
397
398
			fTokenOffset = fOffset;
399
			fColumn = UNDEFINED;
400
401
			if (fRules != null) {
402
				minundefinedTokenLength = -1;
403
				for (int i = 0; i < fRules.length; i++) {
404
					undefinedTokenLength = 0;
405
					IToken token = (fRules[i].evaluate(this));
406
					if (!token.isUndefined()) {
407
						return token;
408
					} else {
409
						if (undefinedTokenLength > 0
410
								&& (minundefinedTokenLength > undefinedTokenLength || minundefinedTokenLength == -1)) {
411
							minundefinedTokenLength = undefinedTokenLength;
412
						}
413
					}
414
				}
415
				if (minundefinedTokenLength > -1) {
416
					addToOffset(minundefinedTokenLength);
417
					return fDefaultReturnToken;
418
				}
419
420
			}
421
422
			if (read() == EOF)
423
				return Token.EOF;
424
			return fDefaultReturnToken;
425
		}
426
427
		public void setUndefinedTokenLength(int undefinedTokenLength) {
428
			this.undefinedTokenLength = undefinedTokenLength;
429
		}
236
	}
430
	}
237
431
238
}
432
}
(-)src/org/eclipse/mylyn/tasks/ui/editors/TaskFormPage.java (-2 / +2 lines)
Lines 272-278 Link Here
272
		// order for
272
		// order for
273
		// Hyperlink colouring to work. (Presenter needs document object up
273
		// Hyperlink colouring to work. (Presenter needs document object up
274
		// front)
274
		// front)
275
		TaskTextViewerConfiguration repositoryViewerConfig = new TaskTextViewerConfiguration(false);
275
		TaskTextViewerConfiguration repositoryViewerConfig = new TaskTextViewerConfiguration(false, repository);
276
		commentViewer.configure(repositoryViewerConfig);
276
		commentViewer.configure(repositoryViewerConfig);
277
277
278
		IThemeManager themeManager = getSite().getWorkbenchWindow().getWorkbench().getThemeManager();
278
		IThemeManager themeManager = getSite().getWorkbenchWindow().getWorkbench().getThemeManager();
Lines 406-412 Link Here
406
406
407
		// NOTE: Configuration must be applied before the document is set in order for
407
		// NOTE: Configuration must be applied before the document is set in order for
408
		// Hyperlink coloring to work. (Presenter needs document object up front)
408
		// Hyperlink coloring to work. (Presenter needs document object up front)
409
		TextSourceViewerConfiguration viewerConfig = new TaskTextViewerConfiguration(spellCheck);
409
		TextSourceViewerConfiguration viewerConfig = new TaskTextViewerConfiguration(spellCheck, repository);
410
		commentViewer.configure(viewerConfig);
410
		commentViewer.configure(viewerConfig);
411
411
412
		commentViewer.setDocument(document, annotationModel);
412
		commentViewer.setDocument(document, annotationModel);
(-)src/org/eclipse/mylyn/internal/tasks/ui/editors/RichTextAttributeEditor.java (-1 / +1 lines)
Lines 127-133 Link Here
127
127
128
		// NOTE: configuration must be applied before the document is set in order for
128
		// NOTE: configuration must be applied before the document is set in order for
129
		// hyper link coloring to work, the Presenter requires the document object up front
129
		// hyper link coloring to work, the Presenter requires the document object up front
130
		TextSourceViewerConfiguration viewerConfig = new TaskTextViewerConfiguration(spellCheckingEnabled);
130
		TextSourceViewerConfiguration viewerConfig = new TaskTextViewerConfiguration(spellCheckingEnabled, taskRepository);
131
		viewer.configure(viewerConfig);
131
		viewer.configure(viewerConfig);
132
132
133
		Document document = new Document(getValue());
133
		Document document = new Document(getValue());
(-)src/org/eclipse/mylyn/internal/bugzilla/ui/tasklist/BugzillaConnectorUi.java (-7 / +14 lines)
Lines 78-84 Link Here
78
		return legendItems;
78
		return legendItems;
79
	}
79
	}
80
80
81
	private static final int TASK_NUM_GROUP = 3;
81
//	private static final int TASK_NUM_GROUP = 3;
82
82
83
	@Override
83
	@Override
84
	public ImageDescriptor getTaskKindOverlay(AbstractTask task) {
84
	public ImageDescriptor getTaskKindOverlay(AbstractTask task) {
Lines 104-118 Link Here
104
		return super.getTaskKindOverlay(task);
104
		return super.getTaskKindOverlay(task);
105
	}
105
	}
106
106
107
	private static final String regexp = "(duplicate of|bug|task)(\\s#|#|#\\s|\\s|)(\\s\\d+|\\d+)";
107
//	private static final String regexp = "(duplicate of|bug|task)(\\s#|#|#\\s|\\s|)(\\s\\d+|\\d+)";
108
108
109
	private static final Pattern PATTERN = Pattern.compile(regexp, Pattern.CASE_INSENSITIVE);
109
	private Pattern fPattern;
110
110
111
	private int fTaskNumGroup;
112
	
111
	@Override
113
	@Override
112
	public IHyperlink[] findHyperlinks(TaskRepository repository, String text, int lineOffset, int regionOffset) {
114
	public IHyperlink[] findHyperlinks(TaskRepository repository, String text, int lineOffset, int regionOffset) {
113
		ArrayList<IHyperlink> hyperlinksFound = new ArrayList<IHyperlink>();
115
		ArrayList<IHyperlink> hyperlinksFound = new ArrayList<IHyperlink>();
114
116
115
		Matcher m = PATTERN.matcher(text);
117
		if (fPattern == null) {
118
			HyperlinkRegularExpression hyperlinkData = this.getHyperlinkRegularExpression(false);
119
			fPattern = Pattern.compile(hyperlinkData.getRegularExpressionString(), Pattern.CASE_INSENSITIVE);
120
			fTaskNumGroup = hyperlinkData.getRegularExpressionGroup();
121
		}
122
		Matcher m = fPattern.matcher(text);
116
		while (m.find()) {
123
		while (m.find()) {
117
			if (lineOffset >= m.start() && lineOffset <= m.end()) {
124
			if (lineOffset >= m.start() && lineOffset <= m.end()) {
118
				IHyperlink link = extractHyperlink(repository, regionOffset, m);
125
				IHyperlink link = extractHyperlink(repository, regionOffset, m);
Lines 127-138 Link Here
127
		return null;
134
		return null;
128
	}
135
	}
129
136
130
	private static IHyperlink extractHyperlink(TaskRepository repository, int regionOffset, Matcher m) {
137
	private IHyperlink extractHyperlink(TaskRepository repository, int regionOffset, Matcher m) {
131
138
132
		int start = -1;
139
		int start = -1;
133
140
134
		if (m.group().startsWith("duplicate")) {
141
		if (m.group().startsWith("duplicate")) {
135
			start = m.start() + m.group().indexOf(m.group(TASK_NUM_GROUP));
142
			start = m.start() + m.group().indexOf(m.group(fTaskNumGroup));
136
		} else {
143
		} else {
137
			start = m.start();
144
			start = m.start();
138
		}
145
		}
Lines 144-150 Link Here
144
151
145
		try {
152
		try {
146
153
147
			String bugId = m.group(TASK_NUM_GROUP).trim();
154
			String bugId = m.group(fTaskNumGroup).trim();
148
			start += regionOffset;
155
			start += regionOffset;
149
			end += regionOffset;
156
			end += regionOffset;
150
157

Return to bug 167941