Control.java 14 KB

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