web/htmlwidgets.py
changeset 4211 eac4b23a42ff
parent 4183 b5aa030bb2f9
child 4252 6c4f109c2b03
--- a/web/htmlwidgets.py	Wed Dec 23 12:20:10 2009 +0100
+++ b/web/htmlwidgets.py	Thu Jan 07 08:02:52 2010 +0100
@@ -9,6 +9,9 @@
 :license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses
 """
 
+from math import floor
+import random
+
 from logilab.mtconverter import xml_escape
 
 from cubicweb.utils import UStringIO
@@ -335,27 +338,90 @@
 
 class ProgressBarWidget(HTMLWidget):
     """display a progress bar widget"""
+    precision = 0.1
+    red_threshold = 1.1
+    orange_threshold = 1.05
+    yellow_threshold = 1
+
     def __init__(self, done, todo, total):
         self.done = done
         self.todo = todo
-        self.total = total
+        self.budget = total
+
+    @property
+    def overrun(self):
+        """overrun = done + todo - """
+        if self.done + self.todo > self.budget:
+            overrun = self.done + self.todo - self.budget
+        else:
+            overrun = 0
+        if overrun < self.precision:
+            overrun = 0
+        return overrun
+
+    @property
+    def overrun_percentage(self):
+        """pourcentage overrun = overrun / budget"""
+        if self.budget == 0:
+            return 0
+        else:
+            return self.overrun * 100. / self.budget
 
     def _render(self):
-        try:
-            percent = self.done*100./self.total
-        except ZeroDivisionError:
-            percent = 0
-        real_percent = percent
-        if percent > 100 :
-            color = 'done'
-            percent = 100
-        elif self.todo + self.done > self.total :
-            color = 'overpassed'
+        done = self.done
+        todo = self.todo
+        budget = self.budget
+        if budget == 0:
+            pourcent = 100
+            todo_pourcent = 0
+        else:
+            pourcent = done*100./budget
+            todo_pourcent = min(todo*100./budget, 100-pourcent)
+        bar_pourcent = pourcent
+        if pourcent > 100.1:
+            color = 'red'
+            bar_pourcent = 100
+        elif todo+done > self.red_threshold*budget:
+            color = 'red'
+        elif todo+done > self.orange_threshold*budget:
+            color = 'orange'
+        elif todo+done > self.yellow_threshold*budget:
+            color = 'yellow'
+        else:
+            color = 'green'
+        if pourcent < 0:
+            pourcent = 0
+
+        if floor(done) == done or done>100:
+            done_str = '%i' % done
         else:
-            color = 'inprogress'
-        if percent < 0:
-            percent = 0
-        self.w(u'<div class="progressbarback" title="%i %%">' % real_percent)
-        self.w(u'<div class="progressbar %s" style="width: %spx; align: left;" ></div>' % (color, percent))
-        self.w(u'</div>')
+            done_str = '%.1f' % done
+        if floor(budget) == budget or budget>100:
+            budget_str = '%i' % budget
+        else:
+            budget_str = '%.1f' % budget
 
+        title = u'%s/%s = %i%%' % (done_str, budget_str, pourcent)
+        short_title = title
+        if self.overrun_percentage:
+            title += u' overrun +%sj (+%i%%)' % (self.overrun,
+                                                 self.overrun_percentage)
+            overrun = self.overrun
+            if floor(overrun) == overrun or overrun>100:
+                overrun_str = '%i' % overrun
+            else:
+                overrun_str = '%.1f' % overrun
+            short_title += u' +%s' % overrun_str
+        # write bars
+        maxi = max(done+todo, budget)
+        if maxi == 0:
+            maxi = 1
+
+        cid = random.randint(0, 100000)
+        self.w(u'%s<br/>'
+               u'<canvas class="progressbar" id="canvas%i" width="100" height="10"></canvas>'
+               u'<script type="application/x-javascript">'
+               u'draw_progressbar("canvas%i", %i, %i, %i, "%s");</script>'
+               % (short_title.replace(' ','&nbsp;'), cid, cid,
+                  int(100.*done/maxi), int(100.*(done+todo)/maxi),
+                  int(100.*budget/maxi), color))