From 7dd91d391ab1cb4e70a288f123338bac347b4b53 Mon Sep 17 00:00:00 2001 From: Eugenio Parodi Date: Fri, 26 Mar 2021 21:48:53 +0000 Subject: [PATCH 1/3] Reworked the list item --- TermTk/TTkCore/ttk.py | 4 +++ TermTk/TTkWidgets/listwidget.py | 56 ++++++++++++++++++++++----------- TermTk/TTkWidgets/menubar.py | 13 ++++---- TermTk/TTkWidgets/widget.py | 7 ++++- TermTk/libbpytop/input.py | 6 ++-- docs/TODO.md | 4 +++ 6 files changed, 63 insertions(+), 27 deletions(-) diff --git a/TermTk/TTkCore/ttk.py b/TermTk/TTkCore/ttk.py index 15a71ff8..ed542dd7 100644 --- a/TermTk/TTkCore/ttk.py +++ b/TermTk/TTkCore/ttk.py @@ -120,6 +120,10 @@ class TTk(TTkWidget): nmevt = mevt.clone(pos=(mevt.x-x, mevt.y-y)) focusWidget.mouseEvent(nmevt) else: + # Sometimes the release event is not retrieved + if focusWidget and focusWidget._pendingMouseRelease: + focusWidget.mouseEvent(nmevt.clone(evt=TTkK.Release)) + focusWidget._pendingMouseRelease = False self.mouseEvent(mevt) elif evt is TTkK.KEY_EVENT: keyHandled = False diff --git a/TermTk/TTkWidgets/listwidget.py b/TermTk/TTkWidgets/listwidget.py index 13ed8562..f5d42335 100644 --- a/TermTk/TTkWidgets/listwidget.py +++ b/TermTk/TTkWidgets/listwidget.py @@ -31,15 +31,17 @@ from TermTk.TTkWidgets.widget import TTkWidget from TermTk.TTkWidgets.label import TTkLabel from TermTk.TTkAbstract.abstractscrollview import TTkAbstractScrollView -class _TTkListWidgetText(TTkLabel): - __slots__ = ('clicked', '_selected', '_highlighted') +class TTkAbstractListItem(TTkLabel): + __slots__ = ('_pressed', '_selected', '_highlighted', 'listItemClicked') def __init__(self, *args, **kwargs): TTkLabel.__init__(self, *args, **kwargs) - self._name = kwargs.get('name' , '_TTkListWidgetText' ) + self._name = kwargs.get('name' , 'TTkAbstractListItem' ) # Define Signals - self.clicked = pyTTkSignal(_TTkListWidgetText) + self.listItemClicked = pyTTkSignal(TTkAbstractListItem) self._selected = False + self._pressed = False self._highlighted = False + self.setFocusPolicy(TTkK.ClickFocus) def _updateColor(self): if self._highlighted: @@ -52,8 +54,18 @@ class _TTkListWidgetText(TTkLabel): else: self.color = TTkCfg.theme.listColor + def keyEvent(self, evt): + return self.parentWidget().keyEvent(evt) + + def mousePressEvent(self, evt): + self._pressed = True + self.highlighted = True + return True + def mouseReleaseEvent(self, evt): - self.clicked.emit(self) + self._pressed = False + self.listItemClicked.emit(self) + self.update() return True @property @@ -101,19 +113,25 @@ class TTkListWidget(TTkAbstractScrollView): x,y = self.getViewOffsets() self.layout().groupMoveTo(-x,-y) - @pyTTkSlot(_TTkListWidgetText) + @pyTTkSlot(TTkAbstractListItem) def _labelSelectedHandler(self, label): if self._selectionMode == TTkK.SingleSelection: - for i in self._selectedItems: - i.selected = False - i.color = TTkCfg.theme.listColor + for item in self._selectedItems: + item.selected = False + item.highlighted = False + self._selectedItems = [label] label.selected = True elif self._selectionMode == TTkK.MultiSelection: + for item in self._selectedItems: + item.highlighted = False label.selected = not label.selected - if label.selected: - self._selectedItems.append(label) - else: - self._selectedItems.remove(label) + if label.selected: + self._selectedItems.append(label) + else: + self._selectedItems.remove(label) + if self._highlighted: + self._highlighted.highlighted = False + label.highlighted = True self._highlighted = label self.setFocus() self.textClicked.emit(label.text) @@ -143,8 +161,8 @@ class TTkListWidget(TTkAbstractScrollView): def addItem(self, item): if isinstance(item, str): - label = _TTkListWidgetText(text=item, width=max(len(item),self.width())) - label.clicked.connect(self._labelSelectedHandler) + label = TTkAbstractListItem(text=item, width=max(len(item),self.width())) + label.listItemClicked.connect(self._labelSelectedHandler) return self.addItem(label) self._items.append(item) _,y,_,h = self.layout().fullWidgetAreaGeometry() @@ -172,21 +190,23 @@ class TTkListWidget(TTkAbstractScrollView): if ( evt.type == TTkK.Character and evt.key==" " ) or \ ( evt.type == TTkK.SpecialKey and evt.key == TTkK.Key_Enter ): if self._highlighted: - self._highlighted.clicked.emit(self._highlighted) + TTkLog.debug(self._highlighted) + self._highlighted.listItemClicked.emit(self._highlighted) return True elif evt.type == TTkK.SpecialKey: if evt.key == TTkK.Key_Tab: return False index = self._items.index(self._highlighted) offx,offy = self.getViewOffsets() + h = self.height() if evt.key == TTkK.Key_Up: index = max(0, index-1) elif evt.key == TTkK.Key_Down: index = min(len(self._items)-1, index+1) elif evt.key == TTkK.Key_PageUp: - index = 0 + index = max(0, index-h) elif evt.key == TTkK.Key_PageDown: - index = len(self._items)-1 + index = min(len(self._items)-1, index+h) elif evt.key == TTkK.Key_Right: self.viewMoveTo(offx+1, offy) elif evt.key == TTkK.Key_Left: diff --git a/TermTk/TTkWidgets/menubar.py b/TermTk/TTkWidgets/menubar.py index 3461ac31..56847fc7 100644 --- a/TermTk/TTkWidgets/menubar.py +++ b/TermTk/TTkWidgets/menubar.py @@ -28,6 +28,7 @@ from TermTk.TTkCore.log import TTkLog from TermTk.TTkCore.signal import pyTTkSignal, pyTTkSlot from TermTk.TTkWidgets.widget import TTkWidget from TermTk.TTkWidgets.button import TTkButton +from TermTk.TTkWidgets.listwidget import TTkListWidget, TTkAbstractListItem from TermTk.TTkLayouts.layout import TTkLayout from TermTk.TTkLayouts.boxlayout import TTkHBoxLayout @@ -45,10 +46,10 @@ class _TTkMenuSpacer(TTkWidget): TTkLog.debug("pippo") self._canvas.drawText(pos=(0,0), text="-"*self.width()) -class _TTkMenuButton(TTkButton): - __slot__ = ('_color', '_borderColor', '_shortcut', '_menu', 'menuButtonClicked') +class _TTkMenuButton(TTkAbstractListItem): + __slots__ = ('_color', '_borderColor', '_shortcut', '_menu', 'menuButtonClicked') def __init__(self, *args, **kwargs): - TTkButton.__init__(self, *args, **kwargs) + TTkAbstractListItem.__init__(self, *args, **kwargs) self._name = kwargs.get('name' , '_TTkMenuButton' ) # signals self.menuButtonClicked = pyTTkSignal(TTkButton) @@ -66,7 +67,7 @@ class _TTkMenuButton(TTkButton): self.resize(txtlen,1) self.setMinimumSize(txtlen+2,1) self.setMaximumSize(txtlen+2,1) - self.clicked.connect(self.menuButtonEvent) + self.listItemClicked.connect(self.menuButtonEvent) def addMenu(self, text): button = _TTkMenuButton(text=text, borderColor=self._borderColor, border=False) @@ -96,8 +97,8 @@ class _TTkMenuButton(TTkButton): self.setFocus() self.update() - @pyTTkSlot() - def menuButtonEvent(self): + @pyTTkSlot(TTkAbstractListItem) + def menuButtonEvent(self, listItem=None): if not self._menu: self.menuButtonClicked.emit(self) return diff --git a/TermTk/TTkWidgets/widget.py b/TermTk/TTkWidgets/widget.py index d52b756c..98f066b6 100644 --- a/TermTk/TTkWidgets/widget.py +++ b/TermTk/TTkWidgets/widget.py @@ -56,7 +56,8 @@ class TTkWidget(TMouseEvents,TKeyEvents): '_padt', '_padb', '_padl', '_padr', '_maxw', '_maxh', '_minw', '_minh', '_focus','_focus_policy', - '_layout', '_canvas', '_visible', '_transparent') + '_layout', '_canvas', '_visible', '_transparent', + '_pendingMouseRelease') def __init__(self, *args, **kwargs): ''' @@ -92,6 +93,8 @@ class TTkWidget(TMouseEvents,TKeyEvents): self._name = kwargs.get('name', 'TTkWidget' ) self._parent = kwargs.get('parent', None ) + self._pendingMouseRelease = False + self._x = kwargs.get('x', 0 ) self._y = kwargs.get('y', 0 ) self._x, self._y = kwargs.get('pos', (self._x, self._y)) @@ -334,6 +337,7 @@ class TTkWidget(TMouseEvents,TKeyEvents): if evt.evt == TTkK.Release: #if self.hasFocus(): # self.clearFocus() + self._pendingMouseRelease = False if self.mouseReleaseEvent(evt): return True @@ -343,6 +347,7 @@ class TTkWidget(TMouseEvents,TKeyEvents): self.raiseWidget() if self.mousePressEvent(evt): # TTkLog.debug(f"Click {self._name}") + self._pendingMouseRelease = True return True if evt.key == TTkK.Wheel: diff --git a/TermTk/libbpytop/input.py b/TermTk/libbpytop/input.py index 20b56eb9..4135128c 100644 --- a/TermTk/libbpytop/input.py +++ b/TermTk/libbpytop/input.py @@ -58,9 +58,11 @@ class MouseEvent: self.evt = evt self.raw = raw - def clone(self, pos=None): + def clone(self, pos=None, evt=None): x,y = pos if pos != None else (self.x, self.y) - return MouseEvent(x, y, self.key, self.evt, self.raw) + if not evt: + evt = self.evt + return MouseEvent(x, y, self.key, evt, self.raw) def key2str(self): return { diff --git a/docs/TODO.md b/docs/TODO.md index 594e4280..7124f314 100644 --- a/docs/TODO.md +++ b/docs/TODO.md @@ -147,6 +147,10 @@ - [x] Events (Signal/Slots) - [ ] Themes - [x] Use Spinbox for R G B +#### Date Picker + - [ ] Basic Implementation + - [ ] Events (Signal/Slots) + - [ ] Themes #### File Picker - [ ] Basic Implementation - [ ] Events (Signal/Slots) From 8ec5fe2fd0226e2a0e514b314d06d5a5d27aba21 Mon Sep 17 00:00:00 2001 From: Eugenio Parodi Date: Fri, 26 Mar 2021 23:20:27 +0000 Subject: [PATCH 2/3] Reworked Menu to support key bindings --- TermTk/TTkCore/canvas.py | 2 +- TermTk/TTkCore/helper.py | 21 ++++++++++++++ TermTk/TTkWidgets/list.py | 2 +- TermTk/TTkWidgets/listwidget.py | 5 ++-- TermTk/TTkWidgets/menubar.py | 49 +++++++++++++++++++++++++-------- TermTk/TTkWidgets/widget.py | 2 ++ 6 files changed, 66 insertions(+), 15 deletions(-) diff --git a/TermTk/TTkCore/canvas.py b/TermTk/TTkCore/canvas.py index c577256b..056c3ea7 100644 --- a/TermTk/TTkCore/canvas.py +++ b/TermTk/TTkCore/canvas.py @@ -468,7 +468,7 @@ class TTkCanvas: self.drawText(pos=(x+1,y), color=color ,text=text) off = 1 else: - self.drawText(pos=(x,y), color=color ,text=text) + self.drawText(pos=(x,y), width=width, color=color ,text=text) if submenu: self._set(y,x+width-1, mb[5], color) off = 0 diff --git a/TermTk/TTkCore/helper.py b/TermTk/TTkCore/helper.py index 75e96291..2242b74e 100644 --- a/TermTk/TTkCore/helper.py +++ b/TermTk/TTkCore/helper.py @@ -42,6 +42,7 @@ class TTkHelper: def __init__(self,x,y,widget): self._widget = widget widget.move(x,y) + _savedFocus = None _overlay = [] class _Shortcut(): @@ -111,6 +112,8 @@ class TTkHelper: def overlay(caller, widget, x, y): wx, wy = TTkHelper.absPos(caller) w,h = widget.size() + if not TTkHelper._savedFocus: + TTkHelper._savedFocus = TTkHelper._focusWidget # Try to keep the overlay widget inside the terminal wx = max(0, wx+x if wx+x+w < TTkGlbl.term_w else TTkGlbl.term_w-w ) wy = max(0, wy+y if wy+y+h < TTkGlbl.term_h else TTkGlbl.term_h-h ) @@ -130,6 +133,24 @@ class TTkHelper: for widget in TTkHelper._overlay: TTkHelper._rootWidget.rootLayout().removeWidget(widget._widget) TTkHelper._overlay = [] + if TTkHelper._focusWidget: + TTkHelper._focusWidget.clearFocus() + if TTkHelper._savedFocus: + bk = TTkHelper._savedFocus + TTkHelper._savedFocus = None + bk.setFocus() + + @staticmethod + def removeSingleOverlay(widget): + if len(TTkHelper._overlay) <= 1: + return TTkHelper.removeOverlay() + rootWidget = TTkHelper.rootOverlay(widget) + rootWidget + for o in TTkHelper._overlay: + if o._widget == rootWidget: + TTkHelper._overlay.remove(o) + TTkHelper._rootWidget.rootLayout().removeWidget(rootWidget) + TTkHelper._overlay[-1]._widget.setFocus() @staticmethod def paintAll(): diff --git a/TermTk/TTkWidgets/list.py b/TermTk/TTkWidgets/list.py index 964869d6..31d79656 100644 --- a/TermTk/TTkWidgets/list.py +++ b/TermTk/TTkWidgets/list.py @@ -35,7 +35,7 @@ class TTkList(TTkAbstractScrollArea): TTkAbstractScrollArea.__init__(self, *args, **kwargs) self._name = kwargs.get('name' , 'TTkList' ) if 'parent' in kwargs: kwargs.pop('parent') - self._listView = TTkListWidget(*args, **kwargs) + self._listView = kwargs.get('listWidget',TTkListWidget(*args, **kwargs)) self.setViewport(self._listView) self.itemClicked = self._listView.itemClicked self.textClicked = self._listView.textClicked diff --git a/TermTk/TTkWidgets/listwidget.py b/TermTk/TTkWidgets/listwidget.py index f5d42335..c6959a5e 100644 --- a/TermTk/TTkWidgets/listwidget.py +++ b/TermTk/TTkWidgets/listwidget.py @@ -60,6 +60,7 @@ class TTkAbstractListItem(TTkLabel): def mousePressEvent(self, evt): self._pressed = True self.highlighted = True + self.update() return True def mouseReleaseEvent(self, evt): @@ -186,11 +187,11 @@ class TTkListWidget(TTkAbstractScrollView): self.viewMoveTo(offx, index) def keyEvent(self, evt): - if not self._highlighted: return + if not self._highlighted: return False if ( evt.type == TTkK.Character and evt.key==" " ) or \ ( evt.type == TTkK.SpecialKey and evt.key == TTkK.Key_Enter ): if self._highlighted: - TTkLog.debug(self._highlighted) + # TTkLog.debug(self._highlighted) self._highlighted.listItemClicked.emit(self._highlighted) return True elif evt.type == TTkK.SpecialKey: diff --git a/TermTk/TTkWidgets/menubar.py b/TermTk/TTkWidgets/menubar.py index 56847fc7..2ae0b4a6 100644 --- a/TermTk/TTkWidgets/menubar.py +++ b/TermTk/TTkWidgets/menubar.py @@ -32,28 +32,47 @@ from TermTk.TTkWidgets.listwidget import TTkListWidget, TTkAbstractListItem from TermTk.TTkLayouts.layout import TTkLayout from TermTk.TTkLayouts.boxlayout import TTkHBoxLayout -class _TTkMenuSpacer(TTkWidget): - __slots__ = ('clicked') + +class _TTkMenuListWidget(TTkListWidget): + __slots__ = ('_previous') + def __init__(self, *args, **kwargs): + TTkListWidget.__init__(self, *args, **kwargs) + self._name = kwargs.get('name' , '_TTkMenuListWidget' ) + self._previous = kwargs.get('previous',None) + + def keyEvent(self, evt): + if evt.type == TTkK.SpecialKey: + if evt.key == TTkK.Key_Left: + TTkHelper.removeSingleOverlay(self) + if self._previous: + self._previous.setFocus() + return True + elif evt.key == TTkK.Key_Right: + if self._highlighted and \ + self._highlighted._menu: + self._highlighted.menuButtonEvent() + return True + return TTkListWidget.keyEvent(self, evt) + + +class _TTkMenuSpacer(TTkAbstractListItem): def __init__(self, *args, **kwargs): - TTkWidget.__init__(self, *args, **kwargs) + TTkAbstractListItem.__init__(self, *args, **kwargs) self._name = kwargs.get('name' , '_TTkMenuSpacer' ) - # Define Signals - self.clicked = pyTTkSignal() self.resize(1,1) - #self.setMinimumHeight(1) def paintEvent(self): - TTkLog.debug("pippo") self._canvas.drawText(pos=(0,0), text="-"*self.width()) class _TTkMenuButton(TTkAbstractListItem): - __slots__ = ('_color', '_borderColor', '_shortcut', '_menu', 'menuButtonClicked') + __slots__ = ('_border', '_borderColor', '_shortcut', '_menu', 'menuButtonClicked') def __init__(self, *args, **kwargs): TTkAbstractListItem.__init__(self, *args, **kwargs) self._name = kwargs.get('name' , '_TTkMenuButton' ) # signals self.menuButtonClicked = pyTTkSignal(TTkButton) self._color = kwargs.get('color', TTkCfg.theme.menuButtonColor ) + self._border = kwargs.get('border', TTkCfg.theme.menuButtonColor ) self._borderColor = kwargs.get('borderColor', TTkCfg.theme.menuButtonBorderColor ) self._shortcut = [] self._menu = [] @@ -94,7 +113,7 @@ class _TTkMenuButton(TTkAbstractListItem): #self._id = self._list.index(label) TTkLog.debug(f"Bind Clicked {button._text}") self.menuButtonClicked.emit(button) - self.setFocus() + TTkHelper.removeOverlay() self.update() @pyTTkSlot(TTkAbstractListItem) @@ -118,20 +137,22 @@ class _TTkMenuButton(TTkAbstractListItem): else: frame = TTkResizableFrame(layout=TTkHBoxLayout(), size=(frameWidth,frameHeight), title=self._text, titleAlign=TTkK.LEFT_ALIGN) pos = (-1, 0) - listw = TTkList(parent=frame) + menuListWidget = _TTkMenuListWidget(previous=self) + listw = TTkList(parent=frame, listWidget = menuListWidget) # listw.textClicked.connect(self._menuCallback) # listw.textClicked.connect(self._menuCallback) TTkLog.debug(f"{self._menu}") for item in self._menu: listw.addItem(item) TTkHelper.overlay(self, frame, pos[0], pos[1]) + listw.viewport().setFocus() self.update() def paintEvent(self): if self._pressed: borderColor = self._borderColor textColor = TTkCfg.theme.menuButtonColorClicked - scColor = TTkCfg.theme.menuButtonShortcutColor + scColor = TTkCfg.theme.menuButtonShortcutColor else: borderColor = self._borderColor textColor = self._color @@ -146,6 +167,12 @@ class _TTkMenuButton(TTkAbstractListItem): borderColor=borderColor, shortcutColor=scColor ) + def focusInEvent(self): + self.highlighted=True + + def focusOutEvent(self): + self.highlighted=False + class TTkMenuLayout(TTkHBoxLayout): __slots__ = ('_itemsLeft', '_itemsCenter', '_itemsRight', '_buttons') def __init__(self, *args, **kwargs): diff --git a/TermTk/TTkWidgets/widget.py b/TermTk/TTkWidgets/widget.py index 98f066b6..d9a68fa3 100644 --- a/TermTk/TTkWidgets/widget.py +++ b/TermTk/TTkWidgets/widget.py @@ -548,6 +548,7 @@ class TTkWidget(TMouseEvents,TKeyEvents): self.layoutUpdated() def setFocus(self): + if self._focus: return TTkLog.debug(self._name) tmp = TTkHelper.getFocus() if tmp == self: return @@ -562,6 +563,7 @@ class TTkWidget(TMouseEvents,TKeyEvents): self.focusInEvent() def clearFocus(self): + if not self._focus: return TTkHelper.clearFocus() self._focus = False self.focusOutEvent() From 9b9642f2914c92a32d63b853c5db53b0376cf2e0 Mon Sep 17 00:00:00 2001 From: Eugenio Parodi Date: Fri, 26 Mar 2021 23:53:29 +0000 Subject: [PATCH 3/3] Fix Focus Issue --- TermTk/TTkCore/helper.py | 3 ++- TermTk/TTkWidgets/menubar.py | 5 +++-- demo/showcase/menubar.py | 4 ++-- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/TermTk/TTkCore/helper.py b/TermTk/TTkCore/helper.py index 2242b74e..ad34c505 100644 --- a/TermTk/TTkCore/helper.py +++ b/TermTk/TTkCore/helper.py @@ -112,7 +112,8 @@ class TTkHelper: def overlay(caller, widget, x, y): wx, wy = TTkHelper.absPos(caller) w,h = widget.size() - if not TTkHelper._savedFocus: + if not TTkHelper._savedFocus and \ + not TTkHelper.isOverlay(TTkHelper._focusWidget): TTkHelper._savedFocus = TTkHelper._focusWidget # Try to keep the overlay widget inside the terminal wx = max(0, wx+x if wx+x+w < TTkGlbl.term_w else TTkGlbl.term_w-w ) diff --git a/TermTk/TTkWidgets/menubar.py b/TermTk/TTkWidgets/menubar.py index 2ae0b4a6..7b4aefb3 100644 --- a/TermTk/TTkWidgets/menubar.py +++ b/TermTk/TTkWidgets/menubar.py @@ -38,7 +38,7 @@ class _TTkMenuListWidget(TTkListWidget): def __init__(self, *args, **kwargs): TTkListWidget.__init__(self, *args, **kwargs) self._name = kwargs.get('name' , '_TTkMenuListWidget' ) - self._previous = kwargs.get('previous',None) + self._previous = kwargs.get('previous',TTkHelper.getFocus()) def keyEvent(self, evt): if evt.type == TTkK.SpecialKey: @@ -49,6 +49,7 @@ class _TTkMenuListWidget(TTkListWidget): return True elif evt.key == TTkK.Key_Right: if self._highlighted and \ + isinstance(self._highlighted,_TTkMenuButton) and \ self._highlighted._menu: self._highlighted.menuButtonEvent() return True @@ -137,7 +138,7 @@ class _TTkMenuButton(TTkAbstractListItem): else: frame = TTkResizableFrame(layout=TTkHBoxLayout(), size=(frameWidth,frameHeight), title=self._text, titleAlign=TTkK.LEFT_ALIGN) pos = (-1, 0) - menuListWidget = _TTkMenuListWidget(previous=self) + menuListWidget = _TTkMenuListWidget() listw = TTkList(parent=frame, listWidget = menuListWidget) # listw.textClicked.connect(self._menuCallback) # listw.textClicked.connect(self._menuCallback) diff --git a/demo/showcase/menubar.py b/demo/showcase/menubar.py index d927fb3c..b7f84baf 100755 --- a/demo/showcase/menubar.py +++ b/demo/showcase/menubar.py @@ -49,7 +49,7 @@ def demoMenuBar(root=None): frameTop.menubarTop().addMenu("X", alignment=ttk.TTkK.RIGHT_ALIGN) window = ttk.TTkWindow(title="Test MenuBar", parent=frameTop,pos=(1,1), size=(60,10), border=True) - fileMenu2 = window.menubarTop().addMenu("&File") + fileMenu2 = window.menubarTop().addMenu("&Fi&le") fileMenu2.addMenu("New File") fileMenu2.addMenu("Old File") fileMenu2.addSpacer() @@ -69,7 +69,7 @@ def demoMenuBar(root=None): fileMenu2.addSpacer() fileMenu2.addMenu("Exit") - editMenu2 = window.menubarTop().addMenu("&Edit") + editMenu2 = window.menubarTop().addMenu("&E&dit") editMenu2.addMenu("Undo") editMenu2.addMenu("Redo") editMenu2.addMenu("Cut")