Repository: biolab/orange3

Issue:
OWSieveDiagram: legible axis labels
Follow up on #2110.

Current widget status.
<img width="549" alt="Screen Shot 2019-04-12 at 11 13 15" src="https://user-images.githubusercontent.com/12524972/56026253-0cfac180-5d14-11e9-8f05-bc67277a8e98.png">

Solve overlap by eliding over the width of the column. If column too small, hide the label.
Also, display proper datetime, not floats.


Discussion:
See #3845 for a fix of a similar problem on OWMosaic

Resolving patch:
diff --git a/Orange/widgets/visualize/owmosaic.py b/Orange/widgets/visualize/owmosaic.py
--- a/Orange/widgets/visualize/owmosaic.py
+++ b/Orange/widgets/visualize/owmosaic.py
@@ -675,14 +675,9 @@ def draw_text(side, attr, x0_x1, y0_y1,
                           y0 - self.ATTR_VAL_OFFSET,
                           y0 + currpos + height * 0.5 * perc]
 
-                    text = CanvasText(
-                        self.canvas, val, xs[side], ys[side], align)
-                    if side == 0 and text.boundingRect().width() > rwidth:
-                        text.setToolTip(val)
-                        while val and text.boundingRect().width() > rwidth:
-                            val = val[:-1]
-                            text.setPlainText(val + "...")
-                            text.setPos(xs[0], ys[0])
+                    CanvasText(
+                        self.canvas, val, xs[side], ys[side], align,
+                        max_width=rwidth if side == 0 else None)
                     space = height if side % 2 else width
                     currpos += perc * space + spacing * (total_attrs - side)
 
diff --git a/Orange/widgets/visualize/owsieve.py b/Orange/widgets/visualize/owsieve.py
--- a/Orange/widgets/visualize/owsieve.py
+++ b/Orange/widgets/visualize/owsieve.py
@@ -333,7 +333,12 @@ def update_graph(self):
         """Update the graph."""
 
         def text(txt, *args, **kwargs):
-            return CanvasText(self.canvas, "", html_text=to_html(txt),
+            text = html_text = None
+            if "max_width" in kwargs:
+                text = txt
+            else:
+                html_text = to_html(txt)
+            return CanvasText(self.canvas, text, html_text=html_text,
                               *args, **kwargs)
 
         def width(txt):
@@ -488,7 +493,7 @@ def _oper(attr, txt):
                 curr_y += height
 
             xl = text(xval_name, curr_x + width / 2, y_off + square_size,
-                      Qt.AlignHCenter | Qt.AlignTop)
+                      Qt.AlignHCenter | Qt.AlignTop, max_width=width)
             max_xlabel_h = max(int(xl.boundingRect().height()), max_xlabel_h)
             curr_x += width
 
diff --git a/Orange/widgets/visualize/utils/__init__.py b/Orange/widgets/visualize/utils/__init__.py
--- a/Orange/widgets/visualize/utils/__init__.py
+++ b/Orange/widgets/visualize/utils/__init__.py
@@ -558,7 +558,8 @@ class CanvasText(QGraphicsTextItem):
     """
     def __init__(self, scene, text="", x=0, y=0,
                  alignment=Qt.AlignLeft | Qt.AlignTop, bold=False, font=None,
-                 z=0, html_text=None, tooltip=None, show=True, vertical=False):
+                 z=0, html_text=None, tooltip=None, show=True, vertical=False,
+                 max_width=None):
         QGraphicsTextItem.__init__(self, text, None)
 
         if font:
@@ -580,6 +581,10 @@ def __init__(self, scene, text="", x=0, y=0,
         self.setZValue(z)
         if tooltip:
             self.setToolTip(tooltip)
+        if max_width is not None:
+            assert not html_text
+            self.elide(max_width)
+
         if show:
             self.show()
         else:
@@ -588,6 +593,18 @@ def __init__(self, scene, text="", x=0, y=0,
         if scene is not None:
             scene.addItem(self)
 
+    def elide(self, max_width):
+        if self.boundingRect().width() <= max_width:
+            return
+        short = self.toPlainText()
+        if not self.toolTip():
+            self.setToolTip(short)
+        while short and self.boundingRect().width() > max_width:
+            short = short[:-1]
+            self.setPlainText(short + "...")
+            # apparently this has to be called to reset position
+            self.setPos(self.x, self.y)
+
     def setPos(self, x, y):
         """setPos with adjustment for alignment"""
         self.x, self.y = x, y


Test patch: