📄 blockmetrics.java
字号:
if (curAnn.realWidth > availableWidth) { if (interlinearizer.getAlignmentUnit() == Interlinear.PIXELS) { splitAnnotation(curAnn, availableWidth, fontMetrics); } else { splitAnnotation(curAnn, availableWidth); } } } allNodes.add(curNode); } // printoutNode(rootNode); // next update calculated widths, the iteration is starting at the bottom // note: you cannot reliably call getChildCount from within an enumeration... //for (int i = 0; i < allNodes.size(); i++) { for (int i = allNodes.size() - 1; i >= 0; i--) { curNode = (DefaultMutableTreeNode) allNodes.get(i); curAnn = (InterlinearAnnotation) curNode.getUserObject(); if (curNode.getChildCount() == 0) { continue; } if (curNode.getChildCount() == 1) { otherNode = (DefaultMutableTreeNode) curNode.getFirstChild(); otherAnn = (InterlinearAnnotation) otherNode.getUserObject(); // don't change the size of a multiple line annotation if ((otherAnn.calcWidth > curAnn.calcWidth) && (curAnn.nrOfLines == 1)) { curAnn.calcWidth = otherAnn.calcWidth; } else if ((otherAnn.calcWidth < curAnn.calcWidth) && (otherAnn.nrOfLines == 1)) { otherAnn.calcWidth = curAnn.calcWidth; propagateSizeDown(otherNode); } } else { // more than one child, can be on several tiers propagateSizeDown(curNode); } } // printoutNode(rootNode); // calculate horizontal positions within the root annotation block, // where the root, visible or not, starts at x = 0, and annotations // inherit positions. Start at top node and propagate downward for (int i = 0; i < allNodes.size(); i++) { curNode = (DefaultMutableTreeNode) allNodes.get(i); if (i == 0) { curAnn = (InterlinearAnnotation) curNode.getUserObject(); curAnn.x = 0; } calculateXPosDown(curNode); } } /** * Check and adapt annotation sizes top-down and recursively. If the sum of * the sizes of the child annotations is larger than the size of the * root, the root annotation is changed and the change is propagated * again. * * @param rootNode the node holding the root annotation of a (sub)tree */ private void propagateSizeDown(DefaultMutableTreeNode rootNode) { if (rootNode == null) { return; } if (rootNode.getChildCount() == 1) { InterlinearAnnotation curAnn = (InterlinearAnnotation) rootNode.getUserObject(); DefaultMutableTreeNode otherNode = (DefaultMutableTreeNode) rootNode.getFirstChild(); InterlinearAnnotation otherAnn = (InterlinearAnnotation) otherNode.getUserObject(); // don't change the size of a multiple line annotation if ((otherAnn.calcWidth > curAnn.calcWidth) && (curAnn.nrOfLines == 1)) { curAnn.calcWidth = otherAnn.calcWidth; } else if ((otherAnn.calcWidth < curAnn.calcWidth) && (otherAnn.nrOfLines == 1)) { otherAnn.calcWidth = curAnn.calcWidth; if (otherNode.getChildCount() > 0) { propagateSizeDown(otherNode); } } } else if (rootNode.getChildCount() > 1) { InterlinearAnnotation curAnn = (InterlinearAnnotation) rootNode.getUserObject(); int maxWidth = curAnn.calcWidth; DefaultMutableTreeNode otherNode = null; DefaultMutableTreeNode prevNode = null; InterlinearAnnotation otherAnn = null; InterlinearAnnotation prevAnn = null; String tierName = null; String lastTierName = null; int widthPerTier = 0; for (int i = 0; i < rootNode.getChildCount(); i++) { otherNode = (DefaultMutableTreeNode) rootNode.getChildAt(i); otherAnn = (InterlinearAnnotation) otherNode.getUserObject(); tierName = otherAnn.getTierName(); if (tierName == lastTierName) { // add to the current width widthPerTier += (interlinearizer.getEmptySpace() + otherAnn.calcWidth); } else { if (lastTierName != null) { // we have had all annotations of one child tier if (widthPerTier > maxWidth) { maxWidth = widthPerTier; } else if ((widthPerTier < curAnn.calcWidth) && (prevAnn.nrOfLines == 1)) { //add to the last annotation of that tier prevAnn.calcWidth += (curAnn.calcWidth - widthPerTier); if (prevNode.getChildCount() > 0) { propagateSizeDown(prevNode); } } // reset widthPerTier = otherAnn.calcWidth; } else { widthPerTier = otherAnn.calcWidth; } } if (i == (rootNode.getChildCount() - 1)) { //the last child annotation if (widthPerTier > maxWidth) { maxWidth = widthPerTier; } else if ((widthPerTier < curAnn.calcWidth) && (otherAnn.nrOfLines == 1)) { otherAnn.calcWidth += (curAnn.calcWidth - widthPerTier); if (otherNode.getChildCount() > 0) { propagateSizeDown(otherNode); } } } lastTierName = tierName; prevAnn = otherAnn; prevNode = otherNode; } if ((maxWidth > curAnn.calcWidth) && (curAnn.nrOfLines == 1)) { curAnn.calcWidth = maxWidth; // do it again, with changed size propagateSizeDown(rootNode); } } } /** * Calculate the x positions of child annotations recursively. * * @param rootNode the node holding the root annotation */ private void calculateXPosDown(DefaultMutableTreeNode rootNode) { if (rootNode == null) { return; } if (rootNode.getChildCount() == 1) { InterlinearAnnotation curAnn = (InterlinearAnnotation) rootNode.getUserObject(); DefaultMutableTreeNode otherNode = (DefaultMutableTreeNode) rootNode.getFirstChild(); InterlinearAnnotation otherAnn = (InterlinearAnnotation) otherNode.getUserObject(); // the one child gets the same x-pos as the parent otherAnn.x = curAnn.x; if (otherNode.getChildCount() > 0) { calculateXPosDown(otherNode); } } else if (rootNode.getChildCount() > 1) { InterlinearAnnotation curAnn = (InterlinearAnnotation) rootNode.getUserObject(); DefaultMutableTreeNode otherNode = null; InterlinearAnnotation otherAnn = null; InterlinearAnnotation prevAnn = null; String tierName = null; String lastTierName = null; for (int i = 0; i < rootNode.getChildCount(); i++) { otherNode = (DefaultMutableTreeNode) rootNode.getChildAt(i); otherAnn = (InterlinearAnnotation) otherNode.getUserObject(); tierName = otherAnn.getTierName(); if (tierName == lastTierName) { otherAnn.x = prevAnn.x + prevAnn.calcWidth + interlinearizer.getEmptySpace(); } else { otherAnn.x = curAnn.x; } if (otherNode.getChildCount() > 0) { calculateXPosDown(otherNode); } lastTierName = tierName; prevAnn = otherAnn; } } // printoutNode(rootNode); } /** * Splits/wraps annotation values at space boundaries. Words that are wider * than the available width are not split. The typical scenario will be * that a value is just a bit wider than one line and that it therefore * is most efficient to start calculations by truncating words from the * end of the string. Note: It is assumed that the params are not null and * that the annotation width has been checked to be larger than the * available width. * * @param prAnn the InterlinearAnnotation containing the value * @param available the available width for the value * @param metrics the font metrics, used to calculate sizes */ private void splitAnnotation(InterlinearAnnotation prAnn, int available, FontMetrics metrics) { int estimatedNrLines = (int) Math.ceil(prAnn.realWidth / available); ArrayList lines = new ArrayList(); if (estimatedNrLines <= 2) { //if (1 + 1 != 2) { // start calculations at the end String value = prAnn.getValue(); int charIndex = value.length(); int size = prAnn.realWidth; String temp = null; while (true) { charIndex = value.lastIndexOf(SPACE_CHAR, charIndex); if (charIndex < 0) { // don't try to split words lines.add(value); break; } temp = value.substring(0, charIndex); size = metrics.stringWidth(temp); if (size < available) { lines.add(temp); value = value.substring(charIndex + 1); size = metrics.stringWidth(value); if (size < available) { lines.add(value); break; } charIndex = value.length(); } else { //value = temp; charIndex--; } } } else { // start calculations at the begin String value = prAnn.getValue(); int charIndex = 0; int prevIndex = -1; int size = prAnn.realWidth; String temp = null; while (true) { charIndex = value.indexOf(SPACE_CHAR, charIndex); if (charIndex < 0) { if (prevIndex > 0) { // one word will go to the next line temp = value.substring(0, prevIndex); lines.add(temp); value = value.substring(prevIndex + 1); lines.add(value); break; } else { // don't try to split words lines.add(value); break; } } temp = value.substring(0, charIndex); size = metrics.stringWidth(temp); if (size > available) { if (prevIndex < 0) { // just add temp lines.add(temp); value = value.substring(charIndex + 1); prevIndex = charIndex; if (metrics.stringWidth(value) < available) { lines.add(value); break; } } else { temp = value.substring(0, prevIndex); lines.add(temp); value = value.substring(prevIndex + 1); if (metrics.stringWidth(value) < available) { lines.add(value); break; } charIndex = 0; prevIndex = -1; } } else { prevIndex = charIndex; charIndex++; } } } if (lines.size() > 1) { prAnn.setLines((String[]) lines.toArray(new String[] { })); prAnn.calcWidth = available; prAnn.realWidth = available; } } /** * Splits/wraps annotation values at space boundaries. Words that are wider * than the available width are not split. Measurements are based on * number of characters. * * @param prAnn the InterlinearAnnotation containing the value * @param available the available width for the value
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -