| @@ -2386,6 +2386,20 @@ void LogicEditorWidget::mouseDoubleClickEvent(QMouseEvent *event) | |||||
| event->accept(); | event->accept(); | ||||
| } | } | ||||
| void LogicEditorWidget::keyPressEvent(QKeyEvent *event) | |||||
| { | |||||
| if (event != nullptr | |||||
| && event->key() == Qt::Key_Escape | |||||
| && event->modifiers() == Qt::NoModifier | |||||
| && mouse_wire_mode_ != MouseWireMode::Select) | |||||
| { | |||||
| setMouseWireMode(MouseWireMode::Select); | |||||
| event->accept(); | |||||
| return; | |||||
| } | |||||
| QGraphicsView::keyPressEvent(event); | |||||
| } | |||||
| void LogicEditorWidget::drawForeground( | void LogicEditorWidget::drawForeground( | ||||
| QPainter *painter, const QRectF &rect) | QPainter *painter, const QRectF &rect) | ||||
| { | { | ||||
| @@ -15,6 +15,7 @@ | |||||
| class QGraphicsScene; | class QGraphicsScene; | ||||
| class QCompleter; | class QCompleter; | ||||
| class QEvent; | class QEvent; | ||||
| class QKeyEvent; | |||||
| class QLineEdit; | class QLineEdit; | ||||
| class QMouseEvent; | class QMouseEvent; | ||||
| class QPainter; | class QPainter; | ||||
| @@ -77,6 +78,7 @@ protected: | |||||
| void mouseMoveEvent(QMouseEvent *event) override; | void mouseMoveEvent(QMouseEvent *event) override; | ||||
| void mouseReleaseEvent(QMouseEvent *event) override; | void mouseReleaseEvent(QMouseEvent *event) override; | ||||
| void mouseDoubleClickEvent(QMouseEvent *event) override; | void mouseDoubleClickEvent(QMouseEvent *event) override; | ||||
| void keyPressEvent(QKeyEvent *event) override; | |||||
| void drawForeground(QPainter *painter, const QRectF &rect) override; | void drawForeground(QPainter *painter, const QRectF &rect) override; | ||||
| void resizeEvent(QResizeEvent *event) override; | void resizeEvent(QResizeEvent *event) override; | ||||
| void scrollContentsBy(int dx, int dy) override; | void scrollContentsBy(int dx, int dy) override; | ||||
| @@ -1476,6 +1476,16 @@ void MainWindow::clearActiveSelection() | |||||
| logic_editor_widget_->clearSelection(); | logic_editor_widget_->clearSelection(); | ||||
| selected_logic_node_id_.clear(); | selected_logic_node_id_.clear(); | ||||
| showLogicNodeProperties({}); | showLogicNodeProperties({}); | ||||
| if (logic_editor_widget_->mouseWireMode() | |||||
| != LogicEditorWidget::MouseWireMode::Select) | |||||
| { | |||||
| const QSignalBlocker draw_blocker(ui_->mouseDrawWireAction); | |||||
| const QSignalBlocker erase_blocker(ui_->mouseEraseWireAction); | |||||
| ui_->mouseDrawWireAction->setChecked(false); | |||||
| ui_->mouseEraseWireAction->setChecked(false); | |||||
| logic_editor_widget_->setMouseWireMode( | |||||
| LogicEditorWidget::MouseWireMode::Select); | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| @@ -839,6 +839,36 @@ void testWireGesturePreviewKeepsAtomicCommit() | |||||
| "undo must restore every cell changed by the gesture"); | "undo must restore every cell changed by the gesture"); | ||||
| } | } | ||||
| void testEscapeExitsMouseWireMode() | |||||
| { | |||||
| TestProjectStorage storage; | |||||
| ProjectService project_service(storage); | |||||
| LogicEditorService editor(project_service); | |||||
| LogicEditorWidget widget(editor); | |||||
| const auto press_escape = [&widget] | |||||
| { | |||||
| QKeyEvent event( | |||||
| QEvent::KeyPress, | |||||
| Qt::Key_Escape, | |||||
| Qt::NoModifier); | |||||
| QApplication::sendEvent(&widget, &event); | |||||
| require(event.isAccepted(), "escape must be consumed by the logic editor"); | |||||
| }; | |||||
| widget.setMouseWireMode(LogicEditorWidget::MouseWireMode::Draw); | |||||
| press_escape(); | |||||
| require( | |||||
| widget.mouseWireMode() == LogicEditorWidget::MouseWireMode::Select, | |||||
| "escape must exit mouse draw mode"); | |||||
| widget.setMouseWireMode(LogicEditorWidget::MouseWireMode::Erase); | |||||
| press_escape(); | |||||
| require( | |||||
| widget.mouseWireMode() == LogicEditorWidget::MouseWireMode::Select, | |||||
| "escape must exit mouse erase mode"); | |||||
| } | |||||
| void testCursorAdvanceAndInlineCommandInput() | void testCursorAdvanceAndInlineCommandInput() | ||||
| { | { | ||||
| TestProjectStorage storage; | TestProjectStorage storage; | ||||
| @@ -1232,6 +1262,7 @@ int main(int argc, char *argv[]) | |||||
| testLogicEditorGridSelectionAndDeletion(); | testLogicEditorGridSelectionAndDeletion(); | ||||
| testLadderLayoutAndDragDeletion(); | testLadderLayoutAndDragDeletion(); | ||||
| testWireGesturePreviewKeepsAtomicCommit(); | testWireGesturePreviewKeepsAtomicCommit(); | ||||
| testEscapeExitsMouseWireMode(); | |||||
| testCursorAdvanceAndInlineCommandInput(); | testCursorAdvanceAndInlineCommandInput(); | ||||
| testVerticalWireShortcutAdvancesDownward(); | testVerticalWireShortcutAdvancesDownward(); | ||||
| testSegmentLevelTraceProjection(); | testSegmentLevelTraceProjection(); | ||||