<commit_before>package dynamake.tools;

import java.awt.Component;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JComponent;
import javax.swing.SwingUtilities;

import dynamake.commands.DualCommand;
import dynamake.commands.DualCommandPair;
import dynamake.commands.UnwrapToLocationsTransaction;
import dynamake.commands.WrapTransaction;
import dynamake.models.CanvasModel;
import dynamake.models.Location;
import dynamake.models.Model;
import dynamake.models.ModelComponent;
import dynamake.models.ModelLocation;
import dynamake.models.LiveModel.ProductionPanel;
import dynamake.models.factories.CanvasModelFactory;
import dynamake.models.factories.Factory;
import dynamake.transcription.DualCommandFactory;
import dynamake.transcription.Collector;
import dynamake.transcription.Connection;

public class PlotTool implements Tool {
	@Override
	public String getName() {
		return "Plot";
	}

	@Override
	public void mouseMoved(ProductionPanel productionPanel, MouseEvent e, ModelComponent modelOver, Connection<Model> connection, Collector<Model> collector) {

	}

	@Override
	public void mouseExited(ProductionPanel productionPanel, MouseEvent e, Connection<Model> connection, Collector<Model> collector) {

	}

	@Override
	public void mouseReleased(final ProductionPanel productionPanel, MouseEvent e, ModelComponent modelOver, Connection<Model> connection, Collector<Model> collector) {
		if(mouseDown != null) {
			final Rectangle creationBoundsInProductionPanel = interactionPresenter.getPlotBounds(mouseDown, e.getPoint());
			final Rectangle creationBoundsInSelection = SwingUtilities.convertRectangle(productionPanel, creationBoundsInProductionPanel, interactionPresenter.getSelectionFrame());
			
			// Find components within the creation bounds of the selection
			final ArrayList<ModelComponent> componentsWithinBounds = new ArrayList<ModelComponent>();
			for(Component c: ((JComponent)interactionPresenter.getSelection()).getComponents()) {
				if(creationBoundsInSelection.contains(c.getBounds())) {
					// Add in reverse order because views are positioned in the reverse order in the CanvasModel
					// This way, the views are sorted ascending index-wise
					componentsWithinBounds.add(0, (ModelComponent)c);
				}
			}

			if(interactionPresenter.getSelection().getModelBehind() instanceof CanvasModel) {
				final ModelComponent selection = interactionPresenter.getSelection();
				// Wrap if one more models are contained within the effect frame
				if(componentsWithinBounds.size() > 0) {
					collector.execute(new DualCommandFactory<Model>() {
						@Override
						public void createDualCommands(List<DualCommand<Model>> dualCommands) {
							CanvasModel target = (CanvasModel)selection.getModelBehind();
							Location targetLocation = selection.getModelTranscriber().getModelLocation();
							int indexOfWrapper = target.getModelCount() - componentsWithinBounds.size();
							ModelLocation wrapperLocationInTarget = new CanvasModel.IndexLocation(indexOfWrapper);
							
							// Each of the model locations should be moved from target to wrapper
							Location[] modelLocations = new Location[componentsWithinBounds.size()];
							int[] modelIndexes = new int[componentsWithinBounds.size()];
							for(int i = 0; i < modelLocations.length; i++) {
								ModelComponent view = componentsWithinBounds.get(i);
								modelLocations[i] = view.getModelTranscriber().getModelLocation();
								modelIndexes[i] = target.indexOfModel(view.getModelBehind());
							}
							
							dualCommands.add(new DualCommandPair<Model>(
								new WrapTransaction(targetLocation, creationBoundsInSelection, modelLocations), 
								new UnwrapToLocationsTransaction(targetLocation, wrapperLocationInTarget, modelIndexes, creationBoundsInSelection)
							));
						}
					});
				} else {
					final Factory factory = new CanvasModelFactory();
					
					collector.execute(new DualCommandFactory<Model>() {
						@Override
						public void createDualCommands(List<DualCommand<Model>> dualCommands) {
							ModelComponent target = selection;
							
							CanvasModel canvasModel = (CanvasModel)target.getModelBehind();
							Location canvasModelLocation = target.getModelTranscriber().getModelLocation();
							int index = canvasModel.getModelCount();
							
							dualCommands.add(new DualCommandPair<Model>(
								new CanvasModel.AddModelTransaction(canvasModelLocation, creationBoundsInSelection, factory), 
								new CanvasModel.RemoveModelTransaction(canvasModelLocation, index) // Relative location
							));
						}
					});
				}
			}

			interactionPresenter.reset(collector);
			interactionPresenter = null;
			
			collector.commit();
			
			mouseDown = null;
		}
	}
	
	private Point mouseDown;
	private InteractionPresenter interactionPresenter;

	@Override
	public void mousePressed(final ProductionPanel productionPanel, final MouseEvent e, ModelComponent modelOver, Connection<Model> connection, Collector<Model> collector) {
		if(modelOver.getModelBehind() instanceof CanvasModel) {
			mouseDown = e.getPoint();
			Point referencePoint = SwingUtilities.convertPoint((JComponent)e.getSource(), e.getPoint(), (JComponent)modelOver);
			
			interactionPresenter = new InteractionPresenter(productionPanel);
			interactionPresenter.selectFromEmpty(modelOver, referencePoint, collector);
		}
	}

	@Override
	public void mouseDragged(final ProductionPanel productionPanel, final MouseEvent e, ModelComponent modelOver, Collector<Model> collector, Connection<Model> connection) {
		if(mouseDown != null) {
			final Rectangle plotBoundsInProductionPanel = interactionPresenter.getPlotBounds(mouseDown, e.getPoint());
			
			interactionPresenter.changeEffectFrameDirect2(plotBoundsInProductionPanel, collector);
		}
	}

	@Override
	public void paint(Graphics g) {

	}

	@Override
	public void rollback(ProductionPanel productionPanel, Collector<Model> collector) {
		interactionPresenter.reset(collector);
		interactionPresenter = null;
	}
}<commit_msg>Added proper handling of rollback in plot tool. Before, an null exception was simply printed. Now, a test has been added in rollback of plot tool to ensure that exception is not provoked.<commit_after>package dynamake.tools;

import java.awt.Component;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JComponent;
import javax.swing.SwingUtilities;

import dynamake.commands.DualCommand;
import dynamake.commands.DualCommandPair;
import dynamake.commands.UnwrapToLocationsTransaction;
import dynamake.commands.WrapTransaction;
import dynamake.models.CanvasModel;
import dynamake.models.Location;
import dynamake.models.Model;
import dynamake.models.ModelComponent;
import dynamake.models.ModelLocation;
import dynamake.models.LiveModel.ProductionPanel;
import dynamake.models.factories.CanvasModelFactory;
import dynamake.models.factories.Factory;
import dynamake.transcription.DualCommandFactory;
import dynamake.transcription.Collector;
import dynamake.transcription.Connection;

public class PlotTool implements Tool {
	@Override
	public String getName() {
		return "Plot";
	}

	@Override
	public void mouseMoved(ProductionPanel productionPanel, MouseEvent e, ModelComponent modelOver, Connection<Model> connection, Collector<Model> collector) {

	}

	@Override
	public void mouseExited(ProductionPanel productionPanel, MouseEvent e, Connection<Model> connection, Collector<Model> collector) {

	}

	@Override
	public void mouseReleased(final ProductionPanel productionPanel, MouseEvent e, ModelComponent modelOver, Connection<Model> connection, Collector<Model> collector) {
		if(mouseDown != null) {
			final Rectangle creationBoundsInProductionPanel = interactionPresenter.getPlotBounds(mouseDown, e.getPoint());
			final Rectangle creationBoundsInSelection = SwingUtilities.convertRectangle(productionPanel, creationBoundsInProductionPanel, interactionPresenter.getSelectionFrame());
			
			// Find components within the creation bounds of the selection
			final ArrayList<ModelComponent> componentsWithinBounds = new ArrayList<ModelComponent>();
			for(Component c: ((JComponent)interactionPresenter.getSelection()).getComponents()) {
				if(creationBoundsInSelection.contains(c.getBounds())) {
					// Add in reverse order because views are positioned in the reverse order in the CanvasModel
					// This way, the views are sorted ascending index-wise
					componentsWithinBounds.add(0, (ModelComponent)c);
				}
			}

			if(interactionPresenter.getSelection().getModelBehind() instanceof CanvasModel) {
				final ModelComponent selection = interactionPresenter.getSelection();
				// Wrap if one more models are contained within the effect frame
				if(componentsWithinBounds.size() > 0) {
					collector.execute(new DualCommandFactory<Model>() {
						@Override
						public void createDualCommands(List<DualCommand<Model>> dualCommands) {
							CanvasModel target = (CanvasModel)selection.getModelBehind();
							Location targetLocation = selection.getModelTranscriber().getModelLocation();
							int indexOfWrapper = target.getModelCount() - componentsWithinBounds.size();
							ModelLocation wrapperLocationInTarget = new CanvasModel.IndexLocation(indexOfWrapper);
							
							// Each of the model locations should be moved from target to wrapper
							Location[] modelLocations = new Location[componentsWithinBounds.size()];
							int[] modelIndexes = new int[componentsWithinBounds.size()];
							for(int i = 0; i < modelLocations.length; i++) {
								ModelComponent view = componentsWithinBounds.get(i);
								modelLocations[i] = view.getModelTranscriber().getModelLocation();
								modelIndexes[i] = target.indexOfModel(view.getModelBehind());
							}
							
							dualCommands.add(new DualCommandPair<Model>(
								new WrapTransaction(targetLocation, creationBoundsInSelection, modelLocations), 
								new UnwrapToLocationsTransaction(targetLocation, wrapperLocationInTarget, modelIndexes, creationBoundsInSelection)
							));
						}
					});
				} else {
					final Factory factory = new CanvasModelFactory();
					
					collector.execute(new DualCommandFactory<Model>() {
						@Override
						public void createDualCommands(List<DualCommand<Model>> dualCommands) {
							ModelComponent target = selection;
							
							CanvasModel canvasModel = (CanvasModel)target.getModelBehind();
							Location canvasModelLocation = target.getModelTranscriber().getModelLocation();
							int index = canvasModel.getModelCount();
							
							dualCommands.add(new DualCommandPair<Model>(
								new CanvasModel.AddModelTransaction(canvasModelLocation, creationBoundsInSelection, factory), 
								new CanvasModel.RemoveModelTransaction(canvasModelLocation, index) // Relative location
							));
						}
					});
				}
			}

			interactionPresenter.reset(collector);
			interactionPresenter = null;
			
			collector.commit();
			
			mouseDown = null;
		}
	}
	
	private Point mouseDown;
	private InteractionPresenter interactionPresenter;

	@Override
	public void mousePressed(final ProductionPanel productionPanel, final MouseEvent e, ModelComponent modelOver, Connection<Model> connection, Collector<Model> collector) {
		if(modelOver.getModelBehind() instanceof CanvasModel) {
			mouseDown = e.getPoint();
			Point referencePoint = SwingUtilities.convertPoint((JComponent)e.getSource(), e.getPoint(), (JComponent)modelOver);
			
			interactionPresenter = new InteractionPresenter(productionPanel);
			interactionPresenter.selectFromEmpty(modelOver, referencePoint, collector);
		}
	}

	@Override
	public void mouseDragged(final ProductionPanel productionPanel, final MouseEvent e, ModelComponent modelOver, Collector<Model> collector, Connection<Model> connection) {
		if(mouseDown != null) {
			final Rectangle plotBoundsInProductionPanel = interactionPresenter.getPlotBounds(mouseDown, e.getPoint());
			
			interactionPresenter.changeEffectFrameDirect2(plotBoundsInProductionPanel, collector);
		}
	}

	@Override
	public void paint(Graphics g) {

	}

	@Override
	public void rollback(ProductionPanel productionPanel, Collector<Model> collector) {
		if(mouseDown != null) {
			interactionPresenter.reset(collector);
			interactionPresenter = null;
		}
	}
}
{'fraction_non_alphanumeric': 0.08658321296742096, 'fraction_numerical': 0.0006419515326592842, 'mean_word_length': 5.023682938617689, 'pattern_counts': {'":': 0, '<': 47, '<?xml version=': 0, '>': 47, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '513232', 'n_tokens_mistral': 3947, 'n_tokens_neox': 3198, 'n_words': 750}