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/wizards/EditRepositoryWizard.java (-3 / +5 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
		settingsPage = connectorUi.getSettingsPage(repository);
94
		settingsPage = connectorUi.getSettingsPage(null);
95
		if (settingsPage instanceof AbstractRepositorySettingsPage) {
97
		if (settingsPage instanceof AbstractRepositorySettingsPage) {
96
			((AbstractRepositorySettingsPage) settingsPage).setRepository(repository);
98
			((AbstractRepositorySettingsPage) settingsPage).setRepository(repository);
97
			((AbstractRepositorySettingsPage) settingsPage).setVersion(repository.getVersion());
99
			((AbstractRepositorySettingsPage) settingsPage).setVersion(repository.getVersion());
(-)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
	/**
(-)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 (+214 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2004, 2008 David Green 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
 * Contributors:
9
 *     David Green - initial API and implementation
10
 *******************************************************************************/
11
12
package org.eclipse.mylyn.tasks.ui.wizards;
13
14
import java.util.List;
15
import java.util.concurrent.CopyOnWriteArrayList;
16
17
import org.eclipse.core.runtime.Assert;
18
import org.eclipse.core.runtime.IProgressMonitor;
19
import org.eclipse.core.runtime.IStatus;
20
import org.eclipse.jface.dialogs.IDialogPage;
21
import org.eclipse.jface.wizard.IWizardPage;
22
import org.eclipse.mylyn.tasks.core.TaskRepository;
23
import org.eclipse.swt.widgets.Composite;
24
import org.eclipse.swt.widgets.Control;
25
26
/**
27
 * A contribution to a {@link ITaskRepositoryPage}, which enables plug-ins to contribute UI to the task repository
28
 * settings.
29
 * 
30
 * subclasses must have a default public constructor.
31
 * 
32
 * @author David Green
33
 * @since 3.1
34
 */
35
public abstract class AbstractTaskRepositoryPageContribution {
36
37
	/**
38
	 * A listener interface that should be implemented by classes wishing to be notified of changes that occur within
39
	 * the contribution.
40
	 * 
41
	 * @since 3.1
42
	 */
43
	public interface Listener {
44
45
		/**
46
		 * Called when the state of the contribution changes such that validation should be performed
47
		 * 
48
		 * @param contribution
49
		 *            the contribution that changed
50
		 * 
51
		 * @see ITaskRepositoryPageContribution#validate(IProgressMonitor)
52
		 */
53
		public void validationRequired(AbstractTaskRepositoryPageContribution contribution);
54
55
	}
56
57
	private final List<Listener> listeners = new CopyOnWriteArrayList<Listener>();
58
59
	private final String title;
60
61
	private final String description;
62
63
	private TaskRepository repository;
64
65
	private String connectorKind;
66
67
	private String id;
68
69
	/**
70
	 * 
71
	 * @param title
72
	 *            the title of the contribution, as displayed to the user, usually used as a section heading
73
	 * @param description
74
	 *            the description of the contribution, as displayed to the user, typically as a tool-tip
75
	 * @since 3.1
76
	 */
77
	protected AbstractTaskRepositoryPageContribution(String title, String description) {
78
		this.title = title;
79
		this.description = description;
80
		this.id = "";
81
	}
82
83
	/**
84
	 * Initialize the contribution
85
	 * 
86
	 * @param connectorKind
87
	 *            the kind of connector for which this is a contribution
88
	 * @param repository
89
	 *            the repository for which this contribution was created, or null if the repository is not yet available
90
	 * @since 3.1
91
	 */
92
	public void init(String connectorKind, TaskRepository repository) {
93
		this.connectorKind = connectorKind;
94
		this.repository = repository;
95
	}
96
97
	/**
98
	 * Add a listener to this contribution. The contribution must notify the listener at the appropriate times, for
99
	 * example when a setting has changed in the UI.
100
	 * 
101
	 * @see #removeListener(Listener)
102
	 * @since 3.1
103
	 */
104
	public void addListener(Listener listener) {
105
		listeners.add(listener);
106
	}
107
108
	/**
109
	 * Remove a listener from this contribution.
110
	 * 
111
	 * @see #addListener(Listener)
112
	 * @since 3.1
113
	 */
114
	public void removeListener(Listener listener) {
115
		listeners.remove(listener);
116
	}
117
118
	/**
119
	 * @see IDialogPage#createControl(Composite)
120
	 * @since 3.1
121
	 */
122
	public abstract Control createControl(Composite parent);
123
124
	/**
125
	 * @see IDialogPage#getTitle()
126
	 * @since 3.1
127
	 */
128
	public String getTitle() {
129
		return title;
130
	}
131
132
	/**
133
	 * @see IDialogPage#getDescription()
134
	 * @since 3.1
135
	 */
136
	public String getDescription() {
137
		return description;
138
	}
139
140
	/**
141
	 * @see IWizardPage#isPageComplete()
142
	 * @since 3.1
143
	 */
144
	public abstract boolean isPageComplete();
145
146
	/**
147
	 * @see IWizardPage#canFlipToNextPage()
148
	 * @since 3.1
149
	 */
150
	public abstract boolean canFlipToNextPage();
151
152
	/**
153
	 * Validate the settings of the contribution. Contributions should expect this method to be called often and should
154
	 * thus return quickly. Always called on the UI thread.
155
	 * 
156
	 * @return the status (errors) on the contribution, or null if there are none. A MultiStatus should be used to
157
	 *         return multiple error messages or warnings.
158
	 * @since 3.1
159
	 */
160
	public abstract IStatus validate();
161
162
	/**
163
	 * Apply the settings in the contribution to the given repository.
164
	 * 
165
	 * @param repository
166
	 *            the repository to which settings should be applied
167
	 * 
168
	 * @see ITaskRepositoryPage#applyTo(TaskRepository)
169
	 * @since 3.1
170
	 */
171
	public abstract void applyTo(TaskRepository repository);
172
173
	/**
174
	 * Requests a validation.
175
	 * 
176
	 * @see #validate()
177
	 * @since 3.1
178
	 */
179
	protected void fireValidationRequired() {
180
		for (Listener l : listeners) {
181
			l.validationRequired(this);
182
		}
183
	}
184
185
	/**
186
	 * Returns the repository for which this contribution was created, or null if it was created for a new repository.
187
	 * 
188
	 * @since 3.1
189
	 */
190
	protected final TaskRepository getRepository() {
191
		return repository;
192
	}
193
194
	/**
195
	 * Returns the kind of connector for which this contribution was created.
196
	 * 
197
	 * @since 3.1
198
	 */
199
	protected final String getConnectorKind() {
200
		return connectorKind;
201
	}
202
203
	void setId(String id) {
204
		Assert.isNotNull(id);
205
		this.id = id;
206
	}
207
208
	/**
209
	 * Returns the id as it is declared in the contribution extension point.
210
	 */
211
	public final String getId() {
212
		return id;
213
	}
214
}
(-)src/org/eclipse/mylyn/tasks/ui/wizards/AbstractTaskRepositoryPage.java (+395 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2004, 2008 David Green 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
 * Contributors:
9
 *     David Green - initial API and implementation
10
 *     Tasktop Technologies - improvement
11
 *******************************************************************************/
12
13
package org.eclipse.mylyn.tasks.ui.wizards;
14
15
import java.util.ArrayList;
16
import java.util.Collections;
17
import java.util.Comparator;
18
import java.util.List;
19
20
import org.eclipse.core.runtime.IConfigurationElement;
21
import org.eclipse.core.runtime.IExtension;
22
import org.eclipse.core.runtime.IExtensionPoint;
23
import org.eclipse.core.runtime.IExtensionRegistry;
24
import org.eclipse.core.runtime.IProgressMonitor;
25
import org.eclipse.core.runtime.IStatus;
26
import org.eclipse.core.runtime.MultiStatus;
27
import org.eclipse.core.runtime.Platform;
28
import org.eclipse.core.runtime.Status;
29
import org.eclipse.jface.dialogs.IMessageProvider;
30
import org.eclipse.jface.layout.GridDataFactory;
31
import org.eclipse.jface.util.SafeRunnable;
32
import org.eclipse.jface.wizard.WizardPage;
33
import org.eclipse.mylyn.commons.core.StatusHandler;
34
import org.eclipse.mylyn.internal.tasks.ui.TasksUiPlugin;
35
import org.eclipse.mylyn.tasks.core.TaskRepository;
36
import org.eclipse.swt.SWT;
37
import org.eclipse.swt.layout.GridLayout;
38
import org.eclipse.swt.widgets.Composite;
39
import org.eclipse.ui.forms.events.ExpansionAdapter;
40
import org.eclipse.ui.forms.events.ExpansionEvent;
41
import org.eclipse.ui.forms.widgets.ExpandableComposite;
42
import org.eclipse.ui.forms.widgets.FormToolkit;
43
44
/**
45
 * An abstract base class for repository settings page that supports the <code>taskRepositoryPageContribution</code>
46
 * extension point.
47
 * 
48
 * {@link ITaskRepositoryPage} implementations are encouraged to extend {@link AbstractRepositorySettingsPage} if
49
 * possible as it provides a standard UI for managing server settings.
50
 * 
51
 * @see AbstractRepositorySettingsPage
52
 * @author David Green
53
 * @author Steffen Pingel
54
 * @since 3.1
55
 */
56
public abstract class AbstractTaskRepositoryPage extends WizardPage implements ITaskRepositoryPage {
57
58
	private static final String KIND = "connectorKind";
59
60
	private static final String TASK_REPOSITORY_PAGE_CONTRIBUTION = "taskRepositoryPageContribution";
61
62
	private static final String TASK_REPOSITORY_PAGE_CONTRIBUTION_EXTENSION = "org.eclipse.mylyn.tasks.ui.taskRepositoryPageContribution";
63
64
	private static final Comparator<AbstractTaskRepositoryPageContribution> CONTRIBUTION_COMPARATOR = new ContributionComparator();
65
66
	private final TaskRepository repository;
67
68
	private final List<AbstractTaskRepositoryPageContribution> contributions;
69
70
	FormToolkit toolkit;
71
72
	private Composite compositeContainer;
73
74
	private final AbstractTaskRepositoryPageContribution.Listener contributionListener = new AbstractTaskRepositoryPageContribution.Listener() {
75
		public void validationRequired(AbstractTaskRepositoryPageContribution contribution) {
76
			validatePageSettings();
77
		}
78
	};
79
80
	/**
81
	 * @since 3.1
82
	 */
83
	public AbstractTaskRepositoryPage(String title, String description, TaskRepository repository) {
84
		super(title);
85
		if (repository != null && !repository.getConnectorKind().equals(getConnectorKind())) {
86
			throw new IllegalArgumentException("connectorKind of repository does not match connectorKind of page");
87
		}
88
		this.repository = repository;
89
		this.contributions = new ArrayList<AbstractTaskRepositoryPageContribution>();
90
		setTitle(title);
91
		setDescription(description);
92
	}
93
94
	/**
95
	 * Get the kind of connector supported by this page.
96
	 * 
97
	 * @return the kind of connector, never null
98
	 * @since 3.1
99
	 */
100
	public abstract String getConnectorKind();
101
102
	@Override
103
	public void dispose() {
104
		if (toolkit != null) {
105
			toolkit.dispose();
106
			toolkit = null;
107
		}
108
		super.dispose();
109
	}
110
111
	public void createControl(Composite parent) {
112
		toolkit = new FormToolkit(TasksUiPlugin.getDefault().getFormColors(parent.getDisplay()));
113
114
		compositeContainer = new Composite(parent, SWT.NULL);
115
		GridLayout layout = new GridLayout(1, true);
116
		compositeContainer.setLayout(layout);
117
118
		createContents(compositeContainer);
119
120
		setControl(compositeContainer);
121
	}
122
123
	/**
124
	 * Creates the contents of the page. Subclasses may override this method to change where the contributions are
125
	 * added.
126
	 * 
127
	 * @since 3.1
128
	 */
129
	protected void createContents(Composite parent) {
130
		createSettingControls(parent);
131
		createContributionControls(parent);
132
	}
133
134
	/**
135
	 * Creates the controls of this page.
136
	 * 
137
	 * @since 3.1
138
	 */
139
	protected abstract void createSettingControls(Composite parent);
140
141
	@Override
142
	public boolean isPageComplete() {
143
		return super.isPageComplete() && conributionsIsPageComplete();
144
	}
145
146
	@Override
147
	public boolean canFlipToNextPage() {
148
		return super.canFlipToNextPage() && contributionsCanFlipToNextPage();
149
	}
150
151
	private boolean contributionsCanFlipToNextPage() {
152
		for (AbstractTaskRepositoryPageContribution contribution : contributions) {
153
			if (!contribution.canFlipToNextPage()) {
154
				return false;
155
			}
156
		}
157
		return true;
158
	}
159
160
	private boolean conributionsIsPageComplete() {
161
		for (AbstractTaskRepositoryPageContribution contribution : contributions) {
162
			if (!contribution.isPageComplete()) {
163
				return false;
164
			}
165
		}
166
		return true;
167
	}
168
169
	/**
170
	 * Subclasses should only call this method if they override {@link #createContents(Composite)}.
171
	 * 
172
	 * @param parentControl
173
	 *            the container into which the contributions will create their UI
174
	 * @since 3.1
175
	 */
176
	protected void createContributionControls(final Composite parentControl) {
177
		contributions.clear();
178
		contributions.addAll(findApplicableContributors());
179
180
		if (!contributions.isEmpty()) {
181
			final List<AbstractTaskRepositoryPageContribution> badContributions = new ArrayList<AbstractTaskRepositoryPageContribution>();
182
			for (final AbstractTaskRepositoryPageContribution contribution : contributions) {
183
				SafeRunnable.run(new SafeRunnable() {
184
					public void run() throws Exception {
185
						contribution.init(getConnectorKind(), repository);
186
						contribution.addListener(contributionListener);
187
					}
188
189
					@Override
190
					public void handleException(Throwable e) {
191
						badContributions.add(contribution);
192
						StatusHandler.log(new Status(IStatus.ERROR, TasksUiPlugin.ID_PLUGIN,
193
								"Problems occured when initializing contribution \"" + contribution.getId() + "\"", e));
194
					}
195
				});
196
			}
197
			contributions.removeAll(badContributions);
198
199
			Collections.sort(contributions, CONTRIBUTION_COMPARATOR);
200
201
			for (final AbstractTaskRepositoryPageContribution contribution : contributions) {
202
				final ExpandableComposite section = toolkit.createExpandableComposite(parentControl,
203
						ExpandableComposite.COMPACT | ExpandableComposite.TWISTIE | ExpandableComposite.TITLE_BAR);
204
				section.clientVerticalSpacing = 0;
205
				section.setBackground(parentControl.getBackground());
206
				section.setFont(parentControl.getFont());
207
				section.addExpansionListener(new ExpansionAdapter() {
208
					@Override
209
					public void expansionStateChanged(ExpansionEvent e) {
210
						getControl().getShell().pack();
211
					}
212
				});
213
				section.setText(contribution.getTitle());
214
				section.setToolTipText(contribution.getDescription());
215
216
				GridDataFactory.fillDefaults().grab(true, false).applyTo(section);
217
218
				SafeRunnable.run(new SafeRunnable() {
219
					public void run() throws Exception {
220
						Composite sectionContentsContainer = toolkit.createComposite(section);
221
						sectionContentsContainer.setBackground(parentControl.getBackground());
222
						contribution.createControl(sectionContentsContainer);
223
						section.setClient(sectionContentsContainer);
224
					}
225
226
					@Override
227
					public void handleException(Throwable e) {
228
						section.dispose();
229
						StatusHandler.log(new Status(IStatus.ERROR, TasksUiPlugin.ID_PLUGIN,
230
								"Problems occured when creating control for contribution \"" + contribution.getId()
231
										+ "\"", e));
232
					}
233
				});
234
			}
235
		}
236
	}
237
238
	/**
239
	 * Validate the settings of this page, not including contributions. This method should not be called directly by
240
	 * page implementations. Always run on a UI thread.
241
	 * 
242
	 * @return the status, or null if there are no messages.
243
	 * @see #validatePageSettings()
244
	 * @since 3.1
245
	 */
246
	protected abstract IStatus validate();
247
248
	/**
249
	 * Overriding methods should call <code>super.applyTo(repository)</code>
250
	 * 
251
	 * @since 3.1
252
	 */
253
	public void applyTo(TaskRepository repository) {
254
		applyContributionSettingsTo(repository);
255
	}
256
257
	private void applyContributionSettingsTo(TaskRepository repository) {
258
		for (AbstractTaskRepositoryPageContribution contribution : contributions) {
259
			contribution.applyTo(repository);
260
		}
261
	}
262
263
	/**
264
	 * Returns a status if there is a message to display, otherwise null.
265
	 */
266
	private IStatus computeValidation() {
267
		final MultiStatus cumulativeResult = new MultiStatus(TasksUiPlugin.ID_PLUGIN, IStatus.OK, "Validation failed",
268
				null);
269
270
		// validate the page
271
		IStatus result = validate();
272
		if (result != null) {
273
			cumulativeResult.add(result);
274
		}
275
276
		// validate contributions
277
		for (final AbstractTaskRepositoryPageContribution contribution : contributions) {
278
			SafeRunnable.run(new SafeRunnable() {
279
				public void run() throws Exception {
280
					IStatus result = contribution.validate();
281
					if (result != null) {
282
						cumulativeResult.add(result);
283
					}
284
				}
285
286
				@Override
287
				public void handleException(Throwable e) {
288
					StatusHandler.log(new Status(IStatus.ERROR, TasksUiPlugin.ID_PLUGIN,
289
							"Problems occured when validating contribution \"" + contribution.getId() + "\"", e));
290
				}
291
			});
292
		}
293
294
		return cumulativeResult;
295
	}
296
297
	/**
298
	 * Validate all settings in the page including contributions. This method should be called whenever a setting is
299
	 * changed on the page.
300
	 * 
301
	 * The results of validation are applied and the buttons of the page are updated.
302
	 * 
303
	 * @see #validate(IProgressMonitor)
304
	 * @see #applyValidationResult(IStatus[])
305
	 */
306
	private void validatePageSettings() {
307
		IStatus validationStatus = computeValidation();
308
		applyValidationResult(validationStatus);
309
		getWizard().getContainer().updateButtons();
310
	}
311
312
	/**
313
	 * Apply the results of validation to the page. The implementation finds the most {@link IStatus#getSeverity()
314
	 * severe} status and {@link #setMessage(String, int) applies the message} to the page.
315
	 * 
316
	 * @param status
317
	 *            the status of the validation, or null
318
	 */
319
	private void applyValidationResult(IStatus status) {
320
		if (status == null || status.isOK()) {
321
			setMessage(null, IMessageProvider.INFORMATION);
322
			setErrorMessage(null);
323
		} else {
324
			// find the most severe status
325
			int messageType;
326
			switch (status.getSeverity()) {
327
			case IStatus.OK:
328
			case IStatus.INFO:
329
				messageType = IMessageProvider.INFORMATION;
330
				break;
331
			case IStatus.WARNING:
332
				messageType = IMessageProvider.WARNING;
333
				break;
334
			case IStatus.ERROR:
335
			default:
336
				messageType = IMessageProvider.ERROR;
337
				break;
338
			}
339
			setErrorMessage(null);
340
			setMessage(status.getMessage(), messageType);
341
		}
342
	}
343
344
	private List<AbstractTaskRepositoryPageContribution> findApplicableContributors() {
345
		List<AbstractTaskRepositoryPageContribution> contributors = new ArrayList<AbstractTaskRepositoryPageContribution>();
346
347
		IExtensionRegistry registry = Platform.getExtensionRegistry();
348
349
		IExtensionPoint editorExtensionPoint = registry.getExtensionPoint(TASK_REPOSITORY_PAGE_CONTRIBUTION_EXTENSION);
350
		IExtension[] editorExtensions = editorExtensionPoint.getExtensions();
351
		for (IExtension extension : editorExtensions) {
352
			IConfigurationElement[] elements = extension.getConfigurationElements();
353
			for (IConfigurationElement element : elements) {
354
				if (element.getName().equals(TASK_REPOSITORY_PAGE_CONTRIBUTION)) {
355
					String kind = element.getAttribute(KIND);
356
					if (kind == null || kind.length() == 0 || kind.equals(getConnectorKind())) {
357
						String id = element.getAttribute("id");
358
						try {
359
							if (id == null || id.length() == 0) {
360
								throw new IllegalStateException(TASK_REPOSITORY_PAGE_CONTRIBUTION + "/@id is required");
361
							}
362
							Object contributor = element.createExecutableExtension("class");
363
							AbstractTaskRepositoryPageContribution pageContributor = (AbstractTaskRepositoryPageContribution) contributor;
364
							pageContributor.setId(id);
365
							contributors.add(pageContributor);
366
						} catch (Exception e) {
367
							StatusHandler.log(new Status(IStatus.ERROR, TasksUiPlugin.ID_PLUGIN, "Could not load "
368
									+ TASK_REPOSITORY_PAGE_CONTRIBUTION + " '" + id + "' from plug-in "
369
									+ element.getContributor().getName(), e));
370
						}
371
					}
372
				}
373
			}
374
		}
375
376
		return contributors;
377
	}
378
379
	private static class ContributionComparator implements Comparator<AbstractTaskRepositoryPageContribution> {
380
381
		public int compare(AbstractTaskRepositoryPageContribution o1, AbstractTaskRepositoryPageContribution o2) {
382
			if (o1 == o2) {
383
				return 0;
384
			}
385
			String s1 = o1.getTitle();
386
			String s2 = o2.getTitle();
387
			int i = s1.compareTo(s2);
388
			if (i == 0) {
389
				i = o1.getId().compareTo(o2.getId());
390
			}
391
			return i;
392
		}
393
394
	}
395
}

Return to bug 244653