source: trunk/org.modelica.mdt/src/org/modelica/mdt/NewClassWizard.java @ 51

Last change on this file since 51 was 49, checked in by boris, 19 years ago
File size: 15.4 KB
Line 
1package org.modelica.mdt;
2
3
4import java.io.ByteArrayInputStream;
5import java.io.IOException;
6import java.io.InputStream;
7import java.lang.reflect.InvocationTargetException;
8import java.util.regex.Pattern;
9
10import org.eclipse.core.resources.IContainer;
11import org.eclipse.core.resources.IFile;
12import org.eclipse.core.resources.IResource;
13import org.eclipse.core.resources.IWorkspaceRoot;
14import org.eclipse.core.resources.ResourcesPlugin;
15import org.eclipse.core.runtime.CoreException;
16import org.eclipse.core.runtime.IPath;
17import org.eclipse.core.runtime.IProgressMonitor;
18import org.eclipse.core.runtime.IStatus;
19import org.eclipse.core.runtime.Path;
20import org.eclipse.core.runtime.Status;
21import org.eclipse.jface.dialogs.DialogPage;
22import org.eclipse.jface.dialogs.ErrorDialog;
23import org.eclipse.jface.dialogs.MessageDialog;
24import org.eclipse.jface.operation.IRunnableWithProgress;
25import org.eclipse.jface.viewers.IStructuredSelection;
26import org.eclipse.jface.wizard.Wizard;
27import org.eclipse.jface.wizard.WizardPage;
28import org.eclipse.swt.SWT;
29import org.eclipse.swt.events.ModifyEvent;
30import org.eclipse.swt.events.ModifyListener;
31import org.eclipse.swt.events.SelectionAdapter;
32import org.eclipse.swt.events.SelectionEvent;
33import org.eclipse.swt.events.SelectionListener;
34import org.eclipse.swt.layout.GridData;
35import org.eclipse.swt.layout.GridLayout;
36import org.eclipse.swt.widgets.Combo;
37import org.eclipse.swt.widgets.Composite;
38import org.eclipse.swt.widgets.Label;
39import org.eclipse.swt.widgets.Text;
40import org.eclipse.swt.widgets.Button;
41import org.eclipse.ui.INewWizard;
42import org.eclipse.ui.IWorkbench;
43import org.eclipse.ui.IWorkbenchPage;
44import org.eclipse.ui.PartInitException;
45import org.eclipse.ui.PlatformUI;
46import org.eclipse.ui.dialogs.ContainerSelectionDialog;
47import org.eclipse.ui.ide.IDE;
48
49public class NewClassWizard extends Wizard implements INewWizard
50{
51   
52    public class NewClassPage extends WizardPage
53    {
54        private Text sourceFolder;
55        private Text className;
56        private Combo classType;
57        private Button initialEquation;
58        private Button partialClass;
59        private Button externalBody;
60   
61        private IPath selection = null;
62       
63       
64        /* regexp pattern of a valid modelica class name */
65        //TODO add complete regexp for modelcia class name
66        // see modelica specification page 9 (and perhaps some other pages as well)
67        // http://www.modelica.org/documents/ModelicaSpec22.pdf
68        Pattern classNamePattern = Pattern.compile("[a-zA-Z]\\w*");
69       
70        private boolean classNameValid = false;
71        private boolean sourceFolderValid = false;     
72       
73        public NewClassPage()
74        {
75            super("");
76        }
77
78        public void createControl(Composite parent)
79        {
80            setPageComplete(false);
81            /*
82             * configure description of this page
83             */
84            setTitle("Modelica Class");
85            setDescription("Create a new Modelica class.");
86           
87            // TODO set image descriptor           
88            //setImageDescriptor(...);
89           
90            /*
91             * setup widgets for this page
92             */
93            Composite composite= new Composite(parent, SWT.NONE);
94            setControl(composite);
95            composite.setFont(parent.getFont());
96           
97            GridLayout layout = new GridLayout();
98            layout.numColumns = 3;
99            composite.setLayout(layout);
100           
101            GridData gd;
102
103            /* source folder field */
104            Label l = new Label(composite, SWT.LEFT | SWT.WRAP);
105            l.setText("Source folder:");
106            gd = new GridData();
107            gd.horizontalAlignment = GridData.BEGINNING;
108            l.setLayoutData(gd);
109           
110            sourceFolder = new Text(composite, SWT.SINGLE | SWT.BORDER);
111            gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL);
112            sourceFolder.setLayoutData(gd);
113            setSourceFolder(selection);
114           
115            sourceFolder.addModifyListener(new ModifyListener()
116            {
117                    /* check if entered path exists */
118                    public void modifyText(ModifyEvent e)
119                    {
120                        sourceFolderChanged();
121                    }
122            });
123
124
125            Button b = new Button(composite, SWT.PUSH);
126            b.setText("Browse...");
127            gd = new GridData();
128            gd.horizontalAlignment = GridData.END;
129            b.setLayoutData(gd);
130            b.addSelectionListener(new SelectionAdapter()
131            {
132                public void widgetSelected(SelectionEvent e)
133                {
134                    handleBrowse();
135                }
136            });
137
138           
139            /* class name field */
140            l = new Label(composite, SWT.LEFT | SWT.WRAP);
141            l.setText("Name:");
142            gd = new GridData();
143            gd.horizontalAlignment = GridData.BEGINNING;
144            l.setLayoutData(gd);
145           
146            className = new Text(composite,  SWT.SINGLE | SWT.BORDER);
147            gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL);
148            gd.horizontalSpan = 2;
149            className.setLayoutData(gd);
150
151            className.addModifyListener(new ModifyListener()
152            {
153                /* check if entered classname is valid */
154                public void modifyText(ModifyEvent e)
155                {
156                    if (!isLegalClassName(className.getText()))
157                    {
158                        classNameValid  = false;
159                        updateStatus("Class name is not valid. Illegal identifier.",
160                                    DialogPage.WARNING);
161                    }
162                    else
163                    {
164                        classNameValid  = true;
165                        updateStatus(null, DialogPage.NONE);
166                    }
167                }
168            });
169            className.setFocus();
170
171            /* class type field */
172            l = new Label(composite, SWT.LEFT | SWT.WRAP);
173            l.setText("Type:");
174            gd = new GridData();
175            gd.horizontalAlignment = GridData.BEGINNING;
176            l.setLayoutData(gd);
177           
178            classType = new Combo(composite, SWT.READ_ONLY);
179            classType.setItems(new String [] {"model", "class", "connector", "record",
180                    "block", "type", "function"});
181            classType.setVisibleItemCount(7);
182            classType.select(0);           
183                   
184            gd = new GridData();
185            gd.horizontalAlignment = GridData.BEGINNING;
186            classType.setLayoutData(gd);
187           
188            classType.addSelectionListener(new SelectionListener()
189            {
190
191                public void widgetSelected(SelectionEvent e)
192                {
193                    /*
194                     * update state of the modifiers checkboxes
195                     */
196                    initialEquation.setEnabled
197                    (NewClassWizard.classTypeHaveEquations(classType.getText()));
198                   
199                    partialClass.setEnabled
200                    (NewClassWizard.canBePartial(classType.getText()));
201                   
202                    externalBody.setEnabled(classType.getText().equals("function"));
203
204                }
205
206                public void widgetDefaultSelected(SelectionEvent e)
207                {}
208               
209            });
210           
211            /* fill upp 'empty' space */
212            new Label(composite, SWT.NONE);
213
214           
215            /* create separator */
216            l = new Label(composite, SWT.HORIZONTAL | SWT.SEPARATOR);
217            gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL);
218            gd.horizontalSpan = 3;
219            l.setLayoutData(gd);
220           
221           
222            /* modifiers section */
223            l = new Label(composite, SWT.NONE);
224            l.setText("Modifiers:");
225           
226            /* initial equation block */
227            initialEquation = new Button(composite, SWT.CHECK);
228            initialEquation.setText("include initial equation block");
229           
230            gd = new GridData();
231            gd.horizontalAlignment = GridData.BEGINNING;
232            gd.horizontalSpan = 2;
233            initialEquation.setLayoutData(gd);
234           
235            /* partial class */
236            new Label(composite, SWT.NONE); /* empty label for padding */
237            partialClass = new Button(composite, SWT.CHECK);
238            partialClass.setText("is partial class");
239           
240            gd = new GridData();
241            gd.horizontalAlignment = GridData.BEGINNING;
242            gd.horizontalSpan = 2;
243            partialClass.setLayoutData(gd);
244
245            /* external body */
246            new Label(composite, SWT.NONE); /* empty label for padding */
247            externalBody = new Button(composite, SWT.CHECK);
248            externalBody.setText("have external body");
249            externalBody.setEnabled(false);
250           
251            gd = new GridData();
252            gd.horizontalAlignment = GridData.BEGINNING;
253            gd.horizontalSpan = 2;
254            externalBody.setLayoutData(gd);
255           
256
257        }
258
259        private void sourceFolderChanged()
260        {
261            IResource container = ResourcesPlugin.getWorkspace().getRoot()
262                    .findMember(new Path(sourceFolder.getText()));
263
264            sourceFolderValid = false;
265            if (sourceFolder.getText().length() == 0) {
266                updateStatus("File container must be specified", DialogPage.ERROR);
267                return;
268            }
269            if (container == null
270                    || (container.getType() & (IResource.PROJECT | IResource.FOLDER)) == 0) {
271                updateStatus("File container must exist", DialogPage.ERROR);
272                return;
273            }
274            if (!container.isAccessible()) {
275                updateStatus("Project must be writable", DialogPage.ERROR);
276                return;
277            }
278            sourceFolderValid = true;
279            updateStatus(null, DialogPage.NONE);
280        }
281
282        /**
283         * @return true if name is a valid modelica class name
284         */
285        protected boolean isLegalClassName(String name)
286        {
287            return classNamePattern.matcher(name).matches();
288        }
289       
290        public void init(IStructuredSelection selection)
291        {
292            if (selection == null || selection.size() != 1)
293            {
294                return;
295            }
296            if (!(selection.getFirstElement() instanceof IResource))
297            {
298                return;
299            }
300           
301            /*
302             * now we know that a single element of type IResource is selected
303             */
304            IResource sel = (IResource) selection.getFirstElement();
305
306            this.selection = sel.getFullPath();
307            if (sel.getType() == IResource.FILE)
308            {
309                this.selection = this.selection.removeLastSegments(1);
310            }
311        }
312       
313        private void handleBrowse()
314        {
315            ContainerSelectionDialog dialog =
316                new ContainerSelectionDialog(
317                    getShell(), ResourcesPlugin.getWorkspace().getRoot(), false,
318                    "Choose a source folder:");
319           
320            if (dialog.open() == ContainerSelectionDialog.OK)
321            {
322                Object[] result = dialog.getResult();
323                if (result.length == 1)
324                {
325                    setSourceFolder((IPath) result[0]);
326                }
327            }
328        }
329       
330        private void updateStatus(String message, int messageType)
331        {
332            setMessage(message, messageType);
333            setPageComplete((classNameValid && sourceFolderValid));
334        }
335
336
337        public void setSourceFolder(IPath path)
338        {
339            if (path != null)
340            {               
341                sourceFolder.setText(path.makeRelative().toString());
342                setPageComplete(isPageComplete());
343                sourceFolderValid = true;
344            }                       
345        }
346
347    }
348
349
350    private NewClassPage classPage = new NewClassPage();
351
352    public NewClassWizard()
353    {
354        super();
355    }
356
357    /**
358     * @param classType name of the class type, e.g. 'record'
359     * @return false if class type can't have equations, e.g.
360     * false is returned for record
361     */
362    public static boolean classTypeHaveEquations(String classType)
363    {
364        return 
365        !(classType.equals("record") 
366                || classType.equals("type")
367                || classType.equals("connector") 
368                || classType.equals("function"));
369    }
370   
371    /**
372     * @param classType name of the class type, e.g. 'record'
373     * @return false if class type can't have equations, e.g.
374     * false is returned for type
375     */
376    public static boolean canBePartial(String classType)
377    {
378        return 
379        (!(classType.equals("type") 
380                || classType.equals("function"))); 
381    }
382
383   
384    @Override
385    public boolean performFinish()
386    {
387        final String sourceFolder = classPage.sourceFolder.getText();
388        final String className = classPage.className.getText();
389        final String classType = classPage.classType.getText();
390        final boolean initialEquationBlock = 
391            classPage.initialEquation.getSelection();
392        final boolean partialClass = 
393            classPage.partialClass.getSelection();
394        final boolean externalBody = 
395            classPage.externalBody.getSelection();
396
397       
398        IRunnableWithProgress op = new IRunnableWithProgress() {
399            public void run(IProgressMonitor monitor) 
400                                throws InvocationTargetException
401             {
402                try 
403                {
404                    doFinish(sourceFolder, className, classType, 
405                            initialEquationBlock, partialClass, externalBody, monitor);
406                } 
407                catch (CoreException e)
408                {
409                    throw new InvocationTargetException(e);
410                }
411                finally 
412                {
413                    monitor.done();
414                }
415            }
416        };
417        try
418        {
419            getContainer().run(true, false, op);
420        }
421        catch (InterruptedException e)
422        {
423            return false;
424        }
425        catch (InvocationTargetException e)
426        {
427            Throwable realException = e.getTargetException();
428            MessageDialog.openError(getShell(), "Error", realException.getMessage());
429            return false;
430        }
431        return true;
432    }
433
434    protected void doFinish(String sourceFolder, String className, 
435            String classType, boolean initialEquationBlock, boolean partialClass, 
436            boolean haveExternalBody, IProgressMonitor monitor)
437    throws CoreException
438    {
439        // create a sample file
440        monitor.beginTask("Creating " + className, 2);
441       
442        IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
443        IResource resource = root.findMember(new Path(sourceFolder));
444       
445        IContainer container = (IContainer) resource;
446       
447        final IFile file = container.getFile(new Path(className+".mo"));
448       
449        try
450        {
451            String contents = generateClassContentes(className, classType, 
452                    initialEquationBlock, partialClass, haveExternalBody);
453            InputStream stream = 
454                new ByteArrayInputStream(contents.getBytes());
455            if (file.exists())
456            {
457                file.appendContents(stream, true, true, monitor);
458            }
459            else
460            {
461                file.create(stream, true, monitor);
462            }
463            stream.close();
464        } 
465        catch (IOException e)
466        {
467            /* ignored */
468        }
469        monitor.worked(1);
470        monitor.setTaskName("Opening file for editing...");
471        getShell().getDisplay().asyncExec(new Runnable() 
472        {
473            public void run()
474            {
475                IWorkbenchPage page =
476                    PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
477                try 
478                {
479                    IDE.openEditor(page, file, true);
480                }
481                catch (PartInitException e) 
482                {
483                    ErrorDialog.openError(null, "Error", 
484                            "Could not open class filer in an editor.",(new Status(IStatus.ERROR, 
485                            MdtPlugin.getSymbolicName(), 0, 
486                            "error starting editor for " + file.getName(), e)));
487                }
488            }
489        });
490        monitor.worked(1);
491
492    }
493
494    private String generateClassContentes(String className, String classType, 
495            boolean initialEquationBlock, boolean partialClass, boolean haveExternalBody) 
496    {
497        /*
498         * the gory logic of generating a skeleton for a modelica class
499         */
500        String contents = "";
501
502        if (canBePartial(classType) && partialClass)
503        {
504            contents += "partial ";
505        }
506       
507        contents += classType + " " + className;
508       
509        if (classTypeHaveEquations(classType))
510        {
511            contents += "\n\nequation\n";
512            if (initialEquationBlock)
513            {
514                contents += "\ninitial equation\n";
515            }
516        }
517       
518        if (classType.equals("function"))
519        {
520            if (haveExternalBody)
521            {
522                contents += "\nexternal";
523            }
524            else
525            {   
526                contents += "\nalgorithm\n";
527            }
528        }
529
530        if (!classType.equals("type"))
531        {
532            contents += "\nend " + className;
533        }
534
535        contents += ";";
536        return contents ;
537    }
538
539    public void init(IWorkbench workbench, IStructuredSelection selection)
540    {
541        classPage.init(selection);
542        setWindowTitle("New Modelica Class");
543    }
544
545    @Override
546    public void addPages()
547    {
548        addPage(classPage);
549    }
550}
Note: See TracBrowser for help on using the repository browser.