Beispiel #1
0
class WildEditorGUI(ttk.Frame):
    def __init__(self, *args, **kwargs):
        ttk.Frame.__init__(self, *args, **kwargs)
        title = ttk.Label(self,
                          text='Wild Pokemon Editor',
                          style='Title.TLabel')
        self.entry_id = EntryLabel(self, text='ID')
        self.entry_min = EntryLabel(self, text='Minimum Level')
        self.entry_max = EntryLabel(self, text='Maximum Level')
        self.entry_rarity = EntryLabel(self, text='Rarity (1-?)')
        sep = ttk.Separator(self, orient=tk.HORIZONTAL)
        override_lbl = ttk.Label(self,
                                 text='Overrides',
                                 style='Subtitle.TLabel')
        self.string = EntryLabel(self, text='String Code')
        self.code = EntryLabel(self, text='Value')
        self.choices = ListChoice(self)
        self.add = ttk.Button(self, text='Add')

        for entry in (self.entry_id, self.entry_min, self.entry_max,
                      self.entry_rarity, self.code):
            intValidate(entry.entry, 'u16')

        title.pack(padx=10)
        self.entry_id.pack(fill=tk.X)
        self.entry_min.pack(fill=tk.X)
        self.entry_max.pack(fill=tk.X)
        self.entry_rarity.pack(fill=tk.X)
        sep.pack(fill=tk.X, pady=(12, 0), padx=5)
        override_lbl.pack()
        self.string.pack(fill=tk.X)
        self.code.pack(fill=tk.X)
        self.choices.pack(pady=(10, 5), expand=tk.YES, fill=tk.BOTH)
        self.add.pack(pady=(5, 0))
Beispiel #2
0
class ItemEditorGUI(ttk.Frame):
    def __init__(self, parent=None):
        ttk.Frame.__init__(self, parent)

        title = ttk.Label(self,
                          text='Item Database Editor',
                          style='Title.TLabel')
        self.sort = SortBox(self)
        self.items = ListChoice(self)
        sep = ttk.Separator(self)
        self.add_button = ttk.Button(self, text='Add')
        grid = WidgetGrid(self, 2)
        self.id = grid.add_widget(EntryLabel, text='ID', expand=tk.YES)
        self.price = grid.add_widget(EntryLabel,
                                     text='Sell Price',
                                     expand=tk.YES)
        self.name = grid.add_widget(EntryLabel, text='Name', expand=tk.YES)
        description_label = ttk.Label(self, text='Description')
        self.description = VariableText(self, height=10, width=50)

        title.pack()
        self.sort.pack(expand=tk.YES, fill=tk.X, pady=5)
        self.items.pack(expand=tk.YES, fill=tk.BOTH)
        self.add_button.pack()
        sep.pack(fill=tk.X, pady=(10, 0), padx=10)
        grid.pack(fill=tk.X)
        description_label.pack()
        self.description.pack(fill=tk.BOTH)

        intValidate(self.id.entry, 'u16')
        intValidate(self.price.entry, 'u32')
Beispiel #3
0
class CreditsEditorGUI(ttk.Frame):
    def __init__(self, parent=None):
        ttk.Frame.__init__(self, parent)
        title = ttk.Label(self, text='Credits Editor', style='Title.TLabel')
        self.checkVar = tk.IntVar()
        chk = ttk.Checkbutton(self, text='Add Before?', variable=self.checkVar)
        self.list = ListChoice(self)
        butFrame = ttk.Frame(self)
        self.add_text_button = ttk.Button(butFrame, text='Add Text', width=14)
        self.add_image_button = ttk.Button(butFrame,
                                           text='Add Image',
                                           width=14)
        entry_frm = ttk.Frame(self)
        self.x_pos = EntryLabel(entry_frm, text='X Position')
        self.y_buf = EntryLabel(entry_frm, text='Y Buffer')

        self.multi_widget = MultiWidget(self)

        title.pack()
        chk.pack()
        self.list.pack(expand=tk.YES, fill=tk.BOTH)
        butFrame.pack(fill=tk.X, pady=(5, 5))
        self.add_text_button.pack(side=tk.LEFT, padx=10, expand=tk.YES)
        self.add_image_button.pack(side=tk.LEFT, padx=10, expand=tk.YES)

        entry_frm.pack(fill=tk.X)
        self.x_pos.pack(side=tk.LEFT, expand=tk.YES, fill=tk.X, padx=5)
        self.y_buf.pack(side=tk.LEFT, expand=tk.YES, fill=tk.X, padx=5)
        self.multi_widget.pack(fill=tk.BOTH)

        intValidate(self.x_pos.entry, 'u16')
        intValidate(self.y_buf.entry, 'u16')
Beispiel #4
0
class PlaylistEditorGUI(ttk.Frame):
    def __init__(self, parent=None):
        ttk.Frame.__init__(self, parent)
        title = ttk.Label(self, text='Playlist Editor', style='Title.TLabel')
        self.songs = ListChoice(self)
        self.name = EntryLabel(self, text='Song Name', width=50)
        self.button = ttk.Button(self, text='Add')

        title.pack()
        self.songs.pack(expand=tk.YES, fill=tk.BOTH)
        self.name.pack(fill=tk.X, pady=10)
        self.button.pack(fill=tk.X)
Beispiel #5
0
class TravelEditorGUI(ttk.Frame):
    def __init__(self, parent=None):
        ttk.Frame.__init__(self, parent)
        self.entries = []
        title = ttk.Label(self, text='Travel Map Editor', style='Title.TLabel')
        self.maps = ListChoice(self)
        self.add_button = ttk.Button(self, text='Add')
        sep = ttk.Separator(self, orient=tk.HORIZONTAL)
        top = ttk.Frame(self)
        mid = ttk.Frame(self)
        bot = ttk.Frame(self)
        self.entry_x = EntryLabel(top, text='X Position')
        self.entry_y = EntryLabel(top, text='Y Position')
        self.entry_display = EntryLabel(mid, text='Display Name')
        self.entry_ref = EntryLabel(mid, text='Reference Name')
        self.entry_map = EntryLabel(bot, text='Map Name')
        self.entry_spawn = EntryLabel(bot, text='Spawn ID')
        self.entries += self.entry_x, self.entry_y, self.entry_display, self.entry_ref, self.entry_map, self.entry_spawn

        title.pack()
        self.maps.pack(expand=tk.YES, fill=tk.BOTH)
        self.add_button.pack(pady=10)
        sep.pack(fill=tk.X, padx=10)
        top.pack(fill=tk.BOTH)
        mid.pack(fill=tk.BOTH)
        bot.pack(fill=tk.BOTH)
        self.entry_x.pack(expand=tk.YES, fill=tk.X, side=tk.LEFT, padx=(0, 5))
        self.entry_y.pack(expand=tk.YES, fill=tk.X, side=tk.LEFT, padx=(5, 0))
        self.entry_display.pack(expand=tk.YES,
                                fill=tk.X,
                                side=tk.LEFT,
                                padx=(0, 5))
        self.entry_ref.pack(expand=tk.YES,
                            fill=tk.X,
                            side=tk.LEFT,
                            padx=(5, 0))
        self.entry_map.pack(expand=tk.YES,
                            fill=tk.X,
                            side=tk.LEFT,
                            padx=(0, 5))
        self.entry_spawn.pack(expand=tk.YES,
                              fill=tk.X,
                              side=tk.LEFT,
                              padx=(5, 0),
                              pady=(10, 2))

        for entry in self.entry_x, self.entry_y, self.entry_spawn:
            intValidate(entry.entry, 'u16')
class OptionEdit(SimpleLine):
    LABEL = 'Display Line:'

    def __init__(self, parent):
        SimpleLine.__init__(self, parent)
        option_lbl = ttk.Label(self, text='Options', style='Subtitl.TLabel')
        self.options = ListChoice(self)
        self.add_option = ttk.Button(self, text='Add')
        self.option_display = EntryLabel(self, text='Option Line')
        self.jump = EntryLabel(self, text='Jump Point')

        option_lbl.pack()
        self.options.pack(expand=tk.YES, fill=tk.BOTH)
        self.add_option.pack()
        self.option_display.pack(expand=tk.YES, fill=tk.X)
        self.jump.pack(expand=tk.YES, fill=tk.X)
Beispiel #7
0
class FollowPath(ttk.Frame):
    def __init__(self, parent=None):
        ttk.Frame.__init__(self, parent)
        self.nodes = []
        self.check = ttk.Checkbutton(self, text='Reverse loop')
        self.node_list = ListChoice(self)
        lbl = ttk.Label(self, text='Direction')
        self.direction = ttk.Combobox(self,
                                      justify=tk.CENTER,
                                      value=(D_UP, D_LEFT, D_RIGHT, D_DOWN))
        self.steps = EntryLabel(self, text='Number of Steps')
        self.add_button = ttk.Button(self, text='Add')

        self.check.pack()
        self.node_list.pack(expand=tk.YES, fill=tk.BOTH)
        lbl.pack()
        self.direction.pack(fill=tk.X)
        self.steps.pack(fill=tk.X)
        self.add_button.pack(pady=5)

        self.direction.state(['readonly'])
        intValidate(self.steps.entry, 'u8')
Beispiel #8
0
class PeoplemonEditorGUI(ttk.Frame):
    def __init__(self, parent=None):
        ttk.Frame.__init__(self, parent)

        lft_frm = ttk.Frame(self)
        title = ttk.Label(lft_frm,
                          text='Move Database Editor',
                          style='Title.TLabel')
        self.sort = SortBox(lft_frm)
        self.items = ListChoice(lft_frm, width=50, height=12)
        self.add_button = ttk.Button(lft_frm, text='Add')
        sep6 = ttk.Separator(lft_frm)
        desc_lbl = ttk.Label(lft_frm,
                             text='Description',
                             style='Subtitle.TLabel')
        self.description = VariableText(lft_frm, width=40, height=10)
        sep = ttk.Separator(self, orient=tk.VERTICAL)

        middle_frm = ttk.Frame(self)
        grid = WidgetGrid(middle_frm, 4)
        self.id = grid.add_widget(EntryLabel, text='ID', expand=tk.YES)
        self.name = grid.add_widget(EntryLabel, text='Name', expand=tk.YES)
        self.base_xp = grid.add_widget(EntryLabel,
                                       text='Base XP Yield',
                                       expand=tk.YES)
        self.xp_group = grid.add_widget(ComboLabel,
                                        text='XP Group',
                                        expand=tk.YES)
        self.special_id = grid.add_widget(EntryLabel,
                                          text='Special Ability ID',
                                          expand=tk.YES)
        self.type = grid.add_widget(EntryLabel, text='Type', expand=tk.YES)
        self.evolve_level = grid.add_widget(EntryLabel,
                                            text='Evolve Level',
                                            expand=tk.YES)
        self.evolve_id = grid.add_widget(EntryLabel,
                                         text='Evolve ID',
                                         expand=tk.YES)
        sep2 = ttk.Separator(middle_frm)

        base_frm = ttk.Frame(middle_frm)
        self.base_stats = StatsGUI(base_frm, title='Base Stats')
        sep3 = ttk.Separator(base_frm, orient=tk.VERTICAL)
        self.ev_stats = StatsGUI(base_frm, title='EV Awards')

        sep4 = ttk.Separator(middle_frm)
        learn_move_frm = ttk.Frame(middle_frm)
        move_lbl = ttk.Label(learn_move_frm,
                             text='Learned Moves',
                             style='Subtitle.TLabel')
        self.learn_list = ListChoice(learn_move_frm, width=40, height=8)
        self.add_learn_move = ttk.Button(learn_move_frm, text='Add')
        move_frm = ttk.Frame(learn_move_frm)
        self.learn_move_id = EntryLabel(move_frm, text='Move ID')
        self.learn_level = EntryLabel(move_frm, text='Learn Level')

        sep5 = ttk.Separator(middle_frm, orient=tk.VERTICAL)
        available_frm = ttk.Frame(middle_frm)
        available_lbl = ttk.Label(available_frm,
                                  text='Available Moves',
                                  style='Subtitle.TLabel')
        self.available_list = ListChoice(available_frm, width=40, height=8)
        self.add_available_button = ttk.Button(available_frm, text='Add')
        self.available_move_id = EntryLabel(available_frm, text='Move ID')

        lft_frm.pack(side=tk.LEFT, expand=tk.YES, fill=tk.BOTH)
        title.pack()
        self.sort.pack(fill=tk.X, pady=5)
        self.items.pack(expand=tk.YES, fill=tk.BOTH)
        self.add_button.pack()
        sep6.pack(fill=tk.X, padx=10, pady=10)
        desc_lbl.pack()
        self.description.pack(expand=tk.YES, fill=tk.BOTH)

        sep.pack(side=tk.LEFT, fill=tk.Y, padx=10, pady=10)
        middle_frm.pack(side=tk.LEFT, fill=tk.BOTH)
        grid.pack(fill=tk.X)

        sep2.pack(fill=tk.X, pady=(10, 0), padx=10)
        base_frm.pack(fill=tk.X)
        self.base_stats.pack(side=tk.LEFT, expand=tk.YES, fill=tk.X)
        sep3.pack(side=tk.LEFT, fill=tk.Y, padx=10, pady=10)
        self.ev_stats.pack(side=tk.LEFT, expand=tk.YES, fill=tk.X)

        sep4.pack(fill=tk.X, pady=10, padx=10)
        learn_move_frm.pack(side=tk.LEFT, fill=tk.BOTH)
        move_lbl.pack()
        self.learn_list.pack(expand=tk.YES, fill=tk.BOTH)
        self.add_learn_move.pack(pady=(3, 0))
        move_frm.pack(fill=tk.X)
        self.learn_move_id.pack(side=tk.LEFT, expand=tk.YES, fill=tk.X, padx=2)
        self.learn_level.pack(side=tk.LEFT, expand=tk.YES, fill=tk.X, padx=2)

        sep5.pack(side=tk.LEFT, fill=tk.Y, padx=10, pady=10)
        available_frm.pack(side=tk.LEFT, fill=tk.BOTH)
        available_lbl.pack()
        self.available_list.pack(expand=tk.YES, fill=tk.BOTH)
        self.add_available_button.pack(pady=(3, 0))
        self.available_move_id.pack(fill=tk.X)

        for widget in self.type, self.special_id, self.learn_level, self.evolve_level, self.evolve_id:
            intValidate(widget.entry, 'u8')

        for widget in self.id, self.base_xp, self.available_move_id, self.learn_move_id:
            intValidate(widget.entry, 'u16')
Beispiel #9
0
class MoveEditorGUI(ttk.Frame):
    def __init__(self, parent=None):
        ttk.Frame.__init__(self, parent)

        lft_frm = ttk.Frame(self)
        title = ttk.Label(lft_frm, text='Move Database Editor', style='Title.TLabel')
        self.sort = SortBox(lft_frm)
        self.items = ListChoice(lft_frm, width=50)
        self.add_button = ttk.Button(lft_frm, text='Add')

        right_frm = ttk.Frame(self)
        sep2 = ttk.Separator(self, orient=tk.VERTICAL)

        self.name = EntryLabel(right_frm, text='Name')
        id_frm = ttk.Frame(right_frm)
        self.id = EntryLabel(id_frm, text='ID')
        self.classification = ComboLabel(id_frm, text='Move Classification', values=list(CLASSIFICATIONS.keys()))
        grid = WidgetGrid(right_frm, 3)
        self.attack = grid.add_widget(EntryLabel, text='Attack')
        self.accuracy = grid.add_widget(EntryLabel, text='Accuracy')
        self.effect = grid.add_widget(EntryLabel, text='Effect')
        self.priority = grid.add_widget(EntryLabel, text='Priority')
        self.pp = grid.add_widget(EntryLabel, text='PP')
        self.type = grid.add_widget(EntryLabel, text='Type')
        self.chance = grid.add_widget(EntryLabel, text='Chance of Effect')
        self.intensity = grid.add_widget(EntryLabel, text='Effect Intensity')
        self.score = grid.add_widget(EntryLabel, text='Effect Score')
        self.attacker_anim = grid.add_widget(EntryLabel, text='Attacker Anim', expand=tk.YES)
        self.defender_anim = grid.add_widget(EntryLabel, text='Defender Anim', expand=tk.YES)
        chk_frm = ttk.Frame(right_frm)
        self.is_special = ttk.Checkbutton(chk_frm, text='Is Special')
        self.targets_self = ttk.Checkbutton(chk_frm, text='Targets Self')

        description_label = ttk.Label(right_frm, text='Description')
        self.description = VariableText(right_frm, height=10, width=40)

        lft_frm.pack(side=tk.LEFT, expand=tk.YES, fill=tk.BOTH)
        title.pack()
        self.sort.pack(fill=tk.X, pady=5)
        self.items.pack(expand=tk.YES, fill=tk.BOTH)
        self.add_button.pack()

        right_frm.pack(fill=tk.BOTH, side=tk.RIGHT)
        sep2.pack(expand=tk.YES, fill=tk.Y, padx=10, pady=10)
        self.name.pack(fill=tk.X)
        id_frm.pack(fill=tk.X)
        self.id.pack(side=tk.LEFT, fill=tk.X, padx=2)
        self.classification.pack(side=tk.LEFT, expand=tk.YES, fill=tk.X,  padx=(2, 2))
        grid.pack(fill=tk.BOTH)
        chk_frm.pack()
        self.is_special.pack(side=tk.LEFT, fill=tk.X)
        self.targets_self.pack(side=tk.LEFT, fill=tk.X)

        description_label.pack()
        self.description.pack(expand=tk.YES, fill=tk.BOTH)

        self.classification.state(('readonly', ))

        for widget in self.id, self.attack, self.accuracy, self.priority, self.pp:
            intValidate(widget.entry, 'u16')
        for widget in self.type, self.effect, self.intensity, self.score, self.chance:
            intValidate(widget.entry, 'u8')
Beispiel #10
0
class TrainerEditorGUI(ttk.Frame):
    def __init__(self, parent=None):
        ttk.Frame.__init__(self, parent)
        self.aiTypes = {
            AI_RANDOM: 0,
            AI_DUMB: 1,
            AI_SMART: 2,
            AI_SUICIDAL: 3,
            AI_AGGRESSIVE: 4,
            AI_DEFENSIVE: 5,
            AI_AVERAGE: 6,
            AI_ADAPTIVE: 7
        }

        title = ttk.Label(self, text='Trainer Editor', style='Title.TLabel')
        left_frm = ttk.Frame(self)
        grid = WidgetGrid(left_frm, 2)
        self.name = grid.add_widget(EntryLabel, text='Trainer Name')
        self.anim_name = grid.add_widget(EntryLabel, text='Animation Name')
        self.before_convo = grid.add_widget(EntryLabel,
                                            text='Before Battle Convo')
        self.after_convo = grid.add_widget(EntryLabel,
                                           text='After Battle Convo')
        self.lost_text = grid.add_widget(EntryLabel, text='Lost Battle Text')
        self.sight_range = grid.add_widget(EntryLabel, text='Sight Range')
        self.playlist = grid.add_widget(EntryLabel, text='Playlist')
        self.background = grid.add_widget(EntryLabel, text='Background Image')
        grid.add_widget(ttk.Label, text='AI Type', width=12, anchor=tk.CENTER)
        grid.add_widget(ttk.Label,
                        text='Motion Type',
                        width=12,
                        anchor=tk.CENTER)
        self.ai_type = grid.add_widget(
            ttk.Combobox,
            values=(AI_RANDOM, AI_DUMB, AI_SMART, AI_SUICIDAL, AI_AGGRESSIVE,
                    AI_DEFENSIVE, AI_AVERAGE, AI_ADAPTIVE),
            justify=tk.CENTER)
        self.motion_type = grid.add_widget(ttk.Combobox,
                                           values=(B_STILL, B_SPIN, B_FOLLOW,
                                                   B_WANDER),
                                           justify=tk.CENTER)
        sep = ttk.Separator(left_frm)

        second_row = ttk.Frame(left_frm)
        col1 = ttk.Frame(second_row)
        peoplemon_lbl = ttk.Label(col1, text='Peoplemon List')
        self.peoplemon_list = ListChoice(col1)
        self.file_name = EntryLabel(col1, text='Filename')
        self.add_peoplemon = ttk.Button(col1, text='Add')

        col2 = ttk.Frame(second_row)
        item_lbl = ttk.Label(col2, text='Item List')
        self.item_list = ListChoice(col2)
        self.item_id = EntryLabel(col2, text='Item ID')
        self.add_item = ttk.Button(col2, text='Add')

        self.right_frm = ttk.Frame(self)
        sep2 = ttk.Separator(self.right_frm, orient=tk.VERTICAL)
        motion_lbl = ttk.Label(self.right_frm,
                               text='Motion Options',
                               style='Subtitle.TLabel')
        self.behavior_widget = BehaviorWidget(self.right_frm)

        title.pack()
        left_frm.pack(expand=tk.YES, fill=tk.BOTH, side=tk.LEFT)
        grid.pack(expand=tk.YES, fill=tk.X)
        sep.pack(expand=tk.YES, fill=tk.X, padx=10, pady=5)

        second_row.pack(expand=tk.YES, fill=tk.BOTH, padx=20)
        col1.pack(side=tk.LEFT, expand=tk.YES, fill=tk.BOTH, padx=(0, 20))
        col2.pack(side=tk.LEFT, expand=tk.YES, fill=tk.BOTH, padx=(20, 0))

        peoplemon_lbl.pack()
        self.peoplemon_list.pack(expand=tk.YES, fill=tk.BOTH)
        self.file_name.pack(expand=tk.YES, fill=tk.X)
        self.add_peoplemon.pack(pady=(10, 0))

        item_lbl.pack()
        self.item_list.pack(expand=tk.YES, fill=tk.BOTH)
        self.item_id.pack(expand=tk.YES, fill=tk.X)
        self.add_item.pack(pady=(10, 0))

        self.right_frm.pack(fill=tk.BOTH, side=tk.LEFT)
        sep2.pack(fill=tk.Y, padx=(10, 0), side=tk.LEFT)
        motion_lbl.pack(padx=10)
        self.behavior_widget.pack(expand=tk.YES, fill=tk.BOTH)

        self.ai_type.state(['readonly'])
        self.motion_type.state(['readonly'])
        intValidate(self.sight_range.entry, 'u8')
        intValidate(self.item_id.entry, 'u16')
Beispiel #11
0
class Editor(ttk.Frame):
    UP = 1
    DOWN = 2
    LEFT = 3
    RIGHT = 4

    def __init__(self, parent, controller):
        ttk.Frame.__init__(self, parent)
        self.controller = controller
        self.sidebar = ttk.Frame(self)
        self.center_side = ttk.Frame(self)
        self.right_side = ttk.Frame(self)
        self.image_list = ListChoice(self.sidebar)
        self.preview = CanvasPlus(self.sidebar,
                                  width=1,
                                  height=200,
                                  borderwidth=2,
                                  relief=tk.SUNKEN,
                                  background='white')
        self.frame_select = ttk.Scale(self.center_side,
                                      from_=1,
                                      to=1,
                                      command=self.on_frame_scale_changed)
        self.frame_label = ttk.Label(self.center_side,
                                     text='Frame',
                                     style='Title.TLabel')
        self.canvas = CanvasPlus(self.center_side,
                                 width=SIZE[0],
                                 height=SIZE[1],
                                 highlightthickness=0,
                                 background='white')

        self.length_var = tk.IntVar(self)
        self.frame_trace = self.length_var.trace_variable(
            'w', self.change_length)
        self.length = EntryLabel(self.right_side,
                                 text="Frame Length",
                                 entry_variable=self.length_var)
        intValidate(self.length.entry, 'u16')

        self.trans_var = tk.IntVar(self)
        self.transparency = ttk.Scale(self.right_side,
                                      from_=0,
                                      to=255,
                                      command=self.change_transparency)
        self.transparency_alt = ttk.Entry(self.right_side,
                                          width=15,
                                          justify=tk.CENTER,
                                          textvariable=self.trans_var)
        intValidate(self.transparency_alt, 'u8')
        self.apply = ttk.Button(self.right_side,
                                text='Apply',
                                command=self.apply_transparency)

        self.sidebar.pack(side=tk.LEFT, expand=tk.YES, fill=tk.BOTH)
        ttk.Label(self.sidebar, text='Images', style='Title.TLabel').pack()
        self.image_list.pack(side=tk.TOP, expand=tk.YES, fill=tk.BOTH)
        self.preview.pack(side=tk.TOP, expand=tk.YES, fill=tk.BOTH)
        ttk.Button(self.sidebar,
                   text='Insert Image',
                   command=self.insert_image).pack(pady=(3, 5))

        self.center_side.pack(side=tk.LEFT, fill=tk.Y)
        self.frame_label.pack()
        self.frame_select.pack(fill=tk.X)

        self.canvas.pack()
        self.canvas.bind('<Control-Prior>', self.move_forward)
        self.canvas.bind('<Control-Next>', self.move_backward)
        self.canvas.bind('<Prior>',
                         lambda event: self.handle_next(event, False))
        self.canvas.bind('<Next>', lambda event: self.handle_next(event, True))
        self.canvas.bind('<Delete>', self.on_delete_click)
        self.canvas.bind('<Control-Button-1>', self.on_ctrl_click)
        self.canvas.bind('<Control-B1-Motion>', self.on_ctrl_drag)
        self.canvas.bind('<Button-1>', self.on_left_click)
        self.canvas.bind('<Button-3>', self.on_right_click)
        self.canvas.bind('<Up>', lambda event: self.move(Editor.UP))
        self.canvas.bind('<Down>', lambda event: self.move(Editor.DOWN))
        self.canvas.bind('<Left>', lambda event: self.move(Editor.LEFT))
        self.canvas.bind('<Right>', lambda event: self.move(Editor.RIGHT))
        self.canvas.bind('<Control-c >', self.copy)
        self.canvas.bind('<Control-v >', self.paste)

        self.right_side.pack(side=tk.LEFT, fill=tk.Y)
        ttk.Label(self.right_side, text='Frame Settings',
                  style='Title.TLabel').pack(pady=(10, 10))
        self.length.pack()
        ttk.Label(self.right_side,
                  text='Selection Transparency').pack(pady=(10, 0))
        self.transparency.pack(fill=tk.X, padx=(3, 3))
        self.transparency_alt.pack()
        self.apply.pack(pady=(5, 0))
        ttk.Button(self.right_side, text='Preview',
                   command=self.preview_anim).pack(pady=(30, 0))

        self.cur_preview = None  # Stores current preview image to prevent garbage collection
        self.outline = None  # Stores the current outline object
        self.copied = None  # Stroes a DrawnImage object that was copied

        # Create the background photo
        image = Image.open('resources\\layout.png')
        self.background = ImageTk.PhotoImage(image)
        self.canvas.create_image(image.size[0] // 2,
                                 image.size[1] // 2,
                                 image=self.background)

        self.transparency.set(255)
        self.toggle_transparency()

        self.controller.animation.frames.signal_add.connect(
            self.on_frame_add_or_remove)
        self.controller.animation.frames.signal_remove.connect(
            self.on_frame_add_or_remove)
        self.controller.animation.images.signal_add.connect(
            self.on_preview_add)
        self.controller.animation.images.signal_remove.connect(
            self.on_preview_remove)
        self.image_list.signal_select.connect(self.on_preview_selected)
        self.image_list.signal_delete.connect(self.on_preview_deleted)
        self.controller.editor_model.signal_frame_changed.connect(
            self.on_frame_change)
        self.on_frame_change(0)

    def on_left_click(self, event):
        clicked_image = self.selected_image(self.canvas.canvasx(event.x),
                                            self.canvas.canvasy(event.y))
        if type(clicked_image
                ) == DrawnImage and clicked_image != self.get_selected():
            self.select(clicked_image)

    def on_right_click(self, event):
        pos = (self.canvas.canvasx(event.x), self.canvas.canvasy(event.y))
        selected = self.selected_image(*pos) is not None
        self.on_left_click(event)
        menu = SimpleMenu(self, tearoff=0)
        if self.cur_preview is not None:
            menu.add_action('Insert', lambda: self.insert_image(pos))
        if selected:
            menu.add_action('Copy', self.copy)
        if self.copied is not None:
            menu.add_action('Paste', lambda: self.paste_at(pos))
        if selected:
            menu.add_action('Move Back', self.move_backward)
            menu.add_action('Move Forward', self.move_forward)
            menu.add_action('Delete', self.on_delete_click)
        menu.tk_popup(event.x_root, event.y_root)

    def on_ctrl_click(self, event):
        self.canvas.scan_mark(event.x, event.y)

    def on_ctrl_drag(self, event):
        self.canvas.scan_dragto(event.x, event.y, gain=1)

    def on_delete_click(self, event=None):
        if self.get_selected() is None:
            return
        self.controller.animation.frames[
            self.controller.editor_model.current_frame].images.remove(
                self.get_selected())
        self.set_selected(None)
        self.toggle_transparency()

    def move_backward(self, event=None):
        self.move_depth(operator.sub)

    def move_forward(self, event=None):
        self.move_depth(operator.add)

    def move_depth(self, op):
        if self.get_selected():
            frame = self.controller.animation.frames[
                self.controller.editor_model.current_frame]
            ind = frame.images.index(self.get_selected())
            next_ind = max(0, min(op(ind, 1), len(frame.images)))
            print(ind, next_ind)
            frame.images.remove(self.get_selected())
            frame.images.insert(next_ind, self.get_selected())
            self.outline.draw(self.canvas)

    def on_preview_add(self, ind, anim_img):
        logging.info("Loading Image " + anim_img.name)
        img = DrawnImage(anim_img)
        self.image_list.append(img)
        self.image_list.set_selection(-1)

    def on_preview_remove(self, ind, anim_img):
        to_remove = (ind for ind, img in enumerate(self.image_list)
                     if img.anim_img == anim_img)
        for ind in to_remove:
            img = self.image_list.pop(ind)
            if self.preview:
                img.destroy(self.preview)
        self.controller.editor_model.current_frame = self.controller.editor_model.current_frame

    def on_preview_selected(self, ind):
        if ind is None:
            if self.cur_preview is not None:
                self.cur_preview.destroy(self.preview)
            return
        img = self.image_list[ind]
        img.scale_max(self.preview)
        img.center(self.preview)
        if self.cur_preview:
            self.preview.delete(tk.ALL)
        img.draw(self.preview)
        self.cur_preview = img

    def on_preview_deleted(self):
        ind = self.image_list.get_selection()
        if ind is None:
            return
        anim_image = self.controller.animation.images[ind]
        answer = None
        for frame in self.controller.animation.frames:
            new = [
                image for image in frame.images if image.anim_img == anim_image
            ]
            if len(new) and answer is None:
                answer = askokcancel(
                    title='Delete Image',
                    message='Deleting this image will also delete it '
                    'from all frames of the animation')
                if answer is False:
                    return
            for image in new:
                frame.images.remove(image)
        self.controller.animation.images.pop(ind)

    def on_image_add(self, ind, image):
        logging.info("Adding {} level: {}".format(image.name, image.level))
        frame = self.controller.animation.frames[
            self.controller.editor_model.current_frame]
        image.level = ind
        image.draw(self.canvas)
        for i in range(ind + 1, len(frame.images)):
            img = frame.images[i]
            img.level = i
            img.redraw(self.canvas)

        self.select(image)

    def on_image_remove(self, ind, image):
        logging.info("Removing {} level: {}".format(image.name, image.level))
        frame = self.controller.animation.frames[
            self.controller.editor_model.current_frame]
        if image == self.get_selected():
            self.outline.destroy(self.canvas)
        image.destroy(self.canvas)
        for i in range(ind, len(frame.images)):
            img = frame.images[i]
            img.level = ind
            img.redraw(self.canvas)

    def on_frame_add_or_remove(self, ind, frame):
        self.frame_select.config(to=len(self.controller.animation.frames))

    def on_frame_scale_changed(self, event):
        """
        Event handler for when the frame selector scale is moved

        event -> The event object

        pre-conditions: self.cur_frame is valid index into self.frames
        post-conditions: Frame changed if number changed enough

        return -> None
        """
        num = self.frame_select.get()
        rounded = round(num)
        if rounded != num:
            self.frame_select.set(rounded)
            return
        if num - 1 != self.controller.editor_model.current_frame:
            self.controller.editor_model.current_frame = num - 1

    def on_frame_change(self, ind):
        if self.outline:
            self.outline.destroy(self.canvas)
        self.frame_label.config(text='Frame {}'.format(ind + 1))
        self.canvas.delete('drawn_image')
        self.canvas.delete('outline')
        self.frame_select.set(ind + 1)
        if self.controller.editor_model.current_frame != 0:
            last_frm = self.controller.animation.frames[ind - 1]
            last_frm.draw_half_transparent(self.canvas)
        frame = self.controller.animation.frames[ind]
        self.length_var.set(frame.length)
        frame.draw(self.canvas)
        frame.images.signal_add.connect(self.on_image_add)
        frame.images.signal_remove.connect(self.on_image_remove)
        if self.get_selected():
            self.select(self.get_selected())
        self.toggle_transparency()

    def insert_image(self, pos=None):
        """
        Inserts the currently selected image into the current frame

        pre-conditions: self.cur_preview is a CanvasImage object
                        self.cur_frame is a valid index of a Frame in self.frames
        post-conditions: Image is inserted into current frame

        return -> None
        """
        if self.cur_preview is None:
            return
        frame = self.controller.animation.frames[
            self.controller.editor_model.current_frame]
        img = self.cur_preview
        new = img.copy()
        new.canvas = self.canvas
        new.scale_original()
        if pos is not None:
            new.x = int(pos[0] - new.width / 2)
            new.y = int(pos[1] - new.height / 2)
        else:
            new.center(self.canvas)
        frame.images.append(new)

    def selected_image(self, x, y):
        self.canvas.focus_set()
        references = self.canvas.find_overlapping_references(x, y, x, y)
        for ref in reversed(references):
            if type(ref) == Outline:
                return ref
            if type(ref) == DrawnImage:
                center_x, center_y = ref.get_center()
                top_left_x = center_x - (ref.scaled_img.size[0] / 2)
                top_left_y = center_y - (ref.scaled_img.size[1] / 2)
                x_, y_ = int(x - top_left_x), int(y - top_left_y)
                transparency = ref.scaled_img.load()[x_, y_][3]
                if transparency > 0:
                    return ref
        return None

    def select(self, image):
        """
        Selects an image on the canvas for editing. Draws outline around image

        image -> The CanvasImage object to select

        pre-conditions: Image is drawn on the canvas
        post-conditions: The image is selected

        return -> None
        """
        if self.outline:
            self.outline.destroy(self.canvas)
        self.set_selected(image)
        self.controller.animation.frames[
            self.controller.editor_model.current_frame].last_selected = image
        self.outline = Outline(self.canvas, image)
        self.outline.draw(self.canvas)
        self.toggle_transparency()
        self.transparency.set(image.transparency)
        self.trans_var.set(image.transparency)

    def copy(self, event=None):
        self.copied = self.get_selected().copy()

    def paste(self, event):
        self.paste_at()

    def paste_at(self, location=None):
        if self.copied:
            frm = self.controller.animation.frames[
                self.controller.editor_model.current_frame]
            cpy = self.copied.copy()
            if location:
                cpy.x = int(location[0] - cpy.width / 2)
                cpy.y = int(location[1] - cpy.height / 2)
            frm.images.append(cpy)
            self.select(cpy)

    def toggle_transparency(self):
        if self.get_selected():
            self.transparency.state(['!disabled'])
            self.transparency_alt.state(['!disabled'])
            self.apply.state(['!disabled'])
        else:
            self.transparency.state(['disabled'])
            self.transparency_alt.state(['disabled'])
            self.apply.state(['disabled'])

    def handle_next(self, event, prev):
        """
        Event handler for toggling selection to the next image

        event -> The event object
        prev -> True if the previous image should actually be selected, otherwise false

        pre-conditions: self.cur_frame is a valid index of self.frames
        post-conditions: Current selected object is changed
        """
        images = self.controller.animation.frames[
            self.controller.editor_model.current_frame].images
        if self.get_selected():
            ind = images.index(self.get_selected())
            if prev:
                ind -= 1
            else:
                ind += 1
            img = images[ind % len(images)]
            self.select(img)
        elif len(images) != 0:
            self.select(images[0])

    def change_length(self, name, empty, mode):
        try:
            num = int(self.length_var.get())
        except ValueError:
            return
        if num != self.controller.animation.frames[
                self.controller.editor_model.current_frame].length:
            self.controller.animation.frames[
                self.controller.editor_model.current_frame].length = num

    def change_transparency(self, event):
        if self.get_selected():
            transparency = round(self.transparency.get())
            self.get_selected().transparency = transparency
            self.trans_var.set(transparency)
            self.get_selected().destroy(self.canvas)
            self.get_selected().draw(self.canvas)
            self.outline.destroy(self.canvas)
            self.outline.draw(self.canvas)

    def apply_transparency(self):
        if self.outline:
            transparency = self.trans_var.get()
            self.transparency.set(transparency)
            self.change_transparency(None)

    def move(self, direction):
        if not self.get_selected():
            return
        if direction == Editor.UP:
            self.get_selected().y -= 1
            self.outline.move(0, -1)
        elif direction == Editor.DOWN:
            self.get_selected().y += 1
            self.outline.move(0, 1)
        elif direction == Editor.RIGHT:
            self.get_selected().x += 1
            self.outline.move(1, 0)
        elif direction == Editor.LEFT:
            self.get_selected().x -= 1
            self.outline.move(-1, 0)

        self.outline.redraw(self.canvas)

    def preview_anim(self):
        def clear_canvas():
            self.canvas.delete('drawn_image')
            self.canvas.delete('outline')

        clear_canvas()
        for frame in self.controller.animation.frames:
            start = time.time()
            clear_canvas()
            frame.draw(self.canvas)
            self.canvas.update_idletasks()
            self.canvas.update()
            end = time.time()
            wait = frame.length / 1000 - (end - start)
            wait = 0 if wait < 0 else wait
            time.sleep(wait)

        self.controller.editor_model.current_frame = self.controller.editor_model.current_frame

    def set_selected(self, img):
        self.controller.animation.frames[
            self.controller.editor_model.current_frame].last_selected = img

    def get_selected(self):
        return self.controller.animation.frames[
            self.controller.editor_model.current_frame].last_selected