|
Added
Link Here
|
| 0 |
- |
1 |
/******************************************************************************* |
|
|
2 |
* Copyright (c) 2010, 2011 SAP AG 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 |
* SAP AG - initial API and implementation |
| 10 |
*******************************************************************************/ |
| 11 |
package org.eclipse.skalli.view.component; |
| 12 |
|
| 13 |
import java.util.ArrayList; |
| 14 |
import java.util.Collection; |
| 15 |
import java.util.Iterator; |
| 16 |
import java.util.List; |
| 17 |
import java.util.UUID; |
| 18 |
|
| 19 |
import org.apache.commons.lang.StringUtils; |
| 20 |
import org.eclipse.skalli.api.java.ProjectService; |
| 21 |
import org.eclipse.skalli.common.Services; |
| 22 |
import org.eclipse.skalli.common.util.UUIDList; |
| 23 |
import org.eclipse.skalli.model.core.Project; |
| 24 |
import org.eclipse.skalli.model.ext.PropertyName; |
| 25 |
|
| 26 |
import com.vaadin.data.Item; |
| 27 |
import com.vaadin.data.Validator.InvalidValueException; |
| 28 |
import com.vaadin.data.util.IndexedContainer; |
| 29 |
import com.vaadin.ui.AbstractSelect; |
| 30 |
import com.vaadin.ui.AbstractSelect.Filtering; |
| 31 |
import com.vaadin.ui.Button; |
| 32 |
import com.vaadin.ui.Button.ClickEvent; |
| 33 |
import com.vaadin.ui.ComboBox; |
| 34 |
import com.vaadin.ui.CustomField; |
| 35 |
import com.vaadin.ui.HorizontalLayout; |
| 36 |
import com.vaadin.ui.Select; |
| 37 |
import com.vaadin.ui.VerticalLayout; |
| 38 |
|
| 39 |
public class MultiComboBox extends CustomField { |
| 40 |
|
| 41 |
private static final long serialVersionUID = -2946220818606365985L; |
| 42 |
|
| 43 |
private static final String STYLE_LAYOUT = "multicombobox-layout"; |
| 44 |
private static final String STYLE_LINE_LAYOUT = "multicombobox-line"; |
| 45 |
private static final String STYLE_BUTTON = "multicombobox-btn"; |
| 46 |
|
| 47 |
private UUIDList values; |
| 48 |
private VerticalLayout layout; |
| 49 |
private List<ComboBoxElement> comboBoxEntries; |
| 50 |
private String description; |
| 51 |
private boolean readOnly; |
| 52 |
private int columns; |
| 53 |
|
| 54 |
private static class ComboBoxElement { |
| 55 |
public ComboBoxElement(ComboBox comboBox) { |
| 56 |
this.comboBox = comboBox; |
| 57 |
comboBox.setItemCaptionPropertyId(ProjectDataSource.PROPERTY_DISPLAYNAME); |
| 58 |
comboBox.setItemCaptionMode(AbstractSelect.ITEM_CAPTION_MODE_PROPERTY); |
| 59 |
comboBox.setFilteringMode(Filtering.FILTERINGMODE_CONTAINS); |
| 60 |
comboBox.setImmediate(true); |
| 61 |
comboBox.setNewItemsAllowed(false); |
| 62 |
comboBox.setNullSelectionAllowed(true); |
| 63 |
} |
| 64 |
|
| 65 |
ComboBox comboBox; |
| 66 |
Button removeButton; |
| 67 |
} |
| 68 |
|
| 69 |
public MultiComboBox(String caption, UUIDList values) { |
| 70 |
if (values == null) { |
| 71 |
throw new IllegalArgumentException("argument 'values' must not be null"); |
| 72 |
} |
| 73 |
setCaption(caption); |
| 74 |
this.values = values; |
| 75 |
init(values); |
| 76 |
layout = new VerticalLayout(); |
| 77 |
layout.setStyleName(STYLE_LAYOUT); |
| 78 |
renderComboBoxes(); |
| 79 |
setCompositionRoot(layout); |
| 80 |
} |
| 81 |
|
| 82 |
private void renderComboBoxes() { |
| 83 |
boolean hasMultipleEntries = comboBoxEntries.size() > 1; |
| 84 |
int last = comboBoxEntries.size() - 1; |
| 85 |
for (int i = 0; i <= last; ++i) { |
| 86 |
ComboBoxElement comboBoxEntry = comboBoxEntries.get(i); |
| 87 |
HorizontalLayout horLayout = new HorizontalLayout(); |
| 88 |
horLayout.setStyleName(STYLE_LINE_LAYOUT); |
| 89 |
ComboBox comboBox = comboBoxEntry.comboBox; |
| 90 |
if (comboBox.getValue() == null) { |
| 91 |
comboBox.setEnabled(!readOnly); |
| 92 |
} else { |
| 93 |
comboBox.setReadOnly(readOnly); |
| 94 |
} |
| 95 |
horLayout.addComponent(comboBox); |
| 96 |
|
| 97 |
if (hasMultipleEntries) { |
| 98 |
Button b = createRemoveButton(); |
| 99 |
comboBoxEntry.removeButton = b; |
| 100 |
horLayout.addComponent(b); |
| 101 |
} |
| 102 |
if (i == last) { |
| 103 |
horLayout.addComponent(createAddButton()); |
| 104 |
} |
| 105 |
|
| 106 |
layout.addComponent(horLayout); |
| 107 |
} |
| 108 |
} |
| 109 |
|
| 110 |
private void init(UUIDList values) { |
| 111 |
comboBoxEntries = new ArrayList<ComboBoxElement>(); |
| 112 |
if (values != null && !values.isEmpty()) { |
| 113 |
for (UUID value : values) { |
| 114 |
ComboBox comboBox = createComboBox(value); |
| 115 |
comboBoxEntries.add(new ComboBoxElement(comboBox)); |
| 116 |
} |
| 117 |
} else { |
| 118 |
ComboBox comboBox = createComboBox(null); |
| 119 |
comboBoxEntries.add(new ComboBoxElement(comboBox)); |
| 120 |
} |
| 121 |
} |
| 122 |
|
| 123 |
private ComboBox createComboBox(UUID uuid) { |
| 124 |
ComboBox comboBox = new ComboBox(null, new ProjectDataSource()); |
| 125 |
if (description != null) { |
| 126 |
comboBox.setDescription(description); |
| 127 |
} |
| 128 |
if (uuid != null) { |
| 129 |
ProjectService projectService = Services.getRequiredService(ProjectService.class); |
| 130 |
Project project = projectService.getByUUID(uuid); |
| 131 |
comboBox.select(project); |
| 132 |
} |
| 133 |
return comboBox; |
| 134 |
} |
| 135 |
|
| 136 |
public void setColumns(int columns) { |
| 137 |
this.columns = columns; |
| 138 |
for (ComboBoxElement entry : comboBoxEntries) { |
| 139 |
entry.comboBox.setWidth(columns, Select.UNITS_EM); |
| 140 |
} |
| 141 |
} |
| 142 |
|
| 143 |
private Button createAddButton() { |
| 144 |
Button b = new Button("Add"); |
| 145 |
b.setStyleName(Button.STYLE_LINK); |
| 146 |
b.addStyleName(STYLE_BUTTON); |
| 147 |
b.setDescription("Add another entry"); |
| 148 |
b.setEnabled(!readOnly); |
| 149 |
b.addListener(new Button.ClickListener() { |
| 150 |
@Override |
| 151 |
public void buttonClick(ClickEvent event) { |
| 152 |
ComboBox cb = createComboBox(null); |
| 153 |
cb.setWidth(columns, Select.UNITS_EM); |
| 154 |
comboBoxEntries.add(new ComboBoxElement(cb)); |
| 155 |
layout.removeAllComponents(); |
| 156 |
renderComboBoxes(); |
| 157 |
} |
| 158 |
}); |
| 159 |
return b; |
| 160 |
} |
| 161 |
|
| 162 |
private Button createRemoveButton() { |
| 163 |
Button b = new Button("Remove"); |
| 164 |
b.setStyleName(Button.STYLE_LINK); |
| 165 |
b.addStyleName(STYLE_BUTTON); |
| 166 |
b.setDescription("Remove this entry"); |
| 167 |
b.addListener(new Button.ClickListener() { |
| 168 |
@Override |
| 169 |
public void buttonClick(ClickEvent event) { |
| 170 |
Button b = event.getButton(); |
| 171 |
Iterator<ComboBoxElement> it = comboBoxEntries.iterator(); |
| 172 |
while (it.hasNext()) { |
| 173 |
ComboBoxElement element = it.next(); |
| 174 |
if (element.removeButton == b) { |
| 175 |
it.remove(); |
| 176 |
break; |
| 177 |
} |
| 178 |
} |
| 179 |
layout.removeAllComponents(); |
| 180 |
renderComboBoxes(); |
| 181 |
} |
| 182 |
}); |
| 183 |
return b; |
| 184 |
} |
| 185 |
|
| 186 |
@Override |
| 187 |
public void setDescription(String description) { |
| 188 |
this.description = description; |
| 189 |
for (ComboBoxElement element : comboBoxEntries) { |
| 190 |
element.comboBox.setDescription(description); |
| 191 |
} |
| 192 |
} |
| 193 |
|
| 194 |
@Override |
| 195 |
public Object getValue() { |
| 196 |
UUIDList uuid = new UUIDList(comboBoxEntries.size()); |
| 197 |
copyValues(uuid); |
| 198 |
return uuid; |
| 199 |
} |
| 200 |
|
| 201 |
@Override |
| 202 |
public void commit() throws SourceException, InvalidValueException { |
| 203 |
values.clear(); |
| 204 |
copyValues(values); |
| 205 |
} |
| 206 |
|
| 207 |
private void copyValues(UUIDList values) { |
| 208 |
for (ComboBoxElement entry : comboBoxEntries) { |
| 209 |
Project project = (Project) entry.comboBox.getValue(); |
| 210 |
if (project == null) { |
| 211 |
return; |
| 212 |
} |
| 213 |
UUID value = project.getUuid(); |
| 214 |
if (StringUtils.isNotBlank(value.toString())) { |
| 215 |
values.add(value); |
| 216 |
} |
| 217 |
} |
| 218 |
} |
| 219 |
|
| 220 |
@Override |
| 221 |
public Class<?> getType() { |
| 222 |
return Collection.class; |
| 223 |
} |
| 224 |
|
| 225 |
private static class ProjectDataSource extends IndexedContainer { |
| 226 |
|
| 227 |
private static final long serialVersionUID = 8192530422436522676L; |
| 228 |
|
| 229 |
@PropertyName(position = 0) |
| 230 |
public static final Object PROPERTY_DISPLAYNAME = "displayName"; |
| 231 |
|
| 232 |
public ProjectDataSource() { |
| 233 |
super(); |
| 234 |
addContainerProperty(Project.PROPERTY_NAME, String.class, null); |
| 235 |
addContainerProperty(Project.PROPERTY_PROJECTID, String.class, null); |
| 236 |
addContainerProperty(PROPERTY_DISPLAYNAME, String.class, null); |
| 237 |
|
| 238 |
ProjectService projectService = Services.getRequiredService(ProjectService.class); |
| 239 |
List<Project> projects = projectService.getAll(); |
| 240 |
for (Project project : projects) { |
| 241 |
addItem(project); |
| 242 |
} |
| 243 |
sort(new Object[] { Project.PROPERTY_NAME, Project.PROPERTY_PROJECTID }, new boolean[] { true, true }); |
| 244 |
} |
| 245 |
|
| 246 |
private Item addItem(Project project) { |
| 247 |
// item key = project instance |
| 248 |
Item item = getItem(project); |
| 249 |
if (item == null) { |
| 250 |
item = super.addItem(project); // IndexedContainer#addItem return null, if entry already exists!!! |
| 251 |
} |
| 252 |
if (item != null) { |
| 253 |
String projectId = project.getProjectId(); |
| 254 |
String name = project.getName(); |
| 255 |
item.getItemProperty(Project.PROPERTY_NAME).setValue(name); |
| 256 |
item.getItemProperty(Project.PROPERTY_PROJECTID).setValue(projectId); |
| 257 |
item.getItemProperty(PROPERTY_DISPLAYNAME).setValue(name + " <" + projectId + ">"); |
| 258 |
} |
| 259 |
return item; |
| 260 |
} |
| 261 |
} |
| 262 |
|
| 263 |
@Override |
| 264 |
public void setReadOnly(boolean readOnly) { |
| 265 |
this.readOnly = readOnly; |
| 266 |
layout.removeAllComponents(); |
| 267 |
renderComboBoxes(); |
| 268 |
} |
| 269 |
|
| 270 |
@Override |
| 271 |
public boolean isReadOnly() { |
| 272 |
return readOnly; |
| 273 |
} |
| 274 |
|
| 275 |
} |