/*
* RapidMiner
*
* Copyright (C) 2001-2014 by RapidMiner and the contributors
*
* Complete list of developers available at our web site:
*
* http://rapidminer.com
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see http://www.gnu.org/licenses/.
*/
package com.rapidminer.gui.tour;
import java.util.LinkedList;
import java.util.List;
/** A tour consisting of multiple {@link Step}s explaining the usage of RapidMiner
* or an Extension.
*
* Implementations of tour must implement a default (no-arg) constructor since
* they are created reflectively.
*
*
* @author Thilo Kamradt
*
*/
public abstract class IntroductoryTour {
public static interface TourListener {
/**
* will be called by a {@link Step} if the Tour was closed or is finished
*/
public void tourClosed();
}
private int maxSteps;
/**
* This Array has to be filled with Subclasses of {@link Step} which will guide the Tour.
*/
protected Step[] step;
private String tourKey;
private boolean completeWindow;
private List<TourListener> listeners;
private Step head;
/**
* This Constructor will initialize the {@link Step} step[] which has to be filled in the buildTour() Method and adds automatically a {@link FinalStep} to the end of your tour.
*
* @param max number of steps you want to perform (size of the Array you want to fill)
* @param tourName name of the your tour (will be used as key as well)
*/
public IntroductoryTour(int steps, String tourName) {
this(steps, tourName, true);
}
/**
* This Constructor will initialize the {@link Step} step[] which has to be filled in the buildTour() Method
*
* @param steps number of Steps you will do (size of the Array you want to fill)
* @param tourName name of the your tour (will be used as key as well)
* @param addComppleteWindow indicates whether a {@link FinalStep} with will be added or not.
*/
public IntroductoryTour(int steps, String tourName, boolean addComppleteWindow) {
this.tourKey = tourName;
this.completeWindow = addComppleteWindow;
this.maxSteps = steps;
this.listeners = new LinkedList<TourListener>();
}
/**
* method to initializes the needed Array of {@link Step} and the FinalStep if wanted
*/
private void init() {
step = new Step[maxSteps];
}
/**
* starts the Tour
*/
public void startTour() {
init();
buildTour();
placeFollowers();
head.start();
}
/**
* This method fills the step[] instances of subclasses of {@link Step} which will guide through the tour
*/
protected abstract void buildTour();
/**
* method to get the key and name of the Tour.
* @return String with key of the Tour
*/
public String getKey() {
return tourKey;
}
/**
* This method connects the single steps to a queue and the the needed parameters to the steps.
* After calling this method the isFinal-, tourKey-, index- and listeners-parameter of Step is set.
*/
private void placeFollowers() {
Step tail;
int counter = 1;
Step[] currentPreconditions = step[0].getPreconditions();
head = ((currentPreconditions.length == 0) ? step[0] : currentPreconditions[0]);
tail = head;
head.makeSettings(tourKey, ((currentPreconditions.length == 0) ? counter++ : counter), this.getSize(), false, listeners);
//iterate over Array and create a queue
for (int i = (counter - 1); i < step.length; i++) {
//enqueue the Preconditions
currentPreconditions = step[i].getPreconditions();
for (int j = 0; j < currentPreconditions.length; j++) {
if(i == 0 && j == 0) {
continue;
}
currentPreconditions[j].makeSettings(tourKey, counter , this.getSize(), false, listeners);
tail.setNext(currentPreconditions[j]);
tail = tail.getNext();
}
// add the current Step to the queue and set the next step
tail.setNext(step[i]);
tail = tail.getNext();
if(!completeWindow && i == (step.length - 1)){
//this is the final step
tail.makeSettings(tourKey, counter++ , this.getSize(), true, listeners);
} else {
//this is just a step
tail.makeSettings(tourKey, counter++ , this.getSize(), false, listeners);
}
}
if(completeWindow) {
tail.setNext(new FinalStep(tourKey));
tail.getNext().makeSettings(tourKey, counter++ , this.getSize(), true, listeners);
}
}
// private void placeFollowers() {
// Step tail;
// Step[] currentPreconditions = step[0].getPreconditions();
// Step[] nextPreconditions;
// tail = head;
// // set head and tail of the queue
// if(currentPreconditions.length == 0) {
// head = step[0];
// tail = head;
// } else {
// head = currentPreconditions[0];
// tail = head;
// if(currentPreconditions.length != 1) {
// for(int h = 1; h < currentPreconditions.length; h++) {
// tail.setNext(currentPreconditions[h]);
// tail = currentPreconditions[h];
// }
// }
// tail.setNext(step[0]);
// tail = step[0];
// }
// //iterate over Array and create a queue
// for (int i = 1; i < step.length; i++) {
// //enqueue the Preconditions
// currentPreconditions = step[i].getPreconditions();
// if(currentPreconditions.length != 0) {
// for (int j = 0; j < currentPreconditions.length; j++) {
//
// currentPreconditions[j].makeSettings(tourKey, i + 1, this.getSize(), false, listeners);
// if(j == (currentPreconditions.length -1)) {
// currentPreconditions[j].setNext(step[i]);
// } else {
// currentPreconditions[j].setNext(currentPreconditions[j + 1]);
// }
// }
// }
// // add the current Step to the queue and set the next step
// if(i <= (step.length - 2)) {
// step[i].makeSettings(tourKey, i + 1, this.getSize(), false, listeners);
// nextPreconditions = step[i +1].getPreconditions();
// step[i].setNext(nextPreconditions.length == 0 ? step[i +1] : nextPreconditions[0]);
// } else {
// if(completeWindow){
// step[i].makeSettings(tourKey, i + 1, this.getSize(), false, listeners);
// step[i].setNext(new FinalStep(tourKey));
// step[i].getNext().makeSettings(tourKey, maxSteps, this.getSize(), true, listeners);
// } else {
// step[i].makeSettings(tourKey, maxSteps, this.getSize(), true, listeners);
// }
// }
// }
// }
/**
* Adds a {@link TourListener} to the IntroductoryTour and to all {@link Step}s of the Tour.
* @param listener TourListener
*/
public void addListener(TourListener listener) {
this.listeners.add(listener);
}
/**
*
* @return returns the size of the Tour including the {@link FinalStep} if the flag was set.
*/
public int getSize() {
return (completeWindow ? this.maxSteps +1 : maxSteps);
}
}