Control.java 15 KB

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