in java/form/src/org/netbeans/modules/form/layoutdesign/LayoutFeeder.java [4447:4791]
private void mergeInclusionsInCommonSequence(IncludeDesc iDesc1, IncludeDesc iDesc2, LayoutInterval commonGroup) {
boolean more;
do {
more = false;
int startIndex = 0;
LayoutInterval ext1 = null;
int depth1 = 0;
boolean startGap = false;
int endIndex = 0;
LayoutInterval ext2 = null;
int depth2 = 0;
boolean endGap = false;
boolean goingParallel = false;
if (commonGroup.isSequential()) {
if (commonGroup.isParentOf(iDesc1.parent)) {
startIndex = LayoutInterval.getIndexInParent(iDesc1.parent, commonGroup);
depth1 = 1;
ext1 = intervalToExtractIntoCommonSequence(iDesc1, commonGroup);
if (ext1 != null) {
int d = LayoutInterval.getDepthInParent(iDesc1.parent, ext1);
if (d > 0) {
depth1 += d;
}
}
if (dragger.isResizing(dimension)) {
LayoutInterval inSequence = (iDesc1.parent.isSequential() && !iDesc1.newSubGroup)
? iDesc1.parent : iDesc1.neighbor;
if (inSequence != null && LayoutUtils.contentOverlap(addingSpace, inSequence, dimension)) {
goingParallel = true; // resizing in parallel with original sequence
}
}
} else {
startIndex = iDesc1.index;
if (iDesc1.snappedParallel != null && commonGroup.isParentOf(iDesc1.snappedParallel)
&& iDesc1.newSubGroup && dragger.isResizing(dimension)) {
startIndex = LayoutInterval.getIndexInParent(iDesc1.snappedParallel, commonGroup);
} else {
if (startIndex == commonGroup.getSubIntervalCount()) {
startIndex--;
}
startGap = commonGroup.getSubInterval(startIndex).isEmptySpace();
}
}
if (commonGroup.isParentOf(iDesc2.parent)) {
endIndex = LayoutInterval.getIndexInParent(iDesc2.parent, commonGroup);
depth2 = 1;
ext2 = intervalToExtractIntoCommonSequence(iDesc2, commonGroup);
if (ext2 != null) {
int d = LayoutInterval.getDepthInParent(iDesc2.parent, ext2);
if (d > 0) {
depth2 += d;
}
}
if (dragger.isResizing(dimension)) {
LayoutInterval inSequence = (iDesc2.parent.isSequential() && !iDesc2.newSubGroup)
? iDesc2.parent : iDesc2.neighbor;
if (inSequence != null && LayoutUtils.contentOverlap(addingSpace, inSequence, dimension)) {
goingParallel = true; // resizing in parallel with original sequence
}
}
} else {
endIndex = iDesc2.index;
if (iDesc2.snappedParallel != null && commonGroup.isParentOf(iDesc2.snappedParallel)) {
if (iDesc2.newSubGroup && dragger.isResizing(dimension)) {
endIndex = LayoutInterval.getIndexInParent(iDesc2.snappedParallel, commonGroup);
}
if (endIndex == commonGroup.getSubIntervalCount()) {
endIndex--;
}
} else if (endIndex > 0) {
endGap = commonGroup.getSubInterval(--endIndex).isEmptySpace();
}
}
}
boolean validSection = (endIndex > startIndex + 1 || (endIndex == startIndex+1
&& (!startGap || iDesc1.snappedParallel != null) && (!endGap || iDesc2.snappedParallel != null)));
if (validSection && (ext1 != null || ext2 != null)) {
// there is a significant part of the common sequence to be parallelized
LayoutInterval extSeq = new LayoutInterval(SEQUENTIAL);
LayoutInterval startInt = commonGroup.getSubInterval(startIndex);
LayoutInterval endInt = commonGroup.getSubInterval(endIndex);
int posL = LayoutUtils.getVisualPosition(startInt, dimension, LEADING);
int posT = LayoutUtils.getVisualPosition(endInt, dimension, TRAILING);
// check visual overlap of the extracted intervals with the part of the sequence
LayoutInterval parConnectingGap = null;
LayoutInterval extConnectingGap = null;
// temporarily remove ext1 and ext2 for analysis
LayoutInterval parent1, parent2;
int idx1, idx2;
if (ext1 != null) {
parent1 = ext1.getParent();
idx1 = parent1.remove(ext1);
} else {
parent1 = null; idx1 = -1;
}
if (ext2 != null) {
parent2 = ext2.getParent();
idx2 = parent2.remove(ext2);
} else {
parent2 = null; idx2 = -1;
}
// Check if can extract ext1 and ext2 in parallel with whole sub-sequence
// from startIndex to endIndex, or just with the first/last interval at
// startIndex or endIndex (due to orthogonal overlap of ext1/ext2 with
// something from the sequence).
if (ext1 != null
&& !LayoutInterval.isClosedGroup(startInt, TRAILING)
&& LayoutUtils.contentOverlap(ext1, commonGroup, startIndex+1, endIndex, dimension^1)
&& !LayoutUtils.contentOverlap(startInt, commonGroup, startIndex+1, endIndex, dimension^1)) {
while (startIndex < endIndex) {
layoutModel.addInterval(layoutModel.removeInterval(commonGroup, startIndex+1), extSeq, -1);
endIndex--;
}
if (extSeq.getSubIntervalCount() > 0) {
LayoutInterval li = extSeq.getSubInterval(extSeq.getSubIntervalCount()-1);
if (li.isEmptySpace()) { // cut everything after startInt, so at least clone the last gap
parConnectingGap = LayoutInterval.cloneInterval(li, null);
}
li = extSeq.getSubInterval(0);
if (li.isEmptySpace()) {
extConnectingGap = li;
}
}
if (ext2 != null) {
parent2.add(ext2, idx2);
ext2 = null; // don't extract ext2 in this round (its parent just moved to extSeq)
if (depth2 == 1) {
depth2 = 2; // don't adjust iDesc2 and do one more round
}
}
} else if (ext2 != null
&& !LayoutInterval.isClosedGroup(endInt, LEADING)
&& LayoutUtils.contentOverlap(ext2, commonGroup, startIndex, endIndex-1, dimension^1)
&& !LayoutUtils.contentOverlap(endInt, commonGroup, startIndex, endIndex-1, dimension^1)) {
while (startIndex < endIndex) {
layoutModel.addInterval(layoutModel.removeInterval(commonGroup, startIndex), extSeq, -1);
endIndex--;
}
if (extSeq.getSubIntervalCount() > 0) {
LayoutInterval li = extSeq.getSubInterval(0);
if (li.isEmptySpace()) { // cut everything before endInt, so at least clone the first gap
parConnectingGap = LayoutInterval.cloneInterval(li, null);
}
li = extSeq.getSubInterval(extSeq.getSubIntervalCount()-1);
if (li.isEmptySpace()) {
extConnectingGap = li;
}
}
if (ext1 != null) {
parent1.add(ext1, idx1);
ext1 = null; // don't extract ext1 in this round (its parent just moved to extSeq)
if (depth1 == 1) {
depth1 = 2; // don't adjust iDesc1 and do one more round
}
}
}
// return back ext1 and ext2
if (ext1 != null) {
parent1.add(ext1, idx1);
}
if (ext2 != null) {
parent2.add(ext2, idx2);
}
LayoutInterval parGroup;
if (startIndex == 0 && endIndex == commonGroup.getSubIntervalCount()-1) {
// parallel with whole sequence
parGroup = commonGroup.getParent();
} else { // separate part of the original sequence
parGroup = new LayoutInterval(PARALLEL);
LayoutInterval parSeq = new LayoutInterval(SEQUENTIAL);
parGroup.add(parSeq, 0);
parGroup.getCurrentSpace().set(dimension, posL, posT);
while (startIndex <= endIndex) {
layoutModel.addInterval(layoutModel.removeInterval(commonGroup, startIndex), parSeq, -1);
endIndex--;
}
layoutModel.addInterval(parGroup, commonGroup, startIndex);
}
layoutModel.addInterval(extSeq, parGroup, -1);
if (ext1 != null) {
LayoutInterval parent = ext1.getParent();
layoutModel.removeInterval(ext1);
if (LayoutInterval.hasAnyResizingNeighbor(parent, TRAILING)
&& LayoutInterval.getCount(parent, TRAILING, true) > 0
&& !LayoutInterval.wantResize(parent)) {
operations.maintainSize(parent, LayoutInterval.wantResize(ext1), dimension, false);
}
if (parent.getSubIntervalCount() == 1) {
LayoutInterval last = layoutModel.removeInterval(parent, 0);
operations.addContent(last, parent.getParent(), layoutModel.removeInterval(parent), dimension);
if (parent == startInt) {
startInt = last;
}
}
int beforeCount = extSeq.getSubIntervalCount();
operations.addContent(ext1, extSeq, 0, dimension);
if (depth1 == 1 && !iDesc1.parent.isSequential()) {
iDesc1.index = extSeq.getSubIntervalCount() - beforeCount;
}
if (depth2 <= 1) {
if (ext2 == null || !iDesc2.parent.isSequential()) {
iDesc2.index = extSeq.getSubIntervalCount();
} else {
iDesc2.index += extSeq.getSubIntervalCount();
}
}
if (ext2 != null) {
LayoutInterval gap = new LayoutInterval(SINGLE);
int size = LayoutRegion.distance(ext1.getCurrentSpace(), ext2.getCurrentSpace(), dimension, LEADING, TRAILING);
gap.setSize(size);
layoutModel.addInterval(gap, extSeq, -1);
} else { // could have moved things next to startInt to extSeq
if (parConnectingGap != null) {
parent = startInt.getParent();
if (!parent.isSequential()) {
LayoutInterval seq = new LayoutInterval(SEQUENTIAL);
layoutModel.addInterval(seq, parent, layoutModel.removeInterval(startInt));
layoutModel.addInterval(startInt, seq, 0);
parent = seq;
}
assert parent.indexOf(startInt) == 0;
layoutModel.addInterval(parConnectingGap, parent, 1);
}
if (extConnectingGap != null) {
operations.accommodateGap(extConnectingGap, dimension);
if (LayoutInterval.wantResize(startInt) && !LayoutInterval.wantResize(extSeq)) {
operations.setIntervalResizing(extConnectingGap, true);
}
}
}
} else {
iDesc1.index = 0;
if (depth2 <= 1 && !iDesc2.parent.isSequential()) {
iDesc2.index = extSeq.getSubIntervalCount();
}
}
if (ext2 != null) {
LayoutInterval parent = ext2.getParent();
if (ext2.getAlignment() == TRAILING) {
extSeq.setAlignment(TRAILING);
}
layoutModel.removeInterval(ext2);
if (LayoutInterval.hasAnyResizingNeighbor(parent, LEADING)
&& LayoutInterval.getCount(parent, LEADING, true) > 0
&& !LayoutInterval.wantResize(parent)) {
operations.maintainSize(parent, LayoutInterval.wantResize(ext2), dimension, false);
}
if (parent.getSubIntervalCount() == 1) {
LayoutInterval last = layoutModel.removeInterval(parent, 0);
operations.addContent(last, parent.getParent(), layoutModel.removeInterval(parent), dimension);
if (parent == endInt) {
endInt = last;
}
}
operations.addContent(ext2, extSeq, -1, dimension);
if (ext1 == null) { // could have moved things next to endInt to extSeq
if (parConnectingGap != null) {
parent = endInt.getParent();
if (!parent.isSequential()) {
LayoutInterval seq = new LayoutInterval(SEQUENTIAL);
layoutModel.addInterval(seq, parent, layoutModel.removeInterval(endInt));
layoutModel.addInterval(endInt, seq, 0);
parent = seq;
}
assert parent.indexOf(endInt) == 0;
layoutModel.addInterval(parConnectingGap, parent, 0);
}
if (extConnectingGap != null) {
operations.accommodateGap(extConnectingGap, dimension);
if (LayoutInterval.wantResize(endInt) && !LayoutInterval.wantResize(extSeq)) {
operations.setIntervalResizing(extConnectingGap, true);
}
}
}
}
if (depth1 <= 1) {
boolean newSubGroupBeforeMerge = iDesc1.parent == commonGroup && iDesc1.newSubGroup;
iDesc1.parent = extSeq;
if (iDesc2.newSubGroup) {
iDesc1.newSubGroup = true;
} else if (newSubGroupBeforeMerge) {
iDesc1.newSubGroup = false; // actually just created the sub-group
}
iDesc1.neighbor = null;
}
if (depth2 <= 1) {
iDesc2.parent = extSeq;
if (iDesc1.newSubGroup) {
iDesc2.newSubGroup = true;
}
iDesc2.neighbor = null;
}
commonGroup = extSeq;
more = depth1 > 1 || depth2 > 1;
optimizeStructure = true;
} else if (ext1 == null && ext2 == null && validSection) {
// nothing to extract, but the resizing interval still to be in
// parallel with part of the sequence
if (commonGroup.isParentOf(iDesc1.parent)) {
iDesc1.index = startIndex;
}
if (commonGroup.isParentOf(iDesc2.parent)) {
iDesc2.index = endIndex;
}
iDesc1.parent = iDesc2.parent = commonGroup;
iDesc1.newSubGroup = iDesc2.newSubGroup = true;
iDesc1.neighbor = iDesc2.neighbor = null;
} else {
// prefer sub-group in case of end position, outer group in case
// of resizing in parallel with sub-group
boolean p1 = iDesc1.parent.isParentOf(iDesc2.parent);
boolean p2 = iDesc2.parent.isParentOf(iDesc1.parent);
if ((p2 && !goingParallel) || (p1 && goingParallel)) {
iDesc2.parent = iDesc1.parent;
iDesc2.index = iDesc1.index;
iDesc2.newSubGroup = iDesc1.newSubGroup;
iDesc2.neighbor = iDesc1.neighbor;
if (endGap) // there's an outer gap
iDesc2.fixedPosition = false;
} else if ((p1 && !goingParallel) || (p2 && goingParallel)) {
iDesc1.parent = iDesc2.parent;
iDesc1.index = iDesc2.index;
iDesc1.newSubGroup = iDesc2.newSubGroup;
iDesc1.neighbor = iDesc2.neighbor;
if (startGap) // there's an outer gap
iDesc1.fixedPosition = false;
}
}
} while (more);
// might originally be snapped to a group that has just been optimized out
// [TODO better would be to subst. it with a representative component]
if (iDesc1.snappedParallel != null && iDesc1.snappedParallel.isParallel() && iDesc1.snappedParallel.getSubIntervalCount() == 0) {
iDesc1.snappedParallel = null;
}
if (iDesc2.snappedParallel != null && iDesc2.snappedParallel.isParallel() && iDesc2.snappedParallel.getSubIntervalCount() == 0) {
iDesc2.snappedParallel = null;
}
}