Repository: spyder-ide/spyder

Issue:
Improve floating panels in the editor 
The magic for calculate the position of edgeline and indentguides, could be improve it and if hardcoded should be in only one place.
https://github.com/spyder-ide/spyder/pull/4572#discussion_r120737977


Discussion:
@rlaverde, please work on this one.

Resolving patch:
diff --git a/spyder/api/panel.py b/spyder/api/panel.py
--- a/spyder/api/panel.py
+++ b/spyder/api/panel.py
@@ -11,7 +11,7 @@
 """
 from qtpy.QtWidgets import QWidget, QApplication
 from qtpy.QtGui import QBrush, QColor, QPen, QPainter
-from qtpy.QtCore import Qt
+from qtpy.QtCore import Qt, QPoint, QRect
 
 from spyder.api.editorextension import EditorExtension
 from spyder.config.base import debug_print
@@ -124,3 +124,35 @@ def setVisible(self, visible):
         super(Panel, self).setVisible(visible)
         if self.editor:
             self.editor.panels.refresh()
+
+    def geometry(self):
+        """Return geometry dimentions for floating Panels.
+
+        Note: If None is returned It'll use editor contentsRect dimentions.
+
+        returns: x0, y0, height width.
+        """
+        return 0, 0, None, None
+
+    def set_geometry(self, crect):
+        """Set geometry for floating panels.
+
+        Normally you don't need to override this method, you should override
+        `geometry` instead.
+        """
+        x0, y0, width, height = self.geometry()
+
+        if width is None:
+            width = crect.width()
+        if height is None:
+            height = crect.height()
+
+        # Calculate editor coordinates with their offsets
+        offset = self.editor.contentOffset()
+        x = self.editor.blockBoundingGeometry(self.editor.firstVisibleBlock())\
+            .translated(offset.x(), offset.y()).left() \
+            + self.editor.document().documentMargin() \
+            + self.editor.panels.margin_size(Panel.Position.LEFT)
+        y = crect.top() + self.editor.panels.margin_size(Panel.Position.TOP)
+
+        self.setGeometry(QRect(x+x0, y+y0, width, height))
diff --git a/spyder/widgets/panels/edgeline.py b/spyder/widgets/panels/edgeline.py
--- a/spyder/widgets/panels/edgeline.py
+++ b/spyder/widgets/panels/edgeline.py
@@ -8,12 +8,13 @@
 This module contains the edge line panel
 """
 
-from qtpy.QtCore import Qt, QRect, QPoint
-from qtpy.QtGui import QPainter, QColor
+from qtpy.QtCore import Qt
+from qtpy.QtGui import QPainter, QColor, QPen
 
 from spyder.py3compat import is_text_string
 from spyder.api.panel import Panel
 
+
 class EdgeLine(Panel):
     """Source code editor's edge line (default: 79 columns, PEP8)"""
 
@@ -29,13 +30,12 @@ def paintEvent(self, event):
         painter = QPainter(self)
         size = self.size()
 
-        offsets = [col - min(self.columns) for col in self.columns]
-        for offset in offsets:
-            color = QColor(self.color)
-            color.setAlphaF(.5)
-            painter.setPen(color)
+        color = QColor(self.color)
+        color.setAlphaF(.5)
+        painter.setPen(color)
 
-            x = self.editor.fontMetrics().width(offset * '9')
+        for column in self.columns:
+            x = self.editor.fontMetrics().width(column * '9')
             painter.drawLine(x, 0, x, size.height())
 
     # --- Other methods
@@ -60,20 +60,3 @@ def update_color(self):
         Set edgeline color using syntax highlighter color for comments
         """
         self.color = self.editor.highlighter.get_color_name('comment')
-
-    def set_geometry(self, cr):
-        """Calculate and set geometry of edge line panel.
-            start --> fist line position
-            width --> max position - min position
-        """
-        width = self.editor.fontMetrics().width('9'*(max(self.columns) - min(self.columns))) + 1
-        offset = self.editor.contentOffset()
-        x = self.editor.blockBoundingGeometry(self.editor.firstVisibleBlock()) \
-            .translated(offset.x(), offset.y()).left() \
-            +self.editor.fontMetrics().width('9'*min(self.columns))+5
-
-        top_left = QPoint(x, cr.top())
-        top_left = self.editor.calculate_real_position(top_left)
-        bottom_right = QPoint(top_left.x() + width, cr.bottom())
-
-        self.setGeometry(QRect(top_left, bottom_right))
diff --git a/spyder/widgets/panels/indentationguides.py b/spyder/widgets/panels/indentationguides.py
--- a/spyder/widgets/panels/indentationguides.py
+++ b/spyder/widgets/panels/indentationguides.py
@@ -60,15 +60,3 @@ def update_color(self):
     def set_indentation_width(self, indentation_width):
         """Set indentation width to be used to draw indent guides."""
         self.i_width = indentation_width
-
-    def set_geometry(self, cr):
-        """Calculate and set geometry of indentation guides panel."""
-        offset = self.editor.contentOffset()
-        x = self.editor.blockBoundingGeometry(self.editor.firstVisibleBlock()) \
-            .translated(offset.x(), offset.y()).left() + 5
-
-        top_left = QPoint(x, cr.top())
-        top_left = self.editor.calculate_real_position(top_left)
-        bottom_right = QPoint(top_left.x() + cr.width(), cr.bottom())
-
-        self.setGeometry(QRect(top_left, bottom_right))


Test patch: