123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523 |
- package holeg.ui.controller;
- import holeg.model.*;
- import holeg.preferences.ImagePreference;
- import holeg.preferences.PreferenceKeys;
- import holeg.serialize.CategoryAdapter;
- import holeg.ui.model.GuiSettings;
- import holeg.ui.model.IdCounter;
- import holeg.ui.model.UndoHistory;
- import holeg.ui.view.category.Category;
- import holeg.ui.view.dialog.CreateTemplatePopUp;
- import holeg.utility.events.Action;
- import holeg.utility.events.Event;
- import holeg.utility.math.vector.Vec2i;
- import javax.swing.*;
- import java.io.File;
- import java.io.FileReader;
- import java.io.FileWriter;
- import java.io.IOException;
- import java.util.*;
- import java.util.logging.Logger;
- import java.util.prefs.Preferences;
- import java.util.stream.Collectors;
- import static holeg.serialize.ModelDeserializer.gson;
- /**
- * The Class represents the controller.
- */
- public class Control {
- private static final Logger log = Logger.getLogger(Control.class.getName());
- private static final Preferences prefs = Preferences.userNodeForPackage(Control.class);
- private final CanvasController canvasController;
- private final SimulationManager simulationManager;
- public Event OnCategoryChanged = new Event();
- public Event OnSelectionChanged = new Event();
- public Event OnCanvasUpdate = new Event();
- public Action<Boolean> OnGuiSetEnabled = new Action<>();
- public Action<GroupNode> OnShowGroupNode = new Action<>();
- public Action<GroupNode> OnRemoveGroupNode = new Action<>();
- public Event OnModelChanged = new Event();
- private Model model;
- public Control(Model model) {
- this.model = model;
- this.canvasController = new CanvasController(this);
- this.simulationManager = new SimulationManager(this);
- OnCanvasUpdate.addListener(() -> UndoHistory.addSave(saveModelToJsonString()));
- UndoHistory.addSave(saveModelToJsonString());
- }
- /* Operations for Categories and Objects */
- /**
- * init default category and objects.
- */
- public void resetCategories() {
- GuiSettings.getCategories().clear();
- initCategories();
- saveCategories();
- }
- /**
- * Gives all Category as String
- *
- * @return a array of strings from all Categorys
- */
- public String[] getCategoriesStrings() {
- return GuiSettings.getCategories().stream().map(Category::getName).toArray(String[]::new);
- }
- /**
- * Add new Holon Object to a Category.
- */
- public void addObject(Category cat, String obj, List<HolonElement> list, String img) {
- addNewHolonObject(cat, obj, list, img);
- OnCategoryChanged.broadcast();
- saveCategories();
- }
- /**
- * Add new Holon Switch to a Category.
- *
- * @param cat Category
- * @param obj New Object Name
- */
- public void addSwitch(Category cat, String obj) {
- addNewHolonSwitch(cat, obj);
- OnCategoryChanged.broadcast();
- saveCategories();
- }
- public void deleteCategory(Category category) {
- removeCategory(category);
- saveCategories();
- }
- /**
- * removes a selectedObject from selection.
- */
- public void removeObjectsFromSelection(Collection<AbstractCanvasObject> objects) {
- if (GuiSettings.getSelectedObjects().removeAll(objects)) {
- OnSelectionChanged.broadcast();
- }
- }
- /**
- * removes a selectedObject from selection.
- *
- * @param obj Cpsobject
- */
- public void removeObjectFromSelection(AbstractCanvasObject obj) {
- if (GuiSettings.getSelectedObjects().remove(obj)) {
- OnSelectionChanged.broadcast();
- }
- }
- public void addObjectToSelection(AbstractCanvasObject obj) {
- if (GuiSettings.getSelectedObjects().add(obj)) {
- OnSelectionChanged.broadcast();
- }
- }
- public void addObjectsToSelection(Collection<AbstractCanvasObject> objects) {
- if (GuiSettings.getSelectedObjects().addAll(objects)) {
- OnSelectionChanged.broadcast();
- }
- }
- public void setSelection(Collection<AbstractCanvasObject> objects) {
- GuiSettings.getSelectedObjects().clear();
- addObjectsToSelection(objects);
- }
- public void clearSelection() {
- if (!GuiSettings.getSelectedObjects().isEmpty()) {
- GuiSettings.getSelectedObjects().clear();
- OnSelectionChanged.broadcast();
- }
- }
- public void addObjectOnCanvas(GroupNode node, AbstractCanvasObject object) {
- canvasController.addObject(node, object);
- updateStateForIteration(model.getCurrentIteration());
- }
- /**
- * Deletes an CpsObject on the Canvas and its connections.
- *
- * @param obj AbstractCpsObject
- */
- public void deleteCanvasObject(AbstractCanvasObject obj) {
- canvasController.deleteObject(obj);
- if (obj instanceof GroupNode groupnode) {
- canvasController.deleteAllObjectsInGroupNode(groupnode);
- }
- calculateStateForCurrentIteration();
- OnCanvasUpdate.broadcast();
- }
- public void deleteCanvasObjects(Collection<AbstractCanvasObject> objects) {
- canvasController.deleteObjects(objects);
- calculateStateForCurrentIteration();
- OnCanvasUpdate.broadcast();
- }
- /**
- * Replaces {@code toBeReplaced} by {@code by} on the canvas
- *
- * @param toBeReplaced the object that will be replaced
- * @param by the object that will replace it
- */
- public void replaceCanvasObject(AbstractCanvasObject toBeReplaced, AbstractCanvasObject by) {
- canvasController.replaceObject(toBeReplaced, by);
- OnCanvasUpdate.broadcast();
- }
- /**
- * Add an edge to the Canvas.
- *
- * @param edge the edge
- */
- public boolean addEdgeOnCanvas(Edge edge) {
- if (doesEdgeExist(edge)) {
- return false;
- }
- canvasController.addEdgeOnCanvas(edge);
- OnCanvasUpdate.broadcast();
- return true;
- }
- public boolean doesEdgeExist(Edge edge){
- boolean connectsToSelf = edge.getA() == edge.getB();
- return !connectsToSelf && model.getEdgesOnCanvas().stream().anyMatch(e -> (e.getA() == edge.getA() && e.getB() == edge.getB())
- || (e.getB() == edge.getA() && e.getA() == edge.getB()));
- }
- /**
- * Add an edge to the Canvas.
- *
- * @param edge the edge
- */
- public void addEdgeOnCanvasOrRemoveExisting(Edge edge) {
- boolean connectsToSelf = edge.getA() == edge.getB();
- if(connectsToSelf){
- return;
- }
- Optional<Edge> edgeToRemove = model.getEdgesOnCanvas().stream().filter(e -> (e.getA() == edge.getA() && e.getB() == edge.getB())
- || (e.getB() == edge.getA() && e.getA() == edge.getB())).findAny();
- edgeToRemove.ifPresentOrElse(canvasController::removeEdgesOnCanvas, () -> canvasController.addEdgeOnCanvas(edge));
- updateStateForCurrentIteration();
- }
- /**
- * Removes an Edge from the Canvas.
- *
- * @param edge the edge to remove
- */
- public void removeEdgesOnCanvas(Edge edge) {
- canvasController.removeEdgesOnCanvas(edge);
- OnCanvasUpdate.broadcast();
- }
- public void calculateStateForCurrentIteration() {
- simulationManager.calculateStateForIteration(model.getCurrentIteration());
- }
- public void updateStateForCurrentIteration() {
- simulationManager.calculateStateForIteration(model.getCurrentIteration());
- OnCanvasUpdate.broadcast();
- }
- /**
- * calculates the flow of the edges and the supply for objects.
- *
- * @param x current Iteration
- */
- public void updateStateForIteration(int x) {
- simulationManager.calculateStateForIteration(x);
- OnCanvasUpdate.broadcast();
- }
- /**
- * resets the whole State of the simulation including a reset of all Edges to
- * the default "is working" state
- */
- public void resetSimulation() {
- model.reset();
- }
- /**
- * Getter for Model.
- *
- * @return the Model
- */
- public Model getModel() {
- return model;
- }
- public void replaceObject(AbstractCanvasObject toBeReplaced, AbstractCanvasObject by) {
- canvasController.replaceObject(toBeReplaced, by);
- }
- /**
- * Copy all Selected Objects.
- */
- public void copy() {
- GuiSettings.getClipboardObjects().clear();
- GuiSettings.getClipboardObjects().addAll(GuiSettings.getSelectedObjects());
- }
- public void paste(GroupNode groupNode, Vec2i offset) {
- if (GuiSettings.getClipboardObjects().isEmpty()) {
- return;
- }
- Set<AbstractCanvasObject> copies = GuiSettings.getClipboardObjects().stream().map(AbstractCanvasObject::copy).collect(Collectors.toSet());
- copies.forEach(obj -> {
- obj.getPosition().addAssign(offset);
- obj.getPosition().clampX(0, GuiSettings.canvasSize.getX());
- obj.getPosition().clampY(0, GuiSettings.canvasSize.getY());
- });
- groupNode.addAll(copies);
- updateStateForIteration(model.getCurrentIteration());
- OnSelectionChanged.broadcast();
- }
- public void cut() {
- copy();
- deleteCanvasObjects(GuiSettings.getSelectedObjects());
- clearSelection();
- }
- public void guiSetEnabled(boolean state) {
- OnGuiSetEnabled.broadcast(state);
- }
- /**
- * init default category and objects.
- */
- private void initCategories() {
- Category energy = createCategoryWithName("Energy");
- Category building = createCategoryWithName("Building");
- Category component = createCategoryWithName("Component");
- HolonObject powerPlant = addNewHolonObject(energy, "Power Plant", new ArrayList<>(),
- ImagePreference.Canvas.DefaultObject.PowerPlant);
- HolonObject house = addNewHolonObject(building, "House", new ArrayList<>(), ImagePreference.Canvas.DefaultObject.House);
- addNewHolonSwitch(component, "Switch");
- powerPlant.add(new HolonElement(null, "Power", 10000));
- energy.getObjects().add(powerPlant);
- house.add(new HolonElement(null, "TV", -250));
- house.add(new HolonElement(null, "TV", -250));
- house.add(new HolonElement(null, "Fridge", -500));
- house.add(new HolonElement(null, "Radio", -100));
- house.add(new HolonElement(null, "PC", -250));
- house.add(new HolonElement(null, "PC", -250));
- house.add(new HolonElement(null, "PC", -250));
- house.add(new HolonElement(null, "Light", -50));
- house.add(new HolonElement(null, "Light", -50));
- house.add(new HolonElement(null, "Light", -50));
- house.add(new HolonElement(null, "Light", -50));
- house.add(new HolonElement(null, "Light", -50));
- house.add(new HolonElement(null, "Solar Panel", 300));
- building.getObjects().add(house);
- OnCategoryChanged.broadcast();
- }
- public Category createCategoryWithName(String categoryName) {
- Optional<Category> category = findCategoryWithName(categoryName);
- if (category.isEmpty()) {
- Category cat = new Category(categoryName);
- GuiSettings.getCategories().add(cat);
- OnCategoryChanged.broadcast();
- return cat;
- } else {
- return category.get();
- }
- }
- /**
- * remove a Category from Model.
- *
- * @param c Category
- */
- public void removeCategory(Category c) {
- GuiSettings.getCategories().remove(c);
- OnCategoryChanged.broadcast();
- }
- /**
- * Add Object into a Category.
- *
- * @param category Category
- * @param object Object
- */
- public void addObject(Category category, AbstractCanvasObject object) {
- int i = 0;
- while (category.findObjectWithName(object.getName()).isPresent()) {
- if (object.getName().contains("_"))
- object.setName(object.getName().substring(0, object.getName().indexOf('_')));
- object.setName(object.getName() + "_" + i);
- i++;
- }
- category.getObjects().add(object);
- }
- /**
- * Add new Holon Object to a Category.
- *
- * @param category Category
- * @param object New Object Name
- * @param list Array of Elements
- * @param image the image Path
- */
- public HolonObject addNewHolonObject(Category category, String object, List<HolonElement> list, String image) {
- HolonObject obj = new HolonObject(object);
- obj.setImagePath(image);
- obj.clearElements();
- obj.add(list);
- addObject(category, obj);
- return obj;
- }
- public HolonSwitch addNewHolonSwitch(Category cat, String objName) {
- HolonSwitch holonSwitch = new HolonSwitch(objName);
- addObject(cat, holonSwitch);
- return holonSwitch;
- }
- public Optional<Category> findCategoryWithName(String categoryName) {
- return GuiSettings.getCategories().stream().filter(cat -> cat.getName().equals(categoryName)).findAny();
- }
- public void loadFile(File file) {
- log.info("load" + file);
- try {
- FileReader reader = new FileReader(file);
- Model model = gson.fromJson(reader, Model.class);
- reader.close();
- this.model = model;
- calculateStateForCurrentIteration();
- OnModelChanged.broadcast();
- } catch (IOException e) {
- log.warning(e.getLocalizedMessage());
- }
- clearSelection();
- GuiSettings.setActualSaveFile(file);
- }
- public void loadModelFromJsonString(String json){
- this.model = gson.fromJson(json, Model.class);
- calculateStateForCurrentIteration();
- OnModelChanged.broadcast();
- }
- public String saveModelToJsonString(){
- return gson.toJson(model);
- }
- public void toggleSelectedObjects(Collection<AbstractCanvasObject> objects) {
- Set<AbstractCanvasObject> intersection = new HashSet<>(objects);
- intersection.retainAll(GuiSettings.getSelectedObjects());
- GuiSettings.getSelectedObjects().addAll(objects);
- GuiSettings.getSelectedObjects().removeAll(intersection);
- OnSelectionChanged.broadcast();
- }
- public void saveFile(File file) {
- log.info("save" + file);
- try {
- FileWriter writer = new FileWriter(file);
- gson.toJson(model, writer);
- writer.close();
- } catch (IOException e) {
- log.warning(e.getLocalizedMessage());
- }
- GuiSettings.setActualSaveFile(file);
- }
- public void group() {
- canvasController.group(GuiSettings.getSelectedObjects());
- clearSelection();
- OnCanvasUpdate.broadcast();
- }
- public void ungroup() {
- canvasController.ungroup(GuiSettings.getSelectedObjects());
- clearSelection();
- OnCanvasUpdate.broadcast();
- }
- public void undo(){
- UndoHistory.undo().ifPresent(this::loadModelFromJsonString);
- }
- public void redo(){
- UndoHistory.redo().ifPresent(this::loadModelFromJsonString);
- }
- public void clearModel() {
- model.clear();
- clearSelection();
- model.setCurrentIteration(0);
- IdCounter.reset();
- calculateStateForCurrentIteration();
- OnModelChanged.broadcast();
- GuiSettings.setActualSaveFile(null);
- }
- public void showGroupNode(GroupNode groupNode) {
- OnShowGroupNode.broadcast(groupNode);
- clearSelection();
- }
- public void loadCategory(){
- String json = prefs.get(PreferenceKeys.Category.DefaultCategory, "Init");
- if(json.equals("Init")){
- initCategories();
- return;
- }
- GuiSettings.getCategories().clear();
- GuiSettings.getCategories().addAll(CategoryAdapter.Gson.fromJson(json, CategoryAdapter.CategorySet));
- OnCategoryChanged.broadcast();
- }
- public void saveCategories(){
- String json = CategoryAdapter.Gson.toJson(GuiSettings.getCategories());
- prefs.put(PreferenceKeys.Category.DefaultCategory, json);
- }
- }
|