Example #1
0
    def update_theme(self, var, index, mode):
        """
        A callback function on the variable observer. Update existing theme if existing, otherwise, create a new theme
        and apply to app

        :param var: the name of the tkinter variable observed
        :param index: the index of the item (if an array)
        :param mode: the mode of the trace observer
        """
        theme_id = str(uuid.uuid4(
        ))  # a unique (and temporary) identifier for the new theme
        self.update_selector_image()

        try:
            colors = Colors(primary=self.getvar('primary'),
                            secondary=self.getvar('secondary'),
                            success=self.getvar('success'),
                            info=self.getvar('info'),
                            warning=self.getvar('warning'),
                            danger=self.getvar('danger'),
                            fg=self.getvar('fg'),
                            bg=self.getvar('bg'),
                            selectfg=self.getvar('selectfg'),
                            selectbg=self.getvar('selectbg'),
                            border=self.getvar('border'),
                            inputfg=self.getvar('inputfg'),
                            inputbg=self.getvar('inputbg'))
        except Exception:
            return

        try:
            self.style.register_theme(
                ThemeDefinition(name=theme_id,
                                themetype=self.getvar('type'),
                                font=self.getvar('font'),
                                colors=colors))

            # # attach the new theme to the style so that it is not garbage collected!!
            # self.new_style = StylerTTK(self.style, definition)
            self.style.theme_use(themename=theme_id)
        except Exception:
            return
Example #2
0
    def __init__(self, parent, **kwargs):
        excluded = [
            'anchor', 'theme', 'image', 'compound', 'relief', 'bordwidth',
            'maximum', 'value', 'variable', 'indicatorcolor', 'troughcolor',
            'textvariable', 'angle'
        ]
        kwargs_ = {k: v for k, v in kwargs.items() if k not in excluded}
        self.style = kwargs.get('style') or 'primary.TLabel'
        super().__init__(parent,
                         class_='RadialGauge',
                         style=self.style,
                         **kwargs_)

        self.indicatorcolor = kwargs.get('indicatorcolor') or self._lookup(
            self.style, 'foreground')
        self.indicatorthickness = kwargs.get('indicatorthickness') or 20
        self.troughcolor = kwargs.get('troughcolor') or Colors.update_hsv(
            self._lookup('TCombobox', 'background'), vd=-0.03)
        self.size = kwargs.get('size') or 200
        self.startangle = kwargs.get('angle') or 90
        self.im = Image.new('RGBA', (self.size, self.size))
        self.arc = ImageTk.PhotoImage(self.im)

        self.textvariable = kwargs.get('textvariable') or tk.StringVar(
            value=kwargs.get('text'))
        self.configure(textvariable=self.textvariable)
        self.variable = kwargs.get('variable') or tk.IntVar(
            value=kwargs.get('value'))
        self.variable.trace_add('write', self.update_indicator)

        self.maximum = 100 if kwargs.get('maximum') == None or kwargs.get(
            'maximum') <= 0 else kwargs.get('maximum')
        self.is_maximum = False

        self.configure(compound='center', anchor='center', image=self.arc)
        self.bind('<Configure>', self.resize)
Example #3
0
    def weekday_header(self):
        """Returns a list of weekdays to be used as a header in the calendar based on the firstweekday"""
        weekdays = ['Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa', 'Su']
        return weekdays[self.firstweekday:] + weekdays[:self.firstweekday]


if __name__ == '__main__':
    # TODO setup the styling in the __init__ file, and setup the class so that it can be easilily modified.
    # TODO add documentation to all classes and methods.
    # TODO reduce the padding on the DateEntry button for dark themes to account for the removed border on dark
    #   theme entry widgets.

    style = Style('lumen')
    pressed_vd = -0.2
    disabled_bg = (Colors.update_hsv(style.colors.inputbg, vd=-0.2) if style.theme.type == 'light' else
                   Colors.update_hsv(style.colors.inputbg, vd=-0.3))
    style.configure('calendar.primary.Outline.Toolbutton',
                    lightcolor=style.colors.bg,
                    darkcolor=style.colors.bg,
                    bordercolor=style.colors.bg)
    style.configure('exit.primary.TButton',
                    relief='flat',
                    font='helvetica 12')
    style.configure('chevron.primary.TButton', font='helvetica 14')
    style.map('exit.primary.TButton',
              background=[
                  ('disabled', disabled_bg),
                  ('pressed', '!disabled', Colors.update_hsv(style.colors.primary, vd=pressed_vd)),
                  ('hover', '!disabled', style.colors.danger)])
Example #4
0
    def __init__(self,
                 master=None,
                 arcrange=None,
                 arcoffset=None,
                 amounttotal=100,
                 amountused=0,
                 interactive=False,
                 labelfont='Helvetica 10 bold',
                 labelstyle='secondary.TLabel',
                 labeltext=None,
                 metersize=200,
                 meterstyle='primary.TLabel',
                 metertype='full',
                 meterthickness=10,
                 showvalue=True,
                 stripethickness=0,
                 textappend=None,
                 textfont='Helvetica 25 bold',
                 textprepend=None,
                 wedgesize=0,
                 **kw):
        """
        Args:
            master (Widget): Parent widget
            arcoffset (int): The amount to offset the arc's starting position in degrees; 0 is at 3 o'clock.
            arcrange (int): The range of the arc in degrees from start to end.
            amounttotal (int): The maximum value of the meter.
            amountused (int): The current value of the meter; displayed if ``showvalue=True``.
            interactive (bool): Enables the meter to be adjusted with mouse interaction.
            labelfont(Font or str): The font of the supplemental label.
            labelstyle (str): The ttk style used to render the supplemental label.
            labeltext (str): Supplemental label text that appears `below` the center text.
            metersize (int): The size of the meter; represented by one side length of a square.
            meterstyle (str): The ttk style used to render the meter and center text.
            metertype (str): One of **full** or **semi**; displays a full-circle or semi-circle.
            meterthickness (int): The thickness of the meter's progress bar.
            showvalue (bool): Show the meter's value in the center text; default = True.
            stripethickness (int): The meter's progress bar can be displayed in solid or striped form. If the value is
                greater than 0, the meter's progress bar changes from a solid to striped, where the value is the
                thickness of the stripes.
            textappend (str): A short string appended to the center text.
            textfont (Font or str): The font of the center text.
            textprepend (str): A short string prepended to the center text.
            wedgesize (int): If greater than zero, the width of the wedge on either side of the current meter value.
        """
        super().__init__(master=master, **kw)

        self.box = ttk.Frame(self, width=metersize, height=metersize)

        if metertype == 'semi':
            self.arcoffset = arcoffset if arcoffset is not None else 135
            self.arcrange = arcrange if arcrange is not None else 270
        else:  # aka 'full'
            self.arcoffset = arcoffset if arcoffset is not None else -90
            self.arcrange = arcrange if arcrange is not None else 360

        # widget variables
        self.amountusedvariable = IntVar(value=amountused)
        self.amounttotalvariable = IntVar(value=amounttotal)
        self.labelvariable = StringVar(value=labeltext)
        self.amountusedvariable.trace_add('write', self.draw_meter)

        # misc widget settings
        self.towardsmaximum = True
        self.metersize = metersize
        self.meterthickness = meterthickness
        self.stripethickness = stripethickness
        self.showvalue = showvalue
        self.wedgesize = wedgesize

        # translate system colors if a ttkbootstrap style is not used
        if 'system' in self.lookup(meterstyle, 'foreground').lower():
            self.meterforeground = self.convert_system_color(
                self.lookup(meterstyle, 'foreground'))
        else:
            self.meterforeground = self.lookup(meterstyle, 'foreground')
        if 'system' in self.lookup(meterstyle, 'background').lower():
            self.meterbackground = Colors.update_hsv(self.convert_system_color(
                self.lookup(meterstyle, 'background')),
                                                     vd=-0.1)
        else:
            self.meterbackground = Colors.update_hsv(self.lookup(
                meterstyle, 'background'),
                                                     vd=-0.1)

        # meter image
        self.meter = ttk.Label(self.box)
        self.draw_base_image()
        self.draw_meter()

        # text & label widgets
        self.textcontainer = ttk.Frame(self.box)
        self.textprepend = ttk.Label(self.textcontainer,
                                     text=textprepend,
                                     font=labelfont,
                                     style=labelstyle)
        self.textprepend.configure(anchor='s', padding=(0, 5))
        self.text = ttk.Label(self.textcontainer,
                              textvariable=self.amountusedvariable,
                              style=meterstyle,
                              font=textfont)
        self.textappend = ttk.Label(self.textcontainer,
                                    text=textappend,
                                    font=labelfont,
                                    style=labelstyle)
        self.textappend.configure(anchor='s', padding=(0, 5))
        self.label = ttk.Label(self.box,
                               text=labeltext,
                               style=labelstyle,
                               font=labelfont)

        # set interactive mode
        if interactive:
            self.meter.bind('<B1-Motion>', self.on_dial_interact)
            self.meter.bind('<Button-1>', self.on_dial_interact)

        # geometry management
        self.meter.place(x=0, y=0)
        self.box.pack()
        if labeltext:
            self.textcontainer.place(relx=0.5, rely=0.45, anchor='center')
        else:
            self.textcontainer.place(relx=0.5, rely=0.5, anchor='center')
        if textprepend:
            self.textprepend.pack(side='left', fill='y')
        if showvalue:
            self.text.pack(side='left', fill='y')
        if textappend:
            self.textappend.pack(side='left', fill='y')
        self.label.place(relx=0.5, rely=0.6, anchor='center')