This commit is contained in:
16
opentcs-plantoverview-panel-resourceallocation/build.gradle
Normal file
16
opentcs-plantoverview-panel-resourceallocation/build.gradle
Normal 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
|
||||
}
|
||||
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
# SPDX-FileCopyrightText: The openTCS Authors
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
org.opentcs.guing.plugins.panels.allocation.AllocationPanelModule
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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";
|
||||
}
|
||||
@@ -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("{bundleNameSlashes}").getString("{key}")"/>
|
||||
</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>
|
||||
@@ -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
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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"
|
||||
@@ -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
|
||||
@@ -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
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 154 B |
Binary file not shown.
|
After Width: | Height: | Size: 147 B |
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
Reference in New Issue
Block a user