Commit 9e547ed6 authored by Nico Mack's avatar Nico Mack

Added Splashscreen and onscreen logging

parent 04998dd6
......@@ -130,3 +130,8 @@ COUNT_ATTRIBUTE=count
SHADE_ATTRIBUTE=shade
SHADE_DARKER_VALUE=darker
SHADE_BRIGHTER_VALUE=brighter
MARKER_NODE=marker
MARKERS_NODE=markers
MARKER_BUILDER_NAMESPACE=lu.list.itis.dkd.tui.marker.builder
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<Configuration status="WARN" packages="lu.list.itis.dkd.tui.logging">
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
</Console>
<OnScreenLog name="SplashScreen" size="1000">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
</OnScreenLog>
</Appenders>
<Loggers>
<Root level="error">
<AppenderRef ref="Console"/>
<AppenderRef ref="SplashScreen"/>
</Root>
<Logger name="lu.list.itis.dkd.tui" level="info"/>
</Loggers>
......
......@@ -30,7 +30,7 @@
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugin>
</plugins>
</build>
<dependencies>
......@@ -95,7 +95,6 @@
<version>2.8</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-core</artifactId>
......@@ -108,5 +107,19 @@
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.jgoodies</groupId>
<artifactId>jgoodies-forms</artifactId>
<version>1.9.0</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>4.1</version>
</dependency>
</dependencies>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>
\ No newline at end of file
......@@ -24,6 +24,7 @@ import lu.list.itis.dkd.dbc.annotation.NonNullByDefault;
import lu.list.itis.dkd.dbc.annotation.Nullable;
import lu.list.itis.dkd.tui.content.Content;
import lu.list.itis.dkd.tui.utility.Calibration;
import lu.list.itis.dkd.tui.utility.SplashScreen;
import lu.list.itis.dkd.tui.utility.TextHelper;
import lu.list.itis.dkd.tui.widget.BaseWidget;
......@@ -33,6 +34,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsDevice;
......@@ -81,6 +83,8 @@ public class TangibleInterfaceManager extends JComponent {
/** Field indicating whether the application should be shown full screen or not. */
protected boolean fullscreen;
protected boolean splashShown;
/** Title of the frame visualising the application. */
private String title;
......@@ -106,6 +110,8 @@ public class TangibleInterfaceManager extends JComponent {
private Area fullScreenArea;
private SplashScreen splashScreen;
/**
* Constructor initialising several fields and setting up the basic interface.
*
......@@ -117,6 +123,7 @@ public class TangibleInterfaceManager extends JComponent {
public TangibleInterfaceManager(TangibleApplication applicationContext, Properties properties) {
tangibleApplication = applicationContext;
interfaceProperties = properties;
splashShown = false;
System.setProperty("sun.awt.noerasebackground", "true");
......@@ -176,10 +183,7 @@ public class TangibleInterfaceManager extends JComponent {
});
frame.addKeyListener(new TuiKeyAdapter());
}
/** Method used to show the application's main frame. */
public void showWindow() {
setBounds();
frame.setIgnoreRepaint(true);
frame.getContentPane().setBackground(Color.BLACK);
......@@ -193,10 +197,39 @@ public class TangibleInterfaceManager extends JComponent {
frame.setUndecorated(true);
}
splashScreen = new SplashScreen(windowWidth, windowHeight);
}
/** Method used to show the application's main frame. */
public void showWindow() {
this.showSplashScreen();
}
protected void showSplashScreen() {
frame.getContentPane().remove(this);
frame.getContentPane().setLayout(new FlowLayout());
frame.getContentPane().add(splashScreen);
frame.setVisible(true);
frame.repaint();
splashShown = true;
}
protected void hideSplashScreen() {
frame.getContentPane().remove(splashScreen);
frame.getContentPane().add(this);
frame.setLayout(null);
setBounds();
frame.setVisible(true);
frame.repaint();
splashShown = false;
}
/** Method used to destroy the current frame. */
protected void destroyWindow() {
frame.setVisible(false);
......@@ -205,6 +238,14 @@ public class TangibleInterfaceManager extends JComponent {
frame = new JFrame();
}
public void doneLoading() {
// this.setupWindow();
// frame.setVisible(true);
hideSplashScreen();
frame.repaint();
}
/**
* Method for toggling whether the application is verbose. The method will toggle between
* showing all logging messages and showing only messages with a level of {@link Level#SEVERE}.
......@@ -291,6 +332,8 @@ public class TangibleInterfaceManager extends JComponent {
public void paint(@Nullable Graphics canvas) {
Preconditions.checkArgument(canvas != null, "The Graphics context cannot be null!"); //$NON-NLS-1$
// RepaintManager repaintManager = RepaintManager.currentManager(this);
// boolean oldState = repaintManager.isDoubleBufferingEnabled();
// repaintManager.setDoubleBufferingEnabled(false);
......@@ -447,6 +490,13 @@ public class TangibleInterfaceManager extends JComponent {
setupCalibrationWindow();
calibrationMode = true;
break;
case KeyEvent.VK_A:
if (splashShown) {
hideSplashScreen();
} else {
showSplashScreen();
}
break;
default:
logger.info("The keypress could not be associated to a case!"); //$NON-NLS-1$
break;
......
/**
* Copyright Luxembourg Institute of Science and Technology, 2017. 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.logging;
/**
* @author mack
* @since [major].[minor]
* @version [major].[minor].[micro]
*/
public interface LogListener {
/**
* @param message
*/
public void messageLogged(String message);
}
/**
* Copyright Luxembourg Institute of Science and Technology, 2017. 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.logging;
import org.apache.logging.log4j.core.Filter;
import org.apache.logging.log4j.core.Layout;
import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.appender.AbstractAppender;
import org.apache.logging.log4j.core.config.plugins.Plugin;
import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
import org.apache.logging.log4j.core.config.plugins.PluginElement;
import org.apache.logging.log4j.core.config.plugins.PluginFactory;
import org.apache.logging.log4j.core.layout.PatternLayout;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
/**
* @author mack
* @since [major].[minor]
* @version [major].[minor].[micro]
*/
@Plugin(name = "OnScreenLog", category = "Core", elementType = "appender", printObject = true)
public final class OnScreenLogAppender extends AbstractAppender {
// private CircularFifoQueue<String> logBuffer;
private int capacity;
private int size;
private Layout<? extends Serializable> layout;
private List<LogListener> logListeners;
private static HashMap<String, OnScreenLogAppender> instances = new HashMap<>();
/**
* @param name
* @param filter
* @param layout
* @param size
*/
public OnScreenLogAppender(String name, Filter filter, Layout<? extends Serializable> layout, int size) {
super(name, filter, layout);
this.capacity = size;
this.size = 0;
this.layout = layout;
// logBuffer = new CircularFifoQueue<>(size);
logListeners = new ArrayList<>();
}
/** {@inheritDoc} */
@Override
public void append(LogEvent event) {
String entry = new String(this.layout.toByteArray(event));
// logBuffer.add(entry);
this.size += (this.size < this.capacity) ? 1 : 0;
notifyLogListeners(entry);
}
/**
* @return
*/
public int getMessageCount() {
return this.size;
}
/**
* @param listener
*/
public void addLogListener(LogListener listener) {
logListeners.add(listener);
}
private void notifyLogListeners(String entry) {
logListeners.forEach(listener -> listener.messageLogged(entry));
}
// Your custom appender needs to declare a factory method
// annotated with `@PluginFactory`. Log4j will parse the configuration
// and call this factory method to construct an appender instance with
// the configured attributes.
/**
* @param name
* @param layout
* @param filter
* @param size
* @return
*/
@PluginFactory
public static OnScreenLogAppender createAppender(
@PluginAttribute("name") String name,
@PluginElement("Layout") Layout<? extends Serializable> layout,
@PluginElement("Filter") final Filter filter,
@PluginAttribute("size") Integer size) {
if (name == null) {
LOGGER.error("No name provided for OnScreenLogAppender"); //$NON-NLS-1$
return null;
}
Layout<? extends Serializable> _layout = (layout == null) ? PatternLayout.createDefaultLayout() : layout;
instances.put(name, new OnScreenLogAppender(name, filter, _layout, size));
return instances.get(name);
}
/**
* @param name
* @return
*/
public static OnScreenLogAppender getInstance(String name) {
return instances.get(name);
}
}
......@@ -174,6 +174,12 @@ public class Externalization extends NLS {
public static String SQUARE_SIZE_NODE;
public static String TRIANGLE_SIZE_NODE;
public static String MARKER_NODE;
public static String MARKERS_NODE;
public static String MARKER_BUILDER_NAMESPACE;
static {
// initialize resource bundle
NLS.initializeMessages(BUNDLE_NAME, Externalization.class);
......
......@@ -22,8 +22,6 @@ package lu.list.itis.dkd.tui.utility;
import lu.list.itis.dkd.dbc.annotation.NonNull;
import com.google.common.base.Preconditions;
/**
* Class implementing a {@link CoordinateState} for screen coordinates. The class features methods
* to transition to all other states.
......@@ -89,8 +87,8 @@ public class ScreenCoordinates extends CoordinateState {
/** {@inheritDoc} */
@Override
public Point transform(Point normalized) {
Preconditions.checkArgument((normalized.x >= 0) && (normalized.x <= 1));
Preconditions.checkArgument((normalized.y >= 0) && (normalized.y <= 1));
// Preconditions.checkArgument((normalized.x >= 0) && (normalized.x <= 1));
// Preconditions.checkArgument((normalized.y >= 0) && (normalized.y <= 1));
double screenx = Calibration.getScreenLeft() + (normalized.x * Calibration.getScreenWidth());
double screeny = Calibration.getScreenTop() + (normalized.y * Calibration.getScreenHeight());
......
/**
* Copyright Luxembourg Institute of Science and Technology, 2017. 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.utility;
import lu.list.itis.dkd.tui.logging.LogListener;
import lu.list.itis.dkd.tui.logging.OnScreenLogAppender;
import com.jgoodies.forms.layout.CellConstraints;
import com.jgoodies.forms.layout.FormLayout;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.awt.Color;
import java.awt.FontMetrics;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.ScrollPaneConstants;
import javax.swing.text.DefaultCaret;
/**
* @author mack
* @since [major].[minor]
* @version [major].[minor].[micro]
*/
// ***************************************************************************
// * Class Definition and Members *
// ***************************************************************************
public class SplashScreen extends JPanel implements LogListener {
private BufferedImage logo;
private JTextArea log;
private JScrollPane logScroller;
private OnScreenLogAppender appender;
// ***************************************************************************
// * Constants
// ***************************************************************************
private static final long serialVersionUID = -53719161591027476L;
private static final Logger LOGGER = LoggerFactory.getLogger(SplashScreen.class.getSimpleName());
private static final String LOGO_PATH = "../resources/TULIP.png"; //$NON-NLS-1$
private static final String COLUMN_SPECS = "left:pref, 5dlu, 60dlu:grow"; //$NON-NLS-1$
private static final String ROW_SPECS = "center:300dlu:grow, 5dlu, bottom:300dlu:grow"; //$NON-NLS-1$
// ---------------------------------------------------------------------------
// ***************************************************************************
// * Constructor(s)
// ***************************************************************************
// ---------------------------------------------------------------------------
public SplashScreen(int screenWidth, int screenHeight) {
logo = this.getImage(this.getClass(), LOGO_PATH);
this.setLayout(new FormLayout(COLUMN_SPECS, ROW_SPECS));
this.setBackground(Color.BLACK);
CellConstraints constraints = new CellConstraints();
Image scaledLogo = logo.getScaledInstance(640, 284, Image.SCALE_SMOOTH);
this.add(new JLabel(new ImageIcon(scaledLogo)), constraints.xy(1, 1));
log = new JTextArea();
log.setLineWrap(false);
log.setOpaque(false);
log.setForeground(Color.LIGHT_GRAY);
log.setEditable(false);
DefaultCaret caret = (DefaultCaret) log.getCaret();
caret.setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE);
logScroller = new JScrollPane(log);
logScroller.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
logScroller.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);
logScroller.setAutoscrolls(true);
logScroller.setOpaque(false);
logScroller.getViewport().setOpaque(false);
this.add(logScroller, constraints.xywh(1, 3, 3, 1));
FontMetrics metrics = log.getFontMetrics(log.getFont());
int columns = (int) (screenWidth / (metrics.charWidth('A') * 1.4));
int rows = screenHeight / (2 * metrics.getHeight());
log.setColumns(columns);
log.setRows(rows);
appender = OnScreenLogAppender.getInstance("SplashScreen");
appender.addLogListener(this);
}
// ---------------------------------------------------------------------------
// ***************************************************************************
// * Primitives(s)
// ***************************************************************************
// ---------------------------------------------------------------------------
private BufferedImage getImage(Class<?> referenceClass, String imagePath) {
URL location = referenceClass.getResource(imagePath);
BufferedImage image = null;
if (location != null)
try {
image = ImageIO.read(location);
} catch (IOException exception) {
LOGGER.error("I/O Error while attempting to read {}!", imagePath, exception); //$NON-NLS-1$
}
if ((image == null) || (image.getHeight() <= 0)) {
LOGGER.warn("Couldn't find Image {} relative to {}!", imagePath, referenceClass.getName()); //$NON-NLS-1$
}
return image;
}
/** {@inheritDoc} */
@Override
public void messageLogged(String message) {
log.append(message);
log.setRows(appender.getMessageCount());
}
// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------
// ***************************************************************************
// * Class Body
// ***************************************************************************
// ---------------------------------------------------------------------------
}
......@@ -93,6 +93,8 @@ public class StateManager {
/**
* Constructor initialising the internal map of states. The map will contain one entry, a
* {@link LimboState}.
*
* @param persistent
*/
public StateManager(boolean persistent) {
states = HashMultimap.create();
......
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