Package org.jwildfire.create.tina.mutagen

Source Code of org.jwildfire.create.tina.mutagen.MutaGenController

/*
  JWildfire - an image and animation processor written in Java
  Copyright (C) 1995-2014 Andreas Maschke

  This 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; either version 2.1 of the
  License, or (at your option) any later version.
  This software 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 software;
  if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
  02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jwildfire.create.tina.mutagen;

import static org.jwildfire.base.mathlib.MathLib.EPSILON;
import static org.jwildfire.base.mathlib.MathLib.fabs;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.MouseEvent;
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.ArrayList;
import java.util.List;

import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFileChooser;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JTabbedPane;
import javax.swing.JTextPane;
import javax.swing.KeyStroke;
import javax.swing.border.LineBorder;

import org.jwildfire.base.Prefs;
import org.jwildfire.base.Tools;
import org.jwildfire.create.tina.animate.FlameMorphService;
import org.jwildfire.create.tina.animate.FlameMorphType;
import org.jwildfire.create.tina.base.Flame;
import org.jwildfire.create.tina.base.Layer;
import org.jwildfire.create.tina.io.FlameReader;
import org.jwildfire.create.tina.io.FlameWriter;
import org.jwildfire.create.tina.randomflame.RandomFlameGeneratorSampler;
import org.jwildfire.create.tina.render.FlameRenderer;
import org.jwildfire.create.tina.render.RenderInfo;
import org.jwildfire.create.tina.render.RenderMode;
import org.jwildfire.create.tina.render.RenderedFlame;
import org.jwildfire.create.tina.swing.FlameFileChooser;
import org.jwildfire.create.tina.swing.JWFNumberField;
import org.jwildfire.create.tina.swing.TinaController;
import org.jwildfire.image.SimpleImage;
import org.jwildfire.swing.ErrorHandler;
import org.jwildfire.swing.ImagePanel;

public class MutaGenController {
  public static final int PAGE_INDEX = 2;
  private final TinaController tinaController;
  private final ErrorHandler errorHandler;
  private final Prefs prefs;
  private final JTabbedPane rootTabbedPane;
  private final JPanel flamePanels[];
  private final JButton loadFlameFromEditorBtn;
  private final JButton loadFlameFromFileBtn;
  private final JProgressBar progressBar;
  private final JWFNumberField amountREd;
  private final JComboBox horizontalTrend1Cmb;
  private final JComboBox horizontalTrend2Cmb;
  private final JComboBox verticalTrend1Cmb;
  private final JComboBox verticalTrend2Cmb;
  private final JButton backButton;
  private final JButton forwardButton;
  private final JButton saveFlameToEditorBtn;
  private final JButton saveFlameToFileBtn;
  private final JTextPane hintPane;

  private ImagePanel imagePanels[][];
  private final int MUTA_ROWS = 5;
  private final int MUTA_COLS = 5;
  private final List<MutationSet> mutationList = new ArrayList<MutationSet>();
  private int selectedGenerationIdx = -1;
  private int selRow = -1, selCol = -1;

  private class MutationSet {
    final int rows, cols;
    final Flame baseFlame;
    final Flame[][] flames;

    public MutationSet(int pRows, int pCols, Flame pBaseFlame) {
      rows = pRows;
      cols = pCols;
      flames = new Flame[rows][cols];
      baseFlame = pBaseFlame;
      flames[rows / 2][cols / 2] = pBaseFlame;
    }

    public MutationSet(int pRows, int pCols, Flame pBaseFlame, List<Flame> pFlames) {
      rows = pRows;
      cols = pCols;
      flames = new Flame[rows][cols];
      int idx = 0;
      for (int i = 0; i < pRows; i++) {
        for (int j = 0; j < pCols; j++) {
          flames[i][j] = pFlames.get(idx++);
        }
      }
      baseFlame = pBaseFlame;
      flames[rows / 2][cols / 2] = pBaseFlame;
    }

    public int getRows() {
      return rows;
    }

    public int getCols() {
      return cols;
    }

    public Flame getFlame(int pRow, int pCol) {
      return flames[pRow][pCol];
    }

    public Flame getBaseFlame() {
      return baseFlame;
    }

  }

  public MutaGenController(TinaController pTinaController, ErrorHandler pErrorHandler, Prefs pPrefs, JTabbedPane pRootTabbedPane, JPanel pFlamePanels[],
      JButton pLoadFlameFromEditorBtn, JButton pLoadFlameFromFileBtn,
      JProgressBar pProgressBar, JWFNumberField pAmountREd, JComboBox pHorizontalTrend1Cmb, JComboBox pHorizontalTrend2Cmb,
      JComboBox pVerticalTrend1Cmb, JComboBox pVerticalTrend2Cmb, JButton pBackButton, JButton pForwardButton, JTextPane pHintPane,
      JButton pSaveFlameToEditorBtn, JButton pSaveFlameToFileBtn) {
    tinaController = pTinaController;
    errorHandler = pErrorHandler;
    flamePanels = pFlamePanels;
    prefs = pPrefs;
    rootTabbedPane = pRootTabbedPane;
    loadFlameFromEditorBtn = pLoadFlameFromEditorBtn;
    loadFlameFromFileBtn = pLoadFlameFromFileBtn;
    progressBar = pProgressBar;
    amountREd = pAmountREd;
    horizontalTrend1Cmb = pHorizontalTrend1Cmb;
    horizontalTrend2Cmb = pHorizontalTrend2Cmb;
    verticalTrend1Cmb = pVerticalTrend1Cmb;
    verticalTrend2Cmb = pVerticalTrend2Cmb;
    backButton = pBackButton;
    forwardButton = pForwardButton;
    hintPane = pHintPane;
    saveFlameToEditorBtn = pSaveFlameToEditorBtn;
    saveFlameToFileBtn = pSaveFlameToFileBtn;

    refreshTrendCmb(horizontalTrend1Cmb);
    refreshTrendCmb(horizontalTrend2Cmb);
    refreshTrendCmb(verticalTrend1Cmb);
    refreshTrendCmb(verticalTrend2Cmb);
    amountREd.setValue(1.0);
    initHintsPane();
  }

  private void refreshTrendCmb(JComboBox pCmb) {
    pCmb.removeAllItems();
    pCmb.addItem(MutationType.ALL);
    pCmb.addItem(MutationType.ADD_TRANSFORM);
    pCmb.addItem(MutationType.ADD_VARIATION);
    pCmb.addItem(MutationType.AFFINE);
    pCmb.addItem(MutationType.CHANGE_WEIGHT);
    pCmb.addItem(MutationType.GRADIENT_POSITION);
    pCmb.addItem(MutationType.LOCAL_GAMMA);
    pCmb.addItem(MutationType.RANDOM_FLAME);
    pCmb.addItem(MutationType.RANDOM_GRADIENT);
    pCmb.addItem(MutationType.RANDOM_PARAMETER);
    pCmb.setSelectedIndex(0);
  }

  public void importFlame(Flame pFlame) {
    Flame baseFlame = pFlame.makeCopy();
    MutationSet set = new MutationSet(MUTA_ROWS, MUTA_COLS, baseFlame);
    mutationList.add(set);
    selectedGenerationIdx = mutationList.size() - 1;
    mutate(MUTA_ROWS / 2, MUTA_COLS / 2);
    enableControls();
  }

  private Flame createWeightedFlame(Flame pBaseFlame, Flame pFlame) {
    double amount = (Double) amountREd.getValue();
    if (amount < EPSILON) {
      return pBaseFlame.makeCopy();
    }
    else if (amount > 1.0 - EPSILON) {
      return pFlame.makeCopy();
    }
    else {
      int morphFrames = 1000;
      int morphFrame = Tools.FTOI(morphFrames * amount);
      return FlameMorphService.morphFlames(prefs, FlameMorphType.MORPH, pBaseFlame.makeCopy(), pFlame.makeCopy(), morphFrame, morphFrames);
    }
  }

  private SimpleImage renderFlame(Flame pFlame, Dimension pImgSize, boolean pWithTimeout) {
    int pImageWidth = pImgSize.width, pImageHeight = pImgSize.height;
    SimpleImage img;
    if (pFlame != null && pImageWidth > 16 && pImageHeight > 16) {
      return img = executeRenderThread(pFlame, pImageWidth, pImageHeight, pWithTimeout);
    }
    else {
      img = new SimpleImage(pImageWidth, pImageHeight);
    }
    return img;
  }

  private class RenderThread implements Runnable {
    private boolean done;
    private final Flame flame;
    private final int imageWidth;
    private final int imageHeight;
    private SimpleImage renderResult;
    private FlameRenderer renderer;

    public RenderThread(Flame pFlame, int pImageWidth, int pImageHeight) {
      this.flame = pFlame;
      this.imageWidth = pImageWidth;
      this.imageHeight = pImageHeight;
    }

    @Override
    public void run() {
      done = false;
      try {
        RenderInfo info = new RenderInfo(imageWidth, imageHeight, RenderMode.PREVIEW);
        double wScl = (double) info.getImageWidth() / (double) flame.getWidth();
        double hScl = (double) info.getImageHeight() / (double) flame.getHeight();
        flame.setPixelsPerUnit((wScl + hScl) * 0.5 * flame.getPixelsPerUnit());
        flame.setWidth(imageWidth);
        flame.setHeight(imageHeight);
        flame.setSampleDensity(20.0);
        renderer = new FlameRenderer(flame, prefs, false, false);
        RenderedFlame res = renderer.renderFlame(info);
        renderResult = res.getImage();
      }
      finally {
        done = true;
      }
    }

    public boolean isDone() {
      return done;
    }

    public SimpleImage getRenderResult() {
      return renderResult;
    }

    public void forceAbort() {
      renderer.signalCancel();
    }

  }

  private SimpleImage executeRenderThread(Flame pFlame, int pImageWidth, int pImageHeight, boolean pWithTimeout) {
    RenderThread thread = new RenderThread(pFlame, pImageWidth, pImageHeight);
    long tMax = 1000;
    long t0 = System.currentTimeMillis();
    new Thread(thread).start();
    while (!thread.isDone()) {
      try {
        Thread.sleep(1);
      }
      catch (InterruptedException ex) {
        throw new RuntimeException(ex);
      }
      long t1 = System.currentTimeMillis();
      if (pWithTimeout && (t1 - t0 > tMax)) {
        thread.forceAbort();
        return null;
      }
    }
    return thread.getRenderResult();
  }

  private void createImagePanels() {
    if (imagePanels == null) {
      try {
        final int rows = MUTA_ROWS;
        final int cols = MUTA_COLS;
        final int BORDER_SIZE = 0;

        ((JPanel) flamePanels[0].getParent()).getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(37, 0), "selectLeftCellAction");
        ((JPanel) flamePanels[0].getParent()).getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(39, 0), "selectRightCellAction");
        ((JPanel) flamePanels[0].getParent()).getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(38, 0), "selectTopCellAction");
        ((JPanel) flamePanels[0].getParent()).getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(40, 0), "selectBottomCellAction");
        ((JPanel) flamePanels[0].getParent()).getActionMap().put("selectLeftCellAction", new AbstractAction() {
          @Override
          public void actionPerformed(ActionEvent e) {
            selectLeftCell();
          }
        });
        ((JPanel) flamePanels[0].getParent()).getActionMap().put("selectRightCellAction", new AbstractAction() {
          @Override
          public void actionPerformed(ActionEvent e) {
            selectRightCell();
          }
        });
        ((JPanel) flamePanels[0].getParent()).getActionMap().put("selectTopCellAction", new AbstractAction() {
          @Override
          public void actionPerformed(ActionEvent e) {
            selectUpperCell();
          }
        });
        ((JPanel) flamePanels[0].getParent()).getActionMap().put("selectBottomCellAction", new AbstractAction() {
          @Override
          public void actionPerformed(ActionEvent e) {
            selectLowerCell();
          }
        });

        imagePanels = new ImagePanel[rows][cols];
        int idx = 0;
        for (int i = 0; i < rows; i++) {
          for (int j = 0; j < cols; j++) {
            JPanel panel = flamePanels[idx++];
            Dimension size = panel.getSize();
            SimpleImage img = new SimpleImage(Tools.FTOI(size.getWidth()), Tools.FTOI(size.getHeight()));
            final ImagePanel imgPanel = new ImagePanel(img, 0, 0, img.getImageWidth());
            imagePanels[i][j] = imgPanel;
            imgPanel.setImage(img);
            imgPanel.setLocation(BORDER_SIZE, BORDER_SIZE);

            final int row = i;
            final int col = j;

            imgPanel.addMouseListener(new java.awt.event.MouseAdapter() {

              @Override
              public void mouseClicked(java.awt.event.MouseEvent e) {
                if (e.getClickCount() == 2 || e.getButton() == MouseEvent.BUTTON3) {
                  mutate(row, col);
                }
                else if (e.getClickCount() == 1 && e.getButton() == MouseEvent.BUTTON2) {
                  export(row, col);
                }
              }

              @Override
              public void mousePressed(MouseEvent e) {
                selectCell(row, col);
              }
            });
            panel.add(imgPanel);
          }
        }
      }
      catch (Throwable ex) {
        imagePanels = null;
        errorHandler.handleError(ex);
      }
    }
  }

  protected void selectLeftCell() {
    if (selCol < 0 || selRow < 0) {
      selectCell(0, 0);
    }
    else {
      selCol--;
      if (selCol < 0) {
        selCol = 0;
      }
      selectCell(selRow, selCol);
    }
  }

  protected void selectRightCell() {
    if (selCol < 0 || selRow < 0) {
      selectCell(0, 0);
    }
    else {
      selCol++;
      if (selCol >= MUTA_COLS) {
        selCol = MUTA_COLS - 1;
      }
      selectCell(selRow, selCol);
    }
  }

  protected void selectUpperCell() {
    if (selCol < 0 || selRow < 0) {
      selectCell(0, 0);
    }
    else {
      selRow--;
      if (selRow < 0) {
        selRow = 0;
      }
      selectCell(selRow, selCol);
    }
  }

  protected void selectLowerCell() {
    if (selCol < 0 || selRow < 0) {
      selectCell(0, 0);
    }
    else {
      selRow++;
      if (selRow >= MUTA_ROWS) {
        selRow = MUTA_ROWS - 1;
      }
      selectCell(selRow, selCol);
    }
  }

  protected void selectCell(int pRow, int pCol) {
    createImagePanels();
    final Color selColor = new Color(65, 63, 147);
    final Color deSelColor = new Color(0, 0, 0);

    for (int i = 0; i < 5; i++) {
      for (int j = 0; j < 5; j++) {
        ImagePanel pnl = imagePanels[i][j];
        boolean sel = i == pRow && j == pCol;
        ((JPanel) pnl.getParent()).setBorder(new LineBorder(sel ? selColor : deSelColor, sel ? 5 : 1));
      }
    }
    selRow = pRow;
    selCol = pCol;
    enableControls();
  }

  protected void export(int pRow, int pCol) {
    if (selectedGenerationIdx >= 0 && selectedGenerationIdx < mutationList.size()) {
      MutationSet selectedSet = mutationList.get(selectedGenerationIdx);

      Flame flame = selectedSet.getFlame(pRow, pCol);
      Flame morphedFlame = createWeightedFlame(selectedSet.getBaseFlame(), flame);

      tinaController.importFlame(morphedFlame, true);

      rootTabbedPane.setSelectedIndex(TinaController.PAGE_INDEX);
      rootTabbedPane.getParent().invalidate();
      try {
        Graphics g = rootTabbedPane.getParent().getGraphics();
        if (g != null) {
          rootTabbedPane.getParent().paint(g);
        }
      }
      catch (Throwable ex) {
        ex.printStackTrace();
      }

    }
  }

  private Dimension calcImageSize() {
    createImagePanels();
    ImagePanel pnl = imagePanels[0][0];
    Dimension size = pnl.getSize();
    int imageWidth = Tools.FTOI(size.getWidth());
    int imageHeight = Tools.FTOI(size.getHeight());
    return new Dimension(imageWidth, imageHeight);
  }

  protected void mutate(int pRow, int pCol) {
    try {

      if (selectedGenerationIdx >= 0 && selectedGenerationIdx < mutationList.size()) {
        Dimension renderSize = calcImageSize();
        Dimension probeSize = new Dimension(80, 60);

        MutationSet selectedSet = mutationList.get(selectedGenerationIdx);
        final int rows = MUTA_ROWS;
        final int cols = MUTA_COLS;
        Flame baseFlame = selectedSet.getFlame(pRow, pCol);
        baseFlame = createWeightedFlame(selectedSet.getBaseFlame(), baseFlame);

        boolean doMorph = fabs((Double) amountREd.getValue() - 1.0) > EPSILON;

        List<Flame> mutations = new ArrayList<Flame>();
        initProgress(rows, cols);
        int centreX = rows / 2;
        int centreY = cols / 2;

        SimpleImage baseFlameImg = renderFlame(baseFlame.makeCopy(), probeSize, false);
        SimpleImage simplifiedBaseFlameImg = RandomFlameGeneratorSampler.createSimplifiedRefImage(baseFlameImg);

        int step = 0;
        for (int i = 0; i < rows; i++) {
          for (int j = 0; j < cols; j++) {
            // Let centre flame untouched
            SimpleImage renderedImg = null;
            if ((i != centreX || j != centreY)) {
              int x = (i - centreX);
              int y = (j - centreY);
              final int MAX_ITER = 10;
              final double MIN_RENDER_COVERAGE = 0.42;
              final double MIN_DIFF_COVERAGE = 0.28;
              final double INVALID_COVERAGE = -1.0;
              int iter = 0;
              double bestCoverage = INVALID_COVERAGE;
              Flame bestMutation = null;
              while (true) {
                Flame currMutation = baseFlame.makeCopy();
                List<MutationType> mutationTypes = createMutationTypes(x, y);
                modifyFlame(currMutation, x, y, mutationTypes);
                renderedImg = renderFlame(currMutation.makeCopy(), probeSize, true);
                double coverage = renderedImg != null ? RandomFlameGeneratorSampler.calculateCoverage(renderedImg, 0, 0, 0, true) : INVALID_COVERAGE;
                if (coverage > MIN_RENDER_COVERAGE) {
                  coverage = RandomFlameGeneratorSampler.calculateDiffCoverage(renderedImg, simplifiedBaseFlameImg);
                }
                if (coverage > MIN_DIFF_COVERAGE) {
                  mutations.add(currMutation);
                  if (doMorph) {
                    Flame morphed = createWeightedFlame(baseFlame, currMutation);
                    renderedImg = renderFlame(morphed, renderSize, false);
                  }
                  else {
                    renderedImg = renderFlame(currMutation, renderSize, false);
                  }
                  break;
                }
                else if (coverage > bestCoverage) {
                  bestCoverage = coverage;
                  bestMutation = currMutation;
                }
                // Don't count invalid mutations
                if (renderedImg != null) {
                  iter++;
                }
                if (iter >= MAX_ITER) {
                  mutations.add(bestMutation);
                  if (doMorph) {
                    Flame morphed = createWeightedFlame(baseFlame, bestMutation);
                    renderedImg = renderFlame(morphed, renderSize, false);
                  }
                  else {
                    renderedImg = renderFlame(bestMutation, renderSize, false);
                  }
                  break;
                }
              }
            }
            else {
              mutations.add(baseFlame.makeCopy());
              renderedImg = renderFlame(baseFlame.makeCopy(), renderSize, false);
            }

            ImagePanel pnl = imagePanels[i][j];
            pnl.setImage(renderedImg);
            showProgress(++step);

            try {
              pnl.invalidate();
              Graphics g = pnl.getGraphics();
              if (g != null) {
                pnl.paint(g);
              }
            }
            catch (Throwable ex) {
              ex.printStackTrace();
            }
          }
        }
        MutationSet newSet = new MutationSet(rows, cols, baseFlame, mutations);
        mutationList.add(newSet);
        selectedGenerationIdx = mutationList.size() - 1;
        enableControls();
      }

    }
    catch (Throwable ex) {
      errorHandler.handleError(ex);
    }
  }

  private List<MutationType> createMutationTypes(int pX, int pY) {
    MutationType horizType1 = (MutationType) horizontalTrend1Cmb.getSelectedItem();
    MutationType horizType2 = (MutationType) horizontalTrend2Cmb.getSelectedItem();
    MutationType vertType1 = (MutationType) verticalTrend1Cmb.getSelectedItem();
    MutationType vertType2 = (MutationType) verticalTrend2Cmb.getSelectedItem();

    List<MutationType> mutations = new ArrayList<MutationType>();
    if (Math.random() < 0.5) {
      if (pX == 1 || pX == -1) {
        mutations.add(horizType1);
      }
      if (pY == 1 || pY == -1) {
        mutations.add(vertType1);
      }
    }
    else {
      if (pY == 1 || pY == -1) {
        mutations.add(vertType1);
      }
      if (pX == 1 || pX == -1) {
        mutations.add(horizType1);
      }
    }
    if (Math.random() > 0.5) {
      if (pX == 2 || pX == -2) {
        mutations.add(horizType1);
        mutations.add(horizType2);
      }
      if (pY == 2 || pY == -2) {
        mutations.add(vertType1);
        mutations.add(vertType2);
      }
    }
    else {
      if (pY == 2 || pY == -2) {
        mutations.add(vertType1);
        mutations.add(vertType2);
      }
      if (pX == 2 || pX == -2) {
        mutations.add(horizType1);
        mutations.add(horizType2);
      }
    }
    return mutations;
  }

  private void modifyFlame(Flame pFlame, double pX, int pY, List<MutationType> pMutationTypes) {
    for (MutationType mutationType : pMutationTypes) {
      Mutation mutation = mutationType.createMutationInstance();
      for (Layer layer : pFlame.getLayers()) {
        if (layer.isRenderable()) {
          mutation.execute(layer);
        }
      }
    }
  }

  private void showProgress(int pStep) {
    progressBar.setValue(pStep);
    progressBar.invalidate();
    try {
      Graphics g = progressBar.getGraphics();
      if (g != null) {
        progressBar.paint(g);
      }
    }
    catch (Throwable ex) {
      ex.printStackTrace();
    }
  }

  private void initProgress(int pRows, int pCols) {
    progressBar.setMinimum(0);
    progressBar.setValue(0);
    progressBar.setMaximum(pRows * pCols);
    progressBar.invalidate();
    try {
      Graphics g = progressBar.getGraphics();
      if (g != null) {
        progressBar.paint(g);
      }
    }
    catch (Throwable ex) {
      ex.printStackTrace();
    }
  }

  public void loadFlameFromEditorBtn_clicked() {
    if (tinaController.getCurrFlame() != null) {
      importFlame(tinaController.getCurrFlame());
    }
  }

  public void loadFlameFromFileBtn_clicked() {
    try {
      JFileChooser chooser = new FlameFileChooser(prefs);
      if (prefs.getInputFlamePath() != null) {
        try {
          chooser.setCurrentDirectory(new File(prefs.getInputFlamePath()));
        }
        catch (Exception ex) {
          ex.printStackTrace();
        }
      }
      if (chooser.showOpenDialog(rootTabbedPane) == JFileChooser.APPROVE_OPTION) {
        File file = chooser.getSelectedFile();
        List<Flame> flames = new FlameReader(prefs).readFlames(file.getAbsolutePath());
        Flame flame = flames.get(0);
        prefs.setLastInputFlameFile(file);
        if (flame != null) {
          importFlame(flame);
        }
      }
    }
    catch (Throwable ex) {
      errorHandler.handleError(ex);
    }
  }

  public void backBtn_clicked() {
    if (selectedGenerationIdx > 0 && mutationList.size() > 0) {
      selectedGenerationIdx--;
      drawSelectedSet();
    }
  }

  public void forwardBtn_clicked() {
    if (selectedGenerationIdx >= 0 && selectedGenerationIdx < mutationList.size() - 1) {
      selectedGenerationIdx++;
      drawSelectedSet();
    }
  }

  public void drawSelectedSet() {
    Dimension imgSize = calcImageSize();
    MutationSet selectedSet = mutationList.get(selectedGenerationIdx);
    int rows = selectedSet.getRows();
    int cols = selectedSet.getCols();
    initProgress(rows, cols);
    int step = 0;
    for (int i = 0; i < rows; i++) {
      for (int j = 0; j < cols; j++) {
        Flame mutation = selectedSet.getFlame(i, j).makeCopy();
        Flame morphed = createWeightedFlame(selectedSet.getBaseFlame(), mutation);
        SimpleImage renderedImg = renderFlame(morphed, imgSize, false);
        ImagePanel pnl = imagePanels[i][j];
        pnl.setImage(renderedImg);
        showProgress(++step);
        pnl.invalidate();
        try {
          Graphics g = pnl.getGraphics();
          if (g != null) {
            pnl.paint(g);
          }
        }
        catch (Throwable ex) {
          ex.printStackTrace();
        }
      }
    }
    enableControls();
  }

  private void initHintsPane() {
    hintPane.setContentType("text/html");
    try {
      Font f = new Font(Font.SANS_SERIF, 3, 10);
      hintPane.setFont(f);

      InputStream is = this.getClass().getResourceAsStream("hints.html");
      StringBuffer content = new StringBuffer();
      String lineFeed = System.getProperty("line.separator");
      String line;
      Reader r = new InputStreamReader(is, "utf-8");
      BufferedReader in = new BufferedReader(r);
      while ((line = in.readLine()) != null) {
        content.append(line).append(lineFeed);
      }
      in.close();

      hintPane.setText(content.toString());
      hintPane.setSelectionStart(0);
      hintPane.setSelectionEnd(0);
    }
    catch (Exception ex) {
      ex.printStackTrace();
    }
  }

  private void enableControls() {
    backButton.setEnabled(selectedGenerationIdx > 0 && selectedGenerationIdx < mutationList.size());
    forwardButton.setEnabled(selectedGenerationIdx >= 0 && selectedGenerationIdx < mutationList.size() - 1);
    saveFlameToEditorBtn.setEnabled(selRow >= 0 && selCol >= 0 && selectedGenerationIdx >= 0 && selectedGenerationIdx < mutationList.size());
    saveFlameToFileBtn.setEnabled(selRow >= 0 && selCol >= 0 && selectedGenerationIdx >= 0 && selectedGenerationIdx < mutationList.size());
  }

  public void exportFlameBtn_clicked() {
    if (selectedGenerationIdx >= 0 && selectedGenerationIdx < mutationList.size() && selRow >= 0 && selCol >= 0) {
      export(selRow, selCol);
    }
  }

  public void saveFlameBtn_clicked() {
    if (selectedGenerationIdx >= 0 && selectedGenerationIdx < mutationList.size() && selRow >= 0 && selCol >= 0) {
      MutationSet selectedSet = mutationList.get(selectedGenerationIdx);
      Flame currFlame = selectedSet.getFlame(selRow, selCol);
      try {
        if (currFlame != null) {
          JFileChooser chooser = new FlameFileChooser(prefs);
          if (prefs.getOutputFlamePath() != null) {
            try {
              chooser.setCurrentDirectory(new File(prefs.getOutputFlamePath()));
            }
            catch (Exception ex) {
              ex.printStackTrace();
            }
          }
          if (chooser.showSaveDialog(rootTabbedPane) == JFileChooser.APPROVE_OPTION) {
            File file = chooser.getSelectedFile();
            new FlameWriter().writeFlame(currFlame, file.getAbsolutePath());
            currFlame.setLastFilename(file.getName());
            prefs.setLastOutputFlameFile(file);
          }
        }
      }
      catch (Throwable ex) {
        errorHandler.handleError(ex);
      }
    }
  }
}
TOP

Related Classes of org.jwildfire.create.tina.mutagen.MutaGenController

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.