Initial commit
Some checks failed
Gradle Build / build (push) Has been cancelled

This commit is contained in:
CaiXiang
2024-11-30 18:36:13 +08:00
commit aa56926258
2134 changed files with 232943 additions and 0 deletions

View File

@@ -0,0 +1,16 @@
// 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-project.gradle"
apply from: "${rootDir}/gradle/publishing-java.gradle"
dependencies {
api project(':opentcs-api-injection')
api project(':opentcs-common')
}
task release {
dependsOn build
}

View 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

View File

@@ -0,0 +1,42 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.guing.plugins.panels.allocation;
import org.opentcs.customizations.plantoverview.PlantOverviewInjectionModule;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Configures the resource allocation panel.
*/
public class AllocationPanelModule
extends
PlantOverviewInjectionModule {
/**
* This class's logger.
*/
private static final Logger LOG = LoggerFactory.getLogger(AllocationPanelModule.class);
/**
* Creates a new instance.
*/
public AllocationPanelModule() {
}
@Override
protected void configure() {
ResourceAllocationPanelConfiguration configuration
= getConfigBindingProvider().get(
ResourceAllocationPanelConfiguration.PREFIX,
ResourceAllocationPanelConfiguration.class
);
if (!configuration.enable()) {
LOG.info("Resource allocation panel disabled by configuration.");
return;
}
pluggablePanelFactoryBinder().addBinding().to(ResourceAllocationPanelFactory.class);
}
}

View File

@@ -0,0 +1,4 @@
# SPDX-FileCopyrightText: The openTCS Authors
# SPDX-License-Identifier: MIT
org.opentcs.guing.plugins.panels.allocation.AllocationPanelModule

View File

@@ -0,0 +1,98 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.guing.plugins.panels.allocation;
import static java.util.Objects.requireNonNull;
import java.awt.Component;
import java.net.URL;
import javax.swing.ImageIcon;
import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import org.opentcs.data.model.Path;
import org.opentcs.data.model.Point;
import org.opentcs.data.model.TCSResourceReference;
/**
* Renders the tree nodes with vehicle, point and path icons.
*/
public class AllocationTreeCellRenderer
extends
DefaultTreeCellRenderer {
/**
* The icon for vehicles in the tree view.
*/
private final ImageIcon vehicleIcon;
/**
* The icon for points in the tree view.
*/
private final ImageIcon pointIcon;
/**
* The icon for paths in the tree view.
*/
private final ImageIcon pathIcon;
/**
* Creates a new instance.
*/
public AllocationTreeCellRenderer() {
vehicleIcon = iconByFullPath(
"/org/opentcs/guing/plugins/panels/allocation/symbols/vehicle.18x18.png"
);
pointIcon = iconByFullPath(
"/org/opentcs/guing/plugins/panels/allocation/symbols/point.18x18.png"
);
pathIcon = iconByFullPath(
"/org/opentcs/guing/plugins/panels/allocation/symbols/path.18x18.png"
);
}
@Override
public Component getTreeCellRendererComponent(
JTree tree, Object node, boolean selected,
boolean expanded, boolean isLeaf, int row,
boolean hasFocus
) {
//Let the superclass handle all its stuff related to rendering
super.getTreeCellRendererComponent(tree, node, selected, expanded, isLeaf, row, hasFocus);
if (node instanceof DefaultMutableTreeNode) {
DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode) node;
//User object is of type string only if the node contains a vehicle or is the root node
if (treeNode.getUserObject() instanceof String) {
setIcon(vehicleIcon);
}
//User object is of type TCSResource only if the node contains a path or a point
else if (treeNode.getUserObject() instanceof TCSResourceReference) {
TCSResourceReference<?> resource = (TCSResourceReference<?>) treeNode.getUserObject();
setText(resource.getName());
if (resource.getReferentClass() == Path.class) {
setIcon(pathIcon);
}
else if (resource.getReferentClass() == Point.class) {
setIcon(pointIcon);
}
}
}
return this;
}
/**
* Creates an ImageIcon.
*
* @param fullPath The full (absolute) path of the icon file.
* @return The icon, or <code>null</code>, if the file does not exist.
*/
private ImageIcon iconByFullPath(String fullPath) {
requireNonNull(fullPath, "fullPath");
URL url = getClass().getResource(fullPath);
if (url == null) {
throw new IllegalArgumentException("Icon file not found: " + fullPath);
}
return new ImageIcon(url);
}
}

View File

@@ -0,0 +1,178 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.guing.plugins.panels.allocation;
import static org.opentcs.guing.plugins.panels.allocation.I18nPlantOverviewPanelResourceAllocation.BUNDLE_PATH;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
import java.util.ResourceBundle;
import java.util.stream.Collectors;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.MutableTreeNode;
import org.opentcs.data.model.TCSResourceReference;
/**
* A model for a resource allocation tree to display an alphabetically ordered view for vehicle
* names and their not ordered allocated resources.
*/
public class AllocationTreeModel
extends
DefaultTreeModel {
/**
* This class' bundle.
*/
private static final ResourceBundle BUNDLE = ResourceBundle.getBundle(BUNDLE_PATH);
/**
* Creates a new instance.
*/
public AllocationTreeModel() {
super(
new DefaultMutableTreeNode(BUNDLE.getString("resourceAllocationPanel.treeRoot.text")),
true
);
}
/**
* Updates the vehicle resource allocations displayed in this tree model.
*
* @param vehicleName The name of the vehicle
* @param newAllocations The new vehicle resource allocations
*/
public void updateAllocations(String vehicleName, List<TCSResourceReference<?>> newAllocations) {
updateVehicleAllocation(vehicleName, newAllocations);
removeNotAllocatedVehicles(vehicleName, newAllocations);
}
/**
* Removes all vehicle tree nodes where the vehicle does not have any resources allocated.
*
* @param allocatedVehicles The vehicles which have a resource allocation
*/
private void removeNotAllocatedVehicles(
String vehicleName,
List<TCSResourceReference<?>> resources
) {
@SuppressWarnings("unchecked")
List<DefaultMutableTreeNode> rootChildren
= Collections.list((Enumeration<DefaultMutableTreeNode>) root.children());
for (DefaultMutableTreeNode currentNode : rootChildren) {
Object userObject = currentNode.getUserObject();
//If we have a vehicle node but the vehicle name is not in the set, remove it
if (userObject.equals(vehicleName) && resources.isEmpty()) {
removeNodeFromParent(currentNode);
}
}
}
/**
* Updates the allocated resources for a specified vehicle if necessarry.
*
* @param vehicleName The name of the vehicle
* @param resources The allocated resources of the vehicle
*/
private void updateVehicleAllocation(
String vehicleName,
List<TCSResourceReference<?>> resources
) {
DefaultMutableTreeNode vehicleNode = null;
for (int x = 0; x < root.getChildCount(); x++) {
DefaultMutableTreeNode currentNode = (DefaultMutableTreeNode) root.getChildAt(x);
if (currentNode.getUserObject().equals(vehicleName)) {
vehicleNode = currentNode;
}
}
if (vehicleNode == null) {
vehicleNode = createNewVehicleNode(vehicleName);
}
//Remove all children that are not in the new allocation
List<DefaultMutableTreeNode> vehicleChildren = Collections.list(vehicleNode.children()).stream()
.map(treeNode -> (DefaultMutableTreeNode) treeNode)
.collect(Collectors.toList());
for (DefaultMutableTreeNode current : vehicleChildren) {
if (!resources.contains((TCSResourceReference<?>) current.getUserObject())) {
vehicleNode.remove(current);
}
}
//Add new resources that are not in the jtree already at the correct position
int index = 0;
for (TCSResourceReference<?> resource : resources) {
if (vehicleNode.getChildCount() <= index) {
//Insert the resource at this position
vehicleNode.insert(new DefaultMutableTreeNode(resource, false), index);
}
else {
DefaultMutableTreeNode current = (DefaultMutableTreeNode) vehicleNode.getChildAt(index);
TCSResourceReference<?> resource2 = (TCSResourceReference<?>) current.getUserObject();
//Check if the resource exists at the current position - then we dont have to do anything
if (!resource.equals(resource2)) {
//Check if the resource exists at another position in the children list
int existIndex = getChildIndexOf(resource, vehicleNode);
//If the resource already exists at another point, move it to the index
if (existIndex > 0) {
vehicleNode.remove(existIndex);
}
//Insert the resource at this position
vehicleNode.insert(new DefaultMutableTreeNode(resource, false), index);
}
}
index++;
}
reload(vehicleNode);
}
/**
* Returns the index of the first children containing the resource as user object.
*
* @param resource The resource to search for
* @param vehicleNode The parent node
* @return The index of the node containing the resource or -1 if not found
*/
private int getChildIndexOf(
TCSResourceReference<?> resource,
DefaultMutableTreeNode vehicleNode
) {
int index = 0;
List<DefaultMutableTreeNode> vehicleChildren = Collections.list(vehicleNode.children()).stream()
.map(treeNode -> (DefaultMutableTreeNode) treeNode)
.collect(Collectors.toList());
for (DefaultMutableTreeNode child : vehicleChildren) {
if (child.getUserObject().equals(resource)) {
return index;
}
index++;
}
return -1;
}
/**
* Creates a new vehicle node and adds it to the root node in alphabetical order.
*
* @param vehicleName The name of the vehicle and the user object of the new vehicle node
* @return The vehicle node
*/
private DefaultMutableTreeNode createNewVehicleNode(String vehicleName) {
boolean inserted = false;
DefaultMutableTreeNode vehicleNode = new DefaultMutableTreeNode(vehicleName);
for (int x = 0; x < root.getChildCount(); x++) {
DefaultMutableTreeNode currentNode = (DefaultMutableTreeNode) root.getChildAt(x);
//Insert node alphabetically
if (!inserted && vehicleName.compareTo((String) currentNode.getUserObject()) <= 0) {
insertNodeInto(vehicleNode, (MutableTreeNode) root, x);
inserted = true;
}
}
if (!inserted) {
insertNodeInto(vehicleNode, (MutableTreeNode) root, root.getChildCount());
}
return vehicleNode;
}
}

View File

@@ -0,0 +1,14 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.guing.plugins.panels.allocation;
/**
* Defines constants regarding internationalization.
*/
public interface I18nPlantOverviewPanelResourceAllocation {
/**
* The path to the project's resource bundle.
*/
String BUNDLE_PATH = "i18n/org/opentcs/plantoverview/resourceAllocationPanel/Bundle";
}

View File

@@ -0,0 +1,74 @@
<?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,1,44,0,0,1,-112"/>
</AuxValues>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/>
<SubComponents>
<Container class="javax.swing.JPanel" name="optionsPanel">
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout" value="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout$BorderConstraintsDescription">
<BorderConstraints direction="First"/>
</Constraint>
</Constraints>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
<SubComponents>
<Component class="javax.swing.JCheckBox" name="enableUpdatesCheckbox">
<Properties>
<Property name="selected" type="boolean" value="true"/>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="i18n/org/opentcs/plantoverview/resourceAllocationPanel/Bundle.properties" key="resourceAllocationPanel.checkBox_enableUpdates.text" replaceFormat="java.util.ResourceBundle.getBundle(&quot;{bundleNameSlashes}&quot;).getString(&quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="enableUpdatesCheckboxActionPerformed"/>
</Events>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="-1" gridY="-1" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="0.0" weightY="0.0"/>
</Constraint>
</Constraints>
</Component>
</SubComponents>
</Container>
<Container class="javax.swing.JScrollPane" name="allocationScrollPane">
<AuxValues>
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
</AuxValues>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout" value="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout$BorderConstraintsDescription">
<BorderConstraints direction="Center"/>
</Constraint>
</Constraints>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
<SubComponents>
<Component class="javax.swing.JTree" name="allocationTable">
<Properties>
<Property name="model" type="javax.swing.tree.TreeModel" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
<Connection code="new AllocationTreeModel()" type="code"/>
</Property>
<Property name="cellRenderer" type="javax.swing.tree.TreeCellRenderer" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
<Connection code="new AllocationTreeCellRenderer()" type="code"/>
</Property>
</Properties>
<AuxValues>
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="4"/>
</AuxValues>
</Component>
</SubComponents>
</Container>
</SubComponents>
</Form>

View File

@@ -0,0 +1,243 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.guing.plugins.panels.allocation;
import static java.util.Objects.requireNonNull;
import jakarta.inject.Inject;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import javax.swing.SwingUtilities;
import org.opentcs.access.SharedKernelServicePortal;
import org.opentcs.access.SharedKernelServicePortalProvider;
import org.opentcs.components.kernel.services.ServiceUnavailableException;
import org.opentcs.components.plantoverview.PluggablePanel;
import org.opentcs.customizations.ApplicationEventBus;
import org.opentcs.data.TCSObjectEvent;
import org.opentcs.data.model.Location;
import org.opentcs.data.model.Path;
import org.opentcs.data.model.Point;
import org.opentcs.data.model.TCSResourceReference;
import org.opentcs.data.model.Vehicle;
import org.opentcs.util.event.EventHandler;
import org.opentcs.util.event.EventSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* A panel to display the allocated resources of each vehicle with atleast one allocation.
*/
public class ResourceAllocationPanel
extends
PluggablePanel
implements
EventHandler {
/**
* This class' logger.
*/
private static final Logger LOG = LoggerFactory.getLogger(ResourceAllocationPanel.class);
/**
* The kernel to query allocations from.
*/
private final SharedKernelServicePortalProvider portalProvider;
/**
* Where we register for events.
*/
private final EventSource eventSource;
/**
* The client that is registered with the kernel provider.
*/
private SharedKernelServicePortal sharedPortal;
/**
* Whether this panel was initialized.
*/
private boolean initialized;
/**
* If the table model should update its contents if an event arrives.
*/
private boolean enableUpdates = true;
/**
* Creates a new instance.
*
* @param kernelProvider The kernel provider.
* @param eventSource Where this instance registers for events.
*/
@Inject
@SuppressWarnings("this-escape")
public ResourceAllocationPanel(
SharedKernelServicePortalProvider kernelProvider,
@ApplicationEventBus
EventSource eventSource
) {
this.portalProvider = requireNonNull(kernelProvider, "kernelProvider");
this.eventSource = requireNonNull(eventSource, "eventSource");
initComponents();
}
@Override
public void initialize() {
if (isInitialized()) {
LOG.debug("Already initialized - skipping.");
return;
}
// Register event listener in the kernel.
try {
sharedPortal = portalProvider.register();
}
catch (ServiceUnavailableException exc) {
LOG.warn("Kernel unavailable", exc);
return;
}
eventSource.subscribe(this);
// Trigger an update to the table model.
updateAllVehicleAllocations();
initialized = true;
}
@Override
public boolean isInitialized() {
return initialized;
}
@Override
public void terminate() {
if (!isInitialized()) {
LOG.debug("Already terminated - skipping.");
return;
}
// Remove event listener in the kernel.
eventSource.unsubscribe(this);
sharedPortal.close();
initialized = false;
}
@Override
public void onEvent(Object event) {
requireNonNull(event, "event");
//Skip event if we dont want any updates
if (!enableUpdates) {
return;
}
//Skip non object events as were only interested in vehicle updates
if (!(event instanceof TCSObjectEvent)) {
LOG.debug("Event is not a TCSObjectEvent, ignoring.");
return;
}
//Skip non vehicle events
TCSObjectEvent tcsObjectEvent = (TCSObjectEvent) event;
if (!(tcsObjectEvent.getCurrentOrPreviousObjectState() instanceof Vehicle)) {
LOG.debug("TCSObjectEvent is not about a Vehicle, ignoring.");
return;
}
SwingUtilities.invokeLater(
() -> handleVehicleStateChange((Vehicle) tcsObjectEvent.getCurrentOrPreviousObjectState())
);
}
private void updateAllVehicleAllocations() {
SwingUtilities.invokeLater(
() -> sharedPortal.getPortal().getVehicleService().fetchObjects(Vehicle.class).stream()
.forEach(this::handleVehicleStateChange)
);
}
/**
* Handles a vehicle update.
* Queries the kernel for the resource allocations of all vehicles and updates the table model.
*
* @param vehicle The vehicle which changed
*/
private void handleVehicleStateChange(Vehicle vehicle) {
((AllocationTreeModel) allocationTable.getModel()).updateAllocations(
vehicle.getName(),
vehicle.getAllocatedResources().stream()
.flatMap(set -> inClassOrder(set).stream())
.collect(Collectors.toList())
);
}
private List<TCSResourceReference<?>> inClassOrder(Set<TCSResourceReference<?>> resources) {
List<TCSResourceReference<?>> result = new ArrayList<>();
List<TCSResourceReference<?>> points = new ArrayList<>();
List<TCSResourceReference<?>> locations = new ArrayList<>();
resources.forEach(resource -> {
if (resource.getReferentClass() == Path.class) {
result.add(resource);
}
else if (resource.getReferentClass() == Point.class) {
points.add(resource);
}
else if (resource.getReferentClass() == Location.class) {
locations.add(resource);
}
});
result.addAll(points);
result.addAll(locations);
return result;
}
// 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.
*/
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
optionsPanel = new javax.swing.JPanel();
enableUpdatesCheckbox = new javax.swing.JCheckBox();
allocationScrollPane = new javax.swing.JScrollPane();
allocationTable = new javax.swing.JTree();
setLayout(new java.awt.BorderLayout());
optionsPanel.setLayout(new java.awt.GridBagLayout());
enableUpdatesCheckbox.setSelected(true);
java.util.ResourceBundle bundle = java.util.ResourceBundle.getBundle("i18n/org/opentcs/plantoverview/resourceAllocationPanel/Bundle"); // NOI18N
enableUpdatesCheckbox.setText(bundle.getString("resourceAllocationPanel.checkBox_enableUpdates.text")); // NOI18N
enableUpdatesCheckbox.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
enableUpdatesCheckboxActionPerformed(evt);
}
});
optionsPanel.add(enableUpdatesCheckbox, new java.awt.GridBagConstraints());
add(optionsPanel, java.awt.BorderLayout.PAGE_START);
allocationTable.setModel(new AllocationTreeModel());
allocationTable.setCellRenderer(new AllocationTreeCellRenderer());
allocationScrollPane.setViewportView(allocationTable);
add(allocationScrollPane, java.awt.BorderLayout.CENTER);
}// </editor-fold>//GEN-END:initComponents
// CHECKSTYLE:ON
// FORMATTER:ON
private void enableUpdatesCheckboxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_enableUpdatesCheckboxActionPerformed
enableUpdates = enableUpdatesCheckbox.isSelected();
}//GEN-LAST:event_enableUpdatesCheckboxActionPerformed
// FORMATTER:OFF
// CHECKSTYLE:OFF
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JScrollPane allocationScrollPane;
protected javax.swing.JTree allocationTable;
private javax.swing.JCheckBox enableUpdatesCheckbox;
private javax.swing.JPanel optionsPanel;
// End of variables declaration//GEN-END:variables
// CHECKSTYLE:ON
// FORMATTER:ON
}

View File

@@ -0,0 +1,25 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.guing.plugins.panels.allocation;
import org.opentcs.configuration.ConfigurationEntry;
import org.opentcs.configuration.ConfigurationPrefix;
/**
* Provides methods to configure the continuous load panel.
*/
@ConfigurationPrefix(ResourceAllocationPanelConfiguration.PREFIX)
public interface ResourceAllocationPanelConfiguration {
/**
* This configuration's prefix.
*/
String PREFIX = "resourceallocationpanel";
@ConfigurationEntry(
type = "Boolean",
description = "Whether to enable to register/enable the resource allocation panel.",
orderKey = "0_enable"
)
boolean enable();
}

View File

@@ -0,0 +1,61 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.guing.plugins.panels.allocation;
import static java.util.Objects.requireNonNull;
import static org.opentcs.guing.plugins.panels.allocation.I18nPlantOverviewPanelResourceAllocation.BUNDLE_PATH;
import jakarta.inject.Inject;
import jakarta.inject.Provider;
import java.util.ResourceBundle;
import org.opentcs.access.Kernel;
import org.opentcs.components.plantoverview.PluggablePanel;
import org.opentcs.components.plantoverview.PluggablePanelFactory;
/**
* Provides a {@link ResourceAllocationPanel} for the plant overview if the kernel is in operating
* state.
*/
public class ResourceAllocationPanelFactory
implements
PluggablePanelFactory {
/**
* This class's bundle.
*/
private final ResourceBundle bundle = ResourceBundle.getBundle(BUNDLE_PATH);
/**
* The provider for the panel this factory wants to create.
*/
private final Provider<ResourceAllocationPanel> panelProvider;
/**
* Creates a new instance.
*
* @param panelProvider the provider for the panel
*/
@Inject
public ResourceAllocationPanelFactory(Provider<ResourceAllocationPanel> panelProvider) {
this.panelProvider = requireNonNull(panelProvider, "panelProvider");
}
@Override
public boolean providesPanel(Kernel.State state) {
return (state == Kernel.State.OPERATING);
}
@Override
public String getPanelDescription() {
return bundle.getString("resourceAllocationPanelFactory.panelDescription");
}
@Override
public PluggablePanel createPanel(Kernel.State state) {
if (!providesPanel(state)) {
return null;
}
return panelProvider.get();
}
}

View File

@@ -0,0 +1,10 @@
# SPDX-FileCopyrightText: The openTCS Authors
# SPDX-License-Identifier: CC0-1.0
version = 1
[[annotations]]
path = ["**/*.gif", "**/*.jpg", "**/*.png", "**/*.svg"]
precedence = "closest"
SPDX-FileCopyrightText = "The openTCS Authors"
SPDX-License-Identifier = "CC-BY-4.0"

View File

@@ -0,0 +1,6 @@
# SPDX-FileCopyrightText: The openTCS Authors
# SPDX-License-Identifier: CC-BY-4.0
resourceAllocationPanel.checkBox_enableUpdates.text=Enable updates
resourceAllocationPanel.treeRoot.text=Vehicles
resourceAllocationPanelFactory.panelDescription=Resource allocation

View File

@@ -0,0 +1,6 @@
# SPDX-FileCopyrightText: The openTCS Authors
# SPDX-License-Identifier: CC-BY-4.0
resourceAllocationPanel.checkBox_enableUpdates.text=Aktualisierungen einschalten
resourceAllocationPanel.treeRoot.text=Fahrzeuge
resourceAllocationPanelFactory.panelDescription=Ressourcenzuweisung