From 3b22df3ea728de923fac7449a076ed426d36a660 Mon Sep 17 00:00:00 2001 From: Grant Sanderson Date: Tue, 26 Jun 2018 14:39:47 -0700 Subject: [PATCH] Refactored DecimalNumber to better use string formatting syntax --- mobject/numbers.py | 51 +++++++++++++++++++++++++++++++++------------- 1 file changed, 37 insertions(+), 14 deletions(-) diff --git a/mobject/numbers.py b/mobject/numbers.py index 3a393968..377186a8 100644 --- a/mobject/numbers.py +++ b/mobject/numbers.py @@ -1,6 +1,7 @@ from __future__ import absolute_import from constants import * +import operator as op from mobject.svg.tex_mobject import SingleStringTexMobject from mobject.types.vectorized_mobject import VMobject @@ -9,33 +10,28 @@ from mobject.types.vectorized_mobject import VMobject class DecimalNumber(VMobject): CONFIG = { "num_decimal_places": 2, + "include_sign": False, + "group_with_commas": True, "digit_to_digit_buff": 0.05, "show_ellipsis": False, "unit": None, # Aligned to bottom unless it starts with "^" "include_background_rectangle": False, - "include_sign": False, } def __init__(self, number, **kwargs): VMobject.__init__(self, **kwargs) # TODO, make this more ediable with a getter and setter self.number = number - ndp = self.num_decimal_places - # Build number string if isinstance(number, complex): - num_string = '%.*f%s%.*fi' % ( - ndp, number.real, - "-" if number.imag < 0 else "+", - ndp, abs(number.imag) - ) + formatter = self.get_complex_formatter() else: - num_string = '%.*f' % (ndp, number) - if self.include_sign and number >= 0: - num_string = "+" + num_string - negative_zero_string = "-%.*f" % (ndp, 0.) - if num_string == negative_zero_string: - num_string = num_string[1:] + formatter = self.get_formatter() + num_string = formatter.format(number) + + if num_string.startswith("-") and number == 0: + num_string = num_string[1:] + self.add(*[ SingleStringTexMobject(char, **kwargs) for char in num_string @@ -66,12 +62,39 @@ class DecimalNumber(VMobject): for i, c in enumerate(num_string): if c == "-" and len(num_string) > i + 1: self[i].align_to(self[i + 1], alignment_vect=UP) + elif c == ",": + self[i].shift(self[i].get_height() * DOWN / 2) if self.unit and self.unit.startswith("^"): self.unit_sign.align_to(self, UP) # if self.include_background_rectangle: self.add_background_rectangle() + def get_formatter(self, **kwargs): + """ + Configuration is based first off instance attributes, + but overwritten by any kew word argument. Relevant + key words: + - include_sign + - group_with_commas + - num_decimal_places + - field_name (e.g. 0 or 0.real) + """ + config = dict(self.__dict__) + config.update(kwargs) + return reduce(op.add, [ + "{", + config.get("field_name", ""), + ":", + "+" if config["include_sign"] else "", + "," if config["group_with_commas"] else "", + ".", str(config["num_decimal_places"]), "f", + "}", + ]) + + def get_complex_formatter(self, **kwargs): + pass + class Integer(DecimalNumber): CONFIG = {