diff --git a/pom.xml b/pom.xml
index 5c203e5..4c0763e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -21,7 +21,7 @@
org.graphstream
gs-ui-swing
- 2.0
+ 2.1.0-SNAPSHOT
jar
gs-ui-swing
diff --git a/src-test/org/graphstream/ui/viewer_swing/test/Clicks.java b/src-test/org/graphstream/ui/viewer_swing/test/Clicks.java
new file mode 100644
index 0000000..707f88c
--- /dev/null
+++ b/src-test/org/graphstream/ui/viewer_swing/test/Clicks.java
@@ -0,0 +1,136 @@
+import org.graphstream.graph.Graph;
+import org.graphstream.graph.Node;
+import org.graphstream.graph.implementations.SingleGraph;
+import org.graphstream.ui.swing_viewer.SwingViewer;
+import org.graphstream.ui.swing_viewer.ViewPanel;
+import org.graphstream.ui.view.Viewer;
+import org.graphstream.ui.view.ViewerListener;
+import org.graphstream.ui.view.ViewerPipe;
+
+import javax.swing.*;
+import java.awt.*;
+
+public class Clicks {
+
+ static Graph graph;
+ static JDialog mainFrame;
+ static JPanel mainPanel;
+
+ static JTextArea codeArea;
+
+
+ public static void main(String args[]) {
+ System.setProperty("org.graphstream.ui", "swing");
+ System.setProperty("sun.java2d.uiScale", "1.0");
+ new Clicks();
+ System.out.println("Doneee");
+
+ }
+
+
+ boolean loop;
+ public Clicks() {
+ loop = true;
+ mainFrame = new JDialog();
+ JDialog frame = mainFrame;
+ mainPanel = new JPanel(){
+ @Override
+ public Dimension getPreferredSize() {
+ return new Dimension(640, 480);
+ }
+ };
+ mainPanel.setLayout(new BorderLayout());
+ JPanel panel = mainPanel;
+ codeArea = new JTextArea();
+ codeArea.setEditable(false);
+
+
+
+
+
+
+ frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
+
+ panel.setBorder(BorderFactory.createLineBorder(Color.blue, 5));
+ mainFrame.add(panel);
+
+ graph = new SingleGraph("Clicks");
+ graph.setAttribute("ui.stylesheet",
+ "node {\n" +
+ " fill-color: yellow;\n" +
+ " text-color: blue;\n" +
+ " text-size: 15;\n" +
+ " shape: box;\n" +
+// " size: 50px;\n" +
+ " size-mode: fit;\n" +
+ "}\n" +
+ "sprite.basicBlock {\n" +
+ " shape: rounded-box;\n" +
+ " stroke-mode: plain;\n" +
+ " stroke-color: #000000;\n" +
+ " fill-color: green;\n" +
+ " size-mode: fit;\n" +
+ " text-alignment: center;\n" +
+ "}");
+
+ Node a = graph.addNode("A");
+ a.setAttribute("ui.label", "Line1\nLine2\nLine3\nLine4\nLine5\nLine6\nLine7\nLine8\nLine9\nLine10\nLine11\nLine12\nLine13\nLine14\nLine15\nLine16\nLine17\nLine18\nLine19\nLine20\nLine21\nLine22\nLine23\nLine24\nLine25");
+ graph.addNode("B");
+ graph.addNode("C");
+ graph.addEdge("AB", "A", "B");
+ graph.addEdge("BC", "B", "C");
+ graph.addEdge("CA", "C", "A");
+
+ Viewer viewer = new SwingViewer(graph, Viewer.ThreadingModel.GRAPH_IN_GUI_THREAD);
+
+
+ ViewPanel viewPanel = (ViewPanel) viewer.addDefaultView(false);
+ viewer.getDefaultView().enableMouseOptions();
+ viewer.enableAutoLayout();
+
+ panel.add(viewPanel, BorderLayout.CENTER);
+// panel.add(codeArea, BorderLayout.SOUTH);
+ frame.pack();
+ frame.setLocationRelativeTo(null);
+ frame.setVisible(true);
+ frame.setModal(true);
+
+ ViewerPipe fromViewer = viewer.newViewerPipe();
+ fromViewer.addViewerListener(new MouseOptions());
+ fromViewer.addSink(graph);
+
+ while(loop) {
+ fromViewer.pump();
+ if (!frame.isVisible()) {
+ break;
+ }
+ }
+
+ }
+
+
+
+ public class MouseOptions implements ViewerListener {
+ public void viewClosed(String id) {
+
+ loop = false;
+ }
+
+ public void buttonPushed(String id) {
+// codeArea.setText((String) graph.getNode(id).getAttribute("ui.label"));
+// codeArea.setEditable(false);
+ }
+
+ public void buttonReleased(String id) {
+ System.out.println("Button released on node "+id);
+ }
+
+ public void mouseOver(String id) {
+ System.out.println("Need the Mouse Options to be activated");
+ }
+
+ public void mouseLeft(String id) {
+ System.out.println("Need the Mouse Options to be activated");
+ }
+ }
+}
diff --git a/src/org/graphstream/ui/swing/renderer/shape/swing/IconAndText.java b/src/org/graphstream/ui/swing/renderer/shape/swing/IconAndText.java
index 57a880f..49837b2 100644
--- a/src/org/graphstream/ui/swing/renderer/shape/swing/IconAndText.java
+++ b/src/org/graphstream/ui/swing/renderer/shape/swing/IconAndText.java
@@ -1,9 +1,9 @@
/*
* This file is part of GraphStream .
- *
+ *
* GraphStream is a library whose purpose is to handle static or dynamic
* graph, create them from scratch, file or any source and display them.
- *
+ *
* This program is free software distributed under the terms of two licenses, the
* CeCILL-C license that fits European law, and the GNU Lesser General Public
* License. You can use, modify and/ or redistribute the software under the terms
@@ -11,14 +11,14 @@
* URL or under the terms of the GNU LGPL as published by
* the Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
- *
+ *
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see .
- *
+ *
* The fact that you are presently reading this means that you have had
* knowledge of the CeCILL-C and LGPL licenses and that you accept their terms.
*/
@@ -28,7 +28,7 @@
* @author Guilhelm Savin
* @author Hicham Brahimi
*/
-
+
package org.graphstream.ui.swing.renderer.shape.swing;
import java.awt.Color;
@@ -40,6 +40,8 @@
import java.awt.geom.Rectangle2D;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
+import java.util.ArrayList;
+import java.util.List;
import org.graphstream.ui.graphicGraph.GraphicElement;
import org.graphstream.ui.graphicGraph.stylesheet.Style;
@@ -59,16 +61,16 @@ public abstract class IconAndText {
/** Overall height of the icon and text with all space and padding included. */
//protected double height;
/** Overall descent of the icon and text with all space and padding included. */
- protected double descent;
+ protected double descent;
/** Overall ascent of the icon and text with all space and padding included. */
protected double ascent ;
-
+
protected TextBox text;
protected double offx;
protected double offy;
protected double padx;
protected double pady;
-
+
public IconAndText(TextBox text, double offx, double offy, double padx, double pady) {
this.descent = text.getDescent() ;
this.ascent = text.getAscent();
@@ -78,7 +80,7 @@ public IconAndText(TextBox text, double offx, double offy, double padx, double p
this.padx = padx ;
this.pady = pady ;
}
-
+
public static IconAndText apply(Style style, DefaultCamera2D camera, GraphicElement element) {
BufferedImage icon = null ;
TextBox text = TextBox.apply(camera, style);
@@ -92,41 +94,40 @@ public static IconAndText apply(Style style, DefaultCamera2D camera, GraphicElem
double offy = padx;
if ( padd.size() > 1 )
offy = camera.getMetrics().lengthToPx(off, 1);
-
+
if( style.getIconMode() != IconMode.NONE ) {
String url = style.getIcon();
-
+
if( url.equals( "dynamic" ) ) {
if( element.hasLabel( "ui.icon" ) )
url = element.getLabel( "ui.icon" ).toString();
- else
+ else
url = null;
}
-
+
if( url != null ) {
icon = ImageCache.loadImage(url);
}
}
-
- if (icon == null) {
- return new IconAndTextOnlyText(text, offx, offy, padx, pady);
- }
- else {
- switch (style.getIconMode()) {
- case AT_LEFT:
- return new IconAtLeftAndText( icon, text, offx, offy, padx, pady );
- case AT_RIGHT:
- return new IconAtLeftAndText( icon, text, offx, offy, padx, pady );
- case ABOVE:
- return new IconAtLeftAndText( icon, text, offx, offy, padx, pady );
- case UNDER:
- return new IconAtLeftAndText( icon, text, offx, offy, padx, pady );
- default:
- throw new RuntimeException("???");
- }
- }
- }
-
+
+ if (icon == null) {
+ return new IconAndTextOnlyText(text, offx, offy, padx, pady);
+ } else {
+ switch (style.getIconMode()) {
+ case AT_LEFT:
+ return new IconAtLeftAndText(icon, text, offx, offy, padx, pady);
+ case AT_RIGHT:
+ return new IconAtLeftAndText(icon, text, offx, offy, padx, pady);
+ case ABOVE:
+ return new IconAtLeftAndText(icon, text, offx, offy, padx, pady);
+ case UNDER:
+ return new IconAtLeftAndText(icon, text, offx, offy, padx, pady);
+ default:
+ throw new RuntimeException("???");
+ }
+ }
+ }
+
public abstract void render(Backend backend, DefaultCamera2D camera, double xLeft, double yBottom) ;
public abstract void setIcon(Backend backend, String url) ;
public abstract void setText(Backend backend, String text);
@@ -139,72 +140,73 @@ class IconAndTextOnlyText extends IconAndText {
public IconAndTextOnlyText(TextBox text, double offx, double offy, double padx, double pady ) {
super(text, offx, offy, padx, pady);
}
-
+
public double getWidth() {
return text.getWidth()+padx*2;
}
-
+
public double getHeight() {
- return text.getAscent()+text.getDescent()+pady*2 ;
+ return text.getAscent()+text.getDescent()+text.getHeight()+pady*2 ;
}
-
+
public void setText(Backend backend, String text) {
this.text.setText(text, backend);
}
-
+
public String getText(Backend backend) {
return this.text.getText();
}
-
+
public void setIcon(Backend backend, String url) {}
-
+
public void render(Backend backend, DefaultCamera2D camera, double xLeft, double yBottom) {
- this.text.render(backend, offx+xLeft, offy+yBottom - descent);
+ this.text.render(backend, offx+xLeft,
+ offy+yBottom - this.getHeight() + this.text.getAscent());
}
}
class IconAtLeftAndText extends IconAndText {
private BufferedImage icon ;
-
+
public IconAtLeftAndText(BufferedImage icon, TextBox text, double offx, double offy, double padx, double pady ) {
super(text, offx, offy, padx, pady);
//this.width = text.getWidth() + icon.getWidth(null) + 5 + padx*2 ;
//this.height = Math.max(icon.getHeight(null), text.ascent + text.descent) + pady*2;
this.icon = icon ;
}
-
-
+
+
public void setText(Backend backend, String text) {
this.text.setText(text, backend);
}
-
+
public String getText(Backend backend) {
return this.text.getText();
}
-
+
public void setIcon(Backend backend, String url) {
ImageCache.loadImage(url);
if (icon == null) {
icon = ImageCache.dummyImage();
}
}
-
+
public void render(Backend backend, DefaultCamera2D camera, double xLeft, double yBottom) {
Graphics2D g = backend.graphics2D();
g.drawImage(icon, new AffineTransform(1f, 0f, 0f, 1f, offx+xLeft, offy+(yBottom-(getHeight()/2))-(icon.getHeight()/2)+pady), null);
double th = text.getAscent() + text.getDescent();
double dh = 0f ;
- if(icon.getHeight() > th)
+ if(icon.getHeight() > th)
dh = ((icon.getHeight() - th) / 2f) ;
-
+
this.text.render(backend, offx+xLeft + icon.getWidth() + 5, offy+yBottom - dh - descent);
}
-
+
public double getWidth() {
return text.getWidth() + icon.getWidth(null) + 5 + padx*2;
}
-
-
+
+
public double getHeight() {
return Math.max(icon.getHeight(null), text.getAscent() + text.getDescent()) + pady*2;
}
@@ -214,53 +216,53 @@ public double getHeight() {
abstract class TextBox {
/** The text string. */
String textData;
-
+
/** Renders the text at the given coordinates. */
public abstract void render(Backend backend, double xLeft, double yBottom);
/** Set the text string to paint. */
public abstract void setText(String text, Backend backend);
public abstract String getText();
-
+
public abstract double getWidth();
public abstract double getHeight();
public abstract double getDescent();
public abstract double getAscent();
-
+
/**
* Factory companion object for text boxes.
*/
static FontRenderContext defaultFontRenderContext = new FontRenderContext(new AffineTransform(), true, true);
-
+
public static TextBox apply(DefaultCamera2D camera, Style style) {
String fontName = style.getTextFont();
TextStyle fontStyle = style.getTextStyle();
Value fontSize = style.getTextSize();
Color textColor = ColorManager.getTextColor(style, 0);
Color bgColor = null;
- boolean rounded = false;
-
+ boolean rounded = false;
+
switch (style.getTextBackgroundMode()) {
case NONE: break;
- case PLAIN:
- rounded = false;
+ case PLAIN:
+ rounded = false;
bgColor = ColorManager.getTextBackgroundColor(style, 0);
break;
- case ROUNDEDBOX:
- rounded = true;
+ case ROUNDEDBOX:
+ rounded = true;
bgColor = ColorManager.getTextBackgroundColor(style, 0);
break;
default: break;
}
-
+
Values padding = style.getTextPadding();
double padx = camera.getMetrics().lengthToPx(padding, 0);
double pady = padx ;
if(padding.size() > 1)
camera.getMetrics().lengthToPx(padding, 1);
-
+
return TextBox.apply(fontName, fontStyle, (int)fontSize.value, textColor, bgColor, rounded, padx, pady);
}
-
+
public static TextBox apply(String fontName, TextStyle style, int fontSize, Color textColor, Color bgColor,
boolean rounded, double padx, double pady) {
return new SwingTextBox(FontCache.getFont( fontName, style, fontSize ), textColor, bgColor, rounded, padx, pady);
@@ -268,17 +270,17 @@ public static TextBox apply(String fontName, TextStyle style, int fontSize, Colo
}
class SwingTextBox extends TextBox {
-
+
Font font;
Color textColor;
Color bgColor;
boolean rounded;
double padx;
double pady;
-
- TextLayout text ;
+
+ List text;
Rectangle2D bounds ;
-
+
public SwingTextBox(Font font, Color textColor, Color bgColor, boolean rounded, double padx, double pady) {
this.font = font ;
this.textColor = textColor ;
@@ -286,13 +288,13 @@ public SwingTextBox(Font font, Color textColor, Color bgColor, boolean rounded,
this.rounded = rounded ;
this.padx = padx ;
this.pady = pady ;
-
+
this.text = null ;
this.textData = null ;
this.bounds = new Rectangle2D.Double(0, 0, 0, 0);
}
-
-
+
+
/** Changes the text and compute its bounds. This method tries to avoid recomputing bounds
* if the text does not really changed. */
public void setText(String text, Backend backend) {
@@ -302,9 +304,25 @@ public void setText(String text, Backend backend) {
// the identity transform, and as the FontRenderContext uses the current
// transform, we use a predefined default font render context initialized
// with an identity transform here.
- this.textData = text ;
- this.text = new TextLayout(text, font, TextBox.defaultFontRenderContext);
- this.bounds = this.text.getBounds();
+ this.text = new ArrayList<>();
+ String[] textLines = text.split("\n");
+ double maxWidth = 0;
+ double maxHeight = 0;
+ for (int i = 0; i < textLines.length; i++) {
+ if (textLines[i].length() == 0) {
+ this.text.add(new TextLayout("\b", font, TextBox.defaultFontRenderContext));
+ } else {
+ this.text.add(new TextLayout(textLines[i], font, TextBox.defaultFontRenderContext));
+ maxWidth = Math.max(this.text.get(i).getAdvance(), maxWidth);
+ }
+ maxHeight += this.text.get(i).getAscent()
+ + this.text.get(i).getDescent();
+ }
+ this.bounds = new Rectangle2D.Double(
+ this.text.get(0).getBounds().getX(),
+ this.text.get(0).getBounds().getY(),
+ maxWidth,
+ maxHeight);
}
else {
this.textData = null ;
@@ -313,58 +331,62 @@ public void setText(String text, Backend backend) {
}
}
}
-
+
@Override
public String getText() {
return textData;
}
-
+
public double getWidth() {
- if ( bounds != null )
+ if ( bounds != null )
return bounds.getWidth() ;
else
return 0 ;
}
-
+
public double getHeight() {
- if ( bounds != null )
+ if ( bounds != null )
return bounds.getHeight() ;
else
return 0 ;
}
-
+
public double getDescent() {
- if ( text != null )
- return text.getDescent() ;
+ if ( text != null )
+ return text.get(0).getDescent() ;
else
return 0 ;
}
-
+
public double getAscent() {
- if ( text != null )
- return text.getAscent() ;
+ if ( text != null )
+ return text.get(0).getAscent() ;
else
return 0 ;
}
public void render(Backend backend, double xLeft, double yBottom) {
-
+
if ( text != null ) {
Graphics2D g = backend.graphics2D();
-
+
if (bgColor != null) {
- double a = getAscent() ;
+ double a = getAscent();
double h = a + getDescent() ;
-
+
g.setColor(bgColor);
if(rounded) {
- g.fill(new RoundRectangle2D.Double(xLeft-padx, yBottom-(a+pady), getWidth()+1+(padx+padx), h+(pady+pady), 6, 6));
+ g.fill(new RoundRectangle2D.Double(xLeft-padx, yBottom-(a+pady), getWidth()+1+(padx+padx), h+(pady+pady), 6, 6));
} else {
g.fill(new Rectangle2D.Double(xLeft-padx, yBottom-(a+pady), getWidth()+1+(padx+padx), h+(pady+pady)));
}
}
g.setColor(textColor);
- text.draw(g, (float)xLeft, (float)yBottom);
+ for (int i = 0; i < text.size(); i++) {
+ text.get(i).draw(g, (float) xLeft,
+ (float) yBottom + i *
+ (text.get(i).getAscent() + text.get(i).getDescent()));
+ }
}
}
}