mirror of
https://github.com/bancika/diy-layout-creator
synced 2026-11-07 12:24:58 +10:00
show groups in explorer
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2025 held jointly by the individual authors.
|
||||
|
||||
This file is part of DIYLC.
|
||||
|
||||
DIYLC is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
DIYLC is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with DIYLC. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
package org.diylc.common;
|
||||
|
||||
import java.util.Set;
|
||||
import org.diylc.core.IDIYComponent;
|
||||
|
||||
/**
|
||||
* Interface for component grouping operations.
|
||||
*
|
||||
* @author Branislav Stojkovic
|
||||
*/
|
||||
public interface IGroupProcessor {
|
||||
|
||||
/**
|
||||
* Returns the set of component groups in the current project.
|
||||
* Each group is a set of components that are grouped together.
|
||||
*
|
||||
* @return set of component groups
|
||||
*/
|
||||
Set<Set<IDIYComponent<?>>> getComponentGroups();
|
||||
|
||||
/**
|
||||
* Groups all selected components.
|
||||
*/
|
||||
void groupSelectedComponents();
|
||||
|
||||
/**
|
||||
* Ungroups all selected components.
|
||||
*/
|
||||
void ungroupSelectedComponents();
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ import org.diylc.core.ExpansionMode;
|
||||
import org.diylc.core.IDIYComponent;
|
||||
import org.diylc.core.measures.Size;
|
||||
|
||||
public interface ISelectionProcessor {
|
||||
public interface ISelectionProcessor extends IGroupProcessor {
|
||||
|
||||
/**
|
||||
* Returns the current {@link ComponentTransferable}.
|
||||
@@ -89,16 +89,6 @@ public interface ISelectionProcessor {
|
||||
*/
|
||||
void rotateSelection(int direction);
|
||||
|
||||
/**
|
||||
* Groups all selected components.
|
||||
*/
|
||||
void groupSelectedComponents();
|
||||
|
||||
/**
|
||||
* Ungroups all selected components.
|
||||
*/
|
||||
void ungroupSelectedComponents();
|
||||
|
||||
/**
|
||||
* Mirrors selected components in the given axis.
|
||||
*
|
||||
|
||||
@@ -2912,4 +2912,9 @@ public class Presenter implements IPlugInPort {
|
||||
public DrawingManager getDrawingManager() {
|
||||
return drawingManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Set<IDIYComponent<?>>> getComponentGroups() {
|
||||
return currentProject.getGroups();
|
||||
}
|
||||
}
|
||||
|
||||
+318
-63
@@ -60,9 +60,10 @@ public class ExplorerPane extends JPanel {
|
||||
private JTextField searchField;
|
||||
private JScrollPane componentScrollPane;
|
||||
private ComponentListModel componentListModel;
|
||||
private JList<IDIYComponent<?>> componentList;
|
||||
private JList<ComponentGroupItem> componentList;
|
||||
private ComponentPopupMenu popupMenu;
|
||||
private JComboBox<Sort> sortBox;
|
||||
private ListSelectionListener selectionListener;
|
||||
|
||||
public ExplorerPane(ISwingUI swingUI, IPlugInPort plugInPort) {
|
||||
super();
|
||||
@@ -144,9 +145,9 @@ public class ExplorerPane extends JPanel {
|
||||
return componentScrollPane;
|
||||
}
|
||||
|
||||
public JList<IDIYComponent<?>> getComponentList() {
|
||||
public JList<ComponentGroupItem> getComponentList() {
|
||||
if (componentList == null) {
|
||||
componentList = new DragDropList<IDIYComponent<?>>(new IDragDropListListener() {
|
||||
componentList = new DragDropList<ComponentGroupItem>(new IDragDropListListener() {
|
||||
|
||||
@Override
|
||||
public boolean dropComplete(int selectedIndex, int dropTargetIndex) {
|
||||
@@ -154,7 +155,82 @@ public class ExplorerPane extends JPanel {
|
||||
swingUI.showMessage(REORDERING_NOT_POSSIBLE, "Error", ISwingUI.ERROR_MESSAGE);
|
||||
return false;
|
||||
}
|
||||
plugInPort.moveSelectionToZIndex(getComponentListModel().getSize() - dropTargetIndex);
|
||||
// The list is displayed in reverse order (highest z-index first, index 0 = last in component list)
|
||||
// Component list is in normal order (lowest z-index first, index 0 = first component)
|
||||
// In INSERT mode, dropTargetIndex is where the item will be inserted AFTER removal
|
||||
int listSize = getComponentListModel().getSize();
|
||||
int componentCount = plugInPort.getCurrentProject().getComponents().size();
|
||||
|
||||
// The list size may be different from component count due to groups
|
||||
// listSize = componentCount - groupedComponents + groups
|
||||
// We need to find which component will be at dropTargetIndex in the final list
|
||||
// and convert that to a component index
|
||||
|
||||
// Find the ComponentGroupItem that will be at dropTargetIndex after removal
|
||||
// We want to insert before the component that will be at dropTargetIndex after insertion
|
||||
List<ComponentGroupItem> components = getComponentListModel().getComponents();
|
||||
|
||||
int componentAtTargetListIndex;
|
||||
|
||||
if (dropTargetIndex >= listSize - 1) {
|
||||
// Dropping at the end
|
||||
plugInPort.moveSelectionToZIndex(componentCount);
|
||||
return true;
|
||||
} else if (selectedIndex < dropTargetIndex) {
|
||||
// Dragging up: removal happens before target
|
||||
// After removal, the component that was at dropTargetIndex is now at dropTargetIndex-1
|
||||
// After insertion at dropTargetIndex, it will be at dropTargetIndex+1
|
||||
// So we want to insert before the component currently at dropTargetIndex
|
||||
componentAtTargetListIndex = dropTargetIndex;
|
||||
} else {
|
||||
// Dragging down: removal happens after target
|
||||
// After removal, the component at dropTargetIndex stays at dropTargetIndex
|
||||
// After insertion at dropTargetIndex, it will be at dropTargetIndex+1
|
||||
// So we want to insert before the component currently at dropTargetIndex
|
||||
componentAtTargetListIndex = dropTargetIndex;
|
||||
}
|
||||
|
||||
if (componentAtTargetListIndex >= listSize) {
|
||||
// Insert at the end
|
||||
plugInPort.moveSelectionToZIndex(componentCount);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Get the ComponentGroupItem at that position
|
||||
ComponentGroupItem targetItem = components.get(componentAtTargetListIndex);
|
||||
|
||||
// Find the highest z-index component in this group (or the component itself if single)
|
||||
// Since the list is sorted by z-index (reversed), this is the component that determines
|
||||
// the position of this group in the list
|
||||
IDIYComponent<?> targetComponent = null;
|
||||
int maxComponentIndex = -1;
|
||||
List<IDIYComponent<?>> allComponents = plugInPort.getCurrentProject().getComponents();
|
||||
|
||||
for (IDIYComponent<?> comp : targetItem.getGroup()) {
|
||||
int compIndex = allComponents.indexOf(comp);
|
||||
if (compIndex > maxComponentIndex) {
|
||||
maxComponentIndex = compIndex;
|
||||
targetComponent = comp;
|
||||
}
|
||||
}
|
||||
|
||||
if (targetComponent == null || maxComponentIndex < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// We want to insert before the component at maxComponentIndex
|
||||
// moveSelectionToZIndex will automatically decrement zIndex for each selected component
|
||||
// that's before the target, so we can use maxComponentIndex directly
|
||||
// However, we need to add 1 because we want to insert at dropTargetIndex, not before it
|
||||
int targetComponentIndex = maxComponentIndex + 1;
|
||||
|
||||
if (targetComponentIndex < 0) {
|
||||
targetComponentIndex = 0;
|
||||
} else if (targetComponentIndex > componentCount) {
|
||||
targetComponentIndex = componentCount;
|
||||
}
|
||||
|
||||
plugInPort.moveSelectionToZIndex(targetComponentIndex);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
@@ -162,20 +238,28 @@ public class ExplorerPane extends JPanel {
|
||||
componentList.setFont(DEFAULT_FONT);
|
||||
componentList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
|
||||
componentList.setCellRenderer(new ComponentListCellRenderer(plugInPort.getComponentTypes()));
|
||||
componentList.addListSelectionListener(new ListSelectionListener() {
|
||||
selectionListener = new ListSelectionListener() {
|
||||
|
||||
@Override
|
||||
public void valueChanged(ListSelectionEvent e) {
|
||||
if (e.getValueIsAdjusting())
|
||||
return;
|
||||
|
||||
List<IDIYComponent<?>> selectedValuesList = componentList.getSelectedValuesList();
|
||||
if (selectedValuesList.size() > 0 && !new HashSet<IDIYComponent<?>>(selectedValuesList)
|
||||
List<ComponentGroupItem> selectedValuesList = componentList.getSelectedValuesList();
|
||||
Set<IDIYComponent<?>> expandedSelection = new HashSet<>();
|
||||
|
||||
for (ComponentGroupItem selected : selectedValuesList) {
|
||||
// Always add all components from the group item
|
||||
expandedSelection.addAll(selected.getGroup());
|
||||
}
|
||||
|
||||
if (expandedSelection.size() > 0 && !expandedSelection
|
||||
.equals(new HashSet<IDIYComponent<?>>(plugInPort.getSelectedComponents()))) {
|
||||
plugInPort.setSelection(selectedValuesList, true);
|
||||
plugInPort.setSelection(expandedSelection, true);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
componentList.addListSelectionListener(selectionListener);
|
||||
|
||||
componentList.addMouseListener(new MouseAdapter() {
|
||||
|
||||
@@ -205,8 +289,13 @@ public class ExplorerPane extends JPanel {
|
||||
if (plugInPort.getNewComponentTypeSlot() == null && (e.isPopupTrigger()
|
||||
|| (pressedEvent != null && pressedEvent.isPopupTrigger()))) {
|
||||
|
||||
final List<IDIYComponent<?>> selectedValues = componentList.getSelectedValuesList();
|
||||
getComponentPopupMenu().prepareAndShowAt(selectedValues, selectedValues, e.getX(),
|
||||
final List<ComponentGroupItem> selectedValues = componentList.getSelectedValuesList();
|
||||
// Extract actual components from selected items
|
||||
List<IDIYComponent<?>> components = new ArrayList<>();
|
||||
for (ComponentGroupItem item : selectedValues) {
|
||||
components.addAll(item.getGroup());
|
||||
}
|
||||
getComponentPopupMenu().prepareAndShowAt(components, components, e.getX(),
|
||||
e.getY());
|
||||
}
|
||||
}
|
||||
@@ -238,46 +327,94 @@ public class ExplorerPane extends JPanel {
|
||||
}
|
||||
|
||||
public void setSelection(Set<IDIYComponent<?>> selectedComponents) {
|
||||
List<IDIYComponent<?>> selectedValuesList = componentList.getSelectedValuesList();
|
||||
if (new HashSet<IDIYComponent<?>>(selectedValuesList)
|
||||
.equals(new HashSet<IDIYComponent<?>>(plugInPort.getSelectedComponents())))
|
||||
List<ComponentGroupItem> selectedValuesList = componentList.getSelectedValuesList();
|
||||
|
||||
// Extract components from selected values
|
||||
Set<IDIYComponent<?>> currentSelected = new HashSet<>();
|
||||
for (ComponentGroupItem item : selectedValuesList) {
|
||||
currentSelected.addAll(item.getGroup());
|
||||
}
|
||||
|
||||
if (currentSelected.equals(selectedComponents))
|
||||
return;
|
||||
|
||||
final JList<IDIYComponent<?>> list = this.getComponentList();
|
||||
final JList<ComponentGroupItem> list = this.getComponentList();
|
||||
|
||||
if (selectedComponents.size() == 0) {
|
||||
list.clearSelection();
|
||||
} else {
|
||||
// Temporarily remove listener to prevent infinite loop
|
||||
list.removeListSelectionListener(selectionListener);
|
||||
try {
|
||||
if (selectedComponents.size() == 0) {
|
||||
list.clearSelection();
|
||||
} else {
|
||||
// Build a map from component to its group (if any)
|
||||
Set<Set<IDIYComponent<?>>> groups = plugInPort.getComponentGroups();
|
||||
Map<IDIYComponent<?>, Set<IDIYComponent<?>>> componentToGroup = new java.util.HashMap<>();
|
||||
if (groups != null && !groups.isEmpty()) {
|
||||
for (Set<IDIYComponent<?>> group : groups) {
|
||||
for (IDIYComponent<?> component : group) {
|
||||
componentToGroup.put(component, group);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int[] indices = new int[selectedComponents.size()];
|
||||
int n = 0;
|
||||
List<IDIYComponent<?>> components = this.getComponentListModel().getComponents();
|
||||
for (int i = 0; i < components.size(); i++) {
|
||||
indices[n] = -1; // this should not happen
|
||||
if (selectedComponents.contains(components.get(i)))
|
||||
indices[n++] = i;
|
||||
if (n == indices.length)
|
||||
break;
|
||||
// Find indices of items to select
|
||||
List<ComponentGroupItem> components = this.getComponentListModel().getComponents();
|
||||
Set<Integer> selectedIndices = new HashSet<>();
|
||||
Set<Set<IDIYComponent<?>>> selectedGroups = new HashSet<>();
|
||||
|
||||
for (IDIYComponent<?> selected : selectedComponents) {
|
||||
Set<IDIYComponent<?>> group = componentToGroup.get(selected);
|
||||
if (group != null) {
|
||||
// Component is in a group
|
||||
if (!selectedGroups.contains(group)) {
|
||||
// Find the ComponentGroupItem for this group
|
||||
for (int i = 0; i < components.size(); i++) {
|
||||
ComponentGroupItem groupItem = components.get(i);
|
||||
if (groupItem.getGroup().equals(group)) {
|
||||
selectedIndices.add(i);
|
||||
selectedGroups.add(group);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Component is not in any group, find the ComponentGroupItem that contains only this component
|
||||
for (int i = 0; i < components.size(); i++) {
|
||||
ComponentGroupItem groupItem = components.get(i);
|
||||
if (groupItem.getGroup().size() == 1 && groupItem.getGroup().contains(selected)) {
|
||||
selectedIndices.add(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int[] indices = selectedIndices.stream().mapToInt(i -> i).toArray();
|
||||
|
||||
list.getSelectionModel().setValueIsAdjusting(true);
|
||||
list.setSelectedIndices(indices);
|
||||
list.getSelectionModel().setValueIsAdjusting(false);
|
||||
if (indices.length > 0) {
|
||||
int firstVisibleIndex = list.getFirstVisibleIndex();
|
||||
int lastVisibleIndex = list.getLastVisibleIndex();
|
||||
// if none of the selected items is visible, jump to the first one
|
||||
if (!Arrays.stream(indices)
|
||||
.anyMatch(index -> firstVisibleIndex <= index && index <= lastVisibleIndex))
|
||||
list.ensureIndexIsVisible(indices[0]);
|
||||
}
|
||||
}
|
||||
|
||||
list.getSelectionModel().setValueIsAdjusting(true);
|
||||
list.setSelectedIndices(indices);
|
||||
list.getSelectionModel().setValueIsAdjusting(false);
|
||||
int firstVisibleIndex = list.getFirstVisibleIndex();
|
||||
int lastVisibleIndex = list.getFirstVisibleIndex();
|
||||
// if none of the selected items is visible, jump to the first one
|
||||
if (!Arrays.stream(indices)
|
||||
.anyMatch(index -> firstVisibleIndex <= index && index <= lastVisibleIndex))
|
||||
list.ensureIndexIsVisible(indices[0]);
|
||||
} finally {
|
||||
// Re-add listener
|
||||
list.addListSelectionListener(selectionListener);
|
||||
}
|
||||
}
|
||||
|
||||
private class ComponentListModel extends AbstractListModel<IDIYComponent<?>> {
|
||||
private class ComponentListModel extends AbstractListModel<ComponentGroupItem> {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private List<IDIYComponent<?>> componentsRaw;
|
||||
private List<IDIYComponent<?>> components;
|
||||
private List<ComponentGroupItem> components;
|
||||
|
||||
private String searchText;
|
||||
private Sort sort = Sort.Z_INDEX;
|
||||
@@ -289,7 +426,7 @@ public class ExplorerPane extends JPanel {
|
||||
refresh(oldSize);
|
||||
}
|
||||
|
||||
public List<IDIYComponent<?>> getComponents() {
|
||||
public List<ComponentGroupItem> getComponents() {
|
||||
return components;
|
||||
}
|
||||
|
||||
@@ -310,27 +447,32 @@ public class ExplorerPane extends JPanel {
|
||||
}
|
||||
|
||||
private void refresh(int oldSize) {
|
||||
List<IDIYComponent<?>> sortedComponents;
|
||||
|
||||
if (sort == Sort.NAME) {
|
||||
this.components =
|
||||
sortedComponents =
|
||||
componentsRaw.stream().sorted(Comparator.comparing(x -> x.toString().toLowerCase()))
|
||||
.collect(Collectors.toList());
|
||||
} else if (sort == Sort.TYPE) {
|
||||
this.components = componentsRaw.stream()
|
||||
sortedComponents = componentsRaw.stream()
|
||||
.sorted(Comparator.comparing(x -> x.getClass().getName().toLowerCase())
|
||||
.thenComparing(x -> x.toString().toLowerCase()))
|
||||
.collect(Collectors.toList());
|
||||
} else {
|
||||
List<IDIYComponent<?>> componentsClone = new ArrayList<IDIYComponent<?>>(componentsRaw);
|
||||
Collections.reverse(componentsClone);
|
||||
this.components = componentsClone;
|
||||
sortedComponents = componentsClone;
|
||||
}
|
||||
|
||||
if (searchText != null && !searchText.trim().isEmpty()) {
|
||||
this.components = this.components.stream().filter(component -> {
|
||||
sortedComponents = sortedComponents.stream().filter(component -> {
|
||||
return component.getName().toLowerCase().contains(searchText);
|
||||
}).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
// Build list with groups and ungrouped components
|
||||
this.components = buildComponentListWithGroups(sortedComponents);
|
||||
|
||||
int newSize = this.components.size();
|
||||
|
||||
fireContentsChanged(this, 0, Math.min(newSize, oldSize));
|
||||
@@ -339,6 +481,49 @@ public class ExplorerPane extends JPanel {
|
||||
else if (newSize > oldSize)
|
||||
fireIntervalAdded(this, oldSize, newSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the component list, using ComponentGroupItem for all items.
|
||||
* For grouped components, creates one ComponentGroupItem per group.
|
||||
* For ungrouped components, creates a ComponentGroupItem with a single component.
|
||||
*/
|
||||
private List<ComponentGroupItem> buildComponentListWithGroups(List<IDIYComponent<?>> sortedComponents) {
|
||||
Set<Set<IDIYComponent<?>>> groups = plugInPort.getComponentGroups();
|
||||
|
||||
// Build a map from component to its group (if any)
|
||||
Map<IDIYComponent<?>, Set<IDIYComponent<?>>> componentToGroup = new java.util.HashMap<>();
|
||||
if (groups != null && !groups.isEmpty()) {
|
||||
for (Set<IDIYComponent<?>> group : groups) {
|
||||
for (IDIYComponent<?> component : group) {
|
||||
componentToGroup.put(component, group);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Track which groups we've already added
|
||||
Set<Set<IDIYComponent<?>>> addedGroups = new HashSet<>();
|
||||
List<ComponentGroupItem> result = new ArrayList<>();
|
||||
|
||||
for (IDIYComponent<?> component : sortedComponents) {
|
||||
Set<IDIYComponent<?>> group = componentToGroup.get(component);
|
||||
if (group == null) {
|
||||
// Component is not in any group, create a ComponentGroupItem with just this component
|
||||
Set<IDIYComponent<?>> singleComponentGroup = new HashSet<>();
|
||||
singleComponentGroup.add(component);
|
||||
result.add(new ComponentGroupItem(singleComponentGroup));
|
||||
} else {
|
||||
// Component is in a group
|
||||
if (!addedGroups.contains(group)) {
|
||||
// This is the first component from this group we've seen, add the group item
|
||||
result.add(new ComponentGroupItem(group));
|
||||
addedGroups.add(group);
|
||||
}
|
||||
// Otherwise, skip this component as we already have a group item for it
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSize() {
|
||||
@@ -346,12 +531,12 @@ public class ExplorerPane extends JPanel {
|
||||
}
|
||||
|
||||
@Override
|
||||
public IDIYComponent<?> getElementAt(int index) {
|
||||
public ComponentGroupItem getElementAt(int index) {
|
||||
return this.components.get(index);
|
||||
}
|
||||
}
|
||||
|
||||
private static class ComponentListCellRenderer implements ListCellRenderer<IDIYComponent<?>> {
|
||||
private static class ComponentListCellRenderer implements ListCellRenderer<ComponentGroupItem> {
|
||||
|
||||
// private static Color[] layerColors = new Color[] { Color.gray, Color.decode("#ff6363"),
|
||||
// Color.decode("#293462"), Color.decode("#138588"),
|
||||
@@ -367,32 +552,63 @@ public class ExplorerPane extends JPanel {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getListCellRendererComponent(JList<? extends IDIYComponent<?>> list,
|
||||
IDIYComponent<?> value, int index, boolean isSelected, boolean cellHasFocus) {
|
||||
|
||||
ComponentType componentType = componentTypes.get(value.getClass().getCanonicalName());
|
||||
public Component getListCellRendererComponent(JList<? extends ComponentGroupItem> list,
|
||||
ComponentGroupItem value, int index, boolean isSelected, boolean cellHasFocus) {
|
||||
|
||||
JLabel renderer = (JLabel) defaultRenderer.getListCellRendererComponent(list, value, index,
|
||||
isSelected, cellHasFocus);
|
||||
|
||||
int layerId = (int) Math.round(componentType.getZOrder());
|
||||
ComponentGroupItem groupItem = value;
|
||||
|
||||
if (groupItem.getComponentCount() == 1) {
|
||||
// Render as individual component (ungrouped)
|
||||
IDIYComponent<?> component = groupItem.getGroup().iterator().next();
|
||||
ComponentType componentType = componentTypes.get(component.getClass().getCanonicalName());
|
||||
|
||||
if (componentType == null) {
|
||||
renderer.setText(component.toString());
|
||||
return renderer;
|
||||
}
|
||||
|
||||
String valueForDisplay = value.getValueForDisplay();
|
||||
if (isSelected) {
|
||||
if (valueForDisplay == null || valueForDisplay.trim().isEmpty()) {
|
||||
renderer.setText(String.format("[L%s] %s", layerId, value.getName()));
|
||||
int layerId = (int) Math.round(componentType.getZOrder());
|
||||
|
||||
String valueForDisplay = component.getValueForDisplay();
|
||||
if (isSelected) {
|
||||
if (valueForDisplay == null || valueForDisplay.trim().isEmpty()) {
|
||||
renderer.setText(String.format("[L%s] %s", layerId, component.getName()));
|
||||
} else {
|
||||
renderer
|
||||
.setText(String.format("[L%s] %s (%s)", layerId, component.getName(), valueForDisplay));
|
||||
}
|
||||
} else {
|
||||
renderer
|
||||
.setText(String.format("[L%s] %s (%s)", layerId, value.getName(), valueForDisplay));
|
||||
if (valueForDisplay == null || valueForDisplay.trim().isEmpty()) {
|
||||
renderer.setText(String.format("<html><font color='#c0c0c0'>[L%s]</font> %s</html>",
|
||||
layerId, component.getName()));
|
||||
} else {
|
||||
renderer.setText(String.format(
|
||||
"<html><font color='#c0c0c0'>[L%s]</font> %s (<font color='#666666'>%s</font>)</html>",
|
||||
layerId, component.getName(), valueForDisplay));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (valueForDisplay == null || valueForDisplay.trim().isEmpty()) {
|
||||
renderer.setText(String.format("<html><font color='#c0c0c0'>[L%s]</font> %s</html>",
|
||||
layerId, value.getName()));
|
||||
// Render as group
|
||||
// Calculate maximum layer from components in the group
|
||||
int maxLayerId = 0;
|
||||
for (IDIYComponent<?> component : groupItem.getGroup()) {
|
||||
ComponentType componentType = componentTypes.get(component.getClass().getCanonicalName());
|
||||
if (componentType != null) {
|
||||
int layerId = (int) Math.round(componentType.getZOrder());
|
||||
if (layerId > maxLayerId) {
|
||||
maxLayerId = layerId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String text = "Group of " + groupItem.getComponentCount() + " components";
|
||||
if (isSelected) {
|
||||
renderer.setText(String.format("<html>[L%s] <b>%s</b></html>", maxLayerId, text));
|
||||
} else {
|
||||
renderer.setText(String.format(
|
||||
"<html><font color='#c0c0c0'>[L%s]</font> %s (<font color='#666666'>%s</font>)</html>",
|
||||
layerId, value.getName(), valueForDisplay));
|
||||
renderer.setText(String.format("<html><font color='#c0c0c0'>[L%s]</font> %s</html>", maxLayerId, text));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -414,4 +630,43 @@ public class ExplorerPane extends JPanel {
|
||||
return LangUtil.translate(label);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper class to represent a group of components in the explorer list.
|
||||
*/
|
||||
public static class ComponentGroupItem {
|
||||
private final Set<IDIYComponent<?>> group;
|
||||
|
||||
public ComponentGroupItem(Set<IDIYComponent<?>> group) {
|
||||
this.group = group;
|
||||
}
|
||||
|
||||
public Set<IDIYComponent<?>> getGroup() {
|
||||
return group;
|
||||
}
|
||||
|
||||
public int getComponentCount() {
|
||||
return group.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Group of " + group.size() + " components";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null || getClass() != obj.getClass())
|
||||
return false;
|
||||
ComponentGroupItem other = (ComponentGroupItem) obj;
|
||||
return group.equals(other.group);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return group.hashCode();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user