/** * Provides a mapping from the document model coordinate space to the coordinate space of the * view mapped to it. * * @param pos the position to convert * @param a the allocated region to render into * @return the bounding box of the given position is returned * @exception BadLocationException if the given position does not represent a valid location in * the associated document. */ @Override public Shape modelToView(int pos, Shape a, Position.Bias b) throws BadLocationException { // System.err.println("--- begin modelToView ---"); Rectangle alloc = a.getBounds(); RSyntaxTextArea textArea = (RSyntaxTextArea) getContainer(); alloc.height = textArea.getLineHeight(); // metrics.getHeight(); alloc.width = 1; int p0 = getStartOffset(); int p1 = getEndOffset(); int testP = (b == Position.Bias.Forward) ? pos : Math.max(p0, pos - 1); // Get the token list for this line so we don't have to keep // recomputing it if this logical line spans multiple physical // lines. RSyntaxDocument doc = (RSyntaxDocument) getDocument(); Element map = doc.getDefaultRootElement(); int line = map.getElementIndex(p0); Token tokenList = doc.getTokenListForLine(line); float x0 = alloc.x; // 0; while (p0 < p1) { TokenSubList subList = TokenUtils.getSubTokenList( tokenList, p0, WrappedSyntaxView.this, textArea, x0, lineCountTempToken); x0 = subList != null ? subList.x : x0; tokenList = subList != null ? subList.tokenList : null; int p = calculateBreakPosition(p0, tokenList, x0); if ((pos >= p0) && (testP < p)) { // pos < p)) { // it's in this line alloc = RSyntaxUtilities.getLineWidthUpTo( textArea, s, p0, pos, WrappedSyntaxView.this, alloc, alloc.x); // System.err.println("--- end modelToView ---"); return alloc; } // if (p == p1 && pos == p1) { if (p == p1 - 1 && pos == p1 - 1) { // Wants end. if (pos > p0) { alloc = RSyntaxUtilities.getLineWidthUpTo( textArea, s, p0, pos, WrappedSyntaxView.this, alloc, alloc.x); } // System.err.println("--- end modelToView ---"); return alloc; } p0 = (p == p0) ? p1 : p; // System.err.println("... ... Incrementing y"); alloc.y += alloc.height; } throw new BadLocationException(null, pos); }
/** Calculate the number of lines that will be rendered by logical line when it is wrapped. */ final int calculateLineCount() { int nlines = 0; int startOffset = getStartOffset(); int p1 = getEndOffset(); // Get the token list for this line so we don't have to keep // recomputing it if this logical line spans multiple physical // lines. RSyntaxTextArea textArea = (RSyntaxTextArea) getContainer(); RSyntaxDocument doc = (RSyntaxDocument) getDocument(); Element map = doc.getDefaultRootElement(); int line = map.getElementIndex(startOffset); Token tokenList = doc.getTokenListForLine(line); float x0 = 0; // FIXME: should be alloc.x!! alloc.x;//0; // System.err.println(">>> calculateLineCount: " + startOffset + "-" + p1); for (int p0 = startOffset; p0 < p1; ) { // System.err.println("... ... " + p0 + ", " + p1); nlines += 1; TokenSubList subList = TokenUtils.getSubTokenList( tokenList, p0, WrappedSyntaxView.this, textArea, x0, lineCountTempToken); x0 = subList != null ? subList.x : x0; tokenList = subList != null ? subList.tokenList : null; int p = calculateBreakPosition(p0, tokenList, x0); // System.err.println("... ... ... break position p==" + p); p0 = (p == p0) ? ++p : p; // this is the fix of #4410243 // we check on situation when // width is too small and // break position is calculated // incorrectly. // System.err.println("... ... ... new p0==" + p0); } /* int numLines = 0; try { numLines = textArea.getLineCount(); } catch (BadLocationException ble) { ble.printStackTrace(); } System.err.println(">>> >>> calculated number of lines for this view (line " + line + "/" + numLines + ": " + nlines); */ return nlines; }
/** * Provides a mapping from the view coordinate space to the logical coordinate space of the * model. * * @param fx the X coordinate * @param fy the Y coordinate * @param a the allocated region to render into * @return the location within the model that best represents the given point in the view * @see View#viewToModel */ @Override public int viewToModel(float fx, float fy, Shape a, Position.Bias[] bias) { // PENDING(prinz) implement bias properly bias[0] = Position.Bias.Forward; Rectangle alloc = (Rectangle) a; RSyntaxDocument doc = (RSyntaxDocument) getDocument(); int x = (int) fx; int y = (int) fy; if (y < alloc.y) { // above the area covered by this icon, so the the position // is assumed to be the start of the coverage for this view. return getStartOffset(); } else if (y > alloc.y + alloc.height) { // below the area covered by this icon, so the the position // is assumed to be the end of the coverage for this view. return getEndOffset() - 1; } else { // positioned within the coverage of this view vertically, // so we figure out which line the point corresponds to. // if the line is greater than the number of lines // contained, then simply use the last line as it represents // the last possible place we can position to. RSyntaxTextArea textArea = (RSyntaxTextArea) getContainer(); alloc.height = textArea.getLineHeight(); int p1 = getEndOffset(); // Get the token list for this line so we don't have to keep // recomputing it if this logical line spans multiple // physical lines. Element map = doc.getDefaultRootElement(); int p0 = getStartOffset(); int line = map.getElementIndex(p0); Token tlist = doc.getTokenListForLine(line); // Look at each physical line-chunk of this logical line. while (p0 < p1) { // We can always use alloc.x since we always break // lines so they start at the beginning of a physical // line. TokenSubList subList = TokenUtils.getSubTokenList( tlist, p0, WrappedSyntaxView.this, textArea, alloc.x, lineCountTempToken); tlist = subList != null ? subList.tokenList : null; int p = calculateBreakPosition(p0, tlist, alloc.x); // If desired view position is in this physical chunk. if ((y >= alloc.y) && (y < (alloc.y + alloc.height))) { // Point is to the left of the line if (x < alloc.x) { return p0; } // Point is to the right of the line else if (x > alloc.x + alloc.width) { return p - 1; } // Point is in this physical line! else { // Start at alloc.x since this chunk starts // at the beginning of a physical line. int n = tlist.getListOffset(textArea, WrappedSyntaxView.this, alloc.x, x); // NOTE: We needed to add the max() with // p0 as getTokenListForLine returns -1 // for empty lines (just a null token). // How did this work before? // FIXME: Have null tokens have their // offset but a -1 length. return Math.max(Math.min(n, p1 - 1), p0); } // End of else. } // End of if ((y>=alloc.y) && ... p0 = (p == p0) ? p1 : p; alloc.y += alloc.height; } // End of while (p0<p1). return getEndOffset() - 1; } // End of else. }