Beispiel #1
0
        def askSpan(orient='v'):
            win = Toplevel()
            pxmin = LabeledEntry(win)
            pxmin.pack()
            pxmin.label_text = 'xmin' if orient == 'v' else 'ymin'
            pxmax = LabeledEntry(win)
            pxmax.pack()
            pxmax.label_text = 'xmax' if orient == 'v' else 'ymax'

            def formatter(val):
                val = float(val)
                val /= 100.
                return '{0:0.2f}'.format(val)

            alphaScale = LabeledScale(win,
                                      from_=0,
                                      to=100,
                                      name='alpha',
                                      formatter=formatter)
            alphaScale.set(50.0)
            alphaScale.pack()
            win.protocol('WM_DELETE_WINDOW', win.quit)
            win.focus_set()
            win.grab_set()
            win.mainloop()
            xmin = pxmin.entry.get()
            xmax = pxmax.entry.get()
            alpha = alphaScale.get() / 100.
            win.destroy()
            return map(float, (xmin, xmax, alpha))
Beispiel #2
0
    def append_algorithm(self, algorithm):
        #To do: when algo is reset, the frm should be removed
        for algoName in self.__frameDict:
            self.__frameDict[algoName]['frame'].pack_forget()
        frm = Frame(self)
        frm.pack()
        paramInfo = {}
        params = algorithm['parameters']
        for index, name in enumerate(params):
            param = params[name]
            paramitem = LabeledEntry(frm)
            paramitem.label_text = name
            paramitem.label_width = 5
            paramitem.entry_width = 8
            if self.balloon:
                tip = f'''{param.shortdesc}

Type: {param.type.__name__}.'''
                self.balloon.bind_widget(paramitem.label, balloonmsg=tip)
            if param.type is int:
                paramitem.checker_function = self._app.gui.value_checker.check_int
            elif param.type is float:
                paramitem.checker_function = self._app.gui.value_checker.check_float
            paramitem.grid(row=index % self.__MAXROW,
                           column=index // self.__MAXROW)
            #self.__params[param.name] = {'gui':paramitem, 'meta':param}
            paramInfo[param.name] = {'gui': paramitem, 'meta': param}
        self.__algo = algorithm
        #self.__frameDict[algorithm.meta.name]   = frm
        self.__frameDict[algorithm['name']] = dict(frame=frm,
                                                   paramInfo=paramInfo)
        self.__params = paramInfo
Beispiel #3
0
    def __init__(self, *args, **kwargs):
        self._app = Scripting.root_node
        self.__gui_images = []
        self.__topwin = kwargs.pop('topwin')
        super().__init__(*args, **kwargs)

        imageMLbl = ImageTk.PhotoImage(
            file=Scripting.root_node.get_gui_image_path(
                'arrayelemnum20x20.png'))
        self.__gui_images.append(imageMLbl)
        self.__M = LabeledEntry(self)
        self.__M.label.config(text='M', image=imageMLbl, compound='left')
        self.__M.entry_width = 6
        self.__M.entry_text = 10
        self.__M.entry.bind('<Return>',
                            lambda dumb: self._on_solve_button_click())
        self.__M.checker_function = self._app.gui.value_checker.check_int
        self.__M.pack()

        self._app.gui.balloon.bind_widget(
            self.__M, balloonmsg='The number of the array elements.')

        image_solve = ImageTk.PhotoImage(
            file=Scripting.root_node.get_gui_image_path('run20x20.png'))
        self.__gui_images.append(image_solve)

        self.__btnSolve = Button(self,
                                 text='Solve',
                                 image=image_solve,
                                 compound='left',
                                 command=self._on_solve_button_click)
        self.__btnSolve.pack(side='top', fill='x')
        self._app.gui.balloon.bind_widget(
            self.__btnSolve,
            balloonmsg='Launch the solver to synthesize the correlation matrix.'
        )

        image_display = ImageTk.PhotoImage(
            file=Scripting.root_node.get_gui_image_path(
                'Pattern_Display_Button.png'))
        self.__gui_images.append(image_display)
        self.__bDisplay = IntVar(0)
        chk_display = Checkbutton(self,
                                  text="Verbose",
                                  image=image_display,
                                  compound='left',
                                  variable=self.__bDisplay)
        chk_display.pack(side='top')
        self._app.gui.balloon.bind_widget(chk_display,
                                          balloonmsg='Display solver output.')
        chk_display_width = chk_display.winfo_width()
        self.__btnSolve['width'] = chk_display_width

        self.name = 'Optimize'
Beispiel #4
0
def show(dataframe):
    win = Toplevel()
    win.title("WaveSyn-DataFrameDisplay")
    query_entry = LabeledEntry(win)
    query_entry.pack(fill="x", expand="no")
    query_entry.label_text = "Query:"

    def query_func(event):
        if event.keysym == "Return":
            new_df = dataframe.query(query_entry.entry_text)
            show(new_df)

    query_entry.entry.bind("<Key>", query_func)
    st = ScrolledTree(win)
    st.pack(fill="both", expand="yes")
    st.load_dataframe(dataframe)
Beispiel #5
0
    def __init__(self, *args, **kwargs):
        if 'value_checker' in kwargs:
            value_checker = kwargs.pop('value_checker')
            check_float = value_checker.check_float
        else:
            check_float = None

        if 'balloon' in kwargs:
            balloon_bind_widget = kwargs.pop('balloon').bind_widget
        else:
            balloon_bind_widget = lambda *args, **kwargs: None

        super(AxisGroup, self).__init__(*args, **kwargs)
        self.__params = [StringVar() for i in range(8)]
        paramfrm = Frame(self)
        paramfrm.pack()
        names = [
            'xmin', 'xmax', 'ymin', 'ymax', 'major xtick', 'major ytick',
            'minor xtick', 'minor ytick'
        ]
        images = [
            'xmin20x20.png', 'xmax20x20.png', 'ymin20x20.png', 'ymax20x20.png',
            'ViewTab_MajorXTick.png', 'ViewTab_MajorYTick.png',
            'ViewTab_MinorXTick.png', 'ViewTab_MinorYTick.png'
        ]
        for c in range(4):
            for r in range(2):
                temp = LabeledEntry(paramfrm)
                #image   = ImageTk.PhotoImage(file=Scripting.root_node.get_gui_image_path(images[c*2+r]))
                set_attributes(temp,
                               checker_function=check_float,
                               label_common_icon=images[c * 2 + r],
                               label_width=5 if c * 2 + r < 4 else 10,
                               entry_width=5,
                               entry_variable=self.__params[c * 2 + r])
                temp.entry.bind('<Return>', self._on_confirm_button_click)
                temp.grid(row=r, column=c)
                balloon_bind_widget(temp, balloonmsg=names[c * 2 + r])

        btnfrm = Frame(self)
        btnfrm.pack()
        Button(btnfrm, text='Confirm',
               command=self._on_confirm_button_click).pack(side='left')
        Button(btnfrm, text='Auto',
               command=self._on_auto_button_click).pack(side='right')
        self.name = 'Axis'
        self.__figure_observer = self.FigureObserver(self)
Beispiel #6
0
        def askgridprop():
            win = Toplevel()
            color = ['#000000', '#000000']

            propvars = [StringVar() for i in range(4)]
            guidata = ({
                'linestyle': ('Major Line Style', propvars[0], None),
                'linewidth':
                ('Major Line Width', propvars[1], check_nonnegative_float)
            }, {
                'linestyle': ('Minor Line Style', propvars[2], None),
                'linewidth':
                ('Minor Line Width', propvars[3], check_nonnegative_float)
            })

            for d in guidata:
                for key in d:
                    pitem = LabeledEntry(win)
                    pitem.pack()
                    pitem.label_text = d[key][0]
                    pitem.entry['textvariable'] = d[key][1]
                    if d[key][2]:
                        pitem.checker_function = d[key][2]

            def setmajorcolor():
                c = askcolor()
                color[0] = c[1]

            def setminorcolor():
                c = askcolor()
                color[1] = c[1]

            Button(win, text='Major Line Color', command=setmajorcolor).pack()
            Button(win, text='Minor Line Color', command=setminorcolor).pack()

            win.protocol('WM_DELETE_WINDOW', win.quit)
            win.focus_set()
            win.grab_set()
            win.mainloop()
            win.destroy()

            c_major = StringVar()
            c_major.set(color[0])
            c_minor = StringVar()
            c_minor.set(color[1])
            guidata[0]['color'] = ('Major Line Color', c_major, None)
            guidata[1]['color'] = ('Minor Line Color', c_minor, None)
            return guidata
Beispiel #7
0
        def __init__(self, *args, **kwargs):
            timer       = kwargs.pop('timer')
            self.__timer    = timer
            
            super().__init__(*args, **kwargs)
            interval    = LabeledEntry(self)
            interval.label_text  = 'Interval (ms)'
            interval.entry_text  = str(timer.interval)
            interval.entry_width = 5
            interval.pack(side='top')
            self.interval   = interval
            
            self.active   = IntVar(timer.active)
            Checkbutton(self, text='Activate', variable=self.active, command=self._on_active_button_click).pack(side='top')
            Button(self, text='OK', command=self._on_ok_button_click).pack(side='top')
            
            def hide(): self.visible    = False
            self.protocol('WM_DELETE_WINDOW', hide)

            self.__visible  = True
            self.visible = False
Beispiel #8
0
 def __init__(self, *args, **kwargs):
     #self._app = app = Application.instance
     self.__topwin = kwargs.pop('topwin')
     Group.__init__(self, *args, **kwargs)
     Button(self, text='Load *.mat', command=self.onLoadClick).pack()
     paramX = LabeledEntry(self)
     paramX.label_text = 'x = '
     paramX.entry_width = 6
     paramX.pack()
     self.__paramX = paramX
     paramY = LabeledEntry(self)
     paramY.label_text = 'y = '
     paramY.entry_width = 6
     paramY.pack()
     self.__paramY = paramY
     self.name = 'Load'
Beispiel #9
0
    def __init__(self, *args, **kwargs):
        self._app = kwargs.pop('wavesyn_root')
        self.__topwin = kwargs.pop('topwin')

        super().__init__(*args, **kwargs)

        parameter_frame = Frame(self)
        parameter_frame.pack(side='left', expand='yes', fill='y')
        self.__num = LabeledEntry(parameter_frame)
        set_attributes(self.__num,
                       label_text='num',
                       entry_text='1',
                       label_width=5,
                       entry_width=8,
                       checker_function=self._app.gui.value_checker.check_int)
        self.__num.entry.bind('<Return>', lambda event: self._on_solve_click())
        self.__num.pack(side='top')

        self.__pci = LabeledEntry(parameter_frame)
        set_attributes(self.__pci,
                       label_text='PCI',
                       entry_text='100',
                       label_width=5,
                       entry_width=8,
                       checker_function=self._app.gui.value_checker.check_int)
        self.__pci.pack(side='top')

        self.__parallel_checker_variable = IntVar()
        self.__parallel_checker = Checkbutton(
            parameter_frame,
            text="Parallel",
            variable=self.__parallel_checker_variable,
            command=self._on_parallel_checker_click)
        self.__parallel_checker.pack()

        progfrm = Frame(self)
        progfrm.pack(side='left', expand='yes', fill='y')

        self.__genbtn = Button(progfrm,
                               text='Generate',
                               command=self._on_solve_click)
        self.__genbtn.pack(side='top')
        Button(progfrm, text='Stop',
               command=self._on_stop_button_click).pack(side='top')

        self.__progressbar_variable = IntVar()
        self.__finishedwav = IntVar()
        self.__progressbar = Progressbar(progfrm,
                                         orient='horizontal',
                                         variable=self.__progressbar_variable,
                                         maximum=100)
        self.__progressbar.pack(side='left')
        self.__progressbar.config(length=55)
        self.__finishedwavbar = Progressbar(progfrm,
                                            orient='horizontal',
                                            variable=self.__finishedwav)
        self.__finishedwavbar.pack(side='left')
        self.__finishedwavbar.config(length=30)

        self.name = 'Generate'

        self.getparams = None
        self.__stopflag = False
Beispiel #10
0
class OptimizeGroup(Group):
    def __init__(self, *args, **kwargs):
        self._app = kwargs.pop('wavesyn_root')
        self.__topwin = kwargs.pop('topwin')

        super().__init__(*args, **kwargs)

        parameter_frame = Frame(self)
        parameter_frame.pack(side='left', expand='yes', fill='y')
        self.__num = LabeledEntry(parameter_frame)
        set_attributes(self.__num,
                       label_text='num',
                       entry_text='1',
                       label_width=5,
                       entry_width=8,
                       checker_function=self._app.gui.value_checker.check_int)
        self.__num.entry.bind('<Return>', lambda event: self._on_solve_click())
        self.__num.pack(side='top')

        self.__pci = LabeledEntry(parameter_frame)
        set_attributes(self.__pci,
                       label_text='PCI',
                       entry_text='100',
                       label_width=5,
                       entry_width=8,
                       checker_function=self._app.gui.value_checker.check_int)
        self.__pci.pack(side='top')

        self.__parallel_checker_variable = IntVar()
        self.__parallel_checker = Checkbutton(
            parameter_frame,
            text="Parallel",
            variable=self.__parallel_checker_variable,
            command=self._on_parallel_checker_click)
        self.__parallel_checker.pack()

        progfrm = Frame(self)
        progfrm.pack(side='left', expand='yes', fill='y')

        self.__genbtn = Button(progfrm,
                               text='Generate',
                               command=self._on_solve_click)
        self.__genbtn.pack(side='top')
        Button(progfrm, text='Stop',
               command=self._on_stop_button_click).pack(side='top')

        self.__progressbar_variable = IntVar()
        self.__finishedwav = IntVar()
        self.__progressbar = Progressbar(progfrm,
                                         orient='horizontal',
                                         variable=self.__progressbar_variable,
                                         maximum=100)
        self.__progressbar.pack(side='left')
        self.__progressbar.config(length=55)
        self.__finishedwavbar = Progressbar(progfrm,
                                            orient='horizontal',
                                            variable=self.__finishedwav)
        self.__finishedwavbar.pack(side='left')
        self.__finishedwavbar.config(length=30)

        self.name = 'Generate'

        self.getparams = None
        self.__stopflag = False

    def _on_solve_click(self):
        params = self.__topwin.parameter_group.get_parameters()
        repeat_times = self.__num.get_int()

        if self.__parallel_checker_variable.get():
            run = self.__topwin.current_algorithm.process_run
        else:
            run = self.__topwin.current_algorithm.thread_run
        with code_printer():
            run(on_finished=['store', 'draw'],
                progress_indicator='progress_dialog',
                repeat_times=repeat_times,
                **params)

    def _on_stop_button_click(self):
        self.__stopflag = True

    def _on_parallel_checker_click(self):
        topwin = self.__topwin
        if topwin.current_algorithm.need_cuda:
            self.__parallel_checker_variable.set(0)
            topwin.root_node.gui.dialogs.report(f'''{topwin.node_path}:
Current algorithm "{topwin.current_algorithm.meta.name}" need CUDA worker, which does not support multi-cpu parallel.
            ''')

    def _cancel_parallel(self):
        self.__parallel_checker_variable.set(0)
Beispiel #11
0
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        label_width = 5
        unit_combobox_width = 4

        lambda_ent = PhysicalQuantityEntry(self, 
            unit_info=_length_units,
            default_unit_name="m")
        lambda_ent.label_text = "λ"
        lambda_ent.label_width = label_width
        lambda_ent.unit_combobox_width = unit_combobox_width
        lambda_ent.pack(expand=tk.YES, fill=tk.X)

        d_ent = PhysicalQuantityEntry(self,
            unit_info=_length_units,
            default_unit_name="m")
        d_ent.label_text = "d"
        d_ent.label_width = label_width
        d_ent.unit_combobox_width = unit_combobox_width
        d_ent.pack(expand=tk.YES, fill=tk.X)

        N_ent = LabeledEntry(self)
        N_ent.label_text = "N"
        N_ent.label_width = label_width
        N_ent.pack(expand=tk.YES, fill=tk.X)

        theta_ent = PhysicalQuantityEntry(self,
            unit_info=_angle_units,
            default_unit_name="deg")
        theta_ent.label_text = "θ"
        theta_ent.label_width = label_width
        theta_ent.unit_combobox_width = unit_combobox_width
        theta_ent.pack(expand=tk.YES, fill=tk.X)

        k_ent = LabeledEntry(self)
        k_ent.label_text = "k"
        k_ent.label_width = label_width
        k_ent.pack(expand=tk.YES, fill=tk.X)
Beispiel #12
0
class OptimizeGroup(Group):
    def __init__(self, *args, **kwargs):
        self._app = Scripting.root_node
        self.__gui_images = []
        self.__topwin = kwargs.pop('topwin')
        super().__init__(*args, **kwargs)

        imageMLbl = ImageTk.PhotoImage(
            file=Scripting.root_node.get_gui_image_path(
                'arrayelemnum20x20.png'))
        self.__gui_images.append(imageMLbl)
        self.__M = LabeledEntry(self)
        self.__M.label.config(text='M', image=imageMLbl, compound='left')
        self.__M.entry_width = 6
        self.__M.entry_text = 10
        self.__M.entry.bind('<Return>',
                            lambda dumb: self._on_solve_button_click())
        self.__M.checker_function = self._app.gui.value_checker.check_int
        self.__M.pack()

        self._app.gui.balloon.bind_widget(
            self.__M, balloonmsg='The number of the array elements.')

        image_solve = ImageTk.PhotoImage(
            file=Scripting.root_node.get_gui_image_path('run20x20.png'))
        self.__gui_images.append(image_solve)

        self.__btnSolve = Button(self,
                                 text='Solve',
                                 image=image_solve,
                                 compound='left',
                                 command=self._on_solve_button_click)
        self.__btnSolve.pack(side='top', fill='x')
        self._app.gui.balloon.bind_widget(
            self.__btnSolve,
            balloonmsg='Launch the solver to synthesize the correlation matrix.'
        )

        image_display = ImageTk.PhotoImage(
            file=Scripting.root_node.get_gui_image_path(
                'Pattern_Display_Button.png'))
        self.__gui_images.append(image_display)
        self.__bDisplay = IntVar(0)
        chk_display = Checkbutton(self,
                                  text="Verbose",
                                  image=image_display,
                                  compound='left',
                                  variable=self.__bDisplay)
        chk_display.pack(side='top')
        self._app.gui.balloon.bind_widget(chk_display,
                                          balloonmsg='Display solver output.')
        chk_display_width = chk_display.winfo_width()
        self.__btnSolve['width'] = chk_display_width

        self.name = 'Optimize'

    def _on_solve_button_click(self):
        with code_printer():
            topwin = self.__topwin
            beam_data = topwin.edit_group.beam_data
            if not beam_data:
                showerror(
                    'Error',
                    'Please input the specification of the ideal beam pattern.'
                )
                return
            topwin.figure_book.clear()
            topwin.set_ideal_pattern(*beam_data)
            topwin.plot_ideal_pattern()

        M = self.__M.get_int()
        display = self.__bDisplay.get()

        with code_printer():
            topwin.solve.new_thread_run(M=M,
                                        verbose=bool(display),
                                        on_finish=["draw"])
Beispiel #13
0
    def __init__(self, *args, **kwargs):
        self._app = Scripting.root_node
        self.__topwin = kwargs.pop('topwin')
        super().__init__(*args, **kwargs)
        frm = Frame(self)

        self.__center = LabeledEntry(frm)
        set_attributes(self.__center,
                       label_text='center(deg)',
                       entry_text=0,
                       checker_function=self._app.gui.value_checker.check_int,
                       entry_width=5,
                       label_width=10)
        self.__center.pack(side='top')
        self._app.gui.balloon.bind_widget(
            self.__center, balloonmsg='Specify the beam center here.')

        self.__width = LabeledEntry(frm)
        set_attributes(self.__width,
                       label_text='width(deg)',
                       entry_text=20,
                       checker_function=self._app.gui.value_checker.check_int,
                       entry_width=5,
                       label_width=10)
        self.__width.pack(side='top')
        self._app.gui.balloon.bind_widget(
            self.__width, balloonmsg='Specify the beam width here.')

        self.__gui_images = []

        imageAddBtn = ImageTk.PhotoImage(
            file=Scripting.root_node.get_gui_image_path(
                'Pattern_Add_Button.png'))
        self.__gui_images.append(imageAddBtn)
        btn = Button(frm, image=imageAddBtn, command=self._on_add_button_click)
        btn.pack(side='left')
        self._app.gui.balloon.bind_widget(
            btn, balloonmsg='Add new beam to the ideal pattern.')

        imageDelBtn = ImageTk.PhotoImage(
            file=Scripting.root_node.get_gui_image_path(
                'Pattern_Del_Button.png'))
        self.__gui_images.append(imageDelBtn)
        btn = Button(frm,
                     image=imageDelBtn,
                     command=self._on_delete_button_click)
        btn.pack(side='left')
        self._app.gui.balloon.bind_widget(
            btn, balloonmsg='Remove the selected beam in the listbox.')

        imageClrBtn = ImageTk.PhotoImage(
            file=Scripting.root_node.get_gui_image_path(
                'Pattern_Clear_Button.png'))
        self.__gui_images.append(imageClrBtn)
        btn = Button(frm,
                     image=imageClrBtn,
                     command=self._on_clear_button_click)
        btn.pack(side='left')
        self._app.gui.balloon.bind_widget(
            btn, balloonmsg='Clear the listbox of the beam parameters.')

        imagePlotBtn = ImageTk.PhotoImage(
            file=Scripting.root_node.get_gui_image_path(
                'Pattern_Plot_Button.png'))
        self.__gui_images.append(imagePlotBtn)
        btn = Button(frm,
                     image=imagePlotBtn,
                     command=self._on_plot_ideal_pattern)
        btn.pack(side='left')
        self._app.gui.balloon.bind_widget(btn,
                                          balloonmsg='Plot the ideal pattern.')

        frm.pack(side='left', fill='y')

        self.__paramlist = ScrolledList(self)
        self.__paramlist.list.config(height=4, width=10)
        self.__paramlist.pack(side='left')
        self.name = 'Edit Ideal Pattern'

        self.optgrp = None
Beispiel #14
0
class EditGroup(Group):
    def __init__(self, *args, **kwargs):
        self._app = Scripting.root_node
        self.__topwin = kwargs.pop('topwin')
        super().__init__(*args, **kwargs)
        frm = Frame(self)

        self.__center = LabeledEntry(frm)
        set_attributes(self.__center,
                       label_text='center(deg)',
                       entry_text=0,
                       checker_function=self._app.gui.value_checker.check_int,
                       entry_width=5,
                       label_width=10)
        self.__center.pack(side='top')
        self._app.gui.balloon.bind_widget(
            self.__center, balloonmsg='Specify the beam center here.')

        self.__width = LabeledEntry(frm)
        set_attributes(self.__width,
                       label_text='width(deg)',
                       entry_text=20,
                       checker_function=self._app.gui.value_checker.check_int,
                       entry_width=5,
                       label_width=10)
        self.__width.pack(side='top')
        self._app.gui.balloon.bind_widget(
            self.__width, balloonmsg='Specify the beam width here.')

        self.__gui_images = []

        imageAddBtn = ImageTk.PhotoImage(
            file=Scripting.root_node.get_gui_image_path(
                'Pattern_Add_Button.png'))
        self.__gui_images.append(imageAddBtn)
        btn = Button(frm, image=imageAddBtn, command=self._on_add_button_click)
        btn.pack(side='left')
        self._app.gui.balloon.bind_widget(
            btn, balloonmsg='Add new beam to the ideal pattern.')

        imageDelBtn = ImageTk.PhotoImage(
            file=Scripting.root_node.get_gui_image_path(
                'Pattern_Del_Button.png'))
        self.__gui_images.append(imageDelBtn)
        btn = Button(frm,
                     image=imageDelBtn,
                     command=self._on_delete_button_click)
        btn.pack(side='left')
        self._app.gui.balloon.bind_widget(
            btn, balloonmsg='Remove the selected beam in the listbox.')

        imageClrBtn = ImageTk.PhotoImage(
            file=Scripting.root_node.get_gui_image_path(
                'Pattern_Clear_Button.png'))
        self.__gui_images.append(imageClrBtn)
        btn = Button(frm,
                     image=imageClrBtn,
                     command=self._on_clear_button_click)
        btn.pack(side='left')
        self._app.gui.balloon.bind_widget(
            btn, balloonmsg='Clear the listbox of the beam parameters.')

        imagePlotBtn = ImageTk.PhotoImage(
            file=Scripting.root_node.get_gui_image_path(
                'Pattern_Plot_Button.png'))
        self.__gui_images.append(imagePlotBtn)
        btn = Button(frm,
                     image=imagePlotBtn,
                     command=self._on_plot_ideal_pattern)
        btn.pack(side='left')
        self._app.gui.balloon.bind_widget(btn,
                                          balloonmsg='Plot the ideal pattern.')

        frm.pack(side='left', fill='y')

        self.__paramlist = ScrolledList(self)
        self.__paramlist.list.config(height=4, width=10)
        self.__paramlist.pack(side='left')
        self.name = 'Edit Ideal Pattern'

        self.optgrp = None

    def _on_add_button_click(self):
        self.__paramlist.list.insert(
            'end', f'{self.__center.get_int()}, {self.__width.get_int()}')

    def _on_delete_button_click(self):
        self.__paramlist.list.delete('anchor')

    def _on_clear_button_click(self):
        self.__paramlist.clear()

    def _on_plot_ideal_pattern(self):
        with code_printer():
            center, width = self.beam_data
            self.__topwin.set_ideal_pattern(center, width)
            self.__topwin.plot_ideal_pattern()

    @property
    def beam_data(self):
        beamParams = self.__paramlist.list.get(0, 'end')
        if not beamParams:
            self._app.print_error('An error occurred!')
            self._app.gui.console.show_tips([{
                'type':
                'text',
                'content':
                '''This exception happens when the listbox of the beam parameters are empty.
To make a valid ideal pattern, at least one beam should be specified.
'''
            }])
            return
        center, width = zip(
            *[map(float, param.split(',')) for param in beamParams])
        return center, width