(refs #7362) Creation of new SCL modules in SCL module browser
[simantics/platform.git] / bundles / org.simantics.scl.ui / src / org / simantics / scl / ui / modulebrowser / CreateModuleDialog.java
1 package org.simantics.scl.ui.modulebrowser;
2
3 import java.io.IOException;
4 import java.util.ArrayList;
5
6 import org.eclipse.core.runtime.Status;
7 import org.eclipse.jface.dialogs.Dialog;
8 import org.eclipse.jface.dialogs.ErrorDialog;
9 import org.eclipse.jface.dialogs.IDialogConstants;
10 import org.eclipse.jface.layout.GridDataFactory;
11 import org.eclipse.jface.layout.GridLayoutFactory;
12 import org.eclipse.swt.SWT;
13 import org.eclipse.swt.events.DisposeEvent;
14 import org.eclipse.swt.events.DisposeListener;
15 import org.eclipse.swt.events.ModifyEvent;
16 import org.eclipse.swt.events.ModifyListener;
17 import org.eclipse.swt.events.SelectionAdapter;
18 import org.eclipse.swt.events.SelectionEvent;
19 import org.eclipse.swt.graphics.Color;
20 import org.eclipse.swt.widgets.Button;
21 import org.eclipse.swt.widgets.Composite;
22 import org.eclipse.swt.widgets.Control;
23 import org.eclipse.swt.widgets.Label;
24 import org.eclipse.swt.widgets.Shell;
25 import org.eclipse.swt.widgets.Text;
26 import org.osgi.framework.Bundle;
27 import org.simantics.scl.osgi.SCLOsgi;
28 import org.simantics.scl.ui.editor2.OpenSCLModule;
29 import org.simantics.scl.ui.modulebrowser.PluginSelectionDialog.Entry;
30
31 import gnu.trove.map.hash.THashMap;
32
33 public class CreateModuleDialog extends Dialog {
34
35     SCLModuleBrowser parentBrowser;
36     
37     String initialPackageName = "";
38     String initialPluginName = "";
39     
40     Text packageName;
41     Text moduleName;
42     Text pluginName;
43     private THashMap<String,Bundle> bundles;
44     
45     private Color normalBackground;
46     private Color errorBackground;
47
48     protected CreateModuleDialog(Shell parentShell, SCLModuleBrowser parentBrowser) {
49         super(parentShell);
50         this.parentBrowser = parentBrowser;
51         setShellStyle(SWT.RESIZE | SWT.TITLE | SWT.BORDER);
52         bundles = CreateModuleAction.findGoodBundles();
53         
54         normalBackground = parentShell.getDisplay().getSystemColor(SWT.COLOR_WHITE);
55         errorBackground =  new Color(parentShell.getDisplay(), 255, 128, 128);
56     }
57
58     @Override
59     protected Control createDialogArea(Composite parent) {
60         getShell().setText("Create New Module");
61         getShell().addDisposeListener(new DisposeListener() {
62             @Override
63             public void widgetDisposed(DisposeEvent e) {
64                 errorBackground.dispose();
65             }
66         });
67
68         final Composite composite = (Composite) super.createDialogArea(parent);
69         GridLayoutFactory.fillDefaults().margins(10,10).numColumns(2).applyTo(composite);
70         GridDataFactory.fillDefaults().grab(true,true).applyTo(composite);
71
72         // Package name
73         Label packageNameLabel = new Label(composite, SWT.NONE);
74         packageNameLabel.setText("Package");
75         GridDataFactory.fillDefaults().applyTo(packageNameLabel);
76
77         packageName = new Text(composite, SWT.BORDER);
78         GridDataFactory.fillDefaults().grab(true, false).minSize(500, SWT.DEFAULT).applyTo(packageName);
79         packageName.setText(initialPackageName);
80         packageName.addModifyListener(modifyListener);
81
82         // Module name
83         Label moduleNameLabel = new Label(composite, SWT.NONE);
84         moduleNameLabel.setText("Module name");
85         GridDataFactory.fillDefaults().applyTo(moduleNameLabel);
86
87         moduleName = new Text(composite, SWT.BORDER);
88         GridDataFactory.fillDefaults().grab(true, false).applyTo(moduleName);
89         moduleName.addModifyListener(modifyListener);
90
91         // Plugin
92         Label pluginNameLabel = new Label(composite, SWT.NONE);
93         pluginNameLabel.setText("Plugin");
94         GridDataFactory.fillDefaults().applyTo(pluginNameLabel);
95
96         Composite pluginNameComposite = new Composite(composite, SWT.NONE);
97         GridDataFactory.fillDefaults().grab(true, false).applyTo(pluginNameComposite);
98         GridLayoutFactory.fillDefaults().numColumns(2).applyTo(pluginNameComposite);
99         
100         pluginName = new Text(pluginNameComposite, SWT.BORDER);
101         GridDataFactory.fillDefaults().grab(true, false).applyTo(pluginName);
102         pluginName.setText(initialPluginName);
103         pluginName.addModifyListener(modifyListener);
104         
105         Button browsePlugins = new Button(pluginNameComposite, SWT.PUSH);
106         browsePlugins.setText("Browse...");
107         GridDataFactory.fillDefaults().applyTo(browsePlugins);
108         browsePlugins.addSelectionListener(new SelectionAdapter() {
109             @Override
110             public void widgetSelected(SelectionEvent e) {
111                 browsePlugins();
112             }
113         });
114
115         // Focus
116         moduleName.setFocus();
117         parent.getDisplay().asyncExec(new Runnable() {
118             @Override
119             public void run() {
120                 validate();
121             }            
122         });
123
124         return composite;
125     }
126     
127     private void browsePlugins() {
128         ArrayList<Entry> entries = new ArrayList<Entry>(bundles.size());
129         String currentPackageName = packageName.getText();
130         for(Bundle bundle : bundles.values())
131             entries.add(new Entry(bundle, CreateModuleAction.packageMatchLength(bundle, currentPackageName)));
132         PluginSelectionDialog dialog = new PluginSelectionDialog(getShell(), entries);
133         if(dialog.open() == Dialog.OK) {
134             Entry result = (Entry)dialog.getFirstResult();
135             if(result != null) {
136                 pluginName.setText(result.bundle.getSymbolicName());
137                 validate();
138             }
139         }
140     }
141     
142     private void validate() {
143         boolean validPackageName = CreateModuleValidator.isValidPackageName(packageName.getText());
144         packageName.setBackground(validPackageName ? normalBackground : errorBackground);
145         
146         boolean validModuleName = CreateModuleValidator.isValidModuleName(moduleName.getText());
147         if(validModuleName && validPackageName) {
148             String fullModuleName = packageName.getText() + "/" + moduleName.getText();
149             validModuleName = SCLOsgi.SOURCE_REPOSITORY.getModuleSource(fullModuleName, null) == null;
150         }
151         moduleName.setBackground(validModuleName ? normalBackground : errorBackground);
152         
153         boolean validPluginName = bundles.containsKey(pluginName.getText());
154         pluginName.setBackground(validPluginName ? normalBackground : errorBackground);
155         
156         getButton(IDialogConstants.OK_ID).setEnabled(validPackageName && validModuleName && validPackageName);
157     }
158     
159     private ModifyListener modifyListener = new ModifyListener() {
160         @Override
161         public void modifyText(ModifyEvent e) {
162             validate();
163         }
164     };
165     
166     public void setPackage(String initialPackageName) {
167         this.initialPackageName = initialPackageName;
168         this.initialPluginName = CreateModuleAction.findBestPlugin(bundles, initialPackageName);
169     }
170     
171     @Override
172     protected void okPressed() {
173         try {
174             Bundle bundle = bundles.get(pluginName.getText());
175             if(bundle != null) {
176                 CreateModuleAction.createModule(bundle, packageName.getText(), moduleName.getText());
177                 parentBrowser.refresh();
178                 OpenSCLModule.openModule(packageName.getText() + "/" + moduleName.getText());
179             }
180         } catch (IOException e) {
181             ErrorDialog.openError(getParentShell(), "Module creation failed", e.getMessage(),
182                     new Status(Status.ERROR, "org.simantics.scl.ui", e.getMessage()));
183         }
184         super.okPressed();
185     }
186 }