Commit 028d0748 authored by Nico Mack's avatar Nico Mack

Added WordCloud corona

parent 5f52d736
......@@ -25,6 +25,7 @@ CENTRE_NODE=centre
CENTRED_NODE=centred
CIRCLE_SIZE_NODE=circleSize
COLOUR_NODE=colour
COLOUR_PALETTE_NODE=colourPalette
COLOURSC_NODE=colourscheme
CONDITION_NODE=condition
CONDITION_BUILDER_NAMESPACE=lu.list.itis.dkd.tui.event.conditional.builder
......@@ -68,6 +69,7 @@ FADE_IN_TIME_NODE=fadeInTime
FADE_OUT_TIME_NODE=fadeOutTime
FADE_WITH_HANDLE_NODE=fadeWithHandle
FADING_ENABLED_NODE=fadingEnabled
FILE_ATTRIBUTE=file
FILL_COLOUR_ELEMENT=fillColour
FILL_COLOUR_NODE=fillColour
FILL_COLOUR_NUANCE_NODE=fillColourNuance
......@@ -217,12 +219,15 @@ TRIGGER_ELEMENT=trigger
TRIGGERS_NODE=triggers
TULIP_NAMESPACE=lu.list.itis.dkd.tui
TYPE_NODE=type
TYPE_ATTRIBUTE=type
UNIT_NODE=unit
UPPER_BOUND_NODE=upperBound
VERSION_NODE=version
VOLUME_NODE=volume
WIDGET_BUILDER_NAMESPACE=lu.list.itis.dkd.tui.widget.builder
WIDTH_NODE=width
WORD_FREQUENCIES_NODE=wordFrequencies
WORD_LENGTH_NODE=wordLength
X_NODE=x
Y_NODE=y
Z_NODE=z
......
......@@ -201,6 +201,11 @@
<artifactId>filters</artifactId>
<version>2.0.235-1</version>
</dependency>
<dependency>
<groupId>com.kennycason</groupId>
<artifactId>kumo-core</artifactId>
<version>1.17</version>
</dependency>
</dependencies>
<repositories>
......
......@@ -451,6 +451,44 @@ public class BootstrappingUtils {
throw (exception);
}
// ---------------------------------------------------------------------------
/**
*
* @param rootElement
* @param childName
* @param optional
* @return
* @throws BuildException
*/
// ---------------------------------------------------------------------------
public static Element getChild(Element rootElement, String childName, boolean optional) throws BuildException {
Element child = rootElement.getChild(childName);
if (!optional && child == null) {
logAndThrowBuildException(new BuildException(StringUtils.build(MANDATORY_NODE_TEMPLATE, childName)), rootElement, childName);
}
return child;
}
// ---------------------------------------------------------------------------
/**
*
* @param rootElement
* @param childName
* @param optional
* @return
* @throws BuildException
*/
// ---------------------------------------------------------------------------
public static List<Element> getChildren(Element rootElement, String childName, boolean optional) throws BuildException {
List<Element> children = rootElement.getChildren(childName);
if (!optional && ((children == null) || children.isEmpty())) {
logAndThrowBuildException(new BuildException(StringUtils.build(MANDATORY_NODE_TEMPLATE, childName)), rootElement, childName);
}
return children;
}
// ---------------------------------------------------------------------------
/**
* returns the content of a child node as a string
......
......@@ -60,6 +60,7 @@ public class Externalization extends NLS {
public static String CENTRED_NODE;
public static String CIRCLE_SIZE_NODE;
public static String COLOUR_NODE;
public static String COLOUR_PALETTE_NODE;
public static String COLOURSC_NODE;
public static String CONDITION_NODE;
public static String CONDITION_BUILDER_NAMESPACE;
......@@ -103,6 +104,7 @@ public class Externalization extends NLS {
public static String FADE_OUT_TIME_NODE;
public static String FADE_WITH_HANDLE_NODE;
public static String FADING_ENABLED_NODE;
public static String FILE_ATTRIBUTE;
public static String FILL_COLOUR_ELEMENT;
public static String FILL_COLOUR_NODE;
public static String FILL_COLOUR_NUANCE_NODE;
......@@ -252,12 +254,15 @@ public class Externalization extends NLS {
public static String TRIGGERS_NODE;
public static String TULIP_NAMESPACE;
public static String TYPE_NODE;
public static String TYPE_ATTRIBUTE;
public static String UNIT_NODE;
public static String UPPER_BOUND_NODE;
public static String VERSION_NODE;
public static String VOLUME_NODE;
public static String WIDGET_BUILDER_NAMESPACE;
public static String WIDTH_NODE;
public static String WORD_FREQUENCIES_NODE;
public static String WORD_LENGTH_NODE;
public static String X_NODE;
public static String Y_NODE;
public static String Z_NODE;
......
/**
* Copyright Luxembourg Institute of Science and Technology, 2018. All rights reserved.
*
* This file is part of TULIP.
*
* TULIP is free software: you can redistribute it and/or modify it under the terms of the GNU
* Lesser General Public License as published by the Free Software Foundation, version 3 of the
* License.
*
* TULIP 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 TULIP. If
* not, see <http://www.gnu.org/licenses/lgpl-3.0.html>.
*/
package lu.list.itis.dkd.tui.widget.corona;
import lu.list.itis.dkd.tui.content.InformationReceiver;
import lu.list.itis.dkd.tui.utility.Point;
import lu.list.itis.dkd.tui.utility.ScreenCoordinates;
import lu.list.itis.dkd.tui.widget.corona.builder.BaseWordCloudBuilder;
import lu.list.itis.dkd.tui.widget.corona.builder.ImageBuilder;
import com.kennycason.kumo.CollisionMode;
import com.kennycason.kumo.WordFrequency;
import com.kennycason.kumo.bg.Background;
import com.kennycason.kumo.collide.Collidable;
import com.kennycason.kumo.font.scale.FontScalar;
import com.kennycason.kumo.nlp.FrequencyAnalyzer;
import com.kennycason.kumo.palette.ColorPalette;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
/**
* @author Nico Mack [nico.mack@list.lu]
* @since 2.5.0
* @version 1.0
*/
// ***************************************************************************
// * Class Definition and Members *
// ***************************************************************************
public class WordCloud extends Corona implements InformationReceiver<String> {
protected String textContent;
protected int width;
protected int height;
protected FrequencyAnalyzer analyzer;
protected ColorPalette palette;
protected FontScalar scaler;
protected com.kennycason.kumo.WordCloud cloud;
private Point cloudCentre;
// ***************************************************************************
// * Constants
// ***************************************************************************
private static final Color TRANSPARENT = new Color(0, 0, 0, 0);
private static final Logger LOGGER = LoggerFactory.getLogger(WordCloud.class.getSimpleName());
// ---------------------------------------------------------------------------
// ***************************************************************************
// * Inner Class *
// ***************************************************************************
// ---------------------------------------------------------------------------
private class ShapeBackground implements Background {
private Shape background;
public ShapeBackground(Shape shape) {
this.background = shape;
}
/** {@inheritDoc} */
@Override
public boolean isInBounds(Collidable collidable) {
final java.awt.Point position = collidable.getPosition();
return this.background.contains(position);
}
}
// ---------------------------------------------------------------------------
// ***************************************************************************
// * Constructor(s) *
// ***************************************************************************
// ---------------------------------------------------------------------------
/**
* Constructor building all fields and calling the implicit super constructor using a
* {@link ImageBuilder} instance holding all values.
*
* @param builder
* The {@link ImageBuilder} instance holding all values.
*/
// ---------------------------------------------------------------------------
public WordCloud(BaseWordCloudBuilder<?> builder) {
super(builder);
this.textContent = builder.textContent;
this.width = builder.width;
this.height = builder.height;
this.analyzer = builder.analyzer;
this.palette = builder.palette;
this.scaler = builder.scaler;
this.buildFromProperties();
this.setInformation(this.textContent);
}
// ---------------------------------------------------------------------------
/**
* @param original
*/
// ---------------------------------------------------------------------------
public WordCloud(WordCloud original) {
super(original);
this.textContent = original.textContent;
this.width = original.width;
this.height = original.height;
this.analyzer = original.analyzer;
this.palette = original.palette;
this.scaler = original.scaler;
this.buildFromProperties();
this.setInformation(this.textContent);
}
// ---------------------------------------------------------------------------
// ***************************************************************************
// * Primitive(s) *
// ***************************************************************************
// ---------------------------------------------------------------------------
private void buildFromProperties() {
if ((this.width <= 0) || (this.height <= 0)) {
Rectangle2D bounds = this.shape.getBounds2D();
this.width = (int) bounds.getWidth();
this.height = (int) bounds.getHeight();
}
this.cloud = new com.kennycason.kumo.WordCloud(new Dimension(this.width, this.height), CollisionMode.PIXEL_PERFECT);
this.cloud.setBackgroundColor(TRANSPARENT);
this.cloud.setBackground(new ShapeBackground(this.shape));
this.cloud.setColorPalette(this.palette);
this.cloud.setFontScalar(this.scaler);
}
// ---------------------------------------------------------------------------
private void renderInformation(String information) {
List<WordFrequency> frequencies = null;
this.textContent = information;
try (InputStream input = IOUtils.toInputStream(information)) {
frequencies = this.analyzer.load(input);
} catch (IOException e) {
LOGGER.error("Failed to read information!", e); //$NON-NLS-1$
}
this.cloud.build(frequencies);
BufferedImage image = this.cloud.getBufferedImage();
this.cloudCentre = (image != null) ? new Point(image.getWidth(null) / 2, image.getHeight(null) / 2, 0, ScreenCoordinates.class)
: new Point();
}
// ---------------------------------------------------------------------------
// ***************************************************************************
// * Class Body *
// ***************************************************************************
// ---------------------------------------------------------------------------
/** {@inheritDoc} */
@Override
public void paint(Graphics2D canvas) {
if (!active) {
return;
}
AffineTransform transform = this.getTransform(this.cloudCentre);
canvas.drawImage(this.cloud.getBufferedImage(), transform, null);
}
// ---------------------------------------------------------------------------
/** {@inheritDoc} */
// ---------------------------------------------------------------------------
@Override
public WordCloud clone() {
return new WordCloud(this);
}
// ---------------------------------------------------------------------------
/** {@inheritDoc} */
// ---------------------------------------------------------------------------
@Override
public void setInformation(String information) {
this.renderInformation(information);
}
// ---------------------------------------------------------------------------
// ***************************************************************************
// * End of Class *
// ***************************************************************************
// ---------------------------------------------------------------------------
}
/**
* Copyright Luxembourg Institute of Science and Technology, 2016.
*
* This file is part of TULIP.
*
* TULIP is licensed under a dual-licensing scheme. For non-commercial purposes, the LGPL version 3,
* as stated below, is applicable. For all commercial purposes TULIP is licensed under a LIST
* proprietary license. Please contact LIST at tto@list.lu to obtain a commercial license.
*
* For all non-commercial purposes, TULIP is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the Free Software
* Foundation, version 3 of the License.
*
* TULIP 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 TULIP. If
* not, see <http://www.gnu.org/licenses/lgpl-3.0.html>.
*/
package lu.list.itis.dkd.tui.widget.corona.builder;
import lu.list.itis.dkd.dbc.annotation.NonNullByDefault;
import lu.list.itis.dkd.tui.bootstrapping.BootstrapCallback;
import lu.list.itis.dkd.tui.bootstrapping.BootstrapContext;
import lu.list.itis.dkd.tui.exception.BuildException;
import lu.list.itis.dkd.tui.utility.Point;
import lu.list.itis.dkd.tui.widget.corona.Image;
import lu.list.itis.dkd.tui.widget.corona.WordCloud;
import org.jdom2.Element;
/**
* {@link WordCloudBuilder} class used to construct an {@link Image} corona by providing methods to
* set all parameters and permutations thereof.
*
* @author Eric Tobias [eric.tobias@list.lu]
* @since 1.0
* @version 2.3.0
*/
@NonNullByDefault
public final class WordCloudBuilder extends BaseWordCloudBuilder<WordCloudBuilder> {
/**
* Constructor setting the centre of the corona.
*
* @param centre
* The centre of the corona, usually the centre of the handle.
*/
public WordCloudBuilder(Point centre) {
super(centre);
}
/**
* Constructor initializing the centre of the corona as well as a possible image and information
* provider as given by the children of a provided element.
*
* @param rootElement
* The element harbouring, on child nodes, the necessary information to initialize all fields
* of the builder.
* @throws BuildException
* Exception raised when the building of a corona instance cannot complete successfully due
* to the violation of one or more contracts associated with the instance, including
* missing, incomplete, or erroneous parameters or values thereof.
*/
public WordCloudBuilder(Element rootElement) throws BuildException {
super(rootElement);
}
/**
* Constructor initializing the centre of the corona as well as a possible image and information
* provider as given by the children of a provided element.
*
* @param rootElement
* The element harbouring, on child nodes, the necessary information to initialize all fields
* of the builder.
* @param context
* @param callback
* @throws BuildException
* Exception raised when the building of a corona instance cannot complete successfully due
* to the violation of one or more contracts associated with the instance, including
* missing, incomplete, or erroneous parameters or values thereof.
*/
public WordCloudBuilder(Element rootElement, BootstrapContext context, BootstrapCallback callback) throws BuildException {
super(rootElement, context, callback);
}
/** {@inheritDoc} */
@Override
public WordCloud build() {
return new WordCloud(this);
}
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment