Starting from 2021-07-01, all LRZ GitLab users will be required to explicitly accept the GitLab Terms of Service. Please see the detailed information at https://doku.lrz.de/display/PUBLIC/GitLab and make sure that your projects conform to the requirements.

Commit 065dabd4 authored by Benedikt Zoennchen's avatar Benedikt Zoennchen
Browse files

Merge branch 'master' of https://gitlab.lrz.de/vadere/vadere

parents 280a2bc8 40bf0d23
......@@ -43,7 +43,7 @@ unit_tests_with_coverage:
script:
- Documentation/version-control/git-hook-vadere-software
- mvn clean
- mvn -Dtest=!TestConvolution,!TestBitonicSort,!TestCLLinkedList test
- mvn -Dtest=!TestConvolution,!TestBitonicSort,!TestCLLinkedList,!TestCLOptimalStepsModel test
- python3 Tools/ContinuousIntegration/collect_line_and_branch_coverage.py
run_scenario_files:
......
......@@ -2,6 +2,13 @@
# In Progress: v0.7
## Added
- In package `org.vadere.simulator.util`, added `TopographyChecker` to show user if the current topography contains problems. The
`TopographyChecker` will check for overlapping `ScenarioElements` and check for inconsistence settings such as missing
TargetIDs for sources or inconsistenct speed ranges for pedestrians. See this [table](Documentation/changelLogImages/TopographyCheckerMessages.md) for supported warnings and erros
as well as this [picture](Documentation/changelLogImages/TopographyChecker.png) to see which kind of overlap produces erros or warnings.
# v0.6 (2018-09-07)
## Added
......
# TopographyChecker Messages
## Overlapping ScenarioElements
|Type of Elemetns | TotalOvelrap/ contained in | PartialOverlap |
|--------------------|:----------------:|:----------------:|
|Obstacle / Obstacle | WARN | ./. |
|Obstacle / Source | ERROR | ERROR |
|Obstacle / Target | ERROR | WARN |
|Obstacle / Stairs | ERROR | WARN |
|Obstacle / Ped. | ERROR | ERROR |
|Source / Source | WARN | WARN |
|Source / Target | WARN | WARN |
|Source / Stairs | WARN | WARN |
|Target / Target | WARN | WARN |
|Target / Stairs | WARN | WARN |
|Stairs / Stairs | ERROR | ERROR |
Legend:
WARN Warning but simulation is possible
ERROR Error and simulation is not possible
./. Nothing to do all good
## Misc Tests
### Errors
- A Source has no targetId set but is setup to spawn pedestrians. Solution: Set targetId
- A Source has a targetId set but the target does not exist. Solution: Create target or remove unused targetId from Source.
- If the SpeedDistributionMean of a pedestrian ist not between min/max speed.
### Warnings
- A Source has no targetId set and does not spawn pedestrians. Solution: Possible error
- A Target is never used by any Source. Solution: Possible error and this will cost performance.
- The Stairs model only works for 'normal' one-step-stairs. If the tread is outside of
the range of 10cm < x < 35cm. The simulation does not make sense.
- If the speed setup of a pedestrian is bigger then 12.0 m/s (world record). This is possible an error.
......@@ -82,7 +82,7 @@
<configuration>
<archive>
<manifest>
<mainClass>org.vadere.simulator.entrypoints.VadereConsole</mainClass>
<mainClass>org.vadere.simulator.entrypoints.cmd.VadereConsole</mainClass>
</manifest>
</archive>
<descriptorRefs>
......
......@@ -298,9 +298,38 @@ TopographyCreator.btnConvexHull.label=Convex Hull
TopographyCreator.btnSimplePolygon.label=Simple Polygon
TopographyCreator.btnCircle.label=Circle
TopographyCreator.btnRectangle.label=Rectangle
TopographyCreator.btnChecker.tooltip=Show Topography Checker Messages
TopographyCreator.btnMakro.tooltip=Generate not set IDs.
select_shape_tooltip=Select Shape
# TopographyChecker
TopographyChecker.type.error=Error
TopographyChecker.type.warning=Warning
TopographyChecker.source.targetIdNotFound=The following target ids where not found in the scenario.
TopographyChecker.source.noTargetIdSet=No Target Ids set for Source.
TopographyChecker.source.noTargetIdAndNoSpawn=No Target Ids set for Source with SpawnNumber 0. This might be an error.
TopographyChecker.source.idNotUnique=Multiple Sources have the same ID.
TopographyChecker.stairs.wrongTreadDim=Stair treadDepth outside of allowed dimension.
TopographyChecker.target.unused=The target is not used in any source. Remove target to increase performance.
TopographyChecker.pedestrian.speedsetup=speedDistributionMean must be within min/max range.
TopographyChecker.pedestrian.speedNotLogical=Min or Max speed of pedestrian is bigger than world record.
TopographyChecker.pedestrian.speedIsNegative=Min or Max speed is negative.
TopographyChecker.overlap.stair.stair=Stairs cannot overlap.
TopographyChecker.overlap.target.stair=A target and a stairs element overlap in scenario.
TopographyChecker.overlap.source.stair=A source and a stairs element overlap in scenario.
TopographyChecker.overlap.source.target=A source and a target element overlap in scenario.
TopographyChecker.overlap.source.source=Two source overlap. This can cause overlapping when useFreeSpaceOnly is not set.
TopographyChecker.overlap.target.target=Two targets overlap.
TopographyChecker.overlap.obstacle.stairs.err=Stairs is completely contained in an obstacle.
TopographyChecker.overlap.obstacle.stairs.warn=Stairs contains an obstacle. This setup works put is not tested. Split in two stairs.
TopographyChecker.overlap.obstacle.target.err=Target is completely contained in an obstacle.
TopographyChecker.overlap.obstacle.target.warn=Target contains an obstacle. This setup works but reduces the actual size of the target.
TopographyChecker.overlap.obstacle.source=Obstacle overlaps with a source. This setup will spawn pedestrians within the obstacle.
TopographyChecker.overlap.obstacle.obstacle=Two obstacles overlap / is enclosed completely. Delete one for better performance.
# tab titles Topography creator / postvis
Tab.Simulation.title=Simulation
Tab.Model.title=Model
......@@ -335,8 +364,12 @@ ActionSeeDiscardChanges.popup.title=Unsaved changes
SaveDespiteJsonErrors.title=JSON-Errors.
SaveDespiteJsonErrors.text=There are errors in the JSON of the currently open scenario. Do you want to correct those?
SaveDespiteTopographyCheckerErrors.title=Topography-Errors.
SaveDespiteTopographyCheckerErrors.text=There are errors in the Topography of the currently open scenario. Do you want to correct those?
RunScenarioJsonErrors.title=Resolve JSON errors
RunScenarioJsonErrors.text=The simulation can't be started with erroneous JSON.
RunScenarioTopographyCheckerErrors.title=Resolve TopographyChecker errors
RunScenarioTopographyCheckerErrors.text=The simulation can't be started with erroneous Topography setup.
RunScenarioNotReadyToRun.text=One or more of the selected scenarios isn't ready to run.
ActionEditScenarioDescription.menu.title=Edit description
......@@ -297,6 +297,34 @@ TopographyCreator.btnConvexHull.label=Convexe H\u00fclle
TopographyCreator.btnSimplePolygon.label=Einfaches Polygon
TopographyCreator.btnCircle.label=Kreis
TopographyCreator.btnRectangle.label=Rechteck
TopographyCreator.btnChecker.tooltip=Topography Linter Nachrichten
TopographyCreator.btnMakro.tooltip=Erzeuge nicht gesetzte IDs.
# TopographyChecker
TopographyChecker.type.error=Fehler
TopographyChecker.type.warning=Warnung
TopographyChecker.source.targetIdNotFound=Die folgenden Ziel-IDs wurden nicht im Szenario gefunden.
TopographyChecker.source.noTargetIdSet=In der Quelle wurden keine Ziel Ids vergeben.
TopographyChecker.source.noTargetIdAndNoSpawn=In der Quelle wurden keine Ziel Ids vergeben, aber die Spawn Anzahl ist bei 0.
TopographyChecker.source.idNotUnique=Quellen haben keine eindeutige ID.
TopographyChecker.stairs.wrongTreadDim=Stufentiefe ist au\u00dferhalb des Definitionsbereichs.
TopographyChecker.target.unused=Das Ziel wird von keiner Quelle verwendet. Entferne das Ziel um die Performance zu erh\u00f6hen
TopographyChecker.pedestrian.speedsetup=speedDistributionMean muss im Bereich min/max liegen.
TopographyChecker.pedestrian.speedNotLogical=Min or Max Geschwindigkeit ist gr\u00f6\u00dfer als Weltrekord.
TopographyChecker.pedestrian.speedIsNegative=Min or Max Geschwindigkeit ist negativ.
TopographyChecker.overlap.stair.stair=Treppen d\u00fcrfen nicht \u00fcberlappen.
TopographyChecker.overlap.target.stair=Ein Ziel und eine Treppen \u00fcberlappen im Scenario.
TopographyChecker.overlap.source.stair=Eine Quelle und eine Treppe \u00fcberlappen im Scenario.
TopographyChecker.overlap.source.target=Eine Quelle und eine Ziel \u00fcberappen im Scenario.
TopographyChecker.overlap.source.source=Zwei Quellen \u00fcberlappen. Wenn useFreeSpaceOnly nicht gesetzt ist kann dies zu \u00fcberlappungen von Pedestrians f\u00fchren.
TopographyChecker.overlap.target.target=Zwei Ziele \u00fcberlappen.
TopographyChecker.overlap.obstacle.stairs.err=Treppe ist komplett in einem Hinderniss eingeschossen.
TopographyChecker.overlap.obstacle.stairs.warn=Treppe hat ein Hinderiss in sich. Dies ist m\u00f6glich aber nicht getestet. Wenn m\u00f6glich in zwei treppen aufteilen.
TopographyChecker.overlap.obstacle.target.err=Ziel ist komplett in einem Hinderniss eingeschlossen
TopographyChecker.overlap.obstacle.target.warn=Ziel hat ein Hinderniss in sich. Dies ist m\u00f6glich reduziert aber die tats\u00c4chliche Fl\u00c4che des Ziels.
TopographyChecker.overlap.obstacle.source=Hinderniss \u00fcberdeckt Quelle. Die f\u00fchrt dazu, dass Pedestrians im Hinderniss erzeugt werden.
TopographyChecker.overlap.obstacle.obstacle=Zwei identische bzw. eingeschlossene Obstacles gefunden. L\u00f6sche eins f\u00fcr bessere Performance
# tab titles Topography creator / postvis
Tab.Simulation.title=Simulation
......@@ -332,8 +360,12 @@ ActionSeeDiscardChanges.popup.title=Ungespeicherte \u00c4nderungen
SaveDespiteJsonErrors.title=Fehlerhaftes JSON.
SaveDespiteJsonErrors.text=Im ge\u00f6ffneten Szenario bestehen Fehler im JSON. Wollen Sie diese korrigieren?
SaveDespiteTopographyCheckerErrors.title=Fehlerhafte Topography.
SaveDespiteTopographyCheckerErrors.text=Im ge\u00f6ffneten Szenario bestehen Fehler in der Topography. Wollen Sie diese korrigieren?
RunScenarioJsonErrors.title=JSON Fehler beheben
RunScenarioJsonErrors.text=Die Simulation kann nicht mit fehlerhaftem JSON gestartet werden.
RunScenarioTopographyCheckerErrors.title=TopographyChecker Fehler beheben
RunScenarioTopographyCheckerErrors.text=Die Simulation kann nicht mit einer fehlerhaften Topography gestartet werden.
RunScenarioNotReadyToRun.text=Eines oder mehrere der ausgew\u00e4hlten Szenario sind derzeit nicht lauff\u00e4hig.
ActionEditScenarioDescription.menu.title=Beschreibung bearbeiten
package org.vadere.gui.components.view;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.io.IOException;
import java.io.InputStream;
import javax.swing.BoxLayout;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import com.jgoodies.forms.layout.CellConstraints;
import com.jgoodies.forms.layout.FormLayout;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
import org.fife.ui.rsyntaxtextarea.SyntaxConstants;
import org.fife.ui.rsyntaxtextarea.Theme;
import org.vadere.simulator.entrypoints.ReflectionAttributeModifier;
import org.vadere.gui.components.model.IDefaultModel;
import org.vadere.gui.projectview.view.JsonValidIndicator;
import org.vadere.gui.projectview.view.ProjectView;
import org.vadere.gui.projectview.view.ScenarioPanel;
import org.vadere.gui.topographycreator.model.AgentWrapper;
import org.vadere.gui.topographycreator.model.TopographyCreatorModel;
import org.vadere.simulator.util.TopographyChecker;
import org.vadere.state.attributes.Attributes;
import org.vadere.state.scenario.Pedestrian;
import org.vadere.state.scenario.ScenarioElement;
import org.vadere.state.util.StateJsonConverter;
import com.jgoodies.forms.layout.CellConstraints;
import com.jgoodies.forms.layout.FormLayout;
import java.awt.*;
import java.io.IOException;
import java.io.InputStream;
import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
/**
* The ScenarioElementView display's a ScenarioElement in JSON-Format.
......@@ -48,26 +42,26 @@ public class ScenarioElementView extends JPanel implements ISelectScenarioElemen
private JsonValidIndicator jsonValidIndicator;
public ScenarioElementView(final IDefaultModel defaultModel) {
this(defaultModel, null);
this(defaultModel,null, null);
}
public ScenarioElementView(final IDefaultModel defaultModel, final Component topComponent) {
public ScenarioElementView(final IDefaultModel defaultModel, final JsonValidIndicator jsonValidIndicator, final Component topComponent) {
this.panelModel = defaultModel;
this.panelModel.addSelectScenarioElementListener(this);
this.jsonValidIndicator = jsonValidIndicator;
CellConstraints cc = new CellConstraints();
JScrollPane scrollPane = new JScrollPane();
scrollPane.setPreferredSize(new Dimension(1, Toolkit.getDefaultToolkit().getScreenSize().height));
if (topComponent != null) {
if (topComponent != null && this.jsonValidIndicator !=null) {
setLayout(new FormLayout("default:grow", "pref, default"));
JPanel jsonMeta = new JPanel(); // name of the scenario element and indicator of
// valid/invalid
jsonMeta.setLayout(new BoxLayout(jsonMeta, BoxLayout.Y_AXIS));
jsonValidIndicator = new JsonValidIndicator();
jsonMeta.add(jsonValidIndicator);
jsonValidIndicator.hide();
jsonMeta.add(this.jsonValidIndicator);
this.jsonValidIndicator.hide();
jsonMeta.add(topComponent);
add(jsonMeta, cc.xy(1, 1));
......
......@@ -19,7 +19,6 @@ import javax.swing.*;
import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.prefs.Preferences;
......@@ -390,6 +389,15 @@ public class ProjectViewModel {
return false;
}
JEditorPane errorPanel = ScenarioPanel.getActiveTopographyErrorMsg();
if (errorPanel != null) {
VDialogManager.showMessageDialogWithBodyAndTextEditorPane(
Messages.getString("RunScenarioTopographyCheckerErrors.title"),
Messages.getString("RunScenarioTopographyCheckerErrors.text"),
errorPanel, JOptionPane.ERROR_MESSAGE);
return false;
}
return true;
}
......
......@@ -55,6 +55,7 @@ public class ScenarioPanel extends JPanel implements IProjectChangeListener, Pro
private ProjectViewModel model;
private static String activeJsonParsingErrorMsg = null;
private static JEditorPane activeTopographyErrorMsg = null;
ScenarioPanel(JLabel scenarioName, ProjectViewModel model) {
......@@ -324,6 +325,14 @@ public class ScenarioPanel extends JPanel implements IProjectChangeListener, Pro
postVisualizationView.loadOutputFile(trajectoryFile, scenarioRM);
}
public static void setActiveTopographyErrorMsg(JEditorPane msg){
activeTopographyErrorMsg = msg;
}
public static JEditorPane getActiveTopographyErrorMsg(){
return activeTopographyErrorMsg;
}
public static void setActiveJsonParsingErrorMsg(String msg) {
activeJsonParsingErrorMsg = msg;
}
......
......@@ -50,6 +50,14 @@ public class VDialogManager {
title, buttonOptions);
}
public static int showConfirmDialogWithBodyAndEditorPane(String title, String body, JEditorPane editorPane,
int buttonOptions) {
return JOptionPane.showConfirmDialog(
ProjectView.getMainWindow(),
getPanelWithBodyAndTextEditorPane(body, editorPane),
title, buttonOptions);
}
public static void showMessageDialogWithBodyAndTextArea(String title, String body, String textAreaContent,
int messageType) {
......@@ -61,6 +69,16 @@ public class VDialogManager {
title, messageType);
}
public static void showMessageDialogWithBodyAndTextEditorPane(String title, String body, JEditorPane jEditorPane,
int messageType) {
JOptionPane.showMessageDialog(
ProjectView.getMainWindow(),
getPanelWithBodyAndTextEditorPane(
"<html>" + body + "<br><br></html>",
jEditorPane),
title, messageType);
}
public static JPanel getPanelWithBodyAndTextArea(String body, String textAreaContent) {
JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
......@@ -75,6 +93,19 @@ public class VDialogManager {
return panel;
}
public static JPanel getPanelWithBodyAndTextEditorPane(String body, JEditorPane jEditorPane){
JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
JLabel label = new JLabel(body);
panel.add(label);
JScrollPane jsp = new JScrollPane(jEditorPane);
jsp.setPreferredSize(new Dimension(600, 300));
panel.add(jsp);
return panel;
}
public static void showMessageDialogWithTextArea(String title, String textAreaContent, int messageType) {
JScrollPane jsp = new JScrollPane(new JTextArea(textAreaContent)); // via http://stackoverflow.com/a/14011536
jsp.setPreferredSize(new Dimension(600, 300));
......@@ -93,6 +124,15 @@ public class VDialogManager {
if (ret == JOptionPane.YES_OPTION)
return false;
}
JEditorPane jEditorPane = ScenarioPanel.getActiveTopographyErrorMsg();
if (jEditorPane != null) {
int ret = VDialogManager.showConfirmDialogWithBodyAndEditorPane(
Messages.getString("SaveDespiteTopographyCheckerErrors.title"),
"<html>" + Messages.getString("SaveDespiteTopographyCheckerErrors.text") + "<br><br><html>",
jEditorPane, JOptionPane.YES_NO_OPTION);
if (ret == JOptionPane.YES_OPTION)
return false;
}
return true;
}
......
package org.vadere.gui.topographycreator.control;
import org.vadere.gui.components.utils.Messages;
import org.vadere.gui.components.utils.Resources;
import org.vadere.gui.projectview.view.JsonValidIndicator;
import org.vadere.gui.projectview.view.ScenarioPanel;
import org.vadere.gui.projectview.view.VDialogManager;
import org.vadere.gui.topographycreator.model.IDrawPanelModel;
import org.vadere.simulator.util.TopographyChecker;
import org.vadere.simulator.util.TopographyCheckerMessage;
import org.vadere.simulator.util.TopographyCheckerMessageType;
import org.vadere.state.scenario.ScenarioElement;
import java.awt.event.ActionEvent;
import java.util.HashMap;
import java.util.List;
import java.util.Observable;
import java.util.Observer;
import java.util.PriorityQueue;
import javax.swing.*;
import javax.swing.event.HyperlinkEvent;
public class ActionTopographyCheckerMenu extends TopographyAction implements Observer {
private final static ImageIcon iconRed = new ImageIcon(Resources.class.getResource("/icons/light_red_icon.png"));
private final static ImageIcon iconYellow = new ImageIcon(Resources.class.getResource("/icons/light_yellow_icon.png"));
private final static ImageIcon iconGreen = new ImageIcon(Resources.class.getResource("/icons/light_green_icon.png"));
private final JsonValidIndicator jsonValidIndicator;
private PriorityQueue<TopographyCheckerMessage> errorMsg;
private PriorityQueue<TopographyCheckerMessage> warnMsg;
private MsgDocument msgDocument;
public ActionTopographyCheckerMenu(String name, IDrawPanelModel<?> panelModel, JsonValidIndicator jsonValidIndicator) {
super(name, iconYellow, panelModel);
this.jsonValidIndicator = jsonValidIndicator;
this.errorMsg = new PriorityQueue<>();
this.warnMsg = new PriorityQueue<>();
panelModel.addObserver(this);
}
/**
* Handel click on traffic light icon and show all TopographyChecker messages generated for the
* current state of the topography.
*/
@Override
public void actionPerformed(ActionEvent e) {
VDialogManager.showMessageDialogWithBodyAndTextEditorPane(
"Topography Checker",
"The following problems where found",
msgDocument,
JOptionPane.INFORMATION_MESSAGE
);
}
/**
* After each change of the Topography which yields a valid json representation check run the
* {@link TopographyChecker} and change the icon respectively. This function also creates the
* message document presented in various dialog windows.
*/
@Override
public void update(Observable o, Object arg) {
if (jsonValidIndicator.isValid()) {
TopographyChecker checker = new TopographyChecker(getScenarioPanelModel().getTopography());
errorMsg.clear();
warnMsg.clear();
ScenarioPanel.setActiveTopographyErrorMsg(null);
addMsg(checker.checkBuildingStep());
putValue(Action.SMALL_ICON, iconGreen);
if (warnMsg.size() > 0) {
putValue(Action.SMALL_ICON, iconYellow);
}
if (errorMsg.size() > 0) {
putValue(Action.SMALL_ICON, iconRed);
}
}
}
/**
* @return MsgDocument containing erros and warnings with links to the specific scenario element
*/
private MsgDocument checkerMessagesToDoc() {
StringBuilder sb = new StringBuilder();
MsgDocument doc = new MsgDocument();
if (errorMsg.size() > 0) {
sb.append("<h3> Errors </h3>").append("<br>");
errorMsg.forEach(m -> msgToDocString(sb, m, doc));
}
if (warnMsg.size() > 0) {
if (sb.length() > 0) {
sb.append("<br>");
}
sb.append("<h3> Warnings </h3>").append("<br>");
warnMsg.forEach(m -> msgToDocString(sb, m, doc));
}
if (errorMsg.size() == 0 && warnMsg.size() == 0) {
sb.append("No Problems found.");
}
doc.setText(sb.toString());
return doc;
}
private void msgToDocString(StringBuilder sb, TopographyCheckerMessage msg, MsgDocument doc) {
sb.append("[");
msg.getMsgTarget().getTargets().forEach(t -> {
doc.makeLink(t, sb);
sb.append(", ");
});
sb.setLength(sb.length()-2);
sb.append("] ");
sb.append("Reason: ").append(Messages.getString(msg.getReason().getLocalMessageId()));
if (!msg.getReasonModifier().isEmpty()) {
sb.append(" ").append(msg.getReasonModifier());
}
sb.append("<br>");
doc.setText(sb.toString());
}
private void addMsg(List<TopographyCheckerMessage> msg) {
msg.forEach(m -> {
if (m.getMsgType().equals(TopographyCheckerMessageType.WARN)) {
warnMsg.add(m);
} else {
errorMsg.add(m);
}
});
msgDocument = checkerMessagesToDoc();
if (errorMsg.size() > 0) {
ScenarioPanel.setActiveTopographyErrorMsg(msgDocument);
}
}
/**
* Simple {@link JEditorPane} wrapper which manages the links within the document to highlight
* the {@link ScenarioElement} producing the error / warning.
*/
class MsgDocument extends JEditorPane {
HashMap<String, ScenarioElement> linkMap;
int id;
MsgDocument() {
linkMap = new HashMap<>();
id = 0;
setContentType("text/html");
setEditable(false);
addHyperlinkListener(e -> {
if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
ScenarioElement element = linkMap.getOrDefault(e.getDescription(), null);
if (element != null) {
getScenarioPanelModel().setSelectedElement(element);
}
}
});
}
void makeLink(ScenarioElement element, StringBuilder sb) {
linkMap.put("element/id/" + id, element);
sb.append("<a href='element/id/")
.append(id).append("'>")
.append(element.getClass().getSimpleName())
.append("{Id:").append(element.getId()).append("}")
.append("</a>");
id++;
}
}
}
package org.vadere.gui.topographycreator.control;
import org.vadere.gui.topographycreator.model.IDrawPanelModel;
import java.awt.event.ActionEvent;
import javax.swing.*;
public class ActionTopographyMakroMenu extends TopographyAction {
public ActionTopographyMakroMenu(String name, ImageIcon icon, IDrawPanelModel<?> panelModel) {
super(name, icon, panelModel);
}
@Override
public void actionPerformed(ActionEvent e) {
getScenarioPanelModel().getTopography().generateUniqueIdIfNotSet();