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 |
} |