niedziela, 29 czerwca 2008

NetBeans + Ecplise = ...

W sobotę (28.08.2008) miałem okazję uczestniczyć w Ecplise DemoCamps w Krakowie. Spotkanie zaliczam do udanych. W drodze powrotnej przypomniał mi się niedawny wpis na blogu Geertjan Wielengi opisujący jak uruchomić aplikację napisaną z wykorzystaniem NetBeans Platform z Eclipsa.
Jako, że ostatnio miałem trochę do czynienia z bardzo fajną biblioteką Visual Library, która wchodzi w skład platformy NetBeans, pomyślałem, że może by spróbować napisać prosty programik w Eclipsie wykorzystujący tą bibliotekę.
Ściągnąłem Visual Library, odpaliłem Eclipsa i zabrałem się do pracy. Okazało się, że tej pracy nie było dużo (wręcz prawie w ogóle).
Po pierwsze stworzyłem panel, na którym miał wylądować edytor graficzny.


package pl.marekklis.graph;

import java.awt.BorderLayout;
import java.awt.Dimension;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;

import org.netbeans.api.visual.graph.GraphScene;

public class GraphTest extends JPanel{

public static void main(String[] args) {
JFrame frame = new JFrame("Graph test");
frame.setMinimumSize(new Dimension(400,300));
frame.setSize(400, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setContentPane(new GraphTest());
frame.pack();
frame.setVisible(true);
}

public GraphTest() {
initComponents();
}

private void initComponents(){
setLayout(new BorderLayout());
JScrollPane scrollPane = new JScrollPane();
add(scrollPane,BorderLayout.CENTER);
GraphScene scene = new GraphSceneImpl();
scrollPane.setViewportView(scene.createView());
add(scene.createSatelliteView(),BorderLayout.WEST);
}

}


Po drugie stworzyłem implementacje GraphScene.


package pl.marekklis.graph;

import java.awt.Point;

import org.netbeans.api.visual.action.ActionFactory;
import org.netbeans.api.visual.action.ConnectProvider;
import org.netbeans.api.visual.action.ConnectorState;
import org.netbeans.api.visual.anchor.AnchorFactory;
import org.netbeans.api.visual.anchor.AnchorShape;
import org.netbeans.api.visual.graph.GraphScene;
import org.netbeans.api.visual.widget.ConnectionWidget;
import org.netbeans.api.visual.widget.LayerWidget;
import org.netbeans.api.visual.widget.Scene;
import org.netbeans.api.visual.widget.Widget;
import org.netbeans.api.visual.widget.general.IconNodeWidget;
import org.openide.util.Utilities;

public class GraphSceneImpl extends GraphScene {

private LayerWidget mainLayer;
private LayerWidget connectionLayer;
private LayerWidget interactionLayer;

public GraphSceneImpl() {
mainLayer = new LayerWidget(this);
connectionLayer = new LayerWidget(this);
interactionLayer = new LayerWidget(this);
addChild(mainLayer);
addChild(connectionLayer);
addChild(interactionLayer);
Widget w1 = addNode("1. węzeł");
w1.setPreferredLocation(new Point(10, 100));
Widget w2 = addNode("2. węzeł");
w2.setPreferredLocation(new Point(100, 250));
Widget w3 = addNode("Jakiś kolejny węzeł");
w3.setPreferredLocation(new Point(250, 250));
Widget w4 = addNode("Jakiś kolejny węzeł");
w4.setPreferredLocation(new Point(250, 350));
getActions().addAction(ActionFactory.createZoomAction());
}

@Override
protected Widget attachNodeWidget(String arg0) {
IconNodeWidget widget = new IconNodeWidget(this);
if (arg0.startsWith("1")) {
widget.setImage(Utilities.loadImage("pl/marekklis/graph/
resources/gr01.png"));
} else if (arg0.startsWith("2")) {
widget.setImage(Utilities.loadImage("pl/marekklis/graph/
resources/gr02.png"));
} else {
widget.setImage(Utilities.loadImage("pl/marekklis/graph/
resources/gr03.png"));
}
widget.getActions().addAction(
ActionFactory.createExtendedConnectAction(
connectionLayer,new MyConnectProvider()));
widget.getActions().addAction(
ActionFactory.createAlignWithMoveAction(
mainLayer, interactionLayer,
ActionFactory.createDefaultAlignWithMoveDecorator()));
widget.setLabel(arg0);
mainLayer.addChild(widget);
return widget;
}

@Override
protected Widget attachEdgeWidget(String arg0) {
return null;
}

@Override
protected void attachEdgeSourceAnchor(
String arg0, String arg1, String arg2) {
}

@Override
protected void attachEdgeTargetAnchor(
String arg0, String arg1, String arg2) {
}

private class MyConnectProvider implements ConnectProvider {

public boolean isSourceWidget(Widget source) {
return source instanceof IconNodeWidget && source != null
? true : false;
}

public ConnectorState isTargetWidget(Widget src, Widget trg) {
return src != trg && trg instanceof IconNodeWidget ?
ConnectorState.ACCEPT : ConnectorState.REJECT;
}

public boolean hasCustomTargetWidgetResolver(Scene arg0) {
return false;
}

public Widget resolveTargetWidget(Scene arg0, Point arg1) {
return null;
}

public void createConnection(Widget source, Widget target) {
ConnectionWidget conn = new ConnectionWidget(
GraphSceneImpl.this);
conn.setTargetAnchorShape(AnchorShape.TRIANGLE_FILLED);
conn.setTargetAnchor(AnchorFactory.
createRectangularAnchor(target));
conn.setSourceAnchor(AnchorFactory.
createRectangularAnchor(source));
connectionLayer.addChild(conn);
}
}
}


I oto efekt:


W naszym okienku mamy działający przykład wykorzystujący Visual Library.

PS. Biblioteki Visual Library nie musimy ściągać gdyż jest ona częścią Netbeansa i znajduje się w katalog_Netbeansa/platform8/modules/.

4 komentarze:

Anonimowy pisze...

Ten program nie
kompiluje się w NetBeans, bo NetBeans nie lubi tego:
attachNodeWidget(__String__ arg0).
Oczywiście po małych zmianach program ruszył.

Marek Kliś pisze...

Dzieki za info.
Mógłbyś wyjaśnić co znaczy "nie lubi".
Typ węzła może być dowolny (za dokumentacją GraphScene<MyNode,MyEdge>) więc może brakować jawnego pokazania typów czyli GraphScene<String,String>.
Ten przykład opisuje jak użyć Visual Library w Eclipsie, jeśli chcesz przykładu użycia Visual Library w projekcie korzystającym z platformy NetBeans to przykładowy projekt z mojej prelekcji na NetBeans Day we Wrocławiu (http://marekklis.blogspot.com/2008/04/netbeans-platform-materiay-z-prelekcji.html)

Anonimowy pisze...

W źródle jest:
attachNodeWidget(String arg0)

a w dokumentacji:
attachNodeWidget(Object arg0)

String czy Object ???

Marek Kliś pisze...

To chyba mamy różne dokumentacje ;)
Wg API NetBeans:
public abstract class GraphScene<N,E> i attachNodeWidget(N node) oraz attachEdgeWidget(E edge).
Visual Library (i NetBeans Platform) korzysta z nowości wprowadzonych w Java 5 m.in. typów ogólnych (generics). Tak jak wcześniej napisałem, brakowało sparametryzowania definicji klasy GraphScene.
Mam nadzieję, że wyjaśniłem Twoje wątpliwości.

Pozdrawiam