1

How can the line count be determined, if a TextArea wraps the text by setting setWrapText(true)? With line count I mean the number of lines the user gets visualized in the whole TextArea inclusive scrollable content.

Neither splitting the text by \n nor asking the paragraph count didn't work, since the wrapping has nothing to do with actual line splits.

Guardian667
  • 417
  • 4
  • 16
  • https://stackoverflow.com/questions/2035910/how-to-get-the-number-of-lines-in-a-textarea – Ali Sajid Jan 30 '18 at 08:27
  • 1
    @AliSajid - this is entirely irrelevant as 1. It is about JavaScript and **not** Java/JavaFX; and 2. It does not account for wrapping, only counting the number of lines in the raw text. – Itai Jan 30 '18 at 09:02

1 Answers1

0

This is my solution thus far, the core principle centered around the fact that the line height returned by the FontMetrics class in javafx is (marginally) off of the actual line height determined by a Text node, which resulted in the basic idea of using this type of node as a helper.

Count lines with active wrap text

Basically determine the actual line height by using a helper Text node for measurement, resetting and restoring the wrapping width on that helper and recording the change in height.

Count lines without active wrap text

This is the easiest: In that case the size of the paragraphs property corresponds directly to the number of lines:

Putting it all together it could look something like this:

  /**
   * Calculates the current amount of rows in the textarea regardless 
   * of "wordWrap" set to {@code true} or {@code false}.
   * 
   * @return the current count of rows; {@code 0} if the count could not be determined
   */
  private int getRowCount() {
    int currentRowCount = 0;
    Text helper = new Text();
    /*
     * Little performance improvement: If "wrapText" is set to false, then the
     * list of paragraphs directly corresponds to the line count, otherwise we need 
     * to get creative...
     */
    if(this.textArea.isWrapText()) {
      // text needs to be on the scene
      Text text = (Text) textArea.lookup(".text");
      if(text == null) {
        return currentRowCount;
      }
      /*
       * Now we just count the paragraphs: If the paragraph size is less
       * than the current wrappingWidth then increment; Otherwise use our
       * Text helper instance to calculate the change in height for the 
       * current paragraph with "wrappingWidth" set to the actual 
       * wrappingWidth of the TextArea text
       */
      helper.setFont(textArea.getFont());
      for (CharSequence paragraph : textArea.getParagraphs()) {
        helper.setText(paragraph.toString());
        Bounds localBounds = helper.getBoundsInLocal();

        double paragraphWidth = localBounds.getWidth();
        if(paragraphWidth > text.getWrappingWidth()) {          
          double oldHeight = localBounds.getHeight();
          // this actually sets the automatic size adjustment into motion...
          helper.setWrappingWidth(text.getWrappingWidth());
          double newHeight = helper.getBoundsInLocal().getHeight();
          // ...and we reset it after computation
          helper.setWrappingWidth(0.0D);

          int paragraphLineCount = Double.valueOf(newHeight / oldHeight).intValue();
          currentRowCount += paragraphLineCount;
        } else {
          currentRowCount += 1;
        }
      }
    } else {
      currentRowCount = textArea.getParagraphs().size();
    }
    return currentRowCount;
  }

Hope this helps!

Harbinger
  • 26
  • 2