package com.redhat.ceylon.eclipse.code.preferences; import static com.redhat.ceylon.eclipse.code.imports.ModuleImportUtil.addModuleImports; import static com.redhat.ceylon.eclipse.code.imports.ModuleImportUtil.makeModuleImportShared; import static com.redhat.ceylon.eclipse.code.imports.ModuleImportUtil.removeModuleImports; import static com.redhat.ceylon.eclipse.code.imports.ModuleImportUtil.removeSharedAnnotation; import static com.redhat.ceylon.eclipse.code.preferences.ModuleImportSelectionDialog.selectModules; import static com.redhat.ceylon.eclipse.core.builder.CeylonBuilder.getProjectModules; import static com.redhat.ceylon.eclipse.core.builder.CeylonBuilder.getProjectTypeChecker; import static com.redhat.ceylon.eclipse.ui.CeylonPlugin.PLUGIN_ID; import static com.redhat.ceylon.eclipse.util.EditorUtil.getDocument; import static com.redhat.ceylon.eclipse.util.EditorUtil.performChange; import static com.redhat.ceylon.eclipse.util.ModuleQueries.getModuleSearchResults; import static org.eclipse.swt.layout.GridData.FILL_BOTH; import static org.eclipse.swt.layout.GridData.FILL_HORIZONTAL; import static org.eclipse.swt.layout.GridData.HORIZONTAL_ALIGN_FILL; import static org.eclipse.swt.layout.GridData.VERTICAL_ALIGN_BEGINNING; import java.util.ArrayList; import java.util.List; import java.util.Map; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.IPackageFragment; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jface.layout.GridDataFactory; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.wizard.WizardDialog; import org.eclipse.ltk.core.refactoring.TextFileChange; 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.Control; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Link; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.TableColumn; import org.eclipse.swt.widgets.TableItem; import org.eclipse.text.edits.InsertEdit; import org.eclipse.text.edits.MultiTextEdit; import org.eclipse.ui.IWorkbenchPropertyPage; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.dialogs.PropertyPage; import org.eclipse.ui.wizards.IWizardDescriptor; import com.redhat.ceylon.cmr.api.ModuleSearchResult; import com.redhat.ceylon.compiler.typechecker.tree.Tree; import com.redhat.ceylon.eclipse.code.editor.Navigation; import com.redhat.ceylon.eclipse.code.navigator.SourceModuleNode; import com.redhat.ceylon.eclipse.code.wizard.NewPackageWizard; import com.redhat.ceylon.eclipse.ui.CeylonResources; import com.redhat.ceylon.ide.common.model.ProjectSourceFile; import com.redhat.ceylon.ide.common.modulesearch.ModuleVersionNode; import com.redhat.ceylon.ide.common.typechecker.ProjectPhasedUnit; import com.redhat.ceylon.model.typechecker.model.Module; import com.redhat.ceylon.model.typechecker.model.ModuleImport; import com.redhat.ceylon.model.typechecker.model.Modules; import com.redhat.ceylon.model.typechecker.model.Package; import com.redhat.ceylon.model.typechecker.model.Unit; public class CeylonModulePropertiesPage extends PropertyPage implements IWorkbenchPropertyPage { // private IResourceChangeListener encodingListener; private Table moduleImportsTable; private IProject project; private IPackageFragment packageFragment; // @Override // public void dispose() { // if (encodingListener!=null) { // getWorkspace().removeResourceChangeListener(encodingListener); // encodingListener = null; // } // super.dispose(); // } private NewPackageWizard openPackageWizard() { IWizardDescriptor descriptor = PlatformUI.getWorkbench() .getNewWizardRegistry() .findWizard(PLUGIN_ID + ".newPackageWizard"); if (descriptor!=null) { try { NewPackageWizard wizard = (NewPackageWizard) descriptor.createWizard(); wizard.init(PlatformUI.getWorkbench(), new StructuredSelection(getElement())); Shell shell = Display.getCurrent() .getActiveShell(); WizardDialog wd = new WizardDialog(shell, wizard); wd.setTitle(wizard.getWindowTitle()); wd.open(); return wizard; } catch (CoreException e) { e.printStackTrace(); } } return null; } @Override protected Control createContents(Composite parent) { initProjectAndModule(); if (packageFragment==null) return parent; createModuleInfoBlock(parent); createPackagesBlock(parent); createModulesBlock(parent); createModuleDescriptorLink(parent); return parent; } public void createModuleDescriptorLink(Composite parent) { new Label(parent, SWT.SEPARATOR|SWT.HORIZONTAL) .setLayoutData(new GridData(FILL_HORIZONTAL)); IFolder folder = (IFolder) packageFragment.getResource(); final IFile moduleDescriptor = folder.getFile("module.ceylon"); Link openDescriptorLink = new Link(parent, 0); GridData gd = GridDataFactory.swtDefaults() .align(SWT.FILL, SWT.CENTER) .indent(0, 6) .create(); openDescriptorLink.setLayoutData(gd); openDescriptorLink.setText("<a>Edit module descriptor...</a>"); openDescriptorLink.addSelectionListener( new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { getShell().close(); Navigation.gotoLocation(moduleDescriptor, 0); } }); } private void initProjectAndModule() { IAdaptable element = getElement(); IFile file = (IFile) element.getAdapter(IFile.class); if (file==null) { SourceModuleNode node = (SourceModuleNode) element.getAdapter( SourceModuleNode.class); if (node==null) { packageFragment = (IPackageFragment) element.getAdapter( IPackageFragment.class); } else { for (IPackageFragment pf: node.getPackageFragments()) { String mname = node.getModule() .getNameAsString(); if (pf.getElementName().equals(mname)) { packageFragment = pf; break; } } } } else { IJavaElement javaElement = JavaCore.create(file.getParent()); if (javaElement instanceof IPackageFragment) { packageFragment = (IPackageFragment) javaElement; } } if (packageFragment!=null) { project = packageFragment.getJavaProject() .getProject(); } } public Module getModule() { if (project==null) return null; Modules projectModules = getProjectModules(project); if (projectModules==null) return null; for (Module m: projectModules.getListOfModules()) { String pname = packageFragment.getElementName(); if (m.getNameAsString().equals(pname)) { return m; } } return null; } private void createModulesBlock(Composite parent) { Label label = new Label(parent, SWT.NONE); label.setText("Imported modules:"); Composite composite = new Composite(parent, SWT.NONE); GridData cgd = new GridData(FILL_BOTH); cgd.grabExcessHorizontalSpace = true; cgd.grabExcessVerticalSpace = true; composite.setLayoutData(cgd); GridLayout layout = new GridLayout(3, true); layout.marginWidth=0; composite.setLayout(layout); moduleImportsTable = new Table(composite, SWT.MULTI | SWT.V_SCROLL | SWT.BORDER); moduleImportsTable.setHeaderVisible(true); moduleImportsTable.setLinesVisible(true); GridData gd = new GridData(FILL_BOTH); gd.horizontalSpan=2; gd.verticalSpan=4; gd.grabExcessHorizontalSpace = true; // gd.grabExcessVerticalSpace = true; gd.heightHint = 100; gd.widthHint = 300; moduleImportsTable.setLayoutData(gd); TableColumn column = new TableColumn(moduleImportsTable, SWT.NONE, 0); column.setText("Module/Version"); column.setWidth(180); TableColumn versionColumn = new TableColumn(moduleImportsTable, SWT.NONE, 1); versionColumn.setText("Version"); versionColumn.setWidth(70); TableColumn sharedColumn = new TableColumn(moduleImportsTable, SWT.NONE, 2); sharedColumn.setText("Transitivity"); sharedColumn.setWidth(70); for (ModuleImport mi: getModule().getImports()) { TableItem item = new TableItem(moduleImportsTable, SWT.NONE); item.setImage(CeylonResources.MODULE); item.setText(mi.getModule().getNameAsString()); item.setText(1, mi.getModule().getVersion()); item.setText(2, mi.isExport() ? "shared" : ""); } GridData bgd = new GridData( VERTICAL_ALIGN_BEGINNING | HORIZONTAL_ALIGN_FILL); bgd.grabExcessHorizontalSpace=false; bgd.widthHint = 50; Button sharedButton = new Button(composite, SWT.PUSH); sharedButton.setText("Toggle Shared"); sharedButton.setLayoutData(bgd); sharedButton.addSelectionListener(new SelectionListener() { @Override public void widgetSelected(SelectionEvent e) { makeShared(moduleImportsTable.getSelection()); // moduleImportsTable.redraw(); } @Override public void widgetDefaultSelected(SelectionEvent e) {} }); Button addButton = new Button(composite, SWT.PUSH); addButton.setText("Add Imports..."); addButton.setLayoutData(bgd); addButton.addSelectionListener(new SelectionListener() { @Override public void widgetSelected(SelectionEvent e) { selectAndAddModules(); } @Override public void widgetDefaultSelected(SelectionEvent e) {} }); Button removeButton = new Button(composite, SWT.PUSH); removeButton.setText("Remove Selected"); removeButton.setLayoutData(bgd); removeButton.addSelectionListener(new SelectionListener() { @Override public void widgetSelected(SelectionEvent e) { removeSelectedModules(); } @Override public void widgetDefaultSelected(SelectionEvent e) {} }); // Label l = new Label(parent, SWT.NONE); // l.setText("(Checked modules are exported.)"); } private void makeShared(TableItem[] items) { List<String> list = new ArrayList<String>(); for (TableItem item: items) { String name = item.getText(); if (!name.equals(Module.LANGUAGE_MODULE_NAME)) { list.add(name); } } makeModuleImportShared(project, getModule(), list.toArray(new String[0])); for (TableItem item: items) { String name = item.getText(); if (!name.equals(Module.LANGUAGE_MODULE_NAME)) { item.setText(2, item.getText(2).isEmpty() ? "shared" : ""); } } } private void createPackagesBlock(Composite parent) { Label label = new Label(parent, SWT.NONE); label.setText("Packages:"); Composite composite = new Composite(parent, SWT.NONE); GridData cgd = new GridData(FILL_HORIZONTAL); cgd.grabExcessHorizontalSpace = true; composite.setLayoutData(cgd); GridLayout layout = new GridLayout(3, true); layout.marginWidth=0; composite.setLayout(layout); final Table packagesTable = new Table(composite, SWT.MULTI | SWT.V_SCROLL | SWT.BORDER); packagesTable.setHeaderVisible(true); packagesTable.setLinesVisible(true); GridData gd = new GridData(FILL_HORIZONTAL); gd.horizontalSpan=2; gd.verticalSpan=2; gd.grabExcessHorizontalSpace = true; // gd.grabExcessVerticalSpace = true; gd.heightHint = 100; gd.widthHint = 300; packagesTable.setLayoutData(gd); TableColumn column = new TableColumn(packagesTable, SWT.NONE, 0); column.setText("Package"); column.setWidth(250); TableColumn sharedColumn = new TableColumn(packagesTable, SWT.NONE, 1); sharedColumn.setText("Visibility"); sharedColumn.setWidth(70); for (Package p: getModule().getPackages()) { TableItem item = new TableItem(packagesTable, SWT.NONE, 0); item.setImage(CeylonResources.PACKAGE); item.setText(p.getNameAsString()); item.setText(1, p.isShared() ? "shared" : ""); } GridData bgd = new GridData( VERTICAL_ALIGN_BEGINNING | HORIZONTAL_ALIGN_FILL); bgd.grabExcessHorizontalSpace=false; bgd.widthHint = 50; Button sharedButton = new Button(composite, SWT.PUSH); sharedButton.setText("Toggle Shared"); sharedButton.setLayoutData(bgd); sharedButton.addSelectionListener(new SelectionListener() { @Override public void widgetSelected(SelectionEvent e) { for (TableItem item: packagesTable.getSelection()) { makeShared(item); } // packagesTable.redraw(); } @Override public void widgetDefaultSelected(SelectionEvent e) {} }); Button createPackageButton = new Button(composite, SWT.PUSH); createPackageButton.setText("Create Package..."); createPackageButton.setLayoutData(bgd); createPackageButton.addSelectionListener(new SelectionListener() { @Override public void widgetSelected(SelectionEvent e) { NewPackageWizard wiz = openPackageWizard(); if (wiz.isCreated()) { IPackageFragment pfr = wiz.getPackageFragment(); TableItem item = new TableItem(packagesTable, SWT.NONE); item.setImage(CeylonResources.PACKAGE); item.setText(pfr.getElementName()); item.setText(1, wiz.isShared() ? "shared" : ""); } } @Override public void widgetDefaultSelected(SelectionEvent e) {} }); // Label l = new Label(parent, SWT.NONE); // l.setText("(Checked packages are shared.)"); new Label(parent, SWT.SEPARATOR|SWT.HORIZONTAL) .setLayoutData(new GridData(FILL_HORIZONTAL)); } private void makeShared(TableItem item) { Package pkg = getModule() .getPackage(item.getText()); Unit unit = pkg.getUnit(); ProjectPhasedUnit<IProject,IResource,IFolder,IFile> phasedUnit; if (unit instanceof ProjectSourceFile) { ProjectSourceFile<IProject,IResource,IFolder,IFile> ceylonUnit = (ProjectSourceFile<IProject,IResource,IFolder,IFile>) unit; phasedUnit = ceylonUnit.getPhasedUnit(); TextFileChange textFileChange = new TextFileChange( "Make Package Shared", phasedUnit.getResourceFile()); textFileChange.setEdit(new MultiTextEdit()); IDocument doc = getDocument(textFileChange); Tree.PackageDescriptor pd = phasedUnit.getCompilationUnit() .getPackageDescriptors() .get(0); if (pkg.isShared()) { removeSharedAnnotation(textFileChange, doc, pd.getAnnotationList()); } else { textFileChange.addEdit(new InsertEdit( pd.getStartIndex(), "shared ")); } performChange(textFileChange); item.setText(1, !pkg.isShared() ? "shared" : ""); } else { item.setChecked(!item.getChecked()); } } private void createModuleInfoBlock(Composite parent) { Composite composite = new Composite(parent, SWT.NONE); GridData cgd = new GridData(FILL_HORIZONTAL); // cgd.grabExcessHorizontalSpace = true; composite.setLayoutData(cgd); GridLayout layout = new GridLayout(2, true); layout.marginWidth=0; composite.setLayout(layout); Label label = new Label(composite, SWT.NONE); label.setText("Module name: "); label = new Label(composite, SWT.NONE); label.setText(packageFragment.getElementName()); /*Label img = new Label(composite, SWT.BORDER); Image image = CeylonPlugin.getInstance() .getImageRegistry().get(CEYLON_NEW_MODULE); img.setImage(image); img.setSize(image.getBounds().width, image.getBounds().height); GridData igd = new GridData(HORIZONTAL_ALIGN_END|VERTICAL_ALIGN_END); igd.verticalSpan=4; // igd.horizontalSpan=2; igd.grabExcessHorizontalSpace=true; img.setLayoutData(igd);*/ label = new Label(composite, SWT.NONE); label.setText("Project name: "); label = new Label(composite, SWT.NONE); label.setText(project.getName()); /*label = new Label(composite, SWT.NONE); label.setText("Module workspace path: "); label = new Label(composite, SWT.NONE); label.setText(pf.getResource().getFullPath().toPortableString()); label = new Label(composite, SWT.NONE); label.setText("Default source file encoding: "); final Link link = new Link(composite, SWT.NONE); try { final IFolder f = (IFolder) pf.getResource(); link.setText(f.getDefaultCharset() + " <a>(Change...)</a>"); link.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { IWorkbenchPreferenceContainer container = (IWorkbenchPreferenceContainer) getContainer(); container.openPage("org.eclipse.ui.propertypages.info.file", null); } }); getWorkspace().addResourceChangeListener(encodingListener=new IResourceChangeListener() { @Override public void resourceChanged(IResourceChangeEvent event) { if (event.getType()==IResourceChangeEvent.POST_CHANGE) { Display.getDefault().asyncExec(new Runnable() { public void run() { try { if (!link.isDisposed()) { link.setText(f.getDefaultCharset() + " <a>(Change...)</a>"); } } catch (CoreException e) { e.printStackTrace(); } } }); } } }); } catch (CoreException e) { e.printStackTrace(); }*/ new Label(parent, SWT.SEPARATOR|SWT.HORIZONTAL) .setLayoutData(new GridData(FILL_HORIZONTAL)); } @Override public void createControl(Composite parent) { noDefaultAndApplyButton(); super.createControl(parent); } private void selectAndAddModules() { ModuleImportContentProvider contentProvider = new ModuleImportContentProvider(getModule(), project) { @Override public ModuleSearchResult getModules(String prefix) { return getModuleSearchResults(prefix, getModule(), getProjectTypeChecker(project), project); } }; ModuleImportSelectionDialog dialog = new ModuleImportSelectionDialog(getShell(), contentProvider); Map<String, ModuleVersionNode> added = selectModules(dialog, project); addModuleImports(project, getModule(), added); for (Map.Entry<String, ModuleVersionNode> entry: added.entrySet()) { TableItem item = new TableItem(moduleImportsTable, SWT.NONE); item.setImage(CeylonResources.MODULE); item.setText(entry.getKey()); item.setText(1, entry.getValue().getVersion()); } } private void removeSelectedModules() { int[] selection = moduleImportsTable.getSelectionIndices(); List<String> names = new ArrayList<String>(); List<Integer> removed = new ArrayList<Integer>(); for (int index: selection) { TableItem item = moduleImportsTable.getItem(index); String name = item.getText(); if (!name.equals(Module.LANGUAGE_MODULE_NAME)) { names.add(name); removed.add(index); } } removeModuleImports(project, getModule(), names); int[] indices = new int[removed.size()]; for (int i=0; i<removed.size(); i++) { indices[i] = removed.get(i); } moduleImportsTable.remove(indices); } }