/* * JBoss, Home of Professional Open Source. * * See the LEGAL.txt file distributed with this work for information regarding copyright ownership and licensing. * * See the AUTHORS.txt file distributed with this work for a full listing of individual contributors. */ package org.teiid.designer.ui.wizards; import org.eclipse.core.resources.IFile; import org.eclipse.jface.viewers.CheckStateChangedEvent; import org.eclipse.jface.viewers.ICheckStateListener; import org.eclipse.jface.window.Window; import org.eclipse.jface.wizard.WizardPage; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Text; import org.eclipse.swt.widgets.Tree; import org.eclipse.ui.dialogs.ElementTreeSelectionDialog; import org.teiid.designer.core.ModelerCore; import org.teiid.designer.core.metamodel.MetamodelDescriptor; import org.teiid.designer.core.workspace.ModelResource; import org.teiid.designer.core.workspace.ModelUtil; import org.teiid.designer.ui.UiConstants; import org.teiid.designer.ui.common.tree.TreeViewerUtil; import org.teiid.designer.ui.common.util.WidgetFactory; import org.teiid.designer.ui.common.viewsupport.ClosedProjectFilter; import org.teiid.designer.ui.common.viewsupport.DotProjectFilter; import org.teiid.designer.ui.common.widget.INodeDescendantsDeselectionHandler; import org.teiid.designer.ui.common.widget.InheritanceCheckboxTreeViewer; import org.teiid.designer.ui.viewsupport.ModelResourceSelectionValidator; import org.teiid.designer.ui.viewsupport.ModelWorkspaceTreeProvider; import org.teiid.designer.ui.viewsupport.ModelingResourceFilter; /** * Extension to Composite containing an InheritanceCheckboxTreeViewer, and intended only for the case where the Composite is the * only thing appearing on a WizardPage. The WizardPage is passed in as a constructor argument and two of its methods are called: * setErrorMessage(), and setPageComplete(). The wizard page is set to complete iff. at least one item in the tree is checked. * * @since 8.0 */ public class CheckboxTreeViewerWizardPanel extends Composite implements UiConstants, ICheckboxTreeViewerListenerController { private final static String BROWSE_SHORTHAND = "..."; //$NON-NLS-1$ private final static int FILE_NAME_TEXT_WIDTH = (int)(Display.getCurrent().getBounds().width * .25); private final static String SELECT_MODEL_TITLE = Util.getString("StructuralCopyWizardPage.selectModelTitle"); //$NON-NLS-1$ private final static String SELECT_MODEL_MSG = Util.getString("StructuralCopyWizardPage.selectModelMsg"); //$NON-NLS-1$ private final static String CHECK_ALL = Util.getString("StructuralCopyWizardPage.checkAll"); //$NON-NLS-1$ private final static String UNCHECK_ALL = Util.getString("StructuralCopyWizardPage.uncheckAll"); //$NON-NLS-1$ private final static String COPY_ALL_DESCRIPTIONS = Util.getString("StructuralCopyWizardPage.copyAllDescriptions"); //$NON-NLS-1$ private WizardPage wizardPage; private INodeDescendantsDeselectionHandler deselectionHandler; private Text fileNameText; private Button browseButton; private Button checkAllButton; private Button uncheckAllButton; private Button copyAllDescriptions; private IStructuralCopyTreePopulator populator = null; private Tree tree; InheritanceCheckboxTreeViewer treeViewer; private MetamodelDescriptor metamodelDescriptor; private ModelResource selectorDialogResult = null; boolean listenForCheckboxChanges = true; protected boolean targetIsVirtual; private boolean firstTimeVisible = true; private boolean copyEntire; public CheckboxTreeViewerWizardPanel( Composite parent, WizardPage wizardPage, INodeDescendantsDeselectionHandler deselectionHandler, MetamodelDescriptor metamodelDescriptor, ModelResource selection, boolean targetIsVirtual ) { super(parent, SWT.NULL); this.wizardPage = wizardPage; this.deselectionHandler = deselectionHandler; this.metamodelDescriptor = metamodelDescriptor; this.selectorDialogResult = selection; this.targetIsVirtual = targetIsVirtual; initialize(); } public InheritanceCheckboxTreeViewer getViewer() { return treeViewer; } public IStructuralCopyTreePopulator getTreePopulator() { return populator; } @Override public void enableCheckboxChangeListener( boolean flag ) { this.listenForCheckboxChanges = flag; } @Override public void checkboxStateChanged() { checkedItemsChanged(); } private void initialize() { GridLayout layout = new GridLayout(); this.setLayout(layout); Composite fileComposite = new Composite(this, SWT.NONE); GridLayout fileCompositeLayout = new GridLayout(); fileComposite.setLayout(fileCompositeLayout); fileCompositeLayout.numColumns = 3; fileCompositeLayout.marginWidth = 0; GridData fileCompositeGridData = new GridData(GridData.FILL_HORIZONTAL); fileComposite.setLayoutData(fileCompositeGridData); Label schemaNameLabel = new Label(fileComposite, SWT.NONE); schemaNameLabel.setText(Util.getString("StructuralCopyWizardPage.existingModelLabel")); //$NON-NLS-1$ fileNameText = WidgetFactory.createTextField(fileComposite, GridData.HORIZONTAL_ALIGN_FILL); fileNameText.setEditable(false); // Line Below will maintain White background, if desired. // fileNameText.setBackground(UiUtil.getSystemColor(SWT.COLOR_WHITE)); GridData fileNameTextGridData = new GridData(); fileNameTextGridData.widthHint = FILE_NAME_TEXT_WIDTH; fileNameText.setLayoutData(fileNameTextGridData); browseButton = new Button(fileComposite, SWT.PUSH); browseButton.setText(BROWSE_SHORTHAND); browseButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected( SelectionEvent ev ) { browseButtonClicked(); } }); Group treeGroup = new Group(this, SWT.NONE); GridLayout treeGroupLayout = new GridLayout(); treeGroup.setLayout(treeGroupLayout); GridData treeGroupGridData = new GridData(GridData.FILL_BOTH); treeGroup.setLayoutData(treeGroupGridData); // copy selection buttons: Button copyEntire = new Button(treeGroup, SWT.RADIO); copyEntire.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); copyEntire.setText(Util.getString("StructuralCopyWizardPage.copyEntireLabel")); //$NON-NLS-1$ final Button selectFeatures = new Button(treeGroup, SWT.RADIO); selectFeatures.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); selectFeatures.setText(Util.getString("StructuralCopyWizardPage.selectFeaturesLabel")); //$NON-NLS-1$ // note that we add selection listeners below the tree stuff and its buttons... // selection tree: tree = new Tree(treeGroup, SWT.V_SCROLL | SWT.H_SCROLL | SWT.CHECK | SWT.BORDER); GridData treeGridData = new GridData(SWT.FILL, SWT.FILL, true, true); tree.setLayoutData(treeGridData); treeViewer = new InheritanceCheckboxTreeViewer( tree, InheritanceCheckboxTreeViewer.CHECKED_WHITE_IF_ALL_DESCENDANTS_CHECKED_ELSE_CHECKED_GRAYED_IF_ANY_CHECKED, deselectionHandler); treeViewer.addCheckStateListener(new ICheckStateListener() { @Override public void checkStateChanged( CheckStateChangedEvent event ) { if (listenForCheckboxChanges) { checkedItemsChanged(); } } }); Composite buttonComposite = new Composite(treeGroup, SWT.NONE); GridLayout buttonLayout = new GridLayout(); buttonComposite.setLayout(buttonLayout); buttonLayout.numColumns = 2; buttonLayout.marginWidth = 0; buttonLayout.marginHeight = 0; checkAllButton = new Button(buttonComposite, SWT.PUSH); checkAllButton.setText(CHECK_ALL); checkAllButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected( SelectionEvent ev ) { treeViewer.setListenerEnabled(false); TreeViewerUtil.setAllChecked(treeViewer, true); treeViewer.setListenerEnabled(true); checkboxStateChanged(); } }); GridData buttonGridData = new GridData(GridData.HORIZONTAL_ALIGN_CENTER); checkAllButton.setLayoutData(buttonGridData); uncheckAllButton = new Button(buttonComposite, SWT.PUSH); uncheckAllButton.setText(UNCHECK_ALL); uncheckAllButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected( SelectionEvent ev ) { treeViewer.setListenerEnabled(false); TreeViewerUtil.setAllChecked(treeViewer, false); treeViewer.setListenerEnabled(true); checkboxStateChanged(); } }); buttonGridData = new GridData(GridData.HORIZONTAL_ALIGN_CENTER); uncheckAllButton.setLayoutData(buttonGridData); // copy selection buttons SelectionListener sl = new SelectionListener() { @Override public void widgetDefaultSelected( SelectionEvent e ) { widgetSelected(e); } @Override public void widgetSelected( SelectionEvent e ) { boolean copyEntire = !selectFeatures.getSelection(); setCopyEntireModel(copyEntire); } }; selectFeatures.addSelectionListener(sl); // initial state: copyEntire.setSelection(true); setCopyEntireModel(true); addOptions(this); } /** * Overridable method to add options from subclasses * * @param parent * @since 5.0 */ protected void addOptions( Composite parent ) { // add a checkbox to copy descriptions (annotations). copyAllDescriptions = new Button(this, SWT.CHECK); copyAllDescriptions.setSelection(true); copyAllDescriptions.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false)); copyAllDescriptions.setText(COPY_ALL_DESCRIPTIONS); } /** * Tells whether the user has explicitly indiciated that they wish to copy the entire selected model, rather than select * pieces of it. * * @return true if the user wishes to copy the entire model. */ public boolean isCopyEntireModel() { // TODO this should also see if everything in the tree is selected, and return true in that case, also. // --> be careful, though, since this method is also called in this class. return copyEntire; } /** * Tells where the user has explicitly indicated they wish to copy all descriptions from the selected model to the new target * model * * @return * @since 5.0 */ public boolean isCopyAllDescriptions() { return copyAllDescriptions.getSelection(); } /** * @see org.eclipse.swt.widgets.Control#setVisible(boolean) * @since 4.2 */ @Override public void setVisible( boolean theVisible ) { super.setVisible(theVisible); // can't call the populator before the tree is visible. treeviewers use lightweight treeitems before they're visible // so setting the populator prior to being visible would check these temporary treeitems instead of the true // treeitems created when the tree is expanded. this is called only the first time visible and a workspace selection. if (theVisible && this.firstTimeVisible && this.selectorDialogResult != null) { this.firstTimeVisible = false; IFile file = (IFile)selectorDialogResult.getResource(); fileNameText.setText(file.getProjectRelativePath().toString()); populator = getFeaturePopulator(file); populator.populateModelFeaturesTree(treeViewer, selectorDialogResult, targetIsVirtual); } } void browseButtonClicked() { IStructuralCopyTreePopulator thePopulator = displaySelectorDialog(); if (thePopulator != null) { populator = thePopulator; populator.populateModelFeaturesTree(treeViewer, selectorDialogResult, targetIsVirtual); setCopyEntireModel(isCopyEntireModel()); // set to the same to redo things } } private IStructuralCopyTreePopulator displaySelectorDialog() { IStructuralCopyTreePopulator result = null; this.selectorDialogResult = null; ModelWorkspaceTreeProvider provider = new ModelWorkspaceTreeProvider(); ElementTreeSelectionDialog dialog = new ElementTreeSelectionDialog(getShell(), provider, provider); dialog.setInput(ModelerCore.getWorkspace().getRoot()); dialog.setAllowMultiple(false); dialog.addFilter(new ClosedProjectFilter()); dialog.addFilter(new DotProjectFilter()); // use resource filter used by model explorer dialog.addFilter(new ModelingResourceFilter()); dialog.setValidator(new ModelResourceSelectionValidator(this.metamodelDescriptor, false)); dialog.setTitle(SELECT_MODEL_TITLE); dialog.setMessage(SELECT_MODEL_MSG); if (dialog.open() == Window.OK) { Object[] selection = dialog.getResult(); if ((selection.length == 1) && (selection[0] instanceof IFile)) { IFile sourceFile = (IFile)selection[0]; result = getFeaturePopulator(sourceFile); selectorDialogResult = null; fileNameText.setText(""); //$NON-NLS-1$ boolean exceptionOccurred = false; try { selectorDialogResult = ModelUtil.getModelResource(sourceFile, true); } catch (Exception ex) { Util.log(ex); exceptionOccurred = true; } if (!exceptionOccurred) { fileNameText.setText(sourceFile.getName()); } } } return result; } protected StructuralCopyModelFeaturePopulator getFeaturePopulator( IFile sourceFile ) { return new StructuralCopyModelFeaturePopulator(sourceFile, this); } void checkedItemsChanged() { int numItemsChecked = treeViewer.getCheckedElements().length; boolean complete = (numItemsChecked > 0); wizardPage.setPageComplete(complete); if (complete) { wizardPage.setErrorMessage(null); } else { // If # of root items == 0, then this method probably cannot have been called anyway, // but in case it was we will not disturb the error message because the error // message should already be stating that the selected file was not // recognizable as an existing model. if (TreeViewerUtil.getRootNodes(treeViewer).size() > 0) { String msg = Util.getString("StructuralCopyWizardPage.needCheckedItem"); //$NON-NLS-1$ wizardPage.setErrorMessage(msg); } } } /** * Updates the enablement of components and message of the wizard page. * * @param copyEntireModel if true, ignore the tree checked state and copy all model features. */ void setCopyEntireModel( boolean copyEntireModel ) { copyEntire = copyEntireModel; tree.setEnabled(!copyEntireModel); checkAllButton.setEnabled(!copyEntireModel); uncheckAllButton.setEnabled(!copyEntireModel); if (copyEntireModel && selectorDialogResult != null) { wizardPage.setPageComplete(true); wizardPage.setErrorMessage(null); } else { checkedItemsChanged(); } // endif } }// end CheckboxTreeViewerWizardPanel