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

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