<commit_before>/**
 * Copyright (c) 2014 by Brainwy Software LTDA. All Rights Reserved.
 * Licensed under the terms of the Eclipse Public License (EPL).
 * Please see the license.txt included with this distribution for details.
 * Any modifications to this file must keep this entire header intact.
 */
package org.python.pydev.shared_ui.editor;

import java.util.Collection;
import java.util.List;
import java.util.Map;

import org.eclipse.core.runtime.Assert;
import org.eclipse.jface.text.JFaceTextUtil;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.ExtendedModifyEvent;
import org.eclipse.swt.custom.ExtendedModifyListener;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.custom.StyledTextContent;
import org.eclipse.swt.custom.TextChangeListener;
import org.eclipse.swt.custom.TextChangedEvent;
import org.eclipse.swt.custom.TextChangingEvent;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Rectangle;
import org.python.pydev.shared_core.log.Log;

public class VerticalIndentGuidesPainter implements PaintListener, ModifyListener, ExtendedModifyListener,
        TextChangeListener {

    private StyledText styledText;
    private boolean inDraw;
    private Rectangle currClientArea;
    private int currCharCount;
    private Map<Integer, List<VerticalLinesToDraw>> lineToVerticalLinesToDraw;
    private StyledTextContent content;
    private final IVerticalLinesIndentGuideComputer indentGuide;
    private int lastXOffset = -1;
    private int lastYOffset = -1;
    private int currTabWidth = -1;
    private boolean askFullRedraw = true; //On the first one always make it full

    public void dispose() {
        styledText = null;
        currClientArea = null;
        lineToVerticalLinesToDraw = null;
        content = null;
        indentGuide.dispose();
    }

    public VerticalIndentGuidesPainter(IVerticalLinesIndentGuideComputer indentGuide) {
        Assert.isNotNull(indentGuide);
        this.indentGuide = indentGuide;
    }

    @Override
    public void paintControl(PaintEvent e) {

        if (inDraw || styledText == null || styledText.isDisposed()) {
            return;
        }
        try {
            inDraw = true;
            boolean showIndentGuide = this.indentGuide.getShowIndentGuide();
            if (!showIndentGuide) {
                return;
            }

            int xOffset = styledText.getHorizontalPixel();
            int yOffset = styledText.getTopPixel();

            //Important: call all to cache the new values (instead of doing all inside the or below).
            boolean styledTextContentChanged = getStyledTextContentChangedAndStoreNew();
            boolean clientAreaChanged = getClientAreaChangedAndStoreNew();
            boolean charCountChanged = getCharCountChangedAndStoreNew();
            boolean tabWidthChanged = getTabWidthChangedAndStoreNew();

            boolean redrawAll = styledTextContentChanged || clientAreaChanged || charCountChanged || tabWidthChanged
                    || xOffset != lastXOffset || yOffset != lastYOffset;

            StyledTextContent currentContent = this.content;
            if (currClientArea == null || currClientArea.width < 5 || currClientArea.height < 5 || currCharCount < 1
                    || currentContent == null || currTabWidth <= 0) {
                return;
            }
            lastXOffset = xOffset;
            lastYOffset = yOffset;

            int topIndex = JFaceTextUtil.getPartialTopIndex(styledText);
            int bottomIndex = JFaceTextUtil.getPartialBottomIndex(styledText);
            if (redrawAll) {
                this.lineToVerticalLinesToDraw = this.indentGuide.computeVerticalLinesToDrawInRegion(styledText,
                        topIndex, bottomIndex);
                // This is a bit unfortunate: when something changes, we may have to repaint out of the clipping
                // region, but even setting the clipping region (e.gc.setClipping), the clipping region may still
                // be unchanged (because the system said that it only wants to repaint some specific area already
                // and we can't make it bigger -- so, what's left for us is asking for a repaint of the full area
                // in this case).
                if (askFullRedraw) {
                    askFullRedraw = false;
                    if (Math.abs(currClientArea.height - e.gc.getClipping().height) > 40) {
                        //Only do it if the difference is really high (some decorations make it usually a bit lower than<commit_msg>Minor<commit_after>/**
 * Copyright (c) 2014 by Brainwy Software LTDA. All Rights Reserved.
 * Licensed under the terms of the Eclipse Public License (EPL).
 * Please see the license.txt included with this distribution for details.
 * Any modifications to this file must keep this entire header intact.
 */
package org.python.pydev.shared_ui.editor;

import java.util.Collection;
import java.util.List;
import java.util.Map;

import org.eclipse.core.runtime.Assert;
import org.eclipse.jface.text.JFaceTextUtil;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.ExtendedModifyEvent;
import org.eclipse.swt.custom.ExtendedModifyListener;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.custom.StyledTextContent;
import org.eclipse.swt.custom.TextChangeListener;
import org.eclipse.swt.custom.TextChangedEvent;
import org.eclipse.swt.custom.TextChangingEvent;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Rectangle;
import org.python.pydev.shared_core.log.Log;

public class VerticalIndentGuidesPainter implements PaintListener, ModifyListener, ExtendedModifyListener,
        TextChangeListener {

    private StyledText styledText;
    private boolean inDraw;
    private Rectangle currClientArea;
    private int currCharCount;
    private Map<Integer, List<VerticalLinesToDraw>> lineToVerticalLinesToDraw;
    private StyledTextContent content;
    private final IVerticalLinesIndentGuideComputer indentGuide;
    private int lastXOffset = -1;
    private int lastYOffset = -1;
    private int currTabWidth = -1;
    private boolean askFullRedraw = true; //On the first one always make it full

    public void dispose() {
        styledText = null;
        currClientArea = null;
        lineToVerticalLinesToDraw = null;
        content = null;
        indentGuide.dispose();
    }

    public VerticalIndentGuidesPainter(IVerticalLinesIndentGuideComputer indentGuide) {
        Assert.isNotNull(indentGuide);
        this.indentGuide = indentGuide;
    }

    @Override
    public void paintControl(PaintEvent e) {

        if (inDraw || styledText == null || styledText.isDisposed()) {
            return;
        }
        try {
            inDraw = true;
            boolean showIndentGuide = this.indentGuide.getShowIndentGuide();
            if (!showIndentGuide) {
                return;
            }

            int xOffset = styledText.getHorizontalPixel();
            int yOffset = styledText.getTopPixel();

            //Important: call all to cache the new values (instead of doing all inside the or below).
            boolean styledTextContentChanged = getStyledTextContentChangedAndStoreNew();
            boolean clientAreaChanged = getClientAreaChangedAndStoreNew();
            boolean charCountChanged = getCharCountChangedAndStoreNew();
            boolean tabWidthChanged = getTabWidthChangedAndStoreNew();

            boolean redrawAll = styledTextContentChanged || clientAreaChanged || charCountChanged || tabWidthChanged
                    || xOffset != lastXOffset || yOffset != lastYOffset;

            StyledTextContent currentContent = this.content;
            if (currClientArea == null || currClientArea.width < 5 || currClientArea.height < 5 || currCharCount < 1
                    || currentContent == null || currTabWidth <= 0) {
                return;
            }
            lastXOffset = xOffset;
            lastYOffset = yOffset;

            int topIndex;
            try {
                topIndex = JFaceTextUtil.getPartialTopIndex(styledText);
            } catch (IllegalArgumentException e1) {
                // Just silence it...
                // java.lang.IllegalArgumentException: Index out of bounds
                // at org.eclipse.swt.SWT.error(SWT.java:4458)
                // at org.eclipse.swt.SWT.error(SWT.java:4392)
                // at org.eclipse.swt.SWT.error(SWT.java:4363)
                // at org.eclipse.swt.custom.StyledText.getOffsetAtLine(StyledText.java:4405)
                // at org.eclipse.jface.text.JFaceTextUtil.getPartialTopIndex(JFaceTextUtil.java:103)
                // at org.python.pydev.shared_ui.editor.VerticalIndentGuidesPainter.paintControl(VerticalIndentGuidesPainter.java:93)
                return;
            }
            int bottomIndex = JFaceTextUtil.getPartialBottomIndex(styledText);
            if (redrawAll) {
                this.lineToVerticalLinesToDraw = this.indentGuide.computeVerticalLinesToDrawInRegion(styledText,
                        topIndex, bottomIndex);
                // This is a bit unfortunate: when something changes, we may have to repaint out of the clipping
                // region, but even setting the clipping region (e.gc.setClipping), the clipping region may still
                // be unchanged (because the system said that it only wants to repaint some specific area already
                // and we can't make it bigger -- so, what's left for us is asking for a repaint of the full area
                // in this case).
                if (askFullRedraw) {
                    askFullRedraw = false;
                    if (Math.abs(currClientArea.height - e.gc.getClipping().height) > 40) {
                        //Only do it if the difference is really high (some decorations make it usually a bit lower than
{'fraction_non_alphanumeric': 0.07890655292749127, 'fraction_numerical': 0.0046529662659945716, 'mean_word_length': 2.67153024911032, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1700627', 'n_tokens_mistral': 2845, 'n_tokens_neox': 2685, 'n_words': 727}