Example #1
0
 def SetLabels(self, labels, labels_file):
     self.labels_file = labels_file
     self.lm = LabelsManager(labels)
     self.UpdateDrawing(2)
Example #2
0
class LabelsWindow(VolumeWindow):
    '''
    ラベル付きボリューム表示ウィンドウ
    '''

    binder = VolumeWindow.binder

    def __init__(self, *args, **kwargs):
        self.lm = None  # LabelsManager
        self._is_enter = False
        self._drag_handle = NO_HANDLE
        self._handle_type = None
        self.border_pen = wx.Pen(BORDER_COLOUR)
        self.handle_brush = wx.Brush(HANDLE_COLOUR)

        self._init_arrow()
        self._load_btn_img()

        VolumeWindow.__init__(self, *args, **kwargs)

        self.AddLayer()

    def GetLabels(self):
        return self.labels

    def SetLabels(self, labels, labels_file):
        self.labels_file = labels_file
        self.lm = LabelsManager(labels)
        self.UpdateDrawing(2)

    def ReloadLabels(self):
        f = self.labels_file
        if f and os.path.exists(f):
            labels = Labels(f)
            self.SetLabels(labels, f)

    def SetHandleColour(self, colour):
        self.handle_brush = wx.Brush(colour)
        self.UpdateDrawing(2)

    #--------------------------------------------------------------------------
    # 描画

    def Draw(self, dc, nlayer):
        if nlayer == 1:
            VolumeWindow.Draw(self, dc, nlayer)
            return

        if nlayer != 2:
            return

        self.DrawBase(dc, nlayer-1)

        old_dc = dc
        dc = wx.GCDC(dc)

        if self.labels and self._vol:

            self.DrawLabels(dc, old_dc)

            if not self.playing:
                selected = self.selected
                if selected:
                    self.DrawHandle(dc, selected)
                    self.DrawFocus(dc, selected)
                else:
                    self.DrawInsert(dc)

    def DrawLabels(self, dc, old_dc):
        left_s = self.left_s

        lf = old_dc.GetLogicalFunction()
        old_dc.SetLogicalFunction(wx.XOR)

        for label in self._get_labels_in_view():
            x1 = self.s_to_i(label.start_s - left_s)
            x2 = self.s_to_i(label.end_s - left_s)
            w = x2 - x1

            if w != 0:
                # ---- ラベルの領域を描画

                dc.SetPen(wx.TRANSPARENT_PEN)

                if label.is_cut():
                    colour = [32, 32, 32, 192]
                else:
                    colour = list(label.colour)
                    colour.append(32)  # alpha

                label_brush = wx.Brush(wx.Colour(*colour))
                dc.SetBrush(label_brush)
                dc.DrawRectangle(x1, 0, w, self.h)

                # ---- 境界
                old_dc.SetPen(self.border_pen)
                old_dc.DrawLine(x1, 0, x1, self.h)
                old_dc.DrawLine(x2, 0, x2, self.h)

        old_dc.SetLogicalFunction(lf)

    # フォーカス矩形を描画
    def DrawFocus(self, dc, selected):
        left_s = self.left_s

        x1 = self.s_to_i(selected.start_s - left_s)
        x2 = self.s_to_i(selected.end_s - left_s)

        lf = dc.GetLogicalFunction()
        dc.SetLogicalFunction(wx.XOR)

        # ---- 境界
        dc.SetPen(wx.WHITE_PEN)
        dc.DrawLine(x1, 0, x1, self.h)
        dc.DrawLine(x2, 0, x2, self.h)

        dc.SetLogicalFunction(lf)

    def DrawHandle(self, dc, selected):
        dc.SetPen(wx.Pen('black', 1, wx.DOT))
        dc.SetBrush(wx.TRANSPARENT_BRUSH)

        self.DrawIfcutAndCut(dc, selected)
        self.DrawSelectedPlay(dc, selected)
        self.DrawMerge(dc, selected)
        self.DrawChangeLblAndRemove(dc, selected)
        self.DrawChangeRange(dc, selected)

    def DrawIfcutAndCut(self, dc, selected):
        '''
        選択範囲の中にある現在位置の上方にある「もしカット再生」ボタン
        と「分割」ボタンを描画
        '''

        if (self._drag_handle == NO_HANDLE and self.can_cut() and
                selected.contains(self.pos_s)):
            pass
        else:
            return

        x = self.pos_i - self.left_i
        d = self.dist

        self.SetHandleTypeBrush(dc, HT_IFCUT, self.selected)
        dc.DrawEllipticArc(x-d, -d, d*2, d*2, 180, 270)
        self.SetHandleTypeBrush(dc, HT_CUT, self.selected)
        dc.DrawEllipticArc(x-d, -d, d*2, d*2, 270, 360)
        dc.DrawBitmap(self.bmp_ifcut, x-36, 20)
        dc.DrawBitmap(self.bmp_cut, x+20, 20)

    def DrawSelectedPlay(self, dc, selected):
        '''
        選択範囲の右上にある選択再生ボタンを描画
        '''

        x = self.s_to_i(selected.end_s) - self.left_i
        d = self.dist

        self.SetHandleTypeBrush(dc, HT_SELECTED, self.selected)
        dc.DrawEllipticArc(x-d, -d, d*2, d*2, 180, 270)
        dc.DrawBitmap(self.bmp_ifcut, x-36, 20)

    def DrawChangeLblAndRemove(self, dc, selected):
        '''
        選択範囲の中にある現在位置の下方にあるラベル変更ボタンと削除ボタンを描画
        '''

        w = self.w
        h = self.h
        st_i = self.s_to_i(selected.start_s)
        ed_i = self.s_to_i(selected.end_s)
        x = (st_i + ed_i) / 2 - self.left_i
        y = h
        d = self.dist / 2

        self.SetHandleTypeBrush(dc, HT_CHGLBL, self.selected)
        dc.DrawEllipticArc(x-d, y-d, d*2, d*2, 90, 180)
        dc.DrawLine(x, h-d, x, h)
        self.SetHandleTypeBrush(dc, HT_REMOVE, self.selected)
        dc.DrawEllipticArc(x-d, y-d, d*2, d*2, 0, 90)

        if selected.is_pause():
            dc.DrawBitmap(self.bmp_dellbl, x-20, y-20)
        else:
            dc.DrawBitmap(self.bmp_sndlbl, x-20, y-20)
        dc.DrawBitmap(self.bmp_remove, x+4, y-20)

    def DrawMerge(self, dc, selected):
        '''
        選択範囲の両端の下にある選択再生ボタンを描画
        '''

        w = self.w
        h = self.h

        lx = self.s_to_i(selected.start_s) - self.left_i
        rx = self.s_to_i(selected.end_s) - self.left_i
        y = h
        d = self.dist / 2

        if self.can_merge_left():
            self.SetHandleTypeBrush(dc, HT_LMERGE, self.selected)
            dc.DrawEllipticArc(lx-d, y-d, d*2, d*2, 0, 90)
            dc.DrawBitmap(self.bmp_lmerge, lx+4, y-20)

        if self.can_merge_right():
            self.SetHandleTypeBrush(dc, HT_RMERGE, self.selected)
            dc.DrawEllipticArc(rx-d, y-d, d*2, d*2, 90, 180)
            dc.DrawBitmap(self.bmp_rmerge, rx-20, y-20)

    def DrawChangeRange(self, dc, selected):
        '''
        選択範囲の両端の中程にある範囲変更ハンドルを描画
        '''

        lx = self.s_to_i(selected.start_s) - self.left_i
        rx = self.s_to_i(selected.end_s) - self.left_i
        ly = self._st_arrow_y
        ry = self._ed_arrow_y
        d = self.dist

        self.SetHandleTypeBrush(dc, HT_LEFT, self.selected)
        dc.DrawEllipticArc(lx-d, ly-d, d*2, d*2, -90, 90)
        self.SetHandleTypeBrush(dc, HT_RIGHT, self.selected)
        dc.DrawEllipticArc(rx-d, ry-d, d*2, d*2, 90, 270)

        dc.SetPen(wx.GREY_PEN)
        dc.SetBrush(self.arrow_brush)
        dc.DrawPolygon(self._right_arrow, lx, ly)
        dc.DrawPolygon(self._left_arrow, rx, ry)

    def DrawInsert(self, dc):
        '''
        選択範囲の外にある現在位置の上方にある「挿入」ボタンを描画
        '''

        if (self._is_enter and self._drag_handle == NO_HANDLE and
                self.can_insert_label()):
            pass
        else:
            return

        dc.SetPen(wx.Pen('black', 1, wx.DOT))
        dc.SetBrush(wx.TRANSPARENT_BRUSH)

        x = self.pos_i - self.left_i
        d = self.dist

        self.SetHandleTypeBrush(dc, HT_INSERT, self.selected)
        dc.DrawEllipticArc(x-d, -d, d*2, d*2, 270, 360)
        dc.DrawBitmap(self.bmp_insert, x+20, 20)

    def SetHandleTypeBrush(self, dc, typ, selected):
        if self._handle_type == typ:
            if selected:
                colour = list(selected.colour)
                colour.append(32)  # alpha

                handle_brush = wx.Brush(wx.Colour(*colour))
                dc.SetBrush(handle_brush)
            else:
                dc.SetBrush(self.handle_brush)
        else:
            dc.SetBrush(wx.TRANSPARENT_BRUSH)

    #--------------------------------------------------------------------------
    # コマンド

    def can_save(self):
        if self._vol and self.can_undo():
            return True
        else:
            return False

    def save(self):
        if not self.can_save():
            return

        self.labels.write(self.labels_file)
        self.lm.clear_history()
        self.post_label_change_evt()

    def find(self, sil_lv, sil_dur, before_dur, after_dur):
        if self._vol is None:
            return

        self.lm.save()
        self.lm.labels = find_sound(self._vol, sil_lv, sil_dur, before_dur, after_dur)
        self.UpdateDrawing(2)
        self.post_label_change_evt()

    def shift(self, val_s):
        if self.labels is None:
            return

        self.lm.save()
        self.labels.shift(val_s)
        self.UpdateDrawing(2)
        self.post_label_change_evt()

    # ---- ラベル編集
    def can_insert_label(self):
        if not self.playing and self.labels:
            return self.labels.can_insert_label(self.pos_s, INSERT_DUR_S, self._vol.dur_s)
        else:
            return False

    def insert_label(self, evt=None):
        if not self.can_insert_label():
            return

        self.lm.save()
        max_s = self.i_to_s(len(self._vol) - 1)
        self.labels.insert_label(self.pos_s, INSERT_DUR_S, max_s)
        self.UpdateDrawing(2)
        self.post_label_change_evt()

    def can_remove_label(self):
        if not self.playing and self.selected:
            return True
        else:
            return False

    def remove_label(self):
        if not self.can_remove_label():
            return

        self.lm.save()
        self.labels.remove_selected()
        self.UpdateDrawing(2)
        self.post_label_change_evt()

    def can_cut(self):
        if not self.playing and self.labels:
            return self.labels.can_cut(self.pos_s)
        else:
            return False

    def cut(self, evt=None):
        if not self.can_cut():
            return

        self.lm.save()
        self.labels.cut(self.pos_s)
        self.UpdateDrawing(2)
        self.post_label_change_evt()

    def can_change_lbl(self):
        if not self.playing and self.selected:
            return self.labels.can_change_lbl()
        else:
            return False

    def change_lbl(self, evt=None):
        if not self.can_change_lbl():
            return

        self.lm.save()
        self.labels.change_lbl()
        self.UpdateDrawing(2)
        self.post_label_change_evt()

    def can_merge_left(self):
        if not self.playing and self.labels:
            return self.labels.can_merge_left()
        else:
            return False

    def merge_left(self):
        if not self.can_merge_left():
            return

        self.lm.save()
        self.labels.merge_left()
        self.UpdateDrawing(2)
        self.post_label_change_evt()

    def can_merge_right(self):
        if not self.playing and self.labels:
            return self.labels.can_merge_right()
        else:
            return False

    def merge_right(self):
        if not self.can_merge_right():
            return

        self.lm.save()
        self.labels.merge_right()
        self.UpdateDrawing(2)
        self.post_label_change_evt()

    # ---- 履歴

    def can_undo(self):
        if not self.playing and self.lm:
            return self.lm.can_undo()
        else:
            return False

    def undo(self):
        if not self.can_undo():
            return

        self.lm.undo()
        self.UpdateDrawing(2)
        self.post_label_change_evt()

    def can_redo(self):
        if not self.playing and self.lm:
            return self.lm.can_redo()
        else:
            return False

    def redo(self):
        if not self.can_redo():
            return

        self.lm.redo()
        self.UpdateDrawing(2)
        self.post_label_change_evt()

    #--------------------------------------------------------------------------
    # イベントハンドラ

    @binder(wx.EVT_SIZE)
    def OnSize(self, evt):
        h = self.ClientSize[1]

        d = h / 7
        self.dist = d

        self._st_arrow_y = d * 2
        self._ed_arrow_y = d * 4

        VolumeWindow.OnSize(self, evt)

    @binder(wx.EVT_ENTER_WINDOW)
    def OnEnterWindow(self, evt):
        self.SetFocus()

        self._is_enter = True

        self.UpdateDrawing(2)

    @binder(wx.EVT_LEAVE_WINDOW)
    def OnLeaveWindow(self, evt):
        self._is_enter = False
        self._handle_type = HT_NONE

        self.post_status_msg_evt()

        if self.selected and self._drag_handle == NO_HANDLE:
            self.labels.selected = None

        self.UpdateDrawing(2)

    @binder(wx.EVT_LEFT_DOWN)
    def OnLeftDown(self, evt):
        self.SetFocus()

        if self._vol is None:
            VolumeWindow.OnLeftDown(self, evt)
            return

        if not self.playing:
            typ = self._set_handle_type(evt.X, evt.Y)

            if typ == HT_LEFT or typ == HT_RIGHT:  # 範囲変更
                if typ == HT_LEFT:
                    self._drag_handle = LEFT_HANDLE
                else:
                    self._drag_handle = RIGHT_HANDLE

                self.lm.save()
                self.CaptureMouse()
                self.UpdateDrawing(2)
                return
            elif typ == HT_IFCUT:  # もしカット再生
                self.post_ifcut_play_evt(self.pos_s)
                return
            elif typ == HT_CUT:  # カット
                self.cut()
                return
            elif typ == HT_SELECTED:  # 選択ラベル再生
                self.post_ifcut_play_evt(self.selected.end_s)
                return
            elif typ == HT_INSERT:  # 範囲挿入
                self.insert_label()
                return
            elif typ == HT_LMERGE:  # 左結合
                self.merge_left()
                return
            elif typ == HT_RMERGE:  # 右結合
                self.merge_right()
                return
            elif typ == HT_CHGLBL:  # ラベル種類変更
                self.change_lbl()
                return
            elif typ == HT_REMOVE:  # ラベル削除
                self.remove_label()
                return

        # ドラッグでスクロールする
        VolumeWindow.OnLeftDown(self, evt)

    @binder(wx.EVT_LEFT_UP)
    def OnLeftUp(self, evt):
        if self._drag_handle != NO_HANDLE and self.HasCapture():
            self.ReleaseMouse()
            self.post_label_change_evt()
        else:
            evt.Skip()
            VolumeWindow.OnLeftUp(self, evt)

        self._drag_handle = NO_HANDLE

    @binder(wx.EVT_RIGHT_DOWN)
    def OnRightDown(self, evt):
        if self._drag_handle != NO_HANDLE and self.HasCapture():
            self.ReleaseMouse()
            self.lm.restore()
            self._drag_handle = NO_HANDLE
            self.UpdateDrawing(2)

    @binder(wx.EVT_MOTION)
    def OnMotion(self, evt):
        if self._vol is None or self.playing:
            VolumeWindow.OnMotion(self, evt)
            return

        update = False

        if self._drag_handle == NO_HANDLE:
            VolumeWindow.OnMotion(self, evt)

            # ---- マウスがラベル範囲内なら選択する
            if not self.playing and self.labels:
                prev_selected = self.selected
                pos_s = self.left_s + self.i_to_s(evt.X)
                selected = self.labels.select(pos_s)

                if prev_selected != selected:
                    update = True

            # ---- ハンドルの操作ができるならハンドルの背景色を変えるために更新
            old = self._handle_type
            new = self._set_handle_type(evt.X, evt.Y)

            if old != new:
                update = True

                self.post_status_msg_evt()
        else:  # ラベル範囲を変更中
            pos_s = self.i_to_s(self.left_i + evt.X)

            if self._drag_handle == LEFT_HANDLE:
                if self.selected:
                    update = self.labels.change_range(start_s=pos_s, is_fit=evt.ShiftDown(), is_near=evt.ControlDown())
                    self.pos_s = self.selected.start_s
            elif self._drag_handle == RIGHT_HANDLE:
                if self.selected:
                    update = self.labels.change_range(end_s=pos_s, is_fit=evt.ShiftDown(), is_near=evt.ControlDown())
                    self.pos_s = self.selected.end_s

        if update:
            self.UpdateDrawing(2)

    @binder(wx.EVT_KEY_DOWN)
    def OnKeyDown(self, evt):
        if self._vol is None:
            return

        key = evt.GetKeyCode()

        if key == wx.WXK_DELETE:
            self.remove_label()
        elif key == wx.WXK_SPACE and evt.ShiftDown():
            if not self.playing:
                self.post_pause_play_evt()
                return

        if self._drag_handle == LEFT_HANDLE:
            if key == wx.WXK_LEFT:
                pos_s = self.selected.start_s - 0.002
                self.labels.change_range(start_s=pos_s)
                self._handle_type = None
                self.pos_s = self.selected.start_s
                self.UpdateDrawing(1)
                return
            elif key == wx.WXK_RIGHT:
                pos_s = self.selected.start_s + 0.002
                self.labels.change_range(start_s=pos_s)
                self._handle_type = None
                self.pos_s = self.selected.start_s
                self.UpdateDrawing(1)
                return
        elif self._drag_handle == RIGHT_HANDLE:
            if key == wx.WXK_LEFT:
                pos_s = self.selected.end_s - 0.002
                self.labels.change_range(end_s=pos_s)
                self._handle_type = None
                self.pos_s = self.selected.end_s
                self.UpdateDrawing(1)
                return
            elif key == wx.WXK_RIGHT:
                pos_s = self.selected.end_s + 0.002
                self.labels.change_range(end_s=pos_s)
                self._handle_type = None
                self.pos_s = self.selected.end_s
                self.UpdateDrawing(1)
                return

        if self.playing == False:
            if 32 <= key <= 127:
                ch = chr(key).lower()

                if ch == 'b' and self.can_cut():
                    self.post_ifcut_play_evt(self.pos_s)
                elif ch == 'c':
                    self.cut()
                elif ch == 'i':
                    self.insert_label()
                elif ch == 'l':
                    self.merge_left()
                elif ch == 'r':
                    self.merge_right()
                elif ch == 's':
                    if evt.ControlDown():
                        self.save()
                    else:
                        if self.selected:
                            end_s = self.selected.end_s
                            self.post_ifcut_play_evt(end_s)
                elif (ch == 'z') and evt.ControlDown():
                    self.undo()
                elif (ch == 'y') and evt.ControlDown():
                    self.redo()

        VolumeWindow.OnKeyDown(self, evt)

    #--------------------------------------------------------------------------
    # プロパティ

    @property
    def labels(self):
        if self.lm:
            return self.lm()
        else:
            return None

    @property
    def selected(self):
        if self.lm:
            return self.lm().selected
        else:
            return None

    #--------------------------------------------------------------------------
    # 内部メソッド

    def _init_arrow(self):
        self._st_arrow_y = 0
        self._ed_arrow_y = 0

        self._right_arrow = None
        self._left_arrow = None

        al = ARROW_SIZE
        self._right_arrow = ((0, al), (al * math.sqrt(3), 0),  (0, -al))
        self._left_arrow  = ((0, al), (-al * math.sqrt(3), 0), (0, -al))

        self.arrow_brush = wx.Brush('#20B2AA')

    def _load_btn_img(self):
        self.bmp_cut = self._load_img('cut.png')
        self.bmp_ifcut = self._load_img('playifcut.png')
        self.bmp_lmerge = self._load_img('mergeleft.png')
        self.bmp_rmerge = self._load_img('mergeright.png')
        self.bmp_insert = self._load_img('insert.png')
        self.bmp_dellbl = self._load_img('dellbl.png')
        self.bmp_sndlbl = self._load_img('sndlbl.png')
        self.bmp_remove = self._load_img('remove.png')

    def _load_img(self, fname):
        img = wx.Image('icon/%s' % fname, wx.BITMAP_TYPE_PNG)
        img = img.Scale(16, 16, wx.IMAGE_QUALITY_HIGH)
        return wx.BitmapFromImage(img)

    def _get_labels_in_view(self):
        '''
        画面内にあるラベルを取得する
        '''

        labels = self.labels
        if labels is None:
            return

        left_s = self.i_to_s(self.left_i)
        right_s = self.i_to_s(self.left_i + self.w - 1)

        labels_in_view = []

        for label in labels:
            if label.end_s < left_s:
                continue

            if label.start_s > right_s:
                return labels_in_view

            # 開始位置が視界の範囲内か?
            if left_s <= label.start_s and label.start_s <= right_s:
                labels_in_view.append(label)
                continue

            # 終了位置が視界の範囲内か?
            if left_s <= label.end_s and label.end_s <= right_s:
                labels_in_view.append(label)
                continue

            # ラベルが視界の全部を含んでいるか?
            if label.contains(left_s) and label.contains(right_s):
                labels_in_view.append(label)
                continue

        return labels_in_view

    def _set_handle_type(self, x, y):
        '''
        引数の座標に対応するハンドルの種類を返す
        '''

        self._handle_type = HT_NONE

        if self.labels is None:
            return self._handle_type

        selected = self.selected
        pos_x = self.pos_i - self.left_i

        # ---- 非選択範囲のハンドル

        if selected is None:
            if (self._hit_test(pos_x, 0, x, y, self.dist) and
                    x > pos_x):  # 範囲挿入ハンドル
                self._handle_type = HT_INSERT
                return self._handle_type

            return self._handle_type

        # ---- 選択範囲のハンドル

        if self._hit_test(pos_x, 0, x, y, self.dist):
            if x <= pos_x:  # もしカット再生ハンドル
                if self.can_cut():
                    self._handle_type = HT_IFCUT
                    return self._handle_type
            else:  # カットハンドル
                if self.can_cut():
                    self._handle_type = HT_CUT

                    # ラベル右上の「もしカット再生」とかぶったらそっち優先

        pos_s = self.left_s + self.i_to_s(x)
        if pos_s < selected.start_s or selected.end_s < pos_s:
            return self._handle_type

        st_x = self.s_to_i(selected.start_s) - self.left_i

        # ---- 左移動ハンドル
        if self._hit_test(st_x, self._st_arrow_y, x, y, self.dist):
            if x >= st_x:
                self._handle_type = HT_LEFT
                return self._handle_type

        # ---- 左結合ハンドル
        if self._hit_test(st_x, self.h, x, y, self.dist / 2):
            if x >= st_x and self.can_merge_left():
                self._handle_type = HT_LMERGE
                return self._handle_type

        ed_x = self.s_to_i(selected.end_s) - self.left_i

        # ---- 右移動ハンドル
        if self._hit_test(ed_x, self._ed_arrow_y, x, y, self.dist):
            if x <= ed_x:
                self._handle_type = HT_RIGHT
                return self._handle_type

        # ---- 右結合ハンドル
        if self._hit_test(ed_x, self.h, x, y, self.dist / 2):
            if x <= ed_x and self.can_merge_right():
                self._handle_type = HT_RMERGE
                return self._handle_type

        # ---- 選択再生ハンドル
        if self._hit_test(ed_x, 0, x, y, self.dist):
            if x <= ed_x:
                self._handle_type = HT_SELECTED
                return self._handle_type

        mid_x = (st_x + ed_x) / 2

        if self._hit_test(mid_x, self.h, x, y, self.dist/2):
            if x <= mid_x:  # ラベル種類変更
                self._handle_type = HT_CHGLBL
            else:  # ラベル削除
                self._handle_type = HT_REMOVE

            return self._handle_type

        return self._handle_type

    def _hit_test(self, ax, ay, bx, by, dist):
        '''
        (ax, ay)と(bx, by)の間の距離がdist以下か?
        '''

        ad = math.sqrt((bx - ax) * (bx - ax) + (by - ay) * (by - ay))
        if ad < dist:
            result = True
        else:
            result = False
        return result

    # ---- イベント発行

    def post_label_change_evt(self):
        evt = LabelsWindowEvent(myEVT_LABEL_CHANGE, self.GetId())
        self.GetEventHandler().ProcessEvent(evt)

    def post_ifcut_play_evt(self, pos_s):
        evt = LabelsWindowEvent(myEVT_REQ_IFCUT_PLAY, self.GetId(), pos_s)
        self.GetEventHandler().ProcessEvent(evt)

    def post_pause_play_evt(self):
        evt = LabelsWindowEvent(myEVT_REQ_PAUSE_PLAY, self.GetId())
        self.GetEventHandler().ProcessEvent(evt)

    def post_status_msg_evt(self):
        typ = self._handle_type
        if typ == HT_NONE:
            msg = u''
        elif typ == HT_LEFT:
            msg = u'範囲を変更'
        elif typ == HT_RIGHT:
            msg = u'範囲を変更'
        elif typ == HT_IFCUT:
            msg = u'もしカット再生'
        elif typ == HT_CUT:
            msg = u'範囲の分割'
        elif typ == HT_SELECTED:
            msg = u'選択再生'
        elif typ == HT_INSERT:
            msg = u'新しい範囲の挿入'
        elif typ == HT_LMERGE:
            msg = u'左の範囲と結合'
        elif typ == HT_RMERGE:
            msg = u'右の範囲と結合'
        elif typ == HT_REMOVE:
            msg = u'範囲の削除'
        elif typ == HT_CHGLBL:
            selected = self.selected
            if selected:
                if selected.is_pause():
                    msg = u'音声の削除'
                else:
                    msg = u'音声削除の取り消し'

        evt = LabelsWindowEvent(myEVT_STATUS_MSG, self.GetId())
        evt.SetMsg(msg)
        self.GetEventHandler().ProcessEvent(evt)