Explorar o código

wrap graph and vscale in single widget

Daniel Sheffield %!s(int64=2) %!d(string=hai) anos
pai
achega
b12a82608e
Modificáronse 2 ficheiros con 68 adicións e 26 borrados
  1. 22 24
      app/activities/TransactionEditor.py
  2. 46 2
      app/widgets.py

+ 22 - 24
app/activities/TransactionEditor.py

@@ -28,8 +28,7 @@ from ..widgets import (
     FocusWidget,
     AutoCompletePopUp,
     NoTabCheckBox,
-    FlowBarGraph,
-    FlowGraphVScale,
+    FlowBarGraphWithVScale,
 )
 from . import ActivityManager
 from .Rating import Rating
@@ -101,6 +100,7 @@ class TransactionEditor(FocusWidget):
         for (k, tf) in self.text_fields.items():
             if k != 'dbview':
                 tf.set_text('')
+        self.graph.set_data([],0)
         return self.update()
     
     def update(self):
@@ -132,7 +132,7 @@ class TransactionEditor(FocusWidget):
             self.rating.update_rating(None, None, None, unit)
             return
 
-        df = self.query_manager.get_historic_prices_data(unit, product=product, organic=organic)
+        df = self.query_manager.get_historic_prices_data(unit, product=product, organic=organic, sort='ts')
         if df.empty:
             self.rating.update_rating(None, None, None, unit)
             return
@@ -143,23 +143,21 @@ class TransactionEditor(FocusWidget):
           float(x) for x in df[['avg','min','max']].iloc[0]
         ]
         self.rating.update_rating(_avg, _min, _max, unit, price=price, quantity=quantity)
+        df = df.sort_values('ts_raw', ascending=True)
         #print(df)
         #input()
-        self.graph._invalidate()
-        top = 10 # need to set this same as in column widget
-        scale = (df['max'].apply(float).iloc[0]/top)*(top+1)
-        self.graph.set_bar_width(1)
         # need to sort by ts and take last 45 items
-        self.graph.set_data(df[['ts_raw','$/unit']].apply(
-            lambda x, axis=None: (
-                x['ts_raw'].timestamp(), float(x['$/unit'])
-            ), axis=1), scale)
-        self.graph_vscale._invalidate()
-        self.graph_vscale.set_scale([
-            ((_min*top)//scale, f'{_min:>5.2f} '),
-            ((_avg*top)//scale, f'{_avg:>5.2f} '),
-            ((_max*top)//scale, f'{_max:>5.2f} '),
-        ], top)
+        self.graph.set_data(
+            df[['ts_raw','$/unit']].apply(
+                lambda x, axis=None: (
+                    x['ts_raw'].timestamp(), float(x['$/unit'])
+                ), axis=1
+            ),
+            df['max'].apply(float).iloc[0],
+            labels=[_min, _avg, _max]
+        )
+        self.graph.set_bar_width(1)
+
 
 
     def focus_on_product(self):
@@ -202,8 +200,11 @@ class TransactionEditor(FocusWidget):
             'spread': Text(''),
             'marker': Text(''),
         }
-        self.graph = FlowBarGraph(['bg','badge_highlight','popup_focus', ], hatt=['dark red', 'dark red', 'dark red'])
-        self.graph_vscale = FlowGraphVScale(self.graph, [], 0)
+        self.graph = FlowBarGraphWithVScale(
+            50, 14,
+            ['bg','badge_highlight','popup_focus', ],
+            hatt=['dark red', 'dark red', 'dark red']
+        )
         self.rating = Rating(dict(filter(
           lambda x: x[0] in ('spread','rating','marker'),
           self.text_fields.items()
@@ -273,15 +274,12 @@ class TransactionEditor(FocusWidget):
               lambda x: _widgets[x] if x is not None else Divider(),
               bottom_pane
             )),
-            (50, Pile([
+            (self.graph.width, Pile([
               LineBox(
                 AttrMap(components['badge'], 'badge'),
                 title="Current Price", title_align='left',
               ),
-              Columns([
-                (6, self.graph_vscale),
-                (44, self.graph),
-              ])
+              self.graph,
             ])),
           ])
         })

+ 46 - 2
app/widgets.py

@@ -313,11 +313,12 @@ class SuggestionPopup(urwid.WidgetWrap):
 
 class FlowBarGraph(urwid.BarGraph):
     ignore_focus = True
-    def __init__(self, *args, **kwargs):
+    def __init__(self, height, *args, **kwargs):
         super().__init__(*args, **kwargs)
+        self.height = height
     
     def rows(self, size, focus=False):
-        return 10
+        return self.height
     
     def render(self, size, focus=False):
         _size = (size[0], self.rows(size))
@@ -335,3 +336,46 @@ class FlowGraphVScale(urwid.GraphVScale):
     def render(self, size, focus=False):
         _size = (size[0], self.rows(size))
         return super().render(_size,focus=focus)
+        
+class FlowBarGraphWithVScale(urwid.Columns):
+    ignore_focus = True
+    
+    @property
+    def width(self):
+        return self._width
+    
+    @property
+    def height(self):
+        return self.graph.height
+    
+    @height.setter
+    def height(self, value):
+        self._invalidate
+        self.graph._invalidate
+        self.graph_vscale._invalidate
+        self.graph.height = value
+    
+    def set_bar_width(self, width):
+        self.graph.set_bar_width(width)
+    
+    def set_data(self, data, _max, labels=None):
+        top = self.height
+        scale = (_max/top)*(top+1)
+        self.graph.set_data(data, scale)
+        if labels is None:
+            return
+        self.graph_vscale._invalidate()
+        self.graph_vscale.set_scale([
+            ((x*top)//scale, f'{x:>5.2f} ') for x in labels
+        ], top)
+    
+    def __init__(self, cols, rows, attr, *args, hatt=None, **kwargs):
+        self._width = cols
+        assert cols > 6
+        self.graph = FlowBarGraph(rows, attr, hatt=hatt)
+        self.graph_vscale = FlowGraphVScale(self.graph, [], 0)
+        super().__init__([
+            (6, self.graph_vscale),
+            (cols-6, self.graph)
+        ], *args, **kwargs)
+