File: C:/Users/fred/anaconda3/Lib/site-packages/spyder/plugins/editor/panels/indentationguides.py
# -*- coding: utf-8 -*-
#
# Copyright © Spyder Project Contributors
# Licensed under the terms of the MIT License
# (see spyder/__init__.py for details)
"""
This module contains the indentation guide panel.
"""
# Third party imports
from qtpy.QtCore import Qt
from qtpy.QtGui import QPainter, QColor
# Local imports
from spyder.api.panel import Panel
class IndentationGuide(Panel):
"""Indentation guides to easy identify nested blocks."""
# --- Qt Overrides
# -----------------------------------------------------------------
def __init__(self):
"""Initialize IndentationGuide panel.
i_width(int): identation width in characters.
"""
Panel.__init__(self)
self.color = Qt.darkGray
self.i_width = 4
self.bar_offset = 0
def on_install(self, editor):
"""Manages install setup of the pane."""
super().on_install(editor)
horizontal_scrollbar = editor.horizontalScrollBar()
horizontal_scrollbar.valueChanged.connect(self.update_bar_position)
horizontal_scrollbar.sliderReleased.connect(self.update)
def update_bar_position(self, value):
self.bar_offset = value
def sizeHint(self):
"""Override Qt method."""
return self.size()
def paintEvent(self, event):
"""
Overriden Qt method.
Paint indent guides.
"""
# Set painter
painter = QPainter(self)
color = QColor(self.color)
color.setAlphaF(.5)
painter.setPen(color)
# Compute offset
offset = (self.editor.document().documentMargin() +
self.editor.contentOffset().x())
# Folding info
folding_panel = self.editor.panels.get('FoldingPanel')
folding_regions = folding_panel.folding_regions
leading_whitespaces = self.editor.leading_whitespaces
# Visible block numbers
visible_blocks = self.editor.get_visible_block_numbers()
# Paint lines
for start_line in folding_regions:
end_line = folding_regions[start_line]
line_numbers = (start_line, end_line)
if self.do_paint(visible_blocks, line_numbers):
start_block = self.editor.document().findBlockByNumber(
start_line)
end_block = self.editor.document().findBlockByNumber(
end_line - 1)
content_offset = self.editor.contentOffset()
top = int(self.editor.blockBoundingGeometry(
start_block).translated(content_offset).top())
bottom = int(self.editor.blockBoundingGeometry(
end_block).translated(content_offset).bottom())
total_whitespace = leading_whitespaces.get(
max(start_line - 1, 0))
end_whitespace = leading_whitespaces.get(end_line - 1)
if end_whitespace and end_whitespace != total_whitespace:
font_metrics = self.editor.fontMetrics()
x = int(font_metrics.width(total_whitespace * '9') +
self.bar_offset + offset)
painter.drawLine(x, top, x, bottom)
# --- Other methods
# -----------------------------------------------------------------
def set_enabled(self, state):
"""Toggle edge line visibility."""
self._enabled = state
self.setVisible(state)
# We need to request folding when toggling state so the lines
# are computed when handling the folding response.
self.editor.request_folding()
def update_color(self):
"""Set color using syntax highlighter color for comments."""
self.color = self.editor.highlighter.get_color_name('comment')
def set_indentation_width(self, indentation_width):
"""Set indentation width to be used to draw indent guides."""
self.i_width = indentation_width
def do_paint(self, visible_blocks, line_numbers):
"""
Decide if we need to paint an indent guide according to the
visible region.
"""
# Line numbers for the visible region.
first_visible_line = visible_blocks[0] + 1
last_visible_line = visible_blocks[1] + 1
# Line numbers for the indent guide.
start_line = line_numbers[0]
end_line = line_numbers[1]
# Guide starts before the visible region and ends inside it.
if (start_line < first_visible_line and
(first_visible_line <= end_line <= last_visible_line)):
return True
# Guide starts before the visible region and ends after it.
if start_line <= first_visible_line and end_line >= last_visible_line:
return True
# Guide starts inside the visible region and ends after it.
if ((first_visible_line <= start_line <= last_visible_line) and
end_line > last_visible_line):
return True
# Guide starts and ends inside the visible region.
if ((first_visible_line <= start_line <= last_visible_line) and
(first_visible_line <= end_line <= last_visible_line)):
return True
# If none of those cases are true, we don't need to paint this guide.
return False