| /** |
| * Copyright (c) 2011, 2015 - Lunifera GmbH (Gross Enzersdorf, Austria), Loetz GmbH&Co.KG (69115 Heidelberg, Germany) |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * Florian Pirchner - Initial implementation |
| */ |
| package org.eclipse.osbp.vaaclipse.ui.preferences.addon.internal; |
| |
| import java.util.ArrayList; |
| import java.util.HashSet; |
| import java.util.List; |
| |
| import javax.annotation.PostConstruct; |
| import javax.inject.Inject; |
| |
| import org.eclipse.e4.core.contexts.ContextInjectionFactory; |
| import org.eclipse.e4.core.contexts.IEclipseContext; |
| import org.eclipse.e4.core.di.annotations.Optional; |
| import org.eclipse.e4.core.services.events.IEventBroker; |
| import org.eclipse.emf.common.util.EList; |
| import org.eclipse.osbp.vaaclipse.ui.preferences.addon.PreferencesAuthorization; |
| import org.eclipse.osbp.vaaclipse.ui.preferences.addon.PreferencesEvents; |
| import org.eclipse.osbp.vaaclipse.ui.preferences.addon.internal.exception.ValidationFailedException; |
| import org.eclipse.osbp.vaaclipse.ui.preferences.addon.internal.util.ModelHelper; |
| import org.eclipse.osbp.vaaclipse.ui.preferences.addon.internal.util.PrefHelper; |
| import org.eclipse.osbp.vaaclipse.ui.preferences.model.FieldEditor; |
| import org.eclipse.osbp.vaaclipse.ui.preferences.model.PreferencesCategory; |
| import org.eclipse.osbp.vaaclipse.ui.preferences.model.PreferencesPage; |
| import org.osgi.framework.BundleContext; |
| import org.osgi.service.prefs.BackingStoreException; |
| import org.osgi.service.prefs.Preferences; |
| import org.eclipse.osbp.vaaclipse.publicapi.resources.BundleResource; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| import com.vaadin.data.Item; |
| import com.vaadin.event.FieldEvents.TextChangeEvent; |
| import com.vaadin.event.FieldEvents.TextChangeListener; |
| import com.vaadin.event.ItemClickEvent; |
| import com.vaadin.server.Sizeable; |
| import com.vaadin.shared.MouseEventDetails.MouseButton; |
| import com.vaadin.ui.Button; |
| import com.vaadin.ui.Button.ClickEvent; |
| import com.vaadin.ui.Button.ClickListener; |
| import com.vaadin.ui.CssLayout; |
| import com.vaadin.ui.HorizontalSplitPanel; |
| import com.vaadin.ui.Label; |
| import com.vaadin.ui.Notification; |
| import com.vaadin.ui.Panel; |
| import com.vaadin.ui.TextField; |
| import com.vaadin.ui.Tree; |
| import com.vaadin.ui.UI; |
| import com.vaadin.ui.VerticalLayout; |
| import com.vaadin.ui.Window; |
| |
| import e4modelextension.VaaclipseApplication; |
| |
| /** |
| * @author rushan |
| * |
| */ |
| public class PreferencesDialog { |
| |
| static final String PAGE_HEADER_ERROR_TEXT = "page-header-error-text"; |
| |
| @Inject |
| IEventBroker eventBroker; |
| |
| @Inject |
| VaaclipseApplication app; |
| |
| @Inject |
| IEclipseContext context; |
| |
| @Inject |
| @Optional |
| PreferencesCategory selectedCategory; |
| |
| @Inject |
| @Optional |
| PreferencesAuthorization authService; |
| |
| Logger logger = LoggerFactory.getLogger(PreferencesDialog.class); |
| |
| @Inject |
| UI ui; |
| |
| TextField filterField = new TextField(); |
| |
| private Tree tree; |
| |
| private Window window; |
| |
| HorizontalSplitPanel splitPanel = new HorizontalSplitPanel(); |
| |
| private Panel treePanel; |
| |
| private VerticalLayout rightSide; |
| |
| private CssLayout leftSide; |
| |
| private Button filterButton = new Button(); |
| private Button clearFilterButton = new Button(); |
| |
| private CssLayout pageHeader; |
| |
| private CssLayout pageContent; |
| |
| private CssLayout pageBottom; |
| |
| private Button restoreDefaults; |
| |
| private Button apply; |
| |
| private VerticalLayout root; |
| |
| private CssLayout dlgButtonPanel; |
| |
| private Button cancelButton; |
| |
| private Button okButton; |
| |
| private Label pageHeaderText; |
| |
| private BundleContext bundleContext; |
| |
| private String errorMessage; |
| |
| List<PreferencesPage> visitedPages = new ArrayList<>(); |
| |
| private HashSet<PreferencesCategory> visibleCategories; |
| |
| private List<PreferencesCategory> categoryList = new ArrayList<>(100); |
| |
| public Window getWindow() { |
| return window; |
| } |
| |
| public PreferencesCategory getSelectedCategory() { |
| return selectedCategory; |
| } |
| |
| public PreferencesPage getCurrentPage() { |
| return selectedCategory.getPage(); |
| } |
| |
| @PostConstruct |
| public void init() { |
| if (selectedCategory == null |
| && !app.getPreferencesCategories().isEmpty()) { |
| selectedCategory = app.getPreferencesCategories().get(0); |
| } |
| |
| createWindow(); |
| createSearchField(); |
| createTree(); |
| |
| addListeners(); |
| } |
| |
| public void createWindow() { |
| window = new Window(); |
| window.setCaption("Preferences"); |
| window.addStyleName("preferences-dialog"); |
| window.setWidth("800px"); |
| window.setHeight("600px"); |
| |
| splitPanel.setSizeFull(); |
| |
| dlgButtonPanel = new CssLayout(); |
| dlgButtonPanel.setWidth("100%"); |
| dlgButtonPanel.addStyleName("dlg-button-panel"); |
| |
| // dlgButtonPanel.addComponent(new Label("<hr/>", ContentMode.HTML)); |
| |
| cancelButton = new Button("Cancel"); |
| cancelButton.addStyleName("cancel-button"); |
| dlgButtonPanel.addComponent(cancelButton); |
| okButton = new Button("OK"); |
| okButton.addStyleName("ok-button"); |
| dlgButtonPanel.addComponent(okButton); |
| |
| root = new VerticalLayout(); |
| root.setSizeFull(); |
| window.setContent(root); |
| root.addComponent(splitPanel); |
| root.addComponent(dlgButtonPanel); |
| root.setExpandRatio(splitPanel, 10); |
| root.setExpandRatio(dlgButtonPanel, 0); |
| |
| treePanel = new Panel(); |
| treePanel.addStyleName("categories-panel"); |
| treePanel.addStyleName("borderless"); |
| treePanel.setSizeFull(); |
| |
| leftSide = new CssLayout(); |
| leftSide.addStyleName("categories"); |
| leftSide.setSizeFull(); |
| // filterField.setWidth("70%"); |
| filterField.addStyleName("categories-filter"); |
| leftSide.addComponent(filterField); |
| |
| filterButton |
| .setIcon(BundleResource |
| .valueOf("platform:/plugin/org.eclipse.osbp.vaaclipse.ui.preferences.addon/img/find.png")); |
| filterButton.addStyleName("vaaclipsebutton"); |
| filterButton.addStyleName("icon-only"); |
| filterButton.addStyleName("filter-category-button"); |
| |
| clearFilterButton |
| .setIcon(BundleResource |
| .valueOf("platform:/plugin/org.eclipse.osbp.vaaclipse.ui.preferences.addon/img/clear.png")); |
| clearFilterButton.addStyleName("vaaclipsebutton"); |
| clearFilterButton.addStyleName("icon-only"); |
| clearFilterButton.addStyleName("clear-filter-button"); |
| |
| leftSide.addComponent(clearFilterButton); |
| leftSide.addComponent(filterButton); |
| leftSide.addComponent(treePanel); |
| |
| rightSide = new VerticalLayout(); |
| rightSide.setSizeFull(); |
| // rightSide.setMargin(new MarginInfo(true, true, false, true)); |
| |
| pageHeader = new CssLayout(); |
| pageHeader.addStyleName("page-header-panel"); |
| pageHeader.setWidth("100%"); |
| pageHeaderText = new Label("Page"); |
| pageHeaderText.addStyleName("page-header-text"); |
| pageHeader.addComponent(pageHeaderText); |
| rightSide.addComponent(pageHeader); |
| |
| pageContent = new CssLayout(); |
| // pageContent.setSizeFull(); |
| Panel pageContentPanel = new Panel(pageContent);// wrap page content to |
| // panel - if content is |
| // too large, scrolling |
| // needed |
| pageContentPanel.setSizeFull(); |
| rightSide.addComponent(pageContentPanel); |
| |
| pageBottom = new CssLayout(); |
| pageBottom.addStyleName("page-bottom-panel"); |
| pageBottom.setWidth("100%"); |
| rightSide.addComponent(pageBottom); |
| |
| apply = new Button("Apply"); |
| apply.addStyleName("apply"); |
| pageBottom.addComponent(apply); |
| |
| restoreDefaults = new Button("RestoreDefaults"); |
| restoreDefaults.addStyleName("restore-defaults"); |
| pageBottom.addComponent(restoreDefaults); |
| |
| splitPanel.addComponent(leftSide); |
| splitPanel.addComponent(rightSide); |
| splitPanel.setSplitPosition(30, Sizeable.Unit.PERCENTAGE); |
| |
| rightSide.setExpandRatio(pageHeader, 0); |
| rightSide.setExpandRatio(pageContentPanel, 1); |
| rightSide.setExpandRatio(pageBottom, 0); |
| |
| clearFilterButton.addClickListener(new ClickListener() { |
| @Override |
| public void buttonClick(ClickEvent event) { |
| filterField.setValue(""); |
| refreshTree(); |
| } |
| }); |
| |
| filterButton.addClickListener(new ClickListener() { |
| |
| @Override |
| public void buttonClick(ClickEvent event) { |
| refreshTree(); |
| } |
| }); |
| } |
| |
| public void createSearchField() { |
| filterField.addTextChangeListener(new TextChangeListener() { |
| |
| @Override |
| public void textChange(TextChangeEvent event) { |
| refreshTree(); |
| } |
| }); |
| } |
| |
| private void createTree() { |
| tree = new Tree(); |
| tree.setSizeFull(); |
| tree.setImmediate(true); |
| treePanel.setContent(tree); |
| |
| tree.addContainerProperty("name", String.class, "NoName"); |
| tree.setItemCaptionPropertyId("name"); |
| |
| ModelHelper.buildChildCategoryListIncludeThisList( |
| app.getPreferencesCategories(), categoryList); |
| |
| refreshTree(); |
| |
| tree.addItemClickListener(new ItemClickEvent.ItemClickListener() { |
| |
| public void itemClick(final ItemClickEvent event) { |
| if (event.getButton() == MouseButton.LEFT) { |
| PreferencesCategory selectedCat = (PreferencesCategory) event |
| .getItemId(); |
| if (selectedCat != null) { |
| openPreferencePageForCategory(selectedCat); |
| } |
| } |
| } |
| }); |
| |
| if (selectedCategory != null) { |
| tree.select(selectedCategory); |
| openPreferencePageForCategory(selectedCategory); |
| } |
| } |
| |
| private void refreshTree() { |
| tree.removeAllItems(); |
| |
| EList<PreferencesCategory> catList = app.getPreferencesCategories(); |
| |
| markVisibility(); |
| |
| fillCategories(catList, null); |
| |
| for (Object id : tree.rootItemIds()) { |
| tree.expandItemsRecursively(id); |
| } |
| } |
| |
| private void markVisibility() { |
| visibleCategories = new HashSet<PreferencesCategory>(); |
| |
| String filterValue = filterField.getValue(); |
| if (filterValue.isEmpty()) { |
| return; |
| } |
| for (PreferencesCategory category : categoryList) { |
| if (category != null && category.getName().contains(filterValue)) { |
| do { |
| visibleCategories.add(category); |
| category = category.getParentCategory(); |
| } while (category != null); |
| } |
| } |
| } |
| |
| @SuppressWarnings("unchecked") |
| private void fillCategories(List<PreferencesCategory> list, |
| PreferencesCategory parentCat) { |
| String search = filterField.getValue().trim(); |
| for (PreferencesCategory c : list) { |
| |
| if (authService != null && c.getParentCategory() != null |
| && "user".equals(c.getParentCategory().getId()) |
| && !authService.isAllowed(c)) { |
| continue; |
| } |
| |
| if (c.getName() == null) |
| c.setName("No Name"); |
| if (filterField.getValue().isEmpty() |
| || visibleCategories.contains(c)) { |
| |
| Item catItem = tree.addItem(c); |
| catItem.getItemProperty("name").setValue(c.getName()); |
| if (c.getChildCategories().isEmpty()) |
| tree.setChildrenAllowed(c, false); |
| |
| if (parentCat != null) |
| tree.setParent(c, parentCat); |
| |
| fillCategories(c.getChildCategories(), c); |
| } |
| } |
| } |
| |
| private void openPreferencePageForCategory(PreferencesCategory selectedCat) { |
| selectedCategory = selectedCat; |
| refreshHeaderMessage(); |
| |
| pageContent.removeAllComponents(); |
| |
| if (selectedCat.getPage() != null) { |
| IEclipseContext pageContext = context.createChild(); |
| pageContext.set(CssLayout.class, pageContent); |
| pageContext.set(PreferencesPage.class, selectedCat.getPage()); |
| PreferencesPageRenderer pageRenderer = ContextInjectionFactory |
| .make(PreferencesPageRenderer.class, pageContext); |
| pageRenderer.render(); |
| visitedPages.add(selectedCat.getPage()); |
| } else if (!selectedCat.getChildCategories().isEmpty()) { |
| pageContent |
| .addComponent(new Label( |
| "Expand the tree to edit a preferences for a specific feature")); |
| } |
| } |
| |
| private void addListeners() { |
| |
| restoreDefaults.addClickListener(new ClickListener() { |
| |
| @Override |
| public void buttonClick(ClickEvent event) { |
| restoreDefaults(); |
| } |
| }); |
| |
| apply.addClickListener(new ClickListener() { |
| |
| @Override |
| public void buttonClick(ClickEvent event) { |
| applyPressed(); |
| } |
| }); |
| |
| okButton.addClickListener(new ClickListener() { |
| |
| @Override |
| public void buttonClick(ClickEvent event) { |
| okPressed(); |
| } |
| }); |
| |
| cancelButton.addClickListener(new ClickListener() { |
| |
| @Override |
| public void buttonClick(ClickEvent event) { |
| cancelPressed(); |
| } |
| }); |
| } |
| |
| public void setErrorMessage(String errorMessage) { |
| this.errorMessage = errorMessage; |
| refreshHeaderMessage(); |
| } |
| |
| public void clearErrorMessage() { |
| this.errorMessage = null; |
| refreshHeaderMessage(); |
| } |
| |
| public void refreshHeaderMessage() { |
| if (errorMessage != null) { |
| pageHeaderText.addStyleName(PAGE_HEADER_ERROR_TEXT); |
| pageHeaderText.setValue(errorMessage); |
| } else { |
| pageHeaderText.removeStyleName(PAGE_HEADER_ERROR_TEXT); |
| pageHeaderText.setValue(selectedCategory.getName()); |
| } |
| } |
| |
| private void restoreDefaults() { |
| PreferencesPage currentPage = getCurrentPage(); |
| if (currentPage != null) { |
| try { |
| restoreDefaultsOnPage(currentPage); |
| } catch (Exception e) { |
| Notification.show("Error restoring defaults", |
| "Restoring defaults on this page failed", |
| Notification.Type.ERROR_MESSAGE); |
| return; |
| } |
| fireEvent(PreferencesEvents.PREFERENCES_TO_DEFAULTS, currentPage); |
| |
| // Refresh the current page (it should be rerendered) |
| openPreferencePageForCategory(getSelectedCategory()); |
| } |
| } |
| |
| private void okPressed() { |
| |
| Exception exception = null; |
| for (PreferencesPage page : visitedPages) { |
| try { |
| applyChangesOnPage(page); |
| } catch (ValidationFailedException validationException) { |
| setErrorMessage(validationException.getLocalizedMessage()); |
| Notification.show("Validation failed", |
| validationException.getLocalizedMessage(), |
| Notification.Type.WARNING_MESSAGE); |
| return; |
| } catch (Exception e) { |
| exception = e; |
| } |
| } |
| if (exception != null) { |
| String errorMessage = "Saving changes was failed on some pages"; |
| setErrorMessage(errorMessage); |
| Notification.show("Error apply changes", errorMessage, |
| Notification.Type.ERROR_MESSAGE); |
| return; |
| } else { |
| fireEvent(PreferencesEvents.PREFERENCES_APPLIED, |
| (PreferencesPage[]) visitedPages |
| .toArray(new PreferencesPage[visitedPages.size()])); |
| } |
| |
| clearErrorMessage(); |
| |
| ui.removeWindow(window); |
| } |
| |
| private void cancelPressed() { |
| ui.removeWindow(window); |
| } |
| |
| private void applyPressed() { |
| PreferencesPage currentPage = getCurrentPage(); |
| if (currentPage != null) { |
| try { |
| applyChangesOnPage(currentPage); |
| } catch (ValidationFailedException validationException) { |
| setErrorMessage(validationException.getLocalizedMessage()); |
| Notification.show("Validation failed", |
| "The preferences is not correct", |
| Notification.Type.WARNING_MESSAGE); |
| return; |
| } catch (Exception e) { |
| setErrorMessage("Applying changes on this page failed"); |
| Notification.show("Error apply changes", |
| "Applying changes on this page failed", |
| Notification.Type.ERROR_MESSAGE); |
| return; |
| } |
| clearErrorMessage(); |
| fireEvent(PreferencesEvents.PREFERENCES_APPLIED, currentPage); |
| } |
| } |
| |
| private void applyChangesOnPage(PreferencesPage page) |
| throws BackingStoreException, ValidationFailedException { |
| PreferencesPageRenderer pageRenderer = (PreferencesPageRenderer) page |
| .getRenderer(); |
| |
| pageRenderer.validate(); |
| |
| try { |
| pageRenderer.save(); |
| } catch (Exception e) { |
| logger.error( |
| "Error copy changes from UI to preferences for category {}", |
| selectedCategory.getName(), e); |
| throw e; |
| } |
| |
| try { |
| PrefHelper.flush(page); |
| } catch (BackingStoreException e) { |
| logger.error("Error flushing changes for category {}", page |
| .getCategory().getName(), e); |
| throw e; |
| } |
| } |
| |
| private void restoreDefaultsOnPage(PreferencesPage page) |
| throws BackingStoreException { |
| |
| try { |
| for (FieldEditor<?> fieldEditor : page.getChildren()) { |
| String defaultValue = fieldEditor.getDefaultValue(); |
| if (defaultValue != null) |
| ((Preferences) fieldEditor.getPreferences()).put( |
| fieldEditor.getPreferenceName(), defaultValue); |
| } |
| } catch (Exception e) { |
| logger.error( |
| "Error copy default values from model to preferences for category {}", |
| page.getCategory().getName(), e); |
| throw e; |
| } |
| |
| try { |
| PrefHelper.flush(page); |
| } catch (BackingStoreException e) { |
| logger.error("Error flushing changes for category {}", page |
| .getCategory().getName(), e); |
| throw e; |
| } |
| } |
| |
| private void fireEvent(String topic, PreferencesPage... pages) { |
| eventBroker.send(topic, pages); |
| } |
| } |