Bläddra i källkod

Adds Pooling to Inspector

TomTroppmann 2 år sedan
förälder
incheckning
f30297c3ec
2 ändrade filer med 134 tillägg och 45 borttagningar
  1. 79 45
      src/ui/view/inspector/InspectorTable.java
  2. 55 0
      src/utility/Pool.java

+ 79 - 45
src/ui/view/inspector/InspectorTable.java

@@ -6,7 +6,6 @@ import java.awt.Container;
 import java.awt.Dimension;
 import java.math.RoundingMode;
 import java.text.NumberFormat;
-import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashSet;
 import java.util.List;
@@ -15,7 +14,6 @@ import java.util.Optional;
 import java.util.Set;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
-
 import javax.swing.BorderFactory;
 import javax.swing.Box;
 import javax.swing.BoxLayout;
@@ -39,11 +37,20 @@ import ui.controller.Control;
 import ui.view.component.TrippleCheckBox;
 import ui.view.component.TrippleCheckBox.State;
 import utility.ImageImport;
+import utility.Pool;
 import utility.events.Action;
 import utility.events.SimpleDocumentListener;
 
 public class InspectorTable extends JPanel {
-	private List<ElementRow> elementRows = new ArrayList<ElementRow>();
+	private Pool<ElementRow> rowPool = new Pool<ElementRow>() {
+		@Override
+		public ElementRow create() {
+			return new ElementRow();
+		}
+	};
+	
+	private final int maxDisplayedRowsNumber = 1000;
+	
 	private Control control;
 	private final int columnHeight = 20;
 	//UI
@@ -68,9 +75,12 @@ public class InspectorTable extends JPanel {
 		generateHeader();
 	}
 
+
+
+
 	private void init() {
 		MigLayout layout = new MigLayout("insets 0,gap 0,wrap 7", // Layout Constraints
-				"[][fill, grow][][fill, grow][fill, grow][][]", // Column constraints
+				"[][fill, grow][fill][fill, grow][fill, grow][][fill]", // Column constraints
 				"[25!][20:20:20]"); // Row constraints
 		this.setLayout(layout);
 		initSelectAllCheckBox();
@@ -107,18 +117,14 @@ public class InspectorTable extends JPanel {
 			switch (selectAllCheckBox.getSelectionState()) {
 			case mid_state_selection:
 			case selected: {
-				for (ElementRow row : elementRows) {
-					row.setSelected(false);
-				}
+				rowPool.getBorrowedStream().forEach(row -> row.setSelected(false));
 				duplicateButton.setEnabled(false);
 				deleteButton.setEnabled(false);
 			}
 				break;
 			case unselected:
-				if(!elementRows.isEmpty()) {					
-					for (ElementRow row : elementRows) {
-						row.setSelected(true);
-					}
+				if(rowPool.getBorrowedCount() == 0) {					
+					rowPool.getBorrowedStream().forEach(row -> row.setSelected(true));
 					duplicateButton.setEnabled(true);
 					deleteButton.setEnabled(true);
 				}
@@ -158,11 +164,11 @@ public class InspectorTable extends JPanel {
 		duplicateButton.setIcon(new ImageIcon(ImageImport.loadImage("Images/duplicate.png", 16, 16)));
 		duplicateButton.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
 		duplicateButton.addActionListener(clicked -> {
-			for (ElementRow row : elementRows) {
+			rowPool.getBorrowedStream().forEach(row -> {
 				if(row.isSelected()) {
 					row.element.parentObject.addElement(new HolonElement(row.element));
 				}
-			}
+			});
 			control.calculateStateAndVisualForCurrentTimeStep();
 			update_ui();
 		});
@@ -171,11 +177,11 @@ public class InspectorTable extends JPanel {
 		deleteButton.setIcon(new ImageIcon(ImageImport.loadImage("Images/minus.png", 16, 16)));
 		deleteButton.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
 		deleteButton.addActionListener(clicked -> {
-			for (ElementRow row : elementRows) {
+			rowPool.getBorrowedStream().forEach(row -> {
 				if(row.isSelected()) {
 					row.element.parentObject.removeElement(row.element);
 				}
-			}
+			});
 			control.calculateStateAndVisualForCurrentTimeStep();
 			update_ui();
 		});
@@ -196,19 +202,28 @@ public class InspectorTable extends JPanel {
 		//clone for concurrency
 		Set<AbstractCanvasObject> selection = new HashSet<>(control.getModel().getSelectedObjects());
 		populateRowsThread = new Thread(() -> {
+			 // time passes      
 			List<HolonElement> elementList = extractElements(selection).toList();
+			int numberOfRows = elementList.size();
 			this.removeAll();
-			elementRows.clear();
-			// TODO Pooling
+			rowPool.clear();
 			generateHeader();
 			for(HolonElement element : elementList)
 			{
-				if(abortThread) break;
-				elementRows.add(new ElementRow(element));
-				revalidate();
-				repaint();
+				ElementRow row = rowPool.get();
+				row.setElement(element);
+			}
+			rowPool.getBorrowedStream().limit(maxDisplayedRowsNumber).takeWhile(row -> !abortThread).forEach(row -> {
+				row.addContainerToInspector();
+			});
+			if(numberOfRows > maxDisplayedRowsNumber) {
+				int remaining = elementList.size() - maxDisplayedRowsNumber;
+				JLabel remainingLabel = new JLabel(remaining + " more...");
+				remainingLabel.setForeground(Color.gray);
+				this.add(remainingLabel, "span");
 			}
 			
+			
 			this.add(buttonPanel, "span");
 			boolean isAtLeastOneHolonObjectSelected = 
 					control.getModel().getSelectedObjects().stream().anyMatch(object -> object instanceof HolonObject);
@@ -226,13 +241,13 @@ public class InspectorTable extends JPanel {
 
 
 	private void updateElementSelection() {
-		Set<HolonElement> eleSet = elementRows.stream().filter(ele -> ele.isSelected()).map(row -> row.element).collect(Collectors.toSet());
+		Set<HolonElement> eleSet = rowPool.getBorrowedStream().filter(ele -> ele.isSelected()).map(row -> row.element).collect(Collectors.toSet());
 		this.OnElementSelectionChanged.broadcast(eleSet);
 	}
 
 	private void updateButtonAppearance() {
-		long count = elementRows.stream().filter(ele -> ele.isSelected()).count();
-		if (count == elementRows.size()) {
+		long count = rowPool.getBorrowedStream().filter(ele -> ele.isSelected()).count();
+		if (count == rowPool.getBorrowedCount()) {
 			selectAllCheckBox.setSelectionState(State.selected);
 		} else if (count == 0) {
 			selectAllCheckBox.setSelectionState(State.unselected);
@@ -257,17 +272,24 @@ public class InspectorTable extends JPanel {
 	
 	
 	private class ElementRow {
-		HolonElement element;
+		private HolonElement element = null;
+		private Container[] cellsInRow = new Container[7];
+		//TextBoxes
+		private JTextField elementNameTextField;
 		private JCheckBox selectionBox;
-		Container[] cellsInRow = new Container[7];
-
-		ElementRow(HolonElement element) {
-			this.element = element;
+		private JTextField idObjectTextField;
+		private JFormattedTextField energyTextField;
+		private JComboBox<Priority> comboBox;
+		private JCheckBox activeCheckBox;
+		private JTextField objectNameTextField;
+		
+		
+		
+		public ElementRow() {
 			this.createEditFields();
-			addContainerToInspector();
 		}
 
-		private void addContainerToInspector() {
+		public void addContainerToInspector() {
 			for (Container cell : cellsInRow) {
 				InspectorTable.this.add(cell);
 			}
@@ -285,6 +307,20 @@ public class InspectorTable extends JPanel {
 			return selectionBox.isSelected();
 		}
 
+		public void setElement(HolonElement element) {
+			this.element = element;
+			selectionBox.setSelected(false);
+			objectNameTextField.setText(this.element.parentObject.getName());
+			idObjectTextField.setText(Integer.toString(this.element.parentObject.getId()));
+			elementNameTextField.setText(this.element.getEleName());
+			energyTextField.setValue(this.element.getEnergy());
+			comboBox.setSelectedItem(this.element.getPriority());
+			activeCheckBox.setSelected(this.element.isActive());
+		}
+		
+		
+		
+		
 		private void createEditFields() {
 			// Selected
 			JPanel selectedColumnPanel = new JPanel(new BorderLayout());
@@ -305,20 +341,20 @@ public class InspectorTable extends JPanel {
 			cellsInRow[0] = selectedColumnPanel;
 
 			// ObjectName and ID
-			JTextField objectNameTextField = new JTextField(this.element.parentObject.getName());
+			objectNameTextField = new JTextField();
 			objectNameTextField.getDocument().addDocumentListener((SimpleDocumentListener) e -> {
 				this.element.parentObject.setName(objectNameTextField.getText());
 			});
 			objectNameTextField.addActionListener(ae -> update_ui());
 			cellsInRow[1] = objectNameTextField;
-			JTextField idObjectTextField = new JTextField(Integer.toString(this.element.parentObject.getId()));
+			idObjectTextField = new JTextField();
 			idObjectTextField.setMinimumSize(idObjectTextField.getPreferredSize());
 			idObjectTextField.setBackground(Color.white);
 			idObjectTextField.setEditable(false);
 			idObjectTextField.setEnabled(false);
 			cellsInRow[2] = idObjectTextField;
 			// Name
-			JTextField elementNameTextField = new JTextField(this.element.getEleName());
+			elementNameTextField = new JTextField();
 			elementNameTextField.getDocument().addDocumentListener((SimpleDocumentListener) e -> {
 				this.element.setEleName(elementNameTextField.getText());
 			});
@@ -326,9 +362,9 @@ public class InspectorTable extends JPanel {
 			cellsInRow[3] = elementNameTextField;
 			// Energy
 
-			JFormattedTextField energyTextField = new JFormattedTextField(doubleFormatter);
+			energyTextField = new JFormattedTextField(doubleFormatter);
 			energyTextField.setInputVerifier(getInputVerifier());
-			energyTextField.setValue(this.element.getEnergy());
+			
 			energyTextField.setBackground(Color.white);
 			energyTextField.addPropertyChangeListener(actionEvent -> {
 				try {
@@ -345,8 +381,7 @@ public class InspectorTable extends JPanel {
 			cellsInRow[4] = energyTextField;
 
 			// Priority
-			JComboBox<Priority> comboBox = new JComboBox<Priority>(Priority.values());
-			comboBox.setSelectedItem(this.element.getPriority());
+			comboBox = new JComboBox<Priority>(Priority.values());
 			comboBox.setBackground(Color.white);
 			comboBox.setEditable(false);
 			comboBox.addActionListener(ae -> {
@@ -360,15 +395,14 @@ public class InspectorTable extends JPanel {
 			checkBoxWrapperPanel.setMinimumSize(new Dimension(columnHeight, columnHeight));
 			checkBoxWrapperPanel.setMaximumSize(new Dimension(columnHeight, columnHeight));
 			// Active
-			JCheckBox checkbox = new JCheckBox();
-			checkbox.setSelected(this.element.isActive());
-			checkbox.setBorder(BorderFactory.createEmptyBorder(0, 2, 0, 0));
-			checkbox.setOpaque(false);
-			checkbox.addActionListener(actionEvent -> {
-				this.element.setActive(checkbox.isSelected());
+			activeCheckBox = new JCheckBox();
+			activeCheckBox.setBorder(BorderFactory.createEmptyBorder(0, 2, 0, 0));
+			activeCheckBox.setOpaque(false);
+			activeCheckBox.addActionListener(actionEvent -> {
+				this.element.setActive(activeCheckBox.isSelected());
 				control.calculateStateAndVisualForCurrentTimeStep();
 			});
-			checkBoxWrapperPanel.add(checkbox, BorderLayout.CENTER);
+			checkBoxWrapperPanel.add(activeCheckBox, BorderLayout.CENTER);
 			cellsInRow[6] = checkBoxWrapperPanel;
 		}
 

+ 55 - 0
src/utility/Pool.java

@@ -0,0 +1,55 @@
+package utility;
+
+import java.util.ArrayList;
+import java.util.stream.Stream;
+
+
+
+public abstract class Pool<T> {
+	int borrowedCount = 0;
+	private int poolCapacity = 1000;
+	private ArrayList<T> poolList = new ArrayList<T>(poolCapacity);
+	private ArrayList<T> borrowedList = new ArrayList<T>(poolCapacity);
+	
+	
+	public abstract T create();
+	
+	public Pool(){
+		poppulatePool(poolCapacity);
+	}
+	
+	public T get(){
+		checkCapacity(borrowedCount);
+		T poolObject = poolList.get(borrowedCount);
+		borrowedCount++;
+		borrowedList.add(poolObject);
+		return poolObject;
+	}
+
+	public void clear() {
+		borrowedList.clear();
+		borrowedCount = 0;
+	}
+	
+	
+	private void poppulatePool(int amount) {
+		for(int i= 0; i < amount; i++) {
+			poolList.add(create());
+		}
+	}
+
+	private void checkCapacity(int requestedCapacity) {
+		if(poolCapacity <= requestedCapacity) {
+			int newSize = 2 * requestedCapacity;
+			poppulatePool(newSize - poolCapacity);	
+			poolCapacity = 2*requestedCapacity;
+		}
+	}
+	public int getBorrowedCount() {
+		return borrowedCount;
+	}
+	public Stream<T> getBorrowedStream(){
+		return borrowedList.stream();
+	}
+	
+}