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

Collapse All | Expand All

(-)src/org/eclipse/mylyn/internal/bugzilla/core/BugzillaAttribute.java (-1 / +1 lines)
Lines 94-100 Link Here
94
94
95
	FILENAME(Messages.BugzillaAttribute_filename, "filename", TaskAttribute.TYPE_SHORT_TEXT, false, false), //$NON-NLS-1$
95
	FILENAME(Messages.BugzillaAttribute_filename, "filename", TaskAttribute.TYPE_SHORT_TEXT, false, false), //$NON-NLS-1$
96
96
97
	FLAG(Messages.BugzillaAttribute_flag, "flag", IBugzillaConstants.EDITOR_TYPE_FLAG, false, false), //$NON-NLS-1$
97
	FLAG(Messages.BugzillaAttribute_flag, "flag", IBugzillaConstants.EDITOR_TYPE_FLAG, true, false), //$NON-NLS-1$
98
98
99
	GROUP(Messages.BugzillaAttribute_Group, "group", TaskAttribute.TYPE_BOOLEAN, true, true), //$NON-NLS-1$
99
	GROUP(Messages.BugzillaAttribute_Group, "group", TaskAttribute.TYPE_BOOLEAN, true, true), //$NON-NLS-1$
100
100
(-)src/org/eclipse/mylyn/internal/bugzilla/core/BugzillaFlagMapper.java (-1 / +1 lines)
Lines 109-115 Link Here
109
		}
109
		}
110
110
111
		if (bugzillaVersion.compareTo(BugzillaVersion.BUGZILLA_3_2) >= 0) {
111
		if (bugzillaVersion.compareTo(BugzillaVersion.BUGZILLA_3_2) >= 0) {
112
			meta.setKind(TaskAttribute.KIND_DEFAULT);
112
			meta.setKind(BugzillaAttribute.KIND_FLAG);
113
		}
113
		}
114
		meta.setReadOnly(false);
114
		meta.setReadOnly(false);
115
115
(-)src/org/eclipse/mylyn/internal/bugzilla/ui/editor/BugzillaFlagPart.java (+305 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2011 Frank Becker 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
 *     Frank Becker - initial API and implementation
10
 *******************************************************************************/
11
12
package org.eclipse.mylyn.internal.bugzilla.ui.editor;
13
14
import java.util.ArrayList;
15
import java.util.Collections;
16
import java.util.Comparator;
17
import java.util.List;
18
import java.util.Map;
19
20
import org.eclipse.jface.action.ToolBarManager;
21
import org.eclipse.jface.layout.GridDataFactory;
22
import org.eclipse.mylyn.internal.bugzilla.core.BugzillaAttribute;
23
import org.eclipse.mylyn.internal.provisional.commons.ui.CommonUiUtil;
24
import org.eclipse.mylyn.internal.tasks.ui.editors.EditorUtil;
25
import org.eclipse.mylyn.internal.tasks.ui.notifications.TaskDiffUtil;
26
import org.eclipse.mylyn.tasks.core.data.TaskAttribute;
27
import org.eclipse.mylyn.tasks.ui.editors.AbstractAttributeEditor;
28
import org.eclipse.mylyn.tasks.ui.editors.AbstractTaskEditorPart;
29
import org.eclipse.mylyn.tasks.ui.editors.LayoutHint;
30
import org.eclipse.mylyn.tasks.ui.editors.LayoutHint.ColumnSpan;
31
import org.eclipse.mylyn.tasks.ui.editors.LayoutHint.RowSpan;
32
import org.eclipse.osgi.util.NLS;
33
import org.eclipse.swt.SWT;
34
import org.eclipse.swt.layout.GridData;
35
import org.eclipse.swt.layout.GridLayout;
36
import org.eclipse.swt.layout.RowLayout;
37
import org.eclipse.swt.widgets.Composite;
38
import org.eclipse.swt.widgets.Label;
39
import org.eclipse.ui.forms.IFormColors;
40
import org.eclipse.ui.forms.events.ExpansionAdapter;
41
import org.eclipse.ui.forms.events.ExpansionEvent;
42
import org.eclipse.ui.forms.widgets.ExpandableComposite;
43
import org.eclipse.ui.forms.widgets.FormToolkit;
44
import org.eclipse.ui.forms.widgets.Section;
45
46
@SuppressWarnings("restriction")
47
public class BugzillaFlagPart extends AbstractTaskEditorPart {
48
	private static final int LABEL_WIDTH = 110;
49
50
	private static final int COLUMN_WIDTH = 140;
51
52
	private static final int COLUMN_GAP = 20;
53
54
	private static final int MULTI_COLUMN_WIDTH = COLUMN_WIDTH + 5 + COLUMN_GAP + LABEL_WIDTH + 5 + COLUMN_WIDTH;
55
56
	private static final int MULTI_ROW_HEIGHT = 55;
57
58
	private boolean hasIncoming;
59
60
	private List<AbstractAttributeEditor> flagEditors;
61
62
	private String infoOverlayText = null;
63
64
	private String infoOverlayTooltipText = null;
65
66
	public BugzillaFlagPart() {
67
		setPartName(Messages.BugzillaFlagPart_Flags_PartName);
68
	}
69
70
	@Override
71
	public void createControl(Composite parent, FormToolkit toolkit) {
72
		initialize();
73
		int style = ExpandableComposite.TWISTIE;
74
		if (hasIncoming) {
75
			style |= ExpandableComposite.EXPANDED;
76
		}
77
		Section flagSection = createSection(parent, toolkit, style);
78
		EditorUtil.setTitleBarForeground(flagSection, toolkit.getColors().getColor(IFormColors.TITLE));
79
80
		GridLayout gl = new GridLayout();
81
		GridData gd = new GridData(SWT.FILL, SWT.NONE, false, false);
82
		gd.horizontalSpan = 4;
83
		flagSection.setLayout(gl);
84
		flagSection.setLayoutData(gd);
85
86
		Composite flagComposite = toolkit.createComposite(flagSection);
87
88
		GridLayout flagsLayout = EditorUtil.createSectionClientLayout();
89
		flagsLayout.numColumns = 4;
90
		flagsLayout.horizontalSpacing = 7;
91
		flagsLayout.verticalSpacing = 6;
92
		flagComposite.setLayout(flagsLayout);
93
94
		GridData flagsData = new GridData(GridData.FILL_BOTH);
95
		flagsData.horizontalSpan = 1;
96
		flagsData.grabExcessVerticalSpace = false;
97
		flagComposite.setLayoutData(flagsData);
98
		GridDataFactory.fillDefaults().align(SWT.FILL, SWT.TOP).grab(true, false).applyTo(flagComposite);
99
100
		createAttributeControls(flagComposite, toolkit, flagsLayout.numColumns);
101
		flagSection.setClient(flagComposite);
102
		toolkit.paintBordersFor(flagComposite);
103
		setSection(toolkit, flagSection);
104
	}
105
106
	private void initialize() {
107
		hasIncoming = false;
108
		flagEditors = new ArrayList<AbstractAttributeEditor>();
109
		int used = 0;
110
		int unused = 0;
111
		String usedDetail = ""; //$NON-NLS-1$
112
		String unusedDetail = ""; //$NON-NLS-1$
113
		Map<String, TaskAttribute> attributes = getTaskData().getRoot().getAttributes();
114
		for (TaskAttribute attribute : attributes.values()) {
115
			if (!BugzillaAttribute.KIND_FLAG.equals(attribute.getMetaData().getKind())) {
116
				continue;
117
			}
118
119
			TaskAttribute stateAttribute = attribute.getAttribute("state"); //$NON-NLS-1$
120
			if (stateAttribute == null) {
121
				continue;
122
			}
123
			String val = stateAttribute.getValue();
124
			if (val != null && !val.equals("") && !val.equals(" ")) { //$NON-NLS-1$ //$NON-NLS-2$
125
				if (used > 0) {
126
					usedDetail += ", "; //$NON-NLS-1$
127
				}
128
				used++;
129
				usedDetail += stateAttribute.getMetaData().getLabel();
130
			} else {
131
				if (unused > 0) {
132
					unusedDetail += ", "; //$NON-NLS-1$
133
				}
134
				unused++;
135
				unusedDetail += stateAttribute.getMetaData().getLabel();
136
			}
137
			AbstractAttributeEditor attributeEditor = createAttributeEditor(attribute);
138
			if (attributeEditor != null) {
139
				flagEditors.add(attributeEditor);
140
				if (getModel().hasIncomingChanges(attribute)) {
141
					hasIncoming = true;
142
				}
143
			}
144
		}
145
		Comparator<AbstractAttributeEditor> attributeSorter = createAttributeEditorSorter();
146
		if (attributeSorter != null) {
147
			Collections.sort(flagEditors, attributeSorter);
148
		}
149
		if (used > 0 && unused > 0) {
150
			infoOverlayText = NLS.bind(Messages.BugzillaFlagPart_numberof_unused_used_flags, "" + unused, "" + used); //$NON-NLS-1$ //$NON-NLS-2$ 
151
		} else {
152
			infoOverlayText = NLS.bind("{0} {1}", used > 0 ? "" + used : "" + unused, used > 0 //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
153
					? used == 1 ? "used flag" : "used flags" //$NON-NLS-1$ //$NON-NLS-2$
154
					: unused == 1 ? "unused flag" : "unused flags"); //$NON-NLS-1$ //$NON-NLS-2$
155
		}
156
		usedDetail = NLS.bind(
157
				"{0} {1}", used == 1 ? Messages.BugzillaFlagPart_used_flag + Messages.BugzillaFlagPart_is : Messages.BugzillaFlagPart_used_flags + Messages.BugzillaFlagPart_are, usedDetail); //$NON-NLS-1$
158
		unusedDetail = NLS.bind(
159
				"{0} {1}", unused == 1 ? Messages.BugzillaFlagPart_unused_flag + Messages.BugzillaFlagPart_is : Messages.BugzillaFlagPart_unused_flags + Messages.BugzillaFlagPart_are, unusedDetail); //$NON-NLS-1$ 
160
		if (used > 0 && unused > 0) {
161
			infoOverlayTooltipText = NLS.bind("{0}\n{1}", usedDetail, unusedDetail); //$NON-NLS-1$
162
		} else {
163
			infoOverlayTooltipText = used > 0 ? usedDetail : unusedDetail;
164
		}
165
	}
166
167
	/**
168
	 * Create a comparator by which attribute editors will be sorted. By default attribute editors are sorted by layout
169
	 * hint priority. Subclasses may override this method to sort attribute editors in a custom way.
170
	 * 
171
	 * @return comparator for {@link AbstractAttributeEditor} objects
172
	 */
173
	protected Comparator<AbstractAttributeEditor> createAttributeEditorSorter() {
174
		return new Comparator<AbstractAttributeEditor>() {
175
			public int compare(AbstractAttributeEditor o1, AbstractAttributeEditor o2) {
176
				int p1 = (o1.getLayoutHint() != null) ? o1.getLayoutHint().getPriority() : LayoutHint.DEFAULT_PRIORITY;
177
				int p2 = (o2.getLayoutHint() != null) ? o2.getLayoutHint().getPriority() : LayoutHint.DEFAULT_PRIORITY;
178
				return p1 - p2;
179
			}
180
		};
181
	}
182
183
	private void createAttributeControls(Composite attributesComposite, FormToolkit toolkit, int columnCount) {
184
		int currentColumn = 1;
185
		int currentPriority = 0;
186
		for (AbstractAttributeEditor attributeEditor : flagEditors) {
187
			int priority = (attributeEditor.getLayoutHint() != null)
188
					? attributeEditor.getLayoutHint().getPriority()
189
					: LayoutHint.DEFAULT_PRIORITY;
190
			if (priority != currentPriority) {
191
				currentPriority = priority;
192
				if (currentColumn > 1) {
193
					while (currentColumn <= columnCount) {
194
						getManagedForm().getToolkit().createLabel(attributesComposite, ""); //$NON-NLS-1$
195
						currentColumn++;
196
					}
197
					currentColumn = 1;
198
				}
199
			}
200
201
			if (attributeEditor.hasLabel()) {
202
				attributeEditor.createLabelControl(attributesComposite, toolkit);
203
				Label label = attributeEditor.getLabelControl();
204
				String text = label.getText();
205
				String shortenText = TaskDiffUtil.shortenText(label, text, LABEL_WIDTH);
206
				label.setText(shortenText);
207
				if (!text.equals(shortenText)) {
208
					label.setToolTipText(text);
209
				}
210
				GridData gd = GridDataFactory.fillDefaults()
211
						.align(SWT.RIGHT, SWT.CENTER)
212
						.hint(LABEL_WIDTH, SWT.DEFAULT)
213
						.create();
214
				if (currentColumn > 1) {
215
					gd.horizontalIndent = COLUMN_GAP;
216
					gd.widthHint = LABEL_WIDTH + COLUMN_GAP;
217
				}
218
				label.setLayoutData(gd);
219
				currentColumn++;
220
			}
221
222
			attributeEditor.createControl(attributesComposite, toolkit);
223
			LayoutHint layoutHint = attributeEditor.getLayoutHint();
224
			GridData gd = new GridData(SWT.FILL, SWT.CENTER, false, false);
225
			if (layoutHint != null
226
					&& !(layoutHint.rowSpan == RowSpan.SINGLE && layoutHint.columnSpan == ColumnSpan.SINGLE)) {
227
				if (layoutHint.rowSpan == RowSpan.MULTIPLE) {
228
					gd.heightHint = MULTI_ROW_HEIGHT;
229
				}
230
				if (layoutHint.columnSpan == ColumnSpan.SINGLE) {
231
					gd.widthHint = COLUMN_WIDTH;
232
					gd.horizontalSpan = 1;
233
				} else {
234
					gd.widthHint = MULTI_COLUMN_WIDTH;
235
					gd.horizontalSpan = columnCount - currentColumn + 1;
236
				}
237
			} else {
238
				gd.widthHint = COLUMN_WIDTH;
239
				gd.horizontalSpan = 1;
240
			}
241
			attributeEditor.getControl().setLayoutData(gd);
242
243
			getTaskEditorPage().getAttributeEditorToolkit().adapt(attributeEditor);
244
245
			currentColumn += gd.horizontalSpan;
246
			currentColumn %= columnCount;
247
		}
248
	}
249
250
	protected String getInfoOverlayText() {
251
		return infoOverlayText;
252
	}
253
254
	protected String getInfoOverlayTooltipText() {
255
		return infoOverlayTooltipText;
256
	}
257
258
	private void createInfoOverlay(Composite composite, Section section, FormToolkit toolkit) {
259
		String text = getInfoOverlayText();
260
		if (text == null) {
261
			return;
262
		}
263
264
		final Label label = toolkit.createLabel(composite, CommonUiUtil.toLabel(text));
265
		label.setForeground(toolkit.getColors().getColor(IFormColors.TITLE));
266
		label.setBackground(null);
267
		label.setVisible(!section.isExpanded());
268
		label.setToolTipText(getInfoOverlayTooltipText());
269
270
		section.addExpansionListener(new ExpansionAdapter() {
271
			@Override
272
			public void expansionStateChanging(ExpansionEvent e) {
273
				label.setVisible(!e.getState());
274
			}
275
		});
276
	}
277
278
	@Override
279
	protected void setSection(FormToolkit toolkit, Section section) {
280
		if (section.getTextClient() == null) {
281
			ToolBarManager toolBarManager = new ToolBarManager(SWT.FLAT);
282
			fillToolBar(toolBarManager);
283
284
			if (toolBarManager.getSize() > 0 || getInfoOverlayText() != null) {
285
				Composite toolbarComposite = toolkit.createComposite(section);
286
				toolbarComposite.setBackground(null);
287
				RowLayout rowLayout = new RowLayout();
288
				rowLayout.marginLeft = 0;
289
				rowLayout.marginRight = 0;
290
				rowLayout.marginTop = 0;
291
				rowLayout.marginBottom = 0;
292
				rowLayout.center = true;
293
				toolbarComposite.setLayout(rowLayout);
294
295
				createInfoOverlay(toolbarComposite, section, toolkit);
296
297
				toolBarManager.createControl(toolbarComposite);
298
				section.clientVerticalSpacing = 0;
299
				section.descriptionVerticalSpacing = 0;
300
				section.setTextClient(toolbarComposite);
301
			}
302
		}
303
		setControl(section);
304
	}
305
}
(-)src/org/eclipse/mylyn/internal/bugzilla/ui/editor/BugzillaTaskEditorPage.java (+10 lines)
Lines 66-71 Link Here
66
66
67
	public static final String ID_PART_BUGZILLA_FLAGS = "org.eclipse.mylyn.bugzilla.ui.editors.part.flags"; //$NON-NLS-1$
67
	public static final String ID_PART_BUGZILLA_FLAGS = "org.eclipse.mylyn.bugzilla.ui.editors.part.flags"; //$NON-NLS-1$
68
68
69
	public static final String PATH_FLAGS = "flags"; //$NON-NLS-1$
70
69
	private final Map<TaskAttribute, AbstractAttributeEditor> attributeEditorMap;
71
	private final Map<TaskAttribute, AbstractAttributeEditor> attributeEditorMap;
70
72
71
	private TaskDataModelListener productListener;
73
	private TaskDataModelListener productListener;
Lines 99-104 Link Here
99
			}
101
			}
100
		}
102
		}
101
103
104
		// Add Bugzilla Flag part
105
		descriptors.add(new TaskEditorPartDescriptor(ID_PART_BUGZILLA_FLAGS) {
106
			@Override
107
			public AbstractTaskEditorPart createPart() {
108
				return new BugzillaFlagPart();
109
			}
110
		}.setPath(ID_PART_ATTRIBUTES + "/" + PATH_FLAGS)); //$NON-NLS-1$
111
102
		// Add Bugzilla Planning part
112
		// Add Bugzilla Planning part
103
		try {
113
		try {
104
			TaskData data = TasksUi.getTaskDataManager().getTaskData(getTask());
114
			TaskData data = TasksUi.getTaskDataManager().getTaskData(getTask());
(-)src/org/eclipse/mylyn/internal/bugzilla/ui/editor/Messages.java (+16 lines)
Lines 25-30 Link Here
25
		NLS.initializeMessages(BUNDLE_NAME, Messages.class);
25
		NLS.initializeMessages(BUNDLE_NAME, Messages.class);
26
	}
26
	}
27
27
28
	public static String BugzillaFlagPart_are;
29
30
	public static String BugzillaFlagPart_Flags_PartName;
31
32
	public static String BugzillaFlagPart_is;
33
34
	public static String BugzillaFlagPart_numberof_unused_used_flags;
35
36
	public static String BugzillaFlagPart_unused_flag;
37
38
	public static String BugzillaFlagPart_unused_flags;
39
40
	public static String BugzillaFlagPart_used_flag;
41
42
	public static String BugzillaFlagPart_used_flags;
43
28
	public static String BugzillaPeoplePart_People;
44
	public static String BugzillaPeoplePart_People;
29
45
30
	public static String BugzillaPeoplePart__Select_to_remove_;
46
	public static String BugzillaPeoplePart__Select_to_remove_;
(-)src/org/eclipse/mylyn/internal/bugzilla/ui/editor/messages.properties (+8 lines)
Lines 8-13 Link Here
8
# Contributors:
8
# Contributors:
9
#      Tasktop Technologies - initial API and implementation
9
#      Tasktop Technologies - initial API and implementation
10
###############################################################################
10
###############################################################################
11
BugzillaFlagPart_are=\ are
12
BugzillaFlagPart_Flags_PartName=Flags
13
BugzillaFlagPart_is=\ is
14
BugzillaFlagPart_numberof_unused_used_flags={0} unused / {1} used flags
15
BugzillaFlagPart_unused_flag=unused flag
16
BugzillaFlagPart_unused_flags=unused flags
17
BugzillaFlagPart_used_flag=used flag
18
BugzillaFlagPart_used_flags=used flags
11
BugzillaPeoplePart_People=People
19
BugzillaPeoplePart_People=People
12
BugzillaPeoplePart__Select_to_remove_=(Select to remove)
20
BugzillaPeoplePart__Select_to_remove_=(Select to remove)
13
21

Return to bug 339470