Commit 2ed5c65e authored by Jakub Kolman's avatar Jakub Kolman
Browse files

Merge branch 'master' into 'issue-38/procrustes-superimposition'

# Conflicts:
#   GUI/src/main/java/cz/fidentis/analyst/registration/RegistrationAction.java
parents 4123f32e f51302ba
Loading
Loading
Loading
Loading
+0 −69
Original line number Diff line number Diff line
package cz.fidentis.analyst.core;

import cz.fidentis.analyst.Logger;
import java.awt.BorderLayout;
import java.util.List;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingWorker;
import org.openide.windows.TopComponent;
import org.openide.windows.WindowManager;

/**
 * Wrapper of the default Java Netbeans Platform output window.
 * This wrapper runs in the worker thread, reads messages logged through 
 * the {@link cz.fidentis.analyst.Logger} and displays them in the output window.
 * 
 * The {@code OutputWindow} is currently executed from 
 * the {@link cz.fidentis.analyst.core.ProjectTopComp}, which is always presented.
 * 
 * @author Radek Oslejsek
 */
public class OutputWindow extends SwingWorker<String, String> {

    private static JTextArea textArea; 
    
    /**
     * Constructor.
     */
    public OutputWindow() {
        TopComponent outputWin = WindowManager.getDefault().findTopComponent("output");
        textArea = new JTextArea();
        JScrollPane sp = new JScrollPane(textArea);
        outputWin.add(sp, BorderLayout.CENTER);
    }

    /**
     * Reads messages of the {@code Logger} in the background and re-sends them
     * the {@link #process(java.util.List)} method.
     * 
     * @return Complete text displayed in the output window.
     * @throws Exception 
     */
    @Override
    protected String doInBackground() throws Exception {
        String line = Logger.reader().readLine();
        while (line != null) {
            publish(line);
            line = Logger.reader().readLine();
        }
        return textArea.getText();
    }
    
    /**
     * Takes text lines process by the {@link #doInBackground()} method and
     * adds them to the output window.
     * 
     * @param chunks process lines
     */
    @Override
    protected void process(List<String> chunks) {
        StringBuilder sb = new StringBuilder();
        sb.append(textArea.getText());
        chunks.forEach(str -> {
            sb.append(str + System.lineSeparator());
        });
        textArea.setText(sb.toString());
    }
        
}
+122 −0
Original line number Diff line number Diff line
package cz.fidentis.analyst.core;

import cz.fidentis.analyst.Logger;
import java.awt.BorderLayout;
import java.io.IOException;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import org.openide.util.Exceptions;
import org.openide.windows.TopComponent;
import org.openide.windows.WindowManager;

/**
 * Wrapper of the default Java Netbeans Platform output window.
 * This singleton runs in the background, reads messages logged through 
 * the {@link cz.fidentis.analyst.Logger} and displays them in the output window.
 * 
 * This singleton is currently executed from 
 * the {@link cz.fidentis.analyst.core.ProjectTopComp}, which is always presented
 * in the FIDENTIS application.
 *
 * @author Radek Oslejsek
 */
public class OutputWindowThread extends Thread {
    
    private JTextArea textArea; 
    
    private static OutputWindowThread instance;
    
    protected OutputWindowThread() {
        TopComponent outputWin = WindowManager.getDefault().findTopComponent("output");
        textArea = new JTextArea();
        JScrollPane sp = new JScrollPane(textArea);
        outputWin.add(sp, BorderLayout.CENTER);
    }
    
    /**
     * Starts the redirection of messages logged via the {@link cz.fidentis.analyst.Logger}
     * into the output window.
     * 
     * @return {@code false} if the singleton/thread is already executed, 
     * {@code true} otherwise.
     */
    public static boolean execute() {
        if (instance != null) {
            return false;
        }
        instance = new OutputWindowThread();
        instance.start(); // executes the run() method
        Logger.redirectToPipe();
        return true;
    }
    
    /**
     * Stops the redirection of messages logged via the {@link cz.fidentis.analyst.Logger}
     * into the output window.
     * 
     * @param err If {@code true} then the logged messages are redirected to the system error output.
     *            Otherwise, the system standard output is used.
     * @return {@code false} if the singleton/thread is already stopped, 
     *         {@code true} otherwise.
     */
    public static boolean stopExecution(boolean err) {
        if (instance == null) {
            return false;
        }
        if (err) {
            Logger.redirectToStdErr();
        } else {
            Logger.redirectToStdOut();
        }
        instance = null;
        return true;
    }
    
    /**
     * Stops the redirection of messages logged via the {@link cz.fidentis.analyst.Logger}
     * into the output window. The messages are redirected into the system standard output.
     * 
     * @return {@code false} if the singleton/thread is already stopped, 
     *         {@code true} otherwise.
     */
    public static boolean stopExecution() {
        return stopExecution(false);
    }
    
    @Override
    public void run() {
        int errorCounter = 0;
        
        while (true) {
            try {
                String line = Logger.read();
                if (line != null) {
                    StringBuilder sb = new StringBuilder();
                    sb.append(textArea.getText())
                            .append(line)
                            .append(System.lineSeparator());
                    textArea.setText(sb.toString());
                    textArea.setCaretPosition(textArea.getDocument().getLength());
                    errorCounter = 0;
                } else {
                    //System.out.println("No datain the message pipe");
                    fallAsleep(2000);
                }
            } catch (IOException ex) {
                if (errorCounter < 8) {
                    errorCounter++;
                }
                System.out.println("IOException: " + ex);
                fallAsleep(errorCounter * 1000);                
            } 
        }
    }
    
    protected void fallAsleep(int mil) {
        try {
            sleep(mil);
        } catch (InterruptedException ex) {
            Exceptions.printStackTrace(ex);
        }
    }
}
+3 −3
Original line number Diff line number Diff line
@@ -81,9 +81,9 @@ public final class ProjectTopComp extends TopComponent {
        putClientProperty(TopComponent.PROP_DRAGGING_DISABLED, Boolean.TRUE);
        putClientProperty(TopComponent.PROP_UNDOCKING_DISABLED, Boolean.TRUE);
        
        // Execute OutputWindow in the worker thread so that messages
        // logged via Logger are displayed in the output window
        (new OutputWindow()).execute();
        // Execute infinite OutputWindowThread that redirects messages logged
        // via Logger into the standard output window
        OutputWindowThread.execute();
    }

    /**
+0 −2
Original line number Diff line number Diff line
@@ -335,8 +335,6 @@ public class RegistrationAction extends ControlPanelAction {
     * to green otherwise set color to default
     */
    private void calculateFeaturePoints() {
        Logger.print("Calculation of feature points");

        if (getPrimaryDrawableFace() == null) { // scene not yet initiated
            return;
        }
+56 −19
Original line number Diff line number Diff line
@@ -14,16 +14,17 @@ import java.util.logging.Level;
 * A logging class that can be used from anywhere to display debugging or other
 * messages.
 * <p>
 * Messages are printed into the standard output unless the {@link #reader()} 
 * method is called. Then the messages are redirected to the returned {@code BufferedReader}.
 * Messages are printed into the system standard output by default. But can be also
 * redirected to system error output or into the pipe.
 * </p>
 * <p>
 * The implementation supposes that the caller of the {@link #reader()} method 
 * (or other object} will read the messages from the {@code BufferedReader} forever. 
 * Otherwise, the program can freeze due to the full buffer.
 * If the messages are redirected into pipe, then <b>a consumer has to be running 
 * concurrently</b> and reading the data through the {@link #read()} method.
 * <b>Otherwise, the program can freeze due to the full buffer!</b>
 * </p>
 * <p>
 * FIDENTIS application automatically redirects logged messages to the output window.
 * FIDENTIS application automatically redirects logged messages to the output window 
 * via the {@code OutputWindowThread}. 
 * </p>
 * <p>
 * <b>Usage:</b>
@@ -39,6 +40,8 @@ import java.util.logging.Level;
 */
public final class Logger {
    
    private static final int PIPE_SIZE = 10240; // default is 1024
    
    private static PrintStream out = System.out;
    private static BufferedReader in;
    
@@ -48,21 +51,53 @@ public final class Logger {
    }
    
    /**
     * Redirects logs from standard output to the {@code BufferedReader}.
     * 
     * @return {@code BufferedReader} to which the logs are redirected.
     * Redirects messages into a pipe. 
     * <b>A consumer has to be running concurrently</b> and reading the messages
     * through the {@link #read()} method.
     * Otherwise, the program can freeze due to the full buffer!
     */
    public static BufferedReader reader() {
        if (in == null) {
    public static synchronized void redirectToPipe() {
        if (in != null) {
            return;
        }
        
        PipedOutputStream pOut = new PipedOutputStream();
        out = new PrintStream(pOut);
        try {
                in = new BufferedReader(new InputStreamReader(new PipedInputStream(pOut)));
            in = new BufferedReader(new InputStreamReader(new PipedInputStream(pOut, PIPE_SIZE)));
        } catch (IOException ex) {
            java.util.logging.Logger.getLogger(Logger.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
        return in;
    
    /**
     * Redirects messages into the system standard output.
     */
    public static synchronized void redirectToStdOut() {
        out = System.out;
        in = null;
    }
    
    /**
     * Redirects messages into the system error output.
     */
    public static synchronized void redirectToStdErr() {
        out = System.err;
        in = null;
    }
    
    /**
     * Returns an event message. If the logger is redirected to standard or error output,
     * then {@code null} is returned. Also, if the is no message, {@code null} is returned.
     * 
     * @return Event message or {@code null}
     * @throws IOException on error in reading the message buffer.
     */
    public static String read() throws IOException {
        if (in == null/* || !in.ready()*/) {
            return null;
        }
        return in.readLine();
    }
    
    /**
@@ -76,6 +111,7 @@ public final class Logger {
                + " [duration unknown]: "
                + msg.trim();
        out.println(outMsg);
        out.flush();
    }

    /**
@@ -114,6 +150,7 @@ public final class Logger {
                + msg.trim();
    
        out.println(outMsg);
        out.flush();
    }
    
}