class StatBox(BoxLayout):
    '''box for getting and displaying stats about rolls. parent app is what's
    called for dice actions and info updates. all calls are
    self.parent_app.request_something(*args).'''
    view_model = ObjectProperty(mvm.StatBox(mvm.DiceTableManager()))
    def __init__(self, **kwargs):
        super(StatBox, self).__init__(**kwargs)

    def display_stats(self, stat_text, vals):
        '''takes a stat title and two values, and displays them.'''
        self.ids['stat_text'].title = stat_text
        self.ids['slider_1'].value = vals[0]
        self.ids['slider_2'].value = vals[1]
    def update(self):
        '''called when dice list changes.'''
        val_1 = int(self.ids['slider_1'].value)
        val_2 = int(self.ids['slider_2'].value)
        info_text, stat_text, vals, min_max = self.view_model.display(val_1,
                                                                      val_2)
        self.ids['info_text'].title = info_text
        self.ids['slider_1'].max = self.ids['slider_2'].max = min_max[1]
        self.ids['slider_1'].min = self.ids['slider_2'].min = min_max[0]
        self.display_stats(stat_text, vals)
    def assign_text_value(self):
        '''called by text_input to assign that value to sliders and
        show stats'''
        val_1 = int(self.ids['slider_1_text'].title.replace(',', ''))
        val_2 = int(self.ids['slider_2_text'].title.replace(',', ''))
        self.ids['slider_1'].value = val_1
        self.ids['slider_2'].value = val_2
    def assign_slider_value(self):
        '''the main function. displays stats of current slider values.'''
        val_1 = int(self.ids['slider_1'].value)
        val_2 = int(self.ids['slider_2'].value)
        self.display_stats(*self.view_model.display_stats(val_1, val_2))
Beispiel #2
0
 def setUp(self):
     self.DTM = mvm.DiceTableManager()
     self.ST = mvm.SavedTables()
     self.interface = mvm.CurrentAndSavedInterface(self.DTM, self.ST)
     self.GB = mvm.GraphBox(self.DTM, self.ST, True)
     self.CB = mvm.ChangeBox(self.DTM)
     self.SB = mvm.StatBox(self.DTM)
     self.AB = mvm.AddBox(self.DTM)
     self.IB = mvm.InfoBox(self.DTM)
class ChangeBox(GridLayout):
    '''displays current dice and allows to change. parent app is what's called
    for dice actions and info updates. all calls are
    self.parent_app.request_something(*args).'''
    view_model = ObjectProperty(mvm.ChangeBox(mvm.DiceTableManager()))
    def __init__(self, **kwargs):
        super(ChangeBox, self).__init__(**kwargs)
        self.cols = 1
        self.old_dice = []
    def add_rm(self, btn):
        '''uses die stored in button and btn title to request add or rm'''
        self.view_model.add_rm(int(btn.title), btn.die)
        self.parent.parent.do_update()
    def reset(self, btn):
        '''resets current table back to empty and display instructions'''
        self.view_model.reset()
        self.parent.parent.do_update()
        self.clear_widgets()
        self.add_widget(Label(text=INTRO_TEXT, text_size=self.size,
                              valign='top', halign='center'))
    def update(self):
        '''updates the current dice after add, rm or clear'''
        new_dice = []
        button_list = self.view_model.display()
        self.clear_widgets()
        max_height = self.height/10
        reset = Button(text='reset table', on_press=self.reset,
                       size_hint=(1, None), height=0.75*max_height)
        self.add_widget(reset)
        if button_list:
            new_height = min((self.height - reset.height) / len(button_list),
                             max_height)
        for labels, die_ in button_list:
            temp = labels[:]
            labels = []
            for label in temp:
                if '50' not in label or 'D' in label:
                    labels.append(label)
            box = BoxLayout(size_hint=(0.8, None), height=new_height,
                            orientation='horizontal')
            self.add_widget(box)
            x_hint = round(1./(len(labels) + 2), 2)
            for label in labels:
                if label[0] == '-' or label[0] == '+':
                    btn = FlashButton(
                        text=label, size_hint=(x_hint, 1), die=die_,
                        on_press=lambda btn: btn.delay(self.add_rm, btn)
                        )
                    box.add_widget(btn)
                else:
                    flash = FlashLabel(text=label, size_hint=(3 * x_hint, 1))
                    box.add_widget(flash)
                    new_dice.append(label)
                    if label not in self.old_dice:
                        Clock.schedule_once(flash.flash_it, 0.01)
        self.old_dice = new_dice
Beispiel #4
0
    def __init__(self, master):
        self.frame = tk.Frame(master)
        self.frame.columnconfigure(0, minsize=300, weight=1)
        self.frame.rowconfigure(0, weight=1)
        self.frame.rowconfigure(0, weight=1)
        self.frame.pack()
        table = mvm.DiceTableManager()
        history = mvm.SavedTables()

        # reloads history file.  if corrupted, notifies and writes an empty hist
        hist_msg = history.reload_from_file()
        if 'ok' not in hist_msg and hist_msg != 'error: no file':
            msgbox.showinfo('Error', 'Error loading history:\n' + hist_msg)
            history.write_to_file()
        change = mvm.ChangeBox(table)
        add = mvm.AddBox(table)
        stat = mvm.StatBox(table)
        self.menus = GraphMenu(self, mvm.GraphBox(table, history, True))
        self.info = mvm.InfoBox(table)
        self.change_box = ChangeBox(self)
        self.change_box.view_model = change
        self.add_box = AddBox(self)
        self.add_box.view_model = add
        self.stat_box = StatBox(self, stat)
        # self.stat_box.view_model = stat


        self.change_box.frame.grid(row=0, column=0, rowspan=2, sticky=tk.NSEW)
        self.change_box.frame.config(borderwidth=5, relief=tk.GROOVE)
        self.add_box.frame.grid(row=0, column=1, sticky=tk.NSEW)
        self.add_box.frame.config(borderwidth=5, relief=tk.GROOVE)
        self.stat_box.frame.grid(row=1, column=1, sticky=tk.NSEW)
        self.stat_box.frame.config(borderwidth=5, relief=tk.GROOVE)

        # the info frame
        info_frame = tk.Frame(self.frame, borderwidth=5, relief=tk.GROOVE)
        info_frame.grid(row=0, column=3, rowspan=2, sticky=tk.NSEW)
        label_btn = tk.Frame(info_frame)
        label_btn.pack(fill=tk.X)
        info_lbl = tk.Label(label_btn, fg='white', bg='blue',
                            text='here are all the rolls\nand their frequency')
        info_lbl.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        tk.Button(label_btn, text='Weights\ninfo', bg='light yellow',
                  command=self.weight_info).pack(side=tk.LEFT, padx=5, pady=5)
        text_scrollbar = tk.Scrollbar(info_frame)
        text_scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        self.info_text = tk.Text(info_frame, yscrollcommand=text_scrollbar.set,
                                 width=20)
        self.info_text.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        text_scrollbar.config(command=self.info_text.yview)

        self.frame.columnconfigure(0, minsize=300, weight=1)
        self.do_update()
 def __init__(self, **kwargs):
     super(DicePlatform, self).__init__(**kwargs)
     table = mvm.DiceTableManager()
     history = mvm.SavedTables()
     self._read_hist_msg = history.reload_from_file()
     change = mvm.ChangeBox(table)
     add = mvm.AddBox(table)
     stat = mvm.StatBox(table)
     graph = mvm.GraphBox(table, history, False)
     info = mvm.InfoBox(table)
     self.ids['change_box'].view_model = change
     self.ids['add_box'].view_model = add
     self.ids['stat_box'].view_model = stat
     self.ids['graph_box'].view_model = graph
     self.ids['info_box'].view_model = info
     self.initializer()
class InfoBox(BoxLayout):
    '''displays basic info about the die.'''
    view_model = ObjectProperty(mvm.InfoBox(mvm.DiceTableManager()))
    def __init__(self, **kwargs):
        super(InfoBox, self).__init__(**kwargs)
    def initialize(self):
        '''called at main app init. workaround for kv file loading after py'''
        self.ids['full_text'].set_title(
            'here are all the rolls and their frequency'
            )
        self.ids['full_text'].ids['page_box_title'].font_size *= 0.75
        self.ids['weights_info'].reset_sizes([0.1, 0.1, 0.80])
        self.ids['weights_info'].set_title('full weight info')
    def choose(self, slider, key):
        '''chooses a page for pagebox with key=string-which box to display in.
        value=int-page number.'''
        lines = self.ids[key].get_lines_number()
        #reversing the slider
        page = int(slider.max) + int(slider.min) - int(slider.value)
        self.ids[key].set_text(*self.view_model.display_chosen_page(page, key))
    def previous(self, key):
        '''displays previous page and updates view for pagebox[key=string]'''
        lines = self.ids[key].get_lines_number()
        self.ids[key].set_text(*self.view_model.display_previous_page(key))
    def next(self, key):
        '''displays next page and updates view for pagebox[key=string]'''
        lines = self.ids[key].get_lines_number()
        self.ids[key].set_text(*self.view_model.display_next_page(key))
    def update(self):
        '''updates views for all parts of the box.'''
        all_info = self.view_model.display_paged(
            self.ids['weights_info'].get_lines_number(),
            self.ids['full_text'].get_lines_number()
            )
        self.ids['general_info'].title = all_info[0]
        self.ids['table_str'].title = all_info[1]
        self.ids['weights_info'].set_text(*all_info[2])
        self.ids['full_text'].set_text(*all_info[3])
Beispiel #7
0
 def __init__(self, master):
     """master is an object that has master.frame."""
     self.master = master
     self.frame = tk.Frame(master.frame)
     self.view_model = mvm.ChangeBox(mvm.DiceTableManager())
Beispiel #8
0
    def __init__(self, master):
        """master is an object that has master.frame."""
        self.master = master
        self.frame = tk.Frame(master.frame)

        self.frame.grid_columnconfigure(0, pad=20)
        self.frame.grid_columnconfigure(1, pad=20)
        self.frame.grid_columnconfigure(2, pad=20)
        self.frame.grid_columnconfigure(3, pad=20)

        self.view_model = mvm.AddBox(mvm.DiceTableManager())

        self.current = tk.StringVar()
        self.current.set('\n\n\n\n')
        tk.Label(self.frame, textvariable=self.current).grid(
            column=0, row=0, sticky=tk.W + tk.E + tk.S + tk.N,
            columnspan=4)

        any_size_lbl = tk.Label(self.frame, text='may input\nany size')
        any_size_lbl.grid(column=0, row=1)
        ToolTip(any_size_lbl,
                'type in a die size between 2 and 200 and press enter.', 250)
        weights = tk.Button(self.frame, text='make\nweights', bg='thistle1',
                            command=self.add_weights)
        weights.grid(column=1, row=1, rowspan=2)
        weights_text = ('A two-sided die with weights 1:4, 2:1 means that it ' +
                        'rolls a one 4 times as often as a 2')
        ToolTip(weights, weights_text, 200)
        strength_lbl = tk.Label(self.frame, text='strength')
        strength_lbl.grid(column=2, row=1)
        strength_text = 'A three-sided die X4 rolls 4, 8, 12 instead of 1, 2, 3'
        ToolTip(strength_lbl, strength_text, 200)
        mod_label = tk.Label(self.frame, text='die\nmodifier')
        mod_label.grid(column=3, row=1)
        ToolTip(mod_label, 'D3+2 rolls 3, 4, 5 instead of 1, 2, 3', 200)

        self.any_size = NumberInput(self.frame, width=10, bg='thistle1')
        self.any_size.bind('<Return>', self.assign_size_text)
        self.any_size.grid(column=0, row=2)

        multiplier = tk.StringVar()
        multiplier.set('X1')
        multiplier.trace('w', partial(self.assign_multiplier, multiplier))
        strength = tk.OptionMenu(self.frame, multiplier,
                                 *['X{}'.format(num) for num in range(1, 11)])
        strength.config(bg='thistle1', activebackground='thistle1')
        strength.grid(column=2, row=2)

        mod = tk.Scale(self.frame, from_=5, to=-5, command=self.assign_mod,
                       bg='thistle1', activebackground='thistle1')
        mod.grid(column=3, row=2, rowspan=2)

        preset = tk.Frame(self.frame)
        for index, preset_text in enumerate(self.view_model.presets):
            btn = tk.Button(preset, text=preset_text, bg='thistle1',
                            command=partial(self.assign_size_btn, preset_text))
            row_, col_ = divmod(index, 4)
            btn.grid(row=row_, column=col_, padx=5)
        preset.grid(column=0, row=3, sticky=tk.NSEW, columnspan=3)
        instruct = tk.Label(self.frame, text=50 * '-', bg='PaleTurquoise1')
        instruct.grid(column=0, row=4, sticky=tk.NSEW, columnspan=4)
        instructions = ('Use buttons above to create the die you want. ' +
                        'Then use the "+" buttons below to add it to the table')
        ToolTip(instruct, instructions, 200)
        self.adder = tk.Frame(self.frame)
        self.adder.grid(column=0, row=5, sticky=tk.NSEW, columnspan=4)

        self.display_die()
class GraphBox(BoxLayout):
    '''buttons for making graphs.  parent app is what's called for dice actions
    and info updates. all calls are self.parent_app.request_something(*args).'''
    view_model = ObjectProperty(mvm.GraphBox(mvm.DiceTableManager(),
                                             mvm.SavedTables(), True))
    def __init__(self, **kwargs):
        super(GraphBox, self).__init__(**kwargs)
        self.confirm = Popup(title='Delete everything?', content=BoxLayout(),
                             size_hint=(0.8, 0.4), title_align='center',
                             title_size=75)
        self.confirm.content.add_widget(Button(text='EVERY\nTHING!!!',
                                               on_press=self.clear_all,
                                               texture_size=self.size))
        self.confirm.content.add_widget(Button(text='never\nmind',
                                               on_press=self.confirm.dismiss))

    def initialize(self):
        '''called at main app init. workaround for kv file loading after py'''
        self.ids['graph_space'].add_widget(PlotCheckBox(size_hint=(1, 0.5),
                                                        parent_obj=self))
        self.update()
    def update(self):
        '''updates the current window to display new graph history and current
        table to graph'''
        current, history = self.view_model.display()
        #sz_hint for 'past graphs' label to take up all the space
        #base_y make sure other widgets fit
        rows = len(history) + 3
        base_y = .99/rows
        if base_y > 0.1:
            base_y = 0.1
        sz_hint = (1, 1 - (rows - 1) * base_y)
        self.ids['graph_space'].clear_widgets()
        self.ids['graph_space'].add_widget(Label(text='past graphs',
                                                 halign='center',
                                                 size_hint=sz_hint))
        for text_, tuple_list_ in history:
            check = PlotCheckBox(size_hint=(0.79, base_y), active=False,
                                 tuple_list=tuple_list_)
            reload_ = FlashButton(
                size_hint=(0.2, base_y), lst=[text_, tuple_list_], max_lines=1,
                text='reload_saved_dice_table', valign='middle', halign='center',
                on_press=lambda btn: btn.delay(self.reload, btn)
                )
            self.ids['graph_space'].add_widget(check)
            self.ids['graph_space'].add_widget(reload_)
            check.text = text_
        self.ids['graph_space'].add_widget(Label(text='new table',
                                                 size_hint=(1, base_y)))
        check = PlotCheckBox(size_hint=(1, base_y), active=True,
                             tuple_list=current[1])
        self.ids['graph_space'].add_widget(check)
        check.text = current[0]
        Clock.schedule_once(lambda dt: check.ids['label'].flash_it(), 0.01)
    def reload(self, btn):
        '''reloads from history to current table'''
        self.view_model.reload_saved_dice_table(btn.lst[0], btn.lst[1])
        self.parent.parent.do_update()
    def graph_it(self):
        '''prepares plot and calls PlotPopup'''
        to_plot = []
        for item in self.ids['graph_space'].children[:]:
            if isinstance(item, PlotCheckBox):
                if item.active:
                    to_plot.append((item.text, item.tuple_list))
        plots = self.view_model.get_requested_graphs(to_plot)
        self.update()
        if plots[2]:
            plotter = PlotPopup(*plots)
            plotter.open()
    def clear_all(self, btn):
        '''clear graph history'''
        self.confirm.dismiss()
        self.view_model.delete_all()
        self.update()
    def clear_selected(self):
        '''clear selected checked items from graph history'''
        to_clear = []
        for item in self.ids['graph_space'].children[1:]:
            if isinstance(item, PlotCheckBox):
                if item.active:
                    to_clear.append((item.text, item.tuple_list))
        self.view_model.delete_requested(to_clear)
        self.update()
class AddBox(BoxLayout):
    '''box for adding new dice.  parent app is what's called for dice actions
    and info updates. all calls are self.parent_app.request_something(*args).'''
    view_model = ObjectProperty(mvm.AddBox(mvm.DiceTableManager()))
    def __init__(self, **kwargs):
        super(AddBox, self).__init__(**kwargs)
    def initialize(self):
        '''called at main app init. workaround for kv file loading after py'''
        for preset_text in self.view_model.presets:
            btn = Button(text=preset_text, on_press=self.assign_size_btn)
            self.ids['presets'].add_widget(btn)
        self.ids['multiplier'].bind(text=self.assign_multiplier)
        self.display_die()
    def update(self):
        '''called by main app at dice change'''
        self.ids['current'].title = (self.view_model.display_current_table())
    def assign_size_btn(self, btn):
        '''assigns the die size and die when a preset btn is pushed'''
        die_size = int(btn.title[1:])
        self.view_model.set_size(die_size)
        self.display_die()
    def assign_size_text(self, text):
        '''asigns the die size and die when title is entered'''
        top = 200
        bottom = 2
        int_string = text
        if int_string:
            die_size = int(text)
            die_size = min(top, max(bottom, die_size))
        if text != str(die_size):
            self.ids['custom_input'].title = str(die_size)
        self.view_model.set_size(die_size)
        self.display_die()
    def assign_mod(self):
        '''assigns a die modifier and new die when slider is moved'''
        mod = int(self.ids['modifier'].value)
        self.view_model.set_mod(mod)
        self.display_die()
    def assign_multiplier(self, spinner, text):
        '''assigns a die multiplier and new_die based on spinner's title.'''
        multiplier = int(text[1:])
        self.view_model.set_multiplier(multiplier)
        self.display_die()
    def display_die(self):
        '''all changes to size, mod and weight call this function'''
        self.ids['add_it'].clear_widgets()
        to_add = self.view_model.display_die()
        x_hint = round(1./(len(to_add) + 1), 2)
        flash = FlashLabel(text=to_add[0], size_hint=(2*x_hint, 1))
        self.ids['add_it'].add_widget(flash)
        flash.flash_it()
        for add_val in to_add[1:]:
            btn = FlashButton(text=add_val, size_hint=(x_hint, 1),
                              on_press=lambda btn: btn.delay(self.add, btn))
            self.ids['add_it'].add_widget(btn)
    def add(self, btn):
        '''uses btn title and die stored in view_model to add to current table'''
        self.view_model.add(int(btn.title))
        self.parent.parent.do_update()
    def record_weights(self, text_val_lst):
        '''takes a list of [('weight for <roll>', int=the_weight)...] and makes
        a weighted die with it.'''
        self.view_model.record_weights_text(text_val_lst)
        self.display_die()
    def add_weights(self):
        '''opens the weightpopup and sizes accordingly'''
        popup = WeightsPopup(self, self.view_model.get_weights_text())
        popup.open()