/******************************************************************************* * Copyright (c) 2004, 2012 BREDEX GmbH. * 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: * BREDEX GmbH - initial API and implementation and/or initial documentation *******************************************************************************/ package org.eclipse.jubula.client.teststyle.properties; import java.util.Map; import javax.persistence.EntityManager; import org.eclipse.jface.dialogs.Dialog; import org.eclipse.jface.viewers.CheckStateChangedEvent; import org.eclipse.jface.viewers.CheckboxTreeViewer; import org.eclipse.jface.viewers.ICheckStateListener; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.ITreeSelection; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.window.Window; import org.eclipse.jubula.client.core.model.ICheckConfContPO; import org.eclipse.jubula.client.core.model.ICheckConfPO; import org.eclipse.jubula.client.core.model.IProjectPO; import org.eclipse.jubula.client.core.persistence.GeneralStorage; import org.eclipse.jubula.client.teststyle.ExtensionHelper; import org.eclipse.jubula.client.teststyle.TeststyleHandler; import org.eclipse.jubula.client.teststyle.checks.BaseCheck; import org.eclipse.jubula.client.teststyle.checks.Severity; import org.eclipse.jubula.client.teststyle.i18n.Messages; import org.eclipse.jubula.client.teststyle.properties.dialogs.attributes.EditAttributeDialog; import org.eclipse.jubula.client.teststyle.properties.dialogs.contexts.EditContextDialog; import org.eclipse.jubula.client.teststyle.properties.nodes.CategoryNode; import org.eclipse.jubula.client.teststyle.properties.nodes.CheckNode; import org.eclipse.jubula.client.teststyle.properties.nodes.INode; import org.eclipse.jubula.client.teststyle.properties.nodes.INode.TreeState; import org.eclipse.jubula.client.teststyle.properties.provider.TeststyleBoxProvider; import org.eclipse.jubula.client.teststyle.properties.provider.TeststyleContentProvider; import org.eclipse.jubula.client.teststyle.properties.provider.TeststyleLabelProvider; import org.eclipse.jubula.client.ui.constants.ContextHelpIds; import org.eclipse.jubula.client.ui.rcp.properties.AbstractProjectPropertyPage; import org.eclipse.jubula.client.ui.rcp.properties.ProjectGeneralPropertyPage.IOkListener; import org.eclipse.jubula.client.ui.widgets.UIComponentHelper; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.StyledText; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.TreeItem; import org.eclipse.ui.PlatformUI; /** * @author marcell * @created Oct 18, 2010 */ public class TeststyleProjectPropertyPage extends AbstractProjectPropertyPage implements IOkListener { // Constants /** Style of the treeviewer */ private static final int TREE_STYLE = SWT.SINGLE | SWT.BORDER | SWT.FULL_SELECTION; /** Text of the teststyle configuration group */ private static final String TS_GROUP = Messages.PropertyFullGroup; /** Text of the enablement checkbox */ private static final String CHK_ENABLED = Messages.PropertyEnableRadio; /** Text of the group */ private static final String GRP_TXT = Messages.PropertyEditGroup; /** Text of the button which edits attributes */ private static final String BTN_ATTR = Messages.PropertyButtonAttribute; /** Text of the button which edits contexts */ private static final String BTN_CONT = Messages.PropertyButtonContext; /** Text of the button which selects everything */ private static final String BTN_SELECT_ALL = Messages.PropertyButtonSelectAll; /** Text of the button which edits contexts */ private static final String BTN_DESELECT_ALL = Messages.PropertyButtonDeselectAll; /** Text that is in the description label */ private static final String LBL_DESCRIPTION = Messages.PropertyLabelDescription; /** ContextHelpId for TESTSTYLE_PROPERTY_PAGE */ private static final String TESTSTYLE_PROPERTY_PAGE = ContextHelpIds.PRAEFIX + "testStylePropertyPageContextId"; //$NON-NLS-1$ // The gui components of the property page /** The composite where all the elements are stored */ private Composite m_composite; /** checkbox that en- or disables teststyle */ private Button m_enabledCheckbox; /** The group where all the important elements are stored */ private Group m_fullGroup; /** The CheckBoxTreeViewer which contains the checks and categories */ private CheckboxTreeViewer m_treeView; /** The composite which contains the tree with the buttons */ private Composite m_treeComposite; /** button for selecting everything */ private Button m_selectAllBtn; /** button for select nothing */ private Button m_deselectAllBtn; /** The button for editing the attributes */ private Button m_editAttrBtn; /** The button for editing the contexts */ private Button m_editContBtn; /** Combobox for editing the severity of a check */ private Combo m_editSeverity; /** textfield for the description */ private StyledText m_descriptionText; // The content provider /** The content provider for the tree */ private TeststyleContentProvider m_treeContentProvider; /** The label provider for the tree */ private TeststyleLabelProvider m_treeLabelProvider; /** The check provider for the tree */ private TeststyleBoxProvider m_treeCheckProvider; // temporary variables that will be synchronized when accepting the project // properties /** is enabled */ private boolean m_enabled; /** * {@inheritDoc} */ protected Control createContents(Composite parent) { m_composite = PropUtils.createCustomComposite(parent); m_enabled = TeststyleHandler.getInstance().isEnabled(); // First we create all elements createProvider(); createEnabledCheckbox(); createFullGroup(); createTreeComposite(); createGroup(); createDescriptionField(); // Then we set their events setTreeEvents(); setGrpEvents(); // set default enablement setTeststyleEnabled(m_enabled); return parent; } /** * */ private void createDescriptionField() { Label lbl = new Label(m_fullGroup, SWT.NULL); lbl.setText(LBL_DESCRIPTION); GridData lblData = new GridData(); lblData.horizontalSpan = 2; lblData.grabExcessHorizontalSpace = true; lbl.setLayoutData(lblData); m_descriptionText = new StyledText(m_fullGroup, SWT.MULTI | SWT.READ_ONLY | SWT.BORDER | SWT.WRAP); m_descriptionText.setCursor(getShell().getDisplay().getSystemCursor( SWT.CURSOR_ARROW)); m_descriptionText.setCaret(null); GridData txtData = new GridData(SWT.DEFAULT, 55); txtData.horizontalSpan = 2; txtData.grabExcessHorizontalSpace = true; txtData.horizontalAlignment = SWT.FILL; m_descriptionText.setBackground(getShell().getDisplay().getSystemColor( SWT.COLOR_WIDGET_BACKGROUND)); m_descriptionText.setLayoutData(txtData); } /** * */ private void createEnabledCheckbox() { m_enabledCheckbox = new Button(m_composite, SWT.CHECK); m_enabledCheckbox.setText(CHK_ENABLED); m_enabledCheckbox.setSelection(m_enabled); m_enabledCheckbox.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { m_enabled = m_enabledCheckbox.getSelection(); setTeststyleEnabled(m_enabled); getApplyButton().setEnabled(true); } }); } /** * */ private void createFullGroup() { // Create the layout GridLayout layout = new GridLayout(); layout.marginHeight = PropUtils.MARGIN_HEIGHT; layout.marginWidth = PropUtils.MARGIN_WIDTH; layout.numColumns = PropUtils.NUM_COLUMNS; // Create the GridData for this composite GridData data = new GridData(SWT.FILL, SWT.FILL, true, true); data.heightHint = PropUtils.WIDTH; data.widthHint = PropUtils.HEIGHT; m_fullGroup = new Group(m_composite, SWT.NULL); m_fullGroup.setText(TS_GROUP); m_fullGroup.setLayout(layout); m_fullGroup.setLayoutData(data); } /** * Overwritten due to the standard enablement of the apply button. * {@inheritDoc} */ public void createControl(Composite parent) { super.createControl(parent); // disable the apply button by default getApplyButton().setEnabled(false); PlatformUI.getWorkbench().getHelpSystem().setHelp( parent, TESTSTYLE_PROPERTY_PAGE); } /** * Creates all providers this property page uses. */ private void createProvider() { /* The content provider for the tree */ m_treeContentProvider = new TeststyleContentProvider(); /* The label provider for the tree */ m_treeLabelProvider = new TeststyleLabelProvider(); /* The check provider for the tree */ m_treeCheckProvider = new TeststyleBoxProvider(); } /** * Creates the tree where the categories and the checks are stored * afterwards. */ private void createTreeComposite() { // First create the griddata, so that the new element fits nicely GridData compGridData = new GridData(SWT.FILL, SWT.FILL, true, true); GridData treeGridData = new GridData(SWT.FILL, SWT.FILL, true, true); treeGridData.horizontalSpan = 2; GridData btn1GridData = new GridData(SWT.END, SWT.FILL, true, false); GridData btn2GridData = new GridData(SWT.END, SWT.FILL, false, false); // Then create the composite and use the new griddata m_treeComposite = new Composite(m_fullGroup, SWT.NONE); // Set the layout of the composite GridLayout layout = new GridLayout(); layout.marginHeight = 0; // no borders layout.marginWidth = 0; // no borders layout.numColumns = 2; // 2 columns so that the button are correct m_treeComposite.setLayout(layout); m_treeComposite.setLayoutData(compGridData); // Create the tree on the approriate place m_treeView = new CheckboxTreeViewer(m_treeComposite, TREE_STYLE); m_treeView.getTree().setLayoutData(treeGridData); // create the two buttons for selecting everything or nothing m_selectAllBtn = new Button(m_treeComposite, SWT.PUSH); m_selectAllBtn.setText(BTN_SELECT_ALL); m_selectAllBtn.setLayoutData(btn1GridData); m_deselectAllBtn = new Button(m_treeComposite, SWT.PUSH); m_deselectAllBtn.setText(BTN_DESELECT_ALL); m_deselectAllBtn.setLayoutData(btn2GridData); // The next methods fills the tree with stuff m_treeView.setContentProvider(m_treeContentProvider); m_treeView.setLabelProvider(m_treeLabelProvider); m_treeView.setCheckStateProvider(m_treeCheckProvider); m_treeView.setInput(PropUtils.getCategoriesAsNodes()); // Set the default expansion to two, so that the checks are visible m_treeView.setAutoExpandLevel(2); m_treeView.expandToLevel(2); } /** * Creates the Group with the buttons for specific editing purposes. */ private void createGroup() { // First create the griddata, so that the new group fits nicely Composite cmp = new Composite(m_fullGroup, SWT.NONE); cmp.setLayoutData(new GridData(SWT.NULL, SWT.FILL, false, false)); cmp.setLayout(new FillLayout(SWT.VERTICAL)); // Then create the new group Group grp = new Group(cmp, SWT.NULL); grp.setText(GRP_TXT); grp.setLayout(new GridLayout(1, false)); // grp.setLayoutData(); // Now puts the buttons and the radio thing in the group, first for // editing the attributes m_editAttrBtn = new Button(grp, SWT.PUSH); m_editAttrBtn.setText(BTN_ATTR); m_editAttrBtn.setEnabled(false); // Then for editing the contexts. m_editContBtn = new Button(grp, SWT.PUSH); m_editContBtn.setText(BTN_CONT); m_editContBtn.setEnabled(false); // Then for editing the severity m_editSeverity = new Combo(grp, SWT.DROP_DOWN | SWT.READ_ONLY); String[] items = new String[Severity.values().length]; for (int i = 0; i < items.length; i++) { items[i] = Severity.values()[i].toString(); } m_editSeverity.setItems(items); m_editSeverity.setEnabled(false); } /** * Sets the events for the tree. */ public void setTreeEvents() { m_treeView.addCheckStateListener(new ICheckStateListener() { @SuppressWarnings("synthetic-access") public void checkStateChanged(CheckStateChangedEvent event) { INode node = (INode) event.getElement(); if (event.getChecked()) { node.setState(TreeState.CHECKED); } else { node.setState(TreeState.EMPTY); } // refreshing the tree where its needed if (node instanceof CategoryNode) { for (INode child : node.getChildren()) { m_treeView.refresh(child); } m_treeView.refresh(node); } else if (node instanceof CheckNode) { m_treeView.refresh(node.getParent()); } m_treeView.setSelection(new StructuredSelection(node)); getApplyButton().setEnabled(true); } }); m_treeView.addSelectionChangedListener(new ISelectionChangedListener() { @SuppressWarnings("synthetic-access") public void selectionChanged(SelectionChangedEvent event) { // This events comes from a tree, so its a treeselection ITreeSelection treeSel = (ITreeSelection) event.getSelection(); // Is it empty? If not, is it a node which contains a check? boolean empty = treeSel.isEmpty(); INode selected = (INode) treeSel.getFirstElement(); boolean isEditable = !empty && selected.isEditable(); boolean hasSeverity = !empty && selected.hasSeverity(); m_editAttrBtn.setEnabled(isEditable); m_editContBtn.setEnabled(isEditable); m_editSeverity.setEnabled(hasSeverity); if (hasSeverity) { m_editSeverity.setText(((CheckNode) selected).getSeverity() .name()); } m_descriptionText.setText(selected.getTooltip()); } }); m_selectAllBtn.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { selectAll(); } }); m_deselectAllBtn.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { deselectAll(); } }); } /** * Selects every element in the tree. */ void selectAll() { INode[] categories = (INode[]) m_treeContentProvider.getElements(null); for (INode category : categories) { category.setState(TreeState.CHECKED); } m_treeView.refresh(); getApplyButton().setEnabled(true); } /** * Deselects every element in the tree. */ void deselectAll() { INode[] categories = (INode[]) m_treeContentProvider.getElements(null); for (INode category : categories) { category.setState(TreeState.EMPTY); } m_treeView.refresh(); getApplyButton().setEnabled(true); } /** * Sets the events for the buttons. */ public void setGrpEvents() { m_editAttrBtn.addSelectionListener(new SelectionAdapter() { @SuppressWarnings("synthetic-access") public void widgetSelected(SelectionEvent e) { ITreeSelection sel = (ITreeSelection) m_treeView.getSelection(); CheckNode node = (CheckNode) sel.getFirstElement(); BaseCheck check = node.getCheck(); Dialog dlg = new EditAttributeDialog(getShell(), check); int status = dlg.open(); if (status == Window.OK) { getApplyButton().setEnabled(true); } } }); m_editContBtn.addSelectionListener(new SelectionAdapter() { @SuppressWarnings("synthetic-access") public void widgetSelected(SelectionEvent e) { ITreeSelection sel = (ITreeSelection) m_treeView.getSelection(); CheckNode node = (CheckNode) sel.getFirstElement(); BaseCheck check = node.getCheck(); Dialog dlg = new EditContextDialog(getShell(), check); int status = dlg.open(); if (status == Window.OK) { getApplyButton().setEnabled(true); } } }); m_editSeverity.addSelectionListener(new SelectionAdapter() { @SuppressWarnings("synthetic-access") public void widgetSelected(SelectionEvent e) { Severity newSev = Severity.valueOf(m_editSeverity.getText()); ITreeSelection sel = (ITreeSelection) m_treeView.getSelection(); CheckNode node = (CheckNode) sel.getFirstElement(); node.setSeverity(newSev); getApplyButton().setEnabled(true); } }); } /** * {@inheritDoc} */ protected void performApply() { okPressed(); getApplyButton().setEnabled(false); } /** * {@inheritDoc} */ public void okPressed() { if (m_treeContentProvider != null) { EntityManager s = getEditSupport().getSession(); IProjectPO project = GeneralStorage.getInstance().getProject(); ICheckConfContPO cfg = s.merge(project.getProjectProperties() .getCheckConfCont()); cfg.setEnabled(m_enabled); m_treeContentProvider.save(s); } } /** * {@inheritDoc} */ public void applyData(Object data) { super.applyData(data); if (data instanceof String) { INode nodeToSelect = null; String checkstyleID = (String)data; Object[] allExpandedElements = m_treeView.getExpandedElements(); for (Object o : allExpandedElements) { if (o instanceof CategoryNode) { CategoryNode catNode = (CategoryNode)o; for (INode node : catNode.getChildren()) { if (node instanceof CheckNode) { CheckNode cn = (CheckNode)node; if (cn.getCheck().getId().equals(checkstyleID)) { nodeToSelect = cn; break; } } } if (nodeToSelect != null) { break; } } } m_treeView .setSelection(new StructuredSelection(nodeToSelect), true); } } /** * {@inheritDoc} */ protected void performDefaults() { Map<String, ICheckConfPO> defaults = ExtensionHelper.getDefaults(); INode[] categories = (INode[]) m_treeContentProvider.getElements(null); for (INode category : categories) { for (INode child : category.getChildren()) { CheckNode checkNode = (CheckNode) child; ICheckConfPO defaultCfg = defaults.get(checkNode.getCheck() .getId()); ICheckConfPO currentCfg = checkNode.getCheck().getConf(); currentCfg.setActive(defaultCfg.isActive()); currentCfg.setSeverity(defaultCfg.getSeverity()); currentCfg.setAttr(defaultCfg.getAttr()); currentCfg.setContexts(defaultCfg.getContexts()); if (checkNode.hasSeverity()) { m_editSeverity.setText(checkNode.getSeverity().name()); } } } m_treeView.refresh(); getApplyButton().setEnabled(true); } /** * @param enabled * If teststyle is enabled for this project or not. */ private void setTeststyleEnabled(boolean enabled) { UIComponentHelper.setEnabledRecursive(m_fullGroup, enabled); m_editAttrBtn.setEnabled(false); m_editContBtn.setEnabled(false); m_editSeverity.setEnabled(false); m_treeView.getTree().setSelection(new TreeItem[] {}); } }