Drop problems in multi-split container:
1/ Cannot drop content inside the content's node itself (e.g. top, left, bottom or righ side of the content leaf).
2/ Drop leaf does not always preserve its height or width after a drop.
Fix:
a/ MultiSplitDockableContainer.setConstraints(...)
// PAMFOLIO-2482 mydoggy: fix drop problems in multi-split container (drop inside same leaf, preserve leaf height or width)
protected DockableLeaf _dockableLeaf;
protected DockableLeaf _aggregationLeaf;
public void setConstraints(Dockable dockable,
Component content,
Dockable aggregationOnDockable,
int aggregationIndexLocation,
AggregationPosition aggregationPosition) {
boolean old = this.storeLayout;
storeLayout = false;
// PAMFOLIO-2482 mydoggy: fix drop problems in multi-split container (drop inside same leaf, preserve leaf height or width)
DockableLeaf oldDockableLeaf = _dockableLeaf;
DockableLeaf oldAggregationLeaf = _aggregationLeaf;
try {
// PAMFOLIO-2482 mydoggy: fix drop problems in multi-split container (drop inside same leaf, preserve leaf height or width)
_dockableLeaf = dockable == null ? null : getLeaf(dockable);
_aggregationLeaf = aggregationOnDockable == null ? null : getLeaf(aggregationOnDockable);
if (_dockableLeaf != null && _dockableLeaf == _aggregationLeaf && _dockableLeaf.getDockables().size() == 1) {
return;
}
removeDockable(dockable);
addDockable(dockable, content, aggregationOnDockable, aggregationIndexLocation, aggregationPosition);
} finally {
storeLayout = old;
// PAMFOLIO-2482 mydoggy: fix drop problems in multi-split container (drop inside same leaf, preserve leaf height or width)
_dockableLeaf = oldDockableLeaf;
_aggregationLeaf = oldAggregationLeaf;
}
}
b/ MultiSplitDockableContainer.validateModel(...)
protected void validateModel(Node root) {
if (root == null || !(root instanceof Split))
return;
List<Node> children = ((Split) root).getChildren();
double sum = 0.0;
for (Node node : children) {
if (!(node instanceof Divider)) {
sum += node.getWeight();
}
if (node instanceof Split) {
validateModel(node);
}
if (sum > 1.0d)
break;
}
if (sum != 1.0d) {
double w = 1.0 / ((children.size() / 2) + 1);
sum = 0;
for (int i = 0, size = children.size() - 1; i < size; i++) {
Node node = children.get(i);
// PAMFOLIO-2482 mydoggy: fix drop problems in multi-split container (drop inside same leaf, preserve leaf height or width)
// node.resetBounds();
if (!(node instanceof Divider)) {
node.setWeight(w);
sum += w;
}
}
Node lastNode = children.get(children.size() - 1);
// PAMFOLIO-2482 mydoggy: fix drop problems in multi-split container (drop inside same leaf, preserve leaf height or width)
// lastNode.resetBounds();
lastNode.setWeight(1.0d - sum);
multiSplitPane.getMultiSplitLayout().setFloatingDividers(true);
}
}
c/ MultiSplitDockableContainer.addDockable(...)
public void addDockable(Dockable dockable,
Component content,
Dockable aggregationOnDockable,
int aggregationIndexLocation,
AggregationPosition aggregationPosition) {
// Validate the model
if (!checkModel())
System.out.println("Check model fail. addDockable before");
if (entries.size() == 0) {
// Just one leaf
DockableLeaf leaf = new DockableLeaf(getNextLeanName(),
dockable.getId());
leaf.setWeight(1.0d);
multiSplitPaneModelRoot = leaf;
multiSplitPane.setModel(leaf);
multiSplitPane.add(getWrapperForComponent(dockable, content, Action.ADD_DOCK), "1");
setRootComponent(multiSplitPane);
SwingUtil.repaint(this);
} else {
boolean resetB = true;
byte[] oldModel = null;
if (dockable.equals(removedDockable)) {
oldModel = lastLayout;
removedDockable = null;
lastLayout = null;
}
boolean invalidAggregationPosition = false;
if (aggregationPosition == AggregationPosition.DEFAULT || aggregationPosition == null) {
invalidAggregationPosition = true;
aggregationPosition = defaultAggregationPosition;
}
if (multiSplitPaneModelRoot instanceof DockableLeaf) {
// The root is a leaf...
DockableLeaf rootLeaf = (DockableLeaf) multiSplitPaneModelRoot;
if (aggregationOnDockable != null && (aggregationPosition == null || invalidAggregationPosition)) {
// Aggregate to an already registered leaf
Component componentWrapper;
if (rootLeaf.getDockables().size() > 1) {
componentWrapper = multiSplitPane.getComponent(0);
} else {
Component rootLeafCmp = getComponentFromWrapper(multiSplitPane.getComponent(0));
multiSplitPane.removeAll();
componentWrapper = forceWrapperForComponent(entries.values().iterator().next().dockable, rootLeafCmp);
multiSplitPane.add(componentWrapper, rootLeaf.getName());
}
// The requeste is to add more than one dockable on the same leaf... no need to request a new leaf name
addToWrapper(componentWrapper, dockable, aggregationIndexLocation, content);
repaintMultiSplit(toolWindowManager.getClientProperty(MyDoggyKeySpace.PERSISTENCE_DELEGATE_PARSING) != null,
multiSplitPaneModelRoot);
rootLeaf.addDockable(dockable.getId());
} else {
// Create a new leaf...
DockableLeaf firstLeaf = rootLeaf;
DockableLeaf secondLeaf;
// Init two leafs
firstLeaf.setWeight(0.5);
secondLeaf = new DockableLeaf(getNextLeanName());
secondLeaf.setWeight(0.5);
// PAMFOLIO-2482 mydoggy: fix drop problems in multi-split container (drop inside same leaf, preserve leaf height or width)
secondLeaf.setBounds(firstLeaf.getBounds());
secondLeaf.addDockable(dockable.getId());
List<Node> children = null;
switch (aggregationPosition) {
case LEFT:
case TOP:
children = Arrays.asList(secondLeaf,
new Divider(),
firstLeaf);
break;
case RIGHT:
case BOTTOM:
children = Arrays.asList(firstLeaf,
new Divider(),
secondLeaf);
break;
}
boolean rowLayout = (aggregationPosition == AggregationPosition.LEFT || aggregationPosition == AggregationPosition.RIGHT);
Split split = new Split();
split.setRowLayout(rowLayout);
split.setBounds(split.getBounds());
split.setChildren(children);
// update the model
multiSplitPaneModelRoot = split;
if (!multiSplitPane.getMultiSplitLayout().getFloatingDividers())
multiSplitPane.getMultiSplitLayout().setFloatingDividers(true);
validateModel(multiSplitPaneModelRoot);
multiSplitPane.setModel(multiSplitPaneModelRoot);
// update the components in the container
Component wrapper;
if (rootLeaf.getDockables().size() > 1) {
wrapper = multiSplitPane.getComponent(0);
} else {
Dockable delegator = entries.values().iterator().next().dockable;
wrapper = getWrapperForComponent(delegator, getComponentFromWrapper(multiSplitPane.getComponent(0)), Action.ADD_DOCK);
}
multiSplitPane.removeAll();
multiSplitPane.add(wrapper, firstLeaf.getName());
multiSplitPane.add(getWrapperForComponent(dockable, content, Action.ADD_DOCK), secondLeaf.getName());
}
} else {
// Take the root, it's a split
Split splitRoot = (Split) multiSplitPaneModelRoot;
// Build content to add
boolean addCmp = true;
String leafName = null;
// Modify model
if (aggregationOnDockable != null) {
// Search for aggregationOnDockable leaf
Stack<Split> stack = new Stack<Split>();
stack.push(splitRoot);
while (!stack.isEmpty()) {
Split split = stack.pop();
for (Node child : split.getChildren()) {
if (child instanceof DockableLeaf) {
DockableLeaf leaf = (DockableLeaf) child;
// PAMFOLIO-2482 mydoggy: fix drop problems in multi-split container (drop inside same leaf, preserve leaf height or width)
// if (leaf.getDockables().contains(aggregationOnDockable.getId())) {
if (leaf == _aggregationLeaf || leaf.getDockables().contains(aggregationOnDockable.getId())) {
if (invalidAggregationPosition) {
// The requeste is to add more than one dockable on the same leaf...
addToWrapper(multiSplitPane.getMultiSplitLayout().getChildMap().get(leaf.getName()),
dockable,
aggregationIndexLocation,
content);
leaf.addDockable(dockable.getId());
addCmp = false;
resetB = false;
} else {
leafName = getNextLeanName();
boolean step1Failed = false;
// Check for concordance to leaf.getParent().isRowLayout and aggregationPosition
Split parent = leaf.getParent();
boolean rowLayout = parent.isRowLayout();
List<Node> parentChildren = parent.getChildren();
int startIndex = parentChildren.indexOf(leaf);
if (rowLayout) {
boolean finalize = false;
switch (aggregationPosition) {
case LEFT:
// PAMFOLIO-2482 mydoggy: fix drop problems in multi-split container (drop inside same leaf, preserve leaf height or width)
DockableLeaf newLeafLeft = new DockableLeaf(leafName, dockable.getId());
newLeafLeft.setBounds(leaf.getBounds());
newLeafLeft.setWeight(leaf.getWeight());
parentChildren.add(startIndex, newLeafLeft);
parentChildren.add(startIndex + 1, new Divider());
finalize = true;
break;
case RIGHT:
// PAMFOLIO-2482 mydoggy: fix drop problems in multi-split container (drop inside same leaf, preserve leaf height or width)
DockableLeaf newLeafRight = new DockableLeaf(leafName, dockable.getId());
newLeafRight.setBounds(leaf.getBounds());
newLeafRight.setWeight(leaf.getWeight());
parentChildren.add(startIndex + 1, new Divider());
parentChildren.add(startIndex + 2, newLeafRight);
finalize = true;
break;
default:
step1Failed = true;
}
if (finalize) {
// Set new children
forceWeight(parentChildren);
parent.setChildren(parentChildren);
}
} else {
boolean finalize = false;
switch (aggregationPosition) {
case TOP:
// PAMFOLIO-2482 mydoggy: fix drop problems in multi-split container (drop inside same leaf, preserve leaf height or width)
DockableLeaf newLeafTop = new DockableLeaf(leafName, dockable.getId());
newLeafTop.setBounds(leaf.getBounds());
newLeafTop.setWeight(leaf.getWeight());
parentChildren.add(startIndex, newLeafTop);
parentChildren.add(startIndex + 1, new Divider());
finalize = true;
break;
case BOTTOM:
// PAMFOLIO-2482 mydoggy: fix drop problems in multi-split container (drop inside same leaf, preserve leaf height or width)
DockableLeaf newLeafBottom = new DockableLeaf(leafName, dockable.getId());
newLeafBottom.setBounds(leaf.getBounds());
newLeafBottom.setWeight(leaf.getWeight());
parentChildren.add(startIndex + 1, new Divider());
parentChildren.add(startIndex + 2, newLeafBottom);
finalize = true;
break;
default:
step1Failed = true;
}
if (finalize) {
// Set new children
forceWeight(parentChildren);
parent.setChildren(parentChildren);
}
}
if (step1Failed) {
// Create two leafs
Leaf newleaf = new DockableLeaf(leafName, dockable.getId());
newleaf.setWeight(0.5);
// PAMFOLIO-2482 mydoggy: fix drop problems in multi-split container (drop inside same leaf, preserve leaf height or width)
newleaf.setBounds(leaf.getBounds());
newleaf.setWeight(leaf.getWeight());
// Creat the split
Split newSplit = new Split();
newSplit.setBounds(leaf.getBounds());
newSplit.setRowLayout((aggregationPosition == AggregationPosition.LEFT || aggregationPosition == AggregationPosition.RIGHT));
newSplit.setWeight(leaf.getWeight());
leaf.getParent().removeNode(leaf);
switch (aggregationPosition) {
case LEFT:
case TOP:
newSplit.setChildren(Arrays.asList(newleaf,
new Divider(),
leaf));
break;
default:
newSplit.setChildren(Arrays.asList(leaf,
new Divider(),
newleaf));
break;
}
leaf.setWeight(0.5);
// Switch the leaf with the new split
parentChildren.set(startIndex, newSplit);
parent.setChildren(parentChildren);
}
}
stack.clear();
break;
}
} else if (child instanceof Split) {
stack.push((Split) child);
}
}
}
if (!multiSplitPane.getMultiSplitLayout().getFloatingDividers())
multiSplitPane.getMultiSplitLayout().setFloatingDividers(true);
} else {
leafName = getNextLeanName();
boolean rowLayout = (aggregationPosition == AggregationPosition.LEFT || aggregationPosition == AggregationPosition.RIGHT);
if (splitRoot.isRowLayout() == rowLayout) {
List<Node> children = splitRoot.getChildren();
switch (aggregationPosition) {
case LEFT:
case TOP:
children.add(0, new DockableLeaf(leafName, dockable.getId()));
children.add(1, new Divider());
break;
case RIGHT:
case BOTTOM:
children.add(new Divider());
children.add(new DockableLeaf(leafName, dockable.getId()));
break;
}
forceWeight(children);
splitRoot.setChildren(children);
} else {
Split newRoot = new Split();
newRoot.setRowLayout(rowLayout);
newRoot.setBounds(multiSplitPaneModelRoot.getBounds());
Leaf leaf = new DockableLeaf(leafName, dockable.getId());
leaf.setWeight(0.5);
multiSplitPaneModelRoot.setWeight(0.5);
List<Node> children = null;
switch (aggregationPosition) {
case LEFT:
case TOP:
children = Arrays.asList(leaf,
new Divider(),
multiSplitPaneModelRoot);
break;
case RIGHT:
case BOTTOM:
children = Arrays.asList(multiSplitPaneModelRoot,
new Divider(),
leaf);
break;
}
forceWeight(children);
newRoot.setChildren(children);
multiSplitPaneModelRoot = newRoot;
}
if (!multiSplitPane.getMultiSplitLayout().getFloatingDividers())
multiSplitPane.getMultiSplitLayout().setFloatingDividers(true);
}
// }
validateModel(multiSplitPaneModelRoot);
multiSplitPane.setModel(multiSplitPaneModelRoot);
if (addCmp)
multiSplitPane.add(getWrapperForComponent(dockable, content, Action.ADD_DOCK), leafName);
}
if (!checkModel())
System.out.println("Check model fail. addDockable end");
if (storeLayout && oldModel != null) {
// Decode stored model
final Node decodedModel = decode(oldModel);
// jumpResetBounds = true;
multiSplitPane.getMultiSplitLayout().setFloatingDividers(false);
SwingUtilities.invokeLater(new Runnable() {
public void run() {
setMultiSplitLayout(decodedModel);
}
});
} else {
if (resetB) {
// PAMFOLIO-2482 mydoggy: fix drop problems in multi-split container (drop inside same leaf, preserve leaf height or width)
// Node split = getLeaf(dockable).getParent();
Node split = null;
DockableLeaf leaf = getLeaf(dockable);
if (leaf != null) {
split = leaf.getParent();
}
if (split == null)
split = multiSplitPaneModelRoot;
repaintMultiSplit(toolWindowManager.getClientProperty(MyDoggyKeySpace.PERSISTENCE_DELEGATE_PARSING) == null,
split);
} else {
repaintMultiSplit(false,
null);
}
}
}
entries.put(dockable, new DockableEntry(dockable, content));
}
d/ MultiSplitTabbedContentContainer.MultiSplitTabbedDockableDropPanel.drop(...), ca. line 319:
if (onIndex == -1) {
// PAMFOLIO-2482 mydoggy: fix drop problems in multi-split container (drop inside same leaf, preserve leaf height or width)
// rejectDrop = true;
} else {
Component onDockableContainer = getOnDockableContainer();
Thank you,
Pierre
Ciao Pierre,
can you send me directly the file?
Best,
./angelo