Control.java 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483
  1. package holeg.ui.controller;
  2. import com.google.gson.Gson;
  3. import com.google.gson.GsonBuilder;
  4. import holeg.adapter.EdgeSerializer;
  5. import holeg.adapter.ModelDeserializer;
  6. import holeg.model.*;
  7. import holeg.preferences.ImagePreference;
  8. import holeg.ui.model.GuiSettings;
  9. import holeg.ui.model.IdCounter;
  10. import holeg.ui.view.dialog.CreateTemplatePopUp;
  11. import holeg.ui.view.category.Category;
  12. import holeg.utility.events.Action;
  13. import holeg.utility.events.Event;
  14. import holeg.utility.math.vector.Vec2i;
  15. import javax.swing.*;
  16. import java.io.File;
  17. import java.io.FileReader;
  18. import java.io.FileWriter;
  19. import java.io.IOException;
  20. import java.util.*;
  21. import java.util.logging.Logger;
  22. /**
  23. * The Class represents the controller.
  24. */
  25. public class Control {
  26. private static final Logger log = Logger.getLogger(Control.class.getName());
  27. private final CanvasController canvasController;
  28. private Model model;
  29. private final SimulationManager simulationManager;
  30. public Event OnCategoryChanged = new Event();
  31. public Event OnSelectionChanged = new Event();
  32. public Event OnCanvasUpdate = new Event();
  33. public Action<Boolean> OnGuiSetEnabled = new Action<>();
  34. public Control(Model model) {
  35. this.model = model;
  36. this.canvasController = new CanvasController(this);
  37. this.simulationManager = new SimulationManager(this);
  38. }
  39. /* Operations for Categories and Objects */
  40. /**
  41. * init default category and objects.
  42. */
  43. public void resetCategories() {
  44. clearCategories();
  45. initCategories();
  46. saveCategory();
  47. }
  48. /**
  49. * Gives all Category as String
  50. *
  51. * @return a array of strings from all Categorys
  52. */
  53. public String[] getCategoriesStrings() {
  54. return GuiSettings.getCategories().stream().map(Category::getName).toArray(String[]::new);
  55. }
  56. /**
  57. * Add new Holon Object to a Category.
  58. */
  59. public void addObject(Category cat, String obj, List<HolonElement> list, String img) {
  60. addNewHolonObject(cat, obj, list, img);
  61. saveCategory();
  62. }
  63. /**
  64. * Add new Holon Switch to a Category.
  65. *
  66. * @param cat Category
  67. * @param obj New Object Name
  68. */
  69. public void addSwitch(Category cat, String obj) {
  70. addNewHolonSwitch(cat, obj);
  71. saveCategory();
  72. }
  73. public void deleteCategory(Category category) {
  74. removeCategory(category);
  75. saveCategory();
  76. }
  77. /**
  78. * removes a selectedObject from selection.
  79. */
  80. public void removeObjectsFromSelection(Collection<AbstractCanvasObject> objects) {
  81. if (GuiSettings.getSelectedObjects().removeAll(objects)) {
  82. OnSelectionChanged.broadcast();
  83. }
  84. }
  85. /**
  86. * removes a selectedObject from selection.
  87. *
  88. * @param obj Cpsobject
  89. */
  90. public void removeObjectFromSelection(AbstractCanvasObject obj) {
  91. if (GuiSettings.getSelectedObjects().remove(obj)) {
  92. OnSelectionChanged.broadcast();
  93. }
  94. }
  95. public void addSelectedObject(AbstractCanvasObject obj) {
  96. if (GuiSettings.getSelectedObjects().add(obj)) {
  97. OnSelectionChanged.broadcast();
  98. }
  99. }
  100. public void addSelectedObjects(Collection<AbstractCanvasObject> objects) {
  101. if (GuiSettings.getSelectedObjects().addAll(objects)) {
  102. OnSelectionChanged.broadcast();
  103. }
  104. }
  105. public void clearSelection() {
  106. if (!GuiSettings.getSelectedObjects().isEmpty()) {
  107. GuiSettings.getSelectedObjects().clear();
  108. OnSelectionChanged.broadcast();
  109. }
  110. }
  111. /**
  112. * This method is primarily for the multi-selection. It adds unselected objects
  113. * to the selection and Removes selected objects from the selection. Like the
  114. * normal OS Desktop selection.
  115. *
  116. * @param objects
  117. */
  118. public void toggleSelectedObjects(Collection<AbstractCanvasObject> objects) {
  119. Set<AbstractCanvasObject> intersection = new HashSet<>(objects);
  120. intersection.retainAll(GuiSettings.getSelectedObjects());
  121. GuiSettings.getSelectedObjects().addAll(objects);
  122. GuiSettings.getSelectedObjects().removeAll(intersection);
  123. OnSelectionChanged.broadcast();
  124. }
  125. /* Operations for Canvas */
  126. /**
  127. * Add a new Object.
  128. *
  129. * @param object the Object
  130. */
  131. public void addObjectCanvas(GroupNode node, AbstractCanvasObject object) {
  132. canvasController.addObject(node, object);
  133. calculateStateAndVisualForTimeStep(model.getCurrentIteration());
  134. }
  135. /**
  136. * Deletes an CpsObject on the Canvas and its connections.
  137. *
  138. * @param obj AbstractCpsObject
  139. */
  140. public void deleteCanvasObject(AbstractCanvasObject obj) {
  141. canvasController.deleteObject(obj);
  142. if (obj instanceof GroupNode groupnode) {
  143. canvasController.deleteAllObjectsInGroupNode(groupnode);
  144. }
  145. calculateStateAndVisualForCurrentTimeStep();
  146. }
  147. public void deleteCanvasObjects(Collection<AbstractCanvasObject> objects) {
  148. canvasController.deleteObjects(objects);
  149. calculateStateAndVisualForCurrentTimeStep();
  150. }
  151. /**
  152. * Replaces {@code toBeReplaced} by {@code by} on the canvas
  153. *
  154. * @param toBeReplaced the object that will be replaced
  155. * @param by the object that will replace it
  156. */
  157. public void replaceCanvasObject(AbstractCanvasObject toBeReplaced, AbstractCanvasObject by) {
  158. canvasController.replaceObject(toBeReplaced, by);
  159. }
  160. /**
  161. * Add an edge to the Canvas.
  162. *
  163. * @param edge the edge
  164. */
  165. public boolean addEdgeOnCanvas(Edge edge) {
  166. boolean connectsItSelf = edge.getA() == edge.getB();
  167. boolean connectionExist = model.getEdgesOnCanvas().stream().anyMatch(e -> (e.getA() == edge.getA() && e.getB() == edge.getB())
  168. || (e.getB() == edge.getA() && e.getA() == edge.getB()));
  169. if (connectsItSelf || connectionExist) {
  170. return false;
  171. }
  172. canvasController.addEdgeOnCanvas(edge);
  173. return true;
  174. }
  175. /**
  176. * Removes an Edge from the Canvas.
  177. *
  178. * @param edge the edge to remove
  179. */
  180. public void removeEdgesOnCanvas(Edge edge) {
  181. canvasController.removeEdgesOnCanvas(edge);
  182. }
  183. /**
  184. * calculates the flow of the edges and the supply for objects for the current
  185. * Timestep.
  186. */
  187. public void calculateStateAndVisualForCurrentTimeStep() {
  188. calculateStateAndVisualForTimeStep(model.getCurrentIteration());
  189. }
  190. public void calculateStateOnlyForCurrentTimeStep() {
  191. calculateStateForTimeStep(model.getCurrentIteration());
  192. }
  193. /**
  194. * calculates the flow of the edges and the supply for objects.
  195. *
  196. * @param x current Iteration
  197. */
  198. public void calculateStateAndVisualForTimeStep(int x) {
  199. simulationManager.calculateStateForTimeStep(x);
  200. log.info("OnCanvasUpdate");
  201. OnCanvasUpdate.broadcast();
  202. }
  203. /**
  204. * calculates the flow of the edges and the supply for objects.
  205. *
  206. * @param x current Iteration
  207. */
  208. public void calculateStateForTimeStep(int x) {
  209. simulationManager.calculateStateForTimeStep(x);
  210. }
  211. /**
  212. * resets the whole State of the simulation including a reset of all Edges to
  213. * the default "is working" state
  214. */
  215. public void resetSimulation() {
  216. model.reset();
  217. }
  218. public void saveCategory() {
  219. //TODO(Tom2022-01-27):
  220. }
  221. /**
  222. * Getter for Model.
  223. *
  224. * @return the Model
  225. */
  226. public Model getModel() {
  227. return model;
  228. }
  229. public void replaceObject(AbstractCanvasObject toBeReplaced, AbstractCanvasObject by) {
  230. canvasController.replaceObject(toBeReplaced, by);
  231. }
  232. /**
  233. * Copy all Selected Objects.
  234. */
  235. public void copy(GroupNode upperNode) {
  236. //TODO(Tom2022-01-27):
  237. }
  238. public void paste(GroupNode upperNode, Vec2i point) {
  239. //TODO(Tom2022-01-27):
  240. OnSelectionChanged.broadcast();
  241. }
  242. public void cut(GroupNode upperNode) {
  243. //TODO(Tom2022-01-27):
  244. OnSelectionChanged.broadcast();
  245. }
  246. /**
  247. * creates a new Template for the given cps Object
  248. *
  249. * @param cps Object, which should become a template
  250. * @param parentFrame
  251. */
  252. public void createTemplate(HolonObject cps, JFrame parentFrame) {
  253. CreateTemplatePopUp t = new CreateTemplatePopUp(cps, model, parentFrame, this);
  254. t.setVisible(true);
  255. }
  256. public void guiSetEnabled(boolean state) {
  257. log.info("guiDisabled");
  258. OnGuiSetEnabled.broadcast(state);
  259. }
  260. /**
  261. * init default category and objects.
  262. */
  263. public void initCategories() {
  264. Category energy = createCategoryWithName("Energy");
  265. Category building = createCategoryWithName("Building");
  266. Category component = createCategoryWithName("Component");
  267. HolonObject powerPlant = addNewHolonObject(energy, "Power Plant", new ArrayList<>(),
  268. ImagePreference.Canvas.DefaultObject.PowerPlant);
  269. HolonObject house = addNewHolonObject(building, "House", new ArrayList<>(), ImagePreference.Canvas.DefaultObject.House);
  270. addNewHolonSwitch(component, "Switch");
  271. powerPlant.add(new HolonElement(null, "Power", 10000));
  272. energy.getObjects().add(powerPlant);
  273. house.add(new HolonElement(null, "TV", -250));
  274. house.add(new HolonElement(null, "TV", -250));
  275. house.add(new HolonElement(null, "Fridge", -500));
  276. house.add(new HolonElement(null, "Radio", -100));
  277. house.add(new HolonElement(null, "PC", -250));
  278. house.add(new HolonElement(null, "PC", -250));
  279. house.add(new HolonElement(null, "PC", -250));
  280. house.add(new HolonElement(null, "Light", -50));
  281. house.add(new HolonElement(null, "Light", -50));
  282. house.add(new HolonElement(null, "Light", -50));
  283. house.add(new HolonElement(null, "Light", -50));
  284. house.add(new HolonElement(null, "Light", -50));
  285. house.add(new HolonElement(null, "Solar Panel", 300));
  286. building.getObjects().add(house);
  287. OnCategoryChanged.broadcast();
  288. }
  289. public Category createCategoryWithName(String categoryName) {
  290. Optional<Category> category = findCategoryWithName(categoryName);
  291. if(category.isEmpty()) {
  292. Category cat = new Category(categoryName);
  293. GuiSettings.getCategories().add(cat);
  294. OnCategoryChanged.broadcast();
  295. return cat;
  296. }else {
  297. return category.get();
  298. }
  299. }
  300. /**
  301. * remove a Category from Model.
  302. *
  303. * @param c
  304. * Category
  305. */
  306. public void removeCategory(Category c) {
  307. GuiSettings.getCategories().remove(c);
  308. OnCategoryChanged.broadcast();
  309. }
  310. public void clearCategories() {
  311. GuiSettings.getCategories().clear();
  312. }
  313. /**
  314. * Add Object into a Category.
  315. *
  316. * @param category
  317. * Category
  318. * @param object
  319. * Object
  320. */
  321. public void addObject(Category category, AbstractCanvasObject object) {
  322. int i = 0;
  323. //TODO(Tom2021-12-1) remove/redo this search
  324. while (category.findObjectWithName(object.getName()).isPresent()) {
  325. if (object.getName().contains("_"))
  326. object.setName(object.getName().substring(0, object.getName().indexOf('_')));
  327. object.setName(object.getName() + "_" + i);
  328. i++;
  329. }
  330. category.getObjects().add(object);
  331. }
  332. /**
  333. * Add new Holon Object to a Category.
  334. *
  335. * @param category
  336. * Category
  337. * @param object
  338. * New Object Name
  339. * @param list
  340. * Array of Elements
  341. * @param image
  342. * the image Path
  343. */
  344. public HolonObject addNewHolonObject(Category category, String object, List<HolonElement> list, String image) {
  345. HolonObject obj = new HolonObject(object);
  346. obj.setImagePath(image);
  347. obj.clearElements();
  348. obj.add(list);
  349. addObject(category, obj);
  350. return obj;
  351. }
  352. public HolonSwitch addNewHolonSwitch(Category cat, String objName) {
  353. HolonSwitch holonSwitch = new HolonSwitch(objName);
  354. addObject(cat, holonSwitch);
  355. return holonSwitch;
  356. }
  357. /**
  358. * Removes an Object from a Category.
  359. * @param category Category
  360. * @param cps the Object
  361. */
  362. public void removeObject(Category category, AbstractCanvasObject cps) {
  363. category.getObjects().remove(cps);
  364. OnCategoryChanged.broadcast();
  365. }
  366. public Optional<Category> findCategoryWithName(String categoryName) {
  367. return GuiSettings.getCategories().stream().filter(cat -> cat.getName().equals(categoryName)).findAny();
  368. }
  369. public void loadFile(File file) {
  370. log.info("load" + file);
  371. try {
  372. FileReader reader = new FileReader(file);
  373. Gson gson = initGson();
  374. Model model = gson.fromJson(reader, Model.class);
  375. reader.close();
  376. this.model = model;
  377. calculateStateAndVisualForCurrentTimeStep();
  378. } catch (IOException e) {
  379. log.warning(e.getLocalizedMessage());
  380. }
  381. clearSelection();
  382. GuiSettings.setActualSaveFile(file);
  383. }
  384. public void saveFile(File file) {
  385. log.info("save" + file);
  386. try {
  387. FileWriter writer = new FileWriter(file);
  388. Gson gson = initGson();
  389. gson.toJson(model, writer);
  390. writer.close();
  391. } catch (IOException e) {
  392. log.warning(e.getLocalizedMessage());
  393. }
  394. GuiSettings.setActualSaveFile(file);
  395. }
  396. public Gson initGson() {
  397. GsonBuilder builder = new GsonBuilder();
  398. builder.registerTypeAdapter(Edge.class, new EdgeSerializer());
  399. builder.registerTypeAdapter(Model.class, new ModelDeserializer());
  400. builder.serializeNulls();
  401. builder.setPrettyPrinting();
  402. return builder.create();
  403. }
  404. public void clearModel() {
  405. model.clear();
  406. clearSelection();
  407. model.setCurrentIteration(0);
  408. IdCounter.reset();
  409. calculateStateAndVisualForCurrentTimeStep();
  410. GuiSettings.setActualSaveFile(null);
  411. }
  412. }