devel:plugins:start
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revisionLast revisionBoth sides next revision | ||
devel:plugins:start [2018/10/02 16:27] – [Mathematical layer classes] expanded this section with further detail on what each part means (textually) alex_chan | devel:plugins:start [2018/10/09 11:10] – danil | ||
---|---|---|---|
Line 1: | Line 1: | ||
====== Plugin development ====== | ====== Plugin development ====== | ||
- | This exercise | + | The following set of exercises |
+ | |||
+ | Before continuing with these exercises make sure that you know how to [[devel:build|build Workcraft from sources]]). | ||
===== Project setup ===== | ===== Project setup ===== | ||
- | To begin, | + | For each exercise you will need to create a new project directory |
- | Next either | + | In the project directory |
<file shell build.gradle> | <file shell build.gradle> | ||
Line 28: | Line 30: | ||
If everything has went smoothly, you are now set to go. | If everything has went smoothly, you are now set to go. | ||
- | ===== Module class ===== | ||
- | As a first step to creating any new Workcraft | + | * [[:devel:plugin: |
+ | * [[:devel:plugin: | ||
+ | * [[:devel: | ||
- | <file java BasicModule.java> | ||
- | package org.workcraft.plugins.basic; | ||
- | |||
- | import org.workcraft.Framework; | ||
- | import org.workcraft.Module; | ||
- | import org.workcraft.PluginManager; | ||
- | |||
- | public class BasicModule implements Module { | ||
- | |||
- | @Override | ||
- | public String getDescription() { | ||
- | return "Basic Module"; | ||
- | } | ||
- | |||
- | @Override | ||
- | public void init() { | ||
- | final Framework framework = Framework.getInstance(); | ||
- | final PluginManager pm = framework.getPluginManager(); | ||
- | pm.registerModelDescriptor(BasicDescriptor.class); | ||
- | } | ||
- | } | ||
- | </ | ||
- | |||
- | One may notice that inside the '' | ||
- | |||
- | In the case of the '' | ||
- | |||
- | <file java BasicDescriptor.java> | ||
- | package org.workcraft.plugins.basic; | ||
- | |||
- | import org.workcraft.dom.ModelDescriptor; | ||
- | import org.workcraft.dom.VisualModelDescriptor; | ||
- | import org.workcraft.dom.math.MathModel; | ||
- | |||
- | public class BasicDescriptor implements ModelDescriptor { | ||
- | |||
- | @Override | ||
- | public String getDisplayName() { | ||
- | return "Basic Model"; | ||
- | } | ||
- | |||
- | @Override | ||
- | public MathModel createMathModel() { | ||
- | return new Basic(); | ||
- | } | ||
- | |||
- | @Override | ||
- | public VisualModelDescriptor getVisualModelDescriptor() { | ||
- | return new VisualBasicDescriptor(); | ||
- | } | ||
- | } | ||
- | </ | ||
- | |||
- | However, unlike how the '' | ||
- | |||
- | The class does this by implementing the '' | ||
- | |||
- | <file java VisualBasicDescriptor.java> | ||
- | package org.workcraft.plugins.basic; | ||
- | |||
- | import org.workcraft.dom.VisualModelDescriptor; | ||
- | import org.workcraft.dom.math.MathModel; | ||
- | import org.workcraft.dom.visual.VisualModel; | ||
- | |||
- | public class VisualBasicDescriptor implements VisualModelDescriptor { | ||
- | |||
- | @Override | ||
- | public VisualModel create(MathModel mathModel) { | ||
- | if (mathModel instanceof Basic) { | ||
- | return new VisualBasic((Basic) mathModel); | ||
- | } | ||
- | throw new RuntimeException(" | ||
- | } | ||
- | } | ||
- | </ | ||
- | |||
- | As a result, we have registered the '' | ||
- | |||
- | ===== Mathematical layer classes ===== | ||
- | |||
- | To describe how our mathematical model works, we need to first determine its node(s) and their functionality and interactivity with each other. Fortunately, | ||
- | |||
- | For our exercise, we will simply make our '' | ||
- | |||
- | <file java Basic.java> | ||
- | package org.workcraft.plugins.basic; | ||
- | |||
- | import org.workcraft.dom.Container; | ||
- | import org.workcraft.dom.Node; | ||
- | import org.workcraft.dom.math.AbstractMathModel; | ||
- | import org.workcraft.dom.math.MathConnection; | ||
- | import org.workcraft.dom.math.MathNode; | ||
- | import org.workcraft.dom.references.HierarchicalUniqueNameReferenceManager; | ||
- | import org.workcraft.dom.references.ReferenceManager; | ||
- | import org.workcraft.serialisation.References; | ||
- | import org.workcraft.util.Hierarchy; | ||
- | |||
- | public class Basic extends AbstractMathModel { | ||
- | |||
- | public Basic() { | ||
- | this(null); | ||
- | } | ||
- | |||
- | public Basic(Container root) { | ||
- | super(root); | ||
- | } | ||
- | |||
- | public MathConnection connect(Node first, Node second) { | ||
- | MathConnection con = new MathConnection((MathNode) first, (MathNode) second); | ||
- | Hierarchy.getNearestContainer(first, | ||
- | return con; | ||
- | } | ||
- | } | ||
- | </ | ||
- | |||
- | To make our example simple, this model will only make use one type of node that is implemented as a relatively trivial '' | ||
- | |||
- | <file java Vertex.java> | ||
- | package org.workcraft.plugins.basic; | ||
- | |||
- | import org.workcraft.annotations.VisualClass; | ||
- | import org.workcraft.dom.math.MathNode; | ||
- | |||
- | @VisualClass(VisualVertex.class) | ||
- | public class Vertex extends MathNode { | ||
- | } | ||
- | </ | ||
- | |||
- | It is also worth noting that our '' | ||
- | |||
- | ===== Visual layer classes ===== | ||
- | |||
- | The visual model extends the '' | ||
- | |||
- | <file java VisualBasic.java> | ||
- | package org.workcraft.plugins.basic; | ||
- | |||
- | import org.workcraft.annotations.DisplayName; | ||
- | import org.workcraft.annotations.ShortName; | ||
- | import org.workcraft.dom.Container; | ||
- | import org.workcraft.dom.Node; | ||
- | import org.workcraft.dom.math.MathConnection; | ||
- | import org.workcraft.dom.visual.AbstractVisualModel; | ||
- | import org.workcraft.dom.visual.VisualComponent; | ||
- | import org.workcraft.dom.visual.VisualGroup; | ||
- | import org.workcraft.dom.visual.connections.VisualConnection; | ||
- | import org.workcraft.exceptions.InvalidConnectionException; | ||
- | import org.workcraft.exceptions.NodeCreationException; | ||
- | import org.workcraft.gui.graph.generators.DefaultNodeGenerator; | ||
- | import org.workcraft.gui.graph.tools.*; | ||
- | import org.workcraft.util.Hierarchy; | ||
- | |||
- | import java.util.ArrayList; | ||
- | import java.util.List; | ||
- | |||
- | @DisplayName(" | ||
- | @ShortName(" | ||
- | public class VisualBasic extends AbstractVisualModel { | ||
- | |||
- | public VisualBasic(Basic model) { | ||
- | this(model, null); | ||
- | } | ||
- | |||
- | public VisualBasic(Basic model, VisualGroup root) { | ||
- | super(model, | ||
- | setGraphEditorTools(); | ||
- | if (root == null) { | ||
- | try { | ||
- | createDefaultFlatStructure(); | ||
- | } catch (NodeCreationException e) { | ||
- | throw new RuntimeException(e); | ||
- | } | ||
- | } | ||
- | } | ||
- | |||
- | private void setGraphEditorTools() { | ||
- | List< | ||
- | tools.add(new SelectionTool()); | ||
- | tools.add(new CommentGeneratorTool()); | ||
- | tools.add(new ConnectionTool()); | ||
- | tools.add(new NodeGeneratorTool(new DefaultNodeGenerator(Vertex.class))); | ||
- | setGraphEditorTools(tools); | ||
- | } | ||
- | |||
- | @Override | ||
- | public void validateConnection(Node first, Node second) throws InvalidConnectionException { | ||
- | if ((first instanceof VisualVertex) && (second instanceof VisualVertex)) return; | ||
- | |||
- | throw new InvalidConnectionException(" | ||
- | } | ||
- | |||
- | @Override | ||
- | public VisualConnection connect(Node first, Node second, MathConnection mConnection) | ||
- | throws InvalidConnectionException { | ||
- | validateConnection(first, | ||
- | |||
- | VisualComponent v1 = (VisualComponent) first; | ||
- | VisualComponent v2 = (VisualComponent) second; | ||
- | Node m1 = v1.getReferencedComponent(); | ||
- | Node m2 = v2.getReferencedComponent(); | ||
- | |||
- | if (mConnection == null) { | ||
- | mConnection = ((Basic) getMathModel()).connect(m1, | ||
- | } | ||
- | VisualConnection vConnection = new VisualConnection(mConnection, | ||
- | Container container = Hierarchy.getNearestContainer(v1, | ||
- | container.add(vConnection); | ||
- | return vConnection; | ||
- | } | ||
- | } | ||
- | </ | ||
- | |||
- | Visualisation of vertex node is implemented by '' | ||
- | |||
- | <file java VisualVertex.java> | ||
- | package org.workcraft.plugins.basic; | ||
- | |||
- | import org.workcraft.dom.visual.DrawRequest; | ||
- | import org.workcraft.dom.visual.VisualComponent; | ||
- | import org.workcraft.gui.Coloriser; | ||
- | |||
- | import java.awt.*; | ||
- | import java.awt.geom.Rectangle2D; | ||
- | |||
- | public class VisualVertex extends VisualComponent { | ||
- | |||
- | public VisualVertex(Vertex vertex) { | ||
- | super(vertex); | ||
- | } | ||
- | |||
- | @Override | ||
- | public void draw(DrawRequest r) { | ||
- | Graphics2D g = r.getGraphics(); | ||
- | |||
- | double xy = -size / 2 + strokeWidth / 2; | ||
- | double wh = size - strokeWidth; | ||
- | Shape shape = new Rectangle2D.Double(xy, | ||
- | |||
- | Color background = r.getDecoration().getBackground(); | ||
- | g.setColor(Coloriser.colorise(getFillColor(), | ||
- | g.fill(shape); | ||
- | |||
- | Color colorisation = r.getDecoration().getColorisation(); | ||
- | g.setColor(Coloriser.colorise(getForegroundColor(), | ||
- | g.setStroke(new BasicStroke((float) strokeWidth)); | ||
- | g.draw(shape); | ||
- | |||
- | drawLabelInLocalSpace(r); | ||
- | drawNameInLocalSpace(r); | ||
- | } | ||
- | } | ||
- | </ | ||
Copyright © 2014-2024 workcraft.org