Example #1
0
class Screen(Observer):
    def __init__(self,parent,bg="white"):
        self.canvas=Canvas(parent,bg=bg)
        print("parent",parent.cget("width"),parent.cget("height"))

        parent.bind("<Configure>", self.resize)
        self.parent=parent
        self.width=int(self.canvas.cget("width"))
        self.height=int(self.canvas.cget("height"))
        self.models=[]
    def update(self,model):
        if model not in self.models:
            self.models.append(model)
        print("View update")
        signal=model.get_signal()
        self.plot_signal(signal,model.get_color(),model.get_name())


    def plot_signal(self,signal,color,name):
        w,h=self.canvas.winfo_width(),self.canvas.winfo_height()
        width,height=int(w),int(h)
        print(self.canvas.find_withtag("signal"+name))
        if self.canvas.find_withtag("signal"+name) :
            self.canvas.delete("signal"+name)
        if signal and len(signal) > 1:
            if name=="X-Y" :
                plot = [((x+2)*width/4, (2*y/self.m+1)*height/2) for (x, y) in signal]
            else :
                plot = [(x*width, y*height/self.m + height/2) for (x, y) in signal]

            signal_id = self.canvas.create_line(plot, fill=color, smooth=1, width=3,tags="signal"+name)
        return

    def packing(self) :
        self.canvas.pack(fill="both", expand=1)
    def grid(self,n,m):
        self.n=n
        self.m=m
        w,h=self.canvas.winfo_width(),self.canvas.winfo_height()
        self.width,self.height=int(w),int(h)
        self.canvas.create_line(0,self.height/2.0,self.width-4,self.height/2,arrow="last",tags="line",fill="blue")
        self.canvas.create_line(self.width/2,self.height,self.width/2,5,arrow="last",tags="line",fill="blue")
        step1=self.width/n
        for t in range(1,n):
            x =t*step1
            self.canvas.create_line(x,0,x,self.height,tags="line")
        step=self.height/m
        for t in range(1,m):
            y =t*step
            self.canvas.create_line(0,y,self.width,y,tags="line")
    def resize(self,event):
        self.canvas.delete("line")
        self.grid(self.n,self.m)
        for model in self.models :
            self.plot_signal(model.get_signal(),
                model.get_color(),
                model.get_name())
Example #2
0
class canvasInterface(interfaceScreen):
    def __init__(self,master,width,height):
        interfaceScreen.__init__(self)
        self.canvas = Canvas(master, width=width, height=height,bg='white')
        self.canvas.grid(row=0,column=1)

    """
    ---------------Interfaz con objeto dibujante---------------------
    """

    def deleteFromCanvas(self,id):
        self.canvas.delete(id)
        pass

    def create_rectangle(self,x1, y1, x2, y2,*arg,**kargs):
        return self.canvas.create_rectangle(x1, y1, x2, y2,*arg,**kargs)
        pass

    def create_line(self,x1, y1, x2,  y2, *args,**kwargs):
        return self.canvas.create_line(x1, y1, x2,  y2, *args,**kwargs)

    def create_text(self,x1, y1,*args,**kargs):
        return self.canvas.create_text(x1, y1,*args,**kargs)

    def scan_mark(self,x,y):
        self.canvas.scan_mark(x, y)
    def scan_dragto(self,x, y, *args,**kwargs):
        self.canvas.scan_dragto(x, y, *args,**kwargs)

    def winfo_height(self):
        return self.canvas.winfo_height()
    def winfo_width(self):
        return self.canvas.winfo_width()
Example #3
0
class MainWindow(Tk):
    def __init__(self, width=100, height=100, bg="red"):
        Tk.__init__(self)
        self.title("Editeur Graphique")
        self.geometry("400x300+1200+300")
        self.canvas = Canvas(self, width=width - 20, height=height - 20, bg=bg)
        self.libelle = Label(text="Serious Game", font="Helvetica 14 bold")
        self.canvas.pack()
        self.libelle.pack()
        print(self.canvas.cget("height"))
        print(self.canvas.cget("width"))
        print(self.canvas.winfo_height())
        print(self.canvas.winfo_width())
Example #4
0
class MainWindow(Frame):
    def __init__(self, parent=None, width=100,height=100,bg="red"):
        Frame.__init__(self,parent, relief="sunken", bd=5)
        self.canvas =Canvas(self,width=width-20,height=height-20, bg=bg)
        self.libelle =Label(text ="Serious Game", font="Helvetica 14 bold")
        print(self.canvas.cget("height"))
        print(self.canvas.cget("width"))
        print(self.canvas.winfo_height())
        print(self.canvas.winfo_width())

    def packing(self) :
        self.pack()
        self.canvas.pack(fill="both",expand=True)
        self.libelle.pack()
Example #5
0
class MainWindow(Frame):
    def __init__(self, parent=None, bg="red"):
        Frame.__init__(self, parent, relief="sunken", bd=5)
        self.parent = parent
        self.menubar = MenuBar(self)
        self.canvas = Canvas(self, bg=bg)
        self.libelle = Label(text="Serious Game", font="Helvetica 14 bold")
        print(self.canvas.cget("height"))
        print(self.canvas.cget("width"))
        print(self.canvas.winfo_height())
        print(self.canvas.winfo_width())

    def packing(self):
        self.menubar.pack(fill="x")
        self.canvas.pack(fill="both", expand=True)
        self.libelle.pack()
        self.pack()

    def file_save(self):
        formats = [('Texte', '*.py'), ('Portable Network Graphics', '*.png')]
        if sys.version_info[0] < 3:
            filename = tkFileDialog.asksaveasfilename(parent=self.parent,
                                                      filetypes=formats,
                                                      title="Save...")
        else:
            filename = filedialog.asksaveasfilename(parent=self.parent,
                                                    filetypes=formats,
                                                    title="Save...")
        if len(nfilename) > 0:
            print("Sauvegarde en cours dans %s" % filename)

    def file_quit(self):
        exit(0)

    def create_circle(self):
        pass

    def delete_circle(self):
        pass

    def help_us(self):
        pass

    def help_tkinter(self):
        pass
Example #6
0
class MapUI:
    def __init__(self, master):
        def center(win):
            win.update_idletasks()
            width = win.winfo_width()
            height = win.winfo_height()
            x = (win.winfo_screenwidth() // 4) - (width // 2) + 40
            y = (win.winfo_screenheight() // 4) - (height // 2) + 40
            win.geometry('{}x{}+{}+{}'.format(width, height, x, y))

        def callback(event):
            event.widget.focus_set()
            print "clicked at", event.x, event.y

            if self.add_tasks_flg.get() == 1:
                # Select number of robots
                # Define elements of pop up window
                self.top = Toplevel()

                self.num_robots = StringVar(self.top)
                self.num_robots.set("1")  # default value
                w = OptionMenu(self.top, self.num_robots, '1', '2', '3',
                               '4').grid(row=0, column=1)
                text1 = Message(self.top, text="Number of robots:",
                                width=150).grid(row=0, column=0)

                self.e = Entry(self.top, width=10)
                self.e.grid(row=1, column=1)
                text2 = Message(self.top, text="Task duration:",
                                width=150).grid(row=1, column=0)
                text3 = Message(self.top, text="(s)", width=60).grid(row=1,
                                                                     column=2)

                newline = Message(self.top, text=" ").grid(row=2)

                button = Button(self.top,
                                text='Enter',
                                command=lambda: self.enter_task(event)).grid(
                                    row=3, column=1)
                button_cancel = Button(self.top,
                                       text='Cancel',
                                       command=self.cancel_task).grid(row=3,
                                                                      column=2)

                center(self.top)

        master.title("Map Interface")
        master.minsize(width=1000, height=750)
        master.maxsize(width=1000, height=750)
        master.config(bg=BKG_COLOUR)
        self.master = master

        # Canvas for overlaying map
        self.map_canvas = Canvas(master,
                                 width=CANVAS_W,
                                 height=CANVAS_H,
                                 bg='gray85',
                                 highlightthickness=0)
        self.map_canvas.pack(side='right', padx=50)
        self.map_canvas.bind("<Button-1>", callback)
        global CANVAS_PTR
        CANVAS_PTR = self.map_canvas
        self.master.update()
        w = self.map_canvas.winfo_width()
        h = self.map_canvas.winfo_height()
        # Overlay a grid
        for i in range(0, w, SQ_SIZE):
            if i != 0:
                self.map_canvas.create_line(i, 0, i, h, dash=1)
        for i in range(0, h, SQ_SIZE):
            if i != 0:
                self.map_canvas.create_line(0, i, w, i, dash=1)

        # Load in flame icon from flame.gif
        self.flame_icon = PhotoImage(file="flame.gif")
        # Load in the drone icon from drone.gif
        global DRONE_ICON
        DRONE_ICON = PhotoImage(file="drone.gif")

        buttons_frame = Canvas(master,
                               width=163,
                               height=230,
                               bg=BUTTONS_BKG_COLOUR,
                               highlightthickness=1,
                               highlightbackground='dim grey')
        buttons_frame.place(x=40, y=200)

        # Define UI buttons
        self.add_tasks_flg = IntVar()
        self.add_tasks_b = Checkbutton(master,
                                       text="Add Tasks",
                                       variable=self.add_tasks_flg,
                                       highlightbackground=BUTTONS_BKG_COLOUR,
                                       background=BUTTONS_BKG_COLOUR)
        self.add_tasks_b.place(x=77, y=240)

        self.clear_wp_b = Button(master,
                                 text='Clear Tasks',
                                 command=self.clear_wp,
                                 highlightbackground=BUTTONS_BKG_COLOUR)
        self.clear_wp_b.config(width=10)
        self.clear_wp_b.place(x=65, y=270)
        '''
        self.gen_wp_file_b = Button(master, text='Generate Waypoints File', command=self.gen_wp_file, highlightbackground=BKG_COLOUR)
        self.gen_wp_file_b.config(width=20)
        self.gen_wp_file_b.place(x=20, y=250)
        '''

        self.land_b = Button(master,
                             text='Land',
                             command=self.land,
                             highlightbackground=BUTTONS_BKG_COLOUR)
        self.land_b.config(width=10)
        self.land_b.place(x=65, y=350)

        # Set up coordinate system conversion and display corners of room:
        file_obj = open('antenna_locations.txt', 'r')
        anchors = []
        for line in file_obj:
            cur_anchors = map(float, line.split())
            anchors.append(cur_anchors)
        file_obj.close()
        anchors = (np.array(anchors)).T

        # Find largest (abs) x and y values to use a reference for conversion ratio
        x_vals = anchors[0]
        largest_x_val = x_vals[np.argmax(abs(x_vals))]
        y_vals = anchors[1]
        largest_y_val = y_vals[np.argmax(abs(y_vals))]

        if largest_x_val > largest_y_val:
            largest_y_val = largest_x_val
        else:
            largest_x_val = largest_y_val

        global m_per_pixel_x
        m_per_pixel_x = float(largest_x_val / (CANVAS_W / 2))
        global m_per_pixel_y
        m_per_pixel_y = float(largest_y_val / (CANVAS_H / 2))

        # Place antenna (anchors) on UI
        anchors = anchors.T
        for cur_anchor in anchors:
            x_pixel_loc = cur_anchor[0] / m_per_pixel_x + CANVAS_W / 2
            y_pixel_loc = -1 * (cur_anchor[1] / m_per_pixel_y) + CANVAS_H / 2

            # Draw antenna @ location
            global ANTENNA_LIST
            antenna_id = self.map_canvas.create_oval(x_pixel_loc - 15,
                                                     y_pixel_loc - 15,
                                                     x_pixel_loc + 15,
                                                     y_pixel_loc + 15,
                                                     fill='red')

        self.master.update()

    global SQ_SIZE
    SQ_SIZE = 20
    global BKG_COLOUR
    BKG_COLOUR = 'gray95'
    global BUTTONS_BKG_COLOUR
    BUTTONS_BKG_COLOUR = 'grey66'
    global CANVAS_W
    CANVAS_W = 700
    global CANVAS_H
    CANVAS_H = 700
    global TASK_LIST
    TASK_LIST = None
    global m_per_pixel_x
    m_per_pixel_x = None
    global m_per_pixel_y
    m_per_pixel_y = None
    global NEW_TASK_FLAG
    NEW_TASK_FLAG = False
    global ANTENNA_LIST
    ANTENNA_LIST = None
    global DRONE_ICON
    DRONE_ICON = None

    flame_icon = None
    ui_wp_list = None
    #task_list = None
    add_wp_flag = False
    task_id = 0
    add_tasks_flg = None

    def add_tasks(self):
        print "adding tasks"
        # function imp here
        self.add_wp_flag = True
        self.map_canvas.config(cursor='pencil')

    def clear_wp(self):
        print "clear tasks"
        global TASK_LIST
        TASK_LIST = None
        for element_id in self.ui_wp_list:
            self.map_canvas.delete(element_id[0])
        self.ui_wp_list = None

    '''
    def gen_wp_file(self):
        print "generate wp file"
        # function imp here
    '''

    def land(self):
        # Send a new task with position (0,0,0) z=0 tells drone to land
        print("land")

    def enter_task(self, event):
        # Determine square (top left corner coords):
        w_start = event.x - event.x % SQ_SIZE
        h_start = event.y - event.y % SQ_SIZE

        #Translate pixel location to physical location
        x_pixel = event.x
        y_pixel = event.y
        # Find out how many pixels from center:
        x_pixel = x_pixel - CANVAS_W / 2
        x_physical = x_pixel * m_per_pixel_x

        #vertical case, note this is flipped
        y_pixel = y_pixel - CANVAS_W / 2
        y_pixel = -1 * y_pixel
        y_physical = y_pixel * m_per_pixel_y

        try:
            # Add to task list
            global TASK_LIST
            if TASK_LIST == None:
                TASK_LIST = [[
                    self.task_id,
                    int(self.num_robots.get()),
                    float(self.e.get()), x_physical, y_physical
                ]]
                global NEW_TASK_FLAG
                NEW_TASK_FLAG = True
            else:
                TASK_LIST.append([
                    self.task_id,
                    int(self.num_robots.get()),
                    float(self.e.get()), x_physical, y_physical
                ])
                global NEW_TASK_FLAG
                NEW_TASK_FLAG = True

            # Indicate task in UI
            element_id = self.map_canvas.create_image(event.x,
                                                      event.y,
                                                      image=self.flame_icon)
            if self.ui_wp_list == None:
                self.ui_wp_list = [[element_id]]
            else:
                self.ui_wp_list.append([element_id])
        except:
            print("Invalid Task Entry")

        self.map_canvas.config(cursor='arrow')
        self.add_wp_flag = False

        print(TASK_LIST)

        self.task_id = self.task_id + 1
        self.top.destroy()

    def cancel_task(self):
        self.top.destroy()
Example #7
0
class SkyglowEstimationToolbox:
    """Main class that establishes GUI."""
    def __init__(self, root):
        self.root = root

        # Radio action buttons
        self.action = None
        self.sgmap_single_btn, self.krn_lib_btn, self.multi_map_btn = None, None, None

        self.file_log_var = StringVar()
        self.csv_file_var = StringVar()
        self.krn_folder_var = StringVar()
        self.output_folder_var = StringVar()
        self.sgmap_folder_var = StringVar()

        self.krn_ent_var = StringVar()
        self.krn_var, self.hem_var = IntVar(), IntVar()
        self.img, self.cdiag = None, None
        self.lat_lbl, self.lat_entry = None, None
        self.k_lbl, self.k_entry = None, None
        self.zen_lbl, self.zen_entry = None, None
        self.azi_lbl, self.azi_entry = None, None
        self.krn_lvl, self.krn_entry, self.krn_btn = None, None, None
        self.txt_redir, self.prg_log = None, None
        self.map_btn, self.gen_krn_btn = None, None

        # Sets window title, size, and icon on screen.
        self.root.title("Skyglow Estimation Toolbox (SET)")
        self.root.geometry('%dx%d+%d+%d' %
                           (constants.SW * 0.75, constants.SH * 0.75, 25, 25))
        self.root.iconbitmap(os.path.join(os.getcwd(), constants.ICO))
        self.root.resizable(False, False)
        self.root.update_idletasks()

        # Creates three paned windows for the main screen.
        base = PanedWindow()
        base.pack(fill=BOTH, expand=1)
        sub1 = PanedWindow(base,
                           orient=VERTICAL,
                           height=self.root.winfo_height() * 3 / 4)
        base.add(sub1)
        sub2 = PanedWindow(sub1,
                           orient=HORIZONTAL,
                           height=self.root.winfo_height() / 5)
        sub1.add(sub2)

        # Creates frame for holding inputs.
        self.input_frame = Frame(sub2)
        sub2.add(self.input_frame)

        # Creates frame for bottom half of main screen.
        self.img_frame = Frame(sub1, bd=2, bg='white', relief="sunken")
        sub1.add(self.img_frame)

        # Creates canvas for displaying images.
        self.img_canvas = Canvas(self.img_frame,
                                 bd=2,
                                 relief="groove",
                                 width=constants.SW * 0.6,
                                 height=self.root.winfo_height() * 3 / 4 * 0.9)
        self.img_canvas.place(relx=.5, rely=.5, anchor=CENTER)

        # Creates help button for link to documentation, instructions, and about.
        self.help_btn = Menubutton(self.input_frame,
                                   text="Help",
                                   relief="raised",
                                   bd=2,
                                   width=8,
                                   pady=1)
        #self.help_btn.place(relx=1, rely=0, anchor=NE)
        self.help_btn.grid(column=4, columnspan=1, row=0)
        self.help_btn_menu = Menu(self.help_btn, tearoff=0)
        doc = 'https://github.com/NASA-DEVELOP'
        self.help_btn_menu.add_command(label="Documentation",
                                       command=lambda: self.open_url(doc))
        self.help_btn_menu.add_command(label="Instructions",
                                       command=self.instructions)
        self.help_btn_menu.add_separator()
        self.help_btn_menu.add_command(label="About", command=self.about)
        self.help_btn["menu"] = self.help_btn_menu

    def main_screen(self):
        """Set up input GUI and image display screen."""
        self.action = IntVar()

        btn_width = int(constants.SW / 60)
        file_width = int(constants.SW / 18)
        lbl_width = int(constants.SW / 60)
        gen_width = int(constants.SW / 42)
        radio_font = Font(family='TkDefaultFont', size=12)
        self.sgmap_single_btn = Radiobutton(
            self.input_frame,
            text="Generate Artificial Skyglow Map",
            font=radio_font,
            width=btn_width,
            variable=self.action,
            value='sng',
            command=self.sng_popup)
        self.krn_lib_btn = Radiobutton(self.input_frame,
                                       text="Generate Kernel Library",
                                       font=radio_font,
                                       width=btn_width,
                                       variable=self.action,
                                       value='krn',
                                       command=self.krn_popup)
        self.multi_map_btn = Radiobutton(
            self.input_frame,
            text="Generate Maps from Multiple Kernels",
            font=radio_font,
            width=btn_width,
            variable=self.action,
            value='mul',
            command=self.mul_popup)
        self.hem_map_btn = Radiobutton(
            self.input_frame,
            text="Generate Hemispherical Visualization",
            font=radio_font,
            width=btn_width,
            variable=self.action,
            value='hem',
            command=self.hem_popup)
        #Place widget
        self.sgmap_single_btn.grid(column=0, columnspan=1, row=0)
        self.krn_lib_btn.grid(column=1, columnspan=1, row=0)
        self.multi_map_btn.grid(column=2, columnspan=1, row=0)
        self.hem_map_btn.grid(column=3, columnspan=1, row=0)

        # VIIRS Image Reference File
        self.file_lbl = Label(self.input_frame,
                              text="Image File:",
                              width=lbl_width,
                              anchor=E)
        self.file_log = Entry(self.input_frame,
                              width=file_width,
                              bd=2,
                              relief="sunken",
                              textvariable=self.file_log_var)
        self.browse_btn = Button(self.input_frame,
                                 text="Browse",
                                 command=self.import_viirs)

        # Angles CSV File
        self.csv_file_lbl = Label(self.input_frame,
                                  text="Angles CSV File:",
                                  width=lbl_width,
                                  anchor=E)
        self.csv_file_log = Entry(self.input_frame,
                                  width=file_width,
                                  bd=2,
                                  relief="sunken",
                                  textvariable=self.csv_file_var)
        self.csv_browse_btn = Button(self.input_frame,
                                     text="Browse",
                                     command=self.import_csv)

        # Multiple Maps form Kernel library
        self.mul_file_lbl = Label(self.input_frame,
                                  text="Kernel Folder:",
                                  width=lbl_width,
                                  anchor=E)
        self.mul_file_log = Entry(self.input_frame,
                                  width=file_width,
                                  bd=2,
                                  relief="sunken",
                                  textvariable=self.krn_folder_var)
        self.mul_browse_btn = Button(self.input_frame,
                                     text="Browse",
                                     command=self.import_krn_folder)

        # MultiKrn Map Output Location
        self.output_lbl = Label(self.input_frame,
                                text="Output Location:",
                                width=lbl_width,
                                anchor=E)
        self.output_log = Entry(self.input_frame,
                                width=file_width,
                                bd=2,
                                relief="sunken",
                                textvariable=self.output_folder_var)
        self.output_btn = Button(self.input_frame,
                                 text="Browse",
                                 command=self.import_out_folder)

        # Hemisphere Output Location
        self.sgmap_folder_lbl = Label(self.input_frame,
                                      text="Skyglow Map Location:",
                                      width=lbl_width,
                                      anchor=E)
        self.sgmap_folder_log = Entry(self.input_frame,
                                      width=file_width,
                                      bd=2,
                                      relief="sunken",
                                      textvariable=self.sgmap_folder_var)
        self.sgmap_folder_btn = Button(self.input_frame,
                                       text="Browse",
                                       command=self.import_sgmap_folder)

        # Import Kernel Checkbutton
        self.check_lbl = Label(self.input_frame,
                               text="Import Kernel:",
                               width=lbl_width,
                               anchor=E)

        self.krn_chk = Checkbutton(self.input_frame,
                                   anchor=W,
                                   variable=self.krn_var,
                                   command=self.checkbtn_val)

        self.hem_chk_lbl = Label(self.input_frame,
                                 text="Generate kernels for hemisphere:",
                                 width=lbl_width,
                                 anchor=E)

        self.hem_chk = Checkbutton(self.input_frame,
                                   anchor=W,
                                   variable=self.hem_var)

        # Region Latitude (deg), Grand Teton National park = 43.7904 degrees N
        self.lat_lbl = Label(self.input_frame,
                             text="Latitude (deg):",
                             width=lbl_width,
                             anchor=E)
        self.lat_entry = Entry(self.input_frame,
                               width=btn_width,
                               bd=2,
                               relief="sunken")
        self.lon_lbl = Label(self.input_frame,
                             text="Longitude (deg):",
                             width=lbl_width,
                             anchor=E)
        self.lon_entry = Entry(self.input_frame,
                               width=btn_width,
                               bd=2,
                               relief="sunken")

        # Atmospheric Clarity Parameter, REF 2, Eq. 12, p. 645
        self.k_lbl = Label(self.input_frame,
                           text="Atmospheric Clarity Parameter:",
                           width=btn_width,
                           anchor=E)
        self.k_entry = Entry(self.input_frame,
                             width=btn_width,
                             bd=2,
                             relief="sunken")

        # Zenith angle (deg), z, REF 2, Fig. 6, p.648
        self.zen_lbl = Label(self.input_frame,
                             text="Zenith Angle (deg):",
                             width=lbl_width,
                             anchor=E)
        self.zen_entry = Entry(self.input_frame,
                               width=btn_width,
                               bd=2,
                               relief="sunken")

        # Azimuth angle (deg)
        self.azi_lbl = Label(self.input_frame,
                             text="Azimuth Angle (deg):",
                             width=lbl_width,
                             anchor=E)
        self.azi_entry = Entry(self.input_frame,
                               width=btn_width,
                               bd=2,
                               relief="sunken")

        self.krn_lbl = Label(self.input_frame,
                             text="Kernel File:",
                             width=lbl_width,
                             anchor=E)
        self.krn_ent = Entry(self.input_frame,
                             width=file_width,
                             bd=2,
                             relief="sunken",
                             textvariable=self.krn_ent_var)
        self.krn_btn = Button(self.input_frame,
                              text="Browse",
                              command=self.import_krn)

        # Generate Artificial Skyglow Map Button
        self.map_btn = Button(self.input_frame,
                              text="Generate Artificial Skyglow Map",
                              width=gen_width,
                              command=self.generate_map)
        # Generate Kernal library button for SET
        self.gen_krn_btn = Button(self.input_frame,
                                  text="Generate Kernel Library",
                                  width=gen_width,
                                  command=self.generate_krn)
        # Generate Map of Multiple Kernals(word better later on)
        self.mul_map_btn = Button(self.input_frame,
                                  text="Generate Maps from Multiple Kernels",
                                  width=gen_width,
                                  command=self.generate_mmap)
        # Generate Hemispherical Visualization Display of Skyglow
        self.hem_gen_btn = Button(self.input_frame,
                                  text="Generate Hemisphere",
                                  width=gen_width,
                                  command=self.generate_hem)

    def import_viirs(self):
        """Import a VIIRS DNB file."""
        # Allows user to search through his directory for VIIRS Image file.
        file_types = [('TIFF Files', '*.tif'), ('All files', '*')]
        file_name = filedialog.askopenfilename(initialdir='/',
                                               title="Select file",
                                               filetypes=file_types)
        self.file_log_var.set(file_name)

        # Checks to see if file is empty. If not, displays image on canvas.
        if file_name != '':
            pilimg = Image.open(file_name)
            pilimg_width, pilimg_height = pilimg.size
            pilimg.tile = [
                t for t in pilimg.tile
                if t[1][2] < pilimg_width and t[1][3] < pilimg_height
            ]
            canvas_size = (self.img_canvas.winfo_width(),
                           self.img_canvas.winfo_height())
            pilimg_r = pilimg.resize(canvas_size, Image.ANTIALIAS)
            pilimg_col = ImageOps.colorize(ImageOps.grayscale(pilimg_r),
                                           (0, 0, 0), (255, 255, 255))
            pilimg_cont = ImageOps.autocontrast(pilimg_col,
                                                cutoff=.4,
                                                ignore=None)
            self.img = ImageTk.PhotoImage(pilimg_cont)
            self.img_canvas.create_image(canvas_size[0] / 2,
                                         canvas_size[1] / 2,
                                         image=self.img)
        else:
            print('File is empty.')

    def import_csv(self):
        """Import CSV file."""
        file_types = [('CSV Files', '*.csv'), ('All files', '*')]
        file_name = filedialog.askopenfilename(initialdir='/',
                                               title="Select file",
                                               filetypes=file_types)
        self.csv_file_var.set(file_name)

        if file_name is '':
            print('File is empty.')

    def import_krn_folder(self):
        """Import kernel folder."""
        krn_dir = filedialog.askdirectory(initialdir='/',
                                          title="Select kernel folder")
        self.krn_folder_var.set(krn_dir)

        if krn_dir is '':
            print('Directory is empty.')

    def import_out_folder(self):
        """Import skyglow output folder."""
        output_dir = filedialog.askdirectory(initialdir='/',
                                             title="Select output folder")
        self.output_folder_var.set(output_dir)

        if output_dir is '':
            print('Directory is empty.')

    def import_krn(self):
        """Import existing kernel tif."""
        file_types = [('TIFF Files', '*.tif'), ('All files', '*')]
        file_name = filedialog.askopenfilename(initialdir='/',
                                               title="Select file",
                                               filetypes=file_types)
        self.krn_ent_var.set(file_name)

    def import_sgmap_folder(self):
        """Import skyglow map folder for hemisphere building."""
        sgmap_dir = filedialog.askdirectory(initialdir='/',
                                            title="Select skyglow map folder")
        self.sgmap_folder_var.set(sgmap_dir)

        if sgmap_dir is '':
            print('Directory is empty.')

    def sng_popup(self):
        """Single map tab."""
        self.remove_all()

        self.check_lbl.grid(column=0, row=2)
        self.krn_chk.place(relx=.22, rely=.41, anchor=CENTER)

        self.file_lbl.grid(column=0, row=1)
        self.file_log.grid(column=1, columnspan=3, row=1)
        self.browse_btn.grid(column=4, row=1, sticky=W, padx=3)

        self.lat_lbl.grid(column=0, row=3)
        self.lat_entry.grid(column=1, row=3)

        self.k_lbl.grid(column=2, row=3)
        self.k_entry.grid(column=3, row=3)

        self.zen_lbl.grid(column=0, row=4)
        self.zen_entry.grid(column=1, row=4)

        self.azi_lbl.grid(column=2, row=4)
        self.azi_entry.grid(column=3, row=4)

        self.map_btn.grid(column=1, columnspan=3, row=5, sticky=N + S + E + W)

    def krn_popup(self):
        """Kernel lib tab."""
        self.remove_all()

        # latitude
        self.lat_lbl.grid(column=0, row=3)
        self.lat_entry.grid(column=1, row=3)

        # atmospheric clarity
        self.k_lbl.grid(column=2, row=3)
        self.k_entry.grid(column=3, row=3)

        # angles file
        self.csv_file_lbl.grid(column=0, row=1)
        self.csv_file_log.grid(column=1, columnspan=3, row=1)
        self.csv_browse_btn.grid(column=4, row=1, sticky=W, padx=3)

        # input VIIRS image
        self.file_lbl.grid(column=0, row=2)
        self.file_log.grid(column=1, columnspan=3, row=2)
        self.browse_btn.grid(column=4, row=2, sticky=W, padx=3)

        self.hem_chk_lbl.grid(column=0, row=4)
        self.hem_chk.place(relx=.21, rely=.69)

        self.gen_krn_btn.grid(column=1,
                              columnspan=3,
                              row=5,
                              sticky=N + S + E + W)

    def mul_popup(self):
        """Multiple maps tab."""
        self.remove_all()

        # Kernel folder location
        self.mul_file_lbl.grid(column=0, row=1)
        self.mul_file_log.grid(column=1, columnspan=3, row=1)
        self.mul_browse_btn.grid(column=4, row=1, sticky=W, padx=3)

        # input VIIRS image
        self.file_lbl.grid(column=0, row=2)
        self.file_log.grid(column=1, columnspan=3, row=2)
        self.browse_btn.grid(column=4, row=2, sticky=W, padx=3)

        # Choose output location
        self.output_lbl.grid(column=0, row=3)
        self.output_log.grid(column=1, columnspan=3, row=3)
        self.output_btn.grid(column=4, row=3, sticky=W, padx=3)

        # Generate map from kernel folder
        self.mul_map_btn.grid(column=1,
                              columnspan=3,
                              row=4,
                              sticky=N + S + E + W)

    def hem_popup(self):
        """Hemisphere tab."""
        self.remove_all()

        # Skyglow Map Folder
        self.sgmap_folder_lbl.grid(column=0, row=1)
        self.sgmap_folder_log.grid(column=1, columnspan=3, row=1)
        self.sgmap_folder_btn.grid(column=4, row=1, sticky=W, padx=3)

        # Latitude entry
        self.lat_lbl.grid(column=0, row=3)
        self.lat_entry.grid(column=1, row=3)

        # Longitude entry
        self.lon_lbl.grid(column=2, row=3)
        self.lon_entry.grid(column=3, row=3)

        # Generate Hemispherical Visualization button
        self.hem_gen_btn.grid(column=1,
                              columnspan=3,
                              row=4,
                              sticky=N + S + E + W)

    def remove_all(self):
        """Remove all existing GUI elements before opening new tab."""
        self.check_lbl.grid_remove()
        self.krn_chk.place_forget()
        self.hem_chk.place_forget()
        self.hem_chk_lbl.grid_remove()
        self.file_lbl.grid_remove()
        self.file_log.grid_remove()
        self.browse_btn.grid_remove()
        self.krn_lbl.grid_remove()
        self.krn_ent.grid_remove()
        self.krn_btn.grid_remove()
        self.lat_lbl.grid_remove()
        self.lat_entry.grid_remove()
        self.k_lbl.grid_remove()
        self.k_entry.grid_remove()
        self.zen_lbl.grid_remove()
        self.zen_entry.grid_remove()
        self.azi_lbl.grid_remove()
        self.azi_entry.grid_remove()
        self.map_btn.grid_remove()
        self.gen_krn_btn.grid_remove()
        self.mul_map_btn.grid_remove()
        self.csv_file_lbl.grid_remove()
        self.csv_file_log.grid_remove()
        self.csv_browse_btn.grid_remove()
        self.mul_file_lbl.grid_remove()
        self.mul_file_log.grid_remove()
        self.mul_browse_btn.grid_remove()
        self.output_lbl.grid_remove()
        self.output_log.grid_remove()
        self.output_btn.grid_remove()
        self.hem_gen_btn.grid_remove()
        self.lat_lbl.grid_remove()
        self.lat_entry.grid_remove()
        self.lon_lbl.grid_remove()
        self.lon_entry.grid_remove()
        self.sgmap_folder_lbl.grid_remove()
        self.sgmap_folder_log.grid_remove()
        self.sgmap_folder_btn.grid_remove()

    def checkbtn_val(self):
        """Change interface based on if Import Kernel button is checked."""
        # Import Kernel File widgets when Kernel Checkbutton is marked.
        if self.krn_var.get():
            self.lat_lbl.grid_remove()
            self.lat_entry.grid_remove()
            self.k_lbl.grid_remove()
            self.k_entry.grid_remove()
            self.zen_lbl.grid_remove()
            self.zen_entry.grid_remove()
            self.azi_lbl.grid_remove()
            self.azi_entry.grid_remove()
            self.krn_lbl.grid(column=0, row=2)
            self.krn_ent.grid(column=1, columnspan=3, row=2)
            self.krn_btn.grid(column=4, row=2, sticky=W, padx=3)
            self.krn_chk.place_forget()
            self.krn_chk.place(relx=0.19, rely=.5)
        # Input parameter widgets when Kernel Checkbuttton is unmarked
        else:
            self.krn_lbl.grid_remove()
            self.krn_ent.grid_remove()
            self.krn_btn.grid_remove()
            self.lat_lbl.grid(column=0, row=3)
            self.lat_entry.grid(column=1, row=3)
            self.k_lbl.grid(column=2, row=3)
            self.k_entry.grid(column=3, row=3)
            self.zen_lbl.grid(column=0, row=4)
            self.zen_entry.grid(column=1, row=4)
            self.azi_lbl.grid(column=2, row=4)
            self.azi_entry.grid(column=3, row=4)
            self.krn_chk.place_forget()
            self.krn_chk.place(relx=0.22, rely=.41, anchor=CENTER)

    @staticmethod
    def open_url(url):
        """"Open a url"""
        webbrowser.open_new(url)

    def instructions(self):
        """Open instructions window."""
        # Instantiates separate Toplevel instruction window.
        instr_window = Toplevel(self.root)
        instr_window.geometry('550x575+25+25')
        instr_window.title('Instructions')
        instr_window.wm_iconbitmap(constants.ICO)
        instr_window.resizable(False, False)

        # Creatse Scrollbar and Frame for containing other widgets.
        instr_scroll = Scrollbar(instr_window)
        instr_scroll.pack(fill=Y, side="right")
        instr_frame = Frame(instr_window, bg='white')
        instr_frame.pack(fill=BOTH, side="left")

        # Adds instruction text from constants and adds image of Cinzano's diagram.
        instr = Text(instr_frame,
                     width=65,
                     height=40,
                     padx=10,
                     pady=5,
                     bd=0,
                     wrap="word")
        instr.insert("end", constants.INSTR)
        cdiagram_file = Image.open("./static/cinzano_diagram.PNG")
        cdiagram_file = cdiagram_file.resize((500, 450), Image.ANTIALIAS)
        self.cdiag = ImageTk.PhotoImage(cdiagram_file)
        instr.image_create("end", image=self.cdiag)
        instr.tag_add("top", "1.0", "4.10")
        instr.tag_config("top", font='Times 12 bold')
        instr.tag_add("body", "5.0", "19.20")
        instr.tag_config("body", font='Times 12')
        instr.insert("end", constants.CDIAG)
        instr.pack()
        instr_scroll.config(command=instr.yview)

    def about(self):
        """Open an about window.

        Window gives authors, SET version number, and icon credit.
        """
        # Instantiates a new Toplevel about window.
        about_window = Toplevel(self.root)
        about_window.geometry('350x335+25+25')
        about_window.title('About')
        about_window.wm_iconbitmap(constants.ICO)
        about_window.resizable(False, False)

        # Adds text to about window.
        about = Text(about_window, width=50, height=30, padx=10, pady=3)
        about.insert("end", constants.ABOUT)
        about.tag_add("abt", "1.0", "21.30")
        about.tag_config("abt", font='Times 10 bold', justify=CENTER)
        about.pack()

    def progress(self):
        """Construct a progress window to monitor darksky."""
        # Instantiates a new Toplevel window and frame for progress bar and loading log.
        self.prg_window = Toplevel(self.root)
        self.prg_window.geometry('650x325+250+250')
        self.prg_window.title('Generating Artificial Skyglow Map...')
        self.prg_window.iconbitmap(constants.ICO)
        self.prg_window.resizable(False, False)
        prg_frame = Frame(self.prg_window)
        prg_frame.pack(fill=BOTH)

        # Creates Scrollbar, Progressbar, and Label for checking progress..
        prg_scroll = Scrollbar(prg_frame)
        prg_scroll.pack(fill=Y, side="right")
        self.prg_bar = ttk.Progressbar(prg_frame,
                                       orient=HORIZONTAL,
                                       length=750,
                                       mode='indeterminate')
        self.prg_bar.pack()
        self.prg_bar.start()
        prg_lbl_txt = StringVar()
        prg_lbl = Label(prg_frame, textvariable=prg_lbl_txt)
        prg_lbl.pack()

        # Displays message log that prints from log file and starts darkskypy.
        self.prg_log = Text(prg_frame,
                            width=90,
                            padx=5,
                            pady=5,
                            relief="sunken")
        self.prg_log.pack()
        self.prg_log.insert(
            "end", "*****Progress Log*****\n=======================\n")
        self.prg_log.tag_add("abt", "1.0", "3.0")
        self.prg_log.tag_config("abt", font='Courier 12 bold', justify=CENTER)
        self.txt_redir = LogRedirector(self.prg_log)
        logger.addHandler(self.txt_redir)
        sys.stderr = StderrRedirector(self.prg_log)
        prg_lbl_txt.set("Start time: " + str(time.asctime()))

        self.no_progress = 0

    def update_progress(self):
        """Update progress window to prevent it from freezing."""
        self.prg_log.update()
        # if only one thread exists, stop progress bar and close window
        if len(threading.enumerate()) == 1:
            self.prg_bar.stop()
            self.no_progress += 1
            if self.no_progress == 3:
                self.prg_window.withdraw()
        else:
            self.prg_bar.start()
        self.root.after(1000, self.update_progress)

    def generate_map(self):
        """Call darksky.sgmapper in background thread."""
        # Acquires input arguments.
        lat_in, k_in, zen_in, azi_in, file_in, krn_file_in = 0, 0, 0, 0, '', ''
        if self.krn_var.get():
            krn_file_in = self.krn_ent_var.get()
        else:
            lat_in = float(self.lat_entry.get())
            k_in = float(self.k_entry.get())
            zen_in = float(self.zen_entry.get())
            azi_in = float(self.azi_entry.get())
        file_in = self.file_log_var.get()

        self.progress()

        # Create new threads to run light propagation model simultaneously.
        p_thread = threading.Thread(target=self.update_progress())
        t_thread = threading.Thread(target=darksky.sgmapper,
                                    args=(lat_in, k_in, zen_in, azi_in,
                                          file_in, krn_file_in))
        t_thread.setDaemon(True)
        p_thread.start()
        t_thread.start()

    def generate_krn(self):
        """Start kernel generation in background threads."""
        # Acquires input arguments
        csv_in, file_in, lat_in, k_in, hem = '', '', 0, 0, False
        csv_in = self.csv_file_var.get()
        file_in = self.file_log_var.get()
        lat_in = float(self.lat_entry.get())
        k_in = float(self.k_entry.get())
        hem = self.hem_var.get()

        self.progress()

        # Create new threads to run light propagation model simultaneously.
        p_thread = threading.Thread(target=self.update_progress())
        with open(csv_in, "rb") as f:
            angle_list = loadtxt(f, delimiter=",", skiprows=1)
        p_thread.start()
        for angle_set in angle_list:
            t_thread = threading.Thread(target=darksky.generate_krn,
                                        args=(lat_in, k_in, angle_set[0],
                                              angle_set[1], file_in, hem))
            t_thread.setDaemon(True)

            t_thread.start()

    def generate_mmap(self):
        """Start brightness map creation from kernels."""
        # Acquires input arguments
        krn_folder_in, file_in, output_in, = '', '', ''
        krn_folder_in = self.krn_folder_var.get()
        file_in = self.file_log_var.get()
        output_in = self.output_folder_var.get()

        self.progress()

        # Create new threads to run light propagation model simultaneously.
        p_thread = threading.Thread(target=self.update_progress())
        t_thread = threading.Thread(target=darksky.multisgmapper,
                                    args=(file_in, krn_folder_in, output_in))
        t_thread.setDaemon(True)
        p_thread.start()
        t_thread.start()

    def generate_hem(self):
        """Generate hemisphere."""
        sgmap_folder_in, lat_in, lon_in, = '', 0, 0
        sgmap_folder_in = self.sgmap_folder_var.get()
        lat_in = float(self.lat_entry.get())
        lon_in = float(self.lon_entry.get())
        darksky.generate_hem(lat_in, lon_in, sgmap_folder_in)
Example #8
0
class Visualizer(Toplevel, core.DrawListener):
    """
    Base class for windows used for visualization of problems.  Deals with many boilerplate TK tasks and has several features.
    - Registers blank listeners for common events and registers exit on close
    - Provides a "virtual coordinate system" that maps onto the window.  This is specified as a position and a width/height.
    - Provides reverse transform from mouse coordinates back to "virtual coordinate system"
    - Allows posting drawing into the GUI thread.  This can be overwhelmed if submissions are too fast.  This should leverage TK's dirty/repaint scheme in some way in the future.
    """
    def __init__(self,
                 canvasWidth,
                 canvasHeight,
                 viewCenterX=0.0,
                 viewCenterY=0.0,
                 viewWidth=1.0,
                 viewHeight=1.0,
                 **kw):
        Toplevel.__init__(self, **kw)
        self.viewCenterX = viewCenterX
        self.viewCenterY = viewCenterY
        self.viewWidth = viewWidth
        self.viewHeight = viewHeight
        self.canvas = Canvas(self, width=canvasWidth, height=canvasHeight)
        self.canvas.pack()
        self.protocol("WM_DELETE_WINDOW", self.onClose)
        self.bind("<Configure>", self.onResize)

    def setView(self, viewCenterX, viewCenterY, viewWidth, viewHeight):
        self.viewCenterX = viewCenterX
        self.viewCenterY = viewCenterY
        self.viewWidth = viewWidth
        self.viewHeight = viewHeight

    def bindWithTransform(self, eventName, handler):
        """
        Binds non-standard handlers to events.  These handlers receive the initial event object, but also an additional
        point parameter which holds the event's location in the "virtual coordinate system" as a numpy array.
        :param eventName:
        :param handler: a handler function with 2 args (point,event)
        :return:
        """
        self.bind(
            eventName, lambda event: handler(
                self.transformCanvasToPoint((event.x, event.y)), event))

    def drawInBackground(self, drawable, **kwargs):
        """Draw the given drawable in the GUI thread.
        drawable should not be touched while drawing."""
        core.inGUIThread(lambda: self.drawToCanvas(drawable, **kwargs))

    def drawToCanvas(self, drawable, **kwargs):
        """Draw the given drawable, applying virtual coordinates transform.
        Must be called from GUI THREAD!"""
        self.canvas.delete(tk.ALL)
        drawable.draw(self, **kwargs)
        self.transformCanvas()

    def transformCanvas(self):
        """Transforms all objects drawn on the canvas in the "virtual coordinate system" to the window's coordinates."""
        canvas = self.canvas
        width = canvas.winfo_width()
        height = canvas.winfo_height()

        canvas.move("all", -self.viewCenterX, -self.viewCenterY)
        canvas.scale("all", 0.0, 0.0, width / self.viewWidth,
                     -height / self.viewHeight)
        canvas.move("all", width / 2.0, height / 2.0)

    def transformCanvasToPoint(self, canvasPoint):
        """
        Given a point on the canvas, such as a mouse coordinate, transform it to the "virtual coordinate system".
        :param canvasPoint: point to transform
        :return: (transX, transY)
        """
        width = self.canvas.winfo_width()
        height = self.canvas.winfo_height()
        transX = self.viewCenterX + self.viewWidth * (canvasPoint[0] -
                                                      width / 2.0) / width
        transY = self.viewCenterY - self.viewHeight * (canvasPoint[1] -
                                                       height / 2.0) / height
        return np.array((transX, transY), np.double)

    def pixelVecToScale(self, vec):
        """
        Scale the given vector, expressed in pixels, to the transform, currently in use.  This allows, things like offsets and the radius of
        points to always be displayed with the same absolute size on the screen.
        """
        return vec * np.array(
            (self.viewWidth / self.canvas.winfo_width(),
             self.viewHeight / self.canvas.winfo_height()), np.double)

    def scaleVecToPixels(self, vec):
        return vec * np.array(
            (self.canvas.winfo_width() / self.viewWidth,
             self.canvas.winfo_height() / self.viewHeight), np.double)

    def onDraw(self, drawable, **kwargs):
        """Callback for DrawListener.  This can be used by a background calculation thread to signal the GUI to draw a new state."""
        self.drawInBackground(drawable)

    def onResize(self, event):
        pass

    def onClose(self):
        os._exit(0)
Example #9
0
class Application(Frame, object):
    """The application main class."""
    WIDTH, HEIGHT = 1280, 720
    BG = 'white'
    FONT = 'Verdana'
    FILE_OPEN_OPTIONS = {
        'mode': 'rb',
        'title': 'Choose *.json file',
        'defaultextension': '.json',
        'filetypes': [('JSON file', '*.json')]
    }
    DEFAULTS = 'default_settings.yaml'

    def __init__(self, master=None):
        """Creates application main window with sizes self.WIDTH and self.HEIGHT.

        :param master: instance - Tkinter.Tk instance
        """
        super(Application, self).__init__(master)
        self.master.title('Engine Game')
        self.master.geometry('{}x{}'.format(self.WIDTH, self.HEIGHT))
        self.master.protocol('WM_DELETE_WINDOW', self.exit)

        self.source = None
        self._map = None
        self.points = None
        self.lines = None
        self.captured_point = None
        self.x0 = None
        self.y0 = None
        self.scale_x = None
        self.scale_y = None
        self.font_size = None
        self.coordinates = {}
        self.captured_lines = {}
        self.canvas_obj = AttrDict()
        self.icons = {
            0: PhotoImage(file=join('icons', 'player_city.png')),
            1: PhotoImage(file=join('icons', 'city.png')),
            2: PhotoImage(file=join('icons', 'market.png')),
            3: PhotoImage(file=join('icons', 'store.png')),
            4: PhotoImage(file=join('icons', 'point.png')),
            5: PhotoImage(file=join('icons', 'player_train.png')),
            6: PhotoImage(file=join('icons', 'train.png')),
            7: PhotoImage(file=join('icons', 'crashed_train.png')),
            8: PhotoImage(file=join('icons', 'collision.png')),
            9: PhotoImage(file=join('icons', 'play.png')),
            10: PhotoImage(file=join('icons', 'play_pressed.png')),
            11: PhotoImage(file=join('icons', 'stop.png')),
            12: PhotoImage(file=join('icons', 'stop_pressed.png'))
        }
        self.queue_requests = {
            0: self.set_status_bar,
            1: self.set_player_idx,
            2: self.build_map,
            3: self.refresh_map,
            4: self.set_available_games,
            99: self.bot_control
        }

        self.settings_window = None
        if exists(expanduser(self.DEFAULTS)):
            with open(expanduser(self.DEFAULTS), 'r') as cfg:
                defaults = DefaultsDict.from_yaml(cfg)
            self.host = None if not defaults.host else str(defaults.host)
            self.port = None if not defaults.port else int(defaults.port)
            self.timeout = None if not defaults.timeout else int(defaults.timeout)
            self.username = None if not defaults.username else str(defaults.username)
            self.password = None if not defaults.password else str(defaults.password)
        else:
            self.host, self.port, self.timeout, self.username, self.password = None, None, None, None, None
        self.player_idx = None
        self.posts = {}
        self.trains = {}
        self.select_game_window = False
        self.available_games = None
        self.game = None
        self.num_players = None
        self.num_turns = None
        self.bot = Bot()
        self.bot_thread = None

        self.menu = Menu(self)
        filemenu = Menu(self.menu)
        filemenu.add_command(label='Open file', command=self.file_open)
        filemenu.add_command(label='Server settings', command=self.open_server_settings)
        filemenu.add_command(label='Select game', command=self.select_game)
        filemenu.add_command(label='Exit', command=self.exit)
        self.menu.add_cascade(label='Menu', menu=filemenu)
        master.config(menu=self.menu)

        self._status_bar = StringVar()
        self.label = Label(master, textvariable=self._status_bar)
        self.label.pack()

        self.frame = Frame(self)
        self.frame.bind('<Configure>', self._resize_frame)
        self.canvas = Canvas(self.frame, bg=self.BG, scrollregion=(0, 0, self.winfo_width(), self.winfo_height()))
        self.canvas.bind('<Button-1>', self._capture_point)
        self.canvas.bind('<Motion>', self._move_point)
        self.canvas.bind('<B1-ButtonRelease>', self._release_point)
        self.canvas.bind('<Configure>', self._resize_canvas)
        hbar = Scrollbar(self.frame, orient=HORIZONTAL)
        hbar.pack(side=BOTTOM, fill=X)
        hbar.config(command=self.canvas.xview)
        vbar = Scrollbar(self.frame, orient=VERTICAL)
        vbar.pack(side=RIGHT, fill=Y)
        vbar.config(command=self.canvas.yview)
        self.canvas.config(xscrollcommand=hbar.set, yscrollcommand=vbar.set)
        self.canvas.pack(fill=BOTH, expand=True)
        self.play = Label(self.canvas, bg='white')
        self.play.configure(image=self.icons[9])
        self.play.bind('<Button-1>', self._play_press)
        self.play.bind('<B1-ButtonRelease>', self._play_release)
        self.stop = Label(self.canvas, bg='white')
        self.stop.configure(image=self.icons[11])
        self.stop.bind('<Button-1>', self._stop_press)
        self.stop.bind('<B1-ButtonRelease>', self._stop_release)
        self.frame.pack(fill=BOTH, expand=True)

        self.weighted = IntVar(value=1)
        self.weighted_check = Checkbutton(self, text='Proportionally to length', variable=self.weighted,
                                          command=self._proportionally)
        self.weighted_check.pack(side=LEFT)

        self.show_weight = IntVar()
        self.show_weight_check = Checkbutton(self, text='Show length', variable=self.show_weight,
                                             command=self.show_weights)
        self.show_weight_check.pack(side=LEFT)

        self.pack(fill=BOTH, expand=True)
        self.requests_executor()
        self.get_available_games()
        self.set_status_bar('Click Play to start the game')
        self.play.place(rely=0.5, relx=0.5, anchor=CENTER)

    @property
    def map(self):
        """Returns the actual map."""
        return self._map

    @map.setter
    def map(self, value):
        """Clears previously drawn map and assigns a new map to self._map."""
        self.clear_map()
        self.canvas.configure(scrollregion=(0, 0, self.canvas.winfo_width(), self.canvas.winfo_height()))
        self.x0, self.y0 = self.canvas.winfo_width() / 2, self.canvas.winfo_height() / 2
        self._map = value

    @staticmethod
    def midpoint(x_start, y_start, x_end, y_end):
        """Calculates a midpoint coordinates between two points.

        :param x_start: int - x coordinate of the start point
        :param y_start: int - y coordinate of the start point
        :param x_end: int - x coordinate of the end point
        :param y_end: int - y coordinate of the end point
        :return: 2-tuple of a midpoint coordinates
        """
        return (x_start + x_end) / 2, (y_start + y_end) / 2

    def _resize_frame(self, event):
        """Calculates new font size each time frame size changes.

        :param event: Tkinter.Event - Tkinter.Event instance for Configure event
        :return: None
        """
        self.font_size = int(0.0125 * min(event.width, event.height))

    def _resize_canvas(self, event):
        """Redraws map each time Canvas size changes. Scales map each time visible part of Canvas is enlarged.

        :param event: Tkinter.Event - Tkinter.Event instance for Configure event
        :return: None
        """
        if self.map:
            k = min(float(event.width) / float(self.x0 * 2), float(event.height) / float(self.y0 * 2))
            self.scale_x, self.scale_y = self.scale_x * k, self.scale_y * k
            self.x0, self.y0 = self.x0 * k, self.y0 * k
            self.redraw_map()
            self.redraw_trains()
            x_start, y_start, x_end, y_end = self.canvas.bbox('all')
            x_start = 0 if x_start > 0 else x_start
            y_start = 0 if y_start > 0 else y_start
            self.canvas.configure(scrollregion=(x_start, y_start, x_end, y_end))

    def _proportionally(self):
        """Rebuilds map and redraws trains."""
        self.build_map()
        self.redraw_trains()

    def _capture_point(self, event):
        """Stores captured point and it's lines.

        :param event: Tkinter.Event - Tkinter.Event instance for ButtonPress event
        :return: None
        """
        x, y = self.canvas.canvasx(event.x), self.canvas.canvasy(event.y)
        obj_ids = self.canvas.find_overlapping(x - 5, y - 5, x + 5, y + 5)
        if not obj_ids:
            return
        for obj_id in obj_ids:
            if obj_id in self.canvas_obj.point.keys():
                self.captured_point = obj_id
                point_idx = self.canvas_obj.point[obj_id]['idx']
                self.captured_lines = {}
                for line_id, attr in self.canvas_obj.line.items():
                    if attr['start_point'] == point_idx:
                        self.captured_lines[line_id] = 'start_point'
                    if attr['end_point'] == point_idx:
                        self.captured_lines[line_id] = 'end_point'
        if self.weighted.get():
            self.weighted.set(0)

    def _release_point(self, event):
        """Writes new coordinates for a moved point and resets self.captured_point and self.captured_lines.

        :param event: Tkinter.Event - Tkinter.Event instance for ButtonRelease event
        :return: None
        """
        if self.captured_point:
            idx = self.canvas_obj.point[self.captured_point]['idx']
            x, y = self.canvas.canvasx(event.x), self.canvas.canvasy(event.y)
            self.coordinates[idx] = (x, y)
            self.points[idx]['x'], self.points[idx]['y'] = (x - self.x0) / self.scale_x, (y - self.y0) / self.scale_y
            self.captured_point = None
            self.captured_lines = {}

    def _move_point(self, event):
        """Moves point and its lines. Moves weights if self.show_weight is set to 1.

        In case some point is moved beyond Canvas border Canvas scrollregion is resized correspondingly.
        :param event: Tkinter.Event - Tkinter.Event instance for Motion event
        :return: None
        """
        if self.captured_point:
            new_x, new_y = self.canvas.canvasx(event.x), self.canvas.canvasy(event.y)
            self.canvas.coords(self.captured_point, new_x, new_y)
            indent_y = self.icons[self.canvas_obj.point[self.captured_point]['icon']].height() / 2 + self.font_size
            if self.canvas_obj.point[self.captured_point]['text_obj']:
                self.canvas.coords(self.canvas_obj.point[self.captured_point]['text_obj'], new_x, new_y - indent_y)
            self.coordinates[self.canvas_obj.point[self.captured_point]['idx']] = (new_x, new_y)
            self.canvas.configure(scrollregion=self.canvas.bbox('all'))

            for line_id, attr in self.captured_lines.items():
                line_attrs = self.canvas_obj.line[line_id]
                if attr == 'start_point':
                    x, y = self.coordinates[line_attrs['end_point']]
                    self.canvas.coords(line_id, new_x, new_y, x, y)
                else:
                    x, y = self.coordinates[line_attrs['start_point']]
                    self.canvas.coords(line_id, x, y, new_x, new_y)
                if self.show_weight.get():
                    mid_x, mid_y = self.midpoint(new_x, new_y, x, y)
                    self.canvas.coords(line_attrs['weight_obj'][1], mid_x, mid_y)
                    r = self.font_size * len(str(line_attrs['weight']))
                    self.canvas.coords(line_attrs['weight_obj'][0], mid_x - r, mid_y - r, mid_x + r, mid_y + r)

            self.redraw_trains()

    def _play_press(self, _):
        """Draws play button pressed icon."""
        self.play.configure(image=self.icons[10])

    def _play_release(self, _):
        """Draws play button icon and calls bot_control method."""
        self.play.configure(image=self.icons[9])
        self.bot_control()

    def _stop_press(self, _):
        """Draws stop button pressed icon."""
        self.stop.configure(image=self.icons[12])

    def _stop_release(self, _):
        """Draws stop buton icon and calls bot_control method."""
        self.stop.configure(image=self.icons[11])
        self.bot_control()

    def set_player_idx(self, value):
        """Sets a player idx value."""
        self.player_idx = value

    def file_open(self):
        """Opens file dialog and builds and draws a map once a file is chosen. Stops bot if its started."""
        path = tkFileDialog.askopenfile(parent=self.master, **self.FILE_OPEN_OPTIONS)
        if path:
            if self.bot_thread:
                self.bot_control()
            self.posts, self.trains = {}, {}
            self.source = path.name
            self.weighted_check.configure(state=NORMAL)
            self.build_map()

    def open_server_settings(self):
        """Opens server settings window."""
        ServerSettings(self, title='Server settings')

    def select_game(self):
        """Opens select game window."""
        self.select_game_window = True
        SelectGame(self, title='Select game')
        self.select_game_window = False
        self.set_status_bar('Click Play to start the game')

    def exit(self):
        """Closes application and stops bot if its started."""
        if self.bot_thread:
            self.bot_control()
        self.master.destroy()

    def bot_control(self):
        """Starts bot for playing the game or stops it if it is started."""
        if not self.bot_thread:
            self.bot_thread = Thread(target=self.bot.start, kwargs={
                'host': self.host,
                'port': self.port,
                'time_out': self.timeout,
                'username': self.username,
                'password': self.password,
                'game': self.game,
                'num_players': self.num_players,
                'num_turns': self.num_turns})
            self.bot_thread.start()
        else:
            self.bot.stop()
            self.bot_thread.join()
            self.bot_thread = None

    def get_available_games(self):
        """Requests a list of available games."""
        if self.select_game_window:
            self.bot.get_available_games(host=self.host, port=self.port, time_out=self.timeout)
        self.after(1000, self.get_available_games)

    def set_available_games(self, games):
        """Sets new value for available games list."""
        self.available_games = games

    def set_status_bar(self, value):
        """Assigns new status bar value and updates it.

        :param value: string - status bar string value
        :return: None
        """
        self._status_bar.set(value)
        self.label.update()

    def build_map(self, source=None):
        """Builds and draws new map.

        :param source: string - source string; could be JSON string or path to *.json file.
        :return: None
        """
        if source:
            self.source = source
        if self.source:
            self.map = Graph(self.source, weighted=self.weighted.get())
            self.set_status_bar('Map title: {}'.format(self.map.name))
            self.points, self.lines = self.map.get_coordinates()
            self.draw_map()

    def draw_map(self):
        """Draws map by prepared coordinates."""
        self.draw_lines()
        self.draw_points()

    def clear_map(self):
        """Clears previously drawn map and resets coordinates and scales."""
        self.canvas.delete('all')
        self.scale_x, self.scale_y = None, None
        self.coordinates = {}

    def redraw_map(self):
        """Redraws existing map by existing coordinates."""
        if self.map:
            self.coordinates = {}
            for obj_id in self.canvas_obj.line:
                self.canvas.delete(obj_id)
            self.draw_lines()
        self.redraw_points()

    def redraw_points(self):
        """Redraws map points by existing coordinates."""
        if self.map:
            for obj_id, attrs in self.canvas_obj.point.items():
                if attrs['text_obj']:
                    self.canvas.delete(attrs['text_obj'])
                self.canvas.delete(obj_id)
            self.draw_points()

    def redraw_trains(self):
        """Redraws existing trains."""
        if self.trains and hasattr(self.canvas_obj, 'train'):
            for obj_id, attrs in self.canvas_obj.train.items():
                self.canvas.delete(attrs['text_obj'])
                self.canvas.delete(obj_id)
        self.draw_trains()

    @prepare_coordinates
    def draw_points(self):
        """Draws map points by prepared coordinates."""
        point_objs = {}
        captured_point_idx = self.canvas_obj.point[self.captured_point]['idx'] if self.captured_point else None
        for idx in self.points.keys():
            x, y = self.coordinates[idx]
            if self.posts and idx in self.posts.keys():
                post_type = self.posts[idx]['type']
                if post_type == 1:
                    status = '{}/{} {}/{} {}/{}'.format(self.posts[idx]['population'],
                                                        self.posts[idx]['population_capacity'],
                                                        self.posts[idx]['product'],
                                                        self.posts[idx]['product_capacity'],
                                                        self.posts[idx]['armor'],
                                                        self.posts[idx]['armor_capacity'])
                elif post_type == 2:
                    status = '{}/{}'.format(self.posts[idx]['product'], self.posts[idx]['product_capacity'])
                else:
                    status = '{}/{}'.format(self.posts[idx]['armor'], self.posts[idx]['armor_capacity'])
                image_id = 0 if post_type == 1 and self.posts[idx]['player_idx'] == self.player_idx else post_type
                point_id = self.canvas.create_image(x, y, image=self.icons[image_id])
                y -= (self.icons[post_type].height() / 2) + self.font_size
                text_id = self.canvas.create_text(x, y, text=status, font="{} {}".format(self.FONT, self.font_size))
            else:
                post_type = 4
                point_id = self.canvas.create_image(x, y, image=self.icons[post_type])
                text_id = None
            point_objs[point_id] = {'idx': idx, 'text_obj': text_id, 'icon': post_type}
            self.captured_point = point_id if idx == captured_point_idx else self.captured_point
        self.canvas_obj['point'] = point_objs

    @prepare_coordinates
    def draw_lines(self):
        """Draws map lines by prepared coordinates and shows their weights if self.show_weight is set to 1."""
        line_objs, captured_lines_idx = {}, {}
        if self.captured_lines:
            for line_id in self.captured_lines.keys():
                captured_lines_idx[self.canvas_obj.line[line_id]['idx']] = line_id
        for idx, attrs in self.lines.items():
            x_start, y_start = self.coordinates[attrs['start_point']]
            x_stop, y_stop = self.coordinates[attrs['end_point']]
            line_id = self.canvas.create_line(x_start, y_start, x_stop, y_stop)
            line_objs[line_id] = {'idx': idx, 'weight': attrs['weight'], 'start_point': attrs['start_point'],
                                  'end_point': attrs['end_point'], 'weight_obj': ()}
            if idx in captured_lines_idx.keys():
                self.captured_lines[line_id] = self.captured_lines.pop(captured_lines_idx[idx])
        self.canvas_obj['line'] = line_objs
        self.show_weights()

    @prepare_coordinates
    def draw_trains(self):
        """Draws trains by prepared coordinates."""
        trains = {}
        for train in self.trains.values():
            start_point = self.lines[train['line_idx']]['start_point']
            end_point = self.lines[train['line_idx']]['end_point']
            weight = self.lines[train['line_idx']]['weight']
            position = train['position']
            x_start, y_start = self.coordinates[start_point]
            x_end, y_end = self.coordinates[end_point]
            delta_x, delta_y = int((x_start - x_end) / weight) * position, int((y_start - y_end) / weight) * position
            x, y = x_start - delta_x, y_start - delta_y
            if train['cooldown'] > 0:
                icon = 7
                status = None
            else:
                icon = 5 if train['player_idx'] == self.player_idx else 6
                status = '{}/{}'.format(train['goods'], train['goods_capacity'])
            indent_y = self.icons[icon].height() / 2
            train_id = self.canvas.create_image(x, y - indent_y, image=self.icons[icon])
            text_id = self.canvas.create_text(x, y - (2 * indent_y + self.font_size), text=status,
                                              font="{} {}".format(self.FONT, self.font_size)) if status else None
            trains[train_id] = {'icon': icon, 'text_obj': text_id}
        self.canvas_obj['train'] = trains

    def show_weights(self):
        """Shows line weights when self.show_weight is set to 1 and hides them when it is set to 0."""
        if not self.canvas_obj:
            return
        if self.show_weight.get():
            for line in self.canvas_obj.line.values():
                if line['weight_obj']:
                    for obj in line['weight_obj']:
                        self.canvas.itemconfigure(obj, state='normal')
                else:
                    x_start, y_start = self.coordinates[line['start_point']]
                    x_end, y_end = self.coordinates[line['end_point']]
                    x, y = self.midpoint(x_start, y_start, x_end, y_end)
                    value = line['weight']
                    size = self.font_size
                    r = int(size) * len(str(value))
                    oval_id = self.canvas.create_oval(x - r, y - r, x + r, y + r, fill=self.BG, width=0)
                    text_id = self.canvas.create_text(x, y, text=value, font="{} {}".format(self.FONT, str(size)))
                    line['weight_obj'] = (oval_id, text_id)
        else:
            for line in self.canvas_obj.line.values():
                if line['weight_obj']:
                    for obj in line['weight_obj']:
                        self.canvas.itemconfigure(obj, state='hidden')

    def requests_executor(self):
        """Dequeues and executes requests. Assigns corresponding label to bot control button."""
        if not self.bot.queue.empty():
            request_type, request_body = self.bot.queue.get_nowait()
            if request_type == 99 and request_body:
                self.open_server_settings()
                request_body = None
            if request_body is not None:
                self.queue_requests[request_type](request_body)
            else:
                self.queue_requests[request_type]()
        if self.bot_thread and self.bot_thread.is_alive():
            if self.play.place_info():
                self.play.place_forget()
                self.stop.place(rely=0.99, relx=0.995, anchor=SE)
        else:
            if self.stop.place_info():
                self.stop.place_forget()
                self.play.place(rely=0.5, relx=0.5, anchor=CENTER)
        self.after(50, self.requests_executor)

    def refresh_map(self, dynamic_objects):
        """Refreshes map with passed dynamic objects.

        :param dynamic_objects: dict - dict of dynamic objects
        :return: None
        """
        for post in dynamic_objects['posts']:
            self.posts[post['point_idx']] = post
        for train in dynamic_objects['trains']:
            self.trains[train['idx']] = train
        self.redraw_points()
        self.redraw_trains()
Example #10
0
class Scraper():

    def __init__(self, img_filename='snap.png'):
        self.canvas = Canvas()
        self.scales = []
        self.canvas.pack()
        self._current_image = None
        self._original_image = None
        
        self.root = self._load_gui()
        self.open_image(img_filename)
        self.repaint()
        self.root.mainloop()

    @property
    def image(self):
        return self._current_image

    @image.setter
    def image(self, value):
        self._current_image = value

    @property
    def original_image(self):
        return self._original_image

    @image.setter
    def image(self, value):
        self._original_image = value

    def open_image(self, filename):
        self.original_image = Image.open(filename).copy()
        self.image = self.original_image

    def repaint(self):
        rgb_min = (self.scale_red_min.get(), self.scale_green_min.get(), self.scale_blue_min.get())
        rgb_max = (self.scale_red_max.get(), self.scale_green_max.get(), self.scale_blue_max.get())
        print "repainting", rgb_min, rgb_max
        self.image = strip_colors(self.original_image, rgb_min, rgb_max)
        self._paint(self.image)

    def _paint(self, image):
        if image is not None:
            # check if we need to resize the canvas, based on the size of the image being painted
            image_width, image_height = image.size
            if self.canvas.winfo_width() != image_width or self.canvas.winfo_height() != image_height:
                self.canvas.config(width=image_width, height=image_height)

            # paint the image to the canvas
            self._img_tk = ImageTk.PhotoImage(image)
            self.canvas.create_image(0, 0, image=self._img_tk, anchor=NW)
        else:
            print 'there is no image to paint'
            return -1
 
    def _load_gui(self):
        root = Tk()
        root.title("Scraper")
        main_frame = Frame(root)
        main_frame.grid(column=0, row=0, sticky=(N, W, E, S))
        main_frame.columnconfigure(0, weight=1)
        main_frame.rowconfigure(0, weight=1)
        main_frame.pack()
        
        self.scale_red_min = Scale(main_frame, from_=0, to=255, orient=HORIZONTAL, command=self._update_red_min)
        self.scale_red_min.grid(column=1, row=1)
       
        self.scale_red_max = Scale(main_frame, from_=0, to=255, orient=HORIZONTAL, command=self._update_red_max)
        self.scale_red_max.grid(column=2, row=1)
        self.scale_red_max.set(255)
        
        self.scale_green_min = Scale(main_frame, from_=0, to=255, orient=HORIZONTAL, command=self._update_green_min)
        self.scale_green_min.grid(column=1, row=2)

        self.scale_green_max = Scale(main_frame, from_=0, to=255, orient=HORIZONTAL, command=self._update_green_max)
        self.scale_green_max.grid(column=2, row=2)
        self.scale_green_max.set(255)

        self.scale_blue_min = Scale(main_frame, from_=0, to=255, orient=HORIZONTAL, command=self._update_blue_min)
        self.scale_blue_min.grid(column=1, row=3)
        
        self.scale_blue_max = Scale(main_frame, from_=0, to=255, orient=HORIZONTAL, command=self._update_blue_max)
        self.scale_blue_max.grid(column=2, row=3)
        self.scale_blue_max.set(255)
        return root

    def _update_red_min(self, value):
        print 'updating red min to %s' % value
        if self.scale_red_min.get() > self.scale_red_max.get():
            self.scale_red_max.set(self.scale_red_min.get())
        self.repaint()

    def _update_red_max(self, value):
        print 'updating red max to %s' % value
        if self.scale_red_max.get() < self.scale_red_min.get():
            self.scale_red_min.set(self.scale_red_max.get())
        self.repaint()

    def _update_green_min(self, value):
        print 'updating green min to %s' % value
        if self.scale_green_min.get() > self.scale_green_max.get():
            self.scale_green_max.set(self.scale_green_min.get())
        self.repaint()

    def _update_green_max(self, value):
        print 'updating green max to  %s' % value
        if self.scale_green_max.get() < self.scale_green_min.get():
            self.scale_green_min.set(self.scale_green_max.get())
        self.repaint()

    def _update_blue_min(self, value):
        print 'updating blue min to %s' % value
        if self.scale_blue_min.get() > self.scale_blue_max.get():
            self.scale_blue_max.set(self.scale_blue_min.get())
        self.repaint()

    def _update_blue_max(self, value):
        print 'updating blue max to %s' % value
        if self.scale_blue_max.get() < self.scale_blue_min.get():
            self.scale_blue_min.set(self.scale_blue_max.get())
        self.repaint()
class Scrolling_Area(Frame, object):

    def __init__(self, master, width=None, anchor=N, height=None, mousewheel_speed = 2, scroll_horizontally=True, xscrollbar=None, scroll_vertically=True, yscrollbar=None, outer_background=None, inner_frame=Frame, **kw):
        Frame.__init__(self, master, class_=self.__class__)

        if outer_background:
            self.configure(background=outer_background)

        self.grid_columnconfigure(0, weight=1)
        self.grid_rowconfigure(0, weight=1)
        
        self._width = width
        self._height = height

        self.canvas = Canvas(self, background=outer_background, highlightthickness=0, width=width, height=height)
        self.canvas.grid(row=0, column=0, sticky=N+E+W+S)

        if scroll_vertically:
            if yscrollbar is not None:
                self.yscrollbar = yscrollbar
            else:
                self.yscrollbar = Scrollbar(self, orient=VERTICAL)
                self.yscrollbar.grid(row=0, column=1,sticky=N+S)
        
            self.canvas.configure(yscrollcommand=self.yscrollbar.set)
            self.yscrollbar['command']=self.canvas.yview
        else:
            self.yscrollbar = None

        if scroll_horizontally:
            if xscrollbar is not None:
                self.xscrollbar = xscrollbar
            else:
                self.xscrollbar = Scrollbar(self, orient=HORIZONTAL)
                self.xscrollbar.grid(row=1, column=0, sticky=E+W)
            
            self.canvas.configure(xscrollcommand=self.xscrollbar.set)
            self.xscrollbar['command']=self.canvas.xview
        else:
            self.xscrollbar = None

        self.rowconfigure(0, weight=1)
        self.columnconfigure(0, weight=1)
        
        self.innerframe = inner_frame(self.canvas, **kw)
        self.innerframe.pack(anchor=anchor)
        
        self.canvas.create_window(0, 0, window=self.innerframe, anchor='nw', tags="inner_frame")

        self.canvas.bind('<Configure>', self._on_canvas_configure)

        Mousewheel_Support(self).add_support_to(self.canvas, xscrollbar=self.xscrollbar, yscrollbar=self.yscrollbar)

    @property
    def width(self):
        return self.canvas.winfo_width()

    @width.setter
    def width(self, width):
        self.canvas.configure(width= width)

    @property
    def height(self):
        return self.canvas.winfo_height()
        
    @height.setter
    def height(self, height):
        self.canvas.configure(height = height)
        
    def set_size(self, width, height):
        self.canvas.configure(width=width, height = height)

    def _on_canvas_configure(self, event):
        width = max(self.innerframe.winfo_reqwidth(), event.width)
        height = max(self.innerframe.winfo_reqheight(), event.height)

        self.canvas.configure(scrollregion="0 0 %s %s" % (width, height))
        self.canvas.itemconfigure("inner_frame", width=width, height=height)

    def update_viewport(self):
        self.update()

        window_width = self.innerframe.winfo_reqwidth()
        window_height = self.innerframe.winfo_reqheight()
        
        if self._width is None:
            canvas_width = window_width
        else:
            canvas_width = min(self._width, window_width)
            
        if self._height is None:
            canvas_height = window_height
        else:
            canvas_height = min(self._height, window_height)

        self.canvas.configure(scrollregion="0 0 %s %s" % (window_width, window_height), width=canvas_width, height=canvas_height)
        self.canvas.itemconfigure("inner_frame", width=window_width, height=window_height)
Example #12
0
class Screen(Observer):
    def __init__(self, parent, bg="white"):
        self.canvas = Canvas(parent, bg=bg)
        self.canvas.bind("<Configure>", self.resize)
        self.width = int(self.canvas.cget("width"))
        self.height = int(self.canvas.cget("height"))

        print("parent", parent.cget("width"), parent.cget("height"))

        self.magnitude = Scale(parent,
                               length=250,
                               orient="horizontal",
                               label="Magnitude",
                               sliderlength=20,
                               showvalue=0,
                               from_=0,
                               to=10,
                               tickinterval=1,
                               relief="sunken")

        self.frequency = Scale(parent,
                               length=250,
                               orient="horizontal",
                               label="Frequency",
                               sliderlength=20,
                               showvalue=0,
                               from_=0,
                               to=10,
                               tickinterval=1,
                               relief="sunken")

        self.phase = Scale(parent,
                           length=250,
                           orient="horizontal",
                           label="Phase",
                           sliderlength=20,
                           showvalue=0,
                           from_=0,
                           to=10,
                           tickinterval=1,
                           relief="sunken")

    def update(self, model):
        print("View update")
        signal = model.get_signal()
        self.plot_signal(signal)

    def get_magnitude(self):
        return self.magnitude

    def get_frequency(self):
        return self.frequency

    def get_phase(self):
        return self.phase

    def plot_signal(self, signal, color="red"):
        w, h = self.canvas.winfo_width(), self.canvas.winfo_height()
        width, height = int(w), int(h)
        print(self.canvas.find_withtag("signal"))
        if self.canvas.find_withtag("signal"):
            self.canvas.delete("signal")
        if signal and len(signal) > 1:
            plot = [(x * width, height / 2.0 * (y + 1)) for (x, y) in signal]
            signal_id = self.canvas.create_line(plot,
                                                fill=color,
                                                smooth=1,
                                                width=3,
                                                tags="signal")
        return

    def grid(self, steps):
        w, h = self.canvas.cget("width"), self.canvas.cget("height")
        width, height = int(w), int(h)
        #       self.canvas.create_line(10,height/2,width,height/2,arrow="last")
        #       self.canvas.create_line(10,height-5,10,5,arrow="last")
        step = (width - 10) / steps * 1.
        for t in range(1, steps + 2):
            x = t * step
            self.canvas.create_line(x, 0, x, height)
            self.canvas.create_line(0, x, width, x)

    def packing(self):
        self.canvas.pack()
        self.magnitude.pack()
        self.frequency.pack()
        self.phase.pack()
        self.canvas.pack(expand=1, fill="both", padx=6)
        self.magnitude.pack(expand=1, fill="x", padx=2)
        self.frequency.pack(expand=1, fill="x", padx=2)
        self.phase.pack(expand=1, fill="x", padx=2)

    def resize(self, event):
        wscale = float(event.width) / self.width
        hscale = float(event.height) / self.height
        self.width = event.width
        self.height = event.height
        print("resize", wscale, hscale)
        # resize the canvas
        #self.config(width=self.width, height=self.height)
        scale_xy = self.width * 1.0 / self.height
        # rescale all the objects tagged with the "all" tag
        self.canvas.scale("all", 0, 0, wscale, hscale)
Example #13
0
    def __init__(self, master):
        def center(win):
            win.update_idletasks()
            width = win.winfo_width()
            height = win.winfo_height()
            x = (win.winfo_screenwidth() // 4) - (width // 2) + 40
            y = (win.winfo_screenheight() // 4) - (height // 2) + 40
            win.geometry('{}x{}+{}+{}'.format(width, height, x, y))

        def callback(event):
            event.widget.focus_set()
            print "clicked at", event.x, event.y

            if self.add_tasks_flg.get() == 1:
                self.enter_task(event)

        master.title("Map Interface")
        master.minsize(width=1000, height=750)
        master.maxsize(width=1000, height=750)
        master.config(bg=BKG_COLOUR)
        self.master = master

        # Canvas for overlaying map
        global MAP_CANVAS
        MAP_CANVAS = Canvas(master,
                            width=CANVAS_W,
                            height=CANVAS_H,
                            bg='gray85',
                            highlightthickness=0)
        MAP_CANVAS.pack(side='right', padx=50)
        MAP_CANVAS.bind("<Button-1>", callback)
        global CANVAS_PTR
        CANVAS_PTR = MAP_CANVAS
        self.master.update()
        w = MAP_CANVAS.winfo_width()
        h = MAP_CANVAS.winfo_height()
        # Overlay a grid
        for i in range(0, w, SQ_SIZE):
            if i != 0:
                MAP_CANVAS.create_line(i, 0, i, h, dash=1)
        for i in range(0, h, SQ_SIZE):
            if i != 0:
                MAP_CANVAS.create_line(0, i, w, i, dash=1)

        # Load in flame icon from flame.gif
        self.flame_icon = PhotoImage(file="flame.gif")
        # Load in the drone icon from drone.gif
        global DRONE_ICON
        DRONE_ICON = PhotoImage(file="drone.gif")

        buttons_frame = Canvas(master,
                               width=163,
                               height=140,
                               bg=BUTTONS_BKG_COLOUR,
                               highlightthickness=1,
                               highlightbackground='dim grey')
        buttons_frame.place(x=40, y=230)

        # Define UI buttons
        self.add_tasks_flg = IntVar()
        self.add_tasks_b = Checkbutton(master,
                                       text="Add Tasks",
                                       variable=self.add_tasks_flg,
                                       highlightbackground=BUTTONS_BKG_COLOUR,
                                       background=BUTTONS_BKG_COLOUR)
        self.add_tasks_b.place(x=77, y=270)

        self.clear_wp_b = Button(master,
                                 text='Clear Tasks',
                                 command=self.clear_wp,
                                 highlightbackground=BUTTONS_BKG_COLOUR)
        self.clear_wp_b.config(width=10)
        self.clear_wp_b.place(x=65, y=300)
        '''
        self.gen_wp_file_b = Button(master, text='Generate Waypoints File', command=self.gen_wp_file, highlightbackground=BKG_COLOUR)
        self.gen_wp_file_b.config(width=20)
        self.gen_wp_file_b.place(x=20, y=250)
        '''
        '''
        self.land_b = Button(master, text='Land', command=self.land, highlightbackground=BUTTONS_BKG_COLOUR)
        self.land_b.config(width=10)
        self.land_b.place(x=65, y=350)
        '''

        # Set up coordinate system conversion and display corners of room:
        file_obj = open('antenna_locations.txt', 'r')
        anchors = []
        for line in file_obj:
            cur_anchors = map(float, line.split())
            anchors.append(cur_anchors)
        file_obj.close()
        anchors = (np.array(anchors)).T

        # Find largest (abs) x and y values to use a reference for conversion ratio
        x_vals = anchors[0]
        largest_x_val = x_vals[np.argmax(abs(x_vals))]
        y_vals = anchors[1]
        largest_y_val = y_vals[np.argmax(abs(y_vals))]

        if largest_x_val > largest_y_val:
            largest_y_val = largest_x_val
        else:
            largest_x_val = largest_y_val

        global m_per_pixel_x
        m_per_pixel_x = float(largest_x_val / (CANVAS_W / 2))
        global m_per_pixel_y
        m_per_pixel_y = float(largest_y_val / (CANVAS_H / 2))

        # Place antenna (anchors) on UI
        anchors = anchors.T
        for cur_anchor in anchors:
            x_pixel_loc = cur_anchor[0] / m_per_pixel_x + CANVAS_W / 2
            y_pixel_loc = -1 * (cur_anchor[1] / m_per_pixel_y) + CANVAS_H / 2

            # Draw antenna @ location
            global ANTENNA_LIST
            antenna_id = MAP_CANVAS.create_oval(x_pixel_loc - 15,
                                                y_pixel_loc - 15,
                                                x_pixel_loc + 15,
                                                y_pixel_loc + 15,
                                                fill='red')

        self.master.update()
class HackPlot(object):
    def __init__(self, parent, move_mode, show_path, use_event_bars,
                 log_levels):
        self.canvas = Canvas(parent, bg="white")
        self.listbox = Listbox(parent,
                               width=20,
                               bg="white",
                               state="disabled",
                               disabledforeground="black")
        self.canvas.bind("<Configure>", self.redraw)
        self.canvas.bind("<ButtonPress-1>", self.mousedown)
        self.canvas.bind("<ButtonRelease-1>", self.mouseup)
        self.canvas.bind("<Motion>", self.mousemove)
        self.canvas.bind("<Leave>", self.mouseleave)
        self.canvas.bind("<ButtonPress-3>", self.cancelzoom)
        self.move_mode = move_mode
        self.show_path = show_path
        self.use_event_bars = use_event_bars
        self.log_levels = log_levels
        self.reset()

    def redraw(self, event):
        self.canvas.delete("all")
        self.legend = []
        self.draw_boundary()
        self.zoom_trace = None
        self.show_textlogs()
        for name in self.plots:
            self.draw_plot(name)
        self.draw_legend()

    def reset(self):
        self.x_low = -0.5
        self.x_high = 0.5
        self.y_low = -0.5
        self.y_high = 0.5
        self.mouse_start = None
        self.color_index = 0
        self.compute_width_height()
        self.draw_boundary()
        self.plots = {}
        self.legend = []
        self.event_bars = []
        self.logs = {}
        self.coord_text = None
        self.zoom_trace = None
        self.redraw(None)

    def compute_width_height(self):
        self.plot_width = self.x_high - self.x_low
        self.plot_height = self.y_high - self.y_low

    # Draw outline of plot area and axis ticks
    def draw_boundary(self):
        for x in self.get_ticks(self.x_low, self.x_high):
            screen_x, _ = self.screen_coords(x, 0)
            self.canvas.create_line(screen_x,
                                    self.canvas.winfo_height() * 0.1,
                                    screen_x,
                                    self.canvas.winfo_height() * 0.9,
                                    fill="light grey")
            self.canvas.create_text(screen_x,
                                    self.canvas.winfo_height() * 0.95,
                                    text=str(x))
        for y in self.get_ticks(self.y_low, self.y_high):
            _, screen_y = self.screen_coords(0, y)
            self.canvas.create_line(self.canvas.winfo_width() * 0.1,
                                    screen_y,
                                    self.canvas.winfo_width() * 0.9,
                                    screen_y,
                                    fill="light grey")
            self.canvas.create_text(self.canvas.winfo_width() * 0.05,
                                    screen_y,
                                    text=str(y))
        self.canvas.create_line(self.canvas.winfo_width() * 0.1,
                                self.canvas.winfo_height() * 0.1,
                                self.canvas.winfo_width() * 0.9,
                                self.canvas.winfo_height() * 0.1,
                                self.canvas.winfo_width() * 0.9,
                                self.canvas.winfo_height() * 0.9,
                                self.canvas.winfo_width() * 0.1,
                                self.canvas.winfo_height() * 0.9,
                                self.canvas.winfo_width() * 0.1,
                                self.canvas.winfo_height() * 0.1)

    def draw_legend(self):
        legend_width = 0
        legend_height = 0
        # Clear the legend, since new plots don't necessarily appear last
        for oid in self.legend:
            self.canvas.delete(oid)
        for name in self.plots:
            # Width = widest text, increase height with number of plots
            legend_width = max(legend_width, len(name) * 6)
            legend_height += 15
        # Add some padding
        legend_width += 10
        legend_height += 10
        if self.plots != {}:
            self.legend.append(
                self.canvas.create_rectangle(self.canvas.winfo_width() -
                                             legend_width,
                                             0,
                                             self.canvas.winfo_width(),
                                             legend_height,
                                             fill="white"))
        index = 0
        for name in self.plots:
            self.legend.append(
                self.canvas.create_text(self.canvas.winfo_width() - 5,
                                        index * 15 + 5,
                                        text=name,
                                        fill=self.plots[name].color,
                                        anchor=NE))
            index += 1

    def get_ticks(self, bound_low, bound_high):
        size = bound_high - bound_low
        # step is size rounded down to next power of 10
        step = 10**math.floor(math.log10(size))
        # Adjust the step so there are good number of ticks
        if size / step > 6:
            step *= 2
        elif size / step < 1.2:
            step /= 5
        elif size / step < 2:
            step /= 2
        return [
            i * step for i in range(int(math.ceil(bound_low / step)),
                                    int(math.ceil(bound_high / step + 1e-3)))
        ]

    def screen_coords(self, x, y):
        screen_x = ((x - self.x_low) / self.plot_width * 0.8 +
                    0.1) * self.canvas.winfo_width()
        screen_y = ((self.y_high - y) / self.plot_height * 0.8 +
                    0.1) * self.canvas.winfo_height()
        return (screen_x, screen_y)

    def plot_coords(self, x, y):
        plot_x = (float(x) / self.canvas.winfo_width() -
                  0.1) / 0.8 * self.plot_width + self.x_low
        plot_y = self.y_high - (float(y) / self.canvas.winfo_height() -
                                0.1) / 0.8 * self.plot_height
        return (plot_x, plot_y)

    def add_plot(self, xvals, yvals, name):
        self.plots[name] = Plot()
        self.plots[name].xvals = xvals
        self.plots[name].yvals = yvals
        self.plots[name].color = colors[self.color_index]
        self.color_index = (self.color_index + 1) % len(colors)
        self.draw_plot(name)
        self.draw_legend()

    def remove_plot(self, name):
        for oid in self.plots[name].points:
            self.canvas.delete(oid)
        self.plots.pop(name)
        self.draw_legend()

    def add_textlog(self, strings, name):
        # Each entry is pair of (first number in string) and (string with ending newline removed)
        self.logs[name] = [(int(re.search("\\d+",
                                          string).group()), string[:-1])
                           for string in strings]
        self.show_textlogs()

    def remove_textlog(self, name):
        self.logs.pop(name)
        self.show_textlogs()

    def draw_plot(self, name):
        color = self.plots[name].color
        points = []
        for x, y in itertools.izip(self.plots[name].xvals,
                                   self.plots[name].yvals):
            if x >= self.x_low and x <= self.x_high and y >= self.y_low and y <= self.y_high:
                screen_x, screen_y = self.screen_coords(x, y)
                points.append(
                    self.canvas.create_rectangle(screen_x - 1,
                                                 screen_y - 1,
                                                 screen_x + 1,
                                                 screen_y + 1,
                                                 outline=color))

        self.plots[name].points = points

    def show_textlogs(self):
        for oid in self.event_bars:
            self.canvas.delete(oid)
        self.event_bars = []
        # Combine all logs into chronological order
        logs = []
        for _, log in self.logs.iteritems():
            logs += log
        logs.sort()
        # Needs to be normal state to add and remove elements
        self.listbox["state"] = NORMAL
        self.listbox.delete(0, END)
        for timestamp, string in logs:
            # Check whether the checkbox matching the start of the string is off
            level_included = True
            for level in self.log_levels:
                if string.startswith(level[1]) and level[0].get() == 0:
                    level_included = False
            if timestamp >= self.x_low and timestamp <= self.x_high and level_included:
                if self.show_path.get() == 0:
                    # Log format is [level]time:/path/to/file.cpp:line: message here
                    # To remove directory name, replace first ':' to last '/' before a ':' with a single ':'
                    string = ":".join(re.split(":[^:]*/", string))
                self.listbox.insert(END, string)
                screen_x, _ = self.screen_coords(float(timestamp), 0)
                if self.use_event_bars.get():
                    self.event_bars.append(
                        self.canvas.create_line(
                            screen_x,
                            self.canvas.winfo_height() * 0.1,
                            screen_x,
                            self.canvas.winfo_height() * 0.9,
                            fill="grey"))
        self.listbox["state"] = DISABLED

    def fit_x(self):
        self.x_low = 1e100
        self.x_high = -1e100
        # For x range, check data and text logs
        for _, plot in self.plots.iteritems():
            self.x_low = min(self.x_low, min(plot.xvals))
            self.x_high = max(self.x_high, max(plot.xvals))
        for _, logs in self.logs.iteritems():
            self.x_low = min(self.x_low, logs[0][0])
            self.x_high = max(self.x_high, logs[-1][0])
        if self.x_low == self.x_high:
            # Add to range to avoid dividing bx 0
            self.x_low -= 0.5
            self.x_high += 0.5
        elif self.x_low > self.x_high:
            # There is no data, reset x range
            self.x_low = -0.5
            self.x_high = 0.5
        self.compute_width_height()
        self.redraw(None)

    def fit_y(self):
        self.y_low = 1e100
        self.y_high = -1e100
        for _, plot in self.plots.iteritems():
            self.y_low = min(self.y_low, min(plot.yvals))
            self.y_high = max(self.y_high, max(plot.yvals))
        if self.y_low == self.y_high:
            # Add to range to avoid dividing by 0
            self.y_low -= 0.5
            self.y_high += 0.5
        elif self.y_low > self.y_high:
            # There is no data, reset y range
            self.y_low = -0.5
            self.y_high = 0.5
        self.compute_width_height()
        self.redraw(None)

    def mousedown(self, event):
        self.mouse_start = self.plot_coords(event.x, event.y)

    def mouseup(self, event):
        mouse_end = self.plot_coords(event.x, event.y)
        if self.mouse_start == None:
            return
        if self.mouse_start[0] == mouse_end[0] or self.mouse_start[
                1] == mouse_end[1]:
            # This would require dividing by 0
            self.mouse_start = None
            return
        if self.move_mode.get() == "zoomin" and self.mouse_start != None:
            # Set plot bounds to selection bounds
            self.x_low = min(self.mouse_start[0], mouse_end[0])
            self.x_high = max(self.mouse_start[0], mouse_end[0])
            self.y_low = min(self.mouse_start[1], mouse_end[1])
            self.y_high = max(self.mouse_start[1], mouse_end[1])
        elif self.move_mode.get() == "zoomout" and self.mouse_start != None:
            selection_x_low = min(self.mouse_start[0], mouse_end[0])
            selection_x_high = max(self.mouse_start[0], mouse_end[0])
            selection_y_low = min(self.mouse_start[1], mouse_end[1])
            selection_y_high = max(self.mouse_start[1], mouse_end[1])
            # Set plot bounds such that current bounds fit in selection, ie,
            # scale zone around selection be ratio of sizes
            self.x_low -= (selection_x_low - self.x_low) * self.plot_width / (
                selection_x_high - selection_x_low)
            self.x_high += (self.x_high -
                            selection_x_high) * self.plot_width / (
                                selection_x_high - selection_x_low)
            self.y_low -= (selection_y_low - self.y_low) * self.plot_height / (
                selection_y_high - selection_y_low)
            self.y_high += (self.y_high -
                            selection_y_high) * self.plot_height / (
                                selection_y_high - selection_y_low)
        self.compute_width_height()
        self.redraw(None)
        self.mouse_start = None

    def mousemove(self, event):
        mouse_end = self.plot_coords(event.x, event.y)
        if self.move_mode.get() == "pan" and self.mouse_start != None:
            self.x_low += self.mouse_start[0] - mouse_end[0]
            self.x_high += self.mouse_start[0] - mouse_end[0]
            self.y_low += self.mouse_start[1] - mouse_end[1]
            self.y_high += self.mouse_start[1] - mouse_end[1]
            self.redraw(None)
        elif self.move_mode.get() in ["zoomin", "zoomout"
                                      ] and self.mouse_start != None:
            self.canvas.delete(self.zoom_trace)
            mouse_start_screen = self.screen_coords(self.mouse_start[0],
                                                    self.mouse_start[1])
            bound_left = min(mouse_start_screen[0], event.x)
            bound_right = max(mouse_start_screen[0], event.x)
            bound_top = min(mouse_start_screen[1], event.y)
            bound_bottom = max(mouse_start_screen[1], event.y)
            self.zoom_trace = self.canvas.create_rectangle(
                bound_left, bound_top, bound_right, bound_bottom)
        if self.coord_text != None:
            self.canvas.delete(self.coord_text)
        self.coord_text = self.canvas.create_text(10,
                                                  10,
                                                  text="({:.6}, {:.6})".format(
                                                      mouse_end[0],
                                                      mouse_end[1]),
                                                  anchor=NW)

    def mouseleave(self, event):
        if self.coord_text != None:
            self.canvas.delete(self.coord_text)
            self.coord_text = None
        self.cancelzoom(None)

    def cancelzoom(self, event):
        self.mouse_start = None
        self.canvas.delete(self.zoom_trace)
Example #15
0
class TrailUI:
    def __init__(self, parent, trail=None):
        self.parent = parent
        self.trail = trail
        self.alpha_reflection = trail.alpha_reflection
        self.states = []
        self.probabilitylabels = {}
        ## scrollbar
        # create a canvas object and a vertical scrollbar for scrolling it
        self.scrollframe = Frame(parent)
        self.hsb = Scrollbar(self.scrollframe, orient=Tkinter.HORIZONTAL)
        self.hsb.pack(fill=Tkinter.X, side=BOTTOM, expand=Tkinter.FALSE)
        self.scrollcanvas = Canvas(self.scrollframe,
                                   bd=0,
                                   highlightthickness=0,
                                   xscrollcommand=self.hsb.set)
        self.scrollcanvas.pack(side=LEFT, fill=BOTH, expand=Tkinter.TRUE)
        self.hsb.config(command=self.scrollcanvas.xview)

        # reset the view
        self.scrollcanvas.xview_moveto(0)
        self.scrollcanvas.yview_moveto(0)

        # put trailframe into scrollframe and assign configs
        self.trailframe = interior = Frame(self.scrollcanvas)
        self.interior_id = self.scrollcanvas.create_window(10,
                                                           0,
                                                           window=interior,
                                                           anchor=Tkinter.NW)
        interior.bind('<Configure>', self._configure_interior)
        self.scrollcanvas.bind('<Configure>', self._configure_canvas)

        self.scrollframe.pack(fill=Tkinter.X, expand=1)
        self.infoframe = Frame(parent)
        self.infoframe.pack(fill=Tkinter.X, expand=1, side=BOTTOM)
        self.canvas = Canvas(self.infoframe, width=1000, height=200)
        self.canvas.pack()
        self.b = Button(self.infoframe,
                        text='Disable Propagation',
                        command=self.__toggle_prop)
        self.b.pack()
        self.b2 = Button(self.infoframe,
                         text='Make active only',
                         command=self.__activeonly)
        self.b2.pack()
        self.parent.title("ClusterF**k")
        self.enable_propagation = True
        self.trail.updateColorList()
        self.maxgridcol = -1
        self.trail.initUI(self)

        # Multi Cell Selection
        self.multiselection_pressed = False
        self.dynamicselection_pressed = False
        self.selectedcells = []
        self.parent.bind("<Control_L>", self.__selection_start)
        self.parent.bind("<KeyRelease-Control_L>", self.__selection_end)
        self.parent.bind("<Shift_L>", self.__dynamic_selection_start)
        self.parent.bind("<KeyRelease-Shift_L>", self.__dynamic_selection_end)

        self.parent.bind("<Escape>", lambda event: self._clear_selection())
        self.parent.bind("<Return>", lambda event: self.open_cell_dialogue())

    # track changes to the canvas and frame width and sync them,
    # also updating the scrollbar
    # taken from https://gist.github.com/EugeneBakin/76c8f9bcec5b390e45df
    def _configure_interior(self, event):
        # update the scrollbars to match the size of the inner frame
        size = (self.trailframe.winfo_reqwidth(),
                self.trailframe.winfo_reqheight())
        self.scrollcanvas.config(scrollregion="0 0 %s %s" % size)
        if self.trailframe.winfo_reqwidth() != self.scrollcanvas.winfo_width():
            # update the canvas's width to fit the inner frame
            self.scrollcanvas.config(width=self.trailframe.winfo_reqwidth())

    def _configure_canvas(self, event):
        if self.trailframe.winfo_reqwidth() != self.scrollcanvas.winfo_width():
            # update the inner frame's width to fill the canvas
            self.scrollcanvas.itemconfigure(
                self.trailframe, width=self.scrollcanvas.winfo_width())

    def __selection_start(self, event):
        print "Selection start/continue"
        self.multiselection_pressed = True

    def __dynamic_selection_start(self, event):
        print "Dynamic selection start"
        self.dynamicselection_pressed = True

    def __selection_end(self, event):
        print "Selection end"
        self.multiselection_pressed = False

    def __dynamic_selection_end(self, event):
        print "Dynamic selection end"
        self.dynamicselection_pressed = False

    def open_cell_dialogue(self):
        if len(self.selectedcells) is 0:
            return

        # oldstate = self.__clickedcells[0]["oldstate"]
        # oldstatestr = ",".join(["{:x}".format(x) for x in oldstate])
        oldstatestr = ""

        dialog = StatePopup(
            self, oldstatestr,
            self.selectedcells[0]["state_probs"])  # TODO add probs

        self.trailframe.wait_window(dialog.top)

        newstate = dialog.value
        # set each cell of the selection to the new state
        if newstate is not None:
            for i, cell in enumerate(self.selectedcells):
                cell["stateUI"].state.set(cell["row"], cell["col"],
                                          set(newstate))

        # self._clear_selection()
        self.redraw_all()
        self.redraw_selection()

    def _clear_selection(self):
        for cell in self.selectedcells:
            cell["stateUI"].undraw_selection(cell)

        self.selectedcells = []

    def __toggle_prop(self):
        self.enable_propagation = not self.enable_propagation
        if self.enable_propagation:
            self.b.config(text="Disable Propagation")
            self.redraw_all()
        else:
            self.b.config(text="Enable Propagation")

    def __activeonly(self):
        self.trail.makeActiveOnly()
        self.redraw_all()

    def get_stateui_at(self, row, col):
        # retrieve state from specific grid position
        for state in self.states:
            if state._row is row and state._col is col:
                return state

        return self.get_stateui_at(row, col - 1)

    def redraw_selection(self):
        for cell in self.selectedcells:
            cell["stateUI"].draw_selection(cell)

    def redraw_all(self):
        if self.enable_propagation:
            self.trail.propagate()
            self.trail.getProbability(verbose=True)
        self.redrawColorList()
        self.redraw_states()
        self.redraw_selection()
        if self.enable_propagation:
            self.redraw_probablities()

    def redraw_states(self):
        for state in self.states:
            state.redraw_state()

        if PRINT_PROPS is True:
            for state in self.states:
                state.redraw_propagation()

    def redraw_probablities(self):
        if self.alpha_reflection is True:
            for i, prob in enumerate(self.trail.probabilities):
                overallprob, sboxprob, mixcolprob = prob.getProbability()
                if i < self.trail.rounds:
                    self.probabilitylabels["S" + str(i)].textvar.set(
                        "2^{0:.2f}".format(math.log(sboxprob, 2)))
                    self.probabilitylabels["M" + str(i + 1)].textvar.set(
                        "2^{0:.2f}".format(math.log(mixcolprob, 2)))
                elif i >= self.trail.rounds + 1:
                    self.probabilitylabels["S" + str(i + 2)].textvar.set(
                        "2^{0:.2f}".format(math.log(sboxprob, 2)))
                    self.probabilitylabels["M" + str(i + 1)].textvar.set(
                        "2^{0:.2f}".format(math.log(mixcolprob, 2)))
                else:  # inner round
                    self.probabilitylabels["I"].textvar.set("2^{0:.2f}".format(
                        math.log(overallprob, 2)))
        else:
            for i, prob in enumerate(self.trail.probabilities):
                overallprob, sboxprob, mixcolprob = prob.getProbability()
                self.probabilitylabels["S" + str(i + 1)].textvar.set(
                    "2^{0:.2f}".format(math.log(sboxprob, 2)))
                self.probabilitylabels["M" + str(i + 1)].textvar.set(
                    "2^{0:.2f}".format(math.log(mixcolprob, 2)))

    def redrawColorList(self):
        self.canvas.delete("colorlist")
        self.trail.updateColorList()
        for i, (state, color) in enumerate(self.trail.colorlist.items()):
            statestr = ",".join(["{:x}".format(x) for x in state])
            x = 15 + int(i / 5) * 250
            y = 15 + (i % 5) * 40
            self.canvas.create_rectangle(x,
                                         y,
                                         x + 25,
                                         y + 25,
                                         fill=color,
                                         tags="colorlist")

            textx = x + 40
            texty = y + 12
            self.canvas.create_text(textx,
                                    texty,
                                    text=statestr,
                                    tags="colorlist",
                                    fill="black",
                                    anchor="w")

    def cleanup(self):
        self.infoframe.destroy()
        self.trailframe.destroy()
Example #16
0
class  TkProgessBar(Frame):
    """
    TkListboxMulticolumn component which can display multi-sortable listbox
    """

    def __init__(self, master, cnf={}, **kw):
        """
        Construct a listbox widget with one or many column and label field for header

        Valid resource names: background, bd, bg, borderwidth, class, colormap,
        fg, font, foreground, height, highlightbackground,
        """
        Frame.__init__(self, master)
        self._value = kw.get('value', 0.0)

        # Create canvas for drawing in
        self._canvas = Canvas(
            self,
            bg=kw.get('bg', 'white'),
            width=kw.get('width', 300),
            height=kw.get('height', 20),
            relief=kw.get('relief', 'sunken'),
            border=kw.get('border', 1)
        )
        self._canvas.pack(fill='both', expand='yes')
        # Drawing a rectangle
        self._rect = self._canvas.create_rectangle(
            0,
            0,
            0,
            self._canvas.winfo_reqheight(),
            fill=kw.get('fillcolor', 'blue'),
            width=0
        )
        # Drawing a text area
        self._text = self._canvas.create_text(
            self._canvas.winfo_reqwidth()/2,
            self._canvas.winfo_reqheight()/2,
            text='',
            fill=kw.get('textcolor', 'gray')
        )
        self.bind('<Configure>', self._update_coords)

    def _update_coords(self, event):
        '''Updates the position of the text and rectangle inside the canvas when the size of
        the widget gets changed.'''
        # looks like we have to call update_idletasks() twice to make sure
        # to get the results we expect
        self._canvas.update_idletasks()
        self._canvas.coords(self._text, self._canvas.winfo_width()/2, self._canvas.winfo_height()/2)
        self._canvas.coords(self._rect, 0, 0, self._canvas.winfo_width()*self._value, self._canvas.winfo_height())
        self._canvas.update_idletasks()

    def get(self, first, last=None):
        """
        return percent and text value
        """
        return self._value, self._canvas.itemcget(self._text, 'text')

    def set(self, value=0.0, text=None):
        '''
        Set different values.
        '''
        #make the value failsafe:
        if value < 0.0:
            value = 0.0
        elif value > 1.0:
            value = 1.0
        self._value = value
        if text == None:
            #if no text is specified use the default percentage string:
            text = str(int(round(100 * value))) + ' %'
        self._canvas.coords(self._rect, 0, 0, self._canvas.winfo_width()*value, self._canvas.winfo_height())
        self._canvas.itemconfigure(self._text, text=text)
        self._canvas.update_idletasks()
Example #17
0
class Cube(MatrixHelpers):

  last_x = 0
  last_y = 0

  def __init__(self, root):
    self.root = root
    self.init_data()
    self.create_canvas()
    self.create_frame()
    self.create_control()
    self.epsilon = lambda d: d * 0.01

  def init_data(self):
    self.cube = self.transpose_matrix([[-100, -100, -100],
                                       [-100,  100, -100],
                                       [-100, -100,  100],
                                       [-100,  100,  100],
                                       [ 100, -100, -100],
                                       [ 100,  100, -100],
                                       [ 100, -100,  100],
                                       [ 100,  100,  100]])
# print(self.cube)
#[(-100, -100, -100, -100, 100, 100, 100, 100),
# (-100, 100, -100, 100, -100, 100, -100, 100),
# (-100, -100, 100, 100, -100, -100, 100, 100)]

  def create_canvas(self):
    self.canvas = Canvas(
        self.root, width=400, height=400)
    self.canvas.pack(fill=BOTH, expand=YES)

  def create_frame(self):
    self.frame = Frame(
        self.root, width=400, height=400)
    self.frame.pack(fill=BOTH, expand=YES)

  def create_control(self):
    self.rotX = Button(self.frame,text="Draw",command=self.rotaX)
    self.rotX.pack()
    self.rotX = Button(self.frame,text="Rotate along X",command=self.rotaX)
    self.rotX.pack()
    self.rotY = Button(self.frame,text="Rotate along Y",command=self.rotaY)
    self.rotY.pack()

  def draw_cube(self):
    cube_points = [[0, 1, 2, 4],
                   [3, 1, 2, 7],
                   [5, 1, 4, 7],
                   [6, 2, 4, 7]]
    '''
            2..........6
          . .         ..
        .   .       .  .
       0..........4    .
       .    3     .    7
       .  .       .   .
       . .        . .
       1..........5

    '''
    w = self.canvas.winfo_width() / 2
    h = self.canvas.winfo_height() / 2
    self.canvas.delete(ALL)
    for i in cube_points:
      for j in i:
        self.canvas.create_line(self.translate_vector(self.cube[0][i[0]], self.cube[1][i[0]], w, h),
                                self.translate_vector(self.cube[0][j], self.cube[1][j], w, h))
        self.canvas.create_text(self.translate_vector(self.cube[0][i[0]],
                                                      self.cube[1][i[0]], w, h),
                                                      text=str("{0:.2f}".format(self.cube[0][i[0]]))
                                                         + " , "
                                                         + str("{0:.2f}".format(self.cube[1][i[0]]))
                                                         + " , "
                                                         + str("{0:.2f}".format(self.cube[2][i[0]])))
        self.canvas.create_text(self.translate_vector(self.cube[0][j],
                                                      self.cube[1][j], w, h),
                                                      text=str("{0:.2f}".format(self.cube[0][j]))
                                                         + " , "
                                                         + str("{0:.2f}".format(self.cube[1][j]))
                                                         + " , "
                                                         + str("{0:.2f}".format(self.cube[2][j])))



  def rotaX(self):
      self.cube = self.rotate_along_x(self.epsilon(5), self.cube)
      self.draw_cube()

  def draw(self):
      self.cube = self.rotate_along_x(0, self.cube)
      self.draw_cube()


  def rotaY(self):
      self.cube = self.rotate_along_y(self.epsilon(5), self.cube)
      self.draw_cube()
Example #18
0
class SimulationCanvas( object ):
    """A canvas where blocks can be dragged around and connected up"""

    size = ( width, height ) = ( 550, 300 )

    def __init__( self, frame ):
        # Create the canvas
        self.canvas = Canvas( frame,
                             width=self.width, height=self.height,
                             relief=RIDGE,
                             background=colours["background"],
                             borderwidth=1 )
        # Add event handlers for dragable items
        self.canvas.tag_bind ( "DRAG", "<ButtonPress-1>", self.mouse_down )
        #self.canvas.tag_bind ("DRAG", "<ButtonRelease-1>", self.mouse_release)
        self.canvas.tag_bind ( "DRAG", "<Enter>", self.enter )
        self.canvas.tag_bind ( "DRAG", "<Leave>", self.leave )
        self.canvas.pack( side=TOP )

        # Some default locations
        self.PREVIEW_WIDTH = 80
        self.PREVIEW_LOCATION = ( self.PREVIEW_X, self.PREVIEW_Y ) = ( 15, 30 )


        # Draw a "preview" area
        self.canvas.create_line( self.PREVIEW_WIDTH, 0, self.PREVIEW_WIDTH, self.height, dash=True )

        # A dict indexed by unique ID of elements in the canvas.
        self.blocks = {}

    def preview_actor( self, codefile ):
        """
        Display a preview of an actor or compisite actor in the canvas,
        it will be dragable into desired position
        """
        logging.debug( "Creating a preview of %(name)s on simulation canvas." % {'name':codefile.name} )

        logging.debug( "Deleting any existing items still tagged 'preview'" )
        self.canvas.delete( "preview" )

        block = CanvasBlock( self.canvas, codefile, *self.PREVIEW_LOCATION )
        self.blocks[block.id] = block



    def mouse_down( self, event ):
        logging.debug( "The mouse was pressed at (%d, %d)" % ( event.x, event.y ) )
        logging.debug( "The mouse went down on a block. Binding mouse release..." )
        selected = self.canvas.gettags( "current" )
        logging.debug( "Currently selected items tags are %s" % selected.__repr__() )
        self.selected_name = [tag for tag in selected if tag.startswith( "name:" ) ][0][5:]
        self.selected_id = [tag for tag in selected if tag.startswith( "id:" ) ][0][3:]
        self.selected_type = [tag for tag in selected if tag.startswith( "type:" ) ][0][5:]
        logging.debug( "Block selected was %s with id:%s" % ( self.selected_name, self.selected_id ) )

        #self.canvas.addtag( 'Selected', 'withtag', self.selected_id )
        logging.debug( "Current blocks are: %s" % self.blocks )
        #self.blocks[block_id].set_colour( colours['selected'] )

        if self.selected_type == "block" or self.selected_type == "text":
            self.blocks[self.selected_id].select(event.x, event.y)
            self.canvas.bind( "<ButtonRelease-1>", self.block_move_mouse_release )
        elif self.selected_type.startswith("input") or self.selected_type.startswith("output"):
            self.blocks[self.selected_id].select_port(self.selected_type)
            self.canvas.bind( "<ButtonRelease-1>", self.port_connect_mouse_release )
        else:
            logging.info("Tried to select %s" % self.selected_type)

    
    def block_move_mouse_release( self, event ):
        logging.debug( "The mouse was released at (%d, %d)" % ( event.x, event.y ) )
        self.canvas.bind( "<ButtonRelease-1>", lambda e: None )
        if event.x >= 0 and event.x <= self.canvas.winfo_width() \
            and event.y >= 0 and event.y <= self.canvas.winfo_height():
                logging.debug( "Valid move inside canvas. Relocating block." )
                self.blocks[self.selected_id].move_to(event.x, event.y)
                if event.x >= self.PREVIEW_WIDTH:
                    if self.blocks[self.selected_id].is_preview():
                        logging.info( "Moved out of preview zone, adding new component to model" )
                        #TODO HERE - add to model compiler or what ever...
                    self.blocks[self.selected_id].unselect()
                else:
                    self.blocks[self.selected_id].preview()
        else:
            logging.info( "Invalid move." )

    def port_connect_mouse_release( self, event ):
        logging.debug( "The mouse was released at (%d, %d)" % ( event.x, event.y ) )
        self.canvas.bind( "<ButtonRelease-1>", lambda e: None )
        if event.x >= 0 and event.x <= self.canvas.winfo_width() \
            and event.y >= 0 and event.y <= self.canvas.winfo_height():
                logging.debug( "Valid location inside canvas." )

                event.widget.itemconfigure( "Selected", fill="#000000" )
                event.widget.itemconfigure( "type:text", fill="#000000" )

                #block = self.canvas.gettags("Selected")
                #logging.debug("Block moved was made up of these components: %s" % block.__repr__())
                self.canvas.dtag( "Selected", "Selected" )

        else:
            logging.info( "Invalid wiring." )

    def enter( self, event ):
        logging.debug( "Enter" )

    def leave( self, event ):
        logging.debug( "Leaving" )
Example #19
0
class Scrolling_Area(Frame, object):

    def __init__(self, master, width=None, anchor=N, height=None, mousewheel_speed = 2, scroll_horizontally=True, xscrollbar=None, scroll_vertically=True, yscrollbar=None, background=None, inner_frame=Frame, **kw):
        Frame.__init__(self, master, class_="Scrolling_Area", background=background)

        self.grid_columnconfigure(0, weight=1)
        self.grid_rowconfigure(0, weight=1)
        
        self._width = width
        self._height = height

        self.canvas = Canvas(self, background=background, highlightthickness=0, width=width, height=height)
        self.canvas.grid(row=0, column=0, sticky=N+E+W+S)

        if scroll_vertically:
            if yscrollbar is not None:
                self.yscrollbar = yscrollbar
            else:
                self.yscrollbar = Scrollbar(self, orient=VERTICAL)
                self.yscrollbar.grid(row=0, column=1,sticky=N+S)
        
            self.canvas.configure(yscrollcommand=self.yscrollbar.set)
            self.yscrollbar['command']=self.canvas.yview
        else:
            self.yscrollbar = None

        if scroll_horizontally:
            if xscrollbar is not None:
                self.xscrollbar = xscrollbar
            else:
                self.xscrollbar = Scrollbar(self, orient=HORIZONTAL)
                self.xscrollbar.grid(row=1, column=0, sticky=E+W)
            
            self.canvas.configure(xscrollcommand=self.xscrollbar.set)
            self.xscrollbar['command']=self.canvas.xview
        else:
            self.xscrollbar = None

        self.rowconfigure(0, weight=1)
        self.columnconfigure(0, weight=1)
        
        self.innerframe = inner_frame(self.canvas, **kw)
        self.innerframe.pack(anchor=anchor)
        
        self.canvas.create_window(0, 0, window=self.innerframe, anchor='nw', tags="inner_frame")

        self.canvas.bind('<Configure>', self._on_canvas_configure)

        Mousewheel_Support(self).add_support_to(self.canvas, xscrollbar=self.xscrollbar, yscrollbar=self.yscrollbar)

    @property
    def width(self):
        return self.canvas.winfo_width()

    @width.setter
    def width(self, width):
        self.canvas.configure(width= width)

    @property
    def height(self):
        return self.canvas.winfo_height()
        
    @height.setter
    def height(self, height):
        self.canvas.configure(height = height)
        
    def set_size(self, width, height):
        self.canvas.configure(width=width, height = height)

    def _on_canvas_configure(self, event):
        width = max(self.innerframe.winfo_reqwidth(), event.width)
        height = max(self.innerframe.winfo_reqheight(), event.height)

        self.canvas.configure(scrollregion="0 0 %s %s" % (width, height))
        self.canvas.itemconfigure("inner_frame", width=width, height=height)

    def update_viewport(self):
        self.update()

        window_width = self.innerframe.winfo_reqwidth()
        window_height = self.innerframe.winfo_reqheight()
        
        if self._width is None:
            canvas_width = window_width
        else:
            canvas_width = min(self._width, window_width)
            
        if self._height is None:
            canvas_height = window_height
        else:
            canvas_height = min(self._height, window_height)

        self.canvas.configure(scrollregion="0 0 %s %s" % (window_width, window_height), width=canvas_width, height=canvas_height)
        self.canvas.itemconfigure("inner_frame", width=window_width, height=window_height)
Example #20
0
class Screen(Observer):
    def __init__(self, parent, bg="white"):
        self.menu_bar = MenuBar(parent)
        self.canvas = Canvas(parent, bg=bg, name="screen")
        self.frameControl = Frame(parent)
        self.frameLabelSignals = LabelFrame(self.frameControl,
                                            text="Signaux",
                                            padx=20,
                                            pady=20)
        self.frameLabelMode = LabelFrame(self.frameControl,
                                         text="Mode",
                                         padx=20,
                                         pady=20)
        self.panelControl = ttk.Notebook(self.frameLabelSignals)
        self.checkbox_signalX = Checkbutton(self.frameLabelMode,
                                            text="Signal X")
        self.checkbox_signalY = Checkbutton(self.frameLabelMode,
                                            text="Signal Y")
        self.checkbox_XY = Checkbutton(self.frameLabelMode, text="XY")

        self.panel_control_page = []  # contient les références de mes curseurs

        for p in parent.get_models():
            self.addPage(p.get_name())

    def addPage(self, name):
        page = ttk.Frame(self.panelControl)
        self.panelControl.add(page, text='signal ' + name)

        visible_checkbox = Checkbutton(page, text="Afficher")
        magnitude = Scale(page,
                          length=250,
                          orient="horizontal",
                          label="Amplitude",
                          sliderlength=20,
                          showvalue=0,
                          from_=0,
                          to=5,
                          tickinterval=1,
                          name="magnitudeScale")
        frequency = Scale(page,
                          length=250,
                          orient="horizontal",
                          label="Frequency",
                          sliderlength=20,
                          showvalue=0,
                          from_=0,
                          to=25,
                          tickinterval=5,
                          name="frequencyScale")
        phase = Scale(page,
                      length=250,
                      orient="horizontal",
                      label="Phase",
                      sliderlength=20,
                      showvalue=0,
                      from_=0,
                      to=20,
                      tickinterval=5,
                      name="phaseScale")
        visible_checkbox.pack(fill="x", pady=6)
        magnitude.pack(expand=1, fill="both", pady=6)
        frequency.pack(expand=1, fill="both", pady=6)
        phase.pack(expand=1, fill="both", pady=6)
        self.panel_control_page.append({
            'visible': visible_checkbox,
            'magnitude': magnitude,
            'frequency': frequency,
            'phase': phase
        })

    def update(self, model):
        if type(model) == list:
            for i, m in enumerate(model):
                signal = m.get_signal()
                #self.plot_signal(signal, m.get_color())
                self.plot_signal(m)
        else:
            signal = model.get_signal()
            self.plot_signal(model)
        self.grid(6, 8)

    def get_panel_control_index(self):
        return self.panelControl.index('current')

    def get_canvas(self):
        return self.canvas

    def get_panel_control_page(self):
        return self.panel_control_page

    def get_magnitude(self, index):
        return self.panel_control_page[index]['magnitude']

    def get_frequency(self, index):
        return self.panel_control_page[index]['frequency']

    def get_phase(self, index):
        return self.panel_control_page[index]['phase']

    def get_visible(self, index):
        return self.panel_control_page[index]['visible']

    def get_checkbox_signalX(self):
        return self.checkbox_signalX

    def get_checkbox_signalY(self):
        return self.checkbox_signalY

    def get_checkbox_XY(self):
        return self.checkbox_XY

    def plot_signal(self, model):
        w, h = self.canvas.winfo_width(), self.canvas.winfo_height()
        width, height = int(w), int(h)

        signal = model.get_signal()
        name = model.get_name()
        color = model.get_color()

        if self.canvas.find_withtag("signal" + name):
            self.canvas.delete("signal" + name)

        if signal and len(signal) > 1 and model.is_visible():
            plot = [(x * width, height / 2.0 * (y + 1)) for (x, y) in signal]
            self.canvas.create_line(plot,
                                    fill=color,
                                    smooth=1,
                                    width=3,
                                    tags="signal" + name)
            self.canvas.scale("signal" + name, width / 2, height / 2, 1.0,
                              0.25)

    def grid(self, row, col):
        w, h = self.canvas.winfo_width(), self.canvas.winfo_height()
        width, height = int(w), int(h)

        if self.canvas.find_withtag("grid"):
            self.canvas.delete("grid")

        # dessin des axes X et Y
        self.canvas.create_line(5,
                                height / 2,
                                width,
                                height / 2,
                                arrow="last",
                                tags=('grid', 'axe-x'))
        self.canvas.create_line(width / 2,
                                height - 5,
                                width / 2,
                                5,
                                arrow="last",
                                tags=('grid', 'axe-y'))

        # dessin des lignes verticales
        for c in range(1, int(row / 2) + 1):
            stepW = width / row
            xd = width / 2 + c * stepW
            xg = width / 2 - c * stepW
            #Creation des lignes verticales
            self.canvas.create_line(xd,
                                    height - 5,
                                    xd,
                                    5,
                                    dash=1,
                                    tags=('grid', 'vertical-line'),
                                    fill='grey')  #cote droit
            self.canvas.create_line(xg,
                                    height - 5,
                                    xg,
                                    5,
                                    dash=1,
                                    tags=('grid', 'vertical-line'),
                                    fill='grey')  #cote gauche
            #Creation des tirets sur x
            self.canvas.create_line(xd,
                                    height / 2 - 4,
                                    xd,
                                    height / 2 + 4,
                                    tags=('grid', 'horizontal-line'),
                                    fill='grey')
            self.canvas.create_line(xg,
                                    height / 2 - 4,
                                    xg,
                                    height / 2 + 4,
                                    tags=('grid', 'horizontal-line'),
                                    fill='grey')

        # dessin des lignes horizontales
        for r in range(1, int(col / 2) + 1):
            stepH = height / col
            yB = height / 2 + r * stepH
            yH = height / 2 - r * stepH
            #Creation des lignes horizontales
            self.canvas.create_line(5,
                                    yB,
                                    width,
                                    yB,
                                    dash=1,
                                    tags=('grid', 'horizontal-line'),
                                    fill='grey')
            self.canvas.create_line(5,
                                    yH,
                                    width,
                                    yH,
                                    dash=1,
                                    tags=('grid', 'horizontal-line'),
                                    fill='grey')
            #Creation des tirets sur y
            self.canvas.create_line(width / 2 - 4,
                                    yB,
                                    width / 2 + 4,
                                    yB,
                                    tags=('grid', 'vertical-line'),
                                    fill='grey')
            self.canvas.create_line(width / 2 - 4,
                                    yH,
                                    width / 2 + 4,
                                    yH,
                                    tags=('grid', 'vertical-line'),
                                    fill='grey')

    def packing(self):
        self.menu_bar.pack(fill='x')
        self.canvas.pack(side=LEFT, expand=1, fill="both", padx=6, pady=6)
        self.panelControl.pack(side=RIGHT, expand=1, fill="both", pady=6)
        self.frameLabelSignals.pack(expand=1, fill="both")
        self.frameLabelMode.pack(expand=1, fill="both")
        self.checkbox_signalX.pack(side=LEFT)
        self.checkbox_signalY.pack(side=LEFT)
        self.checkbox_XY.pack(side=RIGHT)
        self.frameControl.pack(side=RIGHT, expand=1, fill="both", pady=6)
class SimulationCanvas(object):
    """A canvas where blocks can be dragged around and connected up"""

    size = (width, height) = (550, 300)

    def __init__(self, frame):
        # Create the canvas
        self.canvas = Canvas(frame,
                             width=self.width,
                             height=self.height,
                             relief=RIDGE,
                             background=colours["background"],
                             borderwidth=1)
        # Add event handlers for dragable items
        self.canvas.tag_bind("DRAG", "<ButtonPress-1>", self.mouse_down)
        #self.canvas.tag_bind ("DRAG", "<ButtonRelease-1>", self.mouse_release)
        self.canvas.tag_bind("DRAG", "<Enter>", self.enter)
        self.canvas.tag_bind("DRAG", "<Leave>", self.leave)
        self.canvas.pack(side=TOP)

        # Some default locations
        self.PREVIEW_WIDTH = 80
        self.PREVIEW_LOCATION = (self.PREVIEW_X, self.PREVIEW_Y) = (15, 30)

        # Draw a "preview" area
        self.canvas.create_line(self.PREVIEW_WIDTH,
                                0,
                                self.PREVIEW_WIDTH,
                                self.height,
                                dash=True)

        # A dict indexed by unique ID of elements in the canvas.
        self.blocks = {}

    def preview_actor(self, codefile):
        """
        Display a preview of an actor or compisite actor in the canvas,
        it will be dragable into desired position
        """
        logging.debug("Creating a preview of %(name)s on simulation canvas." %
                      {'name': codefile.name})

        logging.debug("Deleting any existing items still tagged 'preview'")
        self.canvas.delete("preview")

        block = CanvasBlock(self.canvas, codefile, *self.PREVIEW_LOCATION)
        self.blocks[block.id] = block

    def mouse_down(self, event):
        logging.debug("The mouse was pressed at (%d, %d)" % (event.x, event.y))
        logging.debug(
            "The mouse went down on a block. Binding mouse release...")
        selected = self.canvas.gettags("current")
        logging.debug("Currently selected items tags are %s" %
                      selected.__repr__())
        self.selected_name = [
            tag for tag in selected if tag.startswith("name:")
        ][0][5:]
        self.selected_id = [tag for tag in selected
                            if tag.startswith("id:")][0][3:]
        self.selected_type = [
            tag for tag in selected if tag.startswith("type:")
        ][0][5:]
        logging.debug("Block selected was %s with id:%s" %
                      (self.selected_name, self.selected_id))

        #self.canvas.addtag( 'Selected', 'withtag', self.selected_id )
        logging.debug("Current blocks are: %s" % self.blocks)
        #self.blocks[block_id].set_colour( colours['selected'] )

        if self.selected_type == "block" or self.selected_type == "text":
            self.blocks[self.selected_id].select(event.x, event.y)
            self.canvas.bind("<ButtonRelease-1>",
                             self.block_move_mouse_release)
        elif self.selected_type.startswith(
                "input") or self.selected_type.startswith("output"):
            self.blocks[self.selected_id].select_port(self.selected_type)
            self.canvas.bind("<ButtonRelease-1>",
                             self.port_connect_mouse_release)
        else:
            logging.info("Tried to select %s" % self.selected_type)

    def block_move_mouse_release(self, event):
        logging.debug("The mouse was released at (%d, %d)" %
                      (event.x, event.y))
        self.canvas.bind("<ButtonRelease-1>", lambda e: None)
        if event.x >= 0 and event.x <= self.canvas.winfo_width() \
            and event.y >= 0 and event.y <= self.canvas.winfo_height():
            logging.debug("Valid move inside canvas. Relocating block.")
            self.blocks[self.selected_id].move_to(event.x, event.y)
            if event.x >= self.PREVIEW_WIDTH:
                if self.blocks[self.selected_id].is_preview():
                    logging.info(
                        "Moved out of preview zone, adding new component to model"
                    )
                    #TODO HERE - add to model compiler or what ever...
                self.blocks[self.selected_id].unselect()
            else:
                self.blocks[self.selected_id].preview()
        else:
            logging.info("Invalid move.")

    def port_connect_mouse_release(self, event):
        logging.debug("The mouse was released at (%d, %d)" %
                      (event.x, event.y))
        self.canvas.bind("<ButtonRelease-1>", lambda e: None)
        if event.x >= 0 and event.x <= self.canvas.winfo_width() \
            and event.y >= 0 and event.y <= self.canvas.winfo_height():
            logging.debug("Valid location inside canvas.")

            event.widget.itemconfigure("Selected", fill="#000000")
            event.widget.itemconfigure("type:text", fill="#000000")

            #block = self.canvas.gettags("Selected")
            #logging.debug("Block moved was made up of these components: %s" % block.__repr__())
            self.canvas.dtag("Selected", "Selected")

        else:
            logging.info("Invalid wiring.")

    def enter(self, event):
        logging.debug("Enter")

    def leave(self, event):
        logging.debug("Leaving")
Example #22
-1
class Viewer(Frame):
    def __init__(self, master,x=600,y=200, onLeft=None, onRight=None, **kwargs):
        self.root=master
        self.xsize=x
        self.ysize=y
        self.onLeft=onLeft
        self.onRight=onRight
        self.ratio=100.
        Frame.__init__(self, master,width=x,height=y, **kwargs)
        self.canvas = Canvas(self, width=x, height=y, background="white")
        self.xsb = Scrollbar(self, orient="horizontal", command=self.canvas.xview)
        self.ysb = Scrollbar(self, orient="vertical", command=self.canvas.yview)
        self.canvas.configure(yscrollcommand=self.ysb.set, xscrollcommand=self.xsb.set)
        self.canvas.configure(scrollregion=(0,0,x,y))

        self.xsb.grid(row=1, column=0, sticky="ew")
        self.ysb.grid(row=0, column=1, sticky="ns")
        self.canvas.grid(row=0, column=0, sticky="nsew")
        self.grid_rowconfigure(0, weight=1)
        self.grid_columnconfigure(0, weight=1)

        self.canvas.bind("<Button-1>", self.clickL)
        self.canvas.bind("<Button-3>", self.clickR)

        # This is what enables using the mouse:
        self.canvas.bind("<ButtonPress-1>", self.move_start)
        self.canvas.bind("<B1-Motion>", self.move_move)
        #linux scroll
        self.canvas.bind("<Button-4>", self.zoomerP)
        self.canvas.bind("<Button-5>", self.zoomerM)

        self.canvas.bind_all("<Prior>", self.zoomerP)
        self.canvas.bind_all("<Next>", self.zoomerM)
        self.canvas.bind_all("E", self.zoomExtens)
        #windows scroll
        self.canvas.bind_all("<MouseWheel>",self.zoomer)

    def reset(self):
        pass

    def set_title(self, title):
        self.root.title( title)

    #move
    def move_start(self, event):
        self.canvas.scan_mark(event.x, event.y)
        return True
    def move_move(self, event):
        self.canvas.scan_dragto(event.x, event.y, gain=1)
        return True

    #windows zoom
    def zoomer(self,event):
        if (event.delta > 0):
            self.ratio *= 1.1
        elif (event.delta < 0):
            self.ratio *= 0.9
        self.redraw()

    def redraw(self):
        self.canvas.delete("all")
        self.canvas.configure(scrollregion = self.canvas.bbox("all"))

    def zoomExtens(self, *args):
        x0,y0,x1,y1 = self.canvas.bbox("all")
        xlen=x1-x0
        ylen=y1-y0
        height=self.canvas.winfo_height()
        width=self.canvas.winfo_width()
        unfit=min(width/float(xlen), height/float(ylen))
        self.ratio*=unfit
        self.redraw()
        #
        """"
        if xlen and ylen:
            self ratio*=
            self.canvas.scale("all", xlen/2., ylen/2., float(self.xsize)/xlen, float(self.ysize)/ylen)
            self.canvas.configure(scrollregion = self.canvas.bbox("all"))
        """
    #linux zoom
    def zoomerP(self,event):
        self.canvas.scale("all", event.x, event.y, 1.1, 1.1)
        self.canvas.configure(scrollregion = self.canvas.bbox("all"))
    def zoomerM(self,event):
        self.canvas.scale("all", event.x, event.y, 0.9, 0.9)
        self.canvas.configure(scrollregion = self.canvas.bbox("all"))
    def pose2p(self, pose):
        x,y=pose[:2]
        return int(x*self.ratio), -int(y*self.ratio)

    def line2p(self, line):
        if type(line[0]) in (float, int):
            line=zip(line[::2],line[1::2])
        return map(self.pose2p, line)
    def p2m(self, x, y):
        return x/self.ratio, -y/self.ratio
    def create_line(self, coords, **kwargs):
        return self.canvas.create_line(self.line2p(coords), **kwargs)
    def create_polygon(self, coords, **kwargs):
        return self.canvas.create_polygon(self.line2p(coords), **kwargs)
    def delete(self, object):
        self.canvas.delete(object)

    def clickL(self, event):
        if self.onLeft:
            x,y=self.p2m(int(self.canvas.canvasx(event.x)), int(self.canvas.canvasy(event.y)))
            self.onLeft(x,y)
        return True

    def clickR(self, event):
        if self.onRight:
            x,y=self.p2m(int(self.canvas.canvasx(event.x)), int(self.canvas.canvasy(event.y)))
            self.onRight(x,y)
        return True