Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
View | Details | Raw Unified | Return to bug 244653 | Differences between
and this patch

Collapse All | Expand All

(-)src/org/eclipse/mylyn/internal/tasks/ui/editors/TaskEditorExtensions.java (-2 / +20 lines)
Lines 86-92 Link Here
86
		init();
86
		init();
87
		String id = taskRepository.getProperty(REPOSITORY_PROPERTY_EDITOR_EXTENSION);
87
		String id = taskRepository.getProperty(REPOSITORY_PROPERTY_EDITOR_EXTENSION);
88
		if (id == null) {
88
		if (id == null) {
89
			// TODO 3.1 disabled until bug 244653 is resolved
89
			// TODO 3.1 disabled until bug 253115 is resolved
90
			//id = getDefaultTaskEditorExtensionId(taskRepository);
90
			//id = getDefaultTaskEditorExtensionId(taskRepository);
91
		}
91
		}
92
		return id;
92
		return id;
Lines 96-104 Link Here
96
		repository.setProperty(REPOSITORY_PROPERTY_EDITOR_EXTENSION, editorExtensionId);
96
		repository.setProperty(REPOSITORY_PROPERTY_EDITOR_EXTENSION, editorExtensionId);
97
	}
97
	}
98
98
99
	/**
100
	 * Get the default task editor extension id for the given task repository
101
	 * 
102
	 * @param taskRepository
103
	 * @return the default task editor extension id or null if there is no default
104
	 */
99
	public static String getDefaultTaskEditorExtensionId(TaskRepository taskRepository) {
105
	public static String getDefaultTaskEditorExtensionId(TaskRepository taskRepository) {
106
		return getDefaultTaskEditorExtensionId(taskRepository.getConnectorKind());
107
	}
108
109
	/**
110
	 * Get the default task editor extension id for the given kind of connector
111
	 * 
112
	 * @param connectorKind
113
	 *            the kind of connector
114
	 * 
115
	 * @return the default task editor extension id or null if there is no default
116
	 */
117
	public static String getDefaultTaskEditorExtensionId(String connectorKind) {
100
		init();
118
		init();
101
		return associationByConnectorKind.get(taskRepository.getConnectorKind());
119
		return associationByConnectorKind.get(connectorKind);
102
	}
120
	}
103
121
104
	/**
122
	/**
(-)src/org/eclipse/mylyn/internal/tasks/ui/wizards/EditRepositoryWizard.java (-3 / +6 lines)
Lines 18-23 Link Here
18
import org.eclipse.jface.viewers.IStructuredSelection;
18
import org.eclipse.jface.viewers.IStructuredSelection;
19
import org.eclipse.jface.wizard.Wizard;
19
import org.eclipse.jface.wizard.Wizard;
20
import org.eclipse.mylyn.commons.core.StatusHandler;
20
import org.eclipse.mylyn.commons.core.StatusHandler;
21
import org.eclipse.mylyn.internal.tasks.core.LocalRepositoryConnector;
21
import org.eclipse.mylyn.internal.tasks.ui.RefactorRepositoryUrlOperation;
22
import org.eclipse.mylyn.internal.tasks.ui.RefactorRepositoryUrlOperation;
22
import org.eclipse.mylyn.internal.tasks.ui.TasksUiPlugin;
23
import org.eclipse.mylyn.internal.tasks.ui.TasksUiPlugin;
23
import org.eclipse.mylyn.tasks.core.TaskRepository;
24
import org.eclipse.mylyn.tasks.core.TaskRepository;
Lines 72-78 Link Here
72
73
73
			repository.flushAuthenticationCredentials();
74
			repository.flushAuthenticationCredentials();
74
75
75
			repository.setRepositoryUrl(newUrl);
76
			if (!repository.getConnectorKind().equals(LocalRepositoryConnector.CONNECTOR_KIND)) {
77
				repository.setRepositoryUrl(newUrl);
78
			}
76
			settingsPage.applyTo(repository);
79
			settingsPage.applyTo(repository);
77
			if (oldUrl != null && newUrl != null && !oldUrl.equals(newUrl)) {
80
			if (oldUrl != null && newUrl != null && !oldUrl.equals(newUrl)) {
78
				TasksUiPlugin.getRepositoryManager().notifyRepositoryUrlChanged(repository, oldUrl);
81
				TasksUiPlugin.getRepositoryManager().notifyRepositoryUrlChanged(repository, oldUrl);
Lines 90-97 Link Here
90
	@Override
93
	@Override
91
	public void addPages() {
94
	public void addPages() {
92
		AbstractRepositoryConnectorUi connectorUi = TasksUiPlugin.getConnectorUi(repository.getConnectorKind());
95
		AbstractRepositoryConnectorUi connectorUi = TasksUiPlugin.getConnectorUi(repository.getConnectorKind());
93
		// TODO 3.1 pass repository
96
94
		settingsPage = connectorUi.getSettingsPage(null);
97
		settingsPage = connectorUi.getSettingsPage(repository);
95
		if (settingsPage instanceof AbstractRepositorySettingsPage) {
98
		if (settingsPage instanceof AbstractRepositorySettingsPage) {
96
			((AbstractRepositorySettingsPage) settingsPage).setRepository(repository);
99
			((AbstractRepositorySettingsPage) settingsPage).setRepository(repository);
97
			((AbstractRepositorySettingsPage) settingsPage).setVersion(repository.getVersion());
100
			((AbstractRepositorySettingsPage) settingsPage).setVersion(repository.getVersion());
(-)plugin.xml (+1 lines)
Lines 8-13 Link Here
8
    <extension-point id="duplicateDetectors" name="duplicateDetectors" schema="schema/duplicateDetectors.exsd"/>
8
    <extension-point id="duplicateDetectors" name="duplicateDetectors" schema="schema/duplicateDetectors.exsd"/>
9
    <extension-point id="presentations" name="presentations" schema="schema/presentations.exsd"/>
9
    <extension-point id="presentations" name="presentations" schema="schema/presentations.exsd"/>
10
    <extension-point id="taskEditorExtensions" name="Task Editor Extension" schema="schema/taskEditorExtensions.exsd"/>
10
    <extension-point id="taskEditorExtensions" name="Task Editor Extension" schema="schema/taskEditorExtensions.exsd"/>
11
    <extension-point id="taskRepositoryPageContribution" name="Task Repository Page Contribution" schema="schema/taskRepositoryPageContribution.exsd"/>
11
12
12
    <extension
13
    <extension
13
          point="org.eclipse.mylyn.context.core.bridges">
14
          point="org.eclipse.mylyn.context.core.bridges">
(-)src/org/eclipse/mylyn/tasks/ui/wizards/AbstractRepositorySettingsPage.java (-24 / +196 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
* Copyright (c) 2004, 2008 Tasktop Technologies and others.
2
 * Copyright (c) 2004, 2008 Tasktop Technologies and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 28-34 Link Here
28
import org.eclipse.jface.operation.IRunnableWithProgress;
28
import org.eclipse.jface.operation.IRunnableWithProgress;
29
import org.eclipse.jface.preference.PreferenceDialog;
29
import org.eclipse.jface.preference.PreferenceDialog;
30
import org.eclipse.jface.preference.StringFieldEditor;
30
import org.eclipse.jface.preference.StringFieldEditor;
31
import org.eclipse.jface.wizard.WizardPage;
32
import org.eclipse.mylyn.commons.core.StatusHandler;
31
import org.eclipse.mylyn.commons.core.StatusHandler;
33
import org.eclipse.mylyn.commons.net.AuthenticationCredentials;
32
import org.eclipse.mylyn.commons.net.AuthenticationCredentials;
34
import org.eclipse.mylyn.commons.net.AuthenticationType;
33
import org.eclipse.mylyn.commons.net.AuthenticationType;
Lines 67-73 Link Here
67
import org.eclipse.ui.forms.events.HyperlinkEvent;
66
import org.eclipse.ui.forms.events.HyperlinkEvent;
68
import org.eclipse.ui.forms.events.IHyperlinkListener;
67
import org.eclipse.ui.forms.events.IHyperlinkListener;
69
import org.eclipse.ui.forms.widgets.ExpandableComposite;
68
import org.eclipse.ui.forms.widgets.ExpandableComposite;
70
import org.eclipse.ui.forms.widgets.FormToolkit;
71
import org.eclipse.ui.forms.widgets.Hyperlink;
69
import org.eclipse.ui.forms.widgets.Hyperlink;
72
70
73
/**
71
/**
Lines 78-85 Link Here
78
 * @author Rob Elves
76
 * @author Rob Elves
79
 * @author Steffen Pingel
77
 * @author Steffen Pingel
80
 * @author Frank Becker
78
 * @author Frank Becker
79
 * @author David Green
80
 * @since 2.0
81
 */
81
 */
82
public abstract class AbstractRepositorySettingsPage extends WizardPage implements ITaskRepositoryPage {
82
public abstract class AbstractRepositorySettingsPage extends AbstractTaskRepositoryPage implements ITaskRepositoryPage {
83
83
84
	protected static final String PREFS_PAGE_ID_NET_PROXY = "org.eclipse.ui.net.NetPreferences";
84
	protected static final String PREFS_PAGE_ID_NET_PROXY = "org.eclipse.ui.net.NetPreferences";
85
85
Lines 123-128 Link Here
123
123
124
	protected StringFieldEditor proxyPasswordEditor;
124
	protected StringFieldEditor proxyPasswordEditor;
125
125
126
	// FIXME shadows declaration in super
126
	protected TaskRepository repository;
127
	protected TaskRepository repository;
127
128
128
	private Button validateServerButton;
129
	private Button validateServerButton;
Lines 205-222 Link Here
205
206
206
	private Button disconnectedButton;
207
	private Button disconnectedButton;
207
208
208
	// TODO 3.1 make accessible to subclasses 
209
	private FormToolkit toolkit;
210
211
	/**
209
	/**
212
	 * @since 3.0
210
	 * @since 3.0
213
	 */
211
	 */
214
	public AbstractRepositorySettingsPage(String title, String description, TaskRepository taskRepository) {
212
	public AbstractRepositorySettingsPage(String title, String description, TaskRepository taskRepository) {
215
		super(title);
213
		super(title, description, taskRepository);
216
		this.repository = taskRepository;
214
		repository = taskRepository;
217
		this.connector = TasksUi.getRepositoryManager().getRepositoryConnector(getConnectorKind());
215
		this.connector = TasksUi.getRepositoryManager().getRepositoryConnector(getConnectorKind());
218
		setTitle(title);
219
		setDescription(description);
220
		setNeedsAnonymousLogin(false);
216
		setNeedsAnonymousLogin(false);
221
		setNeedsEncoding(true);
217
		setNeedsEncoding(true);
222
		setNeedsTimeZone(true);
218
		setNeedsTimeZone(true);
Lines 228-247 Link Here
228
	/**
224
	/**
229
	 * @since 3.0
225
	 * @since 3.0
230
	 */
226
	 */
227
	@Override
231
	public abstract String getConnectorKind();
228
	public abstract String getConnectorKind();
232
229
233
	@Override
230
	@Override
234
	public void dispose() {
231
	public void dispose() {
235
		super.dispose();
232
		super.dispose();
236
		if (toolkit != null) {
237
			toolkit.dispose();
238
			toolkit = null;
239
		}
240
	}
233
	}
241
234
242
	public void createControl(Composite parent) {
235
	/**
243
		toolkit = new FormToolkit(TasksUiPlugin.getDefault().getFormColors(parent.getDisplay()));
236
	 * @since 2.0
237
	 */
238
	@Override
239
	protected void createContents(Composite parent) {
240
		createSettingControls(parent);
241
	}
244
242
243
	/**
244
	 * @since 2.0
245
	 */
246
	@Override
247
	protected void createSettingControls(Composite parent) {
245
		if (repository != null) {
248
		if (repository != null) {
246
			originalUrl = repository.getRepositoryUrl();
249
			originalUrl = repository.getRepositoryUrl();
247
			AuthenticationCredentials oldCredentials = repository.getCredentials(AuthenticationType.REPOSITORY);
250
			AuthenticationCredentials oldCredentials = repository.getCredentials(AuthenticationType.REPOSITORY);
Lines 628-633 Link Here
628
631
629
		addStatusSection();
632
		addStatusSection();
630
633
634
		addContributionSection();
635
631
		Composite managementComposite = new Composite(compositeContainer, SWT.NULL);
636
		Composite managementComposite = new Composite(compositeContainer, SWT.NULL);
632
		GridLayout managementLayout = new GridLayout(4, false);
637
		GridLayout managementLayout = new GridLayout(4, false);
633
		managementLayout.marginHeight = 0;
638
		managementLayout.marginHeight = 0;
Lines 701-707 Link Here
701
706
702
		updateHyperlinks();
707
		updateHyperlinks();
703
708
704
		setControl(compositeContainer);
705
	}
709
	}
706
710
707
	private void addProxySection() {
711
	private void addProxySection() {
Lines 855-860 Link Here
855
		proxyExpComposite.setExpanded(!systemProxyButton.getSelection());
859
		proxyExpComposite.setExpanded(!systemProxyButton.getSelection());
856
	}
860
	}
857
861
862
	private void addContributionSection() {
863
		Composite composite = toolkit.createComposite(compositeContainer);
864
		GridDataFactory.fillDefaults().grab(true, false).span(2, SWT.DEFAULT).applyTo(composite);
865
866
		GridLayout layout = new GridLayout(1, false);
867
		layout.marginWidth = 0;
868
		layout.marginTop = -5;
869
		composite.setLayout(layout);
870
871
		composite.setBackground(compositeContainer.getBackground());
872
873
		createContributionControls(composite);
874
	}
875
858
	private void addStatusSection() {
876
	private void addStatusSection() {
859
		ExpandableComposite statusComposite = toolkit.createExpandableComposite(compositeContainer,
877
		ExpandableComposite statusComposite = toolkit.createExpandableComposite(compositeContainer,
860
				ExpandableComposite.COMPACT | ExpandableComposite.TWISTIE | ExpandableComposite.TITLE_BAR);
878
				ExpandableComposite.COMPACT | ExpandableComposite.TWISTIE | ExpandableComposite.TITLE_BAR);
Lines 912-917 Link Here
912
		}
930
		}
913
	}
931
	}
914
932
933
	/**
934
	 * @since 2.0
935
	 */
915
	public void setAnonymous(boolean selected) {
936
	public void setAnonymous(boolean selected) {
916
		if (!needsAnonymousLogin) {
937
		if (!needsAnonymousLogin) {
917
			return;
938
			return;
Lines 937-942 Link Here
937
		}
958
		}
938
	}
959
	}
939
960
961
	/**
962
	 * @since 2.0
963
	 */
940
	public void setHttpAuth(boolean selected) {
964
	public void setHttpAuth(boolean selected) {
941
		if (!needsHttpAuth) {
965
		if (!needsHttpAuth) {
942
			return;
966
			return;
Lines 963-968 Link Here
963
		return httpAuthButton.getSelection();
987
		return httpAuthButton.getSelection();
964
	}
988
	}
965
989
990
	/**
991
	 * @since 2.0
992
	 */
966
	public void setUseDefaultProxy(boolean selected) {
993
	public void setUseDefaultProxy(boolean selected) {
967
		if (!needsProxy) {
994
		if (!needsProxy) {
968
			return;
995
			return;
Lines 985-992 Link Here
985
		setProxyAuth(proxyAuthButton.getSelection());
1012
		setProxyAuth(proxyAuthButton.getSelection());
986
	}
1013
	}
987
1014
1015
	/**
1016
	 * @since 2.0
1017
	 */
988
	public void setProxyAuth(boolean selected) {
1018
	public void setProxyAuth(boolean selected) {
989
990
		proxyAuthButton.setSelection(selected);
1019
		proxyAuthButton.setSelection(selected);
991
		proxyAuthButton.setEnabled(!systemProxyButton.getSelection());
1020
		proxyAuthButton.setEnabled(!systemProxyButton.getSelection());
992
		if (!selected) {
1021
		if (!selected) {
Lines 1039-1046 Link Here
1039
	protected void repositoryTemplateSelected(RepositoryTemplate template) {
1068
	protected void repositoryTemplateSelected(RepositoryTemplate template) {
1040
	}
1069
	}
1041
1070
1071
	/**
1072
	 * @since 2.0
1073
	 */
1042
	protected abstract void createAdditionalControls(Composite parent);
1074
	protected abstract void createAdditionalControls(Composite parent);
1043
1075
1076
	/**
1077
	 * @since 2.0
1078
	 */
1044
	protected abstract boolean isValidUrl(String name);
1079
	protected abstract boolean isValidUrl(String name);
1045
1080
1046
	private void updateHyperlinks() {
1081
	private void updateHyperlinks() {
Lines 1064-1069 Link Here
1064
		}
1099
		}
1065
	}
1100
	}
1066
1101
1102
	/**
1103
	 * @since 2.0
1104
	 */
1067
	public String getRepositoryLabel() {
1105
	public String getRepositoryLabel() {
1068
		return repositoryLabelEditor.getStringValue();
1106
		return repositoryLabelEditor.getStringValue();
1069
	}
1107
	}
Lines 1075-1088 Link Here
1075
		return TaskRepositoryManager.stripSlashes(serverUrlCombo.getText());
1113
		return TaskRepositoryManager.stripSlashes(serverUrlCombo.getText());
1076
	}
1114
	}
1077
1115
1116
	/**
1117
	 * @since 2.0
1118
	 */
1078
	public String getUserName() {
1119
	public String getUserName() {
1079
		return repositoryUserNameEditor.getStringValue();
1120
		return repositoryUserNameEditor.getStringValue();
1080
	}
1121
	}
1081
1122
1123
	/**
1124
	 * @since 2.0
1125
	 */
1082
	public String getPassword() {
1126
	public String getPassword() {
1083
		return repositoryPasswordEditor.getStringValue();
1127
		return repositoryPasswordEditor.getStringValue();
1084
	}
1128
	}
1085
1129
1130
	/**
1131
	 * @since 2.0
1132
	 */
1086
	public String getHttpAuthUserId() {
1133
	public String getHttpAuthUserId() {
1087
		if (needsHttpAuth()) {
1134
		if (needsHttpAuth()) {
1088
			return httpAuthUserNameEditor.getStringValue();
1135
			return httpAuthUserNameEditor.getStringValue();
Lines 1091-1096 Link Here
1091
		}
1138
		}
1092
	}
1139
	}
1093
1140
1141
	/**
1142
	 * @since 2.0
1143
	 */
1094
	public String getHttpAuthPassword() {
1144
	public String getHttpAuthPassword() {
1095
		if (needsHttpAuth()) {
1145
		if (needsHttpAuth()) {
1096
			return httpAuthPasswordEditor.getStringValue();
1146
			return httpAuthPasswordEditor.getStringValue();
Lines 1099-1104 Link Here
1099
		}
1149
		}
1100
	}
1150
	}
1101
1151
1152
	/**
1153
	 * @since 2.0
1154
	 */
1102
	public String getProxyHostname() {
1155
	public String getProxyHostname() {
1103
		if (needsProxy()) {
1156
		if (needsProxy()) {
1104
			return proxyHostnameEditor.getStringValue();
1157
			return proxyHostnameEditor.getStringValue();
Lines 1107-1112 Link Here
1107
		}
1160
		}
1108
	}
1161
	}
1109
1162
1163
	/**
1164
	 * @since 2.0
1165
	 */
1110
	public String getProxyPort() {
1166
	public String getProxyPort() {
1111
		if (needsProxy()) {
1167
		if (needsProxy()) {
1112
			return proxyPortEditor.getStringValue();
1168
			return proxyPortEditor.getStringValue();
Lines 1115-1120 Link Here
1115
		}
1171
		}
1116
	}
1172
	}
1117
1173
1174
	/**
1175
	 * @since 2.0
1176
	 */
1118
	public Boolean getUseDefaultProxy() {
1177
	public Boolean getUseDefaultProxy() {
1119
		if (needsProxy()) {
1178
		if (needsProxy()) {
1120
			return systemProxyButton.getSelection();
1179
			return systemProxyButton.getSelection();
Lines 1123-1128 Link Here
1123
		}
1182
		}
1124
	}
1183
	}
1125
1184
1185
	/**
1186
	 * @since 2.0
1187
	 */
1126
	public String getProxyUserName() {
1188
	public String getProxyUserName() {
1127
		if (needsProxy()) {
1189
		if (needsProxy()) {
1128
			return proxyUserNameEditor.getStringValue();
1190
			return proxyUserNameEditor.getStringValue();
Lines 1131-1136 Link Here
1131
		}
1193
		}
1132
	}
1194
	}
1133
1195
1196
	/**
1197
	 * @since 2.0
1198
	 */
1134
	public String getProxyPassword() {
1199
	public String getProxyPassword() {
1135
		if (needsProxy()) {
1200
		if (needsProxy()) {
1136
			return proxyPasswordEditor.getStringValue();
1201
			return proxyPasswordEditor.getStringValue();
Lines 1139-1148 Link Here
1139
		}
1204
		}
1140
	}
1205
	}
1141
1206
1207
	/**
1208
	 * @since 2.0
1209
	 */
1142
	public void init(IWorkbench workbench) {
1210
	public void init(IWorkbench workbench) {
1143
		// ignore
1211
		// ignore
1144
	}
1212
	}
1145
1213
1214
	/**
1215
	 * @since 2.0
1216
	 */
1146
	public boolean isAnonymousAccess() {
1217
	public boolean isAnonymousAccess() {
1147
		if (anonymousButton != null) {
1218
		if (anonymousButton != null) {
1148
			return anonymousButton.getSelection();
1219
			return anonymousButton.getSelection();
Lines 1191-1197 Link Here
1191
		}
1262
		}
1192
1263
1193
		setErrorMessage(errorMessage);
1264
		setErrorMessage(errorMessage);
1194
		return errorMessage == null;
1265
		return errorMessage == null && super.isPageComplete();
1195
	}
1266
	}
1196
1267
1197
	private String credentialsComplete() {
1268
	private String credentialsComplete() {
Lines 1206-1211 Link Here
1206
				|| repositoryPasswordEditor.getStringValue().trim().equals("");
1277
				|| repositoryPasswordEditor.getStringValue().trim().equals("");
1207
	}
1278
	}
1208
1279
1280
	/**
1281
	 * @since 2.0
1282
	 */
1209
	protected String isUniqueUrl(String urlString) {
1283
	protected String isUniqueUrl(String urlString) {
1210
		if (!urlString.equals(originalUrl)) {
1284
		if (!urlString.equals(originalUrl)) {
1211
			if (repositoryUrls == null) {
1285
			if (repositoryUrls == null) {
Lines 1223-1233 Link Here
1223
		return null;
1297
		return null;
1224
	}
1298
	}
1225
1299
1300
	/**
1301
	 * @since 2.0
1302
	 */
1226
	@Deprecated
1303
	@Deprecated
1227
	public void setRepository(TaskRepository repository) {
1304
	public void setRepository(TaskRepository repository) {
1228
		this.repository = repository;
1305
		this.repository = repository;
1229
	}
1306
	}
1230
1307
1308
	/**
1309
	 * @since 2.0
1310
	 */
1231
	public void setVersion(String previousVersion) {
1311
	public void setVersion(String previousVersion) {
1232
		if (previousVersion == null) {
1312
		if (previousVersion == null) {
1233
			serverVersion = TaskRepository.NO_VERSION_SPECIFIED;
1313
			serverVersion = TaskRepository.NO_VERSION_SPECIFIED;
Lines 1236-1249 Link Here
1236
		}
1316
		}
1237
	}
1317
	}
1238
1318
1319
	/**
1320
	 * @since 2.0
1321
	 */
1239
	public String getVersion() {
1322
	public String getVersion() {
1240
		return serverVersion;
1323
		return serverVersion;
1241
	}
1324
	}
1242
1325
1326
	/**
1327
	 * @since 2.0
1328
	 */
1243
	public TaskRepository getRepository() {
1329
	public TaskRepository getRepository() {
1244
		return repository;
1330
		return repository;
1245
	}
1331
	}
1246
1332
1333
	/**
1334
	 * @since 2.0
1335
	 */
1247
	public String getCharacterEncoding() {
1336
	public String getCharacterEncoding() {
1248
		if (defaultEncoding == null) {
1337
		if (defaultEncoding == null) {
1249
			return null;
1338
			return null;
Lines 1260-1265 Link Here
1260
		}
1349
		}
1261
	}
1350
	}
1262
1351
1352
	/**
1353
	 * @since 2.0
1354
	 */
1263
	public TaskRepository createTaskRepository() {
1355
	public TaskRepository createTaskRepository() {
1264
		TaskRepository repository = new TaskRepository(connector.getConnectorKind(), getRepositoryUrl());
1356
		TaskRepository repository = new TaskRepository(connector.getConnectorKind(), getRepositoryUrl());
1265
		applyTo(repository);
1357
		applyTo(repository);
Lines 1269-1274 Link Here
1269
	/**
1361
	/**
1270
	 * @since 2.2
1362
	 * @since 2.2
1271
	 */
1363
	 */
1364
	@Override
1272
	public void applyTo(TaskRepository repository) {
1365
	public void applyTo(TaskRepository repository) {
1273
		repository.setVersion(getVersion());
1366
		repository.setVersion(getVersion());
1274
		if (needsEncoding()) {
1367
		if (needsEncoding()) {
Lines 1307-1362 Link Here
1307
		}
1400
		}
1308
1401
1309
		repository.setOffline(disconnectedButton.getSelection());
1402
		repository.setOffline(disconnectedButton.getSelection());
1403
1404
		super.applyTo(repository);
1310
	}
1405
	}
1311
1406
1407
	/**
1408
	 * @since 2.0
1409
	 */
1312
	public AbstractRepositoryConnector getConnector() {
1410
	public AbstractRepositoryConnector getConnector() {
1313
		return connector;
1411
		return connector;
1314
	}
1412
	}
1315
1413
1414
	/**
1415
	 * @since 2.0
1416
	 */
1316
	public boolean needsEncoding() {
1417
	public boolean needsEncoding() {
1317
		return needsEncoding;
1418
		return needsEncoding;
1318
	}
1419
	}
1319
1420
1421
	/**
1422
	 * @since 2.0
1423
	 */
1320
	public boolean needsTimeZone() {
1424
	public boolean needsTimeZone() {
1321
		return needsTimeZone;
1425
		return needsTimeZone;
1322
	}
1426
	}
1323
1427
1428
	/**
1429
	 * @since 2.0
1430
	 */
1324
	public boolean needsAnonymousLogin() {
1431
	public boolean needsAnonymousLogin() {
1325
		return needsAnonymousLogin;
1432
		return needsAnonymousLogin;
1326
	}
1433
	}
1327
1434
1435
	/**
1436
	 * @since 2.0
1437
	 */
1328
	public boolean needsAdvanced() {
1438
	public boolean needsAdvanced() {
1329
		return needsAdvanced;
1439
		return needsAdvanced;
1330
	}
1440
	}
1331
1441
1442
	/**
1443
	 * @since 2.0
1444
	 */
1332
	public void setNeedsEncoding(boolean needsEncoding) {
1445
	public void setNeedsEncoding(boolean needsEncoding) {
1333
		this.needsEncoding = needsEncoding;
1446
		this.needsEncoding = needsEncoding;
1334
	}
1447
	}
1335
1448
1449
	/**
1450
	 * @since 2.0
1451
	 */
1336
	public void setNeedsTimeZone(boolean needsTimeZone) {
1452
	public void setNeedsTimeZone(boolean needsTimeZone) {
1337
		this.needsTimeZone = needsTimeZone;
1453
		this.needsTimeZone = needsTimeZone;
1338
	}
1454
	}
1339
1455
1456
	/**
1457
	 * @since 2.0
1458
	 */
1340
	public void setNeedsAdvanced(boolean needsAdvanced) {
1459
	public void setNeedsAdvanced(boolean needsAdvanced) {
1341
		this.needsAdvanced = needsAdvanced;
1460
		this.needsAdvanced = needsAdvanced;
1342
	}
1461
	}
1343
1462
1463
	/**
1464
	 * @since 2.0
1465
	 */
1344
	public boolean needsHttpAuth() {
1466
	public boolean needsHttpAuth() {
1345
		return this.needsHttpAuth;
1467
		return this.needsHttpAuth;
1346
	}
1468
	}
1347
1469
1470
	/**
1471
	 * @since 2.0
1472
	 */
1348
	public void setNeedsHttpAuth(boolean needsHttpAuth) {
1473
	public void setNeedsHttpAuth(boolean needsHttpAuth) {
1349
		this.needsHttpAuth = needsHttpAuth;
1474
		this.needsHttpAuth = needsHttpAuth;
1350
	}
1475
	}
1351
1476
1477
	/**
1478
	 * @since 2.0
1479
	 */
1352
	public void setNeedsProxy(boolean needsProxy) {
1480
	public void setNeedsProxy(boolean needsProxy) {
1353
		this.needsProxy = needsProxy;
1481
		this.needsProxy = needsProxy;
1354
	}
1482
	}
1355
1483
1484
	/**
1485
	 * @since 2.0
1486
	 */
1356
	public boolean needsProxy() {
1487
	public boolean needsProxy() {
1357
		return this.needsProxy;
1488
		return this.needsProxy;
1358
	}
1489
	}
1359
1490
1491
	/**
1492
	 * @since 2.0
1493
	 */
1360
	public void setNeedsAnonymousLogin(boolean needsAnonymousLogin) {
1494
	public void setNeedsAnonymousLogin(boolean needsAnonymousLogin) {
1361
		this.needsAnonymousLogin = needsAnonymousLogin;
1495
		this.needsAnonymousLogin = needsAnonymousLogin;
1362
	}
1496
	}
Lines 1365-1385 Link Here
1365
		this.needsValidation = needsValidation;
1499
		this.needsValidation = needsValidation;
1366
	}
1500
	}
1367
1501
1502
	/**
1503
	 * @since 2.0
1504
	 */
1368
	public boolean needsValidation() {
1505
	public boolean needsValidation() {
1369
		return needsValidation;
1506
		return needsValidation;
1370
	}
1507
	}
1371
1508
1372
	/** for testing */
1509
	/**
1510
	 * Public for testing.
1511
	 * 
1512
	 * @since 2.0
1513
	 */
1373
	public void setUrl(String url) {
1514
	public void setUrl(String url) {
1374
		serverUrlCombo.setText(url);
1515
		serverUrlCombo.setText(url);
1375
	}
1516
	}
1376
1517
1377
	/** for testing */
1518
	/**
1519
	 * Public for testing.
1520
	 * 
1521
	 * @since 2.0
1522
	 */
1378
	public void setUserId(String id) {
1523
	public void setUserId(String id) {
1379
		repositoryUserNameEditor.setStringValue(id);
1524
		repositoryUserNameEditor.setStringValue(id);
1380
	}
1525
	}
1381
1526
1382
	/** for testing */
1527
	/**
1528
	 * Public for testing.
1529
	 * 
1530
	 * @since 2.0
1531
	 */
1383
	public void setPassword(String pass) {
1532
	public void setPassword(String pass) {
1384
		repositoryPasswordEditor.setStringValue(pass);
1533
		repositoryPasswordEditor.setStringValue(pass);
1385
	}
1534
	}
Lines 1413-1418 Link Here
1413
		}
1562
		}
1414
	}
1563
	}
1415
1564
1565
	/**
1566
	 * Validate settings provided by the {@link #getValidator(TaskRepository) validator}, typically the server settings.
1567
	 * 
1568
	 * @since 2.0
1569
	 */
1416
	protected void validateSettings() {
1570
	protected void validateSettings() {
1417
		final Validator validator = getValidator(createTaskRepository());
1571
		final Validator validator = getValidator(createTaskRepository());
1418
		if (validator == null) {
1572
		if (validator == null) {
Lines 1453-1458 Link Here
1453
		getWizard().getContainer().updateButtons();
1607
		getWizard().getContainer().updateButtons();
1454
	}
1608
	}
1455
1609
1610
	/**
1611
	 * @since 3.1
1612
	 */
1613
	@Override
1614
	protected IStatus validate() {
1615
		return null;
1616
	}
1617
1618
	/**
1619
	 * @since 2.0
1620
	 */
1456
	protected void applyValidatorResult(Validator validator) {
1621
	protected void applyValidatorResult(Validator validator) {
1457
		IStatus status = validator.getStatus();
1622
		IStatus status = validator.getStatus();
1458
		String message = status.getMessage();
1623
		String message = status.getMessage();
Lines 1483-1491 Link Here
1483
		setErrorMessage(null);
1648
		setErrorMessage(null);
1484
	}
1649
	}
1485
1650
1651
	/**
1652
	 * @since 2.0
1653
	 */
1486
	protected abstract Validator getValidator(TaskRepository repository);
1654
	protected abstract Validator getValidator(TaskRepository repository);
1487
1655
1488
	// public for testing
1656
	/**
1657
	 * Public for testing.
1658
	 * 
1659
	 * @since 2.0
1660
	 */
1489
	public abstract class Validator {
1661
	public abstract class Validator {
1490
1662
1491
		private IStatus status;
1663
		private IStatus status;
(-)schema/taskRepositoryPageContribution.exsd (+119 lines)
Added Link Here
1
<?xml version='1.0' encoding='UTF-8'?>
2
<!-- Schema file written by PDE -->
3
<schema targetNamespace="org.eclipse.mylyn.tasks.ui" xmlns="http://www.w3.org/2001/XMLSchema">
4
<annotation>
5
      <appinfo>
6
         <meta.schema plugin="org.eclipse.mylyn.tasks.ui" id="taskRepositoryPageContribution" name="Task Repository Page Contribution"/>
7
      </appinfo>
8
      <documentation>
9
         This extension point enables plug-ins to contribute user interface to the task repository settings dialog.
10
      </documentation>
11
   </annotation>
12
13
   <element name="extension">
14
      <annotation>
15
         <appinfo>
16
            <meta.element />
17
         </appinfo>
18
      </annotation>
19
      <complexType>
20
         <sequence>
21
            <element ref="taskRepositoryPageContribution" minOccurs="1" maxOccurs="unbounded"/>
22
         </sequence>
23
         <attribute name="point" type="string" use="required">
24
            <annotation>
25
               <documentation>
26
                  
27
               </documentation>
28
            </annotation>
29
         </attribute>
30
         <attribute name="id" type="string">
31
            <annotation>
32
               <documentation>
33
                  
34
               </documentation>
35
            </annotation>
36
         </attribute>
37
         <attribute name="name" type="string">
38
            <annotation>
39
               <documentation>
40
                  
41
               </documentation>
42
               <appinfo>
43
                  <meta.attribute translatable="true"/>
44
               </appinfo>
45
            </annotation>
46
         </attribute>
47
      </complexType>
48
   </element>
49
50
   <element name="taskRepositoryPageContribution">
51
      <complexType>
52
         <attribute name="class" type="string" use="required">
53
            <annotation>
54
               <documentation>
55
                  
56
               </documentation>
57
               <appinfo>
58
                  <meta.attribute kind="java" basedOn="org.eclipse.mylyn.tasks.ui.wizards.AbstractTaskRepositoryPageContribution:"/>
59
               </appinfo>
60
            </annotation>
61
         </attribute>
62
         <attribute name="connectorKind" type="string">
63
            <annotation>
64
               <documentation>
65
                  the kind of repository connector for which this contributor should be used, or &quot;&quot; (the empty string) if it applies to all connectors
66
               </documentation>
67
            </annotation>
68
         </attribute>
69
         <attribute name="id" type="string" use="required">
70
            <annotation>
71
               <documentation>
72
                  a unique identifier that identifies the contribution
73
               </documentation>
74
            </annotation>
75
         </attribute>
76
      </complexType>
77
   </element>
78
79
   <annotation>
80
      <appinfo>
81
         <meta.section type="since"/>
82
      </appinfo>
83
      <documentation>
84
         3.1
85
      </documentation>
86
   </annotation>
87
88
   <annotation>
89
      <appinfo>
90
         <meta.section type="examples"/>
91
      </appinfo>
92
      <documentation>
93
         &lt;extension
94
          point=&quot;org.eclipse.mylyn.tasks.ui.taskRepositoryPageContribution&quot;&gt;
95
       &lt;taskRepositoryPageContribution class=&quot;org.eclipse.mylyn.internal.tasks.ui.wizards.TaskEditorExtensionSettingsContribution&quot;/&gt;
96
    &lt;/extension&gt;
97
      </documentation>
98
   </annotation>
99
100
   <annotation>
101
      <appinfo>
102
         <meta.section type="apiinfo"/>
103
      </appinfo>
104
      <documentation>
105
         [Enter API information here.]
106
      </documentation>
107
   </annotation>
108
109
   <annotation>
110
      <appinfo>
111
         <meta.section type="implementation"/>
112
      </appinfo>
113
      <documentation>
114
         [Enter information about supplied implementation of this extension point.]
115
      </documentation>
116
   </annotation>
117
118
119
</schema>
(-)src/org/eclipse/mylyn/tasks/ui/wizards/AbstractTaskRepositoryPageContribution.java (+210 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2004, 2007 Mylyn project committers and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *******************************************************************************/
8
9
package org.eclipse.mylyn.tasks.ui.wizards;
10
11
import java.util.List;
12
import java.util.concurrent.CopyOnWriteArrayList;
13
14
import org.eclipse.core.runtime.IProgressMonitor;
15
import org.eclipse.core.runtime.IStatus;
16
import org.eclipse.jface.dialogs.IDialogPage;
17
import org.eclipse.jface.wizard.IWizardPage;
18
import org.eclipse.mylyn.tasks.core.TaskRepository;
19
import org.eclipse.swt.widgets.Composite;
20
21
/**
22
 * A contribution to a {@link ITaskRepositoryPage}, which enables plug-ins to contribute UI to the task repository
23
 * settings.
24
 * 
25
 * subclasses must have a default public constructor.
26
 * 
27
 * @author David Green
28
 * @since 3.1
29
 */
30
public abstract class AbstractTaskRepositoryPageContribution {
31
32
	/**
33
	 * A listener interface that should be implemented by classes wishing to be notified of changes that occur within
34
	 * the contribution.
35
	 * 
36
	 * @since 3.1
37
	 */
38
	public interface Listener {
39
40
		/**
41
		 * Called when the state of the contribution changes such that validation should be performed
42
		 * 
43
		 * @param contribution
44
		 *            the contribution that changed
45
		 * 
46
		 * @see ITaskRepositoryPageContribution#validate(IProgressMonitor)
47
		 */
48
		public void validationRequired(AbstractTaskRepositoryPageContribution contribution);
49
50
	}
51
52
	private final List<Listener> listeners = new CopyOnWriteArrayList<Listener>();
53
54
	private final String title;
55
56
	private final String description;
57
58
	private TaskRepository repository;
59
60
	private String connectorKind;
61
62
	private String id;
63
64
	/**
65
	 * 
66
	 * @param title
67
	 *            the title of the contribution, as displayed to the user, usually used as a section heading
68
	 * @param description
69
	 *            the description of the contribution, as displayed to the user, typically as a tool-tip
70
	 * @since 3.1
71
	 */
72
	protected AbstractTaskRepositoryPageContribution(String title, String description) {
73
		this.title = title;
74
		this.description = description;
75
	}
76
77
	/**
78
	 * Initialize the contribution
79
	 * 
80
	 * @param connectorKind
81
	 *            the kind of connector for which this is a contribution
82
	 * @param repository
83
	 *            the repository for which this contribution was created, or null if the repository is not yet available
84
	 * @since 3.1
85
	 */
86
	public void init(String connectorKind, TaskRepository repository) {
87
		this.connectorKind = connectorKind;
88
		this.repository = repository;
89
	}
90
91
	/**
92
	 * Add a listener to this contribution. The contribution must notify the listener at the appropriate times, for
93
	 * example when a setting has changed in the UI.
94
	 * 
95
	 * @see #removeListener(Listener)
96
	 * @since 3.1
97
	 */
98
	public void addListener(Listener listener) {
99
		listeners.add(listener);
100
	}
101
102
	/**
103
	 * Remove a listener from this contribution.
104
	 * 
105
	 * @see #addListener(Listener)
106
	 * @since 3.1
107
	 */
108
	public void removeListener(Listener listener) {
109
		listeners.remove(listener);
110
	}
111
112
	/**
113
	 * @see IDialogPage#createControl(Composite)
114
	 * @since 3.1
115
	 */
116
	public abstract void createControl(Composite parent);
117
118
	/**
119
	 * @see IDialogPage#getTitle()
120
	 * @since 3.1
121
	 */
122
	public String getTitle() {
123
		return title;
124
	}
125
126
	/**
127
	 * @see IDialogPage#getDescription()
128
	 * @since 3.1
129
	 */
130
	public String getDescription() {
131
		return description;
132
	}
133
134
	/**
135
	 * @see IWizardPage#isPageComplete()
136
	 * @since 3.1
137
	 */
138
	public abstract boolean isPageComplete();
139
140
	/**
141
	 * @see IWizardPage#canFlipToNextPage()
142
	 * @since 3.1
143
	 */
144
	public abstract boolean canFlipToNextPage();
145
146
	/**
147
	 * Validate the settings of the contribution. Contributions should expect this method to be called often and should
148
	 * thus return quickly. Always called on the UI thread.
149
	 * 
150
	 * @return the status (errors) on the contribution, or null if there are none. A MultiStatus should be used to
151
	 *         return multiple error messages or warnings.
152
	 * @since 3.1
153
	 */
154
	public abstract IStatus validate();
155
156
	/**
157
	 * Apply the settings in the contribution to the given repository.
158
	 * 
159
	 * @param repository
160
	 *            the repository to which settings should be applied
161
	 * 
162
	 * @see ITaskRepositoryPage#applyTo(TaskRepository)
163
	 * @since 3.1
164
	 */
165
	public abstract void applyTo(TaskRepository repository);
166
167
	/**
168
	 * Requests a validation.
169
	 * 
170
	 * @see #validate()
171
	 * @since 3.1
172
	 */
173
	protected void fireValidationRequired() {
174
		for (Listener l : listeners) {
175
			l.validationRequired(this);
176
		}
177
	}
178
179
	/**
180
	 * Returns the repository for which this contribution was created, or null if it was created for a new repository.
181
	 * 
182
	 * @since 3.1
183
	 */
184
	protected TaskRepository getRepository() {
185
		return repository;
186
	}
187
188
	/**
189
	 * Returns the kind of connector for which this contribution was created.
190
	 * 
191
	 * @since 3.1
192
	 */
193
	protected String getConnectorKind() {
194
		return connectorKind;
195
	}
196
197
	void setId(String id) {
198
		if (this.id != null) {
199
			throw new IllegalStateException();
200
		}
201
		this.id = id;
202
	}
203
204
	/**
205
	 * the id as it is declared in the contribution extension point
206
	 */
207
	public String getId() {
208
		return id;
209
	}
210
}
(-)src/org/eclipse/mylyn/tasks/ui/wizards/AbstractTaskRepositoryPage.java (+374 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2004, 2008 Mylyn project committers and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *******************************************************************************/
8
9
package org.eclipse.mylyn.tasks.ui.wizards;
10
11
import java.util.ArrayList;
12
import java.util.Collections;
13
import java.util.Comparator;
14
import java.util.List;
15
16
import org.eclipse.core.runtime.IConfigurationElement;
17
import org.eclipse.core.runtime.IExtension;
18
import org.eclipse.core.runtime.IExtensionPoint;
19
import org.eclipse.core.runtime.IExtensionRegistry;
20
import org.eclipse.core.runtime.IProgressMonitor;
21
import org.eclipse.core.runtime.IStatus;
22
import org.eclipse.core.runtime.MultiStatus;
23
import org.eclipse.core.runtime.Platform;
24
import org.eclipse.core.runtime.Status;
25
import org.eclipse.jface.dialogs.IMessageProvider;
26
import org.eclipse.jface.layout.GridDataFactory;
27
import org.eclipse.jface.util.SafeRunnable;
28
import org.eclipse.jface.wizard.WizardPage;
29
import org.eclipse.mylyn.commons.core.StatusHandler;
30
import org.eclipse.mylyn.internal.tasks.ui.TasksUiPlugin;
31
import org.eclipse.mylyn.tasks.core.TaskRepository;
32
import org.eclipse.swt.SWT;
33
import org.eclipse.swt.layout.GridLayout;
34
import org.eclipse.swt.widgets.Composite;
35
import org.eclipse.ui.forms.events.ExpansionAdapter;
36
import org.eclipse.ui.forms.events.ExpansionEvent;
37
import org.eclipse.ui.forms.widgets.ExpandableComposite;
38
import org.eclipse.ui.forms.widgets.FormToolkit;
39
40
/**
41
 * An abstract base class for repository settings page that supports the <code>taskRepositoryPageContribution</code>
42
 * extension point.
43
 * 
44
 * {@link ITaskRepositoryPage} implementations are encouraged to extend {@link AbstractRepositorySettingsPage} if
45
 * possible as it provides a standard UI for managing server settings.
46
 * 
47
 * @see AbstractRepositorySettingsPage
48
 * @author David Green
49
 * @since 3.1
50
 */
51
public abstract class AbstractTaskRepositoryPage extends WizardPage implements ITaskRepositoryPage {
52
53
	private static final String KIND = "connectorKind";
54
55
	private static final String TASK_REPOSITORY_PAGE_CONTRIBUTION = "taskRepositoryPageContribution";
56
57
	private static final String TASK_REPOSITORY_PAGE_CONTRIBUTION_EXTENSION = "org.eclipse.mylyn.tasks.ui.taskRepositoryPageContribution";
58
59
	private static final Comparator<AbstractTaskRepositoryPageContribution> CONTRIBUTION_COMPARATOR = new ContributionComparator();
60
61
	private final TaskRepository repository;
62
63
	private final List<AbstractTaskRepositoryPageContribution> contributions;
64
65
	FormToolkit toolkit;
66
67
	private Composite compositeContainer;
68
69
	private final AbstractTaskRepositoryPageContribution.Listener contributionListener = new AbstractTaskRepositoryPageContribution.Listener() {
70
		public void validationRequired(AbstractTaskRepositoryPageContribution contribution) {
71
			validatePageSettings();
72
		}
73
	};
74
75
	/**
76
	 * @since 3.1
77
	 */
78
	public AbstractTaskRepositoryPage(String title, String description, TaskRepository repository) {
79
		super(title);
80
		if (repository != null && !repository.getConnectorKind().equals(getConnectorKind())) {
81
			throw new IllegalArgumentException("connectorKind of repository does not match connectorKind of page");
82
		}
83
		this.repository = repository;
84
		this.contributions = new ArrayList<AbstractTaskRepositoryPageContribution>();
85
		setTitle(title);
86
		setDescription(description);
87
	}
88
89
	/**
90
	 * Get the kind of connector supported by this page.
91
	 * 
92
	 * @return the kind of connector, never null
93
	 * @since 3.1
94
	 */
95
	public abstract String getConnectorKind();
96
97
	@Override
98
	public void dispose() {
99
		if (toolkit != null) {
100
			toolkit.dispose();
101
			toolkit = null;
102
		}
103
		super.dispose();
104
	}
105
106
	public void createControl(Composite parent) {
107
		toolkit = new FormToolkit(TasksUiPlugin.getDefault().getFormColors(parent.getDisplay()));
108
109
		compositeContainer = new Composite(parent, SWT.NULL);
110
		GridLayout layout = new GridLayout(1, true);
111
		compositeContainer.setLayout(layout);
112
113
		createContents(compositeContainer);
114
115
		setControl(compositeContainer);
116
	}
117
118
	/**
119
	 * Creates the contents of the page. Subclasses may override this method to change where the contributions are
120
	 * added.
121
	 * 
122
	 * @since 3.1
123
	 */
124
	protected void createContents(Composite parent) {
125
		createSettingControls(parent);
126
		createContributionControls(parent);
127
	}
128
129
	/**
130
	 * Creates the controls of this page.
131
	 * 
132
	 * @since 3.1
133
	 */
134
	protected abstract void createSettingControls(Composite parent);
135
136
	@Override
137
	public boolean isPageComplete() {
138
		return super.isPageComplete() && conributionsIsPageComplete();
139
	}
140
141
	@Override
142
	public boolean canFlipToNextPage() {
143
		return super.canFlipToNextPage() && contributionsCanFlipToNextPage();
144
	}
145
146
	private boolean contributionsCanFlipToNextPage() {
147
		for (AbstractTaskRepositoryPageContribution contribution : contributions) {
148
			if (!contribution.canFlipToNextPage()) {
149
				return false;
150
			}
151
		}
152
		return true;
153
	}
154
155
	private boolean conributionsIsPageComplete() {
156
		for (AbstractTaskRepositoryPageContribution contribution : contributions) {
157
			if (!contribution.isPageComplete()) {
158
				return false;
159
			}
160
		}
161
		return true;
162
	}
163
164
	/**
165
	 * Subclasses should only call this method if they override {@link #createContents(Composite)}.
166
	 * 
167
	 * @param parentControl
168
	 *            the container into which the contributions will create their UI
169
	 * @since 3.1
170
	 */
171
	protected void createContributionControls(Composite parentControl) {
172
		contributions.clear();
173
		contributions.addAll(findApplicableContributors());
174
175
		if (!contributions.isEmpty()) {
176
			final List<AbstractTaskRepositoryPageContribution> badContributions = new ArrayList<AbstractTaskRepositoryPageContribution>();
177
			for (final AbstractTaskRepositoryPageContribution contribution : contributions) {
178
				SafeRunnable.run(new SafeRunnable() {
179
					public void run() throws Exception {
180
						contribution.init(getConnectorKind(), repository);
181
					}
182
183
					@Override
184
					public void handleException(Throwable e) {
185
						badContributions.add(contribution);
186
						super.handleException(e);
187
					}
188
				});
189
				contribution.addListener(contributionListener);
190
			}
191
			for (AbstractTaskRepositoryPageContribution badContribution : badContributions) {
192
				contributions.remove(badContribution);
193
			}
194
195
			Collections.sort(contributions, CONTRIBUTION_COMPARATOR);
196
197
			for (AbstractTaskRepositoryPageContribution contribution : contributions) {
198
				ExpandableComposite section = toolkit.createExpandableComposite(parentControl,
199
						ExpandableComposite.COMPACT | ExpandableComposite.TWISTIE | ExpandableComposite.TITLE_BAR);
200
				section.clientVerticalSpacing = 0;
201
				section.setBackground(parentControl.getBackground());
202
				section.setFont(parentControl.getFont());
203
				section.addExpansionListener(new ExpansionAdapter() {
204
					@Override
205
					public void expansionStateChanged(ExpansionEvent e) {
206
						getControl().getShell().pack();
207
					}
208
				});
209
				section.setText(contribution.getTitle());
210
				section.setToolTipText(contribution.getDescription());
211
212
				GridDataFactory.fillDefaults().grab(true, false).applyTo(section);
213
214
				Composite sectionContentsContainer = toolkit.createComposite(section);
215
				sectionContentsContainer.setBackground(parentControl.getBackground());
216
				contribution.createControl(sectionContentsContainer);
217
218
				section.setClient(sectionContentsContainer);
219
			}
220
		}
221
	}
222
223
	/**
224
	 * Validate the settings of this page, not including contributions. This method should not be called directly by
225
	 * page implementations. Always run on a UI thread.
226
	 * 
227
	 * @return the status, or null if there are no messages.
228
	 * @see #validatePageSettings()
229
	 * @since 3.1
230
	 */
231
	protected abstract IStatus validate();
232
233
	/**
234
	 * Overriding methods should call <code>super.applyTo(repository)</code>
235
	 * 
236
	 * @since 3.1
237
	 */
238
	public void applyTo(TaskRepository repository) {
239
		applyContributionSettingsTo(repository);
240
	}
241
242
	private void applyContributionSettingsTo(TaskRepository repository) {
243
		for (AbstractTaskRepositoryPageContribution contribution : contributions) {
244
			contribution.applyTo(repository);
245
		}
246
	}
247
248
	/**
249
	 * Returns a status if there is a message to display, otherwise null.
250
	 */
251
	private IStatus computeValidation() {
252
		MultiStatus cumulativeResult = new MultiStatus(TasksUiPlugin.ID_PLUGIN, IStatus.OK, "Validation failed", null);
253
254
		// validate the page
255
		IStatus result = validate();
256
		if (result != null) {
257
			cumulativeResult.add(result);
258
		}
259
260
		// validate contributions
261
		for (final AbstractTaskRepositoryPageContribution contribution : contributions) {
262
			final IStatus[] contributionResult = new IStatus[1];
263
			SafeRunnable.run(new SafeRunnable() {
264
				public void run() throws Exception {
265
					contributionResult[0] = contribution.validate();
266
				}
267
			});
268
			if (contributionResult[0] != null) {
269
				cumulativeResult.add(contributionResult[0]);
270
			}
271
		}
272
273
		return cumulativeResult;
274
	}
275
276
	/**
277
	 * Validate all settings in the page including contributions. This method should be called whenever a setting is
278
	 * changed on the page.
279
	 * 
280
	 * The results of validation are applied and the buttons of the page are updated.
281
	 * 
282
	 * @see #validate(IProgressMonitor)
283
	 * @see #applyValidationResult(IStatus[])
284
	 */
285
	private void validatePageSettings() {
286
		IStatus validationStatus = computeValidation();
287
		applyValidationResult(validationStatus);
288
		getWizard().getContainer().updateButtons();
289
	}
290
291
	/**
292
	 * Apply the results of validation to the page. The implementation finds the most {@link IStatus#getSeverity()
293
	 * severe} status and {@link #setMessage(String, int) applies the message} to the page.
294
	 * 
295
	 * @param status
296
	 *            the status of the validation, or null
297
	 */
298
	private void applyValidationResult(IStatus status) {
299
		if (status == null || status.isOK()) {
300
			setMessage(null, IMessageProvider.INFORMATION);
301
			setErrorMessage(null);
302
		} else {
303
			// find the most severe status
304
			int messageType;
305
			switch (status.getSeverity()) {
306
			case IStatus.OK:
307
			case IStatus.INFO:
308
				messageType = IMessageProvider.INFORMATION;
309
				break;
310
			case IStatus.WARNING:
311
				messageType = IMessageProvider.WARNING;
312
				break;
313
			case IStatus.ERROR:
314
			default:
315
				messageType = IMessageProvider.ERROR;
316
				break;
317
			}
318
			setErrorMessage(null);
319
			setMessage(status.getMessage(), messageType);
320
		}
321
	}
322
323
	private List<AbstractTaskRepositoryPageContribution> findApplicableContributors() {
324
		List<AbstractTaskRepositoryPageContribution> contributors = new ArrayList<AbstractTaskRepositoryPageContribution>();
325
326
		IExtensionRegistry registry = Platform.getExtensionRegistry();
327
328
		IExtensionPoint editorExtensionPoint = registry.getExtensionPoint(TASK_REPOSITORY_PAGE_CONTRIBUTION_EXTENSION);
329
		IExtension[] editorExtensions = editorExtensionPoint.getExtensions();
330
		for (IExtension extension : editorExtensions) {
331
			IConfigurationElement[] elements = extension.getConfigurationElements();
332
			for (IConfigurationElement element : elements) {
333
				if (element.getName().equals(TASK_REPOSITORY_PAGE_CONTRIBUTION)) {
334
					String kind = element.getAttribute(KIND);
335
					if (kind == null || kind.length() == 0 || kind.equals(getConnectorKind())) {
336
						String id = element.getAttribute("id");
337
						try {
338
							if (id == null || id.length() == 0) {
339
								throw new IllegalStateException(TASK_REPOSITORY_PAGE_CONTRIBUTION + "/@id is required");
340
							}
341
							Object contributor = element.createExecutableExtension("class");
342
							AbstractTaskRepositoryPageContribution pageContributor = (AbstractTaskRepositoryPageContribution) contributor;
343
							pageContributor.setId(id);
344
							contributors.add(pageContributor);
345
						} catch (Exception e) {
346
							StatusHandler.log(new Status(IStatus.ERROR, TasksUiPlugin.ID_PLUGIN, "Could not load "
347
									+ TASK_REPOSITORY_PAGE_CONTRIBUTION + " '" + id + "' from plug-in "
348
									+ element.getContributor().getName(), e));
349
						}
350
					}
351
				}
352
			}
353
		}
354
355
		return contributors;
356
	}
357
358
	private static class ContributionComparator implements Comparator<AbstractTaskRepositoryPageContribution> {
359
360
		public int compare(AbstractTaskRepositoryPageContribution o1, AbstractTaskRepositoryPageContribution o2) {
361
			if (o1 == o2) {
362
				return 0;
363
			}
364
			String s1 = o1.getTitle();
365
			String s2 = o2.getTitle();
366
			int i = s1.compareTo(s2);
367
			if (i == 0) {
368
				i = o1.getId().compareTo(o2.getId());
369
			}
370
			return i;
371
		}
372
373
	}
374
}

Return to bug 244653