Make Icon Notification javafx - notifications

I would like to ask how is it possible to make a notification icon over an existing Node !
Here is a link I'm using as inspiration !
http://www.red-team-design.com/notification-bubble-css3-keyframe-animation
It would really save me if anyone could give me a help ^^

You can find an example here:
https://www.billmann.de/post/2012/08/05/javafx-miniiconanimationbutton/

I just solved The problem.
I've used the animation created by billman but not extending the StackPane this time, but by extending the Button Node, and I've set the Notification icon to be extending from the StackPane and it worked out perfectly !!
Here the way to do so:
AnimatedButton.java
import javafx.animation.Interpolator;
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.animation.TranslateTransition;
import javafx.scene.Node;
import javafx.scene.control.MenuItem;
import javafx.util.Duration;
public class Icons extends MenuItem {
private final Node icon;
private AnimationType type;
public Icons(String text, Node icon, AnimationType type) {
setText(text);
setGraphic(icon);
this.icon = icon;
this.type = type;
addAnimation();
}
private void addBlinkAnimation() {
final Timeline timeline = new Timeline();
timeline.setCycleCount(Timeline.INDEFINITE);
timeline.setAutoReverse(true);
final KeyValue kv = new KeyValue(icon.opacityProperty(), 0.0);
final KeyFrame kf = new KeyFrame(Duration.millis(700), kv);
timeline.getKeyFrames().add(kf);
timeline.play();
}
private void addJumpAnimation() {
final TranslateTransition translateTransition = new TranslateTransition(Duration.millis(200), icon);
final double start = 0.0;
final double end = start - 4.0;
translateTransition.setFromY(start);
translateTransition.setToY(end);
translateTransition.setCycleCount(-1);
translateTransition.setAutoReverse(true);
translateTransition.setInterpolator(Interpolator.EASE_BOTH);
translateTransition.play();
}
public enum AnimationType {
BLINK, JUMP, NONE;
};
private void addAnimation() {
switch (type) {
case BLINK:
addBlinkAnimation();
break;
case JUMP:
addJumpAnimation();
break;
case NONE:
break;
default:
break;
}
}
}
here's the main.java
import javafx.application.Application;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.MenuButton;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;
public class Main extends Application {
#Override
public void start(Stage primaryStage) {
MenuButton menu = new MenuButton("Bienvenue, Yassine", new ImageView(new Image("http://cdn1.iconfinder.com/data/icons/fs-icons-ubuntu-by-franksouza-/32/google-chrome.png", 20, 20, true, true)));
menu.setCenterShape(true);
Icons btn = new Icons("Notification", createNotification("5"), Icons.AnimationType.JUMP);
Icons btn2 = new Icons("Mails", createNotification("4"), Icons.AnimationType.JUMP);
Icons btn3 = new Icons("Private Messages", createNotification("10"), Icons.AnimationType.JUMP);
menu.getItems().addAll(btn, btn2, btn3);
StackPane root = new StackPane();
Scene scene = new Scene(root, 300, 250);
scene.getStylesheets().add(getClass().getResource("notification_icon.css").toExternalForm());
root.getChildren().add(menu);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
private Node createNotification(String number) {
StackPane p = new StackPane();
Label lab = new Label(number);
lab.setStyle("-fx-text-fill:white");
Circle cercle = new Circle(10, Color.rgb(200, 0, 0, .9));
cercle.setStrokeWidth(2.0);
cercle.setStyle("-fx-background-insets: 0 0 -1 0, 0, 1, 2;");
cercle.setSmooth(true);
p.getChildren().addAll(cercle, lab);
return p;
}
}
and the css
.label{
-fx-font-size: 12;
-fx-font-weight: bold;
-fx-text-fill: black;
-fx-padding:5;
}

Related

Dynamically updating Polyline points in tornadofx

This question is a bit simplistic, but i couldn't figure it out for myself... What I'm trying to do is using a JavaFX Timeline to update my Polyline points. What I've got until now is as follows:
class MainView : View("Hello TornadoFX") {
var myLine: Polyline by singleAssign()
val myTimeline = timeline {
cycleCount = INDEFINITE
}
override val root = hbox {
myLine = polyline(0.0, 0.0, 100.0, 100.0)
myTimeline.apply {
keyFrames += KeyFrame((1/10.0).seconds, {
myLine.points.forEachIndexed { i, d ->
myLine.points[i] = d + 1
}
println(myLine.points)
})
play()
}
}
}
Although the point list does update the values, as shown when printing them, the change is not reflected in the ui.
Thank you very much for your help!
I have not worked with TornadoFX earlier, so I gave a try with the normal JavaFX. Looks like the the UI is updating when the points are updated. May be the issue is something related to your implementation with TornadoFX.
Please check below the working example.
import javafx.animation.Animation;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.shape.Polyline;
import javafx.stage.Stage;
import javafx.util.Duration;
public class PolyLinePointsUpdateDemo extends Application {
#Override
public void start(Stage primaryStage) throws Exception {
Pane root = new Pane();
Scene scene = new Scene(root, 600,600);
primaryStage.setScene(scene);
primaryStage.setTitle("PolyLine Points Update");
primaryStage.show();
Polyline line = new Polyline(0.0, 0.0, 100.0, 100.0);
root.getChildren().add(line);
Timeline timeline = new Timeline();
timeline.getKeyFrames().add(new KeyFrame(Duration.millis(250), e->{
for (int i = 0; i < line.getPoints().size(); i++) {
double d = line.getPoints().get(i);
line.getPoints().set(i, d+1);
}
System.out.println(line.getPoints());
}));
timeline.setCycleCount(Animation.INDEFINITE);
timeline.play();
}
public static void main(String... a){
Application.launch(a);
}
}
Figured out that the issue was simply using an hbox as the parent layout, instead of a pane, which handles the chidren positioning with absolute coordinates.

Java OOP using Translate Transition and JavaFX

The Translate Transition does not output. It uses a method in the main class. I believe it is not working because it is used as an object. There has to be a different code to implement. It uses a method in a main and then puts it into a tester. However, I do not know how to use it because it uses a constructor/object as well. Then, the object turns and changes into a node which I changed it. I do not know how the Translate Transition method is attached to the object and displays it into the javafx console. Please help solve the problem for positive feedback as it shows.
import javafx.animation.TranslateTransition;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Shape;
import javafx.util.Duration;
public class AnxiousShapes {
private Shape shape;
private double delay ;
private int howFarToMoveX;
private int howFarToMoveY;
public AnxiousShapes(int type, int x, int y, int size, double delay, Color color, int hftmX, int hftmY) {
if (type == 0) {shape = new Circle(x, y, size, color);}
//these are the only lines you can change
//in this main class
//else if (type == 1){shape = new Rectangle(x,y,color);}
//else if (type == 2){shape = new Polygon();}
//else if (type == 3) {shape = new Circle(x, y, size, color);}
//else { System.out.println("Error in type");shape = new
//Circle(???????);}
this.delay = delay;
this.howFarToMoveX = hftmX;
this.howFarToMoveY = hftmY;
}
// getter and setters
public TranslateTransition calculateTt() {
TranslateTransition tt = new TranslateTransition(Duration.seconds(this.delay), this.shape);
tt.setToX(this.shape.getLayoutX() + howFarToMoveX);
tt.setToY(shape.getLayoutY() + howFarToMoveY);
// Let the animation run forever -- if the shape
// tries to move "off-screen" it will return to the beginning
tt.setCycleCount(TranslateTransition.INDEFINITE);
return tt;
}
#Override
public String toString() {
return "AnxiousShape [shape=" + shape + ", delay=" + delay + ", howFarToMoveX=" + howFarToMoveX
+ ", howFarToMoveY=" + howFarToMoveY + "]";
}
}
import javafx.animation.TranslateTransition;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;
import javafx.util.Duration;
import javafx.scene.Group;
import javafx.scene.Node;
import java.util.Random;
public class AnxiousShapesTester extends Application {
#Override
public void start(Stage stage) {
// adding the new things
Group root = new Group();
stage.setTitle("Welcome to JavaFX!");
// create the shape circle
AnxiousShapes circle1 = new AnxiousShapes(0, 200, 200, 50, 15,
Color.GREEN, 10 ,35);
root.getChildren().add(circle1.getShape());
// this does not work
// TranslateTransition trans = circle1.calculateTt();
// trans.setNode(root);
// trans.play();
// and I tried this and I already have the movement in constructor for
// delay and x and y but TranslateTransition
// asks for duration.millis(500)
TranslateTransition tt = new
TranslateTransition(Duration.millis(500), root);
tt.play();
Scene scene = new Scene(root, 600, 600, Color.WHITE);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
Application.launch(args);
}
}
In a comment, you say, "this does not work." The problem is trans.setNode(root), which attempts to make root "The target node of this TranslateTransition." Your implementation of calculateTt() already specifies this.shape as the target node. Instead, add a suitable accessor to AnxiousShapes and use the transition as constructed; the following changes are illustrated below:
public Shape getShape() { return this.shape; }
…
AnxiousShapes circle1 = new AnxiousShapes(0, 100, 100, 100, 3, Color.GREEN, 400, 400);
root.getChildren().add(circle1.getShape());
TranslateTransition trans = circle1.calculateTt();
trans.play();

apache poi ppt to png emf

I would like to ask about library APACHE POI. I have a .pptx file and with the example which I found on internet I split each slide into separate images. This works great when slide containts .png, .jpeg images but as soon as I have .emf files in slide this image disappear. So I want to have the same copy of slide but with .emf file as well. Is this possible?
version: Apache POI 3.12
Thanks a lot
As mentioned in the comments, EMF is not supported out of the box ... and as FreeHep decided to have a LGPL license it's unlikely that we will include in our release.
In POI you basically have two options to provide a custom image renderer:
implement and register your ImageRenderer implementation in the Graphics2D context via setRenderingHint(Drawable.IMAGE_RENDERER, new MyImageRendener()). The drawback is, that it will be called for any images and you loose the default handling for bitmap/wmf images
or provide a custom DrawFactory which serves your own DrawPictureShape implementation - as in the example below - which only diverts to the EMF renderer when necessary
(looking at this example, the current POI ImageRenderer handling doesn't look flexible and instead of having a global handler, it might be better to register a handler per content-type ...)
Apart of the usual POI component I've included freehep-graphics2d, freehep-graphicsbase, freehep-graphicsio, freehep-graphicsio-emf and freehep-io.
The example is far from being finished, but I guess you get at least a kick-start:
package org.apache.poi.xslf;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import javax.imageio.ImageIO;
import org.apache.poi.sl.draw.DrawFactory;
import org.apache.poi.sl.draw.DrawPictureShape;
import org.apache.poi.sl.draw.Drawable;
import org.apache.poi.sl.draw.ImageRenderer;
import org.apache.poi.sl.usermodel.PictureData;
import org.apache.poi.sl.usermodel.PictureData.PictureType;
import org.apache.poi.sl.usermodel.PictureShape;
import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;
import org.apache.poi.xslf.usermodel.XMLSlideShow;
import org.apache.poi.xslf.usermodel.XSLFPictureShape;
import org.apache.poi.xslf.usermodel.XSLFSlide;
import org.freehep.graphicsio.emf.EMFInputStream;
import org.freehep.graphicsio.emf.EMFRenderer;
import org.junit.Test;
public class TestEMFRender {
private final static POILogger LOG = POILogFactory.getLogger(TestEMFRender.class);
#Test
public void render() throws Exception {
XMLSlideShow ppt = getDummy();
Dimension pgsize = ppt.getPageSize();
BufferedImage img = new BufferedImage((int)pgsize.getWidth(), (int)pgsize.getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics2D graphics = initGraphicsCtx(img);
// draw stuff
ppt.getSlides().get(0).draw(graphics);
// save the result
File outfile = new File("bla.png");
ImageIO.write(img, "PNG", outfile);
// cleanup
graphics.dispose();
img.flush();
ppt.close();
}
static XMLSlideShow getDummy() throws IOException {
XMLSlideShow ppt = new XMLSlideShow();
FileInputStream fis = new FileInputStream("kiwilogo.emf");
PictureData pd = ppt.addPicture(fis, PictureType.EMF);
fis.close();
XSLFSlide sl = ppt.createSlide();
XSLFPictureShape ps = sl.createPicture(pd);
ps.setAnchor(new Rectangle2D.Double(100, 100, 100, 100));
return ppt;
}
static Graphics2D initGraphicsCtx(BufferedImage img) {
Graphics2D graphics = img.createGraphics();
// default rendering options
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
graphics.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
graphics.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
// custom draw factory
DrawFactory df = new DrawFactory(){
public DrawPictureShape getDrawable(PictureShape<?,?> shape) {
return new DrawPictureShapeEmf(shape);
}
};
graphics.setRenderingHint(Drawable.DRAW_FACTORY, df);
df.fixFonts(graphics);
return graphics;
}
static class DrawPictureShapeEmf extends DrawPictureShape {
public DrawPictureShapeEmf(PictureShape<?,?> shape) {
super(shape);
}
#Override
public void drawContent(Graphics2D graphics) {
PictureData data = getShape().getPictureData();
if(data == null) return;
Rectangle2D anchor = getAnchor(graphics, getShape());
Insets insets = getShape().getClipping();
try {
String contentType = data.getContentType();
ImageRenderer renderer =
PictureType.EMF.contentType.equals(contentType)
? new ImgRenderer()
: super.getImageRenderer(graphics, contentType);
renderer.loadImage(data.getData(), data.getContentType());
renderer.drawImage(graphics, anchor, insets);
} catch (IOException e) {
LOG.log(POILogger.ERROR, "image can't be loaded/rendered.", e);
}
}
}
static class ImgRenderer implements ImageRenderer {
EMFRenderer emfRenderer;
public void loadImage(InputStream data, String contentType) throws IOException {
emfRenderer = new EMFRenderer(new EMFInputStream(data));
}
public void loadImage(byte[] data, String contentType) throws IOException {
loadImage(new ByteArrayInputStream(data), contentType);
}
public Dimension getDimension() {
return emfRenderer.getSize();
}
public void setAlpha(double alpha) {
}
public BufferedImage getImage() {
return null;
}
public BufferedImage getImage(Dimension dim) {
return null;
}
public boolean drawImage(Graphics2D ctx, Rectangle2D graphicsBounds) {
return drawImage(ctx, graphicsBounds, null);
}
public boolean drawImage(Graphics2D ctx, Rectangle2D graphicsBounds, Insets clip) {
AffineTransform at = ctx.getTransform();
try {
Dimension emfDim = emfRenderer.getSize();
// scale output bounds to image bounds
ctx.translate(graphicsBounds.getX(), graphicsBounds.getY());
ctx.scale(graphicsBounds.getWidth()/emfDim.getWidth(), graphicsBounds.getHeight()/emfDim.getHeight());
// TODO: handle clipping
emfRenderer.paint(ctx);
return true;
} catch (RuntimeException e) {
// TODO: logging
return false;
} finally {
ctx.setTransform(at);
}
}
}
}

Cannot successfully add item to beginning of CategoryAxis series for a JavaFX BarChart

I've attempted to implement drag-left and drag-right functionality for a JavaFX BarChart. The drag-left functionality works correct where I add an item at the end of the x-axis data series and remove an item at the beginning.
However, the drag-right functionality does not work as expected. It's supposed to add an item at the beginning of the x-axis series and remove an item at the end. The removal works correctly, but the add operation results in the item being added to the end of the BarChart instead of the beginning.
I suspect it has to do with the use of a CategoryAxis that does not recognize the need to update the BarChart from the ObservableList in a sorted manner (even though I can see that the item gets added to the beginning of the underlying ObservableList).
Also, please let me know if there is a better way of implementing the drag operation.
Below is a full application to reproduce the problem.
import java.text.SimpleDateFormat;
import java.util.Date;
import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.scene.Scene;
import javafx.scene.chart.BarChart;
import javafx.scene.chart.CategoryAxis;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class BarchartProblem extends Application {
private static SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
private double dragStartX = 0;
private long minTime;
private long maxTime;
#FXML
private BarChart<String,Number> histogramBarChart;
#Override
public void start(Stage primaryStage) {
final CategoryAxis xAxis = new CategoryAxis();
final NumberAxis yAxis = new NumberAxis();
xAxis.setLabel("Time");
yAxis.setLabel("Entries");
histogramBarChart = new BarChart<String, Number>(xAxis, yAxis);
final XYChart.Series series1 = new XYChart.Series();
histogramBarChart.setLegendVisible(false);
histogramBarChart.getData().addAll(series1);
histogramBarChart.setOnMousePressed(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent mouseEvent) {
System.out.println(mouseEvent);
dragStartX = mouseEvent.getX();
}
});
histogramBarChart.setOnMouseDragged(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent mouseEvent) {
if (dragStartX > mouseEvent.getX()) {
XYChart.Series series = histogramBarChart.getData().get(0);
minTime += 60000;
maxTime += 60000;
series.getData().add(new XYChart.Data(dateFormat.format(new Date(maxTime)), 0));
series.getData().remove(0);
System.out.println("Drag Left");
} else if (dragStartX < mouseEvent.getX()) {
XYChart.Series series = histogramBarChart.getData().get(0);
minTime -= 60000;
maxTime -= 60000;
series.getData().add(0, new XYChart.Data(dateFormat.format(new Date(minTime)), 0));
series.getData().remove(series.getData().size()-1);
System.out.println("Drag Right");
}
}
});
final long currentTime = System.currentTimeMillis();
minTime = currentTime-60000*30;
maxTime = currentTime;
for (long i = minTime; i <= maxTime; i += 60000) {
series1.getData().add(new XYChart.Data(dateFormat.format(new Date(i)), Math.random()*500));
}
StackPane root = new StackPane();
root.getChildren().add(histogramBarChart);
Scene scene = new Scene(root, 300, 250);
primaryStage.setTitle("BarChart Problem");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}

How to build a custom draw2d layoutmanager?

I would like to have a layout manager that can arrange two elements as follows:
one main element ABCDEF centered
one "postscript" element XYZ, positioned on the top right corner of the encapsulating figure
For example:
***********XYZ*
* ABCDEF *
***************
Can I use an existing layoutmanager for this? How do I build a custom layout manager that supports it?
Many thanks for your advice.
You can do that by using XYLayout.
There is a sample you can build on:
import org.eclipse.draw2d.AbstractLayout;
import org.eclipse.draw2d.Figure;
import org.eclipse.draw2d.FigureCanvas;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.Label;
import org.eclipse.draw2d.LayoutManager;
import org.eclipse.draw2d.LineBorder;
import org.eclipse.draw2d.Panel;
import org.eclipse.draw2d.XYLayout;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Insets;
import org.eclipse.draw2d.geometry.PrecisionRectangle;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
public class HHH {
public static void main(String[] args) {
Display d = new Display();
Shell s = new Shell();
s.setLayout(new FillLayout());
FigureCanvas canvas = new FigureCanvas(s);
Figure content = new Figure();
content.setLayoutManager(new XYLayout());
PostScriptedFigure figure = new PostScriptedFigure();
content.add(figure, new Rectangle(100, 100, -1, -1));
figure.setMainFigure(new Label("The Main figure"));
figure.setPostScriptFigure(new Label("ps"));
figure.setBorder(new LineBorder());
canvas.setContents(content);
s.setSize(600, 500);
s.open();
while (!s.isDisposed()) {
if (!d.readAndDispatch()) {
d.sleep();
}
}
}
}
class PostScriptedFigure extends Panel {
private IFigure mainFigure, postScriptFigure;
private class PostScriptedLayoutManager extends AbstractLayout {
#Override
public void layout(IFigure container) {
final Rectangle clientArea = container.getClientArea();
final IFigure mainFigure = getMainFigure();
final IFigure postScriptFigure = getPostScriptFigure();
if (mainFigure != null) {
final Rectangle bounds = new PrecisionRectangle();
bounds.setSize(mainFigure.getPreferredSize(SWT.DEFAULT, SWT.DEFAULT));
final Rectangle mainClientArea = clientArea.getCopy();
if (postScriptFigure != null) {
mainClientArea.shrink(new Insets(postScriptFigure.getPreferredSize().height(), 0, 0, 0));
}
bounds.translate(mainClientArea.getCenter().getTranslated(bounds.getSize().getScaled(0.5f).getNegated()));
mainFigure.setBounds(bounds);
}
if (postScriptFigure != null) {
final Rectangle bounds = new PrecisionRectangle();
bounds.setSize(postScriptFigure.getPreferredSize(SWT.DEFAULT, SWT.DEFAULT));
bounds.translate(clientArea.getTopRight().getTranslated(bounds.getSize().getNegated().width(), 0));
postScriptFigure.setBounds(bounds);
}
// note that other potentionally added figures are ignored
}
#Override
protected Dimension calculatePreferredSize(IFigure container, int wHint, int hHint) {
final Rectangle rect = new PrecisionRectangle();
final IFigure mainFigure = getMainFigure();
if (mainFigure != null) {
rect.setSize(mainFigure.getPreferredSize());
}
final IFigure postScriptFigure = getPostScriptFigure();
if (postScriptFigure != null) {
rect.resize(mainFigure != null ? 0 : postScriptFigure.getPreferredSize().width() , postScriptFigure.getPreferredSize().height());
}
// note that other potentionally added figures are ignored
final Dimension d = rect.getSize();
final Insets insets = container.getInsets();
return new Dimension(d.width + insets.getWidth(), d.height + insets.getHeight()).union(getBorderPreferredSize(container));
}
}
public PostScriptedFigure() {
super.setLayoutManager(new PostScriptedLayoutManager());
}
#Override
public void setLayoutManager(LayoutManager manager) {
// prevent from setting wrong layout manager
}
public IFigure getMainFigure() {
return mainFigure;
}
public void setMainFigure(IFigure mainFigure) {
if (getMainFigure() != null) {
remove(getMainFigure());
}
this.mainFigure = mainFigure;
add(mainFigure);
}
public IFigure getPostScriptFigure() {
return postScriptFigure;
}
public void setPostScriptFigure(IFigure postScriptFigure) {
if (getPostScriptFigure() != null) {
remove(getPostScriptFigure());
}
this.postScriptFigure = postScriptFigure;
add(postScriptFigure);
}
}