This commit is contained in:
57
opentcs-modeleditor/build.gradle
Normal file
57
opentcs-modeleditor/build.gradle
Normal file
@@ -0,0 +1,57 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
apply from: "${rootDir}/gradle/java-project.gradle"
|
||||
apply from: "${rootDir}/gradle/java-codequality.gradle"
|
||||
apply from: "${rootDir}/gradle/guice-application.gradle"
|
||||
apply from: "${rootDir}/gradle/publishing-java.gradle"
|
||||
|
||||
if (!hasProperty('mainClass')) {
|
||||
ext.mainClass = 'org.opentcs.modeleditor.RunModelEditor'
|
||||
}
|
||||
application.mainClass = ext.mainClass
|
||||
|
||||
ext.collectableDistDir = new File(buildDir, 'install')
|
||||
|
||||
dependencies {
|
||||
api project(':opentcs-common')
|
||||
api project(':opentcs-impl-configuration-gestalt')
|
||||
api project(':opentcs-plantoverview-common')
|
||||
api project(':opentcs-plantoverview-themes-default')
|
||||
|
||||
runtimeOnly group: 'org.slf4j', name: 'slf4j-jdk14', version: '2.0.16'
|
||||
}
|
||||
|
||||
compileJava {
|
||||
options.compilerArgs << "-Xlint:-rawtypes"
|
||||
}
|
||||
|
||||
distributions {
|
||||
main {
|
||||
contents {
|
||||
from "${sourceSets.main.resources.srcDirs[0]}/org/opentcs/modeleditor/distribution"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// For now, we're using hand-crafted start scripts, so disable the application
|
||||
// plugin's start script generation.
|
||||
startScripts.enabled = false
|
||||
|
||||
distTar.enabled = false
|
||||
|
||||
task release {
|
||||
dependsOn build
|
||||
dependsOn installDist
|
||||
}
|
||||
|
||||
run {
|
||||
systemProperties(['java.util.logging.config.file':'./config/logging.config',\
|
||||
'sun.java2d.d3d':'false',\
|
||||
'opentcs.base':'.',\
|
||||
'opentcs.home':'.',\
|
||||
'opentcs.configuration.reload.interval':'10000',\
|
||||
'opentcs.configuration.provider':'gestalt'])
|
||||
jvmArgs('-XX:-OmitStackTraceInFastThrow',\
|
||||
'-splash:bin/splash-image.gif')
|
||||
}
|
||||
40
opentcs-modeleditor/gradle.properties
Normal file
40
opentcs-modeleditor/gradle.properties
Normal file
@@ -0,0 +1,40 @@
|
||||
netbeans.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.wrapAnnotationArgs=WRAP_IF_LONG
|
||||
netbeans.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.alignMultilineMethodParams=true
|
||||
netbeans.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.wrapAfterDotInChainedMethodCalls=false
|
||||
netbeans.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.alignMultilineDisjunctiveCatchTypes=true
|
||||
netbeans.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.alignMultilineFor=true
|
||||
netbeans.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.alignMultilineImplements=true
|
||||
netbeans.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.wrapFor=WRAP_IF_LONG
|
||||
netbeans.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.sortMembersByVisibility=true
|
||||
netbeans.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.visibilityOrder=PUBLIC;PROTECTED;DEFAULT;PRIVATE
|
||||
netbeans.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.placeFinallyOnNewLine=true
|
||||
netbeans.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.wrapMethodParams=WRAP_IF_LONG
|
||||
netbeans.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.enable-indent=true
|
||||
netbeans.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.alignMultilineArrayInit=true
|
||||
netbeans.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.alignMultilineCallArgs=true
|
||||
netbeans.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.wrapDisjunctiveCatchTypes=WRAP_IF_LONG
|
||||
netbeans.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.keepGettersAndSettersTogether=true
|
||||
netbeans.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.wrapExtendsImplementsList=WRAP_ALWAYS
|
||||
netbeans.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.wrapThrowsKeyword=WRAP_ALWAYS
|
||||
netbeans.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.wrapExtendsImplementsKeyword=WRAP_ALWAYS
|
||||
netbeans.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.classMembersOrder=STATIC FIELD;FIELD;STATIC_INIT;CONSTRUCTOR;INSTANCE_INIT;STATIC METHOD;METHOD;STATIC CLASS;CLASS
|
||||
netbeans.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.wrapEnumConstants=WRAP_ALWAYS
|
||||
netbeans.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.wrapCommentText=false
|
||||
netbeans.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.wrapThrowsList=WRAP_IF_LONG
|
||||
netbeans.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.wrapAssert=WRAP_IF_LONG
|
||||
netbeans.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.importGroupsOrder=*
|
||||
netbeans.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.continuationIndentSize=4
|
||||
netbeans.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.placeElseOnNewLine=true
|
||||
netbeans.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.placeCatchOnNewLine=true
|
||||
netbeans.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.alignMultilineAnnotationArgs=true
|
||||
netbeans.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.alignMultilineTryResources=true
|
||||
netbeans.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.preserveNewLinesInComments=true
|
||||
netbeans.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.alignMultilineParenthesized=true
|
||||
netbeans.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.alignMultilineThrows=true
|
||||
netbeans.org-netbeans-modules-editor-indent.CodeStyle.project.text-line-wrap=none
|
||||
netbeans.org-netbeans-modules-editor-indent.CodeStyle.project.indent-shift-width=2
|
||||
netbeans.org-netbeans-modules-editor-indent.CodeStyle.project.spaces-per-tab=2
|
||||
netbeans.org-netbeans-modules-editor-indent.CodeStyle.project.tab-size=2
|
||||
netbeans.org-netbeans-modules-editor-indent.CodeStyle.project.text-limit-width=100
|
||||
netbeans.org-netbeans-modules-editor-indent.CodeStyle.project.expand-tabs=true
|
||||
netbeans.org-netbeans-modules-editor-indent.CodeStyle.usedProfile=project
|
||||
BIN
opentcs-modeleditor/src/dist/bin/splash-image.gif
vendored
Normal file
BIN
opentcs-modeleditor/src/dist/bin/splash-image.gif
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 13 KiB |
2
opentcs-modeleditor/src/dist/bin/splash-image.gif.license
vendored
Normal file
2
opentcs-modeleditor/src/dist/bin/splash-image.gif.license
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
# SPDX-FileCopyrightText: The openTCS Authors
|
||||
# SPDX-License-Identifier: CC-BY-4.0
|
||||
66
opentcs-modeleditor/src/dist/config/logging.config
vendored
Normal file
66
opentcs-modeleditor/src/dist/config/logging.config
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
# SPDX-FileCopyrightText: The openTCS Authors
|
||||
# SPDX-License-Identifier: CC-BY-4.0
|
||||
|
||||
############################################################
|
||||
# Default Logging Configuration File
|
||||
#
|
||||
# You can use a different file by specifying a filename
|
||||
# with the java.util.logging.config.file system property.
|
||||
# For example java -Djava.util.logging.config.file=myfile
|
||||
############################################################
|
||||
|
||||
############################################################
|
||||
# Global properties
|
||||
############################################################
|
||||
|
||||
# "handlers" specifies a comma separated list of log Handler
|
||||
# classes. These handlers will be installed during VM startup.
|
||||
# Note that these classes must be on the system classpath.
|
||||
# By default we only configure a ConsoleHandler, which will only
|
||||
# show messages at the INFO and above levels.
|
||||
#handlers= java.util.logging.ConsoleHandler
|
||||
|
||||
# To also add the FileHandler, use the following line instead.
|
||||
handlers= java.util.logging.FileHandler, java.util.logging.ConsoleHandler
|
||||
|
||||
# Default global logging level.
|
||||
# This specifies which kinds of events are logged across
|
||||
# all loggers. For any given facility this global level
|
||||
# can be overriden by a facility specific level
|
||||
# Note that the ConsoleHandler also has a separate level
|
||||
# setting to limit messages printed to the console.
|
||||
.level= INFO
|
||||
|
||||
############################################################
|
||||
# Handler specific properties.
|
||||
# Describes specific configuration info for Handlers.
|
||||
############################################################
|
||||
|
||||
# default file output is in user's home directory.
|
||||
java.util.logging.FileHandler.pattern = ./log/opentcs-modeleditor.%g.log
|
||||
java.util.logging.FileHandler.limit = 500000
|
||||
java.util.logging.FileHandler.count = 10
|
||||
#java.util.logging.FileHandler.formatter = java.util.logging.SimpleFormatter
|
||||
java.util.logging.FileHandler.formatter = org.opentcs.util.logging.SingleLineFormatter
|
||||
java.util.logging.FileHandler.append = true
|
||||
java.util.logging.FileHandler.level = FINE
|
||||
|
||||
# Limit the message that are printed on the console to INFO and above.
|
||||
java.util.logging.ConsoleHandler.level = INFO
|
||||
#java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
|
||||
java.util.logging.ConsoleHandler.formatter = org.opentcs.util.logging.SingleLineFormatter
|
||||
|
||||
############################################################
|
||||
# Facility specific properties.
|
||||
# Provides extra control for each logger.
|
||||
############################################################
|
||||
|
||||
# For example, set the com.xyz.foo logger to only log SEVERE
|
||||
# messages:
|
||||
#com.xyz.foo.level = SEVERE
|
||||
|
||||
# Logging configuration for single classes. Remember that you might also have to
|
||||
# adjust handler levels!
|
||||
|
||||
#org.opentcs.guing.*.level = FINE
|
||||
#org.opentcs.access.rmi.ProxyInvocationHandler.level = FINE
|
||||
2
opentcs-modeleditor/src/dist/config/opentcs-modeleditor.properties
vendored
Normal file
2
opentcs-modeleditor/src/dist/config/opentcs-modeleditor.properties
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
# SPDX-FileCopyrightText: The openTCS Authors
|
||||
# SPDX-License-Identifier: CC-BY-4.0
|
||||
810
opentcs-modeleditor/src/dist/data/Demo-01.xml
vendored
Normal file
810
opentcs-modeleditor/src/dist/data/Demo-01.xml
vendored
Normal file
@@ -0,0 +1,810 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<model version="6.0.0" name="Demo-01">
|
||||
<point name="Point-0001" positionX="31000" positionY="11000" positionZ="0" vehicleOrientationAngle="NaN" type="HALT_POSITION">
|
||||
<maxVehicleBoundingBox length="1000" width="1000" height="1000" referenceOffsetX="0" referenceOffsetY="0"/>
|
||||
<outgoingPath name="Point-0001 --- Point-0002"/>
|
||||
<outgoingPath name="Point-0001 --- Point-0003"/>
|
||||
<pointLayout positionX="31000" positionY="11000" labelOffsetX="-10" labelOffsetY="-20" layerId="0"/>
|
||||
</point>
|
||||
<point name="Point-0002" positionX="25000" positionY="9000" positionZ="0" vehicleOrientationAngle="NaN" type="PARK_POSITION">
|
||||
<maxVehicleBoundingBox length="1000" width="1000" height="1000" referenceOffsetX="0" referenceOffsetY="0"/>
|
||||
<outgoingPath name="Point-0002 --- Point-0004"/>
|
||||
<outgoingPath name="Point-0002 --- Point-0014"/>
|
||||
<property name="tcs:parkingPositionPriority" value="4"/>
|
||||
<pointLayout positionX="25000" positionY="9000" labelOffsetX="-10" labelOffsetY="-20" layerId="0"/>
|
||||
</point>
|
||||
<point name="Point-0003" positionX="31000" positionY="5000" positionZ="0" vehicleOrientationAngle="NaN" type="HALT_POSITION">
|
||||
<maxVehicleBoundingBox length="1000" width="1000" height="1000" referenceOffsetX="0" referenceOffsetY="0"/>
|
||||
<outgoingPath name="Point-0003 --- Point-0004"/>
|
||||
<outgoingPath name="Point-0003 --- Point-0005"/>
|
||||
<pointLayout positionX="31000" positionY="5000" labelOffsetX="-10" labelOffsetY="-20" layerId="0"/>
|
||||
</point>
|
||||
<point name="Point-0004" positionX="25000" positionY="3000" positionZ="0" vehicleOrientationAngle="NaN" type="PARK_POSITION">
|
||||
<maxVehicleBoundingBox length="1000" width="1000" height="1000" referenceOffsetX="0" referenceOffsetY="0"/>
|
||||
<outgoingPath name="Point-0004 --- Point-0006"/>
|
||||
<outgoingPath name="Point-0004 --- Point-0008"/>
|
||||
<property name="tcs:parkingPositionPriority" value="3"/>
|
||||
<pointLayout positionX="25000" positionY="3000" labelOffsetX="-10" labelOffsetY="-20" layerId="0"/>
|
||||
</point>
|
||||
<point name="Point-0005" positionX="31000" positionY="-1000" positionZ="0" vehicleOrientationAngle="NaN" type="HALT_POSITION">
|
||||
<maxVehicleBoundingBox length="1000" width="1000" height="1000" referenceOffsetX="0" referenceOffsetY="0"/>
|
||||
<outgoingPath name="Point-0005 --- Point-0006"/>
|
||||
<outgoingPath name="Point-0005 --- Point-0007"/>
|
||||
<pointLayout positionX="31000" positionY="-1000" labelOffsetX="-10" labelOffsetY="-20" layerId="0"/>
|
||||
</point>
|
||||
<point name="Point-0006" positionX="25000" positionY="-3000" positionZ="0" vehicleOrientationAngle="NaN" type="PARK_POSITION">
|
||||
<maxVehicleBoundingBox length="1000" width="1000" height="1000" referenceOffsetX="0" referenceOffsetY="0"/>
|
||||
<outgoingPath name="Point-0006 --- Point-0009"/>
|
||||
<outgoingPath name="Point-0006 --- Point-0010"/>
|
||||
<property name="tcs:parkingPositionPriority" value="2"/>
|
||||
<pointLayout positionX="25000" positionY="-3000" labelOffsetX="-10" labelOffsetY="-20" layerId="0"/>
|
||||
</point>
|
||||
<point name="Point-0007" positionX="31000" positionY="-7000" positionZ="0" vehicleOrientationAngle="NaN" type="HALT_POSITION">
|
||||
<maxVehicleBoundingBox length="1000" width="1000" height="1000" referenceOffsetX="0" referenceOffsetY="0"/>
|
||||
<outgoingPath name="Point-0007 --- Point-0010"/>
|
||||
<pointLayout positionX="31000" positionY="-7000" labelOffsetX="-10" labelOffsetY="-20" layerId="0"/>
|
||||
</point>
|
||||
<point name="Point-0008" positionX="22000" positionY="1000" positionZ="0" vehicleOrientationAngle="NaN" type="HALT_POSITION">
|
||||
<maxVehicleBoundingBox length="1000" width="1000" height="1000" referenceOffsetX="0" referenceOffsetY="0"/>
|
||||
<outgoingPath name="Point-0008 --- Point-0009"/>
|
||||
<pointLayout positionX="22000" positionY="1000" labelOffsetX="-10" labelOffsetY="-20" layerId="0"/>
|
||||
</point>
|
||||
<point name="Point-0009" positionX="22000" positionY="-5000" positionZ="0" vehicleOrientationAngle="NaN" type="HALT_POSITION">
|
||||
<maxVehicleBoundingBox length="1000" width="1000" height="1000" referenceOffsetX="0" referenceOffsetY="0"/>
|
||||
<outgoingPath name="Point-0009 --- Point-0011"/>
|
||||
<pointLayout positionX="22000" positionY="-5000" labelOffsetX="-10" labelOffsetY="-20" layerId="0"/>
|
||||
</point>
|
||||
<point name="Point-0010" positionX="25000" positionY="-9000" positionZ="0" vehicleOrientationAngle="NaN" type="PARK_POSITION">
|
||||
<maxVehicleBoundingBox length="1000" width="1000" height="1000" referenceOffsetX="0" referenceOffsetY="0"/>
|
||||
<outgoingPath name="Point-0010 --- Point-0011"/>
|
||||
<property name="tcs:parkingPositionPriority" value="1"/>
|
||||
<pointLayout positionX="25000" positionY="-9000" labelOffsetX="-10" labelOffsetY="-20" layerId="0"/>
|
||||
</point>
|
||||
<point name="Point-0011" positionX="22000" positionY="-11000" positionZ="0" vehicleOrientationAngle="NaN" type="HALT_POSITION">
|
||||
<maxVehicleBoundingBox length="1000" width="1000" height="1000" referenceOffsetX="0" referenceOffsetY="0"/>
|
||||
<outgoingPath name="Point-0011 --- Point-0013"/>
|
||||
<pointLayout positionX="22000" positionY="-11000" labelOffsetX="-10" labelOffsetY="-20" layerId="0"/>
|
||||
</point>
|
||||
<point name="Point-0013" positionX="18000" positionY="-15000" positionZ="0" vehicleOrientationAngle="NaN" type="HALT_POSITION">
|
||||
<maxVehicleBoundingBox length="1000" width="1000" height="1000" referenceOffsetX="0" referenceOffsetY="0"/>
|
||||
<outgoingPath name="Point-0013 --- Point-0015"/>
|
||||
<outgoingPath name="Point-0013 --- Point-0018"/>
|
||||
<outgoingPath name="Point-0013 --- Point-0057"/>
|
||||
<pointLayout positionX="18000" positionY="-15000" labelOffsetX="-10" labelOffsetY="-20" layerId="0"/>
|
||||
</point>
|
||||
<point name="Point-0014" positionX="22000" positionY="7000" positionZ="0" vehicleOrientationAngle="NaN" type="HALT_POSITION">
|
||||
<maxVehicleBoundingBox length="1000" width="1000" height="1000" referenceOffsetX="0" referenceOffsetY="0"/>
|
||||
<outgoingPath name="Point-0014 --- Point-0008"/>
|
||||
<pointLayout positionX="22000" positionY="7000" labelOffsetX="-10" labelOffsetY="-20" layerId="0"/>
|
||||
</point>
|
||||
<point name="Point-0015" positionX="7850" positionY="-11000" positionZ="0" vehicleOrientationAngle="NaN" type="HALT_POSITION">
|
||||
<maxVehicleBoundingBox length="1000" width="1000" height="1000" referenceOffsetX="0" referenceOffsetY="0"/>
|
||||
<outgoingPath name="Point-0015 --- Point-0016"/>
|
||||
<outgoingPath name="Point-0015 --- Point-0050"/>
|
||||
<pointLayout positionX="7850" positionY="-11000" labelOffsetX="-10" labelOffsetY="-20" layerId="0"/>
|
||||
</point>
|
||||
<point name="Point-0016" positionX="-2000" positionY="-11000" positionZ="0" vehicleOrientationAngle="NaN" type="HALT_POSITION">
|
||||
<maxVehicleBoundingBox length="1000" width="1000" height="1000" referenceOffsetX="0" referenceOffsetY="0"/>
|
||||
<outgoingPath name="Point-0016 --- Point-0017"/>
|
||||
<outgoingPath name="Point-0016 --- Point-0022"/>
|
||||
<outgoingPath name="Point-0016 --- Point-0046"/>
|
||||
<pointLayout positionX="-2000" positionY="-11000" labelOffsetX="-10" labelOffsetY="-20" layerId="0"/>
|
||||
</point>
|
||||
<point name="Point-0017" positionX="-12000" positionY="-15000" positionZ="0" vehicleOrientationAngle="NaN" type="HALT_POSITION">
|
||||
<maxVehicleBoundingBox length="1000" width="1000" height="1000" referenceOffsetX="0" referenceOffsetY="0"/>
|
||||
<outgoingPath name="Point-0017 --- Point-0020"/>
|
||||
<pointLayout positionX="-12000" positionY="-15000" labelOffsetX="-10" labelOffsetY="-20" layerId="0"/>
|
||||
</point>
|
||||
<point name="Point-0018" positionX="8000" positionY="-15000" positionZ="0" vehicleOrientationAngle="NaN" type="HALT_POSITION">
|
||||
<maxVehicleBoundingBox length="1000" width="1000" height="1000" referenceOffsetX="0" referenceOffsetY="0"/>
|
||||
<outgoingPath name="Point-0018 --- Point-0019"/>
|
||||
<pointLayout positionX="8000" positionY="-15000" labelOffsetX="-10" labelOffsetY="-20" layerId="0"/>
|
||||
</point>
|
||||
<point name="Point-0019" positionX="-2000" positionY="-15000" positionZ="0" vehicleOrientationAngle="NaN" type="HALT_POSITION">
|
||||
<maxVehicleBoundingBox length="1000" width="1000" height="1000" referenceOffsetX="0" referenceOffsetY="0"/>
|
||||
<outgoingPath name="Point-0019 --- Point-0017"/>
|
||||
<outgoingPath name="Point-0019 --- Point-0022"/>
|
||||
<pointLayout positionX="-2000" positionY="-15000" labelOffsetX="-10" labelOffsetY="-20" layerId="0"/>
|
||||
</point>
|
||||
<point name="Point-0020" positionX="-20000" positionY="-12000" positionZ="0" vehicleOrientationAngle="NaN" type="HALT_POSITION">
|
||||
<maxVehicleBoundingBox length="1000" width="1000" height="1000" referenceOffsetX="0" referenceOffsetY="0"/>
|
||||
<outgoingPath name="Point-0020 --- Point-0021"/>
|
||||
<pointLayout positionX="-20000" positionY="-12000" labelOffsetX="-10" labelOffsetY="-20" layerId="0"/>
|
||||
</point>
|
||||
<point name="Point-0021" positionX="-24000" positionY="-8000" positionZ="0" vehicleOrientationAngle="NaN" type="HALT_POSITION">
|
||||
<maxVehicleBoundingBox length="1000" width="1000" height="1000" referenceOffsetX="0" referenceOffsetY="0"/>
|
||||
<outgoingPath name="Point-0021 --- Point-0023"/>
|
||||
<pointLayout positionX="-24000" positionY="-8000" labelOffsetX="-10" labelOffsetY="-20" layerId="0"/>
|
||||
</point>
|
||||
<point name="Point-0022" positionX="-12000" positionY="-11000" positionZ="0" vehicleOrientationAngle="NaN" type="HALT_POSITION">
|
||||
<maxVehicleBoundingBox length="1000" width="1000" height="1000" referenceOffsetX="0" referenceOffsetY="0"/>
|
||||
<outgoingPath name="Point-0022 --- Point-0056"/>
|
||||
<pointLayout positionX="-12000" positionY="-11000" labelOffsetX="-10" labelOffsetY="-20" layerId="0"/>
|
||||
</point>
|
||||
<point name="Point-0023" positionX="-24000" positionY="-4000" positionZ="0" vehicleOrientationAngle="NaN" type="HALT_POSITION">
|
||||
<maxVehicleBoundingBox length="1000" width="1000" height="1000" referenceOffsetX="0" referenceOffsetY="0"/>
|
||||
<outgoingPath name="Point-0023 --- Point-0024"/>
|
||||
<pointLayout positionX="-24000" positionY="-4000" labelOffsetX="-10" labelOffsetY="-20" layerId="0"/>
|
||||
</point>
|
||||
<point name="Point-0024" positionX="-24000" positionY="1000" positionZ="0" vehicleOrientationAngle="NaN" type="HALT_POSITION">
|
||||
<maxVehicleBoundingBox length="1000" width="1000" height="1000" referenceOffsetX="0" referenceOffsetY="0"/>
|
||||
<outgoingPath name="Point-0024 --- Point-0025"/>
|
||||
<pointLayout positionX="-24000" positionY="1000" labelOffsetX="-10" labelOffsetY="-20" layerId="0"/>
|
||||
</point>
|
||||
<point name="Point-0025" positionX="-24000" positionY="6000" positionZ="0" vehicleOrientationAngle="NaN" type="HALT_POSITION">
|
||||
<maxVehicleBoundingBox length="1000" width="1000" height="1000" referenceOffsetX="0" referenceOffsetY="0"/>
|
||||
<outgoingPath name="Point-0025 --- Point-0026"/>
|
||||
<outgoingPath name="Point-0025 --- Point-0030"/>
|
||||
<outgoingPath name="Point-0025 --- Point-0042"/>
|
||||
<pointLayout positionX="-24000" positionY="6000" labelOffsetX="-10" labelOffsetY="-20" layerId="0"/>
|
||||
</point>
|
||||
<point name="Point-0026" positionX="-24000" positionY="11000" positionZ="0" vehicleOrientationAngle="NaN" type="HALT_POSITION">
|
||||
<maxVehicleBoundingBox length="1000" width="1000" height="1000" referenceOffsetX="0" referenceOffsetY="0"/>
|
||||
<outgoingPath name="Point-0026 --- Point-0027"/>
|
||||
<pointLayout positionX="-24000" positionY="11000" labelOffsetX="-10" labelOffsetY="-20" layerId="0"/>
|
||||
</point>
|
||||
<point name="Point-0027" positionX="-20000" positionY="15000" positionZ="0" vehicleOrientationAngle="NaN" type="PARK_POSITION">
|
||||
<maxVehicleBoundingBox length="1000" width="1000" height="1000" referenceOffsetX="0" referenceOffsetY="0"/>
|
||||
<outgoingPath name="Point-0027 --- Point-0032"/>
|
||||
<property name="tcs:parkingPositionPriority" value="4"/>
|
||||
<pointLayout positionX="-20000" positionY="15000" labelOffsetX="-10" labelOffsetY="-20" layerId="0"/>
|
||||
</point>
|
||||
<point name="Point-0028" positionX="-8000" positionY="11000" positionZ="0" vehicleOrientationAngle="NaN" type="HALT_POSITION">
|
||||
<maxVehicleBoundingBox length="1000" width="1000" height="1000" referenceOffsetX="0" referenceOffsetY="0"/>
|
||||
<outgoingPath name="Point-0028 --- Point-0029"/>
|
||||
<pointLayout positionX="-8000" positionY="11000" labelOffsetX="-10" labelOffsetY="-20" layerId="0"/>
|
||||
</point>
|
||||
<point name="Point-0029" positionX="-2000" positionY="11000" positionZ="0" vehicleOrientationAngle="NaN" type="HALT_POSITION">
|
||||
<maxVehicleBoundingBox length="1000" width="1000" height="1000" referenceOffsetX="0" referenceOffsetY="0"/>
|
||||
<outgoingPath name="Point-0029 --- Point-0035"/>
|
||||
<pointLayout positionX="-2000" positionY="11000" labelOffsetX="-10" labelOffsetY="-20" layerId="0"/>
|
||||
</point>
|
||||
<point name="Point-0030" positionX="-20000" positionY="11000" positionZ="0" vehicleOrientationAngle="NaN" type="HALT_POSITION">
|
||||
<maxVehicleBoundingBox length="1000" width="1000" height="1000" referenceOffsetX="0" referenceOffsetY="0"/>
|
||||
<outgoingPath name="Point-0030 --- Point-0032"/>
|
||||
<pointLayout positionX="-20000" positionY="11000" labelOffsetX="-10" labelOffsetY="-20" layerId="0"/>
|
||||
</point>
|
||||
<point name="Point-0032" positionX="-13000" positionY="11000" positionZ="0" vehicleOrientationAngle="NaN" type="HALT_POSITION">
|
||||
<maxVehicleBoundingBox length="1000" width="1000" height="1000" referenceOffsetX="0" referenceOffsetY="0"/>
|
||||
<outgoingPath name="Point-0032 --- Point-0028"/>
|
||||
<pointLayout positionX="-13000" positionY="11000" labelOffsetX="-10" labelOffsetY="-20" layerId="0"/>
|
||||
</point>
|
||||
<point name="Point-0033" positionX="24000" positionY="15000" positionZ="0" vehicleOrientationAngle="NaN" type="HALT_POSITION">
|
||||
<maxVehicleBoundingBox length="1000" width="1000" height="1000" referenceOffsetX="0" referenceOffsetY="0"/>
|
||||
<outgoingPath name="Point-0033 --- Point-0001"/>
|
||||
<pointLayout positionX="24000" positionY="15000" labelOffsetX="-10" labelOffsetY="-20" layerId="0"/>
|
||||
</point>
|
||||
<point name="Point-0034" positionX="16000" positionY="11000" positionZ="0" vehicleOrientationAngle="NaN" type="HALT_POSITION">
|
||||
<maxVehicleBoundingBox length="1000" width="1000" height="1000" referenceOffsetX="0" referenceOffsetY="0"/>
|
||||
<outgoingPath name="Point-0034 --- Point-0014"/>
|
||||
<outgoingPath name="Point-0034 --- Point-0033"/>
|
||||
<pointLayout positionX="16000" positionY="11000" labelOffsetX="-10" labelOffsetY="-20" layerId="0"/>
|
||||
</point>
|
||||
<point name="Point-0035" positionX="3000" positionY="11000" positionZ="0" vehicleOrientationAngle="NaN" type="HALT_POSITION">
|
||||
<maxVehicleBoundingBox length="1000" width="1000" height="1000" referenceOffsetX="0" referenceOffsetY="0"/>
|
||||
<outgoingPath name="Point-0035 --- Point-0036"/>
|
||||
<pointLayout positionX="3000" positionY="11000" labelOffsetX="-10" labelOffsetY="-20" layerId="0"/>
|
||||
</point>
|
||||
<point name="Point-0036" positionX="9000" positionY="11000" positionZ="0" vehicleOrientationAngle="NaN" type="HALT_POSITION">
|
||||
<maxVehicleBoundingBox length="1000" width="1000" height="1000" referenceOffsetX="0" referenceOffsetY="0"/>
|
||||
<outgoingPath name="Point-0036 --- Point-0034"/>
|
||||
<pointLayout positionX="9000" positionY="11000" labelOffsetX="-10" labelOffsetY="-20" layerId="0"/>
|
||||
</point>
|
||||
<point name="Point-0037" positionX="-8000" positionY="7000" positionZ="0" vehicleOrientationAngle="NaN" type="HALT_POSITION">
|
||||
<maxVehicleBoundingBox length="1000" width="1000" height="1000" referenceOffsetX="0" referenceOffsetY="0"/>
|
||||
<outgoingPath name="Point-0037 --- Point-0028"/>
|
||||
<pointLayout positionX="-8000" positionY="7000" labelOffsetX="-10" labelOffsetY="-20" layerId="0"/>
|
||||
</point>
|
||||
<point name="Point-0038" positionX="-2000" positionY="7000" positionZ="0" vehicleOrientationAngle="NaN" type="HALT_POSITION">
|
||||
<maxVehicleBoundingBox length="1000" width="1000" height="1000" referenceOffsetX="0" referenceOffsetY="0"/>
|
||||
<outgoingPath name="Point-0038 --- Point-0037"/>
|
||||
<pointLayout positionX="-2000" positionY="7000" labelOffsetX="-10" labelOffsetY="-20" layerId="0"/>
|
||||
</point>
|
||||
<point name="Point-0039" positionX="-13000" positionY="9000" positionZ="0" vehicleOrientationAngle="NaN" type="HALT_POSITION">
|
||||
<maxVehicleBoundingBox length="1000" width="1000" height="1000" referenceOffsetX="0" referenceOffsetY="0"/>
|
||||
<outgoingPath name="Point-0039 --- Point-0040"/>
|
||||
<pointLayout positionX="-13000" positionY="9000" labelOffsetX="-10" labelOffsetY="-20" layerId="0"/>
|
||||
</point>
|
||||
<point name="Point-0040" positionX="-8000" positionY="9000" positionZ="0" vehicleOrientationAngle="NaN" type="HALT_POSITION">
|
||||
<maxVehicleBoundingBox length="1000" width="1000" height="1000" referenceOffsetX="0" referenceOffsetY="0"/>
|
||||
<outgoingPath name="Point-0040 --- Point-0041"/>
|
||||
<pointLayout positionX="-8000" positionY="9000" labelOffsetX="-10" labelOffsetY="-20" layerId="0"/>
|
||||
</point>
|
||||
<point name="Point-0041" positionX="-2000" positionY="9000" positionZ="0" vehicleOrientationAngle="NaN" type="HALT_POSITION">
|
||||
<maxVehicleBoundingBox length="1000" width="1000" height="1000" referenceOffsetX="0" referenceOffsetY="0"/>
|
||||
<outgoingPath name="Point-0041 --- Point-0035"/>
|
||||
<pointLayout positionX="-2000" positionY="9000" labelOffsetX="-10" labelOffsetY="-20" layerId="0"/>
|
||||
</point>
|
||||
<point name="Point-0042" positionX="-20000" positionY="9000" positionZ="0" vehicleOrientationAngle="NaN" type="HALT_POSITION">
|
||||
<maxVehicleBoundingBox length="1000" width="1000" height="1000" referenceOffsetX="0" referenceOffsetY="0"/>
|
||||
<outgoingPath name="Point-0042 --- Point-0039"/>
|
||||
<pointLayout positionX="-20000" positionY="9000" labelOffsetX="-10" labelOffsetY="-20" layerId="0"/>
|
||||
</point>
|
||||
<point name="Point-0043" positionX="-11000" positionY="5000" positionZ="0" vehicleOrientationAngle="NaN" type="HALT_POSITION">
|
||||
<maxVehicleBoundingBox length="1000" width="1000" height="1000" referenceOffsetX="0" referenceOffsetY="0"/>
|
||||
<outgoingPath name="Point-0043 --- Point-0052"/>
|
||||
<pointLayout positionX="-11000" positionY="5000" labelOffsetX="-10" labelOffsetY="-20" layerId="0"/>
|
||||
</point>
|
||||
<point name="Point-0044" positionX="7000" positionY="5000" positionZ="0" vehicleOrientationAngle="NaN" type="HALT_POSITION">
|
||||
<maxVehicleBoundingBox length="1000" width="1000" height="1000" referenceOffsetX="0" referenceOffsetY="0"/>
|
||||
<outgoingPath name="Point-0044 --- Point-0047"/>
|
||||
<pointLayout positionX="7000" positionY="5000" labelOffsetX="-10" labelOffsetY="-20" layerId="0"/>
|
||||
</point>
|
||||
<point name="Point-0045" positionX="7000" positionY="-7000" positionZ="0" vehicleOrientationAngle="NaN" type="HALT_POSITION">
|
||||
<maxVehicleBoundingBox length="1000" width="1000" height="1000" referenceOffsetX="0" referenceOffsetY="0"/>
|
||||
<outgoingPath name="Point-0045 --- Point-0016"/>
|
||||
<outgoingPath name="Point-0045 --- Point-0055"/>
|
||||
<pointLayout positionX="7000" positionY="-7000" labelOffsetX="-10" labelOffsetY="-20" layerId="0"/>
|
||||
</point>
|
||||
<point name="Point-0046" positionX="-11000" positionY="-7000" positionZ="0" vehicleOrientationAngle="NaN" type="HALT_POSITION">
|
||||
<maxVehicleBoundingBox length="1000" width="1000" height="1000" referenceOffsetX="0" referenceOffsetY="0"/>
|
||||
<outgoingPath name="Point-0046 --- Point-0054"/>
|
||||
<pointLayout positionX="-11000" positionY="-7000" labelOffsetX="-10" labelOffsetY="-20" layerId="0"/>
|
||||
</point>
|
||||
<point name="Point-0047" positionX="11000" positionY="1000" positionZ="0" vehicleOrientationAngle="NaN" type="HALT_POSITION">
|
||||
<maxVehicleBoundingBox length="1000" width="1000" height="1000" referenceOffsetX="0" referenceOffsetY="0"/>
|
||||
<outgoingPath name="Point-0047 --- Point-0053"/>
|
||||
<pointLayout positionX="11000" positionY="1000" labelOffsetX="-10" labelOffsetY="-20" layerId="0"/>
|
||||
</point>
|
||||
<point name="Point-0048" positionX="-15000" positionY="1000" positionZ="0" vehicleOrientationAngle="NaN" type="HALT_POSITION">
|
||||
<maxVehicleBoundingBox length="1000" width="1000" height="1000" referenceOffsetX="0" referenceOffsetY="0"/>
|
||||
<outgoingPath name="Point-0048 --- Point-0043"/>
|
||||
<pointLayout positionX="-15000" positionY="1000" labelOffsetX="-10" labelOffsetY="-20" layerId="0"/>
|
||||
</point>
|
||||
<point name="Point-0049" positionX="2000" positionY="3000" positionZ="0" vehicleOrientationAngle="NaN" type="HALT_POSITION">
|
||||
<maxVehicleBoundingBox length="1000" width="1000" height="1000" referenceOffsetX="0" referenceOffsetY="0"/>
|
||||
<outgoingPath name="Point-0049 --- Point-0038"/>
|
||||
<pointLayout positionX="2000" positionY="3000" labelOffsetX="-10" labelOffsetY="-20" layerId="0"/>
|
||||
</point>
|
||||
<point name="Point-0050" positionX="2000" positionY="-5000" positionZ="0" vehicleOrientationAngle="NaN" type="HALT_POSITION">
|
||||
<maxVehicleBoundingBox length="1000" width="1000" height="1000" referenceOffsetX="0" referenceOffsetY="0"/>
|
||||
<outgoingPath name="Point-0050 --- Point-0051"/>
|
||||
<pointLayout positionX="2000" positionY="-5000" labelOffsetX="-10" labelOffsetY="-20" layerId="0"/>
|
||||
</point>
|
||||
<point name="Point-0051" positionX="2000" positionY="-1000" positionZ="0" vehicleOrientationAngle="NaN" type="HALT_POSITION">
|
||||
<maxVehicleBoundingBox length="1000" width="1000" height="1000" referenceOffsetX="0" referenceOffsetY="0"/>
|
||||
<outgoingPath name="Point-0051 --- Point-0049"/>
|
||||
<pointLayout positionX="2000" positionY="-1000" labelOffsetX="-10" labelOffsetY="-20" layerId="0"/>
|
||||
</point>
|
||||
<point name="Point-0052" positionX="-2000" positionY="5000" positionZ="0" vehicleOrientationAngle="NaN" type="HALT_POSITION">
|
||||
<maxVehicleBoundingBox length="1000" width="1000" height="1000" referenceOffsetX="0" referenceOffsetY="0"/>
|
||||
<outgoingPath name="Point-0052 --- Point-0044"/>
|
||||
<pointLayout positionX="-2000" positionY="5000" labelOffsetX="-10" labelOffsetY="-20" layerId="0"/>
|
||||
</point>
|
||||
<point name="Point-0053" positionX="11000" positionY="-3000" positionZ="0" vehicleOrientationAngle="NaN" type="HALT_POSITION">
|
||||
<maxVehicleBoundingBox length="1000" width="1000" height="1000" referenceOffsetX="0" referenceOffsetY="0"/>
|
||||
<outgoingPath name="Point-0053 --- Point-0045"/>
|
||||
<pointLayout positionX="11000" positionY="-3000" labelOffsetX="-10" labelOffsetY="-20" layerId="0"/>
|
||||
</point>
|
||||
<point name="Point-0054" positionX="-15000" positionY="-3000" positionZ="0" vehicleOrientationAngle="NaN" type="HALT_POSITION">
|
||||
<maxVehicleBoundingBox length="1000" width="1000" height="1000" referenceOffsetX="0" referenceOffsetY="0"/>
|
||||
<outgoingPath name="Point-0054 --- Point-0048"/>
|
||||
<pointLayout positionX="-15000" positionY="-3000" labelOffsetX="-10" labelOffsetY="-20" layerId="0"/>
|
||||
</point>
|
||||
<point name="Point-0055" positionX="-2000" positionY="-7000" positionZ="0" vehicleOrientationAngle="NaN" type="HALT_POSITION">
|
||||
<maxVehicleBoundingBox length="1000" width="1000" height="1000" referenceOffsetX="0" referenceOffsetY="0"/>
|
||||
<outgoingPath name="Point-0055 --- Point-0046"/>
|
||||
<pointLayout positionX="-2000" positionY="-7000" labelOffsetX="-10" labelOffsetY="-20" layerId="0"/>
|
||||
</point>
|
||||
<point name="Point-0056" positionX="-20000" positionY="-8000" positionZ="0" vehicleOrientationAngle="NaN" type="HALT_POSITION">
|
||||
<maxVehicleBoundingBox length="1000" width="1000" height="1000" referenceOffsetX="0" referenceOffsetY="0"/>
|
||||
<outgoingPath name="Point-0056 --- Point-0023"/>
|
||||
<pointLayout positionX="-20000" positionY="-8000" labelOffsetX="-10" labelOffsetY="-20" layerId="0"/>
|
||||
</point>
|
||||
<point name="Point-0057" positionX="8000" positionY="-21000" positionZ="0" vehicleOrientationAngle="NaN" type="HALT_POSITION">
|
||||
<maxVehicleBoundingBox length="1000" width="1000" height="1000" referenceOffsetX="0" referenceOffsetY="0"/>
|
||||
<outgoingPath name="Point-0057 --- Point-0058"/>
|
||||
<pointLayout positionX="8000" positionY="-21000" labelOffsetX="-10" labelOffsetY="-20" layerId="0"/>
|
||||
</point>
|
||||
<point name="Point-0058" positionX="-2000" positionY="-21000" positionZ="0" vehicleOrientationAngle="NaN" type="HALT_POSITION">
|
||||
<maxVehicleBoundingBox length="1000" width="1000" height="1000" referenceOffsetX="0" referenceOffsetY="0"/>
|
||||
<outgoingPath name="Point-0058 --- Point-0059"/>
|
||||
<pointLayout positionX="-2000" positionY="-21000" labelOffsetX="-10" labelOffsetY="-20" layerId="0"/>
|
||||
</point>
|
||||
<point name="Point-0059" positionX="-12000" positionY="-21000" positionZ="0" vehicleOrientationAngle="NaN" type="HALT_POSITION">
|
||||
<maxVehicleBoundingBox length="1000" width="1000" height="1000" referenceOffsetX="0" referenceOffsetY="0"/>
|
||||
<outgoingPath name="Point-0059 --- Point-0060"/>
|
||||
<pointLayout positionX="-12000" positionY="-21000" labelOffsetX="-10" labelOffsetY="-20" layerId="0"/>
|
||||
</point>
|
||||
<point name="Point-0060" positionX="-20000" positionY="-21000" positionZ="0" vehicleOrientationAngle="NaN" type="HALT_POSITION">
|
||||
<maxVehicleBoundingBox length="1000" width="1000" height="1000" referenceOffsetX="0" referenceOffsetY="0"/>
|
||||
<outgoingPath name="Point-0060 --- Point-0061"/>
|
||||
<pointLayout positionX="-20000" positionY="-21000" labelOffsetX="-10" labelOffsetY="-20" layerId="0"/>
|
||||
</point>
|
||||
<point name="Point-0061" positionX="-24000" positionY="-15000" positionZ="0" vehicleOrientationAngle="NaN" type="HALT_POSITION">
|
||||
<maxVehicleBoundingBox length="1000" width="1000" height="1000" referenceOffsetX="0" referenceOffsetY="0"/>
|
||||
<outgoingPath name="Point-0061 --- Point-0021"/>
|
||||
<pointLayout positionX="-24000" positionY="-15000" labelOffsetX="-10" labelOffsetY="-20" layerId="0"/>
|
||||
</point>
|
||||
<path name="Point-0001 --- Point-0002" sourcePoint="Point-0001" destinationPoint="Point-0002" length="4383" maxVelocity="1000" maxReverseVelocity="0" locked="false">
|
||||
<pathLayout connectionType="BEZIER" layerId="0">
|
||||
<controlPoint x="610" y="-180"/>
|
||||
<controlPoint x="610" y="-180"/>
|
||||
</pathLayout>
|
||||
</path>
|
||||
<path name="Point-0001 --- Point-0003" sourcePoint="Point-0001" destinationPoint="Point-0003" length="5629" maxVelocity="1000" maxReverseVelocity="0" locked="false">
|
||||
<pathLayout connectionType="DIRECT" layerId="0"/>
|
||||
</path>
|
||||
<path name="Point-0002 --- Point-0004" sourcePoint="Point-0002" destinationPoint="Point-0004" length="6000" maxVelocity="500" maxReverseVelocity="0" locked="false">
|
||||
<pathLayout connectionType="DIRECT" layerId="0"/>
|
||||
</path>
|
||||
<path name="Point-0002 --- Point-0014" sourcePoint="Point-0002" destinationPoint="Point-0014" length="4267" maxVelocity="1000" maxReverseVelocity="0" locked="false">
|
||||
<pathLayout connectionType="BEZIER" layerId="0">
|
||||
<controlPoint x="450" y="-174"/>
|
||||
<controlPoint x="450" y="-174"/>
|
||||
</pathLayout>
|
||||
</path>
|
||||
<path name="Point-0003 --- Point-0004" sourcePoint="Point-0003" destinationPoint="Point-0004" length="4336" maxVelocity="1000" maxReverseVelocity="0" locked="false">
|
||||
<pathLayout connectionType="BEZIER" layerId="0">
|
||||
<controlPoint x="610" y="-60"/>
|
||||
<controlPoint x="610" y="-60"/>
|
||||
</pathLayout>
|
||||
</path>
|
||||
<path name="Point-0003 --- Point-0005" sourcePoint="Point-0003" destinationPoint="Point-0005" length="5629" maxVelocity="1000" maxReverseVelocity="0" locked="false">
|
||||
<pathLayout connectionType="DIRECT" layerId="0"/>
|
||||
</path>
|
||||
<path name="Point-0004 --- Point-0006" sourcePoint="Point-0004" destinationPoint="Point-0006" length="6000" maxVelocity="500" maxReverseVelocity="0" locked="false">
|
||||
<pathLayout connectionType="DIRECT" layerId="0"/>
|
||||
</path>
|
||||
<path name="Point-0004 --- Point-0008" sourcePoint="Point-0004" destinationPoint="Point-0008" length="4302" maxVelocity="1000" maxReverseVelocity="0" locked="false">
|
||||
<pathLayout connectionType="BEZIER" layerId="0">
|
||||
<controlPoint x="449" y="-54"/>
|
||||
<controlPoint x="449" y="-54"/>
|
||||
</pathLayout>
|
||||
</path>
|
||||
<path name="Point-0005 --- Point-0006" sourcePoint="Point-0005" destinationPoint="Point-0006" length="4423" maxVelocity="1000" maxReverseVelocity="0" locked="false">
|
||||
<pathLayout connectionType="BEZIER" layerId="0">
|
||||
<controlPoint x="610" y="60"/>
|
||||
<controlPoint x="610" y="60"/>
|
||||
</pathLayout>
|
||||
</path>
|
||||
<path name="Point-0005 --- Point-0007" sourcePoint="Point-0005" destinationPoint="Point-0007" length="5629" maxVelocity="1000" maxReverseVelocity="0" locked="false">
|
||||
<pathLayout connectionType="DIRECT" layerId="0"/>
|
||||
</path>
|
||||
<path name="Point-0006 --- Point-0009" sourcePoint="Point-0006" destinationPoint="Point-0009" length="4302" maxVelocity="1000" maxReverseVelocity="0" locked="false">
|
||||
<pathLayout connectionType="BEZIER" layerId="0">
|
||||
<controlPoint x="449" y="65"/>
|
||||
<controlPoint x="449" y="65"/>
|
||||
</pathLayout>
|
||||
</path>
|
||||
<path name="Point-0006 --- Point-0010" sourcePoint="Point-0006" destinationPoint="Point-0010" length="6000" maxVelocity="500" maxReverseVelocity="0" locked="false">
|
||||
<pathLayout connectionType="DIRECT" layerId="0"/>
|
||||
</path>
|
||||
<path name="Point-0007 --- Point-0010" sourcePoint="Point-0007" destinationPoint="Point-0010" length="4379" maxVelocity="1000" maxReverseVelocity="0" locked="false">
|
||||
<pathLayout connectionType="BEZIER" layerId="0">
|
||||
<controlPoint x="610" y="180"/>
|
||||
<controlPoint x="610" y="180"/>
|
||||
</pathLayout>
|
||||
</path>
|
||||
<path name="Point-0008 --- Point-0009" sourcePoint="Point-0008" destinationPoint="Point-0009" length="5629" maxVelocity="1000" maxReverseVelocity="0" locked="false">
|
||||
<pathLayout connectionType="DIRECT" layerId="0"/>
|
||||
</path>
|
||||
<path name="Point-0009 --- Point-0011" sourcePoint="Point-0009" destinationPoint="Point-0011" length="5629" maxVelocity="1000" maxReverseVelocity="0" locked="false">
|
||||
<pathLayout connectionType="DIRECT" layerId="0"/>
|
||||
</path>
|
||||
<path name="Point-0010 --- Point-0011" sourcePoint="Point-0010" destinationPoint="Point-0011" length="4302" maxVelocity="1000" maxReverseVelocity="0" locked="false">
|
||||
<pathLayout connectionType="BEZIER" layerId="0">
|
||||
<controlPoint x="449" y="185"/>
|
||||
<controlPoint x="449" y="185"/>
|
||||
</pathLayout>
|
||||
</path>
|
||||
<path name="Point-0011 --- Point-0013" sourcePoint="Point-0011" destinationPoint="Point-0013" length="6881" maxVelocity="1000" maxReverseVelocity="0" locked="false">
|
||||
<pathLayout connectionType="BEZIER" layerId="0">
|
||||
<controlPoint x="429" y="289"/>
|
||||
<controlPoint x="429" y="289"/>
|
||||
</pathLayout>
|
||||
</path>
|
||||
<path name="Point-0013 --- Point-0015" sourcePoint="Point-0013" destinationPoint="Point-0015" length="11449" maxVelocity="1000" maxReverseVelocity="0" locked="false">
|
||||
<pathLayout connectionType="BEZIER" layerId="0">
|
||||
<controlPoint x="253" y="287"/>
|
||||
<controlPoint x="213" y="233"/>
|
||||
</pathLayout>
|
||||
</path>
|
||||
<path name="Point-0013 --- Point-0018" sourcePoint="Point-0013" destinationPoint="Point-0018" length="9381" maxVelocity="1000" maxReverseVelocity="0" locked="false">
|
||||
<pathLayout connectionType="DIRECT" layerId="0"/>
|
||||
</path>
|
||||
<path name="Point-0013 --- Point-0057" sourcePoint="Point-0013" destinationPoint="Point-0057" length="11638" maxVelocity="1000" maxReverseVelocity="0" locked="false">
|
||||
<pathLayout connectionType="BEZIER" layerId="0">
|
||||
<controlPoint x="280" y="320"/>
|
||||
<controlPoint x="250" y="410"/>
|
||||
</pathLayout>
|
||||
</path>
|
||||
<path name="Point-0014 --- Point-0008" sourcePoint="Point-0014" destinationPoint="Point-0008" length="5629" maxVelocity="1000" maxReverseVelocity="0" locked="false">
|
||||
<pathLayout connectionType="DIRECT" layerId="0"/>
|
||||
</path>
|
||||
<path name="Point-0015 --- Point-0016" sourcePoint="Point-0015" destinationPoint="Point-0016" length="9241" maxVelocity="1000" maxReverseVelocity="0" locked="false">
|
||||
<pathLayout connectionType="DIRECT" layerId="0"/>
|
||||
</path>
|
||||
<path name="Point-0015 --- Point-0050" sourcePoint="Point-0015" destinationPoint="Point-0050" length="9861" maxVelocity="1000" maxReverseVelocity="0" locked="false">
|
||||
<pathLayout connectionType="BEZIER" layerId="0">
|
||||
<controlPoint x="60" y="199"/>
|
||||
<controlPoint x="60" y="199"/>
|
||||
</pathLayout>
|
||||
</path>
|
||||
<path name="Point-0016 --- Point-0017" sourcePoint="Point-0016" destinationPoint="Point-0017" length="11166" maxVelocity="1000" maxReverseVelocity="0" locked="false">
|
||||
<pathLayout connectionType="BEZIER" layerId="0">
|
||||
<controlPoint x="-126" y="233"/>
|
||||
<controlPoint x="-175" y="288"/>
|
||||
</pathLayout>
|
||||
</path>
|
||||
<path name="Point-0016 --- Point-0022" sourcePoint="Point-0016" destinationPoint="Point-0022" length="9381" maxVelocity="1000" maxReverseVelocity="0" locked="false">
|
||||
<pathLayout connectionType="DIRECT" layerId="0"/>
|
||||
</path>
|
||||
<path name="Point-0016 --- Point-0046" sourcePoint="Point-0016" destinationPoint="Point-0046" length="10093" maxVelocity="1000" maxReverseVelocity="0" locked="false">
|
||||
<pathLayout connectionType="BEZIER" layerId="0">
|
||||
<controlPoint x="-101" y="209"/>
|
||||
<controlPoint x="-159" y="153"/>
|
||||
</pathLayout>
|
||||
</path>
|
||||
<path name="Point-0017 --- Point-0020" sourcePoint="Point-0017" destinationPoint="Point-0020" length="8705" maxVelocity="1000" maxReverseVelocity="0" locked="false">
|
||||
<pathLayout connectionType="BEZIER" layerId="0">
|
||||
<controlPoint x="-293" y="292"/>
|
||||
<controlPoint x="-343" y="250"/>
|
||||
</pathLayout>
|
||||
</path>
|
||||
<path name="Point-0018 --- Point-0019" sourcePoint="Point-0018" destinationPoint="Point-0019" length="9381" maxVelocity="1000" maxReverseVelocity="0" locked="false">
|
||||
<pathLayout connectionType="DIRECT" layerId="0"/>
|
||||
</path>
|
||||
<path name="Point-0019 --- Point-0017" sourcePoint="Point-0019" destinationPoint="Point-0017" length="9381" maxVelocity="1000" maxReverseVelocity="0" locked="false">
|
||||
<pathLayout connectionType="DIRECT" layerId="0"/>
|
||||
</path>
|
||||
<path name="Point-0019 --- Point-0022" sourcePoint="Point-0019" destinationPoint="Point-0022" length="11062" maxVelocity="1000" maxReverseVelocity="0" locked="false">
|
||||
<pathLayout connectionType="BEZIER" layerId="0">
|
||||
<controlPoint x="-113" y="288"/>
|
||||
<controlPoint x="-169" y="233"/>
|
||||
</pathLayout>
|
||||
</path>
|
||||
<path name="Point-0020 --- Point-0021" sourcePoint="Point-0020" destinationPoint="Point-0021" length="6802" maxVelocity="1000" maxReverseVelocity="0" locked="false">
|
||||
<pathLayout connectionType="BEZIER" layerId="0">
|
||||
<controlPoint x="-465" y="230"/>
|
||||
<controlPoint x="-465" y="230"/>
|
||||
</pathLayout>
|
||||
</path>
|
||||
<path name="Point-0021 --- Point-0023" sourcePoint="Point-0021" destinationPoint="Point-0023" length="3752" maxVelocity="1000" maxReverseVelocity="0" locked="false">
|
||||
<pathLayout connectionType="DIRECT" layerId="0"/>
|
||||
</path>
|
||||
<path name="Point-0022 --- Point-0056" sourcePoint="Point-0022" destinationPoint="Point-0056" length="8680" maxVelocity="1000" maxReverseVelocity="0" locked="false">
|
||||
<pathLayout connectionType="BEZIER" layerId="0">
|
||||
<controlPoint x="-296" y="209"/>
|
||||
<controlPoint x="-344" y="169"/>
|
||||
</pathLayout>
|
||||
</path>
|
||||
<path name="Point-0023 --- Point-0024" sourcePoint="Point-0023" destinationPoint="Point-0024" length="4690" maxVelocity="1000" maxReverseVelocity="0" locked="false">
|
||||
<pathLayout connectionType="DIRECT" layerId="0"/>
|
||||
</path>
|
||||
<path name="Point-0024 --- Point-0025" sourcePoint="Point-0024" destinationPoint="Point-0025" length="4690" maxVelocity="1000" maxReverseVelocity="0" locked="false">
|
||||
<pathLayout connectionType="DIRECT" layerId="0"/>
|
||||
</path>
|
||||
<path name="Point-0025 --- Point-0026" sourcePoint="Point-0025" destinationPoint="Point-0026" length="4690" maxVelocity="1000" maxReverseVelocity="0" locked="false">
|
||||
<pathLayout connectionType="DIRECT" layerId="0"/>
|
||||
</path>
|
||||
<path name="Point-0025 --- Point-0030" sourcePoint="Point-0025" destinationPoint="Point-0030" length="7695" maxVelocity="1000" maxReverseVelocity="0" locked="false">
|
||||
<pathLayout connectionType="BEZIER" layerId="0">
|
||||
<controlPoint x="-467" y="-205"/>
|
||||
<controlPoint x="-467" y="-205"/>
|
||||
</pathLayout>
|
||||
</path>
|
||||
<path name="Point-0025 --- Point-0042" sourcePoint="Point-0025" destinationPoint="Point-0042" length="5992" maxVelocity="1000" maxReverseVelocity="0" locked="false">
|
||||
<pathLayout connectionType="BEZIER" layerId="0">
|
||||
<controlPoint x="-469" y="-169"/>
|
||||
<controlPoint x="-469" y="-169"/>
|
||||
</pathLayout>
|
||||
</path>
|
||||
<path name="Point-0026 --- Point-0027" sourcePoint="Point-0026" destinationPoint="Point-0027" length="6841" maxVelocity="1000" maxReverseVelocity="0" locked="false">
|
||||
<pathLayout connectionType="BEZIER" layerId="0">
|
||||
<controlPoint x="-468" y="-287"/>
|
||||
<controlPoint x="-468" y="-287"/>
|
||||
</pathLayout>
|
||||
</path>
|
||||
<path name="Point-0027 --- Point-0032" sourcePoint="Point-0027" destinationPoint="Point-0032" length="8657" maxVelocity="1000" maxReverseVelocity="0" locked="false">
|
||||
<pathLayout connectionType="BEZIER" layerId="0">
|
||||
<controlPoint x="-345" y="-287"/>
|
||||
<controlPoint x="-317" y="-233"/>
|
||||
</pathLayout>
|
||||
</path>
|
||||
<path name="Point-0028 --- Point-0029" sourcePoint="Point-0028" destinationPoint="Point-0029" length="5629" maxVelocity="1000" maxReverseVelocity="0" locked="false">
|
||||
<pathLayout connectionType="DIRECT" layerId="0"/>
|
||||
</path>
|
||||
<path name="Point-0029 --- Point-0035" sourcePoint="Point-0029" destinationPoint="Point-0035" length="4690" maxVelocity="1000" maxReverseVelocity="0" locked="false">
|
||||
<pathLayout connectionType="DIRECT" layerId="0"/>
|
||||
</path>
|
||||
<path name="Point-0030 --- Point-0032" sourcePoint="Point-0030" destinationPoint="Point-0032" length="6567" maxVelocity="1000" maxReverseVelocity="0" locked="false">
|
||||
<pathLayout connectionType="DIRECT" layerId="0"/>
|
||||
</path>
|
||||
<path name="Point-0032 --- Point-0028" sourcePoint="Point-0032" destinationPoint="Point-0028" length="4690" maxVelocity="1000" maxReverseVelocity="0" locked="false">
|
||||
<pathLayout connectionType="DIRECT" layerId="0"/>
|
||||
</path>
|
||||
<path name="Point-0033 --- Point-0001" sourcePoint="Point-0033" destinationPoint="Point-0001" length="6922" maxVelocity="1000" maxReverseVelocity="0" locked="false">
|
||||
<pathLayout connectionType="BEZIER" layerId="0">
|
||||
<controlPoint x="600" y="-300"/>
|
||||
<controlPoint x="600" y="-300"/>
|
||||
</pathLayout>
|
||||
</path>
|
||||
<path name="Point-0034 --- Point-0014" sourcePoint="Point-0034" destinationPoint="Point-0014" length="8731" maxVelocity="1000" maxReverseVelocity="0" locked="false">
|
||||
<pathLayout connectionType="BEZIER" layerId="0">
|
||||
<controlPoint x="423" y="-211"/>
|
||||
<controlPoint x="423" y="-211"/>
|
||||
</pathLayout>
|
||||
</path>
|
||||
<path name="Point-0034 --- Point-0033" sourcePoint="Point-0034" destinationPoint="Point-0033" length="9481" maxVelocity="1000" maxReverseVelocity="0" locked="false">
|
||||
<pathLayout connectionType="BEZIER" layerId="0">
|
||||
<controlPoint x="374" y="-231"/>
|
||||
<controlPoint x="408" y="-285"/>
|
||||
</pathLayout>
|
||||
</path>
|
||||
<path name="Point-0035 --- Point-0036" sourcePoint="Point-0035" destinationPoint="Point-0036" length="5629" maxVelocity="1000" maxReverseVelocity="0" locked="false">
|
||||
<pathLayout connectionType="DIRECT" layerId="0"/>
|
||||
</path>
|
||||
<path name="Point-0036 --- Point-0034" sourcePoint="Point-0036" destinationPoint="Point-0034" length="6567" maxVelocity="1000" maxReverseVelocity="0" locked="false">
|
||||
<pathLayout connectionType="DIRECT" layerId="0"/>
|
||||
</path>
|
||||
<path name="Point-0037 --- Point-0028" sourcePoint="Point-0037" destinationPoint="Point-0028" length="7582" maxVelocity="1000" maxReverseVelocity="0" locked="false">
|
||||
<pathLayout connectionType="BEZIER" layerId="0">
|
||||
<controlPoint x="-209" y="-154"/>
|
||||
<controlPoint x="-210" y="-202"/>
|
||||
</pathLayout>
|
||||
</path>
|
||||
<path name="Point-0038 --- Point-0037" sourcePoint="Point-0038" destinationPoint="Point-0037" length="5629" maxVelocity="1000" maxReverseVelocity="0" locked="false">
|
||||
<pathLayout connectionType="DIRECT" layerId="0"/>
|
||||
</path>
|
||||
<path name="Point-0039 --- Point-0040" sourcePoint="Point-0039" destinationPoint="Point-0040" length="4690" maxVelocity="1000" maxReverseVelocity="0" locked="false">
|
||||
<pathLayout connectionType="DIRECT" layerId="0"/>
|
||||
</path>
|
||||
<path name="Point-0040 --- Point-0041" sourcePoint="Point-0040" destinationPoint="Point-0041" length="5629" maxVelocity="1000" maxReverseVelocity="0" locked="false">
|
||||
<pathLayout connectionType="DIRECT" layerId="0"/>
|
||||
</path>
|
||||
<path name="Point-0041 --- Point-0035" sourcePoint="Point-0041" destinationPoint="Point-0035" length="5734" maxVelocity="1000" maxReverseVelocity="0" locked="false">
|
||||
<pathLayout connectionType="BEZIER" layerId="0">
|
||||
<controlPoint x="15" y="-186"/>
|
||||
<controlPoint x="31" y="-213"/>
|
||||
</pathLayout>
|
||||
</path>
|
||||
<path name="Point-0042 --- Point-0039" sourcePoint="Point-0042" destinationPoint="Point-0039" length="6567" maxVelocity="1000" maxReverseVelocity="0" locked="false">
|
||||
<pathLayout connectionType="DIRECT" layerId="0"/>
|
||||
</path>
|
||||
<path name="Point-0043 --- Point-0052" sourcePoint="Point-0043" destinationPoint="Point-0052" length="8443" maxVelocity="1000" maxReverseVelocity="0" locked="false">
|
||||
<pathLayout connectionType="DIRECT" layerId="0"/>
|
||||
</path>
|
||||
<path name="Point-0044 --- Point-0047" sourcePoint="Point-0044" destinationPoint="Point-0047" length="6881" maxVelocity="1000" maxReverseVelocity="0" locked="false">
|
||||
<pathLayout connectionType="BEZIER" layerId="0">
|
||||
<controlPoint x="209" y="-88"/>
|
||||
<controlPoint x="209" y="-88"/>
|
||||
</pathLayout>
|
||||
</path>
|
||||
<path name="Point-0045 --- Point-0016" sourcePoint="Point-0045" destinationPoint="Point-0016" length="10170" maxVelocity="1000" maxReverseVelocity="0" locked="false">
|
||||
<pathLayout connectionType="BEZIER" layerId="0">
|
||||
<controlPoint x="79" y="154"/>
|
||||
<controlPoint x="30" y="208"/>
|
||||
</pathLayout>
|
||||
</path>
|
||||
<path name="Point-0045 --- Point-0055" sourcePoint="Point-0045" destinationPoint="Point-0055" length="8443" maxVelocity="1000" maxReverseVelocity="0" locked="false">
|
||||
<pathLayout connectionType="DIRECT" layerId="0"/>
|
||||
</path>
|
||||
<path name="Point-0046 --- Point-0054" sourcePoint="Point-0046" destinationPoint="Point-0054" length="6800" maxVelocity="1000" maxReverseVelocity="0" locked="false">
|
||||
<pathLayout connectionType="BEZIER" layerId="0">
|
||||
<controlPoint x="-288" y="127"/>
|
||||
<controlPoint x="-288" y="127"/>
|
||||
</pathLayout>
|
||||
</path>
|
||||
<path name="Point-0047 --- Point-0053" sourcePoint="Point-0047" destinationPoint="Point-0053" length="3752" maxVelocity="1000" maxReverseVelocity="0" locked="false">
|
||||
<pathLayout connectionType="DIRECT" layerId="0"/>
|
||||
</path>
|
||||
<path name="Point-0048 --- Point-0043" sourcePoint="Point-0048" destinationPoint="Point-0043" length="6722" maxVelocity="1000" maxReverseVelocity="0" locked="false">
|
||||
<pathLayout connectionType="BEZIER" layerId="0">
|
||||
<controlPoint x="-287" y="-85"/>
|
||||
<controlPoint x="-287" y="-85"/>
|
||||
</pathLayout>
|
||||
</path>
|
||||
<path name="Point-0049 --- Point-0038" sourcePoint="Point-0049" destinationPoint="Point-0038" length="6882" maxVelocity="1000" maxReverseVelocity="0" locked="false">
|
||||
<pathLayout connectionType="BEZIER" layerId="0">
|
||||
<controlPoint x="30" y="-127"/>
|
||||
<controlPoint x="30" y="-127"/>
|
||||
</pathLayout>
|
||||
</path>
|
||||
<path name="Point-0050 --- Point-0051" sourcePoint="Point-0050" destinationPoint="Point-0051" length="3752" maxVelocity="1000" maxReverseVelocity="0" locked="false">
|
||||
<pathLayout connectionType="DIRECT" layerId="0"/>
|
||||
</path>
|
||||
<path name="Point-0051 --- Point-0049" sourcePoint="Point-0051" destinationPoint="Point-0049" length="3752" maxVelocity="1000" maxReverseVelocity="0" locked="false">
|
||||
<pathLayout connectionType="DIRECT" layerId="0"/>
|
||||
</path>
|
||||
<path name="Point-0052 --- Point-0044" sourcePoint="Point-0052" destinationPoint="Point-0044" length="8443" maxVelocity="1000" maxReverseVelocity="0" locked="false">
|
||||
<pathLayout connectionType="DIRECT" layerId="0"/>
|
||||
</path>
|
||||
<path name="Point-0053 --- Point-0045" sourcePoint="Point-0053" destinationPoint="Point-0045" length="6922" maxVelocity="1000" maxReverseVelocity="0" locked="false">
|
||||
<pathLayout connectionType="BEZIER" layerId="0">
|
||||
<controlPoint x="209" y="130"/>
|
||||
<controlPoint x="209" y="130"/>
|
||||
</pathLayout>
|
||||
</path>
|
||||
<path name="Point-0054 --- Point-0048" sourcePoint="Point-0054" destinationPoint="Point-0048" length="3752" maxVelocity="1000" maxReverseVelocity="0" locked="false">
|
||||
<pathLayout connectionType="DIRECT" layerId="0"/>
|
||||
</path>
|
||||
<path name="Point-0055 --- Point-0046" sourcePoint="Point-0055" destinationPoint="Point-0046" length="8443" maxVelocity="1000" maxReverseVelocity="0" locked="false">
|
||||
<pathLayout connectionType="DIRECT" layerId="0"/>
|
||||
</path>
|
||||
<path name="Point-0056 --- Point-0023" sourcePoint="Point-0056" destinationPoint="Point-0023" length="6882" maxVelocity="1000" maxReverseVelocity="0" locked="false">
|
||||
<pathLayout connectionType="BEZIER" layerId="0">
|
||||
<controlPoint x="-467" y="150"/>
|
||||
<controlPoint x="-467" y="150"/>
|
||||
</pathLayout>
|
||||
</path>
|
||||
<path name="Point-0057 --- Point-0058" sourcePoint="Point-0057" destinationPoint="Point-0058" length="10000" maxVelocity="1000" maxReverseVelocity="0" locked="false">
|
||||
<peripheralOperation completionRequired="true" executionTrigger="AFTER_ALLOCATION" locationName="Fire door 01" name="Open"/>
|
||||
<peripheralOperation completionRequired="false" executionTrigger="AFTER_MOVEMENT" locationName="Fire door 01" name="Close"/>
|
||||
<pathLayout connectionType="DIRECT" layerId="0"/>
|
||||
</path>
|
||||
<path name="Point-0058 --- Point-0059" sourcePoint="Point-0058" destinationPoint="Point-0059" length="10000" maxVelocity="1000" maxReverseVelocity="0" locked="false">
|
||||
<pathLayout connectionType="DIRECT" layerId="0"/>
|
||||
</path>
|
||||
<path name="Point-0059 --- Point-0060" sourcePoint="Point-0059" destinationPoint="Point-0060" length="8000" maxVelocity="1000" maxReverseVelocity="0" locked="false">
|
||||
<pathLayout connectionType="DIRECT" layerId="0"/>
|
||||
</path>
|
||||
<path name="Point-0060 --- Point-0061" sourcePoint="Point-0060" destinationPoint="Point-0061" length="7211" maxVelocity="1000" maxReverseVelocity="0" locked="false">
|
||||
<pathLayout connectionType="BEZIER" layerId="0">
|
||||
<controlPoint x="-470" y="410"/>
|
||||
<controlPoint x="-470" y="370"/>
|
||||
</pathLayout>
|
||||
</path>
|
||||
<path name="Point-0061 --- Point-0021" sourcePoint="Point-0061" destinationPoint="Point-0021" length="8000" maxVelocity="1000" maxReverseVelocity="0" locked="false">
|
||||
<pathLayout connectionType="DIRECT" layerId="0"/>
|
||||
</path>
|
||||
<vehicle name="Vehicle-01" energyLevelCritical="30" energyLevelGood="90" energyLevelFullyRecharged="95" energyLevelSufficientlyRecharged="45" maxVelocity="1000" maxReverseVelocity="1000">
|
||||
<boundingBox length="1000" width="1000" height="1000" referenceOffsetX="0" referenceOffsetY="0"/>
|
||||
<property name="loopback:loadOperation" value="Load cargo"/>
|
||||
<property name="loopback:unloadOperation" value="Unload cargo"/>
|
||||
<vehicleLayout color="#FF0000"/>
|
||||
</vehicle>
|
||||
<vehicle name="Vehicle-02" energyLevelCritical="30" energyLevelGood="90" energyLevelFullyRecharged="95" energyLevelSufficientlyRecharged="45" maxVelocity="1000" maxReverseVelocity="1000">
|
||||
<boundingBox length="1000" width="1000" height="1000" referenceOffsetX="0" referenceOffsetY="0"/>
|
||||
<property name="loopback:loadOperation" value="Load cargo"/>
|
||||
<property name="loopback:unloadOperation" value="Unload cargo"/>
|
||||
<vehicleLayout color="#33FF00"/>
|
||||
</vehicle>
|
||||
<vehicle name="Vehicle-03" energyLevelCritical="30" energyLevelGood="90" energyLevelFullyRecharged="95" energyLevelSufficientlyRecharged="45" maxVelocity="1000" maxReverseVelocity="1000">
|
||||
<boundingBox length="1000" width="1000" height="1000" referenceOffsetX="0" referenceOffsetY="0"/>
|
||||
<property name="loopback:loadOperation" value="Load cargo"/>
|
||||
<property name="loopback:unloadOperation" value="Unload cargo"/>
|
||||
<vehicleLayout color="#00FFFF"/>
|
||||
</vehicle>
|
||||
<vehicle name="Vehicle-04" energyLevelCritical="30" energyLevelGood="90" energyLevelFullyRecharged="95" energyLevelSufficientlyRecharged="45" maxVelocity="1000" maxReverseVelocity="1000">
|
||||
<boundingBox length="1000" width="1000" height="1000" referenceOffsetX="0" referenceOffsetY="0"/>
|
||||
<property name="loopback:loadOperation" value="Load cargo"/>
|
||||
<property name="loopback:unloadOperation" value="Unload cargo"/>
|
||||
<vehicleLayout color="#FF33FF"/>
|
||||
</vehicle>
|
||||
<locationType name="Fire door">
|
||||
<allowedPeripheralOperation name="Close"/>
|
||||
<allowedPeripheralOperation name="Open"/>
|
||||
<property name="tcs:defaultLocationTypeSymbol" value="NONE"/>
|
||||
<locationTypeLayout locationRepresentation="NONE"/>
|
||||
</locationType>
|
||||
<locationType name="Recharge station">
|
||||
<allowedOperation name="CHARGE"/>
|
||||
<allowedOperation name="NOP"/>
|
||||
<property name="tcs:defaultLocationSymbol" value="RECHARGE_GENERIC"/>
|
||||
<property name="tcs:defaultLocationTypeSymbol" value="RECHARGE_GENERIC"/>
|
||||
<locationTypeLayout locationRepresentation="RECHARGE_GENERIC"/>
|
||||
</locationType>
|
||||
<locationType name="Transfer station">
|
||||
<allowedOperation name="Load cargo"/>
|
||||
<allowedOperation name="NOP"/>
|
||||
<allowedOperation name="Unload cargo"/>
|
||||
<property name="tcs:defaultLocationSymbol" value="LOAD_TRANSFER_GENERIC"/>
|
||||
<property name="tcs:defaultLocationTypeSymbol" value="LOAD_TRANSFER_GENERIC"/>
|
||||
<locationTypeLayout locationRepresentation="LOAD_TRANSFER_GENERIC"/>
|
||||
</locationType>
|
||||
<locationType name="Working station">
|
||||
<allowedOperation name="Cut"/>
|
||||
<allowedOperation name="Drill"/>
|
||||
<allowedOperation name="NOP"/>
|
||||
<property name="tcs:defaultLocationSymbol" value="WORKING_GENERIC"/>
|
||||
<property name="tcs:defaultLocationTypeSymbol" value="WORKING_GENERIC"/>
|
||||
<locationTypeLayout locationRepresentation="WORKING_GENERIC"/>
|
||||
</locationType>
|
||||
<location name="Fire door 01" positionX="3500" positionY="-21000" positionZ="0" locked="false" type="Fire door">
|
||||
<property name="tcs:defaultLocationSymbol" value="DEFAULT"/>
|
||||
<property name="tcs:loopbackPeripheral" value="Value unknown"/>
|
||||
<locationLayout positionX="3500" positionY="-21000" labelOffsetX="-10" labelOffsetY="-20" locationRepresentation="DEFAULT" layerId="0"/>
|
||||
</location>
|
||||
<location name="Goods in north 01" positionX="-28000" positionY="11000" positionZ="0" locked="false" type="Transfer station">
|
||||
<link point="Point-0026"/>
|
||||
<property name="tcs:defaultLocationSymbol" value="DEFAULT"/>
|
||||
<locationLayout positionX="-28000" positionY="11000" labelOffsetX="-10" labelOffsetY="-20" locationRepresentation="DEFAULT" layerId="0"/>
|
||||
</location>
|
||||
<location name="Goods in north 02" positionX="-28000" positionY="6000" positionZ="0" locked="false" type="Transfer station">
|
||||
<link point="Point-0025"/>
|
||||
<property name="tcs:defaultLocationSymbol" value="DEFAULT"/>
|
||||
<locationLayout positionX="-28000" positionY="6000" labelOffsetX="-10" labelOffsetY="-20" locationRepresentation="DEFAULT" layerId="0"/>
|
||||
</location>
|
||||
<location name="Goods in south 01" positionX="-2000" positionY="-18000" positionZ="0" locked="false" type="Transfer station">
|
||||
<link point="Point-0019"/>
|
||||
<property name="tcs:defaultLocationSymbol" value="DEFAULT"/>
|
||||
<locationLayout positionX="-2000" positionY="-18000" labelOffsetX="-10" labelOffsetY="-20" locationRepresentation="DEFAULT" layerId="0"/>
|
||||
</location>
|
||||
<location name="Goods in south 02" positionX="-12000" positionY="-24000" positionZ="0" locked="false" type="Transfer station">
|
||||
<link point="Point-0059"/>
|
||||
<property name="tcs:defaultLocationSymbol" value="DEFAULT"/>
|
||||
<locationLayout positionX="-12000" positionY="-24000" labelOffsetX="-10" labelOffsetY="-20" locationRepresentation="DEFAULT" layerId="0"/>
|
||||
</location>
|
||||
<location name="Goods out 01" positionX="-20000" positionY="-15000" positionZ="0" locked="false" type="Transfer station">
|
||||
<link point="Point-0020"/>
|
||||
<property name="tcs:defaultLocationSymbol" value="DEFAULT"/>
|
||||
<locationLayout positionX="-20000" positionY="-15000" labelOffsetX="-10" labelOffsetY="-20" locationRepresentation="DEFAULT" layerId="0"/>
|
||||
</location>
|
||||
<location name="Goods out 02" positionX="-28000" positionY="-8000" positionZ="0" locked="false" type="Transfer station">
|
||||
<link point="Point-0021"/>
|
||||
<property name="tcs:defaultLocationSymbol" value="DEFAULT"/>
|
||||
<locationLayout positionX="-28000" positionY="-8000" labelOffsetX="-10" labelOffsetY="-20" locationRepresentation="DEFAULT" layerId="0"/>
|
||||
</location>
|
||||
<location name="Recharge 01" positionX="27750" positionY="6750" positionZ="0" locked="false" type="Recharge station">
|
||||
<link point="Point-0002"/>
|
||||
<property name="tcs:defaultLocationSymbol" value="DEFAULT"/>
|
||||
<locationLayout positionX="27750" positionY="6250" labelOffsetX="-10" labelOffsetY="-20" locationRepresentation="DEFAULT" layerId="0"/>
|
||||
</location>
|
||||
<location name="Recharge 02" positionX="27750" positionY="750" positionZ="0" locked="false" type="Recharge station">
|
||||
<link point="Point-0004"/>
|
||||
<property name="tcs:defaultLocationSymbol" value="DEFAULT"/>
|
||||
<locationLayout positionX="27750" positionY="250" labelOffsetX="-10" labelOffsetY="-20" locationRepresentation="DEFAULT" layerId="0"/>
|
||||
</location>
|
||||
<location name="Recharge 03" positionX="27750" positionY="-5250" positionZ="0" locked="false" type="Recharge station">
|
||||
<link point="Point-0006"/>
|
||||
<property name="tcs:defaultLocationSymbol" value="DEFAULT"/>
|
||||
<locationLayout positionX="27750" positionY="-5750" labelOffsetX="-10" labelOffsetY="-20" locationRepresentation="DEFAULT" layerId="0"/>
|
||||
</location>
|
||||
<location name="Recharge 04" positionX="27750" positionY="-11250" positionZ="0" locked="false" type="Recharge station">
|
||||
<link point="Point-0010"/>
|
||||
<property name="tcs:defaultLocationSymbol" value="DEFAULT"/>
|
||||
<locationLayout positionX="27750" positionY="-11750" labelOffsetX="-10" labelOffsetY="-20" locationRepresentation="DEFAULT" layerId="0"/>
|
||||
</location>
|
||||
<location name="Storage 01" positionX="-8000" positionY="14000" positionZ="0" locked="false" type="Transfer station">
|
||||
<link point="Point-0028"/>
|
||||
<property name="tcs:defaultLocationSymbol" value="DEFAULT"/>
|
||||
<locationLayout positionX="-8000" positionY="14000" labelOffsetX="-10" labelOffsetY="-20" locationRepresentation="DEFAULT" layerId="0"/>
|
||||
</location>
|
||||
<location name="Storage 02" positionX="-2000" positionY="14000" positionZ="0" locked="false" type="Transfer station">
|
||||
<link point="Point-0029"/>
|
||||
<property name="tcs:defaultLocationSymbol" value="DEFAULT"/>
|
||||
<locationLayout positionX="-2000" positionY="14000" labelOffsetX="-10" labelOffsetY="-20" locationRepresentation="DEFAULT" layerId="0"/>
|
||||
</location>
|
||||
<location name="Working station 01" positionX="-11000" positionY="-3000" positionZ="0" locked="false" type="Working station">
|
||||
<link point="Point-0054"/>
|
||||
<property name="tcs:defaultLocationSymbol" value="DEFAULT"/>
|
||||
<locationLayout positionX="-11000" positionY="-3000" labelOffsetX="-10" labelOffsetY="-20" locationRepresentation="DEFAULT" layerId="0"/>
|
||||
</location>
|
||||
<location name="Working station 02" positionX="15000" positionY="1000" positionZ="0" locked="false" type="Working station">
|
||||
<link point="Point-0047"/>
|
||||
<property name="tcs:defaultLocationSymbol" value="DEFAULT"/>
|
||||
<locationLayout positionX="15000" positionY="1000" labelOffsetX="-10" labelOffsetY="-20" locationRepresentation="DEFAULT" layerId="0"/>
|
||||
</location>
|
||||
<location name="Working station 03" positionX="15000" positionY="-3000" positionZ="0" locked="false" type="Working station">
|
||||
<link point="Point-0053"/>
|
||||
<property name="tcs:defaultLocationSymbol" value="DEFAULT"/>
|
||||
<locationLayout positionX="15000" positionY="-3000" labelOffsetX="-10" labelOffsetY="-20" locationRepresentation="DEFAULT" layerId="0"/>
|
||||
</location>
|
||||
<block name="Block-0001" type="SINGLE_VEHICLE_ONLY">
|
||||
<member name="Point-0016 --- Point-0017"/>
|
||||
<member name="Point-0019 --- Point-0022"/>
|
||||
<blockLayout color="#FF0000"/>
|
||||
</block>
|
||||
<block name="Block-0002" type="SINGLE_VEHICLE_ONLY">
|
||||
<member name="Point-0037 --- Point-0028"/>
|
||||
<member name="Point-0039 --- Point-0040"/>
|
||||
<blockLayout color="#0000FF"/>
|
||||
</block>
|
||||
<block name="Block-0003" type="SINGLE_VEHICLE_ONLY">
|
||||
<member name="Point-0049 --- Point-0038"/>
|
||||
<member name="Point-0052 --- Point-0044"/>
|
||||
<blockLayout color="#00CC00"/>
|
||||
</block>
|
||||
<block name="Block-0004" type="SINGLE_VEHICLE_ONLY">
|
||||
<member name="Point-0015 --- Point-0050"/>
|
||||
<member name="Point-0045 --- Point-0016"/>
|
||||
<member name="Point-0045 --- Point-0055"/>
|
||||
<blockLayout color="#0099FF"/>
|
||||
</block>
|
||||
<visualLayout name="VLayout-01" scaleX="50.0" scaleY="50.0">
|
||||
<layer id="0" ordinal="0" visible="true" name="Default layer" groupId="0"/>
|
||||
<layerGroup id="0" name="Default layer group" visible="true"/>
|
||||
</visualLayout>
|
||||
<property name="tcs:modelFileLastModified" value="2024-09-12T12:01:37Z"/>
|
||||
</model>
|
||||
2
opentcs-modeleditor/src/dist/data/Demo-01.xml.license
vendored
Normal file
2
opentcs-modeleditor/src/dist/data/Demo-01.xml.license
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
# SPDX-FileCopyrightText: The openTCS Authors
|
||||
# SPDX-License-Identifier: CC-BY-4.0
|
||||
0
opentcs-modeleditor/src/dist/lib/openTCS-extensions/.keepme
vendored
Normal file
0
opentcs-modeleditor/src/dist/lib/openTCS-extensions/.keepme
vendored
Normal file
0
opentcs-modeleditor/src/dist/log/.keepme
vendored
Normal file
0
opentcs-modeleditor/src/dist/log/.keepme
vendored
Normal file
38
opentcs-modeleditor/src/dist/startModelEditor.bat
vendored
Normal file
38
opentcs-modeleditor/src/dist/startModelEditor.bat
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
@echo off
|
||||
rem SPDX-FileCopyrightText: The openTCS Authors
|
||||
rem SPDX-License-Identifier: MIT
|
||||
rem
|
||||
rem Start the openTCS Model Editor application.
|
||||
rem
|
||||
|
||||
rem Set window title
|
||||
title Model Editor (openTCS)
|
||||
|
||||
rem Don't export variables to the parent shell
|
||||
setlocal
|
||||
|
||||
rem Set base directory names.
|
||||
set OPENTCS_BASE=.
|
||||
set OPENTCS_HOME=.
|
||||
set OPENTCS_CONFIGDIR=%OPENTCS_HOME%\config
|
||||
set OPENTCS_LIBDIR=%OPENTCS_BASE%\lib
|
||||
|
||||
rem Set the class path
|
||||
set OPENTCS_CP=%OPENTCS_LIBDIR%\*;
|
||||
set OPENTCS_CP=%OPENTCS_CP%;%OPENTCS_LIBDIR%\openTCS-extensions\*;
|
||||
|
||||
rem XXX Be a bit more clever to find out the name of the JVM runtime.
|
||||
set JAVA=javaw
|
||||
|
||||
rem Start plant overview
|
||||
start /b %JAVA% -enableassertions ^
|
||||
-Dopentcs.base="%OPENTCS_BASE%" ^
|
||||
-Dopentcs.home="%OPENTCS_HOME%" ^
|
||||
-Dopentcs.configuration.provider=gestalt ^
|
||||
-Dopentcs.configuration.reload.interval=10000 ^
|
||||
-Djava.util.logging.config.file="%OPENTCS_CONFIGDIR%\logging.config" ^
|
||||
-Dsun.java2d.d3d=false ^
|
||||
-XX:-OmitStackTraceInFastThrow ^
|
||||
-classpath "%OPENTCS_CP%" ^
|
||||
-splash:bin/splash-image.gif ^
|
||||
org.opentcs.modeleditor.RunModelEditor
|
||||
35
opentcs-modeleditor/src/dist/startModelEditor.sh
vendored
Normal file
35
opentcs-modeleditor/src/dist/startModelEditor.sh
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
#!/bin/sh
|
||||
# SPDX-FileCopyrightText: The openTCS Authors
|
||||
# SPDX-License-Identifier: MIT
|
||||
#
|
||||
# Start the openTCS Model Editor application.
|
||||
#
|
||||
|
||||
# Set base directory names.
|
||||
export OPENTCS_BASE=.
|
||||
export OPENTCS_HOME=.
|
||||
export OPENTCS_CONFIGDIR="${OPENTCS_HOME}/config"
|
||||
export OPENTCS_LIBDIR="${OPENTCS_BASE}/lib"
|
||||
|
||||
# Set the class path
|
||||
export OPENTCS_CP="${OPENTCS_LIBDIR}/*"
|
||||
export OPENTCS_CP="${OPENTCS_CP}:${OPENTCS_LIBDIR}/openTCS-extensions/*"
|
||||
|
||||
if [ -n "${OPENTCS_JAVAVM}" ]; then
|
||||
export JAVA="${OPENTCS_JAVAVM}"
|
||||
else
|
||||
# XXX Be a bit more clever to find out the name of the JVM runtime.
|
||||
export JAVA="java"
|
||||
fi
|
||||
|
||||
# Start plant overview
|
||||
${JAVA} -enableassertions \
|
||||
-Dopentcs.base="${OPENTCS_BASE}" \
|
||||
-Dopentcs.home="${OPENTCS_HOME}" \
|
||||
-Dopentcs.configuration.provider=gestalt \
|
||||
-Dopentcs.configuration.reload.interval=10000 \
|
||||
-Djava.util.logging.config.file=${OPENTCS_CONFIGDIR}/logging.config \
|
||||
-XX:-OmitStackTraceInFastThrow \
|
||||
-classpath "${OPENTCS_CP}" \
|
||||
-splash:bin/splash-image.gif \
|
||||
org.opentcs.modeleditor.RunModelEditor
|
||||
@@ -0,0 +1,25 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.modeleditor;
|
||||
|
||||
import org.opentcs.customizations.plantoverview.PlantOverviewInjectionModule;
|
||||
|
||||
/**
|
||||
* Configures/binds the default importers and exporters of the openTCS plant overview.
|
||||
*/
|
||||
public class DefaultImportersExportersModule
|
||||
extends
|
||||
PlantOverviewInjectionModule {
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*/
|
||||
public DefaultImportersExportersModule() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
plantModelImporterBinder();
|
||||
plantModelExporterBinder();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,170 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.modeleditor;
|
||||
|
||||
import com.google.inject.TypeLiteral;
|
||||
import jakarta.inject.Singleton;
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import javax.swing.ToolTipManager;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.UnsupportedLookAndFeelException;
|
||||
import org.opentcs.access.KernelServicePortal;
|
||||
import org.opentcs.access.SslParameterSet;
|
||||
import org.opentcs.access.rmi.KernelServicePortalBuilder;
|
||||
import org.opentcs.access.rmi.factories.NullSocketFactoryProvider;
|
||||
import org.opentcs.access.rmi.factories.SecureSocketFactoryProvider;
|
||||
import org.opentcs.access.rmi.factories.SocketFactoryProvider;
|
||||
import org.opentcs.common.GuestUserCredentials;
|
||||
import org.opentcs.components.plantoverview.LocationTheme;
|
||||
import org.opentcs.customizations.ApplicationHome;
|
||||
import org.opentcs.customizations.plantoverview.PlantOverviewInjectionModule;
|
||||
import org.opentcs.drivers.LowLevelCommunicationEvent;
|
||||
import org.opentcs.guing.common.exchange.ApplicationPortalProviderConfiguration;
|
||||
import org.opentcs.guing.common.exchange.SslConfiguration;
|
||||
import org.opentcs.modeleditor.application.ApplicationInjectionModule;
|
||||
import org.opentcs.modeleditor.components.ComponentsInjectionModule;
|
||||
import org.opentcs.modeleditor.exchange.ExchangeInjectionModule;
|
||||
import org.opentcs.modeleditor.math.path.PathLengthFunctionInjectionModule;
|
||||
import org.opentcs.modeleditor.model.ModelInjectionModule;
|
||||
import org.opentcs.modeleditor.persistence.DefaultPersistenceInjectionModule;
|
||||
import org.opentcs.modeleditor.transport.TransportInjectionModule;
|
||||
import org.opentcs.modeleditor.util.ElementNamingSchemeConfiguration;
|
||||
import org.opentcs.modeleditor.util.ModelEditorConfiguration;
|
||||
import org.opentcs.modeleditor.util.UtilInjectionModule;
|
||||
import org.opentcs.util.ClassMatcher;
|
||||
import org.opentcs.util.gui.dialog.ConnectionParamSet;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* A Guice module for the openTCS plant overview application.
|
||||
*/
|
||||
public class DefaultPlantOverviewInjectionModule
|
||||
extends
|
||||
PlantOverviewInjectionModule {
|
||||
|
||||
/**
|
||||
* This class's logger.
|
||||
*/
|
||||
private static final Logger LOG
|
||||
= LoggerFactory.getLogger(DefaultPlantOverviewInjectionModule.class);
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*/
|
||||
public DefaultPlantOverviewInjectionModule() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
File applicationHome = new File(System.getProperty("opentcs.home", "."));
|
||||
bind(File.class)
|
||||
.annotatedWith(ApplicationHome.class)
|
||||
.toInstance(applicationHome);
|
||||
|
||||
configurePlantOverviewDependencies();
|
||||
install(new ApplicationInjectionModule());
|
||||
install(new ComponentsInjectionModule());
|
||||
install(new ExchangeInjectionModule());
|
||||
install(new PathLengthFunctionInjectionModule());
|
||||
install(new ModelInjectionModule());
|
||||
install(new DefaultPersistenceInjectionModule());
|
||||
install(new TransportInjectionModule());
|
||||
install(new UtilInjectionModule());
|
||||
|
||||
// Ensure there is at least an empty binder for pluggable panels.
|
||||
pluggablePanelFactoryBinder();
|
||||
// Ensure there is at least an empty binder for history entry formatters.
|
||||
objectHistoryEntryFormatterBinder();
|
||||
}
|
||||
|
||||
private void configurePlantOverviewDependencies() {
|
||||
ModelEditorConfiguration configuration
|
||||
= getConfigBindingProvider().get(
|
||||
ModelEditorConfiguration.PREFIX,
|
||||
ModelEditorConfiguration.class
|
||||
);
|
||||
bind(ApplicationPortalProviderConfiguration.class)
|
||||
.toInstance(configuration);
|
||||
bind(ModelEditorConfiguration.class)
|
||||
.toInstance(configuration);
|
||||
configurePlantOverview(configuration);
|
||||
configureThemes(configuration);
|
||||
configureSocketConnections();
|
||||
configureNamingConfiguration();
|
||||
|
||||
bind(new TypeLiteral<List<ConnectionParamSet>>() {
|
||||
})
|
||||
.toInstance(configuration.connectionBookmarks());
|
||||
}
|
||||
|
||||
private void configureNamingConfiguration() {
|
||||
ElementNamingSchemeConfiguration configuration
|
||||
= getConfigBindingProvider().get(
|
||||
ElementNamingSchemeConfiguration.PREFIX,
|
||||
ElementNamingSchemeConfiguration.class
|
||||
);
|
||||
bind(ElementNamingSchemeConfiguration.class)
|
||||
.toInstance(configuration);
|
||||
}
|
||||
|
||||
private void configureSocketConnections() {
|
||||
SslConfiguration sslConfiguration = getConfigBindingProvider().get(
|
||||
SslConfiguration.PREFIX,
|
||||
SslConfiguration.class
|
||||
);
|
||||
|
||||
//Create the data object for the ssl configuration
|
||||
SslParameterSet sslParamSet = new SslParameterSet(
|
||||
SslParameterSet.DEFAULT_KEYSTORE_TYPE,
|
||||
null,
|
||||
null,
|
||||
new File(sslConfiguration.truststoreFile()),
|
||||
sslConfiguration.truststorePassword()
|
||||
);
|
||||
bind(SslParameterSet.class).toInstance(sslParamSet);
|
||||
|
||||
SocketFactoryProvider socketFactoryProvider;
|
||||
if (sslConfiguration.enable()) {
|
||||
socketFactoryProvider = new SecureSocketFactoryProvider(sslParamSet);
|
||||
}
|
||||
else {
|
||||
LOG.warn("SSL encryption disabled, connections will not be secured!");
|
||||
socketFactoryProvider = new NullSocketFactoryProvider();
|
||||
}
|
||||
|
||||
//Bind socket provider to the kernel portal
|
||||
bind(KernelServicePortal.class)
|
||||
.toInstance(
|
||||
new KernelServicePortalBuilder(
|
||||
GuestUserCredentials.USER,
|
||||
GuestUserCredentials.PASSWORD
|
||||
)
|
||||
.setSocketFactoryProvider(socketFactoryProvider)
|
||||
.setEventFilter(new ClassMatcher(LowLevelCommunicationEvent.class).negate())
|
||||
.build()
|
||||
);
|
||||
}
|
||||
|
||||
private void configureThemes(ModelEditorConfiguration configuration) {
|
||||
bind(LocationTheme.class)
|
||||
.to(configuration.locationThemeClass())
|
||||
.in(Singleton.class);
|
||||
}
|
||||
|
||||
private void configurePlantOverview(ModelEditorConfiguration configuration) {
|
||||
Locale.setDefault(Locale.forLanguageTag(configuration.locale()));
|
||||
|
||||
try {
|
||||
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
||||
}
|
||||
catch (ClassNotFoundException | InstantiationException | IllegalAccessException
|
||||
| UnsupportedLookAndFeelException ex) {
|
||||
LOG.warn("Could not set look-and-feel", ex);
|
||||
}
|
||||
// Show tooltips for 30 seconds (Default: 4 sec)
|
||||
ToolTipManager.sharedInstance().setDismissDelay(30 * 1000);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.modeleditor;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import org.opentcs.common.LoopbackAdapterConstants;
|
||||
import org.opentcs.components.kernel.Dispatcher;
|
||||
import org.opentcs.components.kernel.Router;
|
||||
import org.opentcs.components.kernel.Scheduler;
|
||||
import org.opentcs.components.plantoverview.PropertySuggestions;
|
||||
import org.opentcs.data.ObjectPropConstants;
|
||||
|
||||
/**
|
||||
* The default property suggestions of the baseline plant overview.
|
||||
*/
|
||||
public class DefaultPropertySuggestions
|
||||
implements
|
||||
PropertySuggestions {
|
||||
|
||||
private final Set<String> keySuggestions = new HashSet<>();
|
||||
private final Set<String> valueSuggestions = new HashSet<>();
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*/
|
||||
public DefaultPropertySuggestions() {
|
||||
keySuggestions.add(Scheduler.PROPKEY_BLOCK_ENTRY_DIRECTION);
|
||||
keySuggestions.add(Router.PROPKEY_ROUTING_GROUP);
|
||||
keySuggestions.add(Dispatcher.PROPKEY_PARKING_POSITION_PRIORITY);
|
||||
keySuggestions.add(Dispatcher.PROPKEY_ASSIGNED_PARKING_POSITION);
|
||||
keySuggestions.add(Dispatcher.PROPKEY_PREFERRED_PARKING_POSITION);
|
||||
keySuggestions.add(Dispatcher.PROPKEY_ASSIGNED_RECHARGE_LOCATION);
|
||||
keySuggestions.add(Dispatcher.PROPKEY_PREFERRED_RECHARGE_LOCATION);
|
||||
keySuggestions.add(LoopbackAdapterConstants.PROPKEY_INITIAL_POSITION);
|
||||
keySuggestions.add(LoopbackAdapterConstants.PROPKEY_OPERATING_TIME);
|
||||
keySuggestions.add(LoopbackAdapterConstants.PROPKEY_LOAD_OPERATION);
|
||||
keySuggestions.add(LoopbackAdapterConstants.PROPKEY_UNLOAD_OPERATION);
|
||||
keySuggestions.add(LoopbackAdapterConstants.PROPKEY_ACCELERATION);
|
||||
keySuggestions.add(LoopbackAdapterConstants.PROPKEY_DECELERATION);
|
||||
keySuggestions.add(ObjectPropConstants.VEHICLE_DATA_TRANSFORMER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getKeySuggestions() {
|
||||
return keySuggestions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getValueSuggestions() {
|
||||
return valueSuggestions;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.modeleditor;
|
||||
|
||||
import jakarta.inject.Singleton;
|
||||
import org.opentcs.customizations.plantoverview.PlantOverviewInjectionModule;
|
||||
|
||||
/**
|
||||
* This module configures the multibinder used to suggest key value properties in the editor.
|
||||
*/
|
||||
public class PropertySuggestionsModule
|
||||
extends
|
||||
PlantOverviewInjectionModule {
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*/
|
||||
public PropertySuggestionsModule() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
propertySuggestionsBinder().addBinding()
|
||||
.to(DefaultPropertySuggestions.class)
|
||||
.in(Singleton.class);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.modeleditor;
|
||||
|
||||
import com.google.inject.Guice;
|
||||
import com.google.inject.Injector;
|
||||
import com.google.inject.Module;
|
||||
import com.google.inject.util.Modules;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.ServiceLoader;
|
||||
import org.opentcs.configuration.ConfigurationBindingProvider;
|
||||
import org.opentcs.configuration.gestalt.GestaltConfigurationBindingProvider;
|
||||
import org.opentcs.customizations.ConfigurableInjectionModule;
|
||||
import org.opentcs.customizations.plantoverview.PlantOverviewInjectionModule;
|
||||
import org.opentcs.guing.common.util.CompatibilityChecker;
|
||||
import org.opentcs.modeleditor.application.PlantOverviewStarter;
|
||||
import org.opentcs.util.Environment;
|
||||
import org.opentcs.util.logging.UncaughtExceptionLogger;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The plant overview process's default entry point.
|
||||
*/
|
||||
public class RunModelEditor {
|
||||
|
||||
/**
|
||||
* This class's logger.
|
||||
*/
|
||||
private static final Logger LOG = LoggerFactory.getLogger(RunModelEditor.class);
|
||||
|
||||
/**
|
||||
* Prevents external instantiation.
|
||||
*/
|
||||
private RunModelEditor() {
|
||||
}
|
||||
|
||||
/**
|
||||
* The plant overview client's main entry point.
|
||||
*
|
||||
* @param args the command line arguments
|
||||
*/
|
||||
public static void main(final String[] args) {
|
||||
Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionLogger(false));
|
||||
|
||||
Environment.logSystemInfo();
|
||||
ensureVersionCompatibility();
|
||||
|
||||
Injector injector = Guice.createInjector(customConfigurationModule());
|
||||
injector.getInstance(PlantOverviewStarter.class).startPlantOverview();
|
||||
}
|
||||
|
||||
private static void ensureVersionCompatibility() {
|
||||
String version = System.getProperty("java.version");
|
||||
if (!CompatibilityChecker.versionCompatibleWithDockingFrames(version)) {
|
||||
LOG.error("Version incompatible with Docking Frames: '{}'", version);
|
||||
CompatibilityChecker.showVersionIncompatibleWithDockingFramesMessage();
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds and returns a Guice module containing the custom configuration for the plant overview
|
||||
* application, including additions and overrides by the user.
|
||||
*
|
||||
* @return The custom configuration module.
|
||||
*/
|
||||
private static Module customConfigurationModule() {
|
||||
ConfigurationBindingProvider bindingProvider = configurationBindingProvider();
|
||||
ConfigurableInjectionModule plantOverviewInjectionModule
|
||||
= new DefaultPlantOverviewInjectionModule();
|
||||
plantOverviewInjectionModule.setConfigBindingProvider(bindingProvider);
|
||||
return Modules.override(plantOverviewInjectionModule)
|
||||
.with(findRegisteredModules(bindingProvider));
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds and returns all Guice modules registered via ServiceLoader.
|
||||
*
|
||||
* @return The registered/found modules.
|
||||
*/
|
||||
private static List<PlantOverviewInjectionModule> findRegisteredModules(
|
||||
ConfigurationBindingProvider bindingProvider
|
||||
) {
|
||||
List<PlantOverviewInjectionModule> registeredModules = new ArrayList<>();
|
||||
for (PlantOverviewInjectionModule module : ServiceLoader.load(
|
||||
PlantOverviewInjectionModule.class
|
||||
)) {
|
||||
LOG.info(
|
||||
"Integrating injection module {} (source: {})",
|
||||
module.getClass().getName(),
|
||||
module.getClass().getProtectionDomain().getCodeSource()
|
||||
);
|
||||
module.setConfigBindingProvider(bindingProvider);
|
||||
registeredModules.add(module);
|
||||
}
|
||||
return registeredModules;
|
||||
}
|
||||
|
||||
private static ConfigurationBindingProvider configurationBindingProvider() {
|
||||
String chosenProvider = System.getProperty("opentcs.configuration.provider", "gestalt");
|
||||
switch (chosenProvider) {
|
||||
case "gestalt":
|
||||
default:
|
||||
LOG.info("Using gestalt as the configuration provider.");
|
||||
return gestaltConfigurationBindingProvider();
|
||||
}
|
||||
}
|
||||
|
||||
private static ConfigurationBindingProvider gestaltConfigurationBindingProvider() {
|
||||
return new GestaltConfigurationBindingProvider(
|
||||
Paths.get(
|
||||
System.getProperty("opentcs.base", "."),
|
||||
"config",
|
||||
"opentcs-modeleditor-defaults-baseline.properties"
|
||||
)
|
||||
.toAbsolutePath(),
|
||||
Paths.get(
|
||||
System.getProperty("opentcs.base", "."),
|
||||
"config",
|
||||
"opentcs-modeleditor-defaults-custom.properties"
|
||||
)
|
||||
.toAbsolutePath(),
|
||||
Paths.get(
|
||||
System.getProperty("opentcs.home", "."),
|
||||
"config",
|
||||
"opentcs-modeleditor.properties"
|
||||
)
|
||||
.toAbsolutePath()
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.modeleditor.application;
|
||||
|
||||
import com.google.inject.AbstractModule;
|
||||
import jakarta.inject.Singleton;
|
||||
import java.awt.Component;
|
||||
import javax.swing.JFrame;
|
||||
import org.jhotdraw.app.Application;
|
||||
import org.opentcs.customizations.plantoverview.ApplicationFrame;
|
||||
import org.opentcs.guing.common.application.ApplicationState;
|
||||
import org.opentcs.guing.common.application.ComponentsManager;
|
||||
import org.opentcs.guing.common.application.GuiManager;
|
||||
import org.opentcs.guing.common.application.PluginPanelManager;
|
||||
import org.opentcs.guing.common.application.ProgressIndicator;
|
||||
import org.opentcs.guing.common.application.SplashFrame;
|
||||
import org.opentcs.guing.common.application.StatusPanel;
|
||||
import org.opentcs.guing.common.application.ViewManager;
|
||||
import org.opentcs.modeleditor.application.action.ActionInjectionModule;
|
||||
import org.opentcs.modeleditor.application.menus.MenusInjectionModule;
|
||||
import org.opentcs.modeleditor.application.toolbar.ToolBarInjectionModule;
|
||||
import org.opentcs.thirdparty.guing.common.jhotdraw.application.action.edit.UndoRedoManager;
|
||||
import org.opentcs.thirdparty.modeleditor.jhotdraw.application.OpenTCSSDIApplication;
|
||||
|
||||
/**
|
||||
* An injection module for this package.
|
||||
*/
|
||||
public class ApplicationInjectionModule
|
||||
extends
|
||||
AbstractModule {
|
||||
|
||||
/**
|
||||
* The application's main frame.
|
||||
*/
|
||||
private final JFrame applicationFrame = new JFrame();
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*/
|
||||
public ApplicationInjectionModule() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
install(new ActionInjectionModule());
|
||||
install(new MenusInjectionModule());
|
||||
install(new ToolBarInjectionModule());
|
||||
|
||||
bind(ApplicationState.class).in(Singleton.class);
|
||||
|
||||
bind(UndoRedoManager.class).in(Singleton.class);
|
||||
|
||||
bind(ProgressIndicator.class)
|
||||
.to(SplashFrame.class)
|
||||
.in(Singleton.class);
|
||||
bind(StatusPanel.class).in(Singleton.class);
|
||||
|
||||
bind(JFrame.class)
|
||||
.annotatedWith(ApplicationFrame.class)
|
||||
.toInstance(applicationFrame);
|
||||
bind(Component.class)
|
||||
.annotatedWith(ApplicationFrame.class)
|
||||
.toInstance(applicationFrame);
|
||||
|
||||
bind(ViewManagerModeling.class)
|
||||
.in(Singleton.class);
|
||||
bind(ViewManager.class).to(ViewManagerModeling.class);
|
||||
|
||||
bind(Application.class)
|
||||
.to(OpenTCSSDIApplication.class)
|
||||
.in(Singleton.class);
|
||||
|
||||
bind(OpenTCSView.class).in(Singleton.class);
|
||||
bind(GuiManager.class).to(OpenTCSView.class);
|
||||
bind(ComponentsManager.class).to(OpenTCSView.class);
|
||||
bind(PluginPanelManager.class).to(OpenTCSView.class);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.modeleditor.application.action;
|
||||
|
||||
import com.google.inject.AbstractModule;
|
||||
import jakarta.inject.Singleton;
|
||||
|
||||
/**
|
||||
* An injection module for this package.
|
||||
*/
|
||||
public class ActionInjectionModule
|
||||
extends
|
||||
AbstractModule {
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*/
|
||||
public ActionInjectionModule() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
bind(ViewActionMap.class).in(Singleton.class);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.modeleditor.application.menus;
|
||||
|
||||
import com.google.inject.AbstractModule;
|
||||
import com.google.inject.assistedinject.FactoryModuleBuilder;
|
||||
|
||||
/**
|
||||
*/
|
||||
public class MenusInjectionModule
|
||||
extends
|
||||
AbstractModule {
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*/
|
||||
public MenusInjectionModule() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
install(new FactoryModuleBuilder().build(MenuFactory.class));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.modeleditor.application.toolbar;
|
||||
|
||||
import com.google.inject.AbstractModule;
|
||||
import com.google.inject.assistedinject.FactoryModuleBuilder;
|
||||
import jakarta.inject.Singleton;
|
||||
import org.jhotdraw.draw.tool.DragTracker;
|
||||
import org.jhotdraw.draw.tool.SelectAreaTracker;
|
||||
import org.opentcs.modeleditor.application.action.ToolBarManager;
|
||||
import org.opentcs.thirdparty.guing.common.jhotdraw.application.toolbar.OpenTCSDragTracker;
|
||||
import org.opentcs.thirdparty.guing.common.jhotdraw.application.toolbar.OpenTCSSelectAreaTracker;
|
||||
|
||||
/**
|
||||
*/
|
||||
public class ToolBarInjectionModule
|
||||
extends
|
||||
AbstractModule {
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*/
|
||||
public ToolBarInjectionModule() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
install(new FactoryModuleBuilder().build(SelectionToolFactory.class));
|
||||
install(new FactoryModuleBuilder().build(CreationToolFactory.class));
|
||||
|
||||
bind(ToolBarManager.class).in(Singleton.class);
|
||||
|
||||
bind(SelectAreaTracker.class).to(OpenTCSSelectAreaTracker.class);
|
||||
bind(DragTracker.class).to(OpenTCSDragTracker.class);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.modeleditor.components;
|
||||
|
||||
import com.google.inject.AbstractModule;
|
||||
import com.google.inject.PrivateModule;
|
||||
import jakarta.inject.Singleton;
|
||||
import java.awt.event.MouseListener;
|
||||
import org.opentcs.guing.common.components.tree.AbstractTreeViewPanel;
|
||||
import org.opentcs.guing.common.components.tree.BlockMouseListener;
|
||||
import org.opentcs.guing.common.components.tree.BlocksTreeViewManager;
|
||||
import org.opentcs.guing.common.components.tree.BlocksTreeViewPanel;
|
||||
import org.opentcs.guing.common.components.tree.ComponentsTreeViewManager;
|
||||
import org.opentcs.guing.common.components.tree.ComponentsTreeViewPanel;
|
||||
import org.opentcs.guing.common.components.tree.TreeMouseAdapter;
|
||||
import org.opentcs.guing.common.components.tree.TreeView;
|
||||
import org.opentcs.modeleditor.components.dialogs.DialogsInjectionModule;
|
||||
import org.opentcs.modeleditor.components.dockable.DockableInjectionModule;
|
||||
import org.opentcs.modeleditor.components.drawing.DrawingInjectionModule;
|
||||
import org.opentcs.modeleditor.components.layer.LayersInjectionModule;
|
||||
import org.opentcs.modeleditor.components.properties.PropertiesInjectionModule;
|
||||
import org.opentcs.modeleditor.components.tree.elements.TreeElementsInjectionModule;
|
||||
|
||||
/**
|
||||
* A Guice module for this package.
|
||||
*/
|
||||
public class ComponentsInjectionModule
|
||||
extends
|
||||
AbstractModule {
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*/
|
||||
public ComponentsInjectionModule() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
install(new DialogsInjectionModule());
|
||||
install(new DockableInjectionModule());
|
||||
install(new DrawingInjectionModule());
|
||||
install(new PropertiesInjectionModule());
|
||||
install(new TreeElementsInjectionModule());
|
||||
|
||||
install(new ComponentsTreeViewModule());
|
||||
install(new BlocksTreeViewModule());
|
||||
|
||||
install(new LayersInjectionModule());
|
||||
}
|
||||
|
||||
private static class ComponentsTreeViewModule
|
||||
extends
|
||||
PrivateModule {
|
||||
|
||||
ComponentsTreeViewModule() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
// Within this (private) module, there should only be a single tree panel.
|
||||
bind(ComponentsTreeViewPanel.class)
|
||||
.in(Singleton.class);
|
||||
|
||||
// Bind the tree panel annotated with the given annotation to our single
|
||||
// instance and expose only this annotated version.
|
||||
bind(AbstractTreeViewPanel.class)
|
||||
.to(ComponentsTreeViewPanel.class);
|
||||
expose(ComponentsTreeViewPanel.class);
|
||||
|
||||
// Bind TreeView to the single tree panel, too.
|
||||
bind(TreeView.class)
|
||||
.to(ComponentsTreeViewPanel.class);
|
||||
|
||||
// Bind and expose a single manager for the single tree view/panel.
|
||||
bind(ComponentsTreeViewManager.class)
|
||||
.in(Singleton.class);
|
||||
expose(ComponentsTreeViewManager.class);
|
||||
|
||||
bind(MouseListener.class)
|
||||
.to(TreeMouseAdapter.class);
|
||||
}
|
||||
}
|
||||
|
||||
private static class BlocksTreeViewModule
|
||||
extends
|
||||
PrivateModule {
|
||||
|
||||
BlocksTreeViewModule() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
// Within this (private) module, there should only be a single tree panel.
|
||||
bind(BlocksTreeViewPanel.class)
|
||||
.in(Singleton.class);
|
||||
|
||||
// Bind the tree panel annotated with the given annotation to our single
|
||||
// instance and expose only this annotated version.
|
||||
bind(AbstractTreeViewPanel.class)
|
||||
.to(BlocksTreeViewPanel.class);
|
||||
expose(BlocksTreeViewPanel.class);
|
||||
|
||||
// Bind TreeView to the single tree panel, too.
|
||||
bind(TreeView.class)
|
||||
.to(BlocksTreeViewPanel.class);
|
||||
|
||||
// Bind and expose a single manager for the single tree view/panel.
|
||||
bind(BlocksTreeViewManager.class)
|
||||
.in(Singleton.class);
|
||||
expose(BlocksTreeViewManager.class);
|
||||
|
||||
bind(MouseListener.class)
|
||||
.to(BlockMouseListener.class);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.modeleditor.components.dialogs;
|
||||
|
||||
import com.google.inject.AbstractModule;
|
||||
|
||||
/**
|
||||
* A Guice module for this package.
|
||||
*/
|
||||
public class DialogsInjectionModule
|
||||
extends
|
||||
AbstractModule {
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*/
|
||||
public DialogsInjectionModule() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.modeleditor.components.dockable;
|
||||
|
||||
import com.google.inject.AbstractModule;
|
||||
import com.google.inject.assistedinject.FactoryModuleBuilder;
|
||||
import jakarta.inject.Singleton;
|
||||
import org.opentcs.guing.common.components.dockable.DockableHandlerFactory;
|
||||
import org.opentcs.guing.common.components.dockable.DockingManager;
|
||||
|
||||
/**
|
||||
* A Guice module for this package.
|
||||
*/
|
||||
public class DockableInjectionModule
|
||||
extends
|
||||
AbstractModule {
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*/
|
||||
public DockableInjectionModule() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
install(new FactoryModuleBuilder().build(DockableHandlerFactory.class));
|
||||
|
||||
bind(DockingManagerModeling.class).in(Singleton.class);
|
||||
bind(DockingManager.class).to(DockingManagerModeling.class);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.modeleditor.components.drawing;
|
||||
|
||||
import com.google.inject.AbstractModule;
|
||||
import com.google.inject.assistedinject.FactoryModuleBuilder;
|
||||
import jakarta.inject.Singleton;
|
||||
import org.jhotdraw.draw.DrawingEditor;
|
||||
import org.opentcs.guing.common.components.drawing.DrawingOptions;
|
||||
import org.opentcs.guing.common.components.drawing.OpenTCSDrawingEditor;
|
||||
import org.opentcs.guing.common.components.drawing.OpenTCSDrawingView;
|
||||
import org.opentcs.guing.common.components.drawing.figures.FigureFactory;
|
||||
import org.opentcs.thirdparty.modeleditor.jhotdraw.components.drawing.OpenTCSDrawingViewModeling;
|
||||
|
||||
/**
|
||||
* A Guice module for this package.
|
||||
*/
|
||||
public class DrawingInjectionModule
|
||||
extends
|
||||
AbstractModule {
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*/
|
||||
public DrawingInjectionModule() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
install(new FactoryModuleBuilder().build(FigureFactory.class));
|
||||
|
||||
bind(OpenTCSDrawingEditor.class).in(Singleton.class);
|
||||
bind(DrawingEditor.class).to(OpenTCSDrawingEditor.class);
|
||||
|
||||
bind(OpenTCSDrawingView.class).to(OpenTCSDrawingViewModeling.class);
|
||||
|
||||
bind(DrawingOptions.class).in(Singleton.class);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.modeleditor.components.layer;
|
||||
|
||||
import jakarta.inject.Singleton;
|
||||
import org.opentcs.customizations.plantoverview.PlantOverviewInjectionModule;
|
||||
import org.opentcs.guing.common.components.layer.LayerGroupManager;
|
||||
import org.opentcs.guing.common.components.layer.LayerManager;
|
||||
|
||||
/**
|
||||
* A Guice module for this package.
|
||||
*/
|
||||
public class LayersInjectionModule
|
||||
extends
|
||||
PlantOverviewInjectionModule {
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*/
|
||||
public LayersInjectionModule() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
bind(LayerManagerModeling.class).in(Singleton.class);
|
||||
bind(LayerManager.class).to(LayerManagerModeling.class);
|
||||
bind(LayerEditorModeling.class).to(LayerManagerModeling.class);
|
||||
bind(ActiveLayerProvider.class).to(LayerManagerModeling.class);
|
||||
bind(LayersPanel.class).in(Singleton.class);
|
||||
|
||||
bind(LayerGroupManager.class).to(LayerManagerModeling.class);
|
||||
bind(LayerGroupEditorModeling.class).to(LayerManagerModeling.class);
|
||||
bind(LayerGroupsPanel.class).in(Singleton.class);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.modeleditor.components.properties;
|
||||
|
||||
import com.google.inject.TypeLiteral;
|
||||
import com.google.inject.assistedinject.FactoryModuleBuilder;
|
||||
import com.google.inject.multibindings.MapBinder;
|
||||
import jakarta.inject.Singleton;
|
||||
import org.opentcs.customizations.plantoverview.PlantOverviewInjectionModule;
|
||||
import org.opentcs.guing.base.components.properties.type.AbstractComplexProperty;
|
||||
import org.opentcs.guing.base.components.properties.type.BoundingBoxProperty;
|
||||
import org.opentcs.guing.base.components.properties.type.EnergyLevelThresholdSetProperty;
|
||||
import org.opentcs.guing.base.components.properties.type.EnvelopesProperty;
|
||||
import org.opentcs.guing.base.components.properties.type.KeyValueProperty;
|
||||
import org.opentcs.guing.base.components.properties.type.KeyValueSetProperty;
|
||||
import org.opentcs.guing.base.components.properties.type.LinkActionsProperty;
|
||||
import org.opentcs.guing.base.components.properties.type.LocationTypeActionsProperty;
|
||||
import org.opentcs.guing.base.components.properties.type.OrderTypesProperty;
|
||||
import org.opentcs.guing.base.components.properties.type.PeripheralOperationsProperty;
|
||||
import org.opentcs.guing.base.components.properties.type.SymbolProperty;
|
||||
import org.opentcs.guing.common.components.dialogs.DetailsDialogContent;
|
||||
import org.opentcs.guing.common.components.properties.PropertiesComponentsFactory;
|
||||
import org.opentcs.guing.common.components.properties.SelectionPropertiesComponent;
|
||||
import org.opentcs.guing.common.components.properties.panel.BoundingBoxPropertyEditorPanel;
|
||||
import org.opentcs.guing.common.components.properties.panel.EnergyLevelThresholdSetPropertyEditorPanel;
|
||||
import org.opentcs.guing.common.components.properties.panel.EnvelopesPropertyEditorPanel;
|
||||
import org.opentcs.guing.common.components.properties.panel.KeyValuePropertyEditorPanel;
|
||||
import org.opentcs.guing.common.components.properties.panel.KeyValueSetPropertyEditorPanel;
|
||||
import org.opentcs.guing.common.components.properties.panel.LinkActionsEditorPanel;
|
||||
import org.opentcs.guing.common.components.properties.panel.LocationTypeActionsEditorPanel;
|
||||
import org.opentcs.guing.common.components.properties.panel.OrderTypesPropertyEditorPanel;
|
||||
import org.opentcs.guing.common.components.properties.panel.PeripheralOperationsPropertyEditorPanel;
|
||||
import org.opentcs.guing.common.components.properties.panel.PropertiesPanelFactory;
|
||||
import org.opentcs.guing.common.components.properties.panel.SymbolPropertyEditorPanel;
|
||||
import org.opentcs.guing.common.components.properties.table.CellEditorFactory;
|
||||
import org.opentcs.modeleditor.application.menus.MenuItemComponentsFactory;
|
||||
|
||||
/**
|
||||
* A Guice module for this package.
|
||||
*/
|
||||
public class PropertiesInjectionModule
|
||||
extends
|
||||
PlantOverviewInjectionModule {
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*/
|
||||
public PropertiesInjectionModule() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
install(new FactoryModuleBuilder().build(PropertiesPanelFactory.class));
|
||||
install(new FactoryModuleBuilder().build(CellEditorFactory.class));
|
||||
install(new FactoryModuleBuilder().build(PropertiesComponentsFactory.class));
|
||||
install(new FactoryModuleBuilder().build(MenuItemComponentsFactory.class));
|
||||
|
||||
MapBinder<Class<? extends AbstractComplexProperty>, DetailsDialogContent> dialogContentMapBinder
|
||||
= MapBinder.newMapBinder(
|
||||
binder(),
|
||||
new TypeLiteral<Class<? extends AbstractComplexProperty>>() {
|
||||
},
|
||||
new TypeLiteral<DetailsDialogContent>() {
|
||||
}
|
||||
);
|
||||
dialogContentMapBinder
|
||||
.addBinding(KeyValueProperty.class)
|
||||
.to(KeyValuePropertyEditorPanel.class);
|
||||
dialogContentMapBinder
|
||||
.addBinding(KeyValueSetProperty.class)
|
||||
.to(KeyValueSetPropertyEditorPanel.class);
|
||||
dialogContentMapBinder
|
||||
.addBinding(LocationTypeActionsProperty.class)
|
||||
.to(LocationTypeActionsEditorPanel.class);
|
||||
dialogContentMapBinder
|
||||
.addBinding(LinkActionsProperty.class)
|
||||
.to(LinkActionsEditorPanel.class);
|
||||
dialogContentMapBinder
|
||||
.addBinding(SymbolProperty.class)
|
||||
.to(SymbolPropertyEditorPanel.class);
|
||||
dialogContentMapBinder
|
||||
.addBinding(OrderTypesProperty.class)
|
||||
.to(OrderTypesPropertyEditorPanel.class);
|
||||
dialogContentMapBinder
|
||||
.addBinding(PeripheralOperationsProperty.class)
|
||||
.to(PeripheralOperationsPropertyEditorPanel.class);
|
||||
dialogContentMapBinder
|
||||
.addBinding(EnvelopesProperty.class)
|
||||
.to(EnvelopesPropertyEditorPanel.class);
|
||||
dialogContentMapBinder
|
||||
.addBinding(BoundingBoxProperty.class)
|
||||
.to(BoundingBoxPropertyEditorPanel.class);
|
||||
dialogContentMapBinder
|
||||
.addBinding(EnergyLevelThresholdSetProperty.class)
|
||||
.to(EnergyLevelThresholdSetPropertyEditorPanel.class);
|
||||
|
||||
bind(SelectionPropertiesComponent.class)
|
||||
.in(Singleton.class);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.modeleditor.components.tree.elements;
|
||||
|
||||
import com.google.inject.AbstractModule;
|
||||
import com.google.inject.assistedinject.FactoryModuleBuilder;
|
||||
import org.opentcs.guing.common.components.tree.elements.UserObjectFactory;
|
||||
import org.opentcs.guing.common.components.tree.elements.VehicleUserObject;
|
||||
|
||||
/**
|
||||
* A Guice module for this package.
|
||||
*/
|
||||
public class TreeElementsInjectionModule
|
||||
extends
|
||||
AbstractModule {
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*/
|
||||
public TreeElementsInjectionModule() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
install(
|
||||
new FactoryModuleBuilder()
|
||||
.implement(VehicleUserObject.class, VehicleUserObjectModeling.class)
|
||||
.build(UserObjectFactory.class)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.modeleditor.exchange;
|
||||
|
||||
import com.google.inject.AbstractModule;
|
||||
import jakarta.inject.Singleton;
|
||||
import org.opentcs.access.SharedKernelServicePortalProvider;
|
||||
import org.opentcs.common.DefaultPortalManager;
|
||||
import org.opentcs.common.PortalManager;
|
||||
import org.opentcs.customizations.ApplicationEventBus;
|
||||
import org.opentcs.guing.common.exchange.ApplicationPortalProvider;
|
||||
import org.opentcs.util.event.EventBus;
|
||||
import org.opentcs.util.event.EventHandler;
|
||||
import org.opentcs.util.event.EventSource;
|
||||
import org.opentcs.util.event.SimpleEventBus;
|
||||
|
||||
/**
|
||||
* A Guice configuration module for this package.
|
||||
*/
|
||||
public class ExchangeInjectionModule
|
||||
extends
|
||||
AbstractModule {
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*/
|
||||
public ExchangeInjectionModule() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
bind(PortalManager.class)
|
||||
.to(DefaultPortalManager.class)
|
||||
.in(Singleton.class);
|
||||
|
||||
EventBus eventBus = new SimpleEventBus();
|
||||
bind(EventSource.class)
|
||||
.annotatedWith(ApplicationEventBus.class)
|
||||
.toInstance(eventBus);
|
||||
bind(EventHandler.class)
|
||||
.annotatedWith(ApplicationEventBus.class)
|
||||
.toInstance(eventBus);
|
||||
bind(EventBus.class)
|
||||
.annotatedWith(ApplicationEventBus.class)
|
||||
.toInstance(eventBus);
|
||||
|
||||
bind(SharedKernelServicePortalProvider.class)
|
||||
.to(ApplicationPortalProvider.class)
|
||||
.in(Singleton.class);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.modeleditor.math.path;
|
||||
|
||||
import com.google.inject.AbstractModule;
|
||||
import com.google.inject.TypeLiteral;
|
||||
import com.google.inject.multibindings.MapBinder;
|
||||
import org.opentcs.guing.base.model.elements.PathModel;
|
||||
|
||||
/**
|
||||
* A Guice configuration module for this package.
|
||||
*/
|
||||
public class PathLengthFunctionInjectionModule
|
||||
extends
|
||||
AbstractModule {
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*/
|
||||
public PathLengthFunctionInjectionModule() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
MapBinder<PathModel.Type, PathLengthFunction> pathLengthFunctionBinder
|
||||
= MapBinder.newMapBinder(
|
||||
binder(),
|
||||
new TypeLiteral<PathModel.Type>() {
|
||||
},
|
||||
new TypeLiteral<PathLengthFunction>() {
|
||||
}
|
||||
);
|
||||
pathLengthFunctionBinder
|
||||
.addBinding(PathModel.Type.DIRECT)
|
||||
.to(EuclideanDistance.class);
|
||||
pathLengthFunctionBinder
|
||||
.addBinding(PathModel.Type.ELBOW)
|
||||
.to(EuclideanDistance.class);
|
||||
pathLengthFunctionBinder
|
||||
.addBinding(PathModel.Type.SLANTED)
|
||||
.to(EuclideanDistance.class);
|
||||
pathLengthFunctionBinder
|
||||
.addBinding(PathModel.Type.POLYPATH)
|
||||
.to(PolyPathLength.class);
|
||||
pathLengthFunctionBinder
|
||||
.addBinding(PathModel.Type.BEZIER)
|
||||
.to(BezierLength.class);
|
||||
pathLengthFunctionBinder
|
||||
.addBinding(PathModel.Type.BEZIER_3)
|
||||
.to(BezierThreeLength.class);
|
||||
|
||||
bind(PathLengthFunction.class)
|
||||
.to(CompositePathLengthFunction.class);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.modeleditor.model;
|
||||
|
||||
import com.google.inject.AbstractModule;
|
||||
import org.opentcs.guing.common.model.StandardSystemModel;
|
||||
import org.opentcs.guing.common.model.SystemModel;
|
||||
|
||||
/**
|
||||
* A Guice module for the model package.
|
||||
*/
|
||||
public class ModelInjectionModule
|
||||
extends
|
||||
AbstractModule {
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*/
|
||||
public ModelInjectionModule() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
bind(SystemModel.class).to(StandardSystemModel.class);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.modeleditor.persistence;
|
||||
|
||||
import com.google.inject.AbstractModule;
|
||||
import com.google.inject.Singleton;
|
||||
import org.opentcs.guing.common.persistence.ModelFilePersistor;
|
||||
import org.opentcs.guing.common.persistence.ModelFileReader;
|
||||
import org.opentcs.guing.common.persistence.ModelManager;
|
||||
import org.opentcs.guing.common.persistence.unified.UnifiedModelPersistor;
|
||||
import org.opentcs.modeleditor.persistence.unified.UnifiedModelReader;
|
||||
|
||||
/**
|
||||
* Default bindings for model readers and persistors.
|
||||
*/
|
||||
public class DefaultPersistenceInjectionModule
|
||||
extends
|
||||
AbstractModule {
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*/
|
||||
public DefaultPersistenceInjectionModule() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
bind(OpenTCSModelManagerModeling.class).in(Singleton.class);
|
||||
bind(ModelManager.class).to(OpenTCSModelManagerModeling.class);
|
||||
bind(ModelManagerModeling.class).to(OpenTCSModelManagerModeling.class);
|
||||
|
||||
bind(ModelFileReader.class).to(UnifiedModelReader.class);
|
||||
bind(ModelFilePersistor.class).to(UnifiedModelPersistor.class);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.modeleditor.transport;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import org.opentcs.components.plantoverview.OrderTypeSuggestions;
|
||||
import org.opentcs.data.order.OrderConstants;
|
||||
|
||||
/**
|
||||
* The default suggestions for transport order types.
|
||||
*/
|
||||
public class DefaultOrderTypeSuggestions
|
||||
implements
|
||||
OrderTypeSuggestions {
|
||||
|
||||
/**
|
||||
* The transport order type suggestions.
|
||||
*/
|
||||
private final Set<String> typeSuggestions = new HashSet<>();
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*/
|
||||
public DefaultOrderTypeSuggestions() {
|
||||
typeSuggestions.add(OrderConstants.TYPE_NONE);
|
||||
typeSuggestions.add(OrderConstants.TYPE_CHARGE);
|
||||
typeSuggestions.add(OrderConstants.TYPE_PARK);
|
||||
typeSuggestions.add(OrderConstants.TYPE_TRANSPORT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getTypeSuggestions() {
|
||||
return typeSuggestions;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.modeleditor.transport;
|
||||
|
||||
import jakarta.inject.Singleton;
|
||||
import org.opentcs.customizations.plantoverview.PlantOverviewInjectionModule;
|
||||
import org.opentcs.guing.common.transport.OrderTypeSuggestionsPool;
|
||||
|
||||
/**
|
||||
* A Guice module for the transport order type suggestions.
|
||||
*/
|
||||
public class OrderTypeSuggestionsModule
|
||||
extends
|
||||
PlantOverviewInjectionModule {
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*/
|
||||
public OrderTypeSuggestionsModule() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
orderTypeSuggestionsBinder().addBinding()
|
||||
.to(DefaultOrderTypeSuggestions.class)
|
||||
.in(Singleton.class);
|
||||
|
||||
bind(OrderTypeSuggestionsPool.class).in(Singleton.class);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.modeleditor.transport;
|
||||
|
||||
import com.google.inject.AbstractModule;
|
||||
|
||||
/**
|
||||
* A Guice module for this package.
|
||||
*/
|
||||
public class TransportInjectionModule
|
||||
extends
|
||||
AbstractModule {
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*/
|
||||
public TransportInjectionModule() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.modeleditor.util;
|
||||
|
||||
import com.google.inject.AbstractModule;
|
||||
import jakarta.inject.Singleton;
|
||||
import org.opentcs.guing.common.util.PanelRegistry;
|
||||
|
||||
/**
|
||||
* A default Guice module for this package.
|
||||
*/
|
||||
public class UtilInjectionModule
|
||||
extends
|
||||
AbstractModule {
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*/
|
||||
public UtilInjectionModule() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
bind(PanelRegistry.class).in(Singleton.class);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
# SPDX-FileCopyrightText: The openTCS Authors
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
org.opentcs.modeleditor.DefaultImportersExportersModule
|
||||
org.opentcs.modeleditor.PropertySuggestionsModule
|
||||
org.opentcs.modeleditor.transport.OrderTypeSuggestionsModule
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,68 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.modeleditor.application;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
import org.jhotdraw.app.Application;
|
||||
import org.opentcs.guing.common.application.ProgressIndicator;
|
||||
import org.opentcs.guing.common.application.StartupProgressStatus;
|
||||
import org.opentcs.guing.common.event.EventLogger;
|
||||
|
||||
/**
|
||||
* The plant overview application's entry point.
|
||||
*/
|
||||
public class PlantOverviewStarter {
|
||||
|
||||
/**
|
||||
* Our startup progress indicator.
|
||||
*/
|
||||
private final ProgressIndicator progressIndicator;
|
||||
/**
|
||||
* The enclosing application.
|
||||
*/
|
||||
private final Application application;
|
||||
/**
|
||||
* The actual document view.
|
||||
*/
|
||||
private final OpenTCSView opentcsView;
|
||||
/**
|
||||
* Provides logging for events published on the application event bus.
|
||||
*/
|
||||
private final EventLogger eventLogger;
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*
|
||||
* @param progressIndicator The progress indicator to be used.
|
||||
* @param application The application to be used.
|
||||
* @param opentcsView The view to be used.
|
||||
* @param eventLogger Provides logging for events published on the application event bus.
|
||||
*/
|
||||
@Inject
|
||||
public PlantOverviewStarter(
|
||||
ProgressIndicator progressIndicator,
|
||||
Application application,
|
||||
OpenTCSView opentcsView,
|
||||
EventLogger eventLogger
|
||||
) {
|
||||
this.progressIndicator = requireNonNull(progressIndicator, "progressIndicator");
|
||||
this.application = requireNonNull(application, "application");
|
||||
this.opentcsView = requireNonNull(opentcsView, "opentcsView");
|
||||
this.eventLogger = requireNonNull(eventLogger, "eventLogger");
|
||||
}
|
||||
|
||||
public void startPlantOverview() {
|
||||
eventLogger.initialize();
|
||||
|
||||
opentcsView.init();
|
||||
progressIndicator.initialize();
|
||||
progressIndicator.setProgress(StartupProgressStatus.START_PLANT_OVERVIEW);
|
||||
progressIndicator.setProgress(StartupProgressStatus.SHOW_PLANT_OVERVIEW);
|
||||
opentcsView.setApplication(application);
|
||||
// Start the view.
|
||||
application.show(opentcsView);
|
||||
progressIndicator.terminate();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.modeleditor.application;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
import bibliothek.gui.dock.common.DefaultSingleCDockable;
|
||||
import jakarta.inject.Inject;
|
||||
import java.awt.event.FocusEvent;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import org.jhotdraw.draw.DrawingView;
|
||||
import org.opentcs.customizations.ApplicationEventBus;
|
||||
import org.opentcs.guing.common.application.AbstractViewManager;
|
||||
import org.opentcs.guing.common.components.dockable.CStackDockStation;
|
||||
import org.opentcs.modeleditor.components.dockable.DockingManagerModeling;
|
||||
import org.opentcs.util.event.EventSource;
|
||||
|
||||
/**
|
||||
* Manages the mapping of dockables to drawing views, transport order views and
|
||||
* order sequence views.
|
||||
*/
|
||||
public class ViewManagerModeling
|
||||
extends
|
||||
AbstractViewManager {
|
||||
|
||||
/**
|
||||
* Manages the application's docking frames.
|
||||
*/
|
||||
private final DockingManagerModeling dockingManager;
|
||||
/**
|
||||
* The default modelling dockable.
|
||||
*/
|
||||
private DefaultSingleCDockable drawingViewModellingDockable;
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*
|
||||
* @param dockingManager Manages the application's docking frames.
|
||||
* @param eventSource Where this instance registers event listeners.
|
||||
*/
|
||||
@Inject
|
||||
public ViewManagerModeling(
|
||||
DockingManagerModeling dockingManager,
|
||||
@ApplicationEventBus
|
||||
EventSource eventSource
|
||||
) {
|
||||
super(eventSource);
|
||||
this.dockingManager = requireNonNull(dockingManager, "dockingManager");
|
||||
}
|
||||
|
||||
public void init() {
|
||||
setPlantOverviewStateModelling();
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets all components.
|
||||
*/
|
||||
@Override
|
||||
public void reset() {
|
||||
super.reset();
|
||||
drawingViewModellingDockable = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the unique modelling dockable.
|
||||
*
|
||||
* @param dockable The dockable that will be the modelling dockable.
|
||||
* @param title The title of this dockable.
|
||||
*/
|
||||
public void initModellingDockable(DefaultSingleCDockable dockable, String title) {
|
||||
drawingViewModellingDockable = requireNonNull(dockable, "dockable");
|
||||
drawingViewModellingDockable.setTitleText(requireNonNull(title, "title"));
|
||||
drawingViewModellingDockable.setCloseable(false);
|
||||
}
|
||||
|
||||
public void setBitmapToModellingView(File file) {
|
||||
getDrawingViewMap().get(drawingViewModellingDockable)
|
||||
.getDrawingView()
|
||||
.addBackgroundBitmap(file);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets visibility states of all dockables to modelling.
|
||||
*/
|
||||
private void setPlantOverviewStateModelling() {
|
||||
CStackDockStation station
|
||||
= dockingManager.getTabPane(DockingManagerModeling.COURSE_TAB_PANE_ID).getStation();
|
||||
|
||||
for (DefaultSingleCDockable dock : new ArrayList<>(getDrawingViewMap().keySet())) {
|
||||
if (dock != drawingViewModellingDockable) {
|
||||
// Setting it to closeable = false, so the ClosingListener
|
||||
// doesn't remove the dockable when it's closed
|
||||
dock.setCloseable(false);
|
||||
dockingManager.setDockableVisibility(dock.getUniqueId(), false);
|
||||
}
|
||||
}
|
||||
|
||||
dockingManager.showDockable(station, drawingViewModellingDockable, 0);
|
||||
DrawingView view = getDrawingViewMap().get(drawingViewModellingDockable).getDrawingView();
|
||||
view.getComponent().dispatchEvent(new FocusEvent(view.getComponent(), FocusEvent.FOCUS_GAINED));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,471 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.modeleditor.application.action;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
import java.awt.Rectangle;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import javax.swing.Action;
|
||||
import javax.swing.ButtonGroup;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JToggleButton;
|
||||
import javax.swing.JToolBar;
|
||||
import org.jhotdraw.draw.DrawingEditor;
|
||||
import org.jhotdraw.draw.event.ToolAdapter;
|
||||
import org.jhotdraw.draw.event.ToolEvent;
|
||||
import org.jhotdraw.draw.event.ToolListener;
|
||||
import org.jhotdraw.draw.tool.ConnectionTool;
|
||||
import org.jhotdraw.draw.tool.CreationTool;
|
||||
import org.jhotdraw.draw.tool.Tool;
|
||||
import org.jhotdraw.gui.JPopupButton;
|
||||
import org.opentcs.guing.base.model.elements.PathModel;
|
||||
import org.opentcs.guing.base.model.elements.PointModel;
|
||||
import org.opentcs.guing.common.application.action.ToolButtonListener;
|
||||
import org.opentcs.guing.common.application.toolbar.DragTool;
|
||||
import org.opentcs.guing.common.components.drawing.OpenTCSDrawingEditor;
|
||||
import org.opentcs.guing.common.components.drawing.figures.LabeledLocationFigure;
|
||||
import org.opentcs.guing.common.components.drawing.figures.LabeledPointFigure;
|
||||
import org.opentcs.guing.common.components.drawing.figures.LinkConnection;
|
||||
import org.opentcs.guing.common.components.drawing.figures.PathConnection;
|
||||
import org.opentcs.guing.common.event.ResetInteractionToolCommand;
|
||||
import org.opentcs.guing.common.util.CourseObjectFactory;
|
||||
import org.opentcs.guing.common.util.ImageDirectory;
|
||||
import org.opentcs.modeleditor.application.action.actions.CreateBlockAction;
|
||||
import org.opentcs.modeleditor.application.action.actions.CreateLocationTypeAction;
|
||||
import org.opentcs.modeleditor.application.action.actions.CreateVehicleAction;
|
||||
import org.opentcs.modeleditor.application.action.draw.DefaultPointSelectedAction;
|
||||
import org.opentcs.modeleditor.application.toolbar.CreationToolFactory;
|
||||
import org.opentcs.modeleditor.application.toolbar.MultipleSelectionTool;
|
||||
import org.opentcs.modeleditor.application.toolbar.SelectionToolFactory;
|
||||
import org.opentcs.modeleditor.util.I18nPlantOverviewModeling;
|
||||
import org.opentcs.thirdparty.guing.common.jhotdraw.application.action.draw.SelectSameAction;
|
||||
import org.opentcs.thirdparty.guing.common.jhotdraw.util.ResourceBundleUtil;
|
||||
import org.opentcs.thirdparty.modeleditor.jhotdraw.application.action.ButtonFactory;
|
||||
import org.opentcs.thirdparty.modeleditor.jhotdraw.application.action.draw.DefaultPathSelectedAction;
|
||||
import org.opentcs.util.event.EventHandler;
|
||||
|
||||
/**
|
||||
* Sets up and manages a list of tool bars in the graphical user interface.
|
||||
*/
|
||||
public class ToolBarManager
|
||||
implements
|
||||
EventHandler {
|
||||
|
||||
/**
|
||||
* A factory for selectiont tools.
|
||||
*/
|
||||
private final SelectionToolFactory selectionToolFactory;
|
||||
/**
|
||||
* A list of all toolbars.
|
||||
*/
|
||||
private final List<JToolBar> toolBarList = Collections.synchronizedList(new ArrayList<>());
|
||||
/**
|
||||
* A tool bar for actions creating new items.
|
||||
*/
|
||||
private final JToolBar toolBarCreation = new JToolBar();
|
||||
/**
|
||||
* A tool bar for actions regarding alignment.
|
||||
*/
|
||||
private final JToolBar toolBarAlignment = new JToolBar();
|
||||
/**
|
||||
* A toggle button for the selection tool.
|
||||
*/
|
||||
private final JToggleButton selectionToolButton;
|
||||
/**
|
||||
* A toggle button for the drag tool.
|
||||
*/
|
||||
private final JToggleButton dragToolButton;
|
||||
/**
|
||||
* The actual drag tool.
|
||||
*/
|
||||
private DragTool dragTool;
|
||||
/**
|
||||
* A button for creating points.
|
||||
*/
|
||||
private final JPopupButton buttonCreatePoint;
|
||||
/**
|
||||
* A button for creating locations.
|
||||
*/
|
||||
private final JToggleButton buttonCreateLocation;
|
||||
/**
|
||||
* A button for creating paths.
|
||||
*/
|
||||
private final JPopupButton buttonCreatePath;
|
||||
/**
|
||||
* A button for creating location links.
|
||||
*/
|
||||
private final JToggleButton buttonCreateLink;
|
||||
/**
|
||||
* A button for creating location types.
|
||||
*/
|
||||
private final JButton buttonCreateLocationType;
|
||||
/**
|
||||
* A button for creating vehicles.
|
||||
*/
|
||||
private final JButton buttonCreateVehicle;
|
||||
/**
|
||||
* A button for creating blocks.
|
||||
*/
|
||||
private final JButton buttonCreateBlock;
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*
|
||||
* @param actionMap The action map to be used
|
||||
* @param crsObjFactory A factory for course objects
|
||||
* @param editor The drawing editor
|
||||
* @param creationToolFactory The creation tool factory.
|
||||
* @param selectionToolFactory The selection tool factory
|
||||
*/
|
||||
@Inject
|
||||
public ToolBarManager(
|
||||
ViewActionMap actionMap,
|
||||
CourseObjectFactory crsObjFactory,
|
||||
OpenTCSDrawingEditor editor,
|
||||
CreationToolFactory creationToolFactory,
|
||||
SelectionToolFactory selectionToolFactory
|
||||
) {
|
||||
requireNonNull(actionMap, "actionMap");
|
||||
requireNonNull(crsObjFactory, "crsObjFactory");
|
||||
requireNonNull(editor, "editor");
|
||||
requireNonNull(creationToolFactory, "creationToolFactory");
|
||||
this.selectionToolFactory = requireNonNull(selectionToolFactory, "selectionToolFactory");
|
||||
|
||||
ResourceBundleUtil labels
|
||||
= ResourceBundleUtil.getBundle(I18nPlantOverviewModeling.TOOLBAR_PATH);
|
||||
|
||||
// --- 1. ToolBar: Creation ---
|
||||
// Selection, Drag | Create Point, Location, Path, Link |
|
||||
// Create Location Type, Vehicle, Block, Static Route |
|
||||
// Create Transport Order | Find, Show Vehicles
|
||||
toolBarCreation.setActionMap(actionMap);
|
||||
// --- Selection Tool ---
|
||||
selectionToolButton = addSelectionToolButton(toolBarCreation, editor);
|
||||
// --- Drag Tool ---
|
||||
dragToolButton = addDragToolButton(toolBarCreation, editor);
|
||||
|
||||
toolBarCreation.addSeparator();
|
||||
|
||||
// --- Create Point Figure ---
|
||||
LabeledPointFigure lpf = crsObjFactory.createPointFigure();
|
||||
CreationTool creationTool = creationToolFactory.createCreationTool(lpf);
|
||||
buttonCreatePoint = pointToolButton(toolBarCreation, editor, creationTool);
|
||||
creationTool.setToolDoneAfterCreation(false);
|
||||
|
||||
// --- Create Location Figure ---
|
||||
LabeledLocationFigure llf = crsObjFactory.createLocationFigure();
|
||||
creationTool = creationToolFactory.createCreationTool(llf);
|
||||
buttonCreateLocation
|
||||
= addToolButton(
|
||||
toolBarCreation,
|
||||
editor,
|
||||
creationTool,
|
||||
labels.getString("toolBarManager.button_createLocation.tooltipText"),
|
||||
ImageDirectory.getImageIcon("/toolbar/location.22.png")
|
||||
);
|
||||
creationTool.setToolDoneAfterCreation(false);
|
||||
|
||||
// --- Create Path Figure ---
|
||||
PathConnection pc = crsObjFactory.createPathConnection();
|
||||
ConnectionTool connectionTool = creationToolFactory.createConnectionTool(pc);
|
||||
buttonCreatePath = pathToolButton(toolBarCreation, editor, connectionTool);
|
||||
connectionTool.setToolDoneAfterCreation(false);
|
||||
|
||||
// --- Create Link ---
|
||||
LinkConnection lc = crsObjFactory.createLinkConnection();
|
||||
connectionTool = creationToolFactory.createConnectionTool(lc);
|
||||
buttonCreateLink
|
||||
= addToolButton(
|
||||
toolBarCreation,
|
||||
editor,
|
||||
connectionTool,
|
||||
labels.getString("toolBarManager.button_createLink.tooltipText"),
|
||||
ImageDirectory.getImageIcon("/toolbar/link.22.png")
|
||||
);
|
||||
connectionTool.setToolDoneAfterCreation(false);
|
||||
|
||||
toolBarCreation.addSeparator();
|
||||
|
||||
// --- Location Type: No Figure, just creates a tree entry ---
|
||||
buttonCreateLocationType = new JButton(actionMap.get(CreateLocationTypeAction.ID));
|
||||
buttonCreateLocationType.setText(null);
|
||||
toolBarCreation.add(buttonCreateLocationType);
|
||||
|
||||
// --- Create Vehicle Figure ---
|
||||
buttonCreateVehicle = new JButton(actionMap.get(CreateVehicleAction.ID));
|
||||
buttonCreateVehicle.setText(null);
|
||||
toolBarCreation.add(buttonCreateVehicle);
|
||||
|
||||
// --- Create Block ---
|
||||
buttonCreateBlock = new JButton(actionMap.get(CreateBlockAction.ID));
|
||||
buttonCreateBlock.setText(null);
|
||||
toolBarCreation.add(buttonCreateBlock);
|
||||
|
||||
toolBarCreation.addSeparator();
|
||||
|
||||
toolBarCreation.setName(labels.getString("toolBarManager.toolbar_drawing.title"));
|
||||
toolBarList.add(toolBarCreation);
|
||||
|
||||
// --- 3. ToolBar: Alignment ---
|
||||
// Align: West, East, Horizontal; North, South, Vertical
|
||||
// Move: West, East, North, South
|
||||
// Bring to front, Send to back
|
||||
ButtonFactory.addAlignmentButtonsTo(toolBarAlignment, editor);
|
||||
toolBarAlignment.setName(labels.getString("toolBarManager.toolbar_alignment.title"));
|
||||
toolBarList.add(toolBarAlignment);
|
||||
}
|
||||
|
||||
public List<JToolBar> getToolBars() {
|
||||
return toolBarList;
|
||||
}
|
||||
|
||||
public JToolBar getToolBarCreation() {
|
||||
return toolBarCreation;
|
||||
}
|
||||
|
||||
public JToggleButton getSelectionToolButton() {
|
||||
return selectionToolButton;
|
||||
}
|
||||
|
||||
public JToggleButton getDragToolButton() {
|
||||
return dragToolButton;
|
||||
}
|
||||
|
||||
public JPopupButton getButtonCreatePath() {
|
||||
return buttonCreatePath;
|
||||
}
|
||||
|
||||
public JToggleButton getButtonCreateLink() {
|
||||
return buttonCreateLink;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEvent(Object event) {
|
||||
if (event instanceof ResetInteractionToolCommand) {
|
||||
handleToolReset((ResetInteractionToolCommand) event);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleToolReset(ResetInteractionToolCommand evt) {
|
||||
selectionToolButton.setSelected(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the selection tool to the given toolbar.
|
||||
*
|
||||
* @param toolBar The toolbar to add to.
|
||||
* @param editor The DrawingEditor.
|
||||
*/
|
||||
private JToggleButton addSelectionToolButton(
|
||||
JToolBar toolBar,
|
||||
DrawingEditor editor
|
||||
) {
|
||||
List<Action> drawingActions = new ArrayList<>();
|
||||
// Drawing Actions
|
||||
drawingActions.add(new SelectSameAction(editor));
|
||||
|
||||
MultipleSelectionTool selectionTool
|
||||
= selectionToolFactory.createMultipleSelectionTool(drawingActions, new ArrayList<>());
|
||||
|
||||
ButtonGroup buttonGroup;
|
||||
|
||||
if (toolBar.getClientProperty("toolButtonGroup") instanceof ButtonGroup) {
|
||||
buttonGroup = (ButtonGroup) toolBar.getClientProperty("toolButtonGroup");
|
||||
}
|
||||
else {
|
||||
buttonGroup = new ButtonGroup();
|
||||
toolBar.putClientProperty("toolButtonGroup", buttonGroup);
|
||||
}
|
||||
|
||||
// Selection tool
|
||||
editor.setTool(selectionTool);
|
||||
final JToggleButton toggleButton = new JToggleButton();
|
||||
|
||||
if (!(toolBar.getClientProperty("toolHandler") instanceof ToolListener)) {
|
||||
ToolListener toolHandler = new ToolAdapter() {
|
||||
@Override
|
||||
public void toolDone(ToolEvent event) {
|
||||
toggleButton.setSelected(true);
|
||||
}
|
||||
};
|
||||
|
||||
toolBar.putClientProperty("toolHandler", toolHandler);
|
||||
}
|
||||
|
||||
toggleButton.setIcon(ImageDirectory.getImageIcon("/toolbar/select-2.png"));
|
||||
toggleButton.setText(null);
|
||||
toggleButton.setToolTipText(
|
||||
ResourceBundleUtil.getBundle(I18nPlantOverviewModeling.TOOLBAR_PATH)
|
||||
.getString("toolBarManager.button_selectionTool.tooltipText")
|
||||
);
|
||||
|
||||
toggleButton.setSelected(true);
|
||||
toggleButton.addItemListener(new ToolButtonListener(selectionTool, editor));
|
||||
buttonGroup.add(toggleButton);
|
||||
toolBar.add(toggleButton);
|
||||
|
||||
return toggleButton;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param toolBar
|
||||
* @param editor
|
||||
*/
|
||||
private JToggleButton addDragToolButton(JToolBar toolBar, DrawingEditor editor) {
|
||||
final JToggleButton button = new JToggleButton();
|
||||
dragTool = new DragTool();
|
||||
editor.setTool(dragTool);
|
||||
|
||||
if (!(toolBar.getClientProperty("toolHandler") instanceof ToolListener)) {
|
||||
ToolListener toolHandler = new ToolAdapter() {
|
||||
@Override
|
||||
public void toolDone(ToolEvent event) {
|
||||
button.setSelected(true);
|
||||
}
|
||||
};
|
||||
toolBar.putClientProperty("toolHandler", toolHandler);
|
||||
}
|
||||
|
||||
URL url = getClass().getResource(ImageDirectory.DIR + "/toolbar/cursor-opened-hand.png");
|
||||
button.setIcon(new ImageIcon(url));
|
||||
button.setText(null);
|
||||
button.setToolTipText(
|
||||
ResourceBundleUtil.getBundle(I18nPlantOverviewModeling.TOOLBAR_PATH)
|
||||
.getString("toolBarManager.button_dragTool.tooltipText")
|
||||
);
|
||||
|
||||
button.setSelected(false);
|
||||
button.addItemListener(new ToolButtonListener(dragTool, editor));
|
||||
|
||||
ButtonGroup group = (ButtonGroup) toolBar.getClientProperty("toolButtonGroup");
|
||||
group.add(button);
|
||||
toolBar.add(button);
|
||||
return button;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures a JPopupButton with all available Point types.
|
||||
*
|
||||
* @param toolBar
|
||||
* @param editor OpenTCSDrawingEditor
|
||||
* @param tool CreationTool
|
||||
* @param labelKey
|
||||
* @param labels
|
||||
* @return
|
||||
*/
|
||||
private JPopupButton pointToolButton(
|
||||
JToolBar toolBar,
|
||||
DrawingEditor editor,
|
||||
Tool tool
|
||||
) {
|
||||
JPopupButton popupButton = new JPopupButton();
|
||||
ButtonGroup group = (ButtonGroup) toolBar.getClientProperty("toolButtonGroup");
|
||||
popupButton.setAction(
|
||||
new DefaultPointSelectedAction(editor, tool, popupButton, group),
|
||||
new Rectangle(0, 0, 16, 16)
|
||||
);
|
||||
ToolListener toolHandler = (ToolListener) toolBar.getClientProperty("toolHandler");
|
||||
tool.addToolListener(toolHandler);
|
||||
|
||||
for (PointModel.Type type : PointModel.Type.values()) {
|
||||
DefaultPointSelectedAction action
|
||||
= new DefaultPointSelectedAction(editor, tool, type, popupButton, group);
|
||||
popupButton.add(action);
|
||||
action.setEnabled(true);
|
||||
}
|
||||
|
||||
popupButton.setText(null);
|
||||
popupButton.setToolTipText(PointModel.Type.values()[0].getHelptext());
|
||||
popupButton.setIcon(ImageDirectory.getImageIcon("/toolbar/point-halt-arrow.22.png"));
|
||||
popupButton.setFocusable(true);
|
||||
|
||||
group.add(popupButton);
|
||||
toolBar.add(popupButton);
|
||||
|
||||
return popupButton;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method addSelectionToolButton must have been invoked prior to this on the
|
||||
* JToolBar.
|
||||
*
|
||||
* @param toolBar
|
||||
* @param editor
|
||||
* @param tool
|
||||
* @param toolTipText
|
||||
* @param labels
|
||||
* @return
|
||||
*/
|
||||
private JToggleButton addToolButton(
|
||||
JToolBar toolBar,
|
||||
DrawingEditor editor,
|
||||
Tool tool,
|
||||
String toolTipText,
|
||||
ImageIcon iconBase
|
||||
) {
|
||||
JToggleButton toggleButton = new JToggleButton();
|
||||
|
||||
toggleButton.setIcon(iconBase);
|
||||
toggleButton.setText(null);
|
||||
toggleButton.setToolTipText(toolTipText);
|
||||
toggleButton.addItemListener(new ToolButtonListener(tool, editor));
|
||||
|
||||
ToolListener toolHandler = (ToolListener) toolBar.getClientProperty("toolHandler");
|
||||
tool.addToolListener(toolHandler);
|
||||
|
||||
ButtonGroup group = (ButtonGroup) toolBar.getClientProperty("toolButtonGroup");
|
||||
group.add(toggleButton);
|
||||
toolBar.add(toggleButton);
|
||||
|
||||
return toggleButton;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures a JPopupButton with all available path types.
|
||||
*
|
||||
* @param toolBar
|
||||
* @param editor
|
||||
* @param tool
|
||||
* @param labels
|
||||
* @param types
|
||||
* @return
|
||||
*/
|
||||
private JPopupButton pathToolButton(
|
||||
JToolBar toolBar,
|
||||
DrawingEditor editor,
|
||||
Tool tool
|
||||
) {
|
||||
JPopupButton popupButton = new JPopupButton();
|
||||
ButtonGroup group = (ButtonGroup) toolBar.getClientProperty("toolButtonGroup");
|
||||
popupButton.setAction(
|
||||
new DefaultPathSelectedAction(editor, tool, popupButton, group),
|
||||
new Rectangle(0, 0, 16, 16)
|
||||
);
|
||||
ToolListener toolHandler = (ToolListener) toolBar.getClientProperty("toolHandler");
|
||||
tool.addToolListener(toolHandler);
|
||||
|
||||
for (PathModel.Type type : PathModel.Type.values()) {
|
||||
DefaultPathSelectedAction action
|
||||
= new DefaultPathSelectedAction(editor, tool, type, popupButton, group);
|
||||
popupButton.add(action);
|
||||
action.setEnabled(true);
|
||||
}
|
||||
|
||||
popupButton.setText(null);
|
||||
popupButton.setToolTipText(PathModel.Type.values()[0].getHelptext());
|
||||
popupButton.setIcon(ImageDirectory.getImageIcon("/toolbar/path-direct-arrow.22.png"));
|
||||
popupButton.setFocusable(true);
|
||||
|
||||
group.add(popupButton);
|
||||
toolBar.add(popupButton);
|
||||
|
||||
return popupButton;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.modeleditor.application.action;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
import javax.swing.ActionMap;
|
||||
import org.opentcs.guing.common.application.action.file.ModelPropertiesAction;
|
||||
import org.opentcs.guing.common.application.action.file.SaveModelAction;
|
||||
import org.opentcs.guing.common.application.action.file.SaveModelAsAction;
|
||||
import org.opentcs.modeleditor.application.OpenTCSView;
|
||||
import org.opentcs.modeleditor.application.action.actions.CreateBlockAction;
|
||||
import org.opentcs.modeleditor.application.action.actions.CreateLocationTypeAction;
|
||||
import org.opentcs.modeleditor.application.action.actions.CreateVehicleAction;
|
||||
import org.opentcs.modeleditor.application.action.app.AboutAction;
|
||||
import org.opentcs.modeleditor.application.action.file.DownloadModelFromKernelAction;
|
||||
import org.opentcs.modeleditor.application.action.file.LoadModelAction;
|
||||
import org.opentcs.modeleditor.application.action.file.NewModelAction;
|
||||
import org.opentcs.modeleditor.application.action.file.UploadModelToKernelAction;
|
||||
import org.opentcs.modeleditor.application.action.view.AddBitmapAction;
|
||||
import org.opentcs.modeleditor.application.action.view.RestoreDockingLayoutAction;
|
||||
import org.opentcs.thirdparty.guing.common.jhotdraw.application.action.edit.DeleteAction;
|
||||
import org.opentcs.thirdparty.guing.common.jhotdraw.application.action.edit.SelectAllAction;
|
||||
import org.opentcs.thirdparty.guing.common.jhotdraw.application.action.edit.UndoRedoManager;
|
||||
import org.opentcs.thirdparty.modeleditor.jhotdraw.application.action.edit.ClearSelectionAction;
|
||||
import org.opentcs.thirdparty.modeleditor.jhotdraw.application.action.edit.CopyAction;
|
||||
import org.opentcs.thirdparty.modeleditor.jhotdraw.application.action.edit.CutAction;
|
||||
import org.opentcs.thirdparty.modeleditor.jhotdraw.application.action.edit.DuplicateAction;
|
||||
import org.opentcs.thirdparty.modeleditor.jhotdraw.application.action.edit.PasteAction;
|
||||
import org.opentcs.thirdparty.modeleditor.jhotdraw.application.action.file.CloseFileAction;
|
||||
|
||||
/**
|
||||
* A custom ActionMap for the plant overview application.
|
||||
*/
|
||||
public class ViewActionMap
|
||||
extends
|
||||
ActionMap {
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*
|
||||
* @param view The openTCS view
|
||||
* @param undoRedoManager The undo redo manager
|
||||
* @param aboutAction The action to show the about window
|
||||
* @param modelPropertiesAction The action to show some model properties.
|
||||
* @param loadModelFromKernelAction The action to load the current kernel model.
|
||||
*/
|
||||
@Inject
|
||||
@SuppressWarnings("this-escape")
|
||||
public ViewActionMap(
|
||||
OpenTCSView view,
|
||||
UndoRedoManager undoRedoManager,
|
||||
AboutAction aboutAction,
|
||||
ModelPropertiesAction modelPropertiesAction,
|
||||
DownloadModelFromKernelAction loadModelFromKernelAction
|
||||
) {
|
||||
requireNonNull(view, "view");
|
||||
requireNonNull(undoRedoManager, "undoRedoManager");
|
||||
requireNonNull(aboutAction, "aboutAction");
|
||||
|
||||
// --- Menu File ---
|
||||
put(NewModelAction.ID, new NewModelAction(view));
|
||||
put(LoadModelAction.ID, new LoadModelAction(view));
|
||||
put(SaveModelAction.ID, new SaveModelAction(view));
|
||||
put(SaveModelAsAction.ID, new SaveModelAsAction(view));
|
||||
put(ModelPropertiesAction.ID, modelPropertiesAction);
|
||||
put(CloseFileAction.ID, new CloseFileAction(view));
|
||||
|
||||
// --- Menu Synchronize ---
|
||||
put(UploadModelToKernelAction.ID, new UploadModelToKernelAction(view));
|
||||
put(DownloadModelFromKernelAction.ID, loadModelFromKernelAction);
|
||||
|
||||
// --- Menu Edit ---
|
||||
// Undo, Redo
|
||||
put(UndoRedoManager.UNDO_ACTION_ID, undoRedoManager.getUndoAction());
|
||||
put(UndoRedoManager.REDO_ACTION_ID, undoRedoManager.getRedoAction());
|
||||
// Cut, Copy, Paste, Duplicate, Delete
|
||||
put(CutAction.ID, new CutAction());
|
||||
put(CopyAction.ID, new CopyAction());
|
||||
put(PasteAction.ID, new PasteAction());
|
||||
put(DuplicateAction.ID, new DuplicateAction());
|
||||
put(DeleteAction.ID, new DeleteAction());
|
||||
// Select all, Clear selection
|
||||
put(SelectAllAction.ID, new SelectAllAction());
|
||||
put(ClearSelectionAction.ID, new ClearSelectionAction());
|
||||
|
||||
// --- Menu Actions ---
|
||||
// Menu item Actions -> Create ...
|
||||
put(CreateLocationTypeAction.ID, new CreateLocationTypeAction(view));
|
||||
put(CreateVehicleAction.ID, new CreateVehicleAction(view));
|
||||
put(CreateBlockAction.ID, new CreateBlockAction(view));
|
||||
|
||||
// --- Menu View ---
|
||||
put(AddBitmapAction.ID, new AddBitmapAction(view));
|
||||
put(RestoreDockingLayoutAction.ID, new RestoreDockingLayoutAction(view));
|
||||
|
||||
// --- Menu Help ---
|
||||
put(AboutAction.ID, aboutAction);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.modeleditor.application.action.actions;
|
||||
|
||||
import static javax.swing.Action.LARGE_ICON_KEY;
|
||||
import static javax.swing.Action.SMALL_ICON;
|
||||
import static org.opentcs.modeleditor.util.I18nPlantOverviewModeling.TOOLBAR_PATH;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import javax.swing.AbstractAction;
|
||||
import javax.swing.ImageIcon;
|
||||
import org.opentcs.guing.common.application.GuiManagerModeling;
|
||||
import org.opentcs.guing.common.util.ImageDirectory;
|
||||
import org.opentcs.thirdparty.guing.common.jhotdraw.util.ResourceBundleUtil;
|
||||
|
||||
/**
|
||||
* An action to trigger the creation of a block.
|
||||
*/
|
||||
public class CreateBlockAction
|
||||
extends
|
||||
AbstractAction {
|
||||
|
||||
/**
|
||||
* This action class's ID.
|
||||
*/
|
||||
public static final String ID = "openTCS.createBlock";
|
||||
|
||||
private static final ResourceBundleUtil BUNDLE = ResourceBundleUtil.getBundle(TOOLBAR_PATH);
|
||||
/**
|
||||
* The GUI manager instance we're working with.
|
||||
*/
|
||||
private final GuiManagerModeling guiManager;
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*
|
||||
* @param guiManager The GUI manager instance we're working with.
|
||||
*/
|
||||
@SuppressWarnings("this-escape")
|
||||
public CreateBlockAction(GuiManagerModeling guiManager) {
|
||||
this.guiManager = guiManager;
|
||||
|
||||
putValue(NAME, BUNDLE.getString("createBlockAction.name"));
|
||||
putValue(SHORT_DESCRIPTION, BUNDLE.getString("createBlockAction.shortDescription"));
|
||||
|
||||
ImageIcon iconSmall = ImageDirectory.getImageIcon("/toolbar/blockdevice-3.16.png");
|
||||
ImageIcon iconLarge = ImageDirectory.getImageIcon("/toolbar/blockdevice-3.22.png");
|
||||
putValue(SMALL_ICON, iconSmall);
|
||||
putValue(LARGE_ICON_KEY, iconLarge);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent evt) {
|
||||
guiManager.createBlockModel();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.modeleditor.application.action.actions;
|
||||
|
||||
import static javax.swing.Action.LARGE_ICON_KEY;
|
||||
import static javax.swing.Action.SMALL_ICON;
|
||||
import static org.opentcs.modeleditor.util.I18nPlantOverviewModeling.TOOLBAR_PATH;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import javax.swing.AbstractAction;
|
||||
import javax.swing.ImageIcon;
|
||||
import org.opentcs.guing.common.application.GuiManagerModeling;
|
||||
import org.opentcs.guing.common.util.ImageDirectory;
|
||||
import org.opentcs.thirdparty.guing.common.jhotdraw.util.ResourceBundleUtil;
|
||||
|
||||
/**
|
||||
* An action to trigger the creation of a location type.
|
||||
*/
|
||||
public class CreateLocationTypeAction
|
||||
extends
|
||||
AbstractAction {
|
||||
|
||||
/**
|
||||
* This action class's ID.
|
||||
*/
|
||||
public static final String ID = "openTCS.createLocationType";
|
||||
|
||||
private static final ResourceBundleUtil BUNDLE = ResourceBundleUtil.getBundle(TOOLBAR_PATH);
|
||||
/**
|
||||
* The GUI manager instance we're working with.
|
||||
*/
|
||||
private final GuiManagerModeling guiManager;
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*
|
||||
* @param guiManager The GUI manager instance we're working with.
|
||||
*/
|
||||
@SuppressWarnings("this-escape")
|
||||
public CreateLocationTypeAction(GuiManagerModeling guiManager) {
|
||||
this.guiManager = guiManager;
|
||||
|
||||
putValue(NAME, BUNDLE.getString("createLocationTypeAction.name"));
|
||||
putValue(SHORT_DESCRIPTION, BUNDLE.getString("createLocationTypeAction.shortDescription"));
|
||||
|
||||
ImageIcon icon = ImageDirectory.getImageIcon("/toolbar/locationType.22.png");
|
||||
putValue(SMALL_ICON, icon);
|
||||
putValue(LARGE_ICON_KEY, icon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent evt) {
|
||||
guiManager.createLocationTypeModel();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.modeleditor.application.action.actions;
|
||||
|
||||
import static javax.swing.Action.LARGE_ICON_KEY;
|
||||
import static javax.swing.Action.SMALL_ICON;
|
||||
import static org.opentcs.modeleditor.util.I18nPlantOverviewModeling.TOOLBAR_PATH;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import javax.swing.AbstractAction;
|
||||
import javax.swing.ImageIcon;
|
||||
import org.opentcs.guing.common.application.GuiManagerModeling;
|
||||
import org.opentcs.guing.common.util.ImageDirectory;
|
||||
import org.opentcs.thirdparty.guing.common.jhotdraw.util.ResourceBundleUtil;
|
||||
|
||||
/**
|
||||
* An action to trigger the creation of a vehicle.
|
||||
*/
|
||||
public class CreateVehicleAction
|
||||
extends
|
||||
AbstractAction {
|
||||
|
||||
/**
|
||||
* This action class's ID.
|
||||
*/
|
||||
public static final String ID = "openTCS.createVehicle";
|
||||
|
||||
private static final ResourceBundleUtil BUNDLE = ResourceBundleUtil.getBundle(TOOLBAR_PATH);
|
||||
/**
|
||||
* The GUI manager instance we're working with.
|
||||
*/
|
||||
private final GuiManagerModeling guiManager;
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*
|
||||
* @param guiManager The GUI manager instance we're working with.
|
||||
*/
|
||||
@SuppressWarnings("this-escape")
|
||||
public CreateVehicleAction(GuiManagerModeling guiManager) {
|
||||
this.guiManager = guiManager;
|
||||
|
||||
putValue(NAME, BUNDLE.getString("createVehicleAction.name"));
|
||||
putValue(SHORT_DESCRIPTION, BUNDLE.getString("createVehicleAction.shortDescription"));
|
||||
|
||||
ImageIcon icon = ImageDirectory.getImageIcon("/toolbar/car.png");
|
||||
putValue(SMALL_ICON, icon);
|
||||
putValue(LARGE_ICON_KEY, icon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent evt) {
|
||||
guiManager.createVehicleModel();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.modeleditor.application.action.app;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
import static javax.swing.Action.LARGE_ICON_KEY;
|
||||
import static javax.swing.Action.MNEMONIC_KEY;
|
||||
import static javax.swing.Action.SMALL_ICON;
|
||||
import static org.opentcs.modeleditor.util.I18nPlantOverviewModeling.MENU_PATH;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
import java.awt.Component;
|
||||
import java.awt.event.ActionEvent;
|
||||
import javax.swing.AbstractAction;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JOptionPane;
|
||||
import org.opentcs.access.SharedKernelServicePortalProvider;
|
||||
import org.opentcs.customizations.plantoverview.ApplicationFrame;
|
||||
import org.opentcs.guing.common.application.ApplicationState;
|
||||
import org.opentcs.guing.common.util.ImageDirectory;
|
||||
import org.opentcs.modeleditor.application.OpenTCSView;
|
||||
import org.opentcs.thirdparty.guing.common.jhotdraw.util.ResourceBundleUtil;
|
||||
import org.opentcs.util.Environment;
|
||||
|
||||
/**
|
||||
* Displays a dialog showing information about the application.
|
||||
*/
|
||||
public class AboutAction
|
||||
extends
|
||||
AbstractAction {
|
||||
|
||||
/**
|
||||
* This action's ID.
|
||||
*/
|
||||
public static final String ID = "application.about";
|
||||
|
||||
private static final ResourceBundleUtil BUNDLE = ResourceBundleUtil.getBundle(MENU_PATH);
|
||||
/**
|
||||
* Stores the application's current state.
|
||||
*/
|
||||
private final ApplicationState appState;
|
||||
/**
|
||||
* Provides access to a portal.
|
||||
*/
|
||||
private final SharedKernelServicePortalProvider portalProvider;
|
||||
/**
|
||||
* The parent component for dialogs shown by this action.
|
||||
*/
|
||||
private final Component dialogParent;
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*
|
||||
* @param appState Stores the application's current state.
|
||||
* @param portalProvider Provides access to a portal.
|
||||
* @param dialogParent The parent component for dialogs shown by this action.
|
||||
*/
|
||||
@Inject
|
||||
@SuppressWarnings("this-escape")
|
||||
public AboutAction(
|
||||
ApplicationState appState,
|
||||
SharedKernelServicePortalProvider portalProvider,
|
||||
@ApplicationFrame
|
||||
Component dialogParent
|
||||
) {
|
||||
this.appState = requireNonNull(appState, "appState");
|
||||
this.portalProvider = requireNonNull(portalProvider, "portalProvider");
|
||||
this.dialogParent = requireNonNull(dialogParent, "dialogParent");
|
||||
|
||||
putValue(NAME, BUNDLE.getString("aboutAction.name"));
|
||||
putValue(MNEMONIC_KEY, Integer.valueOf('A'));
|
||||
|
||||
ImageIcon icon = ImageDirectory.getImageIcon("/menu/help-contents.png");
|
||||
putValue(SMALL_ICON, icon);
|
||||
putValue(LARGE_ICON_KEY, icon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent evt) {
|
||||
JOptionPane.showMessageDialog(
|
||||
dialogParent,
|
||||
"<html><p><b>" + OpenTCSView.NAME + "</b><br> "
|
||||
+ BUNDLE.getFormatted(
|
||||
"aboutAction.optionPane_applicationInformation.message.baselineVersion",
|
||||
Environment.getBaselineVersion()
|
||||
)
|
||||
+ "<br>"
|
||||
+ BUNDLE.getFormatted(
|
||||
"aboutAction.optionPane_applicationInformation.message.customization",
|
||||
Environment.getCustomizationName(),
|
||||
Environment.getCustomizationVersion()
|
||||
)
|
||||
+ "<br>"
|
||||
+ BUNDLE.getString(
|
||||
"aboutAction.optionPane_applicationInformation.message.copyright"
|
||||
)
|
||||
+ "<br>"
|
||||
+ BUNDLE.getString(
|
||||
"aboutAction.optionPane_applicationInformation.message.runningOn"
|
||||
)
|
||||
+ "<br>"
|
||||
+ "Java: "
|
||||
+ System.getProperty("java.version")
|
||||
+ ", "
|
||||
+ System.getProperty("java.vendor")
|
||||
+ "<br>"
|
||||
+ "JVM: "
|
||||
+ System.getProperty("java.vm.version")
|
||||
+ ", "
|
||||
+ System.getProperty("java.vm.vendor")
|
||||
+ "<br>"
|
||||
+ "OS: "
|
||||
+ System.getProperty("os.name")
|
||||
+ " "
|
||||
+ System.getProperty("os.version")
|
||||
+ ", "
|
||||
+ System.getProperty("os.arch")
|
||||
+ "<br>"
|
||||
+ "<b>Kernel</b><br>"
|
||||
+ portalProvider.getPortalDescription()
|
||||
+ "<br>"
|
||||
+ BUNDLE.getFormatted(
|
||||
"aboutAction.optionPane_applicationInformation.message.mode",
|
||||
appState.getOperationMode()
|
||||
)
|
||||
+ "</p></html>",
|
||||
BUNDLE.getString(
|
||||
"aboutAction.optionPane_applicationInformation.title"
|
||||
),
|
||||
JOptionPane.PLAIN_MESSAGE,
|
||||
new ImageIcon(
|
||||
getClass().getResource("/org/opentcs/guing/res/symbols/openTCS/openTCS.300x132.gif")
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.modeleditor.application.action.draw;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import javax.swing.AbstractAction;
|
||||
import javax.swing.ButtonGroup;
|
||||
import javax.swing.ImageIcon;
|
||||
import org.jhotdraw.draw.DrawingEditor;
|
||||
import org.jhotdraw.draw.action.AbstractSelectedAction;
|
||||
import org.jhotdraw.draw.tool.CreationTool;
|
||||
import org.jhotdraw.draw.tool.Tool;
|
||||
import org.jhotdraw.gui.JPopupButton;
|
||||
import org.opentcs.guing.base.model.elements.PointModel;
|
||||
import org.opentcs.guing.common.components.drawing.figures.LabeledPointFigure;
|
||||
import org.opentcs.guing.common.components.drawing.figures.PointFigure;
|
||||
import org.opentcs.guing.common.util.ImageDirectory;
|
||||
|
||||
/**
|
||||
* This action manages the behaviour when the user selects the point button.
|
||||
*/
|
||||
public class DefaultPointSelectedAction
|
||||
extends
|
||||
AbstractSelectedAction {
|
||||
|
||||
/**
|
||||
* The SelectionProperty contains all point types in the model.
|
||||
*/
|
||||
private final PointModel.Type pointType;
|
||||
|
||||
private final Tool tool;
|
||||
/**
|
||||
* The button this action belongs to.
|
||||
*/
|
||||
private final JPopupButton popupButton;
|
||||
/**
|
||||
* The Icon the popup button uses when this action is selected.
|
||||
*/
|
||||
private final ImageIcon largeIcon;
|
||||
/**
|
||||
* The ButtonGroup the popupButton belongs to. It is necessary to know it,
|
||||
* because
|
||||
* <code>DrawingEditor.setTool()</code> doesn't select or deselect the
|
||||
* popupButton, so we have to do it manually.
|
||||
*/
|
||||
private final ButtonGroup group;
|
||||
|
||||
/**
|
||||
* Constructor for an action of a button in the toolbar.
|
||||
*
|
||||
* @param editor The drawing editor
|
||||
* @param tool The tool
|
||||
* @param popupButton The popup button
|
||||
* @param group The button group
|
||||
*/
|
||||
public DefaultPointSelectedAction(
|
||||
DrawingEditor editor,
|
||||
Tool tool,
|
||||
JPopupButton popupButton,
|
||||
ButtonGroup group
|
||||
) {
|
||||
super(editor);
|
||||
this.tool = requireNonNull(tool);
|
||||
this.popupButton = requireNonNull(popupButton);
|
||||
this.group = requireNonNull(group);
|
||||
|
||||
this.pointType = null;
|
||||
this.largeIcon = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for a button inside a drop down menu of another button.
|
||||
*
|
||||
* @param editor The drawing editor
|
||||
* @param tool The tool
|
||||
* @param pointType The point type
|
||||
* @param popupButton The popup button
|
||||
* @param group The button group
|
||||
*/
|
||||
@SuppressWarnings("this-escape")
|
||||
public DefaultPointSelectedAction(
|
||||
DrawingEditor editor,
|
||||
Tool tool,
|
||||
PointModel.Type pointType,
|
||||
JPopupButton popupButton,
|
||||
ButtonGroup group
|
||||
) {
|
||||
super(editor);
|
||||
this.pointType = requireNonNull(pointType);
|
||||
this.tool = requireNonNull(tool);
|
||||
this.popupButton = requireNonNull(popupButton);
|
||||
this.group = requireNonNull(group);
|
||||
|
||||
this.largeIcon = getLargeImageIconByType(pointType);
|
||||
|
||||
putValue(AbstractAction.NAME, pointType.getDescription());
|
||||
putValue(AbstractAction.SHORT_DESCRIPTION, pointType.getHelptext());
|
||||
putValue(AbstractAction.SMALL_ICON, getImageIconByType(pointType));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (pointType != null) {
|
||||
CreationTool creationTool = (CreationTool) tool;
|
||||
LabeledPointFigure lpf = (LabeledPointFigure) creationTool.getPrototype();
|
||||
PointFigure pointFigure = lpf.getPresentationFigure();
|
||||
pointFigure.getModel().getPropertyType().setValue(pointType);
|
||||
|
||||
popupButton.setText(null);
|
||||
popupButton.setToolTipText(pointType.getHelptext());
|
||||
popupButton.setIcon(largeIcon);
|
||||
}
|
||||
|
||||
getEditor().setTool(tool);
|
||||
group.setSelected(popupButton.getModel(), true);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateEnabledState() {
|
||||
setEnabled(getView() != null && getView().isEnabled());
|
||||
}
|
||||
|
||||
private ImageIcon getImageIconByType(PointModel.Type pointType) {
|
||||
switch (pointType) {
|
||||
case HALT:
|
||||
return ImageDirectory.getImageIcon("/toolbar/point-halt.22.png");
|
||||
case PARK:
|
||||
return ImageDirectory.getImageIcon("/toolbar/point-park.22.png");
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private ImageIcon getLargeImageIconByType(PointModel.Type pointType) {
|
||||
switch (pointType) {
|
||||
case HALT:
|
||||
return ImageDirectory.getImageIcon("/toolbar/point-halt-arrow.22.png");
|
||||
case PARK:
|
||||
return ImageDirectory.getImageIcon("/toolbar/point-park-arrow.22.png");
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.modeleditor.application.action.file;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
import static javax.swing.Action.ACCELERATOR_KEY;
|
||||
import static javax.swing.Action.MNEMONIC_KEY;
|
||||
import static org.opentcs.modeleditor.util.I18nPlantOverviewModeling.MENU_PATH;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
import java.awt.event.ActionEvent;
|
||||
import javax.swing.AbstractAction;
|
||||
import javax.swing.KeyStroke;
|
||||
import org.opentcs.modeleditor.application.OpenTCSView;
|
||||
import org.opentcs.thirdparty.guing.common.jhotdraw.util.ResourceBundleUtil;
|
||||
|
||||
/**
|
||||
* An action to load the current kernel model in the plant overview.
|
||||
*/
|
||||
public class DownloadModelFromKernelAction
|
||||
extends
|
||||
AbstractAction {
|
||||
|
||||
/**
|
||||
* This action's ID.
|
||||
*/
|
||||
public static final String ID = "file.downloadModelFromKernel";
|
||||
|
||||
private static final ResourceBundleUtil BUNDLE = ResourceBundleUtil.getBundle(MENU_PATH);
|
||||
/**
|
||||
* The OpenTCS view.
|
||||
*/
|
||||
private final OpenTCSView openTCSView;
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*
|
||||
* @param openTCSView The openTCS view.
|
||||
*/
|
||||
@Inject
|
||||
@SuppressWarnings("this-escape")
|
||||
public DownloadModelFromKernelAction(OpenTCSView openTCSView) {
|
||||
this.openTCSView = requireNonNull(openTCSView);
|
||||
|
||||
putValue(NAME, BUNDLE.getString("downloadModelFromKernelAction.name"));
|
||||
putValue(SHORT_DESCRIPTION, BUNDLE.getString("downloadModelFromKernelAction.shortDescription"));
|
||||
putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke("alt K"));
|
||||
putValue(MNEMONIC_KEY, Integer.valueOf('K'));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
openTCSView.downloadModelFromKernel();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.modeleditor.application.action.file;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import javax.swing.AbstractAction;
|
||||
import org.opentcs.components.plantoverview.PlantModelExporter;
|
||||
import org.opentcs.guing.common.application.GuiManager;
|
||||
|
||||
/**
|
||||
*/
|
||||
public class ExportPlantModelAction
|
||||
extends
|
||||
AbstractAction {
|
||||
|
||||
private final PlantModelExporter exporter;
|
||||
private final GuiManager guiManager;
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*
|
||||
* @param exporter The importer.
|
||||
* @param guiManager The gui manager
|
||||
*/
|
||||
@SuppressWarnings("this-escape")
|
||||
public ExportPlantModelAction(PlantModelExporter exporter, GuiManager guiManager) {
|
||||
this.exporter = requireNonNull(exporter, "exporter");
|
||||
this.guiManager = requireNonNull(guiManager, "guiManager");
|
||||
this.putValue(NAME, exporter.getDescription());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent evt) {
|
||||
guiManager.exportModel(exporter);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.modeleditor.application.action.file;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import javax.swing.AbstractAction;
|
||||
import org.opentcs.components.plantoverview.PlantModelImporter;
|
||||
import org.opentcs.guing.common.application.GuiManager;
|
||||
|
||||
/**
|
||||
*/
|
||||
public class ImportPlantModelAction
|
||||
extends
|
||||
AbstractAction {
|
||||
|
||||
private final PlantModelImporter importer;
|
||||
private final GuiManager guiManager;
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*
|
||||
* @param importer The importer.
|
||||
* @param guiManager The gui manager
|
||||
*/
|
||||
@SuppressWarnings("this-escape")
|
||||
public ImportPlantModelAction(PlantModelImporter importer, GuiManager guiManager) {
|
||||
this.importer = requireNonNull(importer, "importer");
|
||||
this.guiManager = requireNonNull(guiManager, "guiManager");
|
||||
this.putValue(NAME, importer.getDescription());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent evt) {
|
||||
guiManager.importModel(importer);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.modeleditor.application.action.file;
|
||||
|
||||
import static org.opentcs.modeleditor.util.I18nPlantOverviewModeling.MENU_PATH;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import javax.swing.AbstractAction;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.KeyStroke;
|
||||
import org.opentcs.guing.common.application.GuiManager;
|
||||
import org.opentcs.guing.common.util.ImageDirectory;
|
||||
import org.opentcs.thirdparty.guing.common.jhotdraw.util.ResourceBundleUtil;
|
||||
|
||||
/**
|
||||
*/
|
||||
public class LoadModelAction
|
||||
extends
|
||||
AbstractAction {
|
||||
|
||||
/**
|
||||
* This action's ID.
|
||||
*/
|
||||
public static final String ID = "file.loadModel";
|
||||
private static final ResourceBundleUtil BUNDLE = ResourceBundleUtil.getBundle(MENU_PATH);
|
||||
private final GuiManager view;
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*
|
||||
* @param view The gui manager
|
||||
*/
|
||||
@SuppressWarnings("this-escape")
|
||||
public LoadModelAction(GuiManager view) {
|
||||
this.view = view;
|
||||
|
||||
putValue(NAME, BUNDLE.getString("loadModelAction.name"));
|
||||
putValue(SHORT_DESCRIPTION, BUNDLE.getString("loadModelAction.shortDescription"));
|
||||
putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke("ctrl L"));
|
||||
putValue(MNEMONIC_KEY, Integer.valueOf('L'));
|
||||
|
||||
ImageIcon icon = ImageDirectory.getImageIcon("/menu/document-import-2.png");
|
||||
putValue(SMALL_ICON, icon);
|
||||
putValue(LARGE_ICON_KEY, icon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent evt) {
|
||||
view.loadModel();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.modeleditor.application.action.file;
|
||||
|
||||
import static org.opentcs.modeleditor.util.I18nPlantOverviewModeling.MENU_PATH;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import javax.swing.AbstractAction;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.KeyStroke;
|
||||
import org.opentcs.guing.common.application.GuiManager;
|
||||
import org.opentcs.guing.common.util.ImageDirectory;
|
||||
import org.opentcs.thirdparty.guing.common.jhotdraw.util.ResourceBundleUtil;
|
||||
|
||||
/**
|
||||
*/
|
||||
public class NewModelAction
|
||||
extends
|
||||
AbstractAction {
|
||||
|
||||
/**
|
||||
* This action's ID.
|
||||
*/
|
||||
public static final String ID = "file.newModel";
|
||||
|
||||
private static final ResourceBundleUtil BUNDLE = ResourceBundleUtil.getBundle(MENU_PATH);
|
||||
|
||||
private final GuiManager view;
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*
|
||||
* @param view The gui manager
|
||||
*/
|
||||
@SuppressWarnings("this-escape")
|
||||
public NewModelAction(GuiManager view) {
|
||||
this.view = view;
|
||||
|
||||
putValue(NAME, BUNDLE.getString("newModelAction.name"));
|
||||
putValue(SHORT_DESCRIPTION, BUNDLE.getString("newModelAction.shortDescription"));
|
||||
putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke("ctrl N"));
|
||||
putValue(MNEMONIC_KEY, Integer.valueOf('N'));
|
||||
|
||||
ImageIcon icon = ImageDirectory.getImageIcon("/menu/document-new.png");
|
||||
putValue(SMALL_ICON, icon);
|
||||
putValue(LARGE_ICON_KEY, icon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent evt) {
|
||||
view.createEmptyModel();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.modeleditor.application.action.file;
|
||||
|
||||
import static javax.swing.Action.ACCELERATOR_KEY;
|
||||
import static javax.swing.Action.MNEMONIC_KEY;
|
||||
import static org.opentcs.modeleditor.util.I18nPlantOverviewModeling.MENU_PATH;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.util.Objects;
|
||||
import javax.swing.AbstractAction;
|
||||
import javax.swing.KeyStroke;
|
||||
import org.opentcs.modeleditor.application.OpenTCSView;
|
||||
import org.opentcs.thirdparty.guing.common.jhotdraw.util.ResourceBundleUtil;
|
||||
|
||||
/**
|
||||
* An action to upload the (local) model to the kernel.
|
||||
*/
|
||||
public class UploadModelToKernelAction
|
||||
extends
|
||||
AbstractAction {
|
||||
|
||||
/**
|
||||
* This action's ID.
|
||||
*/
|
||||
public static final String ID = "file.uploadModelToKernel";
|
||||
|
||||
private static final ResourceBundleUtil BUNDLE = ResourceBundleUtil.getBundle(MENU_PATH);
|
||||
|
||||
private final OpenTCSView openTCSView;
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*
|
||||
* @param openTCSView The openTCS view
|
||||
*/
|
||||
@SuppressWarnings("this-escape")
|
||||
public UploadModelToKernelAction(OpenTCSView openTCSView) {
|
||||
this.openTCSView = Objects.requireNonNull(openTCSView);
|
||||
|
||||
putValue(NAME, BUNDLE.getString("uploadModelToKernelAction.name"));
|
||||
putValue(SHORT_DESCRIPTION, BUNDLE.getString("uploadModelToKernelAction.shortDescription"));
|
||||
putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke("alt P"));
|
||||
putValue(MNEMONIC_KEY, Integer.valueOf('P'));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
openTCSView.uploadModelToKernel();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.modeleditor.application.action.view;
|
||||
|
||||
import static org.opentcs.modeleditor.util.I18nPlantOverviewModeling.MENU_PATH;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.io.File;
|
||||
import java.util.Objects;
|
||||
import javax.swing.AbstractAction;
|
||||
import javax.swing.JFileChooser;
|
||||
import javax.swing.filechooser.FileNameExtensionFilter;
|
||||
import org.opentcs.modeleditor.application.OpenTCSView;
|
||||
import org.opentcs.thirdparty.guing.common.jhotdraw.util.ResourceBundleUtil;
|
||||
|
||||
/**
|
||||
* Actions for adding background bitmaps to the drawing view.
|
||||
*/
|
||||
public class AddBitmapAction
|
||||
extends
|
||||
AbstractAction {
|
||||
|
||||
/**
|
||||
* This action's ID.
|
||||
*/
|
||||
public static final String ID = "view.addBitmap";
|
||||
|
||||
private static final ResourceBundleUtil BUNDLE = ResourceBundleUtil.getBundle(MENU_PATH);
|
||||
|
||||
private final JFileChooser fc;
|
||||
|
||||
private final OpenTCSView view;
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*
|
||||
* @param view The openTCS view
|
||||
*/
|
||||
@SuppressWarnings("this-escape")
|
||||
public AddBitmapAction(OpenTCSView view) {
|
||||
this.view = Objects.requireNonNull(view, "view");
|
||||
|
||||
this.fc = new JFileChooser(System.getProperty("opentcs.home"));
|
||||
this.fc.setFileFilter(
|
||||
new FileNameExtensionFilter(
|
||||
"Bitmaps (PNG, JPG, BMP, GIF)",
|
||||
"png",
|
||||
"jpg",
|
||||
"bmp",
|
||||
"gif"
|
||||
)
|
||||
);
|
||||
this.fc.setFileSelectionMode(JFileChooser.FILES_ONLY);
|
||||
|
||||
putValue(NAME, BUNDLE.getString("addBitmapAction.name"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
int returnVal = fc.showOpenDialog(null);
|
||||
|
||||
if (returnVal == JFileChooser.APPROVE_OPTION) {
|
||||
File file = fc.getSelectedFile();
|
||||
view.addBackgroundBitmap(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.modeleditor.application.action.view;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import javax.swing.AbstractAction;
|
||||
import org.opentcs.modeleditor.application.OpenTCSView;
|
||||
|
||||
/**
|
||||
* Action for resetting the docking layout.
|
||||
*/
|
||||
public class RestoreDockingLayoutAction
|
||||
extends
|
||||
AbstractAction {
|
||||
|
||||
/**
|
||||
* This action's ID.
|
||||
*/
|
||||
public static final String ID = "openTCS.restoreDockingLayout";
|
||||
private final OpenTCSView view;
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*
|
||||
* @param view The openTCS view
|
||||
*/
|
||||
public RestoreDockingLayoutAction(OpenTCSView view) {
|
||||
this.view = view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
view.resetWindowArrangement();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.modeleditor.application.menus;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Provider;
|
||||
import java.awt.event.ActionEvent;
|
||||
import javax.swing.JMenuItem;
|
||||
import javax.swing.JOptionPane;
|
||||
import org.jhotdraw.draw.DrawingEditor;
|
||||
import org.opentcs.guing.base.components.properties.event.NullAttributesChangeListener;
|
||||
import org.opentcs.guing.base.components.properties.type.LengthProperty;
|
||||
import org.opentcs.guing.base.model.elements.PathModel;
|
||||
import org.opentcs.guing.common.components.dialogs.StandardContentDialog;
|
||||
import org.opentcs.guing.common.components.drawing.OpenTCSDrawingEditor;
|
||||
import org.opentcs.guing.common.components.drawing.figures.FigureConstants;
|
||||
import org.opentcs.guing.common.components.properties.PropertyUndoActivity;
|
||||
import org.opentcs.modeleditor.components.dialog.PathTypeSelectionPanel;
|
||||
import org.opentcs.modeleditor.math.path.PathLengthFunction;
|
||||
import org.opentcs.modeleditor.util.I18nPlantOverviewModeling;
|
||||
import org.opentcs.thirdparty.guing.common.jhotdraw.application.action.edit.UndoRedoManager;
|
||||
import org.opentcs.thirdparty.guing.common.jhotdraw.util.ResourceBundleUtil;
|
||||
import org.opentcs.util.gui.Icons;
|
||||
|
||||
/**
|
||||
* A menu item to calculate and update the lengths of paths.
|
||||
*/
|
||||
public class CalculatePathLengthMenuItem
|
||||
extends
|
||||
JMenuItem {
|
||||
|
||||
/**
|
||||
* The <code>DrawingEditor</code> instance.
|
||||
*/
|
||||
private final DrawingEditor drawingEditor;
|
||||
/**
|
||||
* The UndoRedoManager instance to be used.
|
||||
*/
|
||||
private final UndoRedoManager undoRedoManager;
|
||||
/**
|
||||
* The calculator to use to calculate the path length.
|
||||
*/
|
||||
private final Provider<PathLengthFunction> pathLengthFunctionProvider;
|
||||
|
||||
@Inject
|
||||
@SuppressWarnings("this-escape")
|
||||
public CalculatePathLengthMenuItem(
|
||||
OpenTCSDrawingEditor drawingEditor,
|
||||
UndoRedoManager undoRedoManager,
|
||||
Provider<PathLengthFunction> pathLengthFunctionProvider
|
||||
) {
|
||||
super(
|
||||
ResourceBundleUtil.getBundle(I18nPlantOverviewModeling.MENU_PATH)
|
||||
.getString("calculatePathLengthMenuItem.text")
|
||||
);
|
||||
this.drawingEditor = requireNonNull(drawingEditor, "drawingEditor");
|
||||
this.undoRedoManager = requireNonNull(undoRedoManager, "undoRedoManager");
|
||||
this.pathLengthFunctionProvider
|
||||
= requireNonNull(pathLengthFunctionProvider, "pathLengthFunctionProvider");
|
||||
|
||||
addActionListener(this::calculatePathLength);
|
||||
}
|
||||
|
||||
private void calculatePathLength(ActionEvent e) {
|
||||
PathTypeSelectionPanel content = new PathTypeSelectionPanel();
|
||||
StandardContentDialog dialog
|
||||
= new StandardContentDialog(JOptionPane.getFrameForComponent(this), content);
|
||||
dialog.setIconImages(Icons.getOpenTCSIcons());
|
||||
dialog.setVisible(true);
|
||||
|
||||
if (dialog.getReturnStatus() != StandardContentDialog.RET_OK) {
|
||||
return;
|
||||
}
|
||||
|
||||
PathLengthFunction pathLengthFunction = pathLengthFunctionProvider.get();
|
||||
|
||||
drawingEditor.getActiveView().getDrawing().getFiguresFrontToBack().stream()
|
||||
.map(figure -> figure.get(FigureConstants.MODEL))
|
||||
.filter(model -> model instanceof PathModel)
|
||||
.map(model -> (PathModel) model)
|
||||
.filter(path -> content.isPathTypeSelected(connectionType(path)))
|
||||
.forEach(path -> updatePath(path, pathLengthFunction));
|
||||
}
|
||||
|
||||
private PathModel.Type connectionType(PathModel path) {
|
||||
return (PathModel.Type) path.getPropertyPathConnType().getValue();
|
||||
}
|
||||
|
||||
private void updatePath(PathModel path, PathLengthFunction pathLengthFunction) {
|
||||
updatePathLength(path, Math.round(pathLengthFunction.applyAsDouble(path)));
|
||||
path.propertiesChanged(new NullAttributesChangeListener());
|
||||
}
|
||||
|
||||
private void updatePathLength(PathModel path, double length) {
|
||||
LengthProperty pathLengthProperty = path.getPropertyLength();
|
||||
|
||||
PropertyUndoActivity pua = new PropertyUndoActivity(pathLengthProperty);
|
||||
pua.snapShotBeforeModification();
|
||||
|
||||
pathLengthProperty.setValueAndUnit(length, LengthProperty.Unit.MM);
|
||||
pathLengthProperty.markChanged();
|
||||
|
||||
pua.snapShotAfterModification();
|
||||
undoRedoManager.addEdit(pua);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.modeleditor.application.menus;
|
||||
|
||||
import com.google.inject.assistedinject.Assisted;
|
||||
import jakarta.inject.Inject;
|
||||
import org.opentcs.guing.base.components.properties.type.CoordinateProperty;
|
||||
import org.opentcs.guing.common.components.properties.CoordinateUndoActivity;
|
||||
import org.opentcs.guing.common.persistence.ModelManager;
|
||||
import org.opentcs.modeleditor.util.I18nPlantOverviewModeling;
|
||||
import org.opentcs.thirdparty.guing.common.jhotdraw.util.ResourceBundleUtil;
|
||||
|
||||
/**
|
||||
*/
|
||||
public class LayoutToModelCoordinateUndoActivity
|
||||
extends
|
||||
CoordinateUndoActivity {
|
||||
|
||||
@Inject
|
||||
public LayoutToModelCoordinateUndoActivity(
|
||||
@Assisted
|
||||
CoordinateProperty property,
|
||||
ModelManager modelManager
|
||||
) {
|
||||
super(property, modelManager);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPresentationName() {
|
||||
return ResourceBundleUtil.getBundle(I18nPlantOverviewModeling.MISC_PATH)
|
||||
.getString("layoutToModelCoordinateUndoActivity.presentationName");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void saveTransformBeforeModification() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void saveTransformForUndo() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void saveTransformForRedo() {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,185 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.modeleditor.application.menus;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
import com.google.inject.assistedinject.Assisted;
|
||||
import jakarta.inject.Inject;
|
||||
import java.awt.Insets;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JMenuItem;
|
||||
import org.jhotdraw.draw.DrawingEditor;
|
||||
import org.jhotdraw.draw.DrawingView;
|
||||
import org.jhotdraw.draw.Figure;
|
||||
import org.opentcs.customizations.ApplicationEventBus;
|
||||
import org.opentcs.data.model.visualization.ElementPropKeys;
|
||||
import org.opentcs.guing.base.components.properties.event.NullAttributesChangeListener;
|
||||
import org.opentcs.guing.base.components.properties.type.CoordinateProperty;
|
||||
import org.opentcs.guing.base.components.properties.type.StringProperty;
|
||||
import org.opentcs.guing.base.model.ModelComponent;
|
||||
import org.opentcs.guing.base.model.elements.LocationModel;
|
||||
import org.opentcs.guing.base.model.elements.PointModel;
|
||||
import org.opentcs.guing.common.components.drawing.OpenTCSDrawingEditor;
|
||||
import org.opentcs.guing.common.components.drawing.figures.FigureConstants;
|
||||
import org.opentcs.guing.common.components.properties.CoordinateUndoActivity;
|
||||
import org.opentcs.guing.common.event.ResetInteractionToolCommand;
|
||||
import org.opentcs.modeleditor.util.I18nPlantOverviewModeling;
|
||||
import org.opentcs.thirdparty.guing.common.jhotdraw.application.action.edit.UndoRedoManager;
|
||||
import org.opentcs.thirdparty.guing.common.jhotdraw.util.ResourceBundleUtil;
|
||||
import org.opentcs.util.event.EventHandler;
|
||||
|
||||
/**
|
||||
* A menu item for copying the value of the layout properties of selected points
|
||||
* or locations to the corresponding model properties.
|
||||
*/
|
||||
public class LayoutToModelMenuItem
|
||||
extends
|
||||
JMenuItem {
|
||||
|
||||
/**
|
||||
* The <code>DrawingEditor</code> instance.
|
||||
*/
|
||||
private final DrawingEditor drawingEditor;
|
||||
/**
|
||||
* The UndoRedoManager instance to be used.
|
||||
*/
|
||||
private final UndoRedoManager undoRedoManager;
|
||||
/**
|
||||
* Where we send events.
|
||||
*/
|
||||
private final EventHandler eventHandler;
|
||||
/**
|
||||
* The components factory.
|
||||
*/
|
||||
private final MenuItemComponentsFactory componentsFactory;
|
||||
/**
|
||||
* A flag if the values of ALL points and location shall be copied when
|
||||
* the menu item is clicked. If false only the selected figures will be
|
||||
* considered.
|
||||
*/
|
||||
private final boolean copyAll;
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*
|
||||
* @param drawingEditor A <code>DrawingEditor</code> instance.
|
||||
* @param undoRedoManager The application's undo/redo manager.
|
||||
* @param eventHandler Where this instance sends events.
|
||||
* @param componentsFactory The components factory.
|
||||
* @param copyAll Indicates whether the values of ALL points and locations
|
||||
* shall be copied when the menu item is clicked. If false only the selected
|
||||
* figures will be considered.
|
||||
*/
|
||||
@Inject
|
||||
@SuppressWarnings("this-escape")
|
||||
public LayoutToModelMenuItem(
|
||||
OpenTCSDrawingEditor drawingEditor,
|
||||
UndoRedoManager undoRedoManager,
|
||||
@ApplicationEventBus
|
||||
EventHandler eventHandler,
|
||||
MenuItemComponentsFactory componentsFactory,
|
||||
@Assisted
|
||||
boolean copyAll
|
||||
) {
|
||||
super(
|
||||
ResourceBundleUtil.getBundle(I18nPlantOverviewModeling.MENU_PATH)
|
||||
.getString("layoutToModelMenuItem.text")
|
||||
);
|
||||
this.drawingEditor = requireNonNull(drawingEditor, "drawingEditor");
|
||||
this.undoRedoManager = requireNonNull(undoRedoManager, "undoRedoManager");
|
||||
this.eventHandler = requireNonNull(eventHandler, "eventHandler");
|
||||
this.componentsFactory = requireNonNull(componentsFactory, "componentsFactory");
|
||||
this.copyAll = copyAll;
|
||||
|
||||
setIcon(
|
||||
new ImageIcon(
|
||||
getClass().getClassLoader()
|
||||
.getResource("org/opentcs/guing/res/symbols/menu/arrow-up-3.png")
|
||||
)
|
||||
);
|
||||
setMargin(new Insets(0, 2, 0, 2));
|
||||
addActionListener();
|
||||
}
|
||||
|
||||
private void addActionListener() {
|
||||
addActionListener(new ActionListener() {
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
for (Figure figure : copyAll
|
||||
? getView().getDrawing().getFiguresFrontToBack()
|
||||
: getView().getSelectedFigures()) {
|
||||
ModelComponent model = figure.get(FigureConstants.MODEL);
|
||||
if (model instanceof PointModel || model instanceof LocationModel) {
|
||||
updateModelX(model);
|
||||
updateModelY(model);
|
||||
model.propertiesChanged(new NullAttributesChangeListener());
|
||||
eventHandler.onEvent(new ResetInteractionToolCommand(this));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private DrawingView getView() {
|
||||
return drawingEditor.getActiveView();
|
||||
}
|
||||
|
||||
private void updateModelY(ModelComponent model)
|
||||
throws IllegalArgumentException {
|
||||
CoordinateProperty modelProperty;
|
||||
if (model instanceof PointModel) {
|
||||
modelProperty = (CoordinateProperty) model.getProperty(PointModel.MODEL_Y_POSITION);
|
||||
}
|
||||
else {
|
||||
modelProperty = (CoordinateProperty) model.getProperty(LocationModel.MODEL_Y_POSITION);
|
||||
}
|
||||
CoordinateUndoActivity cua
|
||||
= componentsFactory.createLayoutToModelCoordinateUndoActivity(modelProperty);
|
||||
cua.snapShotBeforeModification();
|
||||
StringProperty spy;
|
||||
if (model instanceof PointModel) {
|
||||
spy = (StringProperty) model.getProperty(ElementPropKeys.POINT_POS_Y);
|
||||
}
|
||||
else {
|
||||
spy = (StringProperty) model.getProperty(ElementPropKeys.LOC_POS_Y);
|
||||
}
|
||||
|
||||
if (!spy.getText().isEmpty()) {
|
||||
modelProperty.setValueAndUnit(Double.parseDouble(spy.getText()), modelProperty.getUnit());
|
||||
modelProperty.markChanged();
|
||||
}
|
||||
cua.snapShotAfterModification();
|
||||
undoRedoManager.addEdit(cua);
|
||||
}
|
||||
|
||||
private void updateModelX(ModelComponent model)
|
||||
throws IllegalArgumentException {
|
||||
CoordinateProperty modelProperty;
|
||||
if (model instanceof PointModel) {
|
||||
modelProperty = (CoordinateProperty) model.getProperty(PointModel.MODEL_X_POSITION);
|
||||
}
|
||||
else {
|
||||
modelProperty = (CoordinateProperty) model.getProperty(LocationModel.MODEL_X_POSITION);
|
||||
}
|
||||
CoordinateUndoActivity cua
|
||||
= componentsFactory.createLayoutToModelCoordinateUndoActivity(modelProperty);
|
||||
cua.snapShotBeforeModification();
|
||||
StringProperty spx;
|
||||
if (model instanceof PointModel) {
|
||||
spx = (StringProperty) model.getProperty(ElementPropKeys.POINT_POS_X);
|
||||
}
|
||||
else {
|
||||
spx = (StringProperty) model.getProperty(ElementPropKeys.LOC_POS_X);
|
||||
}
|
||||
if (!spx.getText().isEmpty()) {
|
||||
modelProperty.setValueAndUnit(Double.parseDouble(spx.getText()), modelProperty.getUnit());
|
||||
modelProperty.markChanged();
|
||||
}
|
||||
cua.snapShotAfterModification();
|
||||
undoRedoManager.addEdit(cua);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.modeleditor.application.menus;
|
||||
|
||||
/**
|
||||
* A factory for various menus and menu items.
|
||||
*/
|
||||
public interface MenuFactory {
|
||||
|
||||
/**
|
||||
* Creates a menu item for copying the value of the layout properties of
|
||||
* selected elements to the corresponding model properties.
|
||||
*
|
||||
* @param copyAll Indicates whether the values of ALL points and locations
|
||||
* shall be copied when the menu item is clicked. If false only the selected
|
||||
* figures will be considered.
|
||||
* @return The created menu item.
|
||||
*/
|
||||
LayoutToModelMenuItem createLayoutToModelMenuItem(boolean copyAll);
|
||||
|
||||
/**
|
||||
*
|
||||
* @param copyAll Indicates whether the values of ALL points and locations
|
||||
* shall be copied when the menu item is clicked. If false only the selected
|
||||
* figures will be considered.
|
||||
* @return The created menu item.
|
||||
*/
|
||||
ModelToLayoutMenuItem createModelToLayoutMenuItem(boolean copyAll);
|
||||
|
||||
/**
|
||||
* Creates a menu item for calculating the length of paths.
|
||||
*
|
||||
* @return The created menu item.
|
||||
*/
|
||||
CalculatePathLengthMenuItem createCalculatePathLengthMenuItem();
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.modeleditor.application.menus;
|
||||
|
||||
import org.opentcs.guing.base.components.properties.type.CoordinateProperty;
|
||||
|
||||
/**
|
||||
* A factory for creating instances in relation to menu items.
|
||||
*/
|
||||
public interface MenuItemComponentsFactory {
|
||||
|
||||
/**
|
||||
* Creates a {@link LayoutToModelCoordinateUndoActivity} for the given coordinate property.
|
||||
*
|
||||
* @param property The property.
|
||||
* @return The {@link LayoutToModelCoordinateUndoActivity}.
|
||||
*/
|
||||
LayoutToModelCoordinateUndoActivity createLayoutToModelCoordinateUndoActivity(
|
||||
CoordinateProperty property
|
||||
);
|
||||
|
||||
/**
|
||||
* Creates a {@link ModelToLayoutCoordinateUndoActivity} for the given coordinate property.
|
||||
*
|
||||
* @param property The property.
|
||||
* @return The {@link ModelToLayoutCoordinateUndoActivity}.
|
||||
*/
|
||||
ModelToLayoutCoordinateUndoActivity createModelToLayoutCoordinateUndoActivity(
|
||||
CoordinateProperty property
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.modeleditor.application.menus;
|
||||
|
||||
import com.google.inject.assistedinject.Assisted;
|
||||
import jakarta.inject.Inject;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.geom.NoninvertibleTransformException;
|
||||
import org.opentcs.data.model.visualization.ElementPropKeys;
|
||||
import org.opentcs.guing.base.components.properties.type.CoordinateProperty;
|
||||
import org.opentcs.guing.base.components.properties.type.StringProperty;
|
||||
import org.opentcs.guing.base.model.AbstractConnectableModelComponent;
|
||||
import org.opentcs.guing.common.components.drawing.course.Origin;
|
||||
import org.opentcs.guing.common.components.drawing.figures.FigureConstants;
|
||||
import org.opentcs.guing.common.components.drawing.figures.TCSFigure;
|
||||
import org.opentcs.guing.common.components.properties.CoordinateUndoActivity;
|
||||
import org.opentcs.guing.common.persistence.ModelManager;
|
||||
import org.opentcs.modeleditor.util.I18nPlantOverviewModeling;
|
||||
import org.opentcs.thirdparty.guing.common.jhotdraw.util.ResourceBundleUtil;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
*/
|
||||
public class ModelToLayoutCoordinateUndoActivity
|
||||
extends
|
||||
CoordinateUndoActivity {
|
||||
|
||||
/**
|
||||
* This class's logger.
|
||||
*/
|
||||
private static final Logger LOG
|
||||
= LoggerFactory.getLogger(ModelToLayoutCoordinateUndoActivity.class);
|
||||
|
||||
@Inject
|
||||
public ModelToLayoutCoordinateUndoActivity(
|
||||
@Assisted
|
||||
CoordinateProperty property,
|
||||
ModelManager modelManager
|
||||
) {
|
||||
super(property, modelManager);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPresentationName() {
|
||||
return ResourceBundleUtil.getBundle(I18nPlantOverviewModeling.MISC_PATH)
|
||||
.getString("modelToLayoutCoordinateUndoActivity.presentationName");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void saveTransformBeforeModification() {
|
||||
AbstractConnectableModelComponent model
|
||||
= (AbstractConnectableModelComponent) property.getModel();
|
||||
StringProperty pxLayout = (StringProperty) model.getProperty(ElementPropKeys.POINT_POS_X);
|
||||
StringProperty pyLayout = (StringProperty) model.getProperty(ElementPropKeys.POINT_POS_Y);
|
||||
|
||||
Origin origin = bufferedFigure.get(FigureConstants.ORIGIN);
|
||||
TCSFigure pf = bufferedFigure.getPresentationFigure();
|
||||
double zoomScale = pf.getZoomPoint().scale();
|
||||
double xModel
|
||||
= pxModel.getValueByUnit(CoordinateProperty.Unit.MM) / (zoomScale * origin.getScaleX());
|
||||
double yModel
|
||||
= pyModel.getValueByUnit(CoordinateProperty.Unit.MM) / (-zoomScale * origin.getScaleY());
|
||||
String sx = (String) pxLayout.getComparableValue();
|
||||
double xLayout = Double.parseDouble(sx) / (zoomScale * origin.getScaleX());
|
||||
String sy = (String) pyLayout.getComparableValue();
|
||||
double yLayout = Double.parseDouble(sy) / (-zoomScale * origin.getScaleY());
|
||||
|
||||
bufferedTransform.translate(xModel - xLayout, yModel - yLayout);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void saveTransformForUndo() {
|
||||
try {
|
||||
AffineTransform inverse = bufferedTransform.createInverse();
|
||||
bufferedFigure.willChange();
|
||||
bufferedFigure.transform(inverse);
|
||||
bufferedFigure.changed();
|
||||
}
|
||||
catch (NoninvertibleTransformException e) {
|
||||
LOG.warn("Exception inverting transform.", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void saveTransformForRedo() {
|
||||
bufferedFigure.willChange();
|
||||
bufferedFigure.transform(bufferedTransform);
|
||||
bufferedFigure.changed();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,192 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.modeleditor.application.menus;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
import com.google.inject.assistedinject.Assisted;
|
||||
import jakarta.inject.Inject;
|
||||
import java.awt.Insets;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JMenuItem;
|
||||
import org.jhotdraw.draw.DrawingEditor;
|
||||
import org.jhotdraw.draw.DrawingView;
|
||||
import org.jhotdraw.draw.Figure;
|
||||
import org.opentcs.customizations.ApplicationEventBus;
|
||||
import org.opentcs.data.model.visualization.ElementPropKeys;
|
||||
import org.opentcs.guing.base.components.properties.event.AttributesChangeEvent;
|
||||
import org.opentcs.guing.base.components.properties.event.NullAttributesChangeListener;
|
||||
import org.opentcs.guing.base.components.properties.type.CoordinateProperty;
|
||||
import org.opentcs.guing.base.components.properties.type.ModelAttribute;
|
||||
import org.opentcs.guing.base.components.properties.type.StringProperty;
|
||||
import org.opentcs.guing.base.model.ModelComponent;
|
||||
import org.opentcs.guing.base.model.elements.LocationModel;
|
||||
import org.opentcs.guing.base.model.elements.PointModel;
|
||||
import org.opentcs.guing.common.components.drawing.OpenTCSDrawingEditor;
|
||||
import org.opentcs.guing.common.components.drawing.figures.FigureConstants;
|
||||
import org.opentcs.guing.common.components.drawing.figures.LabeledFigure;
|
||||
import org.opentcs.guing.common.components.properties.CoordinateUndoActivity;
|
||||
import org.opentcs.guing.common.event.ResetInteractionToolCommand;
|
||||
import org.opentcs.modeleditor.util.I18nPlantOverviewModeling;
|
||||
import org.opentcs.thirdparty.guing.common.jhotdraw.application.action.edit.UndoRedoManager;
|
||||
import org.opentcs.thirdparty.guing.common.jhotdraw.util.ResourceBundleUtil;
|
||||
import org.opentcs.util.event.EventHandler;
|
||||
|
||||
/**
|
||||
* A menu item for copying the value of the model properties of selected points
|
||||
* or locations to the corresponding layout properties.
|
||||
*/
|
||||
public class ModelToLayoutMenuItem
|
||||
extends
|
||||
JMenuItem {
|
||||
|
||||
/**
|
||||
* The <code>DrawingEditor</code> instance.
|
||||
*/
|
||||
private final DrawingEditor drawingEditor;
|
||||
/**
|
||||
* The UndoRedoManager instance to be used.
|
||||
*/
|
||||
private final UndoRedoManager undoRedoManager;
|
||||
/**
|
||||
* Where we send events.
|
||||
*/
|
||||
private final EventHandler eventBus;
|
||||
/**
|
||||
* The components factory.
|
||||
*/
|
||||
private final MenuItemComponentsFactory componentsFactory;
|
||||
/**
|
||||
* A flag if the values of ALL points and location shall be copied when
|
||||
* the menu item is clicked. If false only the selected figures will be
|
||||
* considered.
|
||||
*/
|
||||
private final boolean copyAll;
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*
|
||||
* @param drawingEditor A <code>DrawingEditor</code> instance.
|
||||
* @param undoRedoManager The application's undo/redo manager.
|
||||
* @param eventHandler Where this instance sends events.
|
||||
* @param componentsFactory The components factory.
|
||||
* @param copyAll Indicates whether the values of ALL points and locations
|
||||
* shall be copied when the menu item is clicked. If false only the selected
|
||||
* figures will be considered.
|
||||
*/
|
||||
@Inject
|
||||
@SuppressWarnings("this-escape")
|
||||
public ModelToLayoutMenuItem(
|
||||
OpenTCSDrawingEditor drawingEditor,
|
||||
UndoRedoManager undoRedoManager,
|
||||
@ApplicationEventBus
|
||||
EventHandler eventHandler,
|
||||
MenuItemComponentsFactory componentsFactory,
|
||||
@Assisted
|
||||
boolean copyAll
|
||||
) {
|
||||
super(
|
||||
ResourceBundleUtil.getBundle(I18nPlantOverviewModeling.MENU_PATH)
|
||||
.getString("modelToLayoutMenuItem.text")
|
||||
);
|
||||
this.drawingEditor = requireNonNull(drawingEditor, "drawingEditor");
|
||||
this.undoRedoManager = requireNonNull(undoRedoManager, "undoRedoManager");
|
||||
this.eventBus = requireNonNull(eventHandler, "eventHandler");
|
||||
this.componentsFactory = requireNonNull(componentsFactory, "componentsFactory");
|
||||
this.copyAll = copyAll;
|
||||
|
||||
setIcon(
|
||||
new ImageIcon(
|
||||
getClass().getClassLoader()
|
||||
.getResource("org/opentcs/guing/res/symbols/menu/arrow-down-3.png")
|
||||
)
|
||||
);
|
||||
setMargin(new Insets(0, 2, 0, 2));
|
||||
addActionListener();
|
||||
}
|
||||
|
||||
private void addActionListener() {
|
||||
addActionListener(new ActionListener() {
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
for (Figure figure : copyAll
|
||||
? getView().getDrawing().getFiguresFrontToBack()
|
||||
: getView().getSelectedFigures()) {
|
||||
ModelComponent model = figure.get(FigureConstants.MODEL);
|
||||
if (model instanceof PointModel || model instanceof LocationModel) {
|
||||
updateLayoutX(model);
|
||||
updateLayoutY(model);
|
||||
// ... and move the figure
|
||||
final LabeledFigure labeledFigure = (LabeledFigure) figure;
|
||||
labeledFigure.propertiesChanged(
|
||||
new AttributesChangeEvent(
|
||||
new NullAttributesChangeListener(), model
|
||||
)
|
||||
);
|
||||
|
||||
model.propertiesChanged(new NullAttributesChangeListener());
|
||||
eventBus.onEvent(new ResetInteractionToolCommand(this));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private DrawingView getView() {
|
||||
return drawingEditor.getActiveView();
|
||||
}
|
||||
|
||||
private void updateLayoutY(ModelComponent model) {
|
||||
CoordinateProperty modelProperty;
|
||||
if (model instanceof PointModel) {
|
||||
modelProperty = (CoordinateProperty) model.getProperty(PointModel.MODEL_Y_POSITION);
|
||||
}
|
||||
else {
|
||||
modelProperty = (CoordinateProperty) model.getProperty(LocationModel.MODEL_Y_POSITION);
|
||||
}
|
||||
CoordinateUndoActivity cua
|
||||
= componentsFactory.createModelToLayoutCoordinateUndoActivity(modelProperty);
|
||||
cua.snapShotBeforeModification();
|
||||
modelProperty.setChangeState(ModelAttribute.ChangeState.DETAIL_CHANGED);
|
||||
StringProperty spy;
|
||||
if (model instanceof PointModel) {
|
||||
spy = (StringProperty) model.getProperty(ElementPropKeys.POINT_POS_Y);
|
||||
}
|
||||
else {
|
||||
spy = (StringProperty) model.getProperty(ElementPropKeys.LOC_POS_Y);
|
||||
}
|
||||
spy.setText(String.valueOf(((Number) modelProperty.getValue()).intValue()));
|
||||
spy.markChanged();
|
||||
cua.snapShotAfterModification();
|
||||
undoRedoManager.addEdit(cua);
|
||||
}
|
||||
|
||||
private void updateLayoutX(ModelComponent model) {
|
||||
CoordinateProperty modelProperty;
|
||||
if (model instanceof PointModel) {
|
||||
modelProperty = (CoordinateProperty) model.getProperty(PointModel.MODEL_X_POSITION);
|
||||
}
|
||||
else {
|
||||
modelProperty = (CoordinateProperty) model.getProperty(LocationModel.MODEL_X_POSITION);
|
||||
}
|
||||
CoordinateUndoActivity cua
|
||||
= componentsFactory.createModelToLayoutCoordinateUndoActivity(modelProperty);
|
||||
cua.snapShotBeforeModification();
|
||||
modelProperty.setChangeState(ModelAttribute.ChangeState.DETAIL_CHANGED);
|
||||
// Copy the model coordinates to the layout coordinates...
|
||||
StringProperty spx;
|
||||
if (model instanceof PointModel) {
|
||||
spx = (StringProperty) model.getProperty(ElementPropKeys.POINT_POS_X);
|
||||
}
|
||||
else {
|
||||
spx = (StringProperty) model.getProperty(ElementPropKeys.LOC_POS_X);
|
||||
}
|
||||
spx.setText(String.valueOf(((Number) modelProperty.getValue()).intValue()));
|
||||
spx.markChanged();
|
||||
cua.snapShotAfterModification();
|
||||
undoRedoManager.addEdit(cua);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.modeleditor.application.menus.menubar;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
import javax.swing.JMenu;
|
||||
import javax.swing.JMenuItem;
|
||||
import org.opentcs.guing.common.components.drawing.OpenTCSDrawingEditor;
|
||||
import org.opentcs.modeleditor.application.action.ViewActionMap;
|
||||
import org.opentcs.modeleditor.application.menus.MenuFactory;
|
||||
import org.opentcs.modeleditor.util.I18nPlantOverviewModeling;
|
||||
import org.opentcs.thirdparty.guing.common.jhotdraw.util.ResourceBundleUtil;
|
||||
|
||||
/**
|
||||
* The application's menu for run-time actions.
|
||||
*/
|
||||
public class ActionsMenu
|
||||
extends
|
||||
JMenu {
|
||||
|
||||
/**
|
||||
* A menu item for assuming the model coordinates from the layout coordinates.
|
||||
*/
|
||||
private final JMenuItem cbiAlignLayoutWithModel;
|
||||
/**
|
||||
* A menu item for assuming the layout coordinates from the model coordinates.
|
||||
*/
|
||||
private final JMenuItem cbiAlignModelWithLayout;
|
||||
/**
|
||||
* A menu item for calculating the euclidean distance for paths.
|
||||
*/
|
||||
private final JMenuItem calculatePathLength;
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*
|
||||
* @param actionMap The application's action map.
|
||||
* @param drawingEditor The application's drawing editor.
|
||||
* @param menuFactory A factory for menu items.
|
||||
*/
|
||||
@Inject
|
||||
@SuppressWarnings("this-escape")
|
||||
public ActionsMenu(
|
||||
ViewActionMap actionMap,
|
||||
OpenTCSDrawingEditor drawingEditor,
|
||||
MenuFactory menuFactory
|
||||
) {
|
||||
requireNonNull(actionMap, "actionMap");
|
||||
requireNonNull(drawingEditor, "drawingEditor");
|
||||
requireNonNull(menuFactory, "menuFactory");
|
||||
|
||||
final ResourceBundleUtil labels
|
||||
= ResourceBundleUtil.getBundle(I18nPlantOverviewModeling.MENU_PATH);
|
||||
|
||||
this.setText(labels.getString("actionsMenu.text"));
|
||||
this.setToolTipText(labels.getString("actionsMenu.tooltipText"));
|
||||
this.setMnemonic('A');
|
||||
|
||||
// Menu item Actions -> Copy model to layout
|
||||
cbiAlignModelWithLayout = menuFactory.createModelToLayoutMenuItem(true);
|
||||
add(cbiAlignModelWithLayout);
|
||||
|
||||
// Menu item Actions -> Copy layout to model
|
||||
cbiAlignLayoutWithModel = menuFactory.createLayoutToModelMenuItem(true);
|
||||
add(cbiAlignLayoutWithModel);
|
||||
|
||||
calculatePathLength = menuFactory.createCalculatePathLengthMenuItem();
|
||||
add(calculatePathLength);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.modeleditor.application.menus.menubar;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
import javax.swing.JMenuBar;
|
||||
|
||||
/**
|
||||
* The plant overview's main menu bar.
|
||||
*/
|
||||
public class ApplicationMenuBar
|
||||
extends
|
||||
JMenuBar {
|
||||
|
||||
private final FileMenu menuFile;
|
||||
private final EditMenu menuEdit;
|
||||
private final ActionsMenu menuActions;
|
||||
private final ViewMenu menuView;
|
||||
private final HelpMenu menuHelp;
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*
|
||||
* @param menuFile The "File" menu.
|
||||
* @param menuEdit The "Edit" menu.
|
||||
* @param menuActions The "Actions" menu.
|
||||
* @param menuView The "View" menu.
|
||||
* @param menuHelp The "Help menu.
|
||||
*/
|
||||
@Inject
|
||||
@SuppressWarnings("this-escape")
|
||||
public ApplicationMenuBar(
|
||||
FileMenu menuFile,
|
||||
EditMenu menuEdit,
|
||||
ActionsMenu menuActions,
|
||||
ViewMenu menuView,
|
||||
HelpMenu menuHelp
|
||||
) {
|
||||
requireNonNull(menuFile, "menuFile");
|
||||
requireNonNull(menuEdit, "menuEdit");
|
||||
requireNonNull(menuActions, "menuActions");
|
||||
requireNonNull(menuView, "menuView");
|
||||
requireNonNull(menuHelp, "menuHelp");
|
||||
|
||||
this.menuFile = menuFile;
|
||||
add(menuFile);
|
||||
|
||||
this.menuEdit = menuEdit;
|
||||
add(menuEdit);
|
||||
|
||||
this.menuActions = menuActions;
|
||||
add(menuActions);
|
||||
|
||||
this.menuView = menuView;
|
||||
add(menuView);
|
||||
|
||||
this.menuHelp = menuHelp;
|
||||
add(menuHelp);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.modeleditor.application.menus.menubar;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
import javax.swing.JMenu;
|
||||
import org.opentcs.modeleditor.application.action.ViewActionMap;
|
||||
import org.opentcs.modeleditor.util.I18nPlantOverviewModeling;
|
||||
import org.opentcs.thirdparty.guing.common.jhotdraw.application.action.edit.DeleteAction;
|
||||
import org.opentcs.thirdparty.guing.common.jhotdraw.application.action.edit.SelectAllAction;
|
||||
import org.opentcs.thirdparty.guing.common.jhotdraw.application.action.edit.UndoRedoManager;
|
||||
import org.opentcs.thirdparty.guing.common.jhotdraw.util.ResourceBundleUtil;
|
||||
import org.opentcs.thirdparty.modeleditor.jhotdraw.application.action.edit.ClearSelectionAction;
|
||||
import org.opentcs.thirdparty.modeleditor.jhotdraw.application.action.edit.CopyAction;
|
||||
import org.opentcs.thirdparty.modeleditor.jhotdraw.application.action.edit.CutAction;
|
||||
import org.opentcs.thirdparty.modeleditor.jhotdraw.application.action.edit.DuplicateAction;
|
||||
import org.opentcs.thirdparty.modeleditor.jhotdraw.application.action.edit.PasteAction;
|
||||
|
||||
/**
|
||||
* The application's "Edit" menu.
|
||||
*/
|
||||
public class EditMenu
|
||||
extends
|
||||
JMenu {
|
||||
|
||||
// private final JMenuItem menuItemCopy;
|
||||
// private final JMenuItem menuItemCut;
|
||||
// private final JMenuItem menuItemDuplicate;
|
||||
// private final JMenuItem menuItemPaste;
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*
|
||||
* @param actionMap The application's action map.
|
||||
*/
|
||||
@Inject
|
||||
@SuppressWarnings("this-escape")
|
||||
public EditMenu(ViewActionMap actionMap) {
|
||||
requireNonNull(actionMap, "actionMap");
|
||||
|
||||
final ResourceBundleUtil labels
|
||||
= ResourceBundleUtil.getBundle(I18nPlantOverviewModeling.MENU_PATH);
|
||||
|
||||
this.setText(labels.getString("editMenu.text"));
|
||||
this.setToolTipText(labels.getString("editMenu.tooltipText"));
|
||||
this.setMnemonic('E');
|
||||
|
||||
// Undo, Redo
|
||||
add(actionMap.get(UndoRedoManager.UNDO_ACTION_ID));
|
||||
add(actionMap.get(UndoRedoManager.REDO_ACTION_ID));
|
||||
addSeparator();
|
||||
// Cut, Copy, Paste, Duplicate
|
||||
// menuItemCut = menuEdit.add(actionMap.get(CutAction.ID));
|
||||
// menuItemCopy = menuEdit.add(actionMap.get(CopyAction.ID));
|
||||
// menuItemPaste = menuEdit.add(actionMap.get(PasteAction.ID));
|
||||
// menuItemDuplicate = menuEdit.add(actionMap.get(DuplicateAction.ID));
|
||||
// Delete
|
||||
add(actionMap.get(DeleteAction.ID));
|
||||
add(actionMap.get(CopyAction.ID));
|
||||
add(actionMap.get(PasteAction.ID));
|
||||
add(actionMap.get(DuplicateAction.ID));
|
||||
add(actionMap.get(CutAction.ID));
|
||||
addSeparator();
|
||||
// Select all, Clear selection
|
||||
add(actionMap.get(SelectAllAction.ID));
|
||||
add(actionMap.get(ClearSelectionAction.ID));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.modeleditor.application.menus.menubar;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
import java.util.Set;
|
||||
import javax.swing.JMenu;
|
||||
import javax.swing.JMenuItem;
|
||||
import org.opentcs.components.plantoverview.PlantModelExporter;
|
||||
import org.opentcs.guing.common.application.GuiManager;
|
||||
import org.opentcs.modeleditor.application.action.file.ExportPlantModelAction;
|
||||
import org.opentcs.modeleditor.util.I18nPlantOverviewModeling;
|
||||
import org.opentcs.thirdparty.guing.common.jhotdraw.util.ResourceBundleUtil;
|
||||
|
||||
/**
|
||||
*/
|
||||
public class FileExportMenu
|
||||
extends
|
||||
JMenu {
|
||||
|
||||
private static final ResourceBundleUtil LABELS
|
||||
= ResourceBundleUtil.getBundle(I18nPlantOverviewModeling.MENU_PATH);
|
||||
|
||||
@Inject
|
||||
@SuppressWarnings("this-escape")
|
||||
public FileExportMenu(
|
||||
Set<PlantModelExporter> exporters,
|
||||
GuiManager guiManager
|
||||
) {
|
||||
super(LABELS.getString("fileExportMenu.text"));
|
||||
requireNonNull(exporters, "exporters");
|
||||
requireNonNull(guiManager, "guiManager");
|
||||
|
||||
for (PlantModelExporter exporter : exporters) {
|
||||
add(new JMenuItem(new ExportPlantModelAction(exporter, guiManager)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.modeleditor.application.menus.menubar;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
import java.util.Set;
|
||||
import javax.swing.JMenu;
|
||||
import javax.swing.JMenuItem;
|
||||
import org.opentcs.components.plantoverview.PlantModelImporter;
|
||||
import org.opentcs.guing.common.application.GuiManager;
|
||||
import org.opentcs.modeleditor.application.action.file.ImportPlantModelAction;
|
||||
import org.opentcs.modeleditor.util.I18nPlantOverviewModeling;
|
||||
import org.opentcs.thirdparty.guing.common.jhotdraw.util.ResourceBundleUtil;
|
||||
|
||||
/**
|
||||
*/
|
||||
public class FileImportMenu
|
||||
extends
|
||||
JMenu {
|
||||
|
||||
private static final ResourceBundleUtil LABELS
|
||||
= ResourceBundleUtil.getBundle(I18nPlantOverviewModeling.MENU_PATH);
|
||||
|
||||
@Inject
|
||||
@SuppressWarnings("this-escape")
|
||||
public FileImportMenu(
|
||||
Set<PlantModelImporter> importers,
|
||||
GuiManager guiManager
|
||||
) {
|
||||
super(LABELS.getString("fileImportMenu.text"));
|
||||
requireNonNull(importers, "importers");
|
||||
requireNonNull(guiManager, "guiManager");
|
||||
|
||||
for (PlantModelImporter importer : importers) {
|
||||
add(new JMenuItem(new ImportPlantModelAction(importer, guiManager)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.modeleditor.application.menus.menubar;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
import javax.swing.JMenu;
|
||||
import javax.swing.JMenuItem;
|
||||
import org.opentcs.guing.common.application.action.file.ModelPropertiesAction;
|
||||
import org.opentcs.guing.common.application.action.file.SaveModelAction;
|
||||
import org.opentcs.guing.common.application.action.file.SaveModelAsAction;
|
||||
import org.opentcs.modeleditor.application.action.ViewActionMap;
|
||||
import org.opentcs.modeleditor.application.action.file.DownloadModelFromKernelAction;
|
||||
import org.opentcs.modeleditor.application.action.file.LoadModelAction;
|
||||
import org.opentcs.modeleditor.application.action.file.NewModelAction;
|
||||
import org.opentcs.modeleditor.application.action.file.UploadModelToKernelAction;
|
||||
import org.opentcs.modeleditor.util.I18nPlantOverviewModeling;
|
||||
import org.opentcs.thirdparty.guing.common.jhotdraw.util.ResourceBundleUtil;
|
||||
import org.opentcs.thirdparty.modeleditor.jhotdraw.application.action.file.CloseFileAction;
|
||||
|
||||
/**
|
||||
* The application's "File" menu.
|
||||
*/
|
||||
public class FileMenu
|
||||
extends
|
||||
JMenu {
|
||||
|
||||
/**
|
||||
* A menu item for creating a new, empty system model.
|
||||
*/
|
||||
private final JMenuItem menuItemNewModel;
|
||||
/**
|
||||
* A menu item for loading a mode into the kernel.
|
||||
*/
|
||||
private final JMenuItem menuItemLoadModel;
|
||||
/**
|
||||
* A menu item for saving the kernel's current model.
|
||||
*/
|
||||
private final JMenuItem menuItemSaveModel;
|
||||
/**
|
||||
* A menu item for saving the kernel's current model with a new name.
|
||||
*/
|
||||
private final JMenuItem menuItemSaveModelAs;
|
||||
/**
|
||||
* A menu item for retrieving the system model data from the kernel.
|
||||
*/
|
||||
private final JMenuItem menuItemDownloadModelFromKernel;
|
||||
/**
|
||||
* A menu item for transferring the system model data to the kernel.
|
||||
*/
|
||||
private final JMenuItem menuItemUploadModelToKernel;
|
||||
/**
|
||||
* A menu item for showing the current model's properties.
|
||||
*/
|
||||
private final JMenuItem menuItemModelProperties;
|
||||
/**
|
||||
* A menu item for closing the application.
|
||||
*/
|
||||
private final JMenuItem menuItemClose;
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*
|
||||
* @param actionMap The application's action map.
|
||||
* @param menuImport The sub-menu for the selectable plant model importers.
|
||||
* @param menuExport The sub-menu for the selectable plant model exporters.
|
||||
*/
|
||||
@Inject
|
||||
@SuppressWarnings("this-escape")
|
||||
public FileMenu(
|
||||
ViewActionMap actionMap,
|
||||
FileImportMenu menuImport,
|
||||
FileExportMenu menuExport
|
||||
) {
|
||||
requireNonNull(actionMap, "actionMap");
|
||||
requireNonNull(menuImport, "menuImport");
|
||||
requireNonNull(menuExport, "menuExport");
|
||||
|
||||
final ResourceBundleUtil labels
|
||||
= ResourceBundleUtil.getBundle(I18nPlantOverviewModeling.MENU_PATH);
|
||||
|
||||
this.setText(labels.getString("fileMenu.text"));
|
||||
this.setToolTipText(labels.getString("fileMenu.tooltipText"));
|
||||
this.setMnemonic('F');
|
||||
|
||||
// Menu item File -> New Model
|
||||
menuItemNewModel = new JMenuItem(actionMap.get(NewModelAction.ID));
|
||||
add(menuItemNewModel);
|
||||
|
||||
// Menu item File -> Load Model
|
||||
menuItemLoadModel = new JMenuItem(actionMap.get(LoadModelAction.ID));
|
||||
add(menuItemLoadModel);
|
||||
|
||||
// Menu item File -> Save Model
|
||||
menuItemSaveModel = new JMenuItem(actionMap.get(SaveModelAction.ID));
|
||||
add(menuItemSaveModel);
|
||||
|
||||
// Menu item File -> Save Model As
|
||||
menuItemSaveModelAs = new JMenuItem(actionMap.get(SaveModelAsAction.ID));
|
||||
add(menuItemSaveModelAs);
|
||||
|
||||
addSeparator();
|
||||
|
||||
add(menuImport);
|
||||
add(menuExport);
|
||||
|
||||
addSeparator();
|
||||
|
||||
// Load model from kernel
|
||||
menuItemDownloadModelFromKernel
|
||||
= new JMenuItem(actionMap.get(DownloadModelFromKernelAction.ID));
|
||||
add(menuItemDownloadModelFromKernel);
|
||||
|
||||
// Persist model in kernel
|
||||
menuItemUploadModelToKernel = new JMenuItem(actionMap.get(UploadModelToKernelAction.ID));
|
||||
add(menuItemUploadModelToKernel);
|
||||
|
||||
addSeparator();
|
||||
|
||||
menuItemModelProperties = new JMenuItem(actionMap.get(ModelPropertiesAction.ID));
|
||||
add(menuItemModelProperties);
|
||||
|
||||
addSeparator();
|
||||
|
||||
// Menu item File -> Close
|
||||
menuItemClose = new JMenuItem(actionMap.get(CloseFileAction.ID));
|
||||
add(menuItemClose);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.modeleditor.application.menus.menubar;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
import javax.swing.JMenu;
|
||||
import javax.swing.JMenuItem;
|
||||
import org.opentcs.modeleditor.application.action.ViewActionMap;
|
||||
import org.opentcs.modeleditor.application.action.app.AboutAction;
|
||||
import org.opentcs.modeleditor.util.I18nPlantOverviewModeling;
|
||||
import org.opentcs.thirdparty.guing.common.jhotdraw.util.ResourceBundleUtil;
|
||||
|
||||
/**
|
||||
* The application's "Help" menu.
|
||||
*/
|
||||
public class HelpMenu
|
||||
extends
|
||||
JMenu {
|
||||
|
||||
/**
|
||||
* A menu item for showing the application's "about" panel.
|
||||
*/
|
||||
private final JMenuItem menuItemAbout;
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*
|
||||
* @param actionMap The application's action map.
|
||||
*/
|
||||
@Inject
|
||||
@SuppressWarnings("this-escape")
|
||||
public HelpMenu(ViewActionMap actionMap) {
|
||||
requireNonNull(actionMap, "actionMap");
|
||||
|
||||
final ResourceBundleUtil labels
|
||||
= ResourceBundleUtil.getBundle(I18nPlantOverviewModeling.MENU_PATH);
|
||||
|
||||
this.setText(labels.getString("helpMenu.text"));
|
||||
this.setToolTipText(labels.getString("helpMenu.tooltipText"));
|
||||
this.setMnemonic('?');
|
||||
|
||||
menuItemAbout = add(actionMap.get(AboutAction.ID));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.modeleditor.application.menus.menubar;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.swing.Action;
|
||||
import javax.swing.JMenu;
|
||||
import javax.swing.JMenuItem;
|
||||
import javax.swing.JToolBar;
|
||||
import org.jhotdraw.app.action.window.ToggleVisibleAction;
|
||||
import org.opentcs.guing.common.application.OperationMode;
|
||||
import org.opentcs.guing.common.application.menus.menubar.ViewPluginPanelsMenu;
|
||||
import org.opentcs.modeleditor.application.action.ToolBarManager;
|
||||
import org.opentcs.modeleditor.application.action.ViewActionMap;
|
||||
import org.opentcs.modeleditor.application.action.view.AddBitmapAction;
|
||||
import org.opentcs.modeleditor.application.action.view.RestoreDockingLayoutAction;
|
||||
import org.opentcs.modeleditor.util.I18nPlantOverviewModeling;
|
||||
import org.opentcs.thirdparty.guing.common.jhotdraw.util.ResourceBundleUtil;
|
||||
|
||||
/**
|
||||
* The application's menu for view-related operations.
|
||||
*/
|
||||
public class ViewMenu
|
||||
extends
|
||||
JMenu {
|
||||
|
||||
/**
|
||||
* The toolbar manager.
|
||||
*/
|
||||
private final ToolBarManager toolBarManager;
|
||||
/**
|
||||
* A menu item for setting a bitmap for the current drawing view.
|
||||
*/
|
||||
private final JMenuItem menuAddBitmap;
|
||||
/**
|
||||
* A menu for manipulating the application's tool bars.
|
||||
*/
|
||||
private final ViewToolBarsMenu menuViewToolBars;
|
||||
/**
|
||||
* A menu for showing/hiding plugin panels.
|
||||
*/
|
||||
private final ViewPluginPanelsMenu menuPluginPanels;
|
||||
/**
|
||||
* A menu item for restoring the default GUI layout.
|
||||
*/
|
||||
private final JMenuItem menuItemRestoreDockingLayout;
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*
|
||||
* @param actionMap The application's action map.
|
||||
* @param toolBarManager The toolbar manager.
|
||||
* @param menuPluginPanels A menu for showing/hiding plugin panels.
|
||||
*/
|
||||
@Inject
|
||||
@SuppressWarnings("this-escape")
|
||||
public ViewMenu(
|
||||
ViewActionMap actionMap,
|
||||
ToolBarManager toolBarManager,
|
||||
ViewPluginPanelsMenu menuPluginPanels
|
||||
) {
|
||||
requireNonNull(actionMap, "actionMap");
|
||||
this.toolBarManager = requireNonNull(toolBarManager, "toolBarManager");
|
||||
requireNonNull(menuPluginPanels, "menuPluginPanels");
|
||||
|
||||
final ResourceBundleUtil labels
|
||||
= ResourceBundleUtil.getBundle(I18nPlantOverviewModeling.MENU_PATH);
|
||||
|
||||
this.setText(labels.getString("viewMenu.text"));
|
||||
this.setToolTipText(labels.getString("viewMenu.tooltipText"));
|
||||
this.setMnemonic('V');
|
||||
|
||||
// Menu item View -> Add Background Image
|
||||
menuAddBitmap = new JMenuItem(actionMap.get(AddBitmapAction.ID));
|
||||
add(menuAddBitmap);
|
||||
|
||||
addSeparator();
|
||||
|
||||
List<Action> viewActions = createToolBarActions();
|
||||
if (!viewActions.isEmpty()) {
|
||||
menuViewToolBars = new ViewToolBarsMenu(viewActions);
|
||||
add(menuViewToolBars);
|
||||
}
|
||||
else {
|
||||
menuViewToolBars = null;
|
||||
}
|
||||
|
||||
// Menu item View -> Plugins
|
||||
this.menuPluginPanels = menuPluginPanels;
|
||||
menuPluginPanels.setOperationMode(OperationMode.MODELLING);
|
||||
add(menuPluginPanels);
|
||||
|
||||
// Menu item View -> Restore docking layout
|
||||
menuItemRestoreDockingLayout = new JMenuItem(actionMap.get(RestoreDockingLayoutAction.ID));
|
||||
menuItemRestoreDockingLayout.setText(
|
||||
labels.getString("viewMenu.menuItem_restoreWindowArrangement.text")
|
||||
);
|
||||
add(menuItemRestoreDockingLayout);
|
||||
}
|
||||
|
||||
private List<Action> createToolBarActions() {
|
||||
List<Action> toolBarActions = new ArrayList<>();
|
||||
for (JToolBar curToolBar : toolBarManager.getToolBars()) {
|
||||
toolBarActions.add(new ToggleVisibleAction(curToolBar, curToolBar.getName()));
|
||||
}
|
||||
return toolBarActions;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.modeleditor.application.menus.menubar;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
import java.util.Collection;
|
||||
import javax.swing.Action;
|
||||
import javax.swing.JCheckBoxMenuItem;
|
||||
import javax.swing.JMenu;
|
||||
import org.opentcs.modeleditor.util.I18nPlantOverviewModeling;
|
||||
import org.opentcs.thirdparty.guing.common.jhotdraw.util.ResourceBundleUtil;
|
||||
|
||||
/**
|
||||
*/
|
||||
public class ViewToolBarsMenu
|
||||
extends
|
||||
JMenu {
|
||||
|
||||
private static final ResourceBundleUtil LABELS_MENU
|
||||
= ResourceBundleUtil.getBundle(I18nPlantOverviewModeling.MENU_PATH);
|
||||
private static final ResourceBundleUtil LABELS_TOOLBAR
|
||||
= ResourceBundleUtil.getBundle(I18nPlantOverviewModeling.TOOLBAR_PATH);
|
||||
|
||||
@SuppressWarnings("this-escape")
|
||||
public ViewToolBarsMenu(Collection<Action> viewActions) {
|
||||
super(LABELS_MENU.getString("viewToolBarsMenu.text"));
|
||||
requireNonNull(viewActions, "viewActions");
|
||||
|
||||
JCheckBoxMenuItem checkBoxMenuItem;
|
||||
for (Action a : viewActions) {
|
||||
checkBoxMenuItem = new JCheckBoxMenuItem(a);
|
||||
add(checkBoxMenuItem);
|
||||
|
||||
if (checkBoxMenuItem.getText().equals(
|
||||
LABELS_TOOLBAR.getString("toolBarManager.toolbar_drawing.title")
|
||||
)) {
|
||||
checkBoxMenuItem.setEnabled(false); // "Draw"-Toolbar musn't be disabled.
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.modeleditor.application.toolbar;
|
||||
|
||||
import org.jhotdraw.draw.ConnectionFigure;
|
||||
import org.jhotdraw.draw.Figure;
|
||||
import org.opentcs.thirdparty.modeleditor.jhotdraw.application.toolbar.OpenTCSConnectionTool;
|
||||
|
||||
/**
|
||||
* A factory for tools concerned with the creation of figures/model elements.
|
||||
*/
|
||||
public interface CreationToolFactory {
|
||||
|
||||
OpenTCSCreationTool createCreationTool(Figure prototype);
|
||||
|
||||
OpenTCSConnectionTool createConnectionTool(ConnectionFigure prototype);
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.modeleditor.application.toolbar;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
import com.google.inject.assistedinject.Assisted;
|
||||
import jakarta.inject.Inject;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import javax.swing.Action;
|
||||
import javax.swing.JMenuItem;
|
||||
import org.jhotdraw.draw.tool.DragTracker;
|
||||
import org.jhotdraw.draw.tool.SelectAreaTracker;
|
||||
import org.opentcs.guing.common.application.ApplicationState;
|
||||
import org.opentcs.modeleditor.application.menus.MenuFactory;
|
||||
import org.opentcs.thirdparty.guing.common.jhotdraw.application.toolbar.AbstractMultipleSelectionTool;
|
||||
|
||||
/**
|
||||
* The default selection tool.
|
||||
*/
|
||||
public class MultipleSelectionTool
|
||||
extends
|
||||
AbstractMultipleSelectionTool {
|
||||
|
||||
/**
|
||||
* A factory for menu items.
|
||||
*/
|
||||
private final MenuFactory menuFactory;
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*
|
||||
* @param appState Stores the application's current state.
|
||||
* @param menuFactory A factory for menu items in popup menus created by this tool.
|
||||
* @param selectAreaTracker The tracker to be used for area selections in the drawing.
|
||||
* @param dragTracker The tracker to be used for dragging figures.
|
||||
* @param drawingActions Drawing-related actions for the popup menus created by this tool.
|
||||
* @param selectionActions Selection-related actions for the popup menus created by this tool.
|
||||
*/
|
||||
@Inject
|
||||
public MultipleSelectionTool(
|
||||
ApplicationState appState,
|
||||
MenuFactory menuFactory,
|
||||
SelectAreaTracker selectAreaTracker,
|
||||
DragTracker dragTracker,
|
||||
@Assisted("drawingActions")
|
||||
Collection<Action> drawingActions,
|
||||
@Assisted("selectionActions")
|
||||
Collection<Action> selectionActions
|
||||
) {
|
||||
super(appState, selectAreaTracker, dragTracker, drawingActions, selectionActions);
|
||||
this.menuFactory = requireNonNull(menuFactory, "menuFactory");
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<JMenuItem> customPopupMenuItems() {
|
||||
// Points and Locations get two additional entries
|
||||
List<JMenuItem> actions = new ArrayList<>();
|
||||
actions.add(menuFactory.createModelToLayoutMenuItem(false));
|
||||
actions.add(menuFactory.createLayoutToModelMenuItem(false));
|
||||
return actions;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.modeleditor.application.toolbar;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
import static org.opentcs.modeleditor.util.I18nPlantOverviewModeling.TOOLBAR_PATH;
|
||||
|
||||
import com.google.inject.assistedinject.Assisted;
|
||||
import jakarta.inject.Inject;
|
||||
import java.awt.event.MouseEvent;
|
||||
import javax.swing.JOptionPane;
|
||||
import org.jhotdraw.draw.Figure;
|
||||
import org.jhotdraw.draw.tool.CreationTool;
|
||||
import org.opentcs.guing.common.components.drawing.figures.LabeledFigure;
|
||||
import org.opentcs.guing.common.components.drawing.figures.ModelBasedFigure;
|
||||
import org.opentcs.modeleditor.components.layer.ActiveLayerProvider;
|
||||
import org.opentcs.thirdparty.guing.common.jhotdraw.util.ResourceBundleUtil;
|
||||
|
||||
/**
|
||||
* A custom tool used to create {@code PointFigure}s and {@code LocationFigure}s.
|
||||
*/
|
||||
public class OpenTCSCreationTool
|
||||
extends
|
||||
CreationTool {
|
||||
|
||||
/**
|
||||
* The resource bundle to use.
|
||||
*/
|
||||
private static final ResourceBundleUtil BUNDLE = ResourceBundleUtil.getBundle(TOOLBAR_PATH);
|
||||
/**
|
||||
* Provides the currently active layer.
|
||||
*/
|
||||
private final ActiveLayerProvider activeLayerProvider;
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*
|
||||
* @param activeLayerProvider Provides the currently active layer.
|
||||
* @param prototype The figure to be used as a prototype.
|
||||
*/
|
||||
@Inject
|
||||
public OpenTCSCreationTool(
|
||||
ActiveLayerProvider activeLayerProvider,
|
||||
@Assisted
|
||||
Figure prototype
|
||||
) {
|
||||
super(prototype);
|
||||
this.activeLayerProvider = requireNonNull(activeLayerProvider, "activeLayerProvider");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mousePressed(MouseEvent evt) {
|
||||
if (!activeLayerProvider.getActiveLayer().getLayer().isVisible()
|
||||
|| !activeLayerProvider.getActiveLayer().getLayerGroup().isVisible()) {
|
||||
JOptionPane.showMessageDialog(
|
||||
evt.getComponent(),
|
||||
BUNDLE.getString("openTcsCreationTool.optionPane_activeLayerNotVisible.message"),
|
||||
BUNDLE.getString("openTcsCreationTool.optionPane_activeLayerNotVisible.title"),
|
||||
JOptionPane.INFORMATION_MESSAGE
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
super.mousePressed(evt);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Figure createFigure() {
|
||||
Figure figure = super.createFigure();
|
||||
|
||||
if (figure instanceof ModelBasedFigure) {
|
||||
((ModelBasedFigure) figure).getModel()
|
||||
.getPropertyLayerWrapper().setValue(activeLayerProvider.getActiveLayer());
|
||||
}
|
||||
else if (figure instanceof LabeledFigure) {
|
||||
((LabeledFigure) figure).getPresentationFigure().getModel()
|
||||
.getPropertyLayerWrapper().setValue(activeLayerProvider.getActiveLayer());
|
||||
}
|
||||
|
||||
return figure;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.modeleditor.application.toolbar;
|
||||
|
||||
import com.google.inject.assistedinject.Assisted;
|
||||
import java.util.Collection;
|
||||
import javax.swing.Action;
|
||||
|
||||
/**
|
||||
*/
|
||||
public interface SelectionToolFactory {
|
||||
|
||||
MultipleSelectionTool createMultipleSelectionTool(
|
||||
@Assisted("drawingActions")
|
||||
Collection<Action> drawingActions,
|
||||
@Assisted("selectionActions")
|
||||
Collection<Action> selectionActions
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<Form version="1.3" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
|
||||
<AuxValues>
|
||||
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/>
|
||||
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
|
||||
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
|
||||
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
|
||||
<AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,0,-93,0,0,0,-102"/>
|
||||
</AuxValues>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JCheckBox" name="allTypesCheckBox">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="i18n/org/opentcs/plantoverview/modeling/miscellaneous.properties" key="pathTypeSelection.allTypes_label.text" replaceFormat="java.util.ResourceBundle.getBundle("{bundleNameSlashes}").getString("{key}")"/>
|
||||
</Property>
|
||||
<Property name="horizontalAlignment" type="int" value="11"/>
|
||||
<Property name="horizontalTextPosition" type="int" value="10"/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="allTypesCheckBoxActionPerformed"/>
|
||||
</Events>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="0" gridWidth="1" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="13" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JCheckBox" name="directCheckBox">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value="Direct:"/>
|
||||
<Property name="horizontalAlignment" type="int" value="11"/>
|
||||
<Property name="horizontalTextPosition" type="int" value="10"/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="directCheckBoxActionPerformed"/>
|
||||
</Events>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="1" gridWidth="1" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="3" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="13" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JCheckBox" name="elbowCheckBox">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value="Elbow:"/>
|
||||
<Property name="horizontalAlignment" type="int" value="11"/>
|
||||
<Property name="horizontalTextPosition" type="int" value="10"/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="elbowCheckBoxActionPerformed"/>
|
||||
</Events>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="2" gridWidth="1" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="3" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="13" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JCheckBox" name="slantedCheckBox">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value="Slanted:"/>
|
||||
<Property name="horizontalAlignment" type="int" value="11"/>
|
||||
<Property name="horizontalTextPosition" type="int" value="10"/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="slantedCheckBoxActionPerformed"/>
|
||||
</Events>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="3" gridWidth="1" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="3" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="13" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JCheckBox" name="polypathCheckBox">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value="Polypath:"/>
|
||||
<Property name="horizontalAlignment" type="int" value="11"/>
|
||||
<Property name="horizontalTextPosition" type="int" value="10"/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="polypathCheckBoxActionPerformed"/>
|
||||
</Events>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="4" gridWidth="1" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="3" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="13" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JCheckBox" name="bezierCheckBox">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value="Bezier:"/>
|
||||
<Property name="horizontalAlignment" type="int" value="11"/>
|
||||
<Property name="horizontalTextPosition" type="int" value="10"/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="bezierCheckBoxActionPerformed"/>
|
||||
</Events>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="5" gridWidth="1" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="3" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="13" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JCheckBox" name="bezier3CheckBox">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value="Bezier 3:"/>
|
||||
<Property name="horizontalAlignment" type="int" value="11"/>
|
||||
<Property name="horizontalTextPosition" type="int" value="10"/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="bezier3CheckBoxActionPerformed"/>
|
||||
</Events>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="6" gridWidth="1" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="3" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="13" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Form>
|
||||
@@ -0,0 +1,264 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.modeleditor.components.dialog;
|
||||
|
||||
import static org.opentcs.guing.base.model.elements.PathModel.Type.BEZIER;
|
||||
import static org.opentcs.guing.base.model.elements.PathModel.Type.BEZIER_3;
|
||||
import static org.opentcs.guing.base.model.elements.PathModel.Type.DIRECT;
|
||||
import static org.opentcs.guing.base.model.elements.PathModel.Type.ELBOW;
|
||||
import static org.opentcs.guing.base.model.elements.PathModel.Type.POLYPATH;
|
||||
import static org.opentcs.guing.base.model.elements.PathModel.Type.SLANTED;
|
||||
|
||||
import org.opentcs.guing.base.model.elements.PathModel;
|
||||
import org.opentcs.guing.common.components.dialogs.DialogContent;
|
||||
import org.opentcs.modeleditor.util.I18nPlantOverviewModeling;
|
||||
import org.opentcs.thirdparty.guing.common.jhotdraw.util.ResourceBundleUtil;
|
||||
|
||||
/**
|
||||
* A dialog content to select a set of path types.
|
||||
*/
|
||||
public class PathTypeSelectionPanel
|
||||
extends
|
||||
DialogContent {
|
||||
|
||||
/**
|
||||
* Creates new form PathTypeSelection.
|
||||
*/
|
||||
@SuppressWarnings("this-escape")
|
||||
public PathTypeSelectionPanel() {
|
||||
setDialogTitle(
|
||||
ResourceBundleUtil.getBundle(I18nPlantOverviewModeling.MISC_PATH)
|
||||
.getString("pathTypeSelection.title")
|
||||
);
|
||||
initComponents();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initFields() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if the given path type is selected.
|
||||
*
|
||||
* @param type The path type to test.
|
||||
* @return True if the path type is selected.
|
||||
*/
|
||||
public boolean isPathTypeSelected(PathModel.Type type) {
|
||||
switch (type) {
|
||||
case DIRECT:
|
||||
return directCheckBox.isSelected();
|
||||
case ELBOW:
|
||||
return elbowCheckBox.isSelected();
|
||||
case SLANTED:
|
||||
return slantedCheckBox.isSelected();
|
||||
case POLYPATH:
|
||||
return polypathCheckBox.isSelected();
|
||||
case BEZIER:
|
||||
return bezierCheckBox.isSelected();
|
||||
case BEZIER_3:
|
||||
return bezier3CheckBox.isSelected();
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void updateAllTypesCheckBox() {
|
||||
allTypesCheckBox.setSelected(
|
||||
directCheckBox.isSelected()
|
||||
&& elbowCheckBox.isSelected()
|
||||
&& slantedCheckBox.isSelected()
|
||||
&& polypathCheckBox.isSelected()
|
||||
&& bezierCheckBox.isSelected()
|
||||
&& bezier3CheckBox.isSelected()
|
||||
);
|
||||
}
|
||||
|
||||
// FORMATTER:OFF
|
||||
// CHECKSTYLE:OFF
|
||||
/**
|
||||
* This method is called from within the constructor to
|
||||
* initialize the form.
|
||||
* WARNING: Do NOT modify this code. The content of this method is
|
||||
* always regenerated by the Form Editor.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||
private void initComponents() {
|
||||
java.awt.GridBagConstraints gridBagConstraints;
|
||||
|
||||
allTypesCheckBox = new javax.swing.JCheckBox();
|
||||
directCheckBox = new javax.swing.JCheckBox();
|
||||
elbowCheckBox = new javax.swing.JCheckBox();
|
||||
slantedCheckBox = new javax.swing.JCheckBox();
|
||||
polypathCheckBox = new javax.swing.JCheckBox();
|
||||
bezierCheckBox = new javax.swing.JCheckBox();
|
||||
bezier3CheckBox = new javax.swing.JCheckBox();
|
||||
|
||||
setLayout(new java.awt.GridBagLayout());
|
||||
|
||||
java.util.ResourceBundle bundle = java.util.ResourceBundle.getBundle("i18n/org/opentcs/plantoverview/modeling/miscellaneous"); // NOI18N
|
||||
allTypesCheckBox.setText(bundle.getString("pathTypeSelection.allTypes_label.text")); // NOI18N
|
||||
allTypesCheckBox.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING);
|
||||
allTypesCheckBox.setHorizontalTextPosition(javax.swing.SwingConstants.LEADING);
|
||||
allTypesCheckBox.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
allTypesCheckBoxActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 0;
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
|
||||
add(allTypesCheckBox, gridBagConstraints);
|
||||
|
||||
directCheckBox.setText("Direct:");
|
||||
directCheckBox.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING);
|
||||
directCheckBox.setHorizontalTextPosition(javax.swing.SwingConstants.LEADING);
|
||||
directCheckBox.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
directCheckBoxActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 1;
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
|
||||
gridBagConstraints.insets = new java.awt.Insets(3, 0, 0, 0);
|
||||
add(directCheckBox, gridBagConstraints);
|
||||
|
||||
elbowCheckBox.setText("Elbow:");
|
||||
elbowCheckBox.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING);
|
||||
elbowCheckBox.setHorizontalTextPosition(javax.swing.SwingConstants.LEADING);
|
||||
elbowCheckBox.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
elbowCheckBoxActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 2;
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
|
||||
gridBagConstraints.insets = new java.awt.Insets(3, 0, 0, 0);
|
||||
add(elbowCheckBox, gridBagConstraints);
|
||||
|
||||
slantedCheckBox.setText("Slanted:");
|
||||
slantedCheckBox.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING);
|
||||
slantedCheckBox.setHorizontalTextPosition(javax.swing.SwingConstants.LEADING);
|
||||
slantedCheckBox.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
slantedCheckBoxActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 3;
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
|
||||
gridBagConstraints.insets = new java.awt.Insets(3, 0, 0, 0);
|
||||
add(slantedCheckBox, gridBagConstraints);
|
||||
|
||||
polypathCheckBox.setText("Polypath:");
|
||||
polypathCheckBox.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING);
|
||||
polypathCheckBox.setHorizontalTextPosition(javax.swing.SwingConstants.LEADING);
|
||||
polypathCheckBox.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
polypathCheckBoxActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 4;
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
|
||||
gridBagConstraints.insets = new java.awt.Insets(3, 0, 0, 0);
|
||||
add(polypathCheckBox, gridBagConstraints);
|
||||
|
||||
bezierCheckBox.setText("Bezier:");
|
||||
bezierCheckBox.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING);
|
||||
bezierCheckBox.setHorizontalTextPosition(javax.swing.SwingConstants.LEADING);
|
||||
bezierCheckBox.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
bezierCheckBoxActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 5;
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
|
||||
gridBagConstraints.insets = new java.awt.Insets(3, 0, 0, 0);
|
||||
add(bezierCheckBox, gridBagConstraints);
|
||||
|
||||
bezier3CheckBox.setText("Bezier 3:");
|
||||
bezier3CheckBox.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING);
|
||||
bezier3CheckBox.setHorizontalTextPosition(javax.swing.SwingConstants.LEADING);
|
||||
bezier3CheckBox.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
bezier3CheckBoxActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 6;
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
|
||||
gridBagConstraints.insets = new java.awt.Insets(3, 0, 0, 0);
|
||||
add(bezier3CheckBox, gridBagConstraints);
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
// CHECKSTYLE:ON
|
||||
// FORMATTER:ON
|
||||
|
||||
private void allTypesCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_allTypesCheckBoxActionPerformed
|
||||
directCheckBox.setSelected(allTypesCheckBox.isSelected());
|
||||
elbowCheckBox.setSelected(allTypesCheckBox.isSelected());
|
||||
slantedCheckBox.setSelected(allTypesCheckBox.isSelected());
|
||||
polypathCheckBox.setSelected(allTypesCheckBox.isSelected());
|
||||
bezierCheckBox.setSelected(allTypesCheckBox.isSelected());
|
||||
bezier3CheckBox.setSelected(allTypesCheckBox.isSelected());
|
||||
}//GEN-LAST:event_allTypesCheckBoxActionPerformed
|
||||
|
||||
private void directCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_directCheckBoxActionPerformed
|
||||
updateAllTypesCheckBox();
|
||||
}//GEN-LAST:event_directCheckBoxActionPerformed
|
||||
|
||||
private void elbowCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_elbowCheckBoxActionPerformed
|
||||
updateAllTypesCheckBox();
|
||||
}//GEN-LAST:event_elbowCheckBoxActionPerformed
|
||||
|
||||
private void slantedCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_slantedCheckBoxActionPerformed
|
||||
updateAllTypesCheckBox();
|
||||
}//GEN-LAST:event_slantedCheckBoxActionPerformed
|
||||
|
||||
private void polypathCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_polypathCheckBoxActionPerformed
|
||||
updateAllTypesCheckBox();
|
||||
}//GEN-LAST:event_polypathCheckBoxActionPerformed
|
||||
|
||||
private void bezierCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bezierCheckBoxActionPerformed
|
||||
updateAllTypesCheckBox();
|
||||
}//GEN-LAST:event_bezierCheckBoxActionPerformed
|
||||
|
||||
private void bezier3CheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bezier3CheckBoxActionPerformed
|
||||
updateAllTypesCheckBox();
|
||||
}//GEN-LAST:event_bezier3CheckBoxActionPerformed
|
||||
|
||||
// FORMATTER:OFF
|
||||
// CHECKSTYLE:OFF
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private javax.swing.JCheckBox allTypesCheckBox;
|
||||
private javax.swing.JCheckBox bezier3CheckBox;
|
||||
private javax.swing.JCheckBox bezierCheckBox;
|
||||
private javax.swing.JCheckBox directCheckBox;
|
||||
private javax.swing.JCheckBox elbowCheckBox;
|
||||
private javax.swing.JCheckBox polypathCheckBox;
|
||||
private javax.swing.JCheckBox slantedCheckBox;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
// CHECKSTYLE:ON
|
||||
// FORMATTER:ON
|
||||
}
|
||||
@@ -0,0 +1,196 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.modeleditor.components.dockable;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
import bibliothek.gui.dock.common.CControl;
|
||||
import bibliothek.gui.dock.common.CGrid;
|
||||
import bibliothek.gui.dock.common.DefaultSingleCDockable;
|
||||
import bibliothek.gui.dock.common.group.CGroupBehavior;
|
||||
import jakarta.inject.Inject;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JFrame;
|
||||
import org.opentcs.customizations.plantoverview.ApplicationFrame;
|
||||
import org.opentcs.guing.common.components.dockable.AbstractDockingManager;
|
||||
import org.opentcs.guing.common.components.dockable.CStack;
|
||||
import org.opentcs.guing.common.components.properties.SelectionPropertiesComponent;
|
||||
import org.opentcs.guing.common.components.tree.BlocksTreeViewManager;
|
||||
import org.opentcs.guing.common.components.tree.ComponentsTreeViewManager;
|
||||
import org.opentcs.modeleditor.components.layer.LayerGroupsPanel;
|
||||
import org.opentcs.modeleditor.components.layer.LayersPanel;
|
||||
import org.opentcs.modeleditor.util.I18nPlantOverviewModeling;
|
||||
import org.opentcs.thirdparty.guing.common.jhotdraw.util.ResourceBundleUtil;
|
||||
|
||||
/**
|
||||
* Utility class for working with dockables.
|
||||
*/
|
||||
public class DockingManagerModeling
|
||||
extends
|
||||
AbstractDockingManager {
|
||||
|
||||
/**
|
||||
* ID of the tab pane that contains the course, transport orders and order sequences.
|
||||
*/
|
||||
public static final String COURSE_TAB_PANE_ID = "course_tab_pane";
|
||||
/**
|
||||
* ID of the tab pane that contains the components, blocks and groups.
|
||||
*/
|
||||
private static final String TREE_TAB_PANE_ID = "tree_tab_pane";
|
||||
private static final String LAYER_TAB_PANE_ID = "layer_tab_pane";
|
||||
private static final String COMPONENTS_ID = "comp_dock";
|
||||
private static final String BLOCKS_ID = "block_dock";
|
||||
private static final String PROPERTIES_ID = "properties_id";
|
||||
private static final String LAYERS_ID = "layers_id";
|
||||
private static final String LAYER_GROUPS_ID = "layer_groups_id";
|
||||
/**
|
||||
* The tree view manager for components.
|
||||
*/
|
||||
private final ComponentsTreeViewManager componentsTreeViewManager;
|
||||
/**
|
||||
* The tree view manager for blocks.
|
||||
*/
|
||||
private final BlocksTreeViewManager blocksTreeViewManager;
|
||||
/**
|
||||
* The panel displaying the properties of the currently selected driving course components.
|
||||
*/
|
||||
private final SelectionPropertiesComponent selectionPropertiesComponent;
|
||||
/**
|
||||
* The panel displaying the layers in the plant model.
|
||||
*/
|
||||
private final LayersPanel layersPanel;
|
||||
/**
|
||||
* The panel displaying the layer groups in the plant model.
|
||||
*/
|
||||
private final LayerGroupsPanel layerGroupsPanel;
|
||||
/**
|
||||
* Tab pane that contains the components, blocks and groups.
|
||||
*/
|
||||
private CStack treeTabPane;
|
||||
/**
|
||||
* Tab pane that contains the course, transport orders and order sequences.
|
||||
*/
|
||||
private CStack courseTabPane;
|
||||
/**
|
||||
* Tab pane that contains layers and layer groups.
|
||||
*/
|
||||
private CStack layerTabPane;
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*
|
||||
* @param applicationFrame The application's main frame.
|
||||
* @param componentsTreeViewManager The tree view manager for components.
|
||||
* @param blocksTreeViewManager The tree view manager for blocks.
|
||||
* @param selectionPropertiesComponent The panel displaying the properties of the currently
|
||||
* selected driving course components.
|
||||
* @param layersPanel The panel displaying the layers in the plant model.
|
||||
* @param layerGroupsPanel The panel displaying the layer groups in the plant model.
|
||||
*/
|
||||
@Inject
|
||||
public DockingManagerModeling(@ApplicationFrame
|
||||
JFrame applicationFrame,
|
||||
ComponentsTreeViewManager componentsTreeViewManager,
|
||||
BlocksTreeViewManager blocksTreeViewManager,
|
||||
SelectionPropertiesComponent selectionPropertiesComponent,
|
||||
LayersPanel layersPanel,
|
||||
LayerGroupsPanel layerGroupsPanel
|
||||
) {
|
||||
super(new CControl(applicationFrame));
|
||||
this.componentsTreeViewManager = requireNonNull(
|
||||
componentsTreeViewManager,
|
||||
"componentsTreeViewManager"
|
||||
);
|
||||
this.blocksTreeViewManager = requireNonNull(blocksTreeViewManager, "blocksTreeViewManager");
|
||||
this.selectionPropertiesComponent = requireNonNull(
|
||||
selectionPropertiesComponent,
|
||||
"selectionPropertiesComponent"
|
||||
);
|
||||
this.layersPanel = requireNonNull(layersPanel, "layersPanel");
|
||||
this.layerGroupsPanel = requireNonNull(layerGroupsPanel, "layerGroupsPanel");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
removeDockable(BLOCKS_ID);
|
||||
removeDockable(COMPONENTS_ID);
|
||||
removeDockable(PROPERTIES_ID);
|
||||
removeDockable(LAYERS_ID);
|
||||
removeDockable(LAYER_GROUPS_ID);
|
||||
getCControl().removeStation(getTabPane(COURSE_TAB_PANE_ID));
|
||||
getCControl().removeStation(getTabPane(TREE_TAB_PANE_ID));
|
||||
getCControl().removeStation(getTabPane(LAYER_TAB_PANE_ID));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initializeDockables() {
|
||||
getCControl().setGroupBehavior(CGroupBehavior.TOPMOST);
|
||||
|
||||
// Disable keyboard shortcuts to avoid collisions.
|
||||
getCControl().putProperty(CControl.KEY_GOTO_NORMALIZED, null);
|
||||
getCControl().putProperty(CControl.KEY_GOTO_EXTERNALIZED, null);
|
||||
getCControl().putProperty(CControl.KEY_GOTO_MAXIMIZED, null);
|
||||
getCControl().putProperty(CControl.KEY_MAXIMIZE_CHANGE, null);
|
||||
|
||||
ResourceBundleUtil bundle
|
||||
= ResourceBundleUtil.getBundle(I18nPlantOverviewModeling.DOCKABLE_PATH);
|
||||
CGrid grid = new CGrid(getCControl());
|
||||
courseTabPane = new CStack(COURSE_TAB_PANE_ID);
|
||||
addTabPane(COURSE_TAB_PANE_ID, courseTabPane);
|
||||
treeTabPane = new CStack(TREE_TAB_PANE_ID);
|
||||
addTabPane(TREE_TAB_PANE_ID, treeTabPane);
|
||||
layerTabPane = new CStack(LAYER_TAB_PANE_ID);
|
||||
addTabPane(LAYER_TAB_PANE_ID, layerTabPane);
|
||||
DefaultSingleCDockable treeViewDock
|
||||
= createDockable(
|
||||
COMPONENTS_ID,
|
||||
bundle.getString("dockingManagerModeling.panel_components.title"),
|
||||
(JComponent) componentsTreeViewManager.getTreeView(),
|
||||
false
|
||||
);
|
||||
DefaultSingleCDockable treeBlocks
|
||||
= createDockable(
|
||||
BLOCKS_ID,
|
||||
bundle.getString("dockingManagerModeling.panel_blocks.title"),
|
||||
(JComponent) blocksTreeViewManager.getTreeView(),
|
||||
false
|
||||
);
|
||||
|
||||
grid.add(0, 0, 250, 400, treeTabPane);
|
||||
grid.add(
|
||||
0, 400, 250, 300,
|
||||
createDockable(
|
||||
PROPERTIES_ID,
|
||||
bundle.getString("dockingManagerModeling.panel_properties.title"),
|
||||
selectionPropertiesComponent,
|
||||
false
|
||||
)
|
||||
);
|
||||
DefaultSingleCDockable layersDock
|
||||
= createDockable(
|
||||
LAYERS_ID,
|
||||
bundle.getString("dockingManagerModeling.panel_layers.title"),
|
||||
layersPanel,
|
||||
false
|
||||
);
|
||||
DefaultSingleCDockable layerGroupsDock
|
||||
= createDockable(
|
||||
LAYER_GROUPS_ID,
|
||||
bundle.getString("dockingManagerModeling.panel_layerGroups.title"),
|
||||
layerGroupsPanel,
|
||||
false
|
||||
);
|
||||
grid.add(0, 700, 250, 300, layerTabPane);
|
||||
grid.add(400, 0, 1000, 500, courseTabPane);
|
||||
|
||||
getCControl().getContentArea().deploy(grid);
|
||||
|
||||
// init tab panes
|
||||
addTabTo(treeViewDock, TREE_TAB_PANE_ID, 0);
|
||||
addTabTo(treeBlocks, TREE_TAB_PANE_ID, 1);
|
||||
addTabTo(layersDock, LAYER_TAB_PANE_ID, 0);
|
||||
addTabTo(layerGroupsDock, LAYER_TAB_PANE_ID, 1);
|
||||
treeTabPane.getStation().setFrontDockable(treeViewDock.intern());
|
||||
layerTabPane.getStation().setFrontDockable(layersDock.intern());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.modeleditor.components.drawing;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import org.jhotdraw.draw.AbstractFigure;
|
||||
import org.jhotdraw.draw.Figure;
|
||||
import org.opentcs.guing.base.event.BlockChangeEvent;
|
||||
import org.opentcs.guing.base.event.BlockChangeListener;
|
||||
import org.opentcs.guing.base.model.FigureDecorationDetails;
|
||||
import org.opentcs.guing.base.model.ModelComponent;
|
||||
import org.opentcs.guing.base.model.elements.BlockModel;
|
||||
import org.opentcs.guing.common.persistence.ModelManager;
|
||||
import org.opentcs.guing.common.util.ModelComponentUtil;
|
||||
|
||||
/**
|
||||
*/
|
||||
public class BlockChangeHandler
|
||||
implements
|
||||
BlockChangeListener {
|
||||
|
||||
/**
|
||||
* The members/elements of a block mapped to the block model.
|
||||
*/
|
||||
private final Map<BlockModel, Set<FigureDecorationDetails>> blockElementsHistory
|
||||
= new HashMap<>();
|
||||
|
||||
/**
|
||||
* The manager keeping/providing the currently loaded model.
|
||||
*/
|
||||
private final ModelManager modelManager;
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*
|
||||
* @param modelManager The model manager.
|
||||
*/
|
||||
@Inject
|
||||
public BlockChangeHandler(ModelManager modelManager) {
|
||||
this.modelManager = requireNonNull(modelManager, "modelManager");
|
||||
}
|
||||
|
||||
@Override // BlockChangeListener
|
||||
public void courseElementsChanged(BlockChangeEvent e) {
|
||||
BlockModel block = (BlockModel) e.getSource();
|
||||
|
||||
// Let the block's elements know the block they are now part of.
|
||||
Set<FigureDecorationDetails> blockElements = block.getPropertyElements().getItems().stream()
|
||||
.map(elementName -> modelManager.getModel().getModelComponent(elementName))
|
||||
.filter(modelComponent -> modelComponent instanceof FigureDecorationDetails)
|
||||
.map(modelComponent -> (FigureDecorationDetails) modelComponent)
|
||||
.collect(Collectors.toSet());
|
||||
for (FigureDecorationDetails component : blockElements) {
|
||||
component.addBlockModel(block);
|
||||
}
|
||||
|
||||
// The elements that are no longer part of the block should also know this.
|
||||
Set<FigureDecorationDetails> removedBlockElements = updateBlockElementHistory(
|
||||
block,
|
||||
blockElements
|
||||
);
|
||||
for (FigureDecorationDetails component : removedBlockElements) {
|
||||
component.removeBlockModel(block);
|
||||
// Update the figure so that it no longer appears as being part of the block.
|
||||
Figure figure = modelManager.getModel().getFigure(((ModelComponent) component));
|
||||
((AbstractFigure) figure).fireFigureChanged();
|
||||
}
|
||||
|
||||
updateBlock(block);
|
||||
}
|
||||
|
||||
@Override // BlockChangeListener
|
||||
public void colorChanged(BlockChangeEvent e) {
|
||||
updateBlock((BlockModel) e.getSource());
|
||||
}
|
||||
|
||||
@Override // BlockChangeListener
|
||||
public void blockRemoved(BlockChangeEvent e) {
|
||||
BlockModel block = (BlockModel) e.getSource();
|
||||
|
||||
// Let the block's elements know they are no longer part of the block.
|
||||
Set<FigureDecorationDetails> removedBlockElements
|
||||
= updateBlockElementHistory(block, new HashSet<>());
|
||||
for (FigureDecorationDetails component : removedBlockElements) {
|
||||
component.removeBlockModel(block);
|
||||
}
|
||||
|
||||
block.removeBlockChangeListener(this);
|
||||
updateBlock(block);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remembers the given set of components as the new block elements for the given
|
||||
* block model and returns the set difference of the old and the new block elements
|
||||
* (e.g. the elements that are no longer part of the block).
|
||||
*
|
||||
* @param block The block model.
|
||||
* @param newBlockElements The new block elements.
|
||||
* @return The set difference of the old and the new block elements.
|
||||
*/
|
||||
private Set<FigureDecorationDetails> updateBlockElementHistory(
|
||||
BlockModel block,
|
||||
Set<FigureDecorationDetails> newBlockElements
|
||||
) {
|
||||
Set<FigureDecorationDetails> oldBlockElements = getBlockElements(block);
|
||||
Set<FigureDecorationDetails> removedBlockElements = new HashSet<>(oldBlockElements);
|
||||
|
||||
removedBlockElements.removeAll(newBlockElements);
|
||||
|
||||
oldBlockElements.clear();
|
||||
oldBlockElements.addAll(newBlockElements);
|
||||
|
||||
return removedBlockElements;
|
||||
}
|
||||
|
||||
private Set<FigureDecorationDetails> getBlockElements(BlockModel block) {
|
||||
return blockElementsHistory.computeIfAbsent(block, b -> new HashSet<>());
|
||||
}
|
||||
|
||||
private void updateBlock(BlockModel block) {
|
||||
for (Figure figure : ModelComponentUtil.getChildFigures(block, modelManager.getModel())) {
|
||||
((AbstractFigure) figure).fireFigureChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.modeleditor.components.drawing;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.swing.undo.AbstractUndoableEdit;
|
||||
import javax.swing.undo.CannotRedoException;
|
||||
import javax.swing.undo.CannotUndoException;
|
||||
import org.jhotdraw.draw.DrawingView;
|
||||
import org.jhotdraw.draw.Figure;
|
||||
import org.opentcs.modeleditor.util.I18nPlantOverviewModeling;
|
||||
import org.opentcs.thirdparty.guing.common.jhotdraw.util.ResourceBundleUtil;
|
||||
|
||||
/**
|
||||
* Undoes or redoes the "delete" action.
|
||||
*/
|
||||
public class DeleteEdit
|
||||
extends
|
||||
AbstractUndoableEdit {
|
||||
|
||||
/**
|
||||
* The drawing view we're working with.
|
||||
*/
|
||||
private final DrawingView drawingView;
|
||||
/**
|
||||
* The deleted figures.
|
||||
*/
|
||||
private final ArrayList<Figure> figures = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*
|
||||
* @param drawingView The drawing view the delete happened in.
|
||||
* @param figures The deleted figures.
|
||||
*/
|
||||
public DeleteEdit(DrawingView drawingView, List<Figure> figures) {
|
||||
this.drawingView = requireNonNull(drawingView, "drawingView");
|
||||
this.figures.addAll(figures);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPresentationName() {
|
||||
return ResourceBundleUtil.getBundle(I18nPlantOverviewModeling.MENU_PATH)
|
||||
.getString("deleteEdit.presentationName");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void undo()
|
||||
throws CannotUndoException {
|
||||
super.undo();
|
||||
drawingView.clearSelection();
|
||||
for (Figure figure : figures) {
|
||||
drawingView.getDrawing().add(figure);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void redo()
|
||||
throws CannotRedoException {
|
||||
super.redo();
|
||||
for (Figure figure : figures) {
|
||||
drawingView.getDrawing().remove(figure);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.modeleditor.components.drawing;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Provider;
|
||||
import javax.swing.JToggleButton;
|
||||
import org.jhotdraw.gui.JPopupButton;
|
||||
import org.opentcs.guing.base.model.elements.VehicleModel;
|
||||
import org.opentcs.guing.common.application.StatusPanel;
|
||||
import org.opentcs.guing.common.components.drawing.DrawingOptions;
|
||||
import org.opentcs.guing.common.components.drawing.DrawingViewPlacardPanel;
|
||||
import org.opentcs.guing.common.components.drawing.DrawingViewScrollPane;
|
||||
import org.opentcs.guing.common.components.drawing.OpenTCSDrawingEditor;
|
||||
import org.opentcs.guing.common.components.drawing.OpenTCSDrawingView;
|
||||
import org.opentcs.guing.common.model.SystemModel;
|
||||
import org.opentcs.guing.common.persistence.ModelManager;
|
||||
|
||||
/**
|
||||
* A factory for drawing views.
|
||||
*/
|
||||
public class DrawingViewFactory {
|
||||
|
||||
/**
|
||||
* A provider for drawing views.
|
||||
*/
|
||||
private final Provider<OpenTCSDrawingView> drawingViewProvider;
|
||||
/**
|
||||
* The drawing editor.
|
||||
*/
|
||||
private final OpenTCSDrawingEditor drawingEditor;
|
||||
/**
|
||||
* The status panel to display the current mouse position in.
|
||||
*/
|
||||
private final StatusPanel statusPanel;
|
||||
/**
|
||||
* The manager keeping/providing the currently loaded model.
|
||||
*/
|
||||
private final ModelManager modelManager;
|
||||
/**
|
||||
* The drawing options.
|
||||
*/
|
||||
private final DrawingOptions drawingOptions;
|
||||
|
||||
@Inject
|
||||
public DrawingViewFactory(
|
||||
Provider<OpenTCSDrawingView> drawingViewProvider,
|
||||
OpenTCSDrawingEditor drawingEditor,
|
||||
StatusPanel statusPanel,
|
||||
ModelManager modelManager,
|
||||
DrawingOptions drawingOptions
|
||||
) {
|
||||
this.drawingViewProvider = requireNonNull(drawingViewProvider, "drawingViewProvider");
|
||||
this.drawingEditor = requireNonNull(drawingEditor, "drawingEditor");
|
||||
this.statusPanel = requireNonNull(statusPanel, "statusPanel");
|
||||
this.modelManager = requireNonNull(modelManager, "modelManager");
|
||||
this.drawingOptions = requireNonNull(drawingOptions, "drawingOptions");
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and returns a new drawing view along with its placard panel, both
|
||||
* wrapped in a scroll pane.
|
||||
*
|
||||
* @param systemModel The system model.
|
||||
* @param selectionToolButton The selection tool button in the tool bar.
|
||||
* @param dragToolButton The drag tool button in the tool bar.
|
||||
* @param linkCreationToolButton The link creation tool button in the tool bar.
|
||||
* @param pathCreationToolButton The path creation tool button in the tool bar.
|
||||
* @return A new drawing view, wrapped in a scroll pane.
|
||||
*/
|
||||
public DrawingViewScrollPane createDrawingView(
|
||||
SystemModel systemModel,
|
||||
JToggleButton selectionToolButton,
|
||||
JToggleButton dragToolButton,
|
||||
JToggleButton linkCreationToolButton,
|
||||
JPopupButton pathCreationToolButton
|
||||
) {
|
||||
requireNonNull(systemModel, "systemModel");
|
||||
requireNonNull(selectionToolButton, "selectionToolButton");
|
||||
requireNonNull(dragToolButton, "dragToolButton");
|
||||
|
||||
OpenTCSDrawingView drawingView = drawingViewProvider.get();
|
||||
drawingEditor.add(drawingView);
|
||||
drawingEditor.setActiveView(drawingView);
|
||||
for (VehicleModel vehicle : systemModel.getVehicleModels()) {
|
||||
drawingView.displayDriveOrders(vehicle, vehicle.getDisplayDriveOrders());
|
||||
}
|
||||
drawingView.setBlocks(systemModel.getMainFolder(SystemModel.FolderKey.BLOCKS));
|
||||
|
||||
DrawingViewPlacardPanel placardPanel = new DrawingViewPlacardPanel(drawingView, drawingOptions);
|
||||
|
||||
DrawingViewScrollPane scrollPane = new DrawingViewScrollPane(drawingView, placardPanel);
|
||||
scrollPane.originChanged(systemModel.getDrawingMethod().getOrigin());
|
||||
|
||||
// --- Listens to draggings in the drawing ---
|
||||
ViewDragScrollListener dragScrollListener
|
||||
= new ViewDragScrollListener(
|
||||
scrollPane,
|
||||
placardPanel.getZoomComboBox(),
|
||||
selectionToolButton,
|
||||
dragToolButton,
|
||||
linkCreationToolButton,
|
||||
pathCreationToolButton,
|
||||
statusPanel,
|
||||
modelManager
|
||||
);
|
||||
drawingView.addMouseListener(dragScrollListener);
|
||||
drawingView.addMouseMotionListener(dragScrollListener);
|
||||
drawingView.getComponent().addMouseWheelListener(dragScrollListener);
|
||||
|
||||
return scrollPane;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.modeleditor.components.drawing;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.swing.undo.AbstractUndoableEdit;
|
||||
import javax.swing.undo.CannotRedoException;
|
||||
import javax.swing.undo.CannotUndoException;
|
||||
import org.jhotdraw.draw.DrawingView;
|
||||
import org.jhotdraw.draw.Figure;
|
||||
import org.opentcs.modeleditor.util.I18nPlantOverviewModeling;
|
||||
import org.opentcs.thirdparty.guing.common.jhotdraw.util.ResourceBundleUtil;
|
||||
|
||||
/**
|
||||
* Undoes or redoes a "paste" action.
|
||||
*/
|
||||
public class PasteEdit
|
||||
extends
|
||||
AbstractUndoableEdit {
|
||||
|
||||
/**
|
||||
* The drawing view we're working with.
|
||||
*/
|
||||
private final DrawingView drawingView;
|
||||
/**
|
||||
* The pasted figures.
|
||||
*/
|
||||
private final ArrayList<Figure> figures = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*
|
||||
* @param drawingView The drawing view the paste happened in.
|
||||
* @param figures The pasted figures.
|
||||
*/
|
||||
public PasteEdit(DrawingView drawingView, List<Figure> figures) {
|
||||
this.drawingView = requireNonNull(drawingView, "drawingView");
|
||||
this.figures.addAll(figures);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPresentationName() {
|
||||
return ResourceBundleUtil.getBundle(I18nPlantOverviewModeling.MENU_PATH)
|
||||
.getString("pasteEdit.presentationName");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void undo()
|
||||
throws CannotUndoException {
|
||||
super.undo();
|
||||
drawingView.getDrawing().removeAll(figures);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void redo()
|
||||
throws CannotRedoException {
|
||||
super.redo();
|
||||
drawingView.getDrawing().addAll(figures);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,346 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.modeleditor.components.drawing;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
import java.awt.Container;
|
||||
import java.awt.Cursor;
|
||||
import java.awt.Point;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.MouseWheelEvent;
|
||||
import java.awt.geom.Point2D;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JToggleButton;
|
||||
import javax.swing.JViewport;
|
||||
import javax.swing.SwingUtilities;
|
||||
import org.jhotdraw.draw.DrawingView;
|
||||
import org.jhotdraw.draw.Figure;
|
||||
import org.jhotdraw.gui.JPopupButton;
|
||||
import org.opentcs.guing.base.model.elements.LayoutModel;
|
||||
import org.opentcs.guing.common.application.StatusPanel;
|
||||
import org.opentcs.guing.common.components.drawing.DrawingViewScrollPane;
|
||||
import org.opentcs.guing.common.components.drawing.ZoomItem;
|
||||
import org.opentcs.guing.common.components.drawing.figures.LabeledLocationFigure;
|
||||
import org.opentcs.guing.common.components.drawing.figures.LabeledPointFigure;
|
||||
import org.opentcs.guing.common.components.drawing.figures.PathConnection;
|
||||
import org.opentcs.guing.common.components.drawing.figures.liner.TripleBezierLiner;
|
||||
import org.opentcs.guing.common.components.drawing.figures.liner.TupelBezierLiner;
|
||||
import org.opentcs.guing.common.persistence.ModelManager;
|
||||
|
||||
/**
|
||||
* A listener for dragging of the drawing view and single objects inside the
|
||||
* view.
|
||||
*/
|
||||
public class ViewDragScrollListener
|
||||
extends
|
||||
MouseAdapter {
|
||||
|
||||
/**
|
||||
* The scroll pane enclosing the drawing view.
|
||||
*/
|
||||
private final DrawingViewScrollPane scrollPane;
|
||||
/**
|
||||
* The combo box for selecting the zoom level.
|
||||
*/
|
||||
private final JComboBox<ZoomItem> zoomComboBox;
|
||||
/**
|
||||
* The button for enabling object selection.
|
||||
*/
|
||||
private final JToggleButton selectionTool;
|
||||
/**
|
||||
* The button for enabling dragging.
|
||||
*/
|
||||
private final JToggleButton dragTool;
|
||||
/**
|
||||
* The button for creating a link.
|
||||
*/
|
||||
private final JToggleButton linkCreationTool;
|
||||
/**
|
||||
* The button for creating a path.
|
||||
*/
|
||||
private final JPopupButton pathCreationTool;
|
||||
/**
|
||||
* The status panel to display the current mouse position in.
|
||||
*/
|
||||
private final StatusPanel statusPanel;
|
||||
/**
|
||||
* The manager keeping/providing the currently loaded model.
|
||||
*/
|
||||
private final ModelManager modelManager;
|
||||
/**
|
||||
* A default cursor for the drawing view.
|
||||
*/
|
||||
private final Cursor defaultCursor;
|
||||
/**
|
||||
* The start position of drag movements.
|
||||
*/
|
||||
private final Point startPoint = new Point();
|
||||
/**
|
||||
* Start coordinate for measuring.
|
||||
* XXX Is this redundant, or is it used for something different than startPoint?
|
||||
*/
|
||||
private final Point2D.Double fMouseStartPoint = new Point2D.Double();
|
||||
/**
|
||||
* Current coordinate for measuring.
|
||||
*/
|
||||
private final Point2D.Double fMouseCurrentPoint = new Point2D.Double();
|
||||
/**
|
||||
* End coordinate for measuring.
|
||||
*/
|
||||
private final Point2D.Double fMouseEndPoint = new Point2D.Double();
|
||||
/**
|
||||
* The figure a user may have pressed on / want to drag.
|
||||
*/
|
||||
private Figure pressedFigure;
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*
|
||||
* @param scrollPane The scroll pane enclosing the drawing view.
|
||||
* @param zoomComboBox The combo box for selecting the zoom level.
|
||||
* @param selectionTool The button for enabling object selection.
|
||||
* @param dragTool The button for enabling dragging.
|
||||
* @param linkCreationTool The button for creating a link.
|
||||
* @param pathCreationTool The button for creating a path.
|
||||
* @param statusPanel The status panel to display the current mouse position in.
|
||||
* @param modelManager The manager keeping/providing the currently loaded model.
|
||||
*/
|
||||
public ViewDragScrollListener(
|
||||
DrawingViewScrollPane scrollPane,
|
||||
JComboBox<ZoomItem> zoomComboBox,
|
||||
JToggleButton selectionTool,
|
||||
JToggleButton dragTool,
|
||||
JToggleButton linkCreationTool,
|
||||
JPopupButton pathCreationTool,
|
||||
StatusPanel statusPanel,
|
||||
ModelManager modelManager
|
||||
) {
|
||||
this.scrollPane = requireNonNull(scrollPane, "scrollPane");
|
||||
this.zoomComboBox = requireNonNull(zoomComboBox, "zoomComboBox");
|
||||
this.selectionTool = requireNonNull(selectionTool, "selectionTool");
|
||||
this.dragTool = requireNonNull(dragTool, "dragTool");
|
||||
this.linkCreationTool = requireNonNull(linkCreationTool, "linkCreationTool");
|
||||
this.pathCreationTool = requireNonNull(pathCreationTool, "pathCreationTool");
|
||||
this.statusPanel = requireNonNull(statusPanel, "statusPanel");
|
||||
this.modelManager = requireNonNull(modelManager, "modelManager");
|
||||
this.defaultCursor = scrollPane.getDrawingView().getComponent().getCursor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseDragged(final MouseEvent evt) {
|
||||
final DrawingView drawingView = scrollPane.getDrawingView();
|
||||
if (!(drawingView.getComponent().getParent() instanceof JViewport)) {
|
||||
return;
|
||||
}
|
||||
|
||||
final JViewport viewport = (JViewport) drawingView.getComponent().getParent();
|
||||
Point cp = SwingUtilities.convertPoint(drawingView.getComponent(), evt.getPoint(), viewport);
|
||||
|
||||
if (dragTool.isSelected()) {
|
||||
int dx = startPoint.x - cp.x;
|
||||
int dy = startPoint.y - cp.y;
|
||||
Point vp = viewport.getViewPosition();
|
||||
vp.translate(dx, dy);
|
||||
drawingView.getComponent().scrollRectToVisible(new Rectangle(vp, viewport.getSize()));
|
||||
}
|
||||
else if (linkCreationTool.isSelected() || pathCreationTool.isSelected()) {
|
||||
viewport.revalidate();
|
||||
// Start scrolling as soon as the mouse is hitting the view bounds.
|
||||
drawingView.getComponent().scrollRectToVisible(new Rectangle(evt.getX(), evt.getY(), 1, 1));
|
||||
}
|
||||
else { // The selection tool is selected
|
||||
viewport.revalidate();
|
||||
|
||||
if (isMovableFigure(pressedFigure)) {
|
||||
if (!isFigureCompletelyInView(pressedFigure, viewport, drawingView)) {
|
||||
// If the figure exceeds the current view, start scrolling as soon as the mouse is
|
||||
// hitting the view bounds.
|
||||
drawingView.getComponent().scrollRectToVisible(
|
||||
new Rectangle(evt.getX(), evt.getY(), 1, 1)
|
||||
);
|
||||
}
|
||||
|
||||
fMouseCurrentPoint.setLocation(drawingView.viewToDrawing(evt.getPoint()));
|
||||
showPositionStatus(false);
|
||||
startPoint.setLocation(cp);
|
||||
}
|
||||
}
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
Rectangle2D.Double drawingArea = drawingView.getDrawing().getDrawingArea();
|
||||
scrollPane.getHorizontalRuler().setPreferredWidth((int) drawingArea.width);
|
||||
scrollPane.getVerticalRuler().setPreferredHeight((int) drawingArea.height);
|
||||
});
|
||||
}
|
||||
|
||||
private boolean isMovableFigure(Figure figure) {
|
||||
return (figure instanceof LabeledPointFigure)
|
||||
|| (figure instanceof LabeledLocationFigure)
|
||||
|| ((figure instanceof PathConnection)
|
||||
&& (((PathConnection) figure).getLiner() instanceof TupelBezierLiner))
|
||||
|| ((figure instanceof PathConnection)
|
||||
&& (((PathConnection) figure).getLiner() instanceof TripleBezierLiner));
|
||||
}
|
||||
|
||||
private boolean isFigureCompletelyInView(
|
||||
Figure figure,
|
||||
JViewport viewport,
|
||||
DrawingView drawingView
|
||||
) {
|
||||
Rectangle viewPortBounds = viewport.getViewRect();
|
||||
Rectangle figureBounds = drawingView.drawingToView(figure.getDrawingArea());
|
||||
|
||||
return (figureBounds.getMinX() > viewPortBounds.getMinX())
|
||||
&& (figureBounds.getMinY() > viewPortBounds.getMinY())
|
||||
&& (figureBounds.getMaxX() < viewPortBounds.getMaxX())
|
||||
&& (figureBounds.getMaxY() < viewPortBounds.getMaxY());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mousePressed(MouseEvent evt) {
|
||||
final DrawingView drawingView = scrollPane.getDrawingView();
|
||||
if (dragIsSelected()) {
|
||||
drawingView.setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR));
|
||||
}
|
||||
Container c = drawingView.getComponent().getParent();
|
||||
if (c instanceof JViewport) {
|
||||
JViewport viewPort = (JViewport) c;
|
||||
Point cp = SwingUtilities.convertPoint(drawingView.getComponent(), evt.getPoint(), viewPort);
|
||||
startPoint.setLocation(cp);
|
||||
}
|
||||
pressedFigure = drawingView.findFigure(evt.getPoint());
|
||||
fMouseCurrentPoint.setLocation(drawingView.viewToDrawing(evt.getPoint()));
|
||||
fMouseStartPoint.setLocation(drawingView.viewToDrawing(evt.getPoint()));
|
||||
showPositionStatus(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseReleased(MouseEvent evt) {
|
||||
if (dragIsSelected()) {
|
||||
return;
|
||||
}
|
||||
|
||||
final DrawingView drawingView = scrollPane.getDrawingView();
|
||||
pressedFigure = null;
|
||||
fMouseEndPoint.setLocation(drawingView.viewToDrawing(evt.getPoint()));
|
||||
if (evt.getButton() != 2) {
|
||||
showPositionStatus(true);
|
||||
}
|
||||
else {
|
||||
showPositionStatus(false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseExited(MouseEvent evt) {
|
||||
dragIsSelected();
|
||||
clearPositionStatus();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseEntered(MouseEvent evt) {
|
||||
dragIsSelected();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseMoved(MouseEvent evt) {
|
||||
final DrawingView drawingView = scrollPane.getDrawingView();
|
||||
fMouseCurrentPoint.setLocation(drawingView.viewToDrawing(evt.getPoint()));
|
||||
showPositionStatus(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent evt) {
|
||||
if (evt.getButton() == 2) {
|
||||
if (dragTool.isSelected()) {
|
||||
selectionTool.setSelected(true);
|
||||
}
|
||||
else if (selectionTool.isSelected()) {
|
||||
dragTool.setSelected(true);
|
||||
}
|
||||
// Sets the correct cursor
|
||||
dragIsSelected();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseWheelMoved(MouseWheelEvent e) {
|
||||
if (e.isControlDown()) {
|
||||
int zoomLevel = zoomComboBox.getSelectedIndex();
|
||||
int notches = e.getWheelRotation();
|
||||
if (zoomLevel != -1) {
|
||||
if (notches < 0) {
|
||||
if (zoomLevel > 0) {
|
||||
zoomLevel--;
|
||||
zoomComboBox.setSelectedIndex(zoomLevel);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (zoomLevel < zoomComboBox.getItemCount() - 1) {
|
||||
zoomLevel++;
|
||||
zoomComboBox.setSelectedIndex(zoomLevel);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the drag tool is selected.
|
||||
*
|
||||
* @return true if the drag tool is selected, false otherwise.
|
||||
*/
|
||||
private boolean dragIsSelected() {
|
||||
final DrawingView drawingView = scrollPane.getDrawingView();
|
||||
if (!selectionTool.isSelected() && dragTool.isSelected()) {
|
||||
drawingView.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
|
||||
return true;
|
||||
}
|
||||
else if (selectionTool.isSelected() && !dragTool.isSelected()) {
|
||||
drawingView.setCursor(defaultCursor);
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the mouse position information in the status panel.
|
||||
*/
|
||||
private void clearPositionStatus() {
|
||||
statusPanel.setPositionText("");
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays the current mouse position or covered area in the status panel.
|
||||
*
|
||||
* @param showCoveredArea Whether to display the dimensions of the covered
|
||||
* area instead of the current mouse coordinates.
|
||||
*/
|
||||
private void showPositionStatus(boolean showCoveredArea) {
|
||||
double x = fMouseCurrentPoint.x;
|
||||
double y = -fMouseCurrentPoint.y;
|
||||
|
||||
if (showCoveredArea) {
|
||||
double w = Math.abs(fMouseEndPoint.x - fMouseStartPoint.x);
|
||||
double h = Math.abs(fMouseEndPoint.y - fMouseStartPoint.y);
|
||||
statusPanel.setPositionText(
|
||||
String.format("X %.0f Y %.0f W %.0f H %.0f", x, y, w, h)
|
||||
);
|
||||
}
|
||||
else {
|
||||
LayoutModel layout = modelManager.getModel().getLayoutModel();
|
||||
double scaleX = (double) layout.getPropertyScaleX().getValue();
|
||||
double scaleY = (double) layout.getPropertyScaleY().getValue();
|
||||
double xmm = x * scaleX;
|
||||
double ymm = y * scaleY;
|
||||
statusPanel.setPositionText(
|
||||
String.format("X %.0f (%.0fmm) Y %.0f (%.0fmm)", x, xmm, y, ymm)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.modeleditor.components.layer;
|
||||
|
||||
import org.opentcs.guing.base.components.layer.LayerWrapper;
|
||||
|
||||
/**
|
||||
* Provides a method to get the currently active layer.
|
||||
*/
|
||||
public interface ActiveLayerProvider {
|
||||
|
||||
/**
|
||||
* Returns the {@link LayerWrapper} instance that holds the currently active layer.
|
||||
*
|
||||
* @return The currently active layer.
|
||||
*/
|
||||
LayerWrapper getActiveLayer();
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.modeleditor.components.layer;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
import org.jhotdraw.draw.Figure;
|
||||
import org.opentcs.guing.base.model.DrawnModelComponent;
|
||||
import org.opentcs.guing.base.model.ModelComponent;
|
||||
import org.opentcs.guing.common.components.drawing.figures.FigureConstants;
|
||||
import org.opentcs.guing.common.event.DrawingEditorEvent;
|
||||
import org.opentcs.guing.common.event.DrawingEditorListener;
|
||||
|
||||
/**
|
||||
* Handles drawing editor events that the layer editor needs to know about.
|
||||
*/
|
||||
public class LayerEditorEventHandler
|
||||
implements
|
||||
DrawingEditorListener {
|
||||
|
||||
/**
|
||||
* The layer editor.
|
||||
*/
|
||||
private final LayerEditorModeling layerEditor;
|
||||
|
||||
@Inject
|
||||
public LayerEditorEventHandler(LayerEditorModeling layerEditor) {
|
||||
this.layerEditor = requireNonNull(layerEditor, "layerEditor");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void figureAdded(DrawingEditorEvent e) {
|
||||
Figure figure = e.getFigure();
|
||||
ModelComponent model = figure.get(FigureConstants.MODEL);
|
||||
if (model instanceof DrawnModelComponent) {
|
||||
layerEditor.add((DrawnModelComponent) model);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void figureRemoved(DrawingEditorEvent e) {
|
||||
Figure figure = e.getFigure();
|
||||
ModelComponent model = figure.get(FigureConstants.MODEL);
|
||||
if (model instanceof DrawnModelComponent) {
|
||||
layerEditor.remove((DrawnModelComponent) model);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void figureSelected(DrawingEditorEvent e) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.modeleditor.components.layer;
|
||||
|
||||
import org.opentcs.guing.base.model.DrawnModelComponent;
|
||||
import org.opentcs.guing.common.components.layer.LayerEditor;
|
||||
|
||||
/**
|
||||
* Provides methods to edit layers.
|
||||
*/
|
||||
public interface LayerEditorModeling
|
||||
extends
|
||||
LayerEditor {
|
||||
|
||||
/**
|
||||
* Creates a new layer.
|
||||
*/
|
||||
void createLayer();
|
||||
|
||||
/**
|
||||
* Deletes the layer with the given layer ID.
|
||||
*
|
||||
* @param layerId The ID of the layer to delete.
|
||||
* @throws IllegalArgumentException If a layer with the given layer ID doesn't exist.
|
||||
*/
|
||||
void deleteLayer(int layerId)
|
||||
throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Adds the given model component to the layer that is set in the component's layer wrapper
|
||||
* property.
|
||||
*
|
||||
* @param modelComponent The model component to add.
|
||||
*/
|
||||
void add(DrawnModelComponent modelComponent);
|
||||
|
||||
/**
|
||||
* Removes the given model component from its layer.
|
||||
*
|
||||
* @param modelComponent The model component to remove.
|
||||
*/
|
||||
void remove(DrawnModelComponent modelComponent);
|
||||
|
||||
/**
|
||||
* Moves the layer with the given ID one level down.
|
||||
*
|
||||
* @param layerId The ID of the layer.
|
||||
*/
|
||||
void moveLayerDown(int layerId);
|
||||
|
||||
/**
|
||||
* Moves the layer with the given ID one level up.
|
||||
*
|
||||
* @param layerId The ID of the layer.
|
||||
*/
|
||||
void moveLayerUp(int layerId);
|
||||
|
||||
/**
|
||||
* Sets the layer with the given ID as the active layer.
|
||||
*
|
||||
* @param layerId The ID of the layer.
|
||||
*/
|
||||
void setLayerActive(int layerId);
|
||||
|
||||
/**
|
||||
* Sets the group ID for the layer with the given ID.
|
||||
*
|
||||
* @param layerId The ID of the layer.
|
||||
* @param groupId The ID of the layer group.
|
||||
*/
|
||||
void setLayerGroupId(int layerId, int groupId);
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.modeleditor.components.layer;
|
||||
|
||||
import org.opentcs.guing.common.components.layer.LayerGroupEditor;
|
||||
|
||||
/**
|
||||
* Provides methods to edit layer groups.
|
||||
*/
|
||||
public interface LayerGroupEditorModeling
|
||||
extends
|
||||
LayerGroupEditor {
|
||||
|
||||
/**
|
||||
* Creates a new layer group.
|
||||
*/
|
||||
void createLayerGroup();
|
||||
|
||||
/**
|
||||
* Deletes the layer group with the given layer group ID.
|
||||
*
|
||||
* @param groupId The ID of the layer group to delete.
|
||||
* @throws IllegalArgumentException If a layer group with the given layer group ID doesn't exist.
|
||||
*/
|
||||
void deleteLayerGroup(int groupId)
|
||||
throws IllegalArgumentException;
|
||||
}
|
||||
@@ -0,0 +1,218 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.modeleditor.components.layer;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JTable;
|
||||
import javax.swing.JToolBar;
|
||||
import javax.swing.ListSelectionModel;
|
||||
import javax.swing.RowSorter;
|
||||
import javax.swing.SortOrder;
|
||||
import javax.swing.table.TableRowSorter;
|
||||
import org.opentcs.data.model.visualization.Layer;
|
||||
import org.opentcs.guing.common.components.layer.LayerGroupManager;
|
||||
import org.opentcs.guing.common.persistence.ModelManager;
|
||||
import org.opentcs.guing.common.util.IconToolkit;
|
||||
import org.opentcs.modeleditor.util.I18nPlantOverviewModeling;
|
||||
|
||||
/**
|
||||
* A panel to display and edit layer groups.
|
||||
*/
|
||||
public class LayerGroupsPanel
|
||||
extends
|
||||
JPanel {
|
||||
|
||||
/**
|
||||
* The path containing the icons.
|
||||
*/
|
||||
private static final String ICON_PATH = "/org/opentcs/guing/res/symbols/layer/";
|
||||
/**
|
||||
* The resource bundle to use.
|
||||
*/
|
||||
private static final ResourceBundle BUNDLE
|
||||
= ResourceBundle.getBundle(I18nPlantOverviewModeling.LAYERS_PATH);
|
||||
/**
|
||||
* The model manager.
|
||||
*/
|
||||
private final ModelManager modelManager;
|
||||
/**
|
||||
* The layer manager.
|
||||
*/
|
||||
private final LayerGroupManager layerGroupManager;
|
||||
/**
|
||||
* The layer editor.
|
||||
*/
|
||||
private final LayerGroupEditorModeling layerGroupEditor;
|
||||
/**
|
||||
* The table to display available layers.
|
||||
*/
|
||||
private JTable table;
|
||||
/**
|
||||
* The table model.
|
||||
*/
|
||||
private LayerGroupsTableModel tableModel;
|
||||
|
||||
@Inject
|
||||
@SuppressWarnings("this-escape")
|
||||
public LayerGroupsPanel(
|
||||
ModelManager modelManager,
|
||||
LayerGroupManager layerGroupManager,
|
||||
LayerGroupEditorModeling layerGroupEditor
|
||||
) {
|
||||
this.modelManager = requireNonNull(modelManager, "modelManager");
|
||||
this.layerGroupManager = requireNonNull(layerGroupManager, "layerGroupManager");
|
||||
this.layerGroupEditor = requireNonNull(layerGroupEditor, "layerGroupEditor");
|
||||
|
||||
initComponents();
|
||||
}
|
||||
|
||||
private void initComponents() {
|
||||
setLayout(new BorderLayout());
|
||||
|
||||
tableModel = new LayerGroupsTableModel(modelManager, layerGroupEditor);
|
||||
layerGroupManager.addLayerGroupChangeListener(tableModel);
|
||||
table = new JTable(tableModel);
|
||||
initTable();
|
||||
|
||||
add(createToolBar(), BorderLayout.NORTH);
|
||||
add(new JScrollPane(table), BorderLayout.CENTER);
|
||||
}
|
||||
|
||||
private void initTable() {
|
||||
table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
||||
|
||||
TableRowSorter<LayerGroupsTableModel> sorter = new TableRowSorter<>(tableModel);
|
||||
// Sort the table by the layer ordinals...
|
||||
sorter.setSortKeys(
|
||||
Arrays.asList(
|
||||
new RowSorter.SortKey(LayerGroupsTableModel.COLUMN_ID, SortOrder.DESCENDING)
|
||||
)
|
||||
);
|
||||
// ...but prevent manual sorting.
|
||||
for (int i = 0; i < table.getColumnCount(); i++) {
|
||||
sorter.setSortable(i, false);
|
||||
}
|
||||
sorter.setSortsOnUpdates(true);
|
||||
table.setRowSorter(sorter);
|
||||
|
||||
// Hide the column that shows the layer group IDs.
|
||||
table.removeColumn(
|
||||
table.getColumnModel()
|
||||
.getColumn(table.convertColumnIndexToView(LayerGroupsTableModel.COLUMN_ID))
|
||||
);
|
||||
}
|
||||
|
||||
private JToolBar createToolBar() {
|
||||
JToolBar toolBar = new JToolBar();
|
||||
toolBar.setFloatable(false);
|
||||
|
||||
toolBar.add(createAddGroupButton());
|
||||
toolBar.add(createRemoveGroupButton());
|
||||
|
||||
return toolBar;
|
||||
}
|
||||
|
||||
private JButton createAddGroupButton() {
|
||||
IconToolkit iconkit = IconToolkit.instance();
|
||||
JButton button
|
||||
= new JButton(iconkit.getImageIconByFullPath(ICON_PATH + "create-layer-group.16.png"));
|
||||
button.addActionListener(actionEvent -> {
|
||||
layerGroupEditor.createLayerGroup();
|
||||
table.getSelectionModel().setSelectionInterval(0, 0);
|
||||
});
|
||||
button.setToolTipText(BUNDLE.getString("layerGroupsPanel.button_addGroup.tooltipText"));
|
||||
|
||||
return button;
|
||||
}
|
||||
|
||||
private JButton createRemoveGroupButton() {
|
||||
IconToolkit iconkit = IconToolkit.instance();
|
||||
JButton button
|
||||
= new JButton(iconkit.getImageIconByFullPath(ICON_PATH + "delete-layer-group.16.png"));
|
||||
button.addActionListener(new RemoveGroupListener());
|
||||
button.setToolTipText(BUNDLE.getString("layerGroupsPanel.button_removeGroup.tooltipText"));
|
||||
|
||||
// Allow the remove group button to be pressed only if there's a group selected and if there's
|
||||
// more than one group in the model.
|
||||
table.getSelectionModel().addListSelectionListener(listSelectionEvent -> {
|
||||
button.setEnabled(table.getSelectedRow() != -1 && tableModel.getRowCount() > 1);
|
||||
});
|
||||
tableModel.addTableModelListener(tableModelEvent -> {
|
||||
button.setEnabled(table.getSelectedRow() != -1 && tableModel.getRowCount() > 1);
|
||||
});
|
||||
|
||||
return button;
|
||||
}
|
||||
|
||||
private class RemoveGroupListener
|
||||
implements
|
||||
ActionListener {
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*/
|
||||
RemoveGroupListener() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
int selectedRow = table.getSelectedRow();
|
||||
int selectedGroupId = tableModel.getDataAt(table.convertRowIndexToModel(selectedRow)).getId();
|
||||
|
||||
Map<Boolean, List<Layer>> layersByGroupAssignment = modelManager.getModel()
|
||||
.getLayoutModel().getPropertyLayerWrappers().getValue().values().stream()
|
||||
.map(wrapper -> wrapper.getLayer())
|
||||
.collect(Collectors.partitioningBy(layer -> layer.getGroupId() == selectedGroupId));
|
||||
List<Layer> layersAssignedToGroupToDelete = layersByGroupAssignment.get(Boolean.TRUE);
|
||||
List<Layer> layersAssignedToOtherGroups = layersByGroupAssignment.get(Boolean.FALSE);
|
||||
|
||||
if (layersAssignedToOtherGroups.isEmpty()) {
|
||||
// All layers in the model are assigned to the group the user wants to remove.
|
||||
// In this case, removing the group is not allowed as that would mean that all layers would
|
||||
// be removed as well and there wouldn't be any layers left.
|
||||
JOptionPane.showMessageDialog(
|
||||
LayerGroupsPanel.this,
|
||||
BUNDLE.getString("layerGroupsPanel.optionPane_groupRemovalNotPossible.message"),
|
||||
BUNDLE.getString("layerGroupsPanel.optionPane_groupRemovalNotPossible.title"),
|
||||
JOptionPane.INFORMATION_MESSAGE
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!layersAssignedToGroupToDelete.isEmpty()) {
|
||||
// The user is about remove a group with layers assigned to it. Removing the group results
|
||||
// in the assigned layers and the model components they contain to be removed as well.
|
||||
int selectedOption = JOptionPane.showConfirmDialog(
|
||||
LayerGroupsPanel.this,
|
||||
BUNDLE.getString(
|
||||
"layerGroupsPanel.optionPane_confirmGroupAndAssignedLayersRemoval.message"
|
||||
),
|
||||
BUNDLE.getString(
|
||||
"layerGroupsPanel.optionPane_confirmGroupAndAssignedLayersRemoval.title"
|
||||
),
|
||||
JOptionPane.YES_NO_OPTION,
|
||||
JOptionPane.WARNING_MESSAGE
|
||||
);
|
||||
if (selectedOption == JOptionPane.NO_OPTION) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
layerGroupEditor.deleteLayerGroup(selectedGroupId);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.modeleditor.components.layer;
|
||||
|
||||
import javax.swing.SwingUtilities;
|
||||
import org.opentcs.guing.common.components.layer.AbstractLayerGroupsTableModel;
|
||||
import org.opentcs.guing.common.components.layer.LayerGroupEditor;
|
||||
import org.opentcs.guing.common.persistence.ModelManager;
|
||||
|
||||
/**
|
||||
* The table model for layer groups for the Model Editor application.
|
||||
*/
|
||||
class LayerGroupsTableModel
|
||||
extends
|
||||
AbstractLayerGroupsTableModel {
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*
|
||||
* @param modelManager The model manager.
|
||||
* @param layerGroupEditor The layer group editor.
|
||||
*/
|
||||
LayerGroupsTableModel(ModelManager modelManager, LayerGroupEditor layerGroupEditor) {
|
||||
super(modelManager, layerGroupEditor);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isNameColumnEditable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isVisibleColumnEditable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void groupsInitialized() {
|
||||
// Once the layers are initialized we want to redraw the entire table to avoid any
|
||||
// display errors.
|
||||
executeOnEventDispatcherThread(() -> fireTableDataChanged());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void groupsChanged() {
|
||||
// Update the entire table but don't use fireTableDataChanged() to preserve the current
|
||||
// selection.
|
||||
executeOnEventDispatcherThread(() -> fireTableRowsUpdated(0, getRowCount() - 1));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void groupAdded() {
|
||||
// Groups are always added to the top (with regard to sorting).
|
||||
executeOnEventDispatcherThread(() -> fireTableRowsInserted(0, 0));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void groupRemoved() {
|
||||
// At this point, there's no way for us to determine the row the removed layer was in. The
|
||||
// entry has already been remove from this table model's data source which is provided by
|
||||
// layersByOrdinal().
|
||||
// Workaround: Since the table now contains one entry less, pretend that the last entry was
|
||||
// deleted.
|
||||
executeOnEventDispatcherThread(() -> fireTableRowsDeleted(getRowCount(), getRowCount()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures the given runnable is executed on the EDT.
|
||||
* If the runnable is already being called on the EDT, the runnable is executed immediately.
|
||||
* Otherwise it is scheduled for execution on the EDT.
|
||||
* <p>
|
||||
* Note: Deferring a runnable by scheduling it for execution on the EDT even though it would
|
||||
* have already been executed on the EDT may lead to exceptions due to data inconsistency.
|
||||
* </p>
|
||||
*
|
||||
* @param runnable The runnable.
|
||||
*/
|
||||
private void executeOnEventDispatcherThread(Runnable runnable) {
|
||||
if (SwingUtilities.isEventDispatchThread()) {
|
||||
runnable.run();
|
||||
}
|
||||
else {
|
||||
SwingUtilities.invokeLater(runnable);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,421 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.modeleditor.components.layer;
|
||||
|
||||
import static org.opentcs.util.Assertions.checkArgument;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import org.jhotdraw.draw.AbstractFigure;
|
||||
import org.jhotdraw.draw.Drawing;
|
||||
import org.opentcs.customizations.ApplicationEventBus;
|
||||
import org.opentcs.data.model.visualization.Layer;
|
||||
import org.opentcs.data.model.visualization.LayerGroup;
|
||||
import org.opentcs.guing.base.components.layer.LayerWrapper;
|
||||
import org.opentcs.guing.base.model.DrawnModelComponent;
|
||||
import org.opentcs.guing.base.model.ModelComponent;
|
||||
import org.opentcs.guing.common.application.ViewManager;
|
||||
import org.opentcs.guing.common.components.drawing.OpenTCSDrawingView;
|
||||
import org.opentcs.guing.common.components.layer.DefaultLayerManager;
|
||||
import org.opentcs.guing.common.components.layer.LayerManager;
|
||||
import org.opentcs.util.event.EventBus;
|
||||
|
||||
/**
|
||||
* The {@link LayerManager} implementation for the model editor application.
|
||||
*/
|
||||
public class LayerManagerModeling
|
||||
extends
|
||||
DefaultLayerManager
|
||||
implements
|
||||
LayerEditorModeling,
|
||||
LayerGroupEditorModeling,
|
||||
ActiveLayerProvider {
|
||||
|
||||
/**
|
||||
* The currently active layer.
|
||||
*/
|
||||
private LayerWrapper activeLayerWrapper;
|
||||
|
||||
@Inject
|
||||
public LayerManagerModeling(
|
||||
ViewManager viewManager,
|
||||
@ApplicationEventBus
|
||||
EventBus eventBus
|
||||
) {
|
||||
super(viewManager, eventBus);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createLayer() {
|
||||
Layer layer = createLayerWrapper().getLayer();
|
||||
getLayerChangeListener().layerAdded();
|
||||
|
||||
setLayerActive(layer.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteLayer(int layerId)
|
||||
throws IllegalArgumentException {
|
||||
checkArgument(
|
||||
getLayerWrapper(layerId) != null,
|
||||
"A layer with layer ID '%d' doesn't exist.",
|
||||
layerId
|
||||
);
|
||||
|
||||
deleteLayerWrapper(layerId);
|
||||
getLayerChangeListener().layerRemoved();
|
||||
|
||||
if (layerId == activeLayerWrapper.getLayer().getId()) {
|
||||
handleActiveLayerRemoved();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(DrawnModelComponent modelComponent) {
|
||||
int layerId = modelComponent.getPropertyLayerWrapper().getValue().getLayer().getId();
|
||||
checkArgument(
|
||||
getLayerWrapper(layerId) != null,
|
||||
"A layer with layer ID '%d' doesn't exist.",
|
||||
layerId
|
||||
);
|
||||
|
||||
addComponent(modelComponent, layerId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(DrawnModelComponent modelComponent) {
|
||||
removeComponent(modelComponent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void moveLayerDown(int layerId) {
|
||||
checkArgument(
|
||||
getLayerWrapper(layerId) != null,
|
||||
"A layer with layer ID '%d' doesn't exist.",
|
||||
layerId
|
||||
);
|
||||
|
||||
List<LayerWrapper> layerWrappersByOrdinal = getLayerWrappers().values().stream()
|
||||
.sorted(Comparator.comparing(wrapper -> wrapper.getLayer().getOrdinal()))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (layerId == layerWrappersByOrdinal.get(0).getLayer().getId()) {
|
||||
// The layer with the given layer ID is already the lowest layer.
|
||||
return;
|
||||
}
|
||||
|
||||
shiftLayerByOne(layerId, layerWrappersByOrdinal);
|
||||
|
||||
getLayerChangeListener().layersChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void moveLayerUp(int layerId) {
|
||||
checkArgument(
|
||||
getLayerWrapper(layerId) != null,
|
||||
"A layer with layer ID '%d' doesn't exist.",
|
||||
layerId
|
||||
);
|
||||
|
||||
List<LayerWrapper> layerWrappersByReverseOrdinal = getLayerWrappers().values().stream()
|
||||
.sorted(
|
||||
Comparator.comparing(
|
||||
wrapper -> wrapper.getLayer().getOrdinal(),
|
||||
Comparator.reverseOrder()
|
||||
)
|
||||
)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (layerId == layerWrappersByReverseOrdinal.get(0).getLayer().getId()) {
|
||||
// The layer with the given layer ID is already the heighest layer.
|
||||
return;
|
||||
}
|
||||
|
||||
shiftLayerByOne(layerId, layerWrappersByReverseOrdinal);
|
||||
|
||||
getLayerChangeListener().layersChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLayerActive(int layerId) {
|
||||
checkArgument(
|
||||
getLayerWrapper(layerId) != null,
|
||||
"A layer with layer ID '%d' doesn't exist.",
|
||||
layerId
|
||||
);
|
||||
|
||||
activeLayerWrapper = getLayerWrapper(layerId);
|
||||
|
||||
getLayerChangeListener().layersChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createLayerGroup() {
|
||||
int groupId = getNextAvailableLayerGroupId();
|
||||
|
||||
// Add the created layer group to the system model's layout.
|
||||
addLayerGroup(new LayerGroup(groupId, "Group " + groupId, true));
|
||||
|
||||
notifyGroupAdded();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteLayerGroup(int groupId)
|
||||
throws IllegalArgumentException {
|
||||
checkArgument(
|
||||
getLayerGroup(groupId) != null,
|
||||
"A layer group with layer group ID '%d' doesn't exist.",
|
||||
groupId
|
||||
);
|
||||
|
||||
// Delete the layers that are assigned to the group.
|
||||
Set<Integer> layerAssignedToGroup = getLayerWrappers().values().stream()
|
||||
.map(wrapper -> wrapper.getLayer())
|
||||
.filter(layer -> layer.getGroupId() == groupId)
|
||||
.map(layer -> layer.getId())
|
||||
.collect(Collectors.toSet());
|
||||
layerAssignedToGroup.forEach(layerId -> deleteLayer(layerId));
|
||||
|
||||
removeLayerGroup(groupId);
|
||||
notifyGroupRemoved();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLayerGroupId(int layerId, int groupId) {
|
||||
checkArgument(
|
||||
getLayerWrapper(layerId) != null,
|
||||
"A layer with layer ID '%d' doesn't exist.",
|
||||
layerId
|
||||
);
|
||||
checkArgument(
|
||||
getLayerGroup(groupId) != null,
|
||||
"A layer group with layer group ID '%d' doesn't exist.",
|
||||
groupId
|
||||
);
|
||||
|
||||
LayerWrapper wrapper = getLayerWrapper(layerId);
|
||||
|
||||
boolean visibleBefore = wrapper.getLayer().isVisible() && wrapper.getLayerGroup().isVisible();
|
||||
wrapper.setLayer(wrapper.getLayer().withGroupId(groupId));
|
||||
wrapper.setLayerGroup(getLayerGroup(groupId));
|
||||
boolean visibleAfter = wrapper.getLayer().isVisible() && wrapper.getLayerGroup().isVisible();
|
||||
|
||||
if (visibleBefore != visibleAfter) {
|
||||
layerVisibilityChanged(wrapper.getLayer(), visibleAfter);
|
||||
}
|
||||
|
||||
getLayerChangeListener().layersChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public LayerWrapper getActiveLayer() {
|
||||
return activeLayerWrapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void reset() {
|
||||
super.reset();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void restoreLayers() {
|
||||
// Make sure there will be one layer set as the active layer. Do it for the highest layer.
|
||||
activeLayerWrapper = getLayerWrappers().values().stream()
|
||||
.sorted(
|
||||
Comparator.comparing(
|
||||
wrapper -> wrapper.getLayer().getOrdinal(),
|
||||
Comparator.reverseOrder()
|
||||
)
|
||||
)
|
||||
.findFirst()
|
||||
.get();
|
||||
|
||||
super.restoreLayers();
|
||||
}
|
||||
|
||||
private LayerWrapper createLayerWrapper() {
|
||||
int layerId = getNextAvailableLayerId();
|
||||
int layerOrdinal = getNextAvailableLayerOrdinal();
|
||||
LayerGroup group = getLayerGroups().values().iterator().next();
|
||||
Layer layer = new Layer(layerId, layerOrdinal, true, "Layer " + layerId, group.getId());
|
||||
LayerWrapper wrapper = new LayerWrapper(layer, group);
|
||||
getComponents().put(layerId, new HashSet<>());
|
||||
|
||||
// Add the created layer wrapper to the system model's layout.
|
||||
addLayerWrapper(wrapper);
|
||||
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
private int getNextAvailableLayerId() {
|
||||
return getLayerWrappers().values().stream()
|
||||
.mapToInt(wrapper -> wrapper.getLayer().getId())
|
||||
.max()
|
||||
.getAsInt() + 1;
|
||||
}
|
||||
|
||||
private int getNextAvailableLayerOrdinal() {
|
||||
return getLayerWrappers().values().stream()
|
||||
.mapToInt(wrapper -> wrapper.getLayer().getOrdinal())
|
||||
.max()
|
||||
.getAsInt() + 1;
|
||||
}
|
||||
|
||||
private int getNextAvailableLayerGroupId() {
|
||||
return getLayerGroups().values().stream()
|
||||
.mapToInt(group -> group.getId())
|
||||
.max()
|
||||
.getAsInt() + 1;
|
||||
}
|
||||
|
||||
private void deleteLayerWrapper(int layerId) {
|
||||
Set<OpenTCSDrawingView> drawingViews = getDrawingViews();
|
||||
drawingViews.forEach(drawingView -> drawingView.getDrawing().willChange());
|
||||
|
||||
Set<ModelComponent> componentsToDelete = getComponents().get(layerId).stream()
|
||||
.map(component -> (ModelComponent) component)
|
||||
.collect(Collectors.toSet());
|
||||
drawingViews.forEach(drawingView -> drawingView.delete(componentsToDelete));
|
||||
|
||||
drawingViews.forEach(drawingView -> drawingView.getDrawing().changed());
|
||||
|
||||
getComponents().remove(layerId);
|
||||
|
||||
// Remove the deleted layer wrapper from the system model's layout.
|
||||
removeLayerWrapper(layerId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the set of drawing views the layer manager is working with.
|
||||
*
|
||||
* @return The set of drawing views the layer manager is working with.
|
||||
*/
|
||||
private Set<OpenTCSDrawingView> getDrawingViews() {
|
||||
return getViewManager().getDrawingViewMap().values().stream()
|
||||
.map(scrollPane -> scrollPane.getDrawingView())
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
private void handleActiveLayerRemoved() {
|
||||
List<Layer> layersByOrdinal = getLayerWrappers().values().stream()
|
||||
.map(wrapper -> wrapper.getLayer())
|
||||
.sorted(Comparator.comparing(layer -> layer.getOrdinal()))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
Optional<Layer> layerUnderRemovedActiveLayer = layersByOrdinal.stream()
|
||||
.takeWhile(layer -> layer.getOrdinal() < activeLayerWrapper.getLayer().getOrdinal())
|
||||
.reduce((layer1, layer2) -> layer2);
|
||||
|
||||
// If there's a layer right under the active layer that just has been removed, select that layer
|
||||
// as the new active layer. Otherwise, just select the lowest layer.
|
||||
if (layerUnderRemovedActiveLayer.isPresent()) {
|
||||
setLayerActive(layerUnderRemovedActiveLayer.get().getId());
|
||||
}
|
||||
else {
|
||||
setLayerActive(layersByOrdinal.get(0).getId());
|
||||
}
|
||||
}
|
||||
|
||||
private void shiftLayerByOne(int layerId, List<LayerWrapper> layers) {
|
||||
LayerWrapper layerWrapper = getLayerWrapper(layerId);
|
||||
int layerWrapperBeforeIndex = layers.indexOf(layerWrapper) - 1;
|
||||
LayerWrapper layerWrapperBefore = layers.get(layerWrapperBeforeIndex);
|
||||
swapLayerOrdinals(layerWrapper, layerWrapperBefore);
|
||||
updateLayerComponentsInDrawing(layerWrapper.getLayer(), layerWrapperBefore.getLayer());
|
||||
}
|
||||
|
||||
private void swapLayerOrdinals(LayerWrapper layerWrapper1, LayerWrapper layerWrapper2) {
|
||||
int ordinal1 = layerWrapper1.getLayer().getOrdinal();
|
||||
int ordinal2 = layerWrapper2.getLayer().getOrdinal();
|
||||
|
||||
Layer oldLayer = layerWrapper1.getLayer();
|
||||
Layer newLayer = oldLayer.withOrdinal(ordinal2);
|
||||
layerWrapper1.setLayer(newLayer);
|
||||
|
||||
oldLayer = layerWrapper2.getLayer();
|
||||
newLayer = oldLayer.withOrdinal(ordinal1);
|
||||
layerWrapper2.setLayer(newLayer);
|
||||
}
|
||||
|
||||
private void updateLayerComponentsInDrawing(Layer... layers) {
|
||||
Set<DrawnModelComponent> componentsToUpdate = new HashSet<>();
|
||||
for (Layer layer : layers) {
|
||||
if (layer.isVisible()) {
|
||||
componentsToUpdate.addAll(getComponents().get(layer.getId()));
|
||||
}
|
||||
}
|
||||
|
||||
Set<Drawing> drawings = getDrawings();
|
||||
|
||||
drawings.forEach(drawing -> drawing.willChange());
|
||||
for (DrawnModelComponent modelComponent : componentsToUpdate) {
|
||||
AbstractFigure figure = (AbstractFigure) getSystemModel().getFigure(modelComponent);
|
||||
drawings.forEach(drawing -> {
|
||||
drawing.basicRemove(figure);
|
||||
drawing.basicAdd(figure);
|
||||
});
|
||||
}
|
||||
drawings.forEach(drawing -> drawing.changed());
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the given layer group to the system model's layout.
|
||||
*
|
||||
* @param layerWrapper The layer group to add.
|
||||
* @throws IllegalArgumentException If a layer group with the same layer group ID already exists
|
||||
* in the system model's layout.
|
||||
*/
|
||||
private void addLayerGroup(LayerGroup layerGroup)
|
||||
throws IllegalArgumentException {
|
||||
int groupId = layerGroup.getId();
|
||||
checkArgument(
|
||||
getLayerGroup(groupId) == null,
|
||||
"A layer group for group ID '%d' already exists in the model.",
|
||||
groupId
|
||||
);
|
||||
|
||||
getLayerGroups().put(groupId, layerGroup);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the layer group with the given group ID from the system model's layout.
|
||||
*
|
||||
* @param layerId The layer group ID.
|
||||
*/
|
||||
private void removeLayerGroup(int groupId) {
|
||||
getLayerGroups().remove(groupId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the given layer wrapper to the system model's layout.
|
||||
*
|
||||
* @param layerWrapper The layer wrapper to add.
|
||||
* @throws IllegalArgumentException If a layer wrapper with the same layer ID already exists
|
||||
* in the system model's layout.
|
||||
*/
|
||||
private void addLayerWrapper(LayerWrapper layerWrapper)
|
||||
throws IllegalArgumentException {
|
||||
int layerId = layerWrapper.getLayer().getId();
|
||||
checkArgument(
|
||||
getLayerWrapper(layerId) == null,
|
||||
"A layer wrapper for layer ID '%d' already exists in the model.",
|
||||
layerId
|
||||
);
|
||||
|
||||
getLayerWrappers().put(layerId, layerWrapper);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the layer wrapper with the given layer ID from the system model's layout.
|
||||
*
|
||||
* @param layerId The layer ID.
|
||||
*/
|
||||
private void removeLayerWrapper(int layerId) {
|
||||
getLayerWrappers().remove(layerId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,380 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.modeleditor.components.layer;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Component;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.swing.AbstractCellEditor;
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.DefaultCellEditor;
|
||||
import javax.swing.DefaultComboBoxModel;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JRadioButton;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JTable;
|
||||
import javax.swing.JToolBar;
|
||||
import javax.swing.ListSelectionModel;
|
||||
import javax.swing.RowSorter;
|
||||
import javax.swing.SortOrder;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.border.Border;
|
||||
import javax.swing.table.TableCellEditor;
|
||||
import javax.swing.table.TableCellRenderer;
|
||||
import javax.swing.table.TableColumn;
|
||||
import javax.swing.table.TableRowSorter;
|
||||
import org.opentcs.data.model.visualization.LayerGroup;
|
||||
import org.opentcs.guing.common.components.layer.DisabledCheckBoxCellRenderer;
|
||||
import org.opentcs.guing.common.components.layer.LayerGroupCellRenderer;
|
||||
import org.opentcs.guing.common.components.layer.LayerGroupManager;
|
||||
import org.opentcs.guing.common.components.layer.LayerManager;
|
||||
import org.opentcs.guing.common.persistence.ModelManager;
|
||||
import org.opentcs.guing.common.util.IconToolkit;
|
||||
import org.opentcs.modeleditor.util.I18nPlantOverviewModeling;
|
||||
import org.opentcs.util.gui.StringListCellRenderer;
|
||||
|
||||
/**
|
||||
* A panel to display and edit layers.
|
||||
*/
|
||||
public class LayersPanel
|
||||
extends
|
||||
JPanel {
|
||||
|
||||
/**
|
||||
* The path containing the icons.
|
||||
*/
|
||||
private static final String ICON_PATH = "/org/opentcs/guing/res/symbols/layer/";
|
||||
/**
|
||||
* The resource bundle to use.
|
||||
*/
|
||||
private static final ResourceBundle BUNDLE
|
||||
= ResourceBundle.getBundle(I18nPlantOverviewModeling.LAYERS_PATH);
|
||||
/**
|
||||
* The model manager.
|
||||
*/
|
||||
private final ModelManager modelManager;
|
||||
/**
|
||||
* The layer manager.
|
||||
*/
|
||||
private final LayerManager layerManager;
|
||||
/**
|
||||
* The layer group manager.
|
||||
*/
|
||||
private final LayerGroupManager layerGroupManager;
|
||||
/**
|
||||
* The layer editor.
|
||||
*/
|
||||
private final LayerEditorModeling layerEditor;
|
||||
/**
|
||||
* Provides the currently active layer.
|
||||
*/
|
||||
private final ActiveLayerProvider activeLayerProvider;
|
||||
/**
|
||||
* The table to display available layers.
|
||||
*/
|
||||
private JTable table;
|
||||
/**
|
||||
* The table model.
|
||||
*/
|
||||
private LayersTableModel tableModel;
|
||||
|
||||
@Inject
|
||||
@SuppressWarnings("this-escape")
|
||||
public LayersPanel(
|
||||
ModelManager modelManager,
|
||||
LayerManager layerManager,
|
||||
LayerGroupManager layerGroupManager,
|
||||
LayerEditorModeling layerEditor,
|
||||
ActiveLayerProvider activeLayerProvider
|
||||
) {
|
||||
this.modelManager = requireNonNull(modelManager, "modelManager");
|
||||
this.layerManager = requireNonNull(layerManager, "layerManager");
|
||||
this.layerGroupManager = requireNonNull(layerGroupManager, "layerGroupManager");
|
||||
this.layerEditor = requireNonNull(layerEditor, "layerEditor");
|
||||
this.activeLayerProvider = requireNonNull(activeLayerProvider, "activeLayerProvider");
|
||||
|
||||
initComponents();
|
||||
}
|
||||
|
||||
private void initComponents() {
|
||||
setLayout(new BorderLayout());
|
||||
|
||||
tableModel = new LayersTableModel(modelManager, activeLayerProvider, layerEditor);
|
||||
layerManager.setLayerChangeListener(tableModel);
|
||||
layerGroupManager.addLayerGroupChangeListener(tableModel);
|
||||
table = new JTable(tableModel);
|
||||
initTable();
|
||||
|
||||
add(createToolBar(), BorderLayout.NORTH);
|
||||
add(new JScrollPane(table), BorderLayout.CENTER);
|
||||
}
|
||||
|
||||
private void initTable() {
|
||||
table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
||||
|
||||
TableRowSorter<LayersTableModel> sorter = new TableRowSorter<>(tableModel);
|
||||
// Sort the table by the layer ordinals...
|
||||
sorter.setSortKeys(
|
||||
Arrays.asList(
|
||||
new RowSorter.SortKey(LayersTableModel.COLUMN_ORDINAL, SortOrder.DESCENDING)
|
||||
)
|
||||
);
|
||||
// ...but prevent manual sorting.
|
||||
for (int i = 0; i < table.getColumnCount(); i++) {
|
||||
sorter.setSortable(i, false);
|
||||
}
|
||||
sorter.setSortsOnUpdates(true);
|
||||
table.setRowSorter(sorter);
|
||||
|
||||
// Hide the column that shows the layer ordinals.
|
||||
table.removeColumn(
|
||||
table.getColumnModel()
|
||||
.getColumn(table.convertColumnIndexToView(LayersTableModel.COLUMN_ORDINAL))
|
||||
);
|
||||
|
||||
table.getColumnModel()
|
||||
.getColumn(table.convertColumnIndexToView(LayersTableModel.COLUMN_GROUP_VISIBLE))
|
||||
.setCellRenderer(new DisabledCheckBoxCellRenderer());
|
||||
|
||||
initActiveColumn();
|
||||
initGroupColumn();
|
||||
}
|
||||
|
||||
private JToolBar createToolBar() {
|
||||
JToolBar toolBar = new JToolBar();
|
||||
toolBar.setFloatable(false);
|
||||
|
||||
toolBar.add(createAddLayerButton());
|
||||
toolBar.add(createRemoveLayerButton());
|
||||
toolBar.add(createMoveLayerUpButton());
|
||||
toolBar.add(createMoveLayerDownButton());
|
||||
|
||||
return toolBar;
|
||||
}
|
||||
|
||||
private void initActiveColumn() {
|
||||
// Since our concept of layers allows only one active layer at a time, a representation of that
|
||||
// state as radio buttons seems to have the potential to be more intuitive for users.
|
||||
// Radio buttons usually come with/in a button group which ensures that only one of the radio
|
||||
// buttons in that group can be selected at a time. In a table, though, such a button group
|
||||
// doesn't seem to work very well if it's used to group radio buttons across multiple rows.
|
||||
// For that reason the behavior of radio buttons in a button group is "emulated" in/trough
|
||||
// the LayerManager implementation.
|
||||
TableColumn columnActive = table.getColumnModel()
|
||||
.getColumn(table.convertColumnIndexToView(LayersTableModel.COLUMN_ACTIVE));
|
||||
columnActive.setCellEditor(new RadioButtonCellEditor());
|
||||
columnActive.setCellRenderer(new RadioButtonCellRenderer());
|
||||
}
|
||||
|
||||
private void initGroupColumn() {
|
||||
TableColumn columnGroup = table.getColumnModel()
|
||||
.getColumn(table.convertColumnIndexToView(LayersTableModel.COLUMN_GROUP));
|
||||
columnGroup.setCellRenderer(new LayerGroupCellRenderer());
|
||||
columnGroup.setCellEditor(new GroupCellEditor());
|
||||
}
|
||||
|
||||
private JButton createAddLayerButton() {
|
||||
IconToolkit iconkit = IconToolkit.instance();
|
||||
JButton button = new JButton(iconkit.getImageIconByFullPath(ICON_PATH + "create-layer.16.png"));
|
||||
button.addActionListener(actionEvent -> {
|
||||
layerEditor.createLayer();
|
||||
table.getSelectionModel().setSelectionInterval(0, 0);
|
||||
});
|
||||
button.setToolTipText(BUNDLE.getString("layersPanel.button_addLayer.tooltipText"));
|
||||
|
||||
return button;
|
||||
}
|
||||
|
||||
private JButton createRemoveLayerButton() {
|
||||
IconToolkit iconkit = IconToolkit.instance();
|
||||
JButton button = new JButton(iconkit.getImageIconByFullPath(ICON_PATH + "delete-layer.16.png"));
|
||||
button.addActionListener(new RemoveLayerListener());
|
||||
button.setToolTipText(BUNDLE.getString("layersPanel.button_removeLayer.tooltipText"));
|
||||
|
||||
// Allow the remove layer button to be pressed only if there's a layer selected and if there's
|
||||
// more than one layer in the model.
|
||||
table.getSelectionModel().addListSelectionListener(listSelectionEvent -> {
|
||||
button.setEnabled(table.getSelectedRow() != -1 && tableModel.getRowCount() > 1);
|
||||
});
|
||||
tableModel.addTableModelListener(tableModelEvent -> {
|
||||
button.setEnabled(table.getSelectedRow() != -1 && tableModel.getRowCount() > 1);
|
||||
});
|
||||
|
||||
return button;
|
||||
}
|
||||
|
||||
private JButton createMoveLayerUpButton() {
|
||||
IconToolkit iconkit = IconToolkit.instance();
|
||||
JButton button
|
||||
= new JButton(iconkit.getImageIconByFullPath(ICON_PATH + "move-layer-up.16.png"));
|
||||
button.setEnabled(false);
|
||||
button.addActionListener(actionEvent -> {
|
||||
int selectedRow = table.getSelectedRow();
|
||||
int selectedLayerId = tableModel.getDataAt(table.convertRowIndexToModel(selectedRow)).getId();
|
||||
layerEditor.moveLayerUp(selectedLayerId);
|
||||
});
|
||||
button.setToolTipText(BUNDLE.getString("layersPanel.button_moveLayerUp.tooltipText"));
|
||||
|
||||
// Allow the button to be pressed only if there's a layer selected.
|
||||
table.getSelectionModel().addListSelectionListener(listSelectionEvent -> {
|
||||
button.setEnabled(table.getSelectedRow() != -1);
|
||||
});
|
||||
|
||||
return button;
|
||||
}
|
||||
|
||||
private JButton createMoveLayerDownButton() {
|
||||
IconToolkit iconkit = IconToolkit.instance();
|
||||
JButton button
|
||||
= new JButton(iconkit.getImageIconByFullPath(ICON_PATH + "move-layer-down.16.png"));
|
||||
button.setEnabled(false);
|
||||
button.addActionListener(actionEvent -> {
|
||||
int selectedRow = table.getSelectedRow();
|
||||
int selectedLayerId = tableModel.getDataAt(table.convertRowIndexToModel(selectedRow)).getId();
|
||||
layerEditor.moveLayerDown(selectedLayerId);
|
||||
});
|
||||
button.setToolTipText(BUNDLE.getString("layersPanel.button_moveLayerDown.tooltipText"));
|
||||
|
||||
// Allow the button to be pressed only if there's a layer selected.
|
||||
table.getSelectionModel().addListSelectionListener(listSelectionEvent -> {
|
||||
button.setEnabled(table.getSelectedRow() != -1);
|
||||
});
|
||||
|
||||
return button;
|
||||
}
|
||||
|
||||
private class RemoveLayerListener
|
||||
implements
|
||||
ActionListener {
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*/
|
||||
RemoveLayerListener() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
int selectedRow = table.getSelectedRow();
|
||||
int selectedLayerId = tableModel.getDataAt(table.convertRowIndexToModel(selectedRow)).getId();
|
||||
|
||||
if (layerManager.containsComponents(selectedLayerId)) {
|
||||
int selectedOption = JOptionPane.showConfirmDialog(
|
||||
LayersPanel.this,
|
||||
BUNDLE.getString("layersPanel.optionPane_confirmLayerWithComponentsRemoval.message"),
|
||||
BUNDLE.getString("layersPanel.optionPane_confirmLayerWithComponentsRemoval.title"),
|
||||
JOptionPane.YES_NO_OPTION,
|
||||
JOptionPane.WARNING_MESSAGE
|
||||
);
|
||||
if (selectedOption == JOptionPane.NO_OPTION) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
layerEditor.deleteLayer(selectedLayerId);
|
||||
}
|
||||
}
|
||||
|
||||
private class RadioButtonCellRenderer
|
||||
implements
|
||||
TableCellRenderer {
|
||||
|
||||
private final Border unfocusedCellBorder = BorderFactory.createEmptyBorder();
|
||||
private final Border focusedCellBorder = UIManager.getBorder("Table.focusCellHighlightBorder");
|
||||
private final JRadioButton radioButton;
|
||||
|
||||
RadioButtonCellRenderer() {
|
||||
radioButton = new JRadioButton();
|
||||
radioButton.setHorizontalAlignment(JRadioButton.CENTER);
|
||||
radioButton.setBorderPainted(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getTableCellRendererComponent(
|
||||
JTable table, Object value, boolean isSelected,
|
||||
boolean hasFocus, int row, int col
|
||||
) {
|
||||
radioButton.setBackground(
|
||||
isSelected ? table.getSelectionBackground() : table.getBackground()
|
||||
);
|
||||
radioButton.setForeground(
|
||||
isSelected ? table.getSelectionForeground() : table.getForeground()
|
||||
);
|
||||
radioButton.setBorder(hasFocus ? focusedCellBorder : unfocusedCellBorder);
|
||||
radioButton.setSelected(Boolean.TRUE.equals(value));
|
||||
|
||||
return radioButton;
|
||||
}
|
||||
}
|
||||
|
||||
private class RadioButtonCellEditor
|
||||
extends
|
||||
AbstractCellEditor
|
||||
implements
|
||||
TableCellEditor {
|
||||
|
||||
private final JRadioButton radioButton;
|
||||
|
||||
RadioButtonCellEditor() {
|
||||
radioButton = new JRadioButton();
|
||||
radioButton.setHorizontalAlignment(JRadioButton.CENTER);
|
||||
radioButton.addActionListener(actionEvent -> stopCellEditing());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getTableCellEditorComponent(
|
||||
JTable table, Object value,
|
||||
boolean isSelected, int row, int col
|
||||
) {
|
||||
radioButton.setSelected(Boolean.TRUE.equals(value));
|
||||
return radioButton;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getCellEditorValue() {
|
||||
return radioButton.isSelected();
|
||||
}
|
||||
}
|
||||
|
||||
private class GroupCellEditor
|
||||
extends
|
||||
DefaultCellEditor {
|
||||
|
||||
private final DefaultComboBoxModel<LayerGroup> model;
|
||||
|
||||
GroupCellEditor() {
|
||||
super(new JComboBox<LayerGroup>());
|
||||
@SuppressWarnings("unchecked")
|
||||
JComboBox<LayerGroup> combobox = (JComboBox<LayerGroup>) getComponent();
|
||||
combobox.setRenderer(new StringListCellRenderer<>(group -> group.getName()));
|
||||
this.model = (DefaultComboBoxModel<LayerGroup>) combobox.getModel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getTableCellEditorComponent(
|
||||
JTable table, Object value,
|
||||
boolean isSelected, int row, int column
|
||||
) {
|
||||
model.removeAllElements();
|
||||
List<LayerGroup> groups = modelManager.getModel().getLayoutModel().getPropertyLayerGroups()
|
||||
.getValue().values().stream()
|
||||
.sorted((o1, o2) -> Integer.compare(o1.getId(), o2.getId()))
|
||||
.collect(Collectors.toList());
|
||||
model.addAll(groups);
|
||||
model.setSelectedItem(table.getModel().getValueAt(row, column));
|
||||
|
||||
return super.getTableCellEditorComponent(table, value, isSelected, row, column);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,311 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.modeleditor.components.layer;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.table.AbstractTableModel;
|
||||
import org.opentcs.data.model.visualization.Layer;
|
||||
import org.opentcs.data.model.visualization.LayerGroup;
|
||||
import org.opentcs.guing.base.components.layer.LayerWrapper;
|
||||
import org.opentcs.guing.common.components.layer.LayerChangeListener;
|
||||
import org.opentcs.guing.common.components.layer.LayerGroupChangeListener;
|
||||
import org.opentcs.guing.common.persistence.ModelManager;
|
||||
import org.opentcs.modeleditor.util.I18nPlantOverviewModeling;
|
||||
|
||||
/**
|
||||
* A table model for layers.
|
||||
*/
|
||||
class LayersTableModel
|
||||
extends
|
||||
AbstractTableModel
|
||||
implements
|
||||
LayerChangeListener,
|
||||
LayerGroupChangeListener {
|
||||
|
||||
/**
|
||||
* The number of the "Active" column.
|
||||
*/
|
||||
public static final int COLUMN_ACTIVE = 0;
|
||||
/**
|
||||
* The number of the "Ordinal" column.
|
||||
*/
|
||||
public static final int COLUMN_ORDINAL = 1;
|
||||
/**
|
||||
* The number of the "Visible" column.
|
||||
*/
|
||||
public static final int COLUMN_VISIBLE = 2;
|
||||
/**
|
||||
* The number of the "Name" column.
|
||||
*/
|
||||
public static final int COLUMN_NAME = 3;
|
||||
/**
|
||||
* The number of the "Group" column.
|
||||
*/
|
||||
public static final int COLUMN_GROUP = 4;
|
||||
/**
|
||||
* The number of the "Group visible" column.
|
||||
*/
|
||||
public static final int COLUMN_GROUP_VISIBLE = 5;
|
||||
/**
|
||||
* The resource bundle to use.
|
||||
*/
|
||||
private static final ResourceBundle BUNDLE
|
||||
= ResourceBundle.getBundle(I18nPlantOverviewModeling.LAYERS_PATH);
|
||||
/**
|
||||
* The column names.
|
||||
*/
|
||||
private static final String[] COLUMN_NAMES
|
||||
= new String[]{
|
||||
BUNDLE.getString(
|
||||
"layersTableModel.column_active.headerText"
|
||||
),
|
||||
BUNDLE.getString(
|
||||
"layersTableModel.column_ordinal.headerText"
|
||||
),
|
||||
BUNDLE.getString(
|
||||
"layersTableModel.column_visible.headerText"
|
||||
),
|
||||
BUNDLE.getString(
|
||||
"layersTableModel.column_name.headerText"
|
||||
),
|
||||
BUNDLE.getString(
|
||||
"layersTableModel.column_group.headerText"
|
||||
),
|
||||
BUNDLE.getString(
|
||||
"layersTableModel.column_groupVisible.headerText"
|
||||
)
|
||||
};
|
||||
/**
|
||||
* The column classes.
|
||||
*/
|
||||
private static final Class<?>[] COLUMN_CLASSES
|
||||
= new Class<?>[]{
|
||||
Boolean.class,
|
||||
Integer.class,
|
||||
Boolean.class,
|
||||
String.class,
|
||||
LayerGroup.class,
|
||||
Boolean.class
|
||||
};
|
||||
/**
|
||||
* The model manager.
|
||||
*/
|
||||
private final ModelManager modelManager;
|
||||
/**
|
||||
* Provides the currently active layer.
|
||||
*/
|
||||
private final ActiveLayerProvider activeLayerProvider;
|
||||
/**
|
||||
* The layer editor.
|
||||
*/
|
||||
private final LayerEditorModeling layerEditor;
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*
|
||||
* @param modelManager The model manager.
|
||||
* @param activeLayerProvider Provides the currently active layer.
|
||||
* @param layerEditor The layer editor.
|
||||
*/
|
||||
LayersTableModel(
|
||||
ModelManager modelManager,
|
||||
ActiveLayerProvider activeLayerProvider,
|
||||
LayerEditorModeling layerEditor
|
||||
) {
|
||||
this.modelManager = requireNonNull(modelManager, "modelManager");
|
||||
this.activeLayerProvider = requireNonNull(activeLayerProvider, "activeLayerProvider");
|
||||
this.layerEditor = requireNonNull(layerEditor, "layerEditor");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRowCount() {
|
||||
return getLayers().size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getColumnCount() {
|
||||
return COLUMN_NAMES.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValueAt(int rowIndex, int columnIndex) {
|
||||
if (rowIndex < 0 || rowIndex >= getRowCount()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Layer entry = getLayers().get(rowIndex);
|
||||
switch (columnIndex) {
|
||||
case COLUMN_ACTIVE:
|
||||
return entry.getId() == activeLayerProvider.getActiveLayer().getLayer().getId();
|
||||
case COLUMN_ORDINAL:
|
||||
return entry.getOrdinal();
|
||||
case COLUMN_VISIBLE:
|
||||
return entry.isVisible();
|
||||
case COLUMN_NAME:
|
||||
return entry.getName();
|
||||
case COLUMN_GROUP:
|
||||
return getLayerGroups().get(entry.getGroupId());
|
||||
case COLUMN_GROUP_VISIBLE:
|
||||
return getLayerGroups().get(entry.getGroupId()).isVisible();
|
||||
default:
|
||||
throw new IllegalArgumentException("Invalid column index: " + columnIndex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getColumnName(int columnIndex) {
|
||||
return COLUMN_NAMES[columnIndex];
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getColumnClass(int columnIndex) {
|
||||
return COLUMN_CLASSES[columnIndex];
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCellEditable(int rowIndex, int columnIndex) {
|
||||
switch (columnIndex) {
|
||||
case COLUMN_ACTIVE:
|
||||
return true;
|
||||
case COLUMN_ORDINAL:
|
||||
return false;
|
||||
case COLUMN_VISIBLE:
|
||||
return true;
|
||||
case COLUMN_NAME:
|
||||
return true;
|
||||
case COLUMN_GROUP:
|
||||
return true;
|
||||
case COLUMN_GROUP_VISIBLE:
|
||||
return false;
|
||||
default:
|
||||
throw new IllegalArgumentException("Invalid column index: " + columnIndex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
|
||||
if (rowIndex < 0 || rowIndex >= getRowCount()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (aValue == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Layer entry = getLayers().get(rowIndex);
|
||||
switch (columnIndex) {
|
||||
case COLUMN_ACTIVE:
|
||||
layerEditor.setLayerActive(entry.getId());
|
||||
break;
|
||||
case COLUMN_ORDINAL:
|
||||
// Do nothing.
|
||||
break;
|
||||
case COLUMN_VISIBLE:
|
||||
layerEditor.setLayerVisible(entry.getId(), (boolean) aValue);
|
||||
break;
|
||||
case COLUMN_NAME:
|
||||
layerEditor.setLayerName(entry.getId(), aValue.toString());
|
||||
break;
|
||||
case COLUMN_GROUP:
|
||||
layerEditor.setLayerGroupId(entry.getId(), ((LayerGroup) aValue).getId());
|
||||
break;
|
||||
case COLUMN_GROUP_VISIBLE:
|
||||
// Do nothing.
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Invalid column index: " + columnIndex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void layersInitialized() {
|
||||
// Once the layers are initialized we want to redraw the entire table to avoid any
|
||||
// display errors.
|
||||
executeOnEventDispatcherThread(() -> fireTableDataChanged());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void layersChanged() {
|
||||
// Update the entire table but don't use fireTableDataChanged() to preserve the current
|
||||
// selection.
|
||||
executeOnEventDispatcherThread(() -> fireTableRowsUpdated(0, getRowCount() - 1));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void layerAdded() {
|
||||
// Layers are always added to the top (with regard to sorting).
|
||||
executeOnEventDispatcherThread(() -> fireTableRowsInserted(0, 0));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void layerRemoved() {
|
||||
// At this point, there's no way for us to determine the row the removed layer was in. The
|
||||
// entry has already been remove from this table model's data source which is provided by
|
||||
// layersByOrdinal().
|
||||
// Workaround: Since the table now contains one entry less, pretend that the last entry was
|
||||
// deleted.
|
||||
executeOnEventDispatcherThread(() -> fireTableRowsDeleted(getRowCount(), getRowCount()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void groupsInitialized() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void groupsChanged() {
|
||||
// The visibility of a group, which we display as well, may have changed. Update the table.
|
||||
executeOnEventDispatcherThread(() -> fireTableRowsUpdated(0, getRowCount() - 1));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void groupAdded() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void groupRemoved() {
|
||||
}
|
||||
|
||||
public Layer getDataAt(int index) {
|
||||
return getLayers().get(index);
|
||||
}
|
||||
|
||||
private List<Layer> getLayers() {
|
||||
return getLayerWrappers().values().stream()
|
||||
.map(wrapper -> wrapper.getLayer())
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private Map<Integer, LayerWrapper> getLayerWrappers() {
|
||||
return modelManager.getModel().getLayoutModel().getPropertyLayerWrappers().getValue();
|
||||
}
|
||||
|
||||
private Map<Integer, LayerGroup> getLayerGroups() {
|
||||
return modelManager.getModel().getLayoutModel().getPropertyLayerGroups().getValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures the given runnable is executed on the EDT.
|
||||
* If the runnable is already being called on the EDT, the runnable is executed immediately.
|
||||
* Otherwise it is scheduled for execution on the EDT.
|
||||
* <p>
|
||||
* Note: Deferring a runnable by scheduling it for execution on the EDT even though it would
|
||||
* have already been executed on the EDT may lead to exceptions due to data inconsistency.
|
||||
* </p>
|
||||
*
|
||||
* @param runnable The runnable.
|
||||
*/
|
||||
private void executeOnEventDispatcherThread(Runnable runnable) {
|
||||
if (SwingUtilities.isEventDispatchThread()) {
|
||||
runnable.run();
|
||||
}
|
||||
else {
|
||||
SwingUtilities.invokeLater(runnable);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.modeleditor.components.tree.elements;
|
||||
|
||||
import com.google.inject.assistedinject.Assisted;
|
||||
import jakarta.inject.Inject;
|
||||
import javax.swing.JPopupMenu;
|
||||
import org.opentcs.guing.base.model.elements.VehicleModel;
|
||||
import org.opentcs.guing.common.application.GuiManager;
|
||||
import org.opentcs.guing.common.components.tree.elements.VehicleUserObject;
|
||||
import org.opentcs.guing.common.persistence.ModelManager;
|
||||
|
||||
/**
|
||||
* A Vehicle object in the tree view.
|
||||
*/
|
||||
public class VehicleUserObjectModeling
|
||||
extends
|
||||
VehicleUserObject {
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*
|
||||
* @param model The corresponding vehicle object.
|
||||
* @param guiManager The gui manager.
|
||||
* @param modelManager Provides the current system model.
|
||||
*/
|
||||
@Inject
|
||||
public VehicleUserObjectModeling(
|
||||
@Assisted
|
||||
VehicleModel model,
|
||||
GuiManager guiManager,
|
||||
ModelManager modelManager
|
||||
) {
|
||||
super(model, guiManager, modelManager);
|
||||
}
|
||||
|
||||
@Override // AbstractUserObject
|
||||
public JPopupMenu getPopupMenu() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.modeleditor.math.path;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
import static org.opentcs.util.Assertions.checkArgument;
|
||||
|
||||
import jakarta.annotation.Nonnull;
|
||||
import jakarta.inject.Inject;
|
||||
import org.opentcs.guing.base.components.properties.type.LengthProperty;
|
||||
import org.opentcs.guing.base.model.elements.PathModel;
|
||||
import org.opentcs.guing.base.model.elements.PointModel;
|
||||
import org.opentcs.guing.common.persistence.ModelManager;
|
||||
|
||||
/**
|
||||
* Calculates the length of {@link PathModel.Type#BEZIER} paths.
|
||||
*/
|
||||
public class BezierLength
|
||||
implements
|
||||
PathLengthFunction {
|
||||
|
||||
private final double scaleX;
|
||||
private final double scaleY;
|
||||
private final PathLengthMath pathLengthMath;
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*
|
||||
* @param manager Provides access to the current system model.
|
||||
* @param pathLengthMath Provides methods to evaluate the position of a point of a Bezier curve.
|
||||
*/
|
||||
@Inject
|
||||
public BezierLength(
|
||||
@Nonnull
|
||||
ModelManager manager,
|
||||
@Nonnull
|
||||
PathLengthMath pathLengthMath
|
||||
) {
|
||||
requireNonNull(manager, "manager");
|
||||
this.pathLengthMath = requireNonNull(pathLengthMath, "pathLengthMath");
|
||||
scaleX = manager.getModel().getLayoutModel().getPropertyScaleX()
|
||||
.getValueByUnit(LengthProperty.Unit.MM);
|
||||
scaleY = manager.getModel().getLayoutModel().getPropertyScaleY()
|
||||
.getValueByUnit(LengthProperty.Unit.MM);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double applyAsDouble(
|
||||
@Nonnull
|
||||
PathModel path
|
||||
) {
|
||||
requireNonNull(path, "path");
|
||||
|
||||
String[] cps = path.getPropertyPathControlPoints().getText().split(";");
|
||||
checkArgument(
|
||||
cps.length == 2,
|
||||
String.format("Path '%s' does not have exactly two control points.", path.getName())
|
||||
);
|
||||
|
||||
PointModel start = (PointModel) path.getStartComponent();
|
||||
PointModel end = (PointModel) path.getEndComponent();
|
||||
|
||||
return pathLengthMath.approximateCubicBezierCurveLength(
|
||||
new Coordinate(
|
||||
start.getPropertyModelPositionX().getValueByUnit(LengthProperty.Unit.MM),
|
||||
start.getPropertyModelPositionY().getValueByUnit(LengthProperty.Unit.MM)
|
||||
),
|
||||
new Coordinate(
|
||||
Double.parseDouble(cps[0].split(",")[0]) * scaleX,
|
||||
Double.parseDouble(cps[0].split(",")[1]) * scaleY * (-1)
|
||||
),
|
||||
new Coordinate(
|
||||
Double.parseDouble(cps[1].split(",")[0]) * scaleX,
|
||||
Double.parseDouble(cps[1].split(",")[1]) * scaleY * (-1)
|
||||
),
|
||||
new Coordinate(
|
||||
end.getPropertyModelPositionX().getValueByUnit(LengthProperty.Unit.MM),
|
||||
end.getPropertyModelPositionY().getValueByUnit(LengthProperty.Unit.MM)
|
||||
),
|
||||
1000
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.modeleditor.math.path;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
import static org.opentcs.util.Assertions.checkArgument;
|
||||
|
||||
import jakarta.annotation.Nonnull;
|
||||
import jakarta.inject.Inject;
|
||||
import org.opentcs.guing.base.components.properties.type.LengthProperty;
|
||||
import org.opentcs.guing.base.model.elements.PathModel;
|
||||
import org.opentcs.guing.base.model.elements.PointModel;
|
||||
import org.opentcs.guing.common.persistence.ModelManager;
|
||||
|
||||
/**
|
||||
* Calculates the length of {@link PathModel.Type#BEZIER_3} paths.
|
||||
*/
|
||||
public class BezierThreeLength
|
||||
implements
|
||||
PathLengthFunction {
|
||||
|
||||
private final double scaleX;
|
||||
private final double scaleY;
|
||||
private final PathLengthMath pathLengthMath;
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*
|
||||
* @param manager Provides access to the current system model.
|
||||
* @param pathLengthMath Provides methods to evaluate the position of a point of a Bezier curve.
|
||||
*/
|
||||
@Inject
|
||||
public BezierThreeLength(
|
||||
@Nonnull
|
||||
ModelManager manager,
|
||||
@Nonnull
|
||||
PathLengthMath pathLengthMath
|
||||
) {
|
||||
requireNonNull(manager, "manager");
|
||||
this.pathLengthMath = requireNonNull(pathLengthMath, "pathLengthMath");
|
||||
scaleX = manager.getModel().getLayoutModel().getPropertyScaleX()
|
||||
.getValueByUnit(LengthProperty.Unit.MM);
|
||||
scaleY = manager.getModel().getLayoutModel().getPropertyScaleY()
|
||||
.getValueByUnit(LengthProperty.Unit.MM);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double applyAsDouble(
|
||||
@Nonnull
|
||||
PathModel path
|
||||
) {
|
||||
requireNonNull(path, "path");
|
||||
|
||||
String[] cps = path.getPropertyPathControlPoints().getText().split(";");
|
||||
checkArgument(
|
||||
cps.length == 5,
|
||||
String.format("Path '%s' does not have exactly five control points.", path.getName())
|
||||
);
|
||||
|
||||
PointModel start = (PointModel) path.getStartComponent();
|
||||
PointModel end = (PointModel) path.getEndComponent();
|
||||
|
||||
return calculateBezierCurveLength(
|
||||
new Coordinate(
|
||||
start.getPropertyModelPositionX().getValueByUnit(LengthProperty.Unit.MM),
|
||||
start.getPropertyModelPositionY().getValueByUnit(LengthProperty.Unit.MM)
|
||||
),
|
||||
new Coordinate(
|
||||
Double.parseDouble(cps[0].split(",")[0]) * scaleX,
|
||||
Double.parseDouble(cps[0].split(",")[1]) * scaleY * (-1)
|
||||
),
|
||||
new Coordinate(
|
||||
Double.parseDouble(cps[1].split(",")[0]) * scaleX,
|
||||
Double.parseDouble(cps[1].split(",")[1]) * scaleY * (-1)
|
||||
),
|
||||
new Coordinate(
|
||||
Double.parseDouble(cps[2].split(",")[0]) * scaleX,
|
||||
Double.parseDouble(cps[2].split(",")[1]) * scaleY * (-1)
|
||||
),
|
||||
new Coordinate(
|
||||
Double.parseDouble(cps[3].split(",")[0]) * scaleX,
|
||||
Double.parseDouble(cps[3].split(",")[1]) * scaleY * (-1)
|
||||
),
|
||||
new Coordinate(
|
||||
Double.parseDouble(cps[4].split(",")[0]) * scaleX,
|
||||
Double.parseDouble(cps[4].split(",")[1]) * scaleY * (-1)
|
||||
),
|
||||
new Coordinate(
|
||||
end.getPropertyModelPositionX().getValueByUnit(LengthProperty.Unit.MM),
|
||||
end.getPropertyModelPositionY().getValueByUnit(LengthProperty.Unit.MM)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
private double calculateBezierCurveLength(
|
||||
Coordinate start, Coordinate cp0, Coordinate cp1,
|
||||
Coordinate cp2, Coordinate cp3, Coordinate cp4,
|
||||
Coordinate end
|
||||
) {
|
||||
return pathLengthMath.approximateCubicBezierCurveLength(start, cp0, cp1, cp2, 1000)
|
||||
+ pathLengthMath.approximateCubicBezierCurveLength(cp2, cp3, cp4, end, 1000);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.modeleditor.math.path;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
import jakarta.annotation.Nonnull;
|
||||
import jakarta.inject.Inject;
|
||||
import java.util.Map;
|
||||
import org.opentcs.guing.base.model.elements.PathModel;
|
||||
|
||||
/**
|
||||
* A composite of various {@link PathLengthFunction}s for different {@link PathModel.Type}s which
|
||||
* falls back to {@link EuclideanDistance}.
|
||||
*/
|
||||
public class CompositePathLengthFunction
|
||||
implements
|
||||
PathLengthFunction {
|
||||
|
||||
private final Map<PathModel.Type, PathLengthFunction> pathLengthFunctions;
|
||||
private final EuclideanDistance euclideanDistance;
|
||||
|
||||
@Inject
|
||||
public CompositePathLengthFunction(
|
||||
@Nonnull
|
||||
Map<PathModel.Type, PathLengthFunction> pathLengthFunctions,
|
||||
@Nonnull
|
||||
EuclideanDistance euclideanDistance
|
||||
) {
|
||||
this.pathLengthFunctions = requireNonNull(pathLengthFunctions, "pathLengthFunctions");
|
||||
this.euclideanDistance = requireNonNull(euclideanDistance, "euclideanDistance");
|
||||
}
|
||||
|
||||
@Override
|
||||
public double applyAsDouble(PathModel path) {
|
||||
return pathLengthFunctions
|
||||
.getOrDefault((PathModel.Type) path.getPropertyPathConnType().getValue(), euclideanDistance)
|
||||
.applyAsDouble(path);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.modeleditor.math.path;
|
||||
|
||||
/**
|
||||
* A generic 2-tuple of double values, usable for 2D coordinates and vectors, for instance.
|
||||
*/
|
||||
public class Coordinate {
|
||||
|
||||
/**
|
||||
* The X coordinate.
|
||||
*/
|
||||
private final double x;
|
||||
/**
|
||||
* The Y coordinate.
|
||||
*/
|
||||
private final double y;
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*
|
||||
* @param x The X coordinate.
|
||||
* @param y The Y coordinate.
|
||||
*/
|
||||
public Coordinate(double x, double y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the x coordinate.
|
||||
*
|
||||
* @return x
|
||||
*/
|
||||
public double getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the y coordinate.
|
||||
*
|
||||
* @return y
|
||||
*/
|
||||
public double getY() {
|
||||
return y;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (!(obj instanceof Coordinate)) {
|
||||
return false;
|
||||
}
|
||||
Coordinate other = (Coordinate) obj;
|
||||
if (this.x != other.x) {
|
||||
return false;
|
||||
}
|
||||
if (this.y != other.y) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return (int) (x * y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Coordinate{" + "x=" + x + ", y=" + y + '}';
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.modeleditor.math.path;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
import jakarta.annotation.Nonnull;
|
||||
import jakarta.inject.Inject;
|
||||
import org.opentcs.guing.base.components.properties.type.LengthProperty;
|
||||
import org.opentcs.guing.base.model.elements.PathModel;
|
||||
import org.opentcs.guing.base.model.elements.PointModel;
|
||||
|
||||
/**
|
||||
* Calculates the length of a path as the Euclidean distance between the start and end point.
|
||||
*/
|
||||
public class EuclideanDistance
|
||||
implements
|
||||
PathLengthFunction {
|
||||
|
||||
private final PathLengthMath pathLengthMath;
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*
|
||||
* @param pathLengthMath Provides a method for the euclidean distance.
|
||||
*/
|
||||
@Inject
|
||||
public EuclideanDistance(
|
||||
@Nonnull
|
||||
PathLengthMath pathLengthMath
|
||||
) {
|
||||
this.pathLengthMath = requireNonNull(pathLengthMath, "pathLengthMath");
|
||||
}
|
||||
|
||||
@Override
|
||||
public double applyAsDouble(
|
||||
@Nonnull
|
||||
PathModel path
|
||||
) {
|
||||
requireNonNull(path, "path");
|
||||
|
||||
PointModel start = (PointModel) path.getStartComponent();
|
||||
PointModel end = (PointModel) path.getEndComponent();
|
||||
|
||||
Coordinate x = new Coordinate(
|
||||
start.getPropertyModelPositionX().getValueByUnit(LengthProperty.Unit.MM),
|
||||
start.getPropertyModelPositionY().getValueByUnit(LengthProperty.Unit.MM)
|
||||
);
|
||||
Coordinate y = new Coordinate(
|
||||
end.getPropertyModelPositionX().getValueByUnit(LengthProperty.Unit.MM),
|
||||
end.getPropertyModelPositionY().getValueByUnit(LengthProperty.Unit.MM)
|
||||
);
|
||||
|
||||
return pathLengthMath.euclideanDistance(x, y);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.modeleditor.math.path;
|
||||
|
||||
import java.util.function.ToDoubleFunction;
|
||||
import org.opentcs.guing.base.model.elements.PathModel;
|
||||
|
||||
/**
|
||||
* A function that computes the length of a path.
|
||||
*/
|
||||
public interface PathLengthFunction
|
||||
extends
|
||||
ToDoubleFunction<PathModel> {
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.modeleditor.math.path;
|
||||
|
||||
/**
|
||||
* Provides the euclidean distance and methods to evaluate the position of a point of a Bezier curve
|
||||
* with n control points at a given parameter value.
|
||||
*/
|
||||
public class PathLengthMath {
|
||||
|
||||
public PathLengthMath() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Approximates the length of a cubic Bezier curve (described via its control points) by
|
||||
* discretization of the curve.
|
||||
*
|
||||
* @param cp0 The control point with index 0 (i.e. the start point of the Bezier curve).
|
||||
* @param cp1 The control point with index 1.
|
||||
* @param cp2 The control point with index 2.
|
||||
* @param cp3 The control point with index 3 (i.e. the end point of the Bezier curve).
|
||||
* @param granularity The granularity of the discretized curve. A higher granularity results in a
|
||||
* more precise approximation.
|
||||
*
|
||||
* @return The approximated length of the Bezier curve.
|
||||
*/
|
||||
public double approximateCubicBezierCurveLength(
|
||||
Coordinate cp0,
|
||||
Coordinate cp1,
|
||||
Coordinate cp2,
|
||||
Coordinate cp3,
|
||||
double granularity
|
||||
) {
|
||||
double length = 0.0;
|
||||
|
||||
for (int i = 0; i < granularity; i++) {
|
||||
length += euclideanDistance(
|
||||
evaluatePointOnCubicBezierCurve((double) i / granularity, cp0, cp1, cp2, cp3),
|
||||
evaluatePointOnCubicBezierCurve((double) (i + 1) / granularity, cp0, cp1, cp2, cp3)
|
||||
);
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates a point's position on a cubic Bezier curve (described via its control points) using
|
||||
* Bernstein basis polynomials.
|
||||
*
|
||||
* @param t The parameter (with a value between 0 and 1) that defines the position of a point
|
||||
* along the Bezier curve. A value of 0 corresponds to the position of the first control point and
|
||||
* a value of 1 to the position of the last control point.
|
||||
* @param cp0 The control point with index 0 (i.e. the start point of the Bezier curve).
|
||||
* @param cp1 The control point with index 1.
|
||||
* @param cp2 The control point with index 2.
|
||||
* @param cp3 The control point with index 3 (i.e. the end point of the Bezier curve).
|
||||
* @return A point's position on a cubic Bezier curve.
|
||||
*/
|
||||
public Coordinate evaluatePointOnCubicBezierCurve(
|
||||
double t,
|
||||
Coordinate cp0,
|
||||
Coordinate cp1,
|
||||
Coordinate cp2,
|
||||
Coordinate cp3
|
||||
) {
|
||||
return new Coordinate(
|
||||
bernsteinPolynomialOfDegree3(t, cp0.getX(), cp1.getX(), cp2.getX(), cp3.getX()),
|
||||
bernsteinPolynomialOfDegree3(t, cp0.getY(), cp1.getY(), cp2.getY(), cp3.getY())
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the distance between two given points using the euclidean algorithm.
|
||||
*
|
||||
* @param p1 The first point.
|
||||
* @param p2 The second point.
|
||||
* @return The distance between these two points.
|
||||
*/
|
||||
public double euclideanDistance(Coordinate p1, Coordinate p2) {
|
||||
return Math.sqrt(Math.pow(p1.getX() - p2.getX(), 2) + Math.pow(p1.getY() - p2.getY(), 2));
|
||||
}
|
||||
|
||||
private double bernsteinPolynomialOfDegree3(
|
||||
double t,
|
||||
double cp0,
|
||||
double cp1,
|
||||
double cp2,
|
||||
double cp3
|
||||
) {
|
||||
double u = 1.0 - t;
|
||||
return Math.pow(u, 3) * cp0
|
||||
+ 3 * Math.pow(u, 2) * t * cp1
|
||||
+ 3 * u * Math.pow(t, 2) * cp2
|
||||
+ Math.pow(t, 3) * cp3;
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user