Exemplo n.º 1
0
class ControlPanel(wx.Panel):
    """"""
    def __init__(self, parent, *args, **kwargs):
        """"""
        self.parent = parent
        self.stitch_plan = kwargs.pop('stitch_plan')
        self.target_stitches_per_second = kwargs.pop('stitches_per_second')
        self.target_duration = kwargs.pop('target_duration')
        kwargs['style'] = wx.BORDER_SUNKEN
        wx.Panel.__init__(self, parent, *args, **kwargs)

        self.statusbar = self.GetTopLevelParent().statusbar

        self.drawing_panel = None
        self.num_stitches = 1
        self.current_stitch = 1
        self.speed = 1
        self.direction = 1

        # Widgets
        self.btnMinus = wx.Button(self, -1, label='-')
        self.btnMinus.Bind(wx.EVT_BUTTON, self.animation_slow_down)
        self.btnMinus.SetToolTip(_('Slow down (arrow down)'))
        self.btnPlus = wx.Button(self, -1, label='+')
        self.btnPlus.Bind(wx.EVT_BUTTON, self.animation_speed_up)
        self.btnPlus.SetToolTip(_('Speed up (arrow up)'))
        self.btnBackwardStitch = wx.Button(self, -1, label='<|')
        self.btnBackwardStitch.Bind(wx.EVT_BUTTON,
                                    self.animation_one_stitch_backward)
        self.btnBackwardStitch.SetToolTip(_('Go on step backward (-)'))
        self.btnForwardStitch = wx.Button(self, -1, label='|>')
        self.btnForwardStitch.Bind(wx.EVT_BUTTON,
                                   self.animation_one_stitch_forward)
        self.btnForwardStitch.SetToolTip(_('Go on step forward (+)'))
        self.directionBtn = wx.Button(self, -1, label='<<')
        self.directionBtn.Bind(wx.EVT_BUTTON, self.on_direction_button)
        self.directionBtn.SetToolTip(
            _('Switch direction (arrow left | arrow right)'))
        self.pauseBtn = wx.Button(self, -1, label=_('Pause'))
        self.pauseBtn.Bind(wx.EVT_BUTTON, self.on_pause_start_button)
        self.pauseBtn.SetToolTip(_('Pause (P)'))
        self.restartBtn = wx.Button(self, -1, label=_('Restart'))
        self.restartBtn.Bind(wx.EVT_BUTTON, self.animation_restart)
        self.restartBtn.SetToolTip(_('Restart (R)'))
        self.quitBtn = wx.Button(self, -1, label=_('Quit'))
        self.quitBtn.Bind(wx.EVT_BUTTON, self.animation_quit)
        self.quitBtn.SetToolTip(_('Quit (Q)'))
        self.slider = wx.Slider(self,
                                -1,
                                value=1,
                                minValue=1,
                                maxValue=2,
                                style=wx.SL_HORIZONTAL | wx.SL_LABELS)
        self.slider.Bind(wx.EVT_SLIDER, self.on_slider)
        self.stitchBox = IntCtrl(self,
                                 -1,
                                 value=1,
                                 min=1,
                                 max=2,
                                 limited=True,
                                 allow_none=False)
        self.stitchBox.Bind(wx.EVT_TEXT, self.on_stitch_box)

        # Layout
        self.vbSizer = vbSizer = wx.BoxSizer(wx.VERTICAL)
        self.hbSizer1 = hbSizer1 = wx.BoxSizer(wx.HORIZONTAL)
        self.hbSizer2 = hbSizer2 = wx.BoxSizer(wx.HORIZONTAL)
        hbSizer1.Add(self.slider, 1, wx.EXPAND | wx.ALL, 3)
        hbSizer1.Add(self.stitchBox, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 2)
        vbSizer.Add(hbSizer1, 1, wx.EXPAND | wx.ALL, 3)
        hbSizer2.Add(self.btnMinus, 0, wx.EXPAND | wx.ALL, 2)
        hbSizer2.Add(self.btnPlus, 0, wx.EXPAND | wx.ALL, 2)
        hbSizer2.Add(self.btnBackwardStitch, 0, wx.EXPAND | wx.ALL, 2)
        hbSizer2.Add(self.btnForwardStitch, 0, wx.EXPAND | wx.ALL, 2)
        hbSizer2.Add(self.directionBtn, 0, wx.EXPAND | wx.ALL, 2)
        hbSizer2.Add(self.pauseBtn, 0, wx.EXPAND | wx.ALL, 2)
        hbSizer2.Add(self.restartBtn, 0, wx.EXPAND | wx.ALL, 2)
        hbSizer2.Add(self.quitBtn, 0, wx.EXPAND | wx.ALL, 2)
        vbSizer.Add(hbSizer2, 0, wx.EXPAND | wx.ALL, 3)
        self.SetSizerAndFit(vbSizer)

        # Keyboard Shortcuts
        shortcut_keys = [
            (wx.ACCEL_NORMAL, wx.WXK_RIGHT, self.animation_forward),
            (wx.ACCEL_NORMAL, wx.WXK_NUMPAD_RIGHT, self.animation_forward),
            (wx.ACCEL_NORMAL, wx.WXK_LEFT, self.animation_reverse),
            (wx.ACCEL_NORMAL, wx.WXK_NUMPAD_LEFT, self.animation_reverse),
            (wx.ACCEL_NORMAL, wx.WXK_UP, self.animation_speed_up),
            (wx.ACCEL_NORMAL, wx.WXK_NUMPAD_UP, self.animation_speed_up),
            (wx.ACCEL_NORMAL, wx.WXK_DOWN, self.animation_slow_down),
            (wx.ACCEL_NORMAL, wx.WXK_NUMPAD_DOWN, self.animation_slow_down),
            (wx.ACCEL_NORMAL, ord('+'), self.animation_one_stitch_forward),
            (wx.ACCEL_NORMAL, ord('='), self.animation_one_stitch_forward),
            (wx.ACCEL_SHIFT, ord('='), self.animation_one_stitch_forward),
            (wx.ACCEL_NORMAL, wx.WXK_ADD, self.animation_one_stitch_forward),
            (wx.ACCEL_NORMAL, wx.WXK_NUMPAD_ADD,
             self.animation_one_stitch_forward),
            (wx.ACCEL_NORMAL, wx.WXK_NUMPAD_UP,
             self.animation_one_stitch_forward),
            (wx.ACCEL_NORMAL, ord('-'), self.animation_one_stitch_backward),
            (wx.ACCEL_NORMAL, ord('_'), self.animation_one_stitch_backward),
            (wx.ACCEL_NORMAL, wx.WXK_SUBTRACT,
             self.animation_one_stitch_backward),
            (wx.ACCEL_NORMAL, wx.WXK_NUMPAD_SUBTRACT,
             self.animation_one_stitch_backward),
            (wx.ACCEL_NORMAL, ord('r'), self.animation_restart),
            (wx.ACCEL_NORMAL, ord('p'), self.on_pause_start_button),
            (wx.ACCEL_NORMAL, wx.WXK_SPACE, self.on_pause_start_button),
            (wx.ACCEL_NORMAL, ord('q'), self.animation_quit)
        ]

        accel_entries = []

        for shortcut_key in shortcut_keys:
            eventId = wx.NewId()
            accel_entries.append((shortcut_key[0], shortcut_key[1], eventId))
            self.Bind(wx.EVT_MENU, shortcut_key[2], id=eventId)

        accel_table = wx.AcceleratorTable(accel_entries)
        self.SetAcceleratorTable(accel_table)
        self.SetFocus()

    def set_drawing_panel(self, drawing_panel):
        self.drawing_panel = drawing_panel
        self.drawing_panel.set_speed(self.speed)

    def set_num_stitches(self, num_stitches):
        if num_stitches < 2:
            # otherwise the slider and intctrl get mad
            num_stitches = 2
        self.num_stitches = num_stitches
        self.stitchBox.SetMax(num_stitches)
        self.slider.SetMax(num_stitches)
        self.choose_speed()

    def choose_speed(self):
        if self.target_duration:
            self.set_speed(int(self.num_stitches /
                               float(self.target_duration)))
        else:
            self.set_speed(self.target_stitches_per_second)

    def animation_forward(self, event=None):
        self.directionBtn.SetLabel("<<")
        self.drawing_panel.forward()
        self.direction = 1
        self.update_speed_text()

    def animation_reverse(self, event=None):
        self.directionBtn.SetLabel(">>")
        self.drawing_panel.reverse()
        self.direction = -1
        self.update_speed_text()

    def on_direction_button(self, event):
        if self.direction == 1:
            self.animation_reverse()
        else:
            self.animation_forward()

    def set_speed(self, speed):
        self.speed = int(max(speed, 1))
        self.update_speed_text()

        if self.drawing_panel:
            self.drawing_panel.set_speed(self.speed)

    def update_speed_text(self):
        self.statusbar.SetStatusText(
            _('Speed: %d stitches/sec') % (self.speed * self.direction), 0)
        self.hbSizer2.Layout()

    def on_slider(self, event):
        stitch = event.GetEventObject().GetValue()
        self.stitchBox.SetValue(stitch)

        if self.drawing_panel:
            self.drawing_panel.set_current_stitch(stitch)

    def on_current_stitch(self, stitch, command):
        if self.current_stitch != stitch:
            self.current_stitch = stitch
            self.slider.SetValue(stitch)
            self.stitchBox.SetValue(stitch)
            self.statusbar.SetStatusText(COMMAND_NAMES[command], 1)

    def on_stitch_box(self, event):
        stitch = self.stitchBox.GetValue()
        self.slider.SetValue(stitch)

        if self.drawing_panel:
            self.drawing_panel.set_current_stitch(stitch)

    def animation_slow_down(self, event):
        """"""
        self.set_speed(self.speed / 2.0)

    def animation_speed_up(self, event):
        """"""
        self.set_speed(self.speed * 2.0)

    def animation_pause(self, event=None):
        self.drawing_panel.stop()

    def animation_start(self, event=None):
        self.drawing_panel.go()

    def on_start(self):
        self.pauseBtn.SetLabel(_('Pause'))

    def on_stop(self):
        self.pauseBtn.SetLabel(_('Start'))

    def on_pause_start_button(self, event):
        """"""
        if self.pauseBtn.GetLabel() == _('Pause'):
            self.animation_pause()
        else:
            self.animation_start()

    def animation_one_stitch_forward(self, event):
        self.animation_pause()
        self.drawing_panel.one_stitch_forward()

    def animation_one_stitch_backward(self, event):
        self.animation_pause()
        self.drawing_panel.one_stitch_backward()

    def animation_quit(self, event):
        self.parent.quit()

    def animation_restart(self, event):
        self.drawing_panel.restart()
Exemplo n.º 2
0
class DmgPatternEditorDlg(wx.Dialog):
    def __init__(self, parent):
        wx.Dialog.__init__(self,
                           parent,
                           id=wx.ID_ANY,
                           title=u"Damage Pattern Editor",
                           size=wx.Size(400, 240))

        self.block = False
        self.SetSizeHintsSz(wx.DefaultSize, wx.DefaultSize)

        mainSizer = wx.BoxSizer(wx.VERTICAL)

        self.headerSizer = headerSizer = wx.BoxSizer(wx.HORIZONTAL)

        cDP = service.DamagePattern.getInstance()

        self.choices = cDP.getDamagePatternList()
        # Remove "Uniform" and "Selected Ammo" Damage Patterns
        for dp in self.choices:
            if dp.name in ("Uniform", "Selected Ammo"):
                self.choices.remove(dp)
        # Sort the remaining list and continue on
        self.choices.sort(key=lambda p: p.name)
        self.ccDmgPattern = wx.Choice(self,
                                      choices=map(lambda p: p.name,
                                                  self.choices))
        self.ccDmgPattern.Bind(wx.EVT_CHOICE, self.patternChanged)
        self.ccDmgPattern.SetSelection(0)

        self.namePicker = wx.TextCtrl(self, style=wx.TE_PROCESS_ENTER)
        self.namePicker.Bind(wx.EVT_TEXT_ENTER, self.processRename)
        self.namePicker.Hide()

        self.btnSave = wx.Button(self, wx.ID_SAVE)
        self.btnSave.Hide()
        self.btnSave.Bind(wx.EVT_BUTTON, self.processRename)

        size = None
        headerSizer.Add(self.ccDmgPattern, 1,
                        wx.ALIGN_CENTER_VERTICAL | wx.RIGHT | wx.LEFT, 3)
        buttons = (("new", wx.ART_NEW),
                   ("rename", bitmapLoader.getBitmap("rename", "icons")),
                   ("copy", wx.ART_COPY), ("delete", wx.ART_DELETE))
        for name, art in buttons:
            bitmap = wx.ArtProvider.GetBitmap(
                art, wx.ART_BUTTON) if name != "rename" else art
            btn = wx.BitmapButton(self, wx.ID_ANY, bitmap)
            if size is None:
                size = btn.GetSize()

            btn.SetMinSize(size)
            btn.SetMaxSize(size)

            btn.Layout()
            setattr(self, name, btn)
            btn.Enable(True)
            btn.SetToolTipString("%s pattern" % name.capitalize())
            headerSizer.Add(btn, 0, wx.ALIGN_CENTER_VERTICAL)

        mainSizer.Add(headerSizer, 0, wx.EXPAND | wx.ALL, 2)

        self.sl = wx.StaticLine(self)
        mainSizer.Add(self.sl, 0, wx.EXPAND | wx.TOP | wx.BOTTOM, 5)

        contentSizer = wx.BoxSizer(wx.VERTICAL)
        self.embitmap = bitmapLoader.getBitmap("em_big", "icons")
        self.thermbitmap = bitmapLoader.getBitmap("thermal_big", "icons")
        self.kinbitmap = bitmapLoader.getBitmap("kinetic_big", "icons")
        self.expbitmap = bitmapLoader.getBitmap("explosive_big", "icons")

        dmgeditSizer = wx.FlexGridSizer(2, 4, 0, 2)
        dmgeditSizer.AddGrowableCol(1)
        dmgeditSizer.AddGrowableCol(2)
        dmgeditSizer.SetFlexibleDirection(wx.BOTH)
        dmgeditSizer.SetNonFlexibleGrowMode(wx.FLEX_GROWMODE_SPECIFIED)

        width = -1
        defSize = wx.Size(width, -1)

        self.editEm = IntCtrl(self, wx.ID_ANY, 0, wx.DefaultPosition, defSize,
                              wx.TE_RIGHT)
        dmgeditSizer.Add(self.editEm, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5)

        self.bmpEM = wx.StaticBitmap(self, wx.ID_ANY, self.embitmap)
        dmgeditSizer.Add(self.bmpEM, 0,
                         wx.ALIGN_CENTER_HORIZONTAL | wx.ALIGN_CENTER_VERTICAL,
                         5)

        self.bmpTHERM = wx.StaticBitmap(self, wx.ID_ANY, self.thermbitmap)
        dmgeditSizer.Add(
            self.bmpTHERM, 0, wx.ALIGN_CENTER_HORIZONTAL
            | wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT, 5)

        self.editThermal = IntCtrl(self, wx.ID_ANY, 0, wx.DefaultPosition,
                                   defSize, 0)
        dmgeditSizer.Add(self.editThermal, 0,
                         wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5)

        self.editKinetic = IntCtrl(self, wx.ID_ANY, 0, wx.DefaultPosition,
                                   defSize, wx.TE_RIGHT)
        dmgeditSizer.Add(self.editKinetic, 0,
                         wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5)

        self.bmpKIN = wx.StaticBitmap(self, wx.ID_ANY, self.kinbitmap)
        dmgeditSizer.Add(self.bmpKIN, 0,
                         wx.ALIGN_CENTER_HORIZONTAL | wx.ALIGN_CENTER_VERTICAL,
                         5)

        self.bmpEXP = wx.StaticBitmap(self, wx.ID_ANY, self.expbitmap)
        dmgeditSizer.Add(
            self.bmpEXP, 0, wx.ALIGN_CENTER_HORIZONTAL
            | wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT, 5)

        self.editExplosive = IntCtrl(self, wx.ID_ANY, 0, wx.DefaultPosition,
                                     defSize, 0)
        dmgeditSizer.Add(self.editExplosive, 0,
                         wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5)

        contentSizer.Add(dmgeditSizer, 1, wx.EXPAND | wx.ALL, 5)
        self.slfooter = wx.StaticLine(self)
        contentSizer.Add(self.slfooter, 0, wx.EXPAND | wx.TOP, 5)

        footerSizer = wx.BoxSizer(wx.HORIZONTAL)

        perSizer = wx.BoxSizer(wx.VERTICAL)

        self.stPercentages = wx.StaticText(self, wx.ID_ANY, u"")
        self.stPercentages.Wrap(-1)
        perSizer.Add(self.stPercentages, 0, wx.BOTTOM | wx.LEFT, 5)

        footerSizer.Add(perSizer, 0, 0, 5)

        self.totSizer = wx.BoxSizer(wx.VERTICAL)

        self.stTotal = wx.StaticText(self, wx.ID_ANY, u"")
        self.stTotal.Wrap(-1)
        self.totSizer.Add(self.stTotal, 0,
                          wx.ALIGN_RIGHT | wx.BOTTOM | wx.RIGHT, 5)

        footerSizer.Add(self.totSizer, 1, 0, 5)

        contentSizer.Add(footerSizer, 0, wx.EXPAND, 5)

        mainSizer.Add(contentSizer, 1, wx.EXPAND, 0)

        self.SetSizer(mainSizer)

        self.Layout()
        bsize = self.GetBestSize()
        self.SetSize((-1, bsize.height))

        self.editEm.SetLimited(True)
        self.editThermal.SetLimited(True)
        self.editKinetic.SetLimited(True)
        self.editExplosive.SetLimited(True)

        self.editEm.SetMin(0)
        self.editThermal.SetMin(0)
        self.editKinetic.SetMin(0)
        self.editExplosive.SetMin(0)

        self.editEm.SetMax(99999)
        self.editThermal.SetMax(99999)
        self.editKinetic.SetMax(99999)
        self.editExplosive.SetMax(99999)

        self.new.Bind(wx.EVT_BUTTON, self.newPattern)
        self.rename.Bind(wx.EVT_BUTTON, self.renamePattern)
        self.copy.Bind(wx.EVT_BUTTON, self.copyPattern)
        self.delete.Bind(wx.EVT_BUTTON, self.deletePattern)

        self.editEm.Bind(wx.EVT_TEXT, self.ValuesUpdated)
        self.editThermal.Bind(wx.EVT_TEXT, self.ValuesUpdated)
        self.editKinetic.Bind(wx.EVT_TEXT, self.ValuesUpdated)
        self.editExplosive.Bind(wx.EVT_TEXT, self.ValuesUpdated)

        self.patternChanged()

    def ValuesUpdated(self, event=None):
        if self.block:
            return

        p = self.getActivePattern()
        p.emAmount = self._EM = self.editEm.GetValue()
        p.thermalAmount = self._THERM = self.editThermal.GetValue()
        p.kineticAmount = self._KIN = self.editKinetic.GetValue()
        p.explosiveAmount = self._EXP = self.editExplosive.GetValue()
        total = self._EM + self._THERM + self._KIN + self._EXP
        format = "EM: % 3d%% THERM: % 3d%% KIN: % 3d%% EXP: % 3d%%"
        if total > 0:
            ltext = format % (self._EM * 100 / total,
                              self._THERM * 100 / total,
                              self._KIN * 100 / total, self._EXP * 100 / total)
        else:
            ltext = format % (0, 0, 0, 0)

        ttext = "Total: % 6d" % (total)
        self.stPercentages.SetLabel(ltext)
        self.stTotal.SetLabel(ttext)
        self.totSizer.Layout()

        if event is not None:
            event.Skip()

        service.DamagePattern.getInstance().saveChanges(p)

    def restrict(self):
        self.editEm.Enable(False)
        self.editExplosive.Enable(False)
        self.editKinetic.Enable(False)
        self.editThermal.Enable(False)
        self.rename.Enable(False)
        self.delete.Enable(False)

    def unrestrict(self):
        self.editEm.Enable()
        self.editExplosive.Enable()
        self.editKinetic.Enable()
        self.editThermal.Enable()
        self.rename.Enable()
        self.delete.Enable()

    def getActivePattern(self):
        if len(self.choices) == 0:
            return None

        return self.choices[self.ccDmgPattern.GetSelection()]

    def patternChanged(self, event=None):
        p = self.getActivePattern()
        if p is None:
            return

        if p.name == "Uniform" or p.name == "Selected Ammo":
            self.restrict()
        else:
            self.unrestrict()

        self.block = True
        for field in ("em", "thermal", "kinetic", "explosive"):
            edit = getattr(self, "edit%s" % field.capitalize())
            amount = getattr(p, "%sAmount" % field)
            edit.SetValue(amount)

        self.block = False
        self.ValuesUpdated()

    def newPattern(self, event):
        cDP = service.DamagePattern.getInstance()
        p = cDP.newPattern()
        self.choices.append(p)
        id = self.ccDmgPattern.Append(p.name)
        self.ccDmgPattern.SetSelection(id)
        self.btnSave.SetLabel("Create")
        self.renamePattern()

    def renamePattern(self, event=None):
        if event is not None:
            self.btnSave.SetLabel("Rename")

        self.ccDmgPattern.Hide()
        self.namePicker.Show()
        self.headerSizer.Replace(self.ccDmgPattern, self.namePicker)
        self.namePicker.SetFocus()
        self.namePicker.SetValue(self.getActivePattern().name)

        for btn in (self.new, self.rename, self.delete, self.copy):
            btn.Hide()
            self.headerSizer.Remove(btn)

        self.headerSizer.Add(self.btnSave, 0, wx.ALIGN_CENTER)
        self.btnSave.Show()
        self.headerSizer.Layout()
        if event is not None:
            event.Skip()

    def processRename(self, event):
        newName = self.namePicker.GetLineText(0)
        self.stPercentages.SetLabel("")
        self.stTotal.SetLabel("")
        p = self.getActivePattern()
        for pattern in self.choices:
            if pattern.name == newName and p != pattern:
                self.stPercentages.SetLabel(
                    "Name already used, please pick another")
                return

        cDP = service.DamagePattern.getInstance()
        cDP.renamePattern(p, newName)

        self.headerSizer.Replace(self.namePicker, self.ccDmgPattern)
        self.ccDmgPattern.Show()
        self.namePicker.Hide()
        self.btnSave.Hide()
        self.headerSizer.Remove(self.btnSave)
        for btn in (self.new, self.rename, self.delete, self.copy):
            self.headerSizer.Add(btn, 0, wx.ALIGN_CENTER_VERTICAL)
            btn.Show()

        sel = self.ccDmgPattern.GetSelection()
        self.ccDmgPattern.Delete(sel)
        self.ccDmgPattern.Insert(newName, sel)
        self.ccDmgPattern.SetSelection(sel)
        self.ValuesUpdated()

    def copyPattern(self, event):
        cDP = service.DamagePattern.getInstance()
        p = cDP.copyPattern(self.getActivePattern())
        self.choices.append(p)
        id = self.ccDmgPattern.Append(p.name)
        self.ccDmgPattern.SetSelection(id)
        self.btnSave.SetLabel("Copy")
        self.renamePattern()
        self.patternChanged()

    def deletePattern(self, event):
        cDP = service.DamagePattern.getInstance()
        sel = self.ccDmgPattern.GetSelection()
        cDP.deletePattern(self.getActivePattern())
        self.ccDmgPattern.Delete(sel)
        self.ccDmgPattern.SetSelection(max(0, sel - 1))
        del self.choices[sel]
        self.patternChanged()

    def __del__(self):
        pass