Skip to main content

Notice: This Wiki is now read only and edits are no longer possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.

Jump to: navigation, search

Difference between revisions of "Extending Sapphire Wizard"

(plugin.xml)
 
(2 intermediate revisions by one other user not shown)
Line 1: Line 1:
 
== Overview  ==
 
== Overview  ==
  
Sapphire does a great deal of automated work behind the scenes for us in creating Wizards, Editors and Dialog boxes. Sometimes there might be some requirement for us in extending Sapphire and providing the registrations via plugin.xml, the Sapphire source distribution has lots of good examples which help us in creating the such Wizards, editors and dialogs. The examples show us how to invoke them from command handlers ''' org.eclipse.ui.handlers ''' extensions, in this article we can see how to extend the Sapphire Wizard and register our custom wizard via plugin.xml, thereby allowing us to Categorize our Wizards and invoke them using the Workbench New Wizard dialog.  
+
Sapphire does a great deal of automated work behind the scenes for us in creating Wizards, Editors and Dialog boxes. Sometimes there might be some requirement for us in extending Sapphire and providing the registrations via plugin.xml, the Sapphire source distribution has lots of good examples which help us in creating the such Wizards, editors and dialogs. The examples show us how to invoke them from command handlers '''org.eclipse.ui.handlers ''' extensions, in this article we can see how to extend the Sapphire Wizard and register our custom wizard via plugin.xml, thereby allowing us to Categorize our Wizards and invoke them using the Workbench New Wizard dialog.  
  
 
For the demonstration purpose I will take a factitious example where will create a Wizard that will help us in creating a new Sapphire model interface that extends IModelElement  
 
For the demonstration purpose I will take a factitious example where will create a Wizard that will help us in creating a new Sapphire model interface that extends IModelElement  
  
<br> Lets start with our model elements definition,
+
<br> Lets start with our model elements definition,  
  
 
== Model  ==
 
== Model  ==
Line 198: Line 198:
 
</source>  
 
</source>  
  
{{Note | '''Note:'''|The SapphireNewWizard apart from extending from '''SapphireWizard&lt;M&gt;''' it should implement '''org.eclipse.ui.INewWizard''', otherwise a classcast exception will be thrown by the Workbench when invoking the Wizard }}
+
{{Note | '''Note:'''|The SapphireNewWizard apart from extending from '''SapphireWizard&lt;M&gt;''' it should implement '''org.eclipse.ui.INewWizard''', otherwise a classcast exception will be thrown by the Workbench when invoking the Wizard }}  
  
 
'''NewSapphireModelCreationWizard.java ''' <source lang="java">
 
'''NewSapphireModelCreationWizard.java ''' <source lang="java">
Line 232: Line 232:
  
 
}
 
}
</source>
+
</source>  
 +
 
 +
Now its the time to register the wizard via the plugin.xml as shown below
  
Now its the time to register the wizard  via the plugin.xml as shown below
+
== plugin.xml ==
  
== plugin.xml ==
 
 
<source lang="xml">
 
<source lang="xml">
 
<?xml version="1.0" encoding="UTF-8"?>
 
<?xml version="1.0" encoding="UTF-8"?>
Line 257: Line 258:
 
   </extension>
 
   </extension>
 
</plugin>
 
</plugin>
</source>
+
</source>  
 +
 
 +
== Create Workspace Resource Wizard ==
 +
 
 +
As an IModelElement cannot be hooked up to a ''Resource'' (see [http://www.eclipse.org/forums/index.php/t/237700/ here]) after it has been created, here is a little custom Wizard to create a WorkspaceResource.
 +
 
 +
'''SapphireCreateWizard.java ''' <source lang="java">
 +
 
 +
public abstract class SapphireCreateWizard<M extends IModelElement> extends Wizard implements INewWizard {
 +
//TODO This class could inherit from org.eclipse.sapphire.ui.swt.SapphireWizard, but addPages and performFinish are final
 +
 
 +
//Sapphire specific
 +
private final M element;
 +
private final ISapphireWizardDef definition;
 +
private final SapphireWizardPart part;
 +
private final SapphirePartListener listener;
 +
 
 +
//Wizard specific
 +
private IStructuredSelection selection;
 +
private WizardNewFileCreationPage createFilePage;
 +
 
 +
/**
 +
* @param element
 +
* @param wizardDefPath
 +
*/
 +
public SapphireCreateWizard(M element, final String wizardDefPath) {
 +
this.element = element;
 +
definition = SapphireUiDefFactory.getWizardDef(wizardDefPath);
 +
 
 +
part = new SapphireWizardPart();
 +
part.init(null, element, definition, Collections.<String, String> emptyMap());
 +
 
 +
setWindowTitle(this.part.getLabel());
 +
 
 +
listener = new SapphirePartListener() {
 +
@Override
 +
public void handleEvent(final SapphirePartEvent event) {
 +
if (event instanceof ImageChangedEvent) {
 +
refreshImage();
 +
}
 +
}
 +
};
 +
 
 +
part.addListener(listener);
 +
refreshImage();
 +
setNeedsProgressMonitor(true);
 +
}
 +
 
 +
@Override
 +
public void addPages() {
 +
// If the Wizard wasn't called via Strg+n
 +
if (selection == null)
 +
selection = new StructuredSelection();
 +
 
 +
// Add WizardNewFileCreationPage
 +
String title = "Create " + element.getClass().getSimpleName();
 +
createFilePage = new WizardNewFileCreationPage(title, (IStructuredSelection) selection);
 +
addPage(createFilePage);
 +
 
 +
// Add declared sapphire pages
 +
for (SapphireWizardPagePart pagePart : part.getPages())
 +
addPage(new SapphireWizardPage(pagePart));
 +
}
 +
 
 +
@Override
 +
public boolean performFinish() {
 +
// Create file, WorkspaceResourceStore and copy content to
 +
// RootXmlResource handle by the store
 +
try {
 +
IFile file = createFilePage.createNewFile();
 +
try {
 +
XmlResourceStore store = new XmlResourceStore(new WorkspaceFileResourceStore(file));
 +
RootXmlResource resource = new RootXmlResource(store);
 +
M newElement = element.getModelElementType().instantiate(resource);
 +
copyContents(element, newElement);
 +
store.save();
 +
} catch (ResourceStoreException e) {
 +
e.printStackTrace();
 +
}
 +
element.resource().save();
 +
} catch (ResourceStoreException e) {
 +
e.printStackTrace();
 +
return false;
 +
}
 +
return true;
 +
}
 +
 
 +
private final void refreshImage() {
 +
setDefaultPageImageDescriptor(toImageDescriptor(this.part.getImage()));
 +
}
 +
 
 +
@Override
 +
public void init(IWorkbench workbench, IStructuredSelection selection) {
 +
this.selection = selection;
 +
}
 +
 
 +
/**
 +
* <p>Found no way how to copy contents from one to another IModelElement,
 +
* so this method will do the work instead</p>
 +
* @param source
 +
* @param destination
 +
*/
 +
abstract protected void copyContents(M source, M destination);
 +
 
 +
}
 +
</source>
 +
 
 +
For a reference implementation you can check [https://github.com/knowing/Knowing/blob/sapphire-model/de.lmu.ifi.dbs.knowing.ui/src/de/lmu/ifi/dbs/knowing/ui/wizard/NewDPUWizard.java this class].
 +
 
 +
{{Note | '''Note:'''|The SapphireCreateWizard doesn't extend  '''SapphireWizard&lt;M&gt;''', because ''addPages'' and ''performFinish''
 +
are declared as final. That leads to code repetition, which should be avoided. }}
 +
 
 +
== Conclusion  ==
  
== ==
+
And there you go, when you start your Eclipse Plug-in, you should see a '''New Sapphire Model''' in the new wizards dialog under the '''Sapphire''' category. Now we have Sapphire based Wizard that can be invoked using the Workbench "New Wizard" dialog
And there you go, when you start your Eclipse Pluign, you should see a '''New Sapphire Model''' in the new wizards dialog under the '''Sapphire''' category
+

Latest revision as of 05:20, 4 September 2011

Overview

Sapphire does a great deal of automated work behind the scenes for us in creating Wizards, Editors and Dialog boxes. Sometimes there might be some requirement for us in extending Sapphire and providing the registrations via plugin.xml, the Sapphire source distribution has lots of good examples which help us in creating the such Wizards, editors and dialogs. The examples show us how to invoke them from command handlers org.eclipse.ui.handlers extensions, in this article we can see how to extend the Sapphire Wizard and register our custom wizard via plugin.xml, thereby allowing us to Categorize our Wizards and invoke them using the Workbench New Wizard dialog.

For the demonstration purpose I will take a factitious example where will create a Wizard that will help us in creating a new Sapphire model interface that extends IModelElement


Lets start with our model elements definition,

Model

ISapphireModelDef .java

@GenerateImpl
@XmlRootBinding(elementName = "sapphire-model")
public interface ISapphireModelDef extends IExecutableModelElement {
 
    ModelElementType TYPE = new ModelElementType(ISapphireModelDef.class);
 
    // *** Package ***
 
    @Label(standard = "Model Package")
    @XmlBinding(path = "model-package")
    ValueProperty PROP_MODEL_PACKAGE = new ValueProperty(TYPE, "ModelPackage");
 
    Value<String> getModelPackage();
 
    void setModelPackage(String value);
 
    // *** ModelName ***
 
    @Label(standard = "Model Name")
    @XmlBinding(path = "model-name")
    ValueProperty PROP_MODEL_NAME = new ValueProperty(TYPE, "ModelName");
 
    void setModelName(String value);
 
    void setModelName(JavaTypeName value);
 
    // *** ValueProperties ***
 
    @Type(base = ISModelValueProperty.class)
    @Label(standard = "Value Properties")
    @XmlListBinding(mappings = { @XmlListBinding.Mapping(element = "", type = ISModelTypedValueProperty.class) })
    ListProperty PROP_VALUE_PROPERTIES = new ListProperty(TYPE,
            "ValueProperties");
 
    ModelElementList<ISModelValueProperty> getValueProperties();
 
    // *** Method: execute ***
 
    @DelegateImplementation(ISapphireModelDefOpMethods.class)
    Status execute(ProgressMonitor monitor);
 
}
ISModelPropertyBase.java
@GenerateImpl
public interface ISModelPropertyBase extends IModelElement {
 
    ModelElementType TYPE = new ModelElementType(ISModelPropertyBase.class);
 
    // *** Name ***
 
    @Label(standard = "Name")
    @XmlBinding(path = "name")
    ValueProperty PROP_Name = new ValueProperty(TYPE, "Name");
 
    Value<String> getName();
 
    void setName(String value);
 
    // *** Label ***
 
    @Label(standard = "Label")
    @XmlBinding(path = "label")
    ValueProperty PROP_LABEL = new ValueProperty(TYPE, "Label");
 
    Value<String> getLabel();
 
    void setLabel(String value);
 
    // *** XmlBinding ***
 
    @Label(standard = "Xml Binding")
    @XmlBinding(path = "xml-binding")
    ValueProperty PROP_XML_BINDING = new ValueProperty(TYPE, "XmlBinding");
 
    Value<String> getXmlBinding();
 
    void setXmlBinding(String value);
 
}
ISModelPropertyBase.java
@GenerateImpl
public interface ISModelTypedValueProperty extends ISModelPropertyBase {
    ModelElementType TYPE = new ModelElementType(
            ISModelTypedValueProperty.class);
 
}

ISModelValueProperty.java

@GenerateImpl
public interface ISModelValueProperty extends ISModelPropertyBase {
 
    ModelElementType TYPE = new ModelElementType(ISModelValueProperty.class);
 
 
}
ISapphireModelDefOpMethods.java
public final class ISapphireModelDefOpMethods
{
    public static final Status execute( final ISapphireModelDef context,
                                        final ProgressMonitor monitor )
    {
        // Do something here.
 
        return Status.createOkStatus();
    }
}

Sapphire UI Definition

<?xml version="1.0" encoding="UTF-8"?>
<definition>
    <import>
        <package>org.eclipse.sapphire.model</package>
    </import>
    <wizard>
        <id>new.sapphire.model.creation.wizard</id>
        <label>New Sapphire Model</label>
        <description>This wizard will allow the creation of New Sapphire Models</description>
        <image>icons/sapphire-32.png</image>
        <page>
            <id>basic.properties</id>
            <label>Model Basic Properties</label>
            <description>Define the basic properties of the model like name, package etc.,</description>
            <content>
                <property-editor>ModelPackage</property-editor>
                <property-editor>ModelName</property-editor>
            </content>
        </page>
        <page>
            <id>new-sapphire-model.valueproperties.page</id>
            <label>Value Properties</label>
            <description>Define all value properties for the model</description>
            <content>
                <property-editor>ValueProperties</property-editor>
            </content>
        </page>
    </wizard>
</definition>

We have now defined our model and defined the Sapphire UI definition we can now create our Custom Wizard classes and register it via plugin.xml

Wizard Classes

SapphireNewWizard.java
public abstract class SapphireNewWizard<M extends IExecutableModelElement>
        extends SapphireWizard<M> implements INewWizard {
 
    private IWorkbench workbench;
    private IStructuredSelection selection;
 
    public SapphireNewWizard(M modelElement, String wizardDefPath) {
        super(modelElement, wizardDefPath);
        setNeedsProgressMonitor(true);
    }
 
    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.ui.IWorkbenchWizard#init(org.eclipse.ui.IWorkbench,
     * org.eclipse.jface.viewers.IStructuredSelection)
     */
    @Override
    public void init(IWorkbench workbench, IStructuredSelection selection) {
        this.workbench = workbench;
        this.selection = selection;
 
    }
 
}
Note.png
' Note:'
The SapphireNewWizard apart from extending from SapphireWizard<M> it should implement org.eclipse.ui.INewWizard, otherwise a classcast exception will be thrown by the Workbench when invoking the Wizard


NewSapphireModelCreationWizard.java
public class NewSapphireModelCreationWizard extends
        SapphireNewWizard<ISapphireModelDef> {
 
    public final static String ID = "org.eclipse.sapphire.ui.wizards.NewSapphireModelCreationWizard";
    private final static String WIZARD_DEF_PATH = "com.sk.contentassist.demo/org/eclipse/sapphire/ui/wizards/sapphire-model-wizards.sdef!new.sapphire.model.creation.wizard";
    private final static ISapphireModelDef modelElement = ISapphireModelDef.TYPE
            .instantiate();
 
    /**
     * @param modelElement
     * @param wizardDefPath
     */
    public NewSapphireModelCreationWizard() {
        super(modelElement, NewSapphireModelCreationWizard.WIZARD_DEF_PATH);
    }
 
    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.sapphire.ui.swt.SapphireWizard#performPostFinish()
     */
    @Override
    protected void performPostFinish() {
        try {
            modelElement.resource().save();
        } catch (ResourceStoreException e) {
            SapphireUiFrameworkPlugin.log(e);
        }
    }
 
}

Now its the time to register the wizard via the plugin.xml as shown below

plugin.xml

<?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.4"?>
<plugin>
 <extension
         point="org.eclipse.ui.newWizards">
      <category
            id="com.sk.contentassist.demo.sapphire.wizard"
            name="Sapphire">
      </category>
      <wizard
            canFinishEarly="false"
            category="com.sk.contentassist.demo.sapphire.wizard"
            class="org.eclipse.sapphire.ui.wizards.NewSapphireModelCreationWizard"
            icon="icons/sapphire-32.png"
            id="org.eclipse.sapphire.ui.wizards.NewSapphireModelCreationWizard"
            name="New Sapphire Model">
      </wizard>
   </extension>
</plugin>

Create Workspace Resource Wizard

As an IModelElement cannot be hooked up to a Resource (see here) after it has been created, here is a little custom Wizard to create a WorkspaceResource.

SapphireCreateWizard.java
public abstract class SapphireCreateWizard<M extends IModelElement> extends Wizard implements INewWizard {
	//TODO This class could inherit from org.eclipse.sapphire.ui.swt.SapphireWizard, but addPages and performFinish are final
 
	//Sapphire specific
	private final M element;
	private final ISapphireWizardDef definition;
	private final SapphireWizardPart part;
	private final SapphirePartListener listener;
 
	//Wizard specific
	private IStructuredSelection selection;
	private WizardNewFileCreationPage createFilePage;
 
	/**
	 * @param element
	 * @param wizardDefPath
	 */
	public SapphireCreateWizard(M element, final String wizardDefPath) {
		this.element = element;
		definition = SapphireUiDefFactory.getWizardDef(wizardDefPath);
 
		part = new SapphireWizardPart();
		part.init(null, element, definition, Collections.<String, String> emptyMap());
 
		setWindowTitle(this.part.getLabel());
 
		listener = new SapphirePartListener() {
			@Override
			public void handleEvent(final SapphirePartEvent event) {
				if (event instanceof ImageChangedEvent) {
					refreshImage();
				}
			}
		};
 
		part.addListener(listener);
		refreshImage();
		setNeedsProgressMonitor(true);
	}
 
	@Override
	public void addPages() {
		// If the Wizard wasn't called via Strg+n
		if (selection == null)
			selection = new StructuredSelection();
 
		// Add WizardNewFileCreationPage
		String title = "Create " + element.getClass().getSimpleName();
		createFilePage = new WizardNewFileCreationPage(title, (IStructuredSelection) selection);
		addPage(createFilePage);
 
		// Add declared sapphire pages
		for (SapphireWizardPagePart pagePart : part.getPages())
			addPage(new SapphireWizardPage(pagePart));
	}
 
	@Override
	public boolean performFinish() {
		// Create file, WorkspaceResourceStore and copy content to
		// RootXmlResource handle by the store
		try {
			IFile file = createFilePage.createNewFile();
			try {
				XmlResourceStore store = new XmlResourceStore(new WorkspaceFileResourceStore(file));
				RootXmlResource resource = new RootXmlResource(store);
				M newElement = element.getModelElementType().instantiate(resource);
				copyContents(element, newElement);
				store.save();
			} catch (ResourceStoreException e) {
				e.printStackTrace();
			}
			element.resource().save();
		} catch (ResourceStoreException e) {
			e.printStackTrace();
			return false;
		}
		return true;
	}
 
	private final void refreshImage() {
		setDefaultPageImageDescriptor(toImageDescriptor(this.part.getImage()));
	}
 
	@Override
	public void init(IWorkbench workbench, IStructuredSelection selection) {
		this.selection = selection;
	}
 
	/**
	 * <p>Found no way how to copy contents from one to another IModelElement,
	 * so this method will do the work instead</p>
	 * @param source
	 * @param destination
	 */
	abstract protected void copyContents(M source, M destination);
 
}

For a reference implementation you can check this class.

Note.png
' Note:'
The SapphireCreateWizard doesn't extend SapphireWizard<M>, because addPages and performFinish are declared as final. That leads to code repetition, which should be avoided.


Conclusion

And there you go, when you start your Eclipse Plug-in, you should see a New Sapphire Model in the new wizards dialog under the Sapphire category. Now we have Sapphire based Wizard that can be invoked using the Workbench "New Wizard" dialog

Back to the top