/* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.activiti.explorer.ui.custom; import java.util.Arrays; import java.util.Collection; import java.util.List; import java.util.Set; import org.activiti.engine.identity.User; import org.activiti.explorer.ExplorerApp; import org.activiti.explorer.I18nManager; import org.activiti.explorer.Messages; import org.activiti.explorer.cache.UserCache; import org.activiti.explorer.identity.LoggedInUser; import org.activiti.explorer.ui.Images; import org.activiti.explorer.ui.event.SubmitEvent; import org.activiti.explorer.ui.event.SubmitEventListener; import org.activiti.explorer.ui.util.ThemeImageColumnGenerator; import com.vaadin.data.Item; import com.vaadin.event.FieldEvents.TextChangeEvent; import com.vaadin.event.FieldEvents.TextChangeListener; import com.vaadin.ui.Alignment; import com.vaadin.ui.Button; import com.vaadin.ui.Button.ClickEvent; import com.vaadin.ui.Button.ClickListener; import com.vaadin.ui.ComboBox; import com.vaadin.ui.Embedded; import com.vaadin.ui.HorizontalLayout; import com.vaadin.ui.Table; import com.vaadin.ui.TextField; import com.vaadin.ui.VerticalLayout; import com.vaadin.ui.themes.Reindeer; /** * A popup window that is used to select people. Two possible modes: * - multiselect: displays two tables that allow to select users from the left table * to the table on the right * - non-multiselect: one table where only one user can be chosen from. * * {@link SubmitEventListener} can be attached to listen to completion of the * selection. The selected user(s) can be retrieved using {@link #getSelectedUserId()} * ,{@link #getSelectedUserIds()} and {@link #getSelectedUserRole(String)}. * * @author Joram Barrez */ public class SelectUsersPopupWindow extends PopupWindow { private static final long serialVersionUID = 1L; protected String title; protected boolean multiSelect = true; protected boolean showRoles = true; protected Collection<String> ignoredUserIds; protected UserCache userCache; protected I18nManager i18nManager; protected VerticalLayout windowLayout; protected TextField searchField; protected HorizontalLayout userSelectionLayout; protected Table matchingUsersTable; protected Button selectUserButton; protected Table selectedUsersTable; protected Button doneButton; public SelectUsersPopupWindow(String title, boolean multiSelect) { this.title = title; this.multiSelect = multiSelect; this.userCache = ExplorerApp.get().getUserCache(); this.i18nManager = ExplorerApp.get().getI18nManager(); } public SelectUsersPopupWindow(String title, boolean multiSelect, Collection<String> ignoredUserIds) { this(title, multiSelect); this.ignoredUserIds = ignoredUserIds; } public SelectUsersPopupWindow(String title, boolean multiSelect, boolean showRoles, Collection<String> ignoredUserIds) { this(title, multiSelect); this.showRoles = showRoles; this.ignoredUserIds = ignoredUserIds; } @Override public void attach() { super.attach(); initUi(); } protected void initUi() { setCaption(title); setModal(true); addStyleName(Reindeer.WINDOW_LIGHT); center(); windowLayout = (VerticalLayout) getContent(); windowLayout.setSpacing(true); if (multiSelect && showRoles) { setWidth(820, UNITS_PIXELS); } else if (multiSelect && !showRoles) { setWidth(685, UNITS_PIXELS); } else { setWidth(340, UNITS_PIXELS); } setHeight(350, UNITS_PIXELS); initSearchField(); initUserSelection(); initDoneButton(); } protected void initSearchField() { HorizontalLayout searchLayout = new HorizontalLayout(); searchLayout.setSpacing(true); addComponent(searchLayout); // textfield searchField = new TextField(); searchField.setInputPrompt(i18nManager.getMessage(Messages.PEOPLE_SEARCH)); searchField.setWidth(180, UNITS_PIXELS); searchField.focus(); searchLayout.addComponent(searchField); // Logic to change table according to input searchField.addListener(new TextChangeListener() { public void textChange(TextChangeEvent event) { searchPeople(event.getText()); } }); initSelectMyselfButton(searchLayout); } protected void initSelectMyselfButton(HorizontalLayout searchLayout) { final LoggedInUser loggedInUser = ExplorerApp.get().getLoggedInUser(); if (ignoredUserIds == null || !ignoredUserIds.contains(loggedInUser.getId())) { Button meButton = new Button(i18nManager.getMessage(Messages.PEOPLE_SELECT_MYSELF)); meButton.setIcon(Images.USER_16); searchLayout.addComponent(meButton); searchLayout.setComponentAlignment(meButton, Alignment.MIDDLE_LEFT); if (multiSelect) { meButton.addListener(new ClickListener() { public void buttonClick(ClickEvent event) { selectUser(loggedInUser.getId(), loggedInUser.getFullName()); } }); } else { meButton.addListener(new ClickListener() { public void buttonClick(ClickEvent event) { addMatchingUser(loggedInUser.getId(), loggedInUser.getFullName()); matchingUsersTable.select(loggedInUser.getId()); fireEvent(new SubmitEvent(doneButton, SubmitEvent.SUBMITTED)); close(); } }); } } } protected void searchPeople(String searchText) { if (searchText.length() >= 2) { matchingUsersTable.removeAllItems(); List<User> results = userCache.findMatchingUsers(searchText); for (User user : results) { if (!multiSelect || !selectedUsersTable.containsId(user.getId())) { if (ignoredUserIds == null || !ignoredUserIds.contains(user.getId())) { addMatchingUser(user.getId(), user.getFirstName() + " " + user.getLastName()); } } } } } protected void addMatchingUser(String userId, String name) { if (!matchingUsersTable.containsId(userId)) { Item item = matchingUsersTable.addItem(userId); item.getItemProperty("userName").setValue(name); } } protected void initUserSelection() { userSelectionLayout = new HorizontalLayout(); userSelectionLayout.setSpacing(true); addComponent(userSelectionLayout); initMatchingUsersTable(); // If multi select: two table to move users from left to the right // non-multi select: only one table if (multiSelect) { initSelectUserButton(); initSelectedUsersTable(); } } protected void initMatchingUsersTable() { matchingUsersTable = new Table(); matchingUsersTable.setColumnHeaderMode(Table.COLUMN_HEADER_MODE_HIDDEN); matchingUsersTable.setSelectable(true); matchingUsersTable.setEditable(false); matchingUsersTable.setImmediate(true); matchingUsersTable.setNullSelectionAllowed(false); matchingUsersTable.setSortDisabled(true); if (multiSelect) { matchingUsersTable.setMultiSelect(true); } matchingUsersTable.addGeneratedColumn("icon", new ThemeImageColumnGenerator(Images.USER_16)); matchingUsersTable.setColumnWidth("icon", 16); matchingUsersTable.addContainerProperty("userName", String.class, null); matchingUsersTable.setWidth(300, UNITS_PIXELS); matchingUsersTable.setHeight(200, UNITS_PIXELS); userSelectionLayout.addComponent(matchingUsersTable); } protected void initSelectUserButton() { selectUserButton = new Button(">"); selectUserButton.addListener(new ClickListener() { public void buttonClick(ClickEvent event) { for (String selectedItemId : (Set<String>) matchingUsersTable.getValue()) { // Remove from left table Item originalItem = matchingUsersTable.getItem(selectedItemId); // And put it in right table selectUser(selectedItemId, (String) originalItem.getItemProperty("userName").getValue()); // Remove from left table (must be done on the end, or item properties will be inaccessible) matchingUsersTable.removeItem(selectedItemId); } } }); userSelectionLayout.addComponent(selectUserButton); userSelectionLayout.setComponentAlignment(selectUserButton, Alignment.MIDDLE_CENTER); } protected void initSelectedUsersTable() { selectedUsersTable = new Table(); selectedUsersTable.setColumnHeaderMode(Table.COLUMN_HEADER_MODE_HIDDEN); selectedUsersTable.setEditable(false); selectedUsersTable.setSortDisabled(true); // Icon column selectedUsersTable.addGeneratedColumn("icon", new ThemeImageColumnGenerator(Images.USER_ADD)); selectedUsersTable.setColumnWidth("icon", 16); // Name column selectedUsersTable.addContainerProperty("userName", String.class, null); // Role column if (showRoles) { selectedUsersTable.addContainerProperty("role", ComboBox.class, null); } // Delete icon column selectedUsersTable.addGeneratedColumn("delete", new ThemeImageColumnGenerator(Images.DELETE, new com.vaadin.event.MouseEvents.ClickListener() { public void click(com.vaadin.event.MouseEvents.ClickEvent event) { Object itemId = ((Embedded) event.getSource()).getData(); // Add to left table (if possible) String searchFieldValue = (String) searchField.getValue(); if (searchFieldValue != null && searchFieldValue.length() >= 2) { String userName = (String) selectedUsersTable.getItem(itemId).getItemProperty("userName").getValue(); if (matchesSearchField(userName)) { Item item = matchingUsersTable.addItem(itemId); item.getItemProperty("userName").setValue(userName); } } // Delete from right table selectedUsersTable.removeItem(itemId); } })); selectedUsersTable.setColumnWidth("icon", 16); if (showRoles) { selectedUsersTable.setWidth(420, UNITS_PIXELS); } else { selectedUsersTable.setWidth(300, UNITS_PIXELS); } selectedUsersTable.setHeight(200, UNITS_PIXELS); userSelectionLayout.addComponent(selectedUsersTable); } protected boolean matchesSearchField(String text) { for (String userNameToken : text.split(" ")) { if (userNameToken.toLowerCase().startsWith(((String) searchField.getValue()).toLowerCase())) { return true; } } return false; } protected void selectUser(String userId, String userName) { if (!selectedUsersTable.containsId(userId)) { Item item = selectedUsersTable.addItem(userId); item.getItemProperty("userName").setValue(userName); if (showRoles) { ComboBox comboBox = new ComboBox(null, Arrays.asList( i18nManager.getMessage(Messages.TASK_ROLE_CONTRIBUTOR), i18nManager.getMessage(Messages.TASK_ROLE_IMPLEMENTER), i18nManager.getMessage(Messages.TASK_ROLE_MANAGER), i18nManager.getMessage(Messages.TASK_ROLE_SPONSOR))); comboBox.select(i18nManager.getMessage(Messages.TASK_ROLE_CONTRIBUTOR)); comboBox.setNewItemsAllowed(true); item.getItemProperty("role").setValue(comboBox); } } } protected void initDoneButton() { doneButton = new Button("Done"); doneButton.addListener(new ClickListener() { public void buttonClick(ClickEvent event) { // Fire event such that depending UI's can be updated fireEvent(new SubmitEvent(doneButton, SubmitEvent.SUBMITTED)); // close popup window close(); } }); addComponent(doneButton); windowLayout.setComponentAlignment(doneButton, Alignment.MIDDLE_RIGHT); } public String getSelectedUserId() { if (multiSelect) { throw new RuntimeException("Only use getSelectedUserId in non-multiselect mode"); } return (String) matchingUsersTable.getValue(); } @SuppressWarnings("unchecked") public Collection<String> getSelectedUserIds() { if (!multiSelect) { throw new RuntimeException("Only use getSelectedUserIds in multiselect mode"); } return (Collection<String>) selectedUsersTable.getItemIds(); } public String getSelectedUserRole(String userId) { if (!multiSelect) { throw new RuntimeException("Only use getSelectedUserIds in multiselect mode"); } return (String) ((ComboBox) selectedUsersTable.getItem(userId).getItemProperty("role").getValue()).getValue(); } }