Loading files
This file is pinned to the selected release. Download the original to open it in your design tool.
/*
* LibrePCB - Professional EDA for everyone!
* Copyright (C) 2013 LibrePCB Developers, see AUTHORS.md for contributors.
* https://librepcb.org/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*******************************************************************************
* Includes
******************************************************************************/
#include "symboleditorfsm.h"
#include "symboleditorstate_addnames.h"
#include "symboleditorstate_addpins.h"
#include "symboleditorstate_addvalues.h"
#include "symboleditorstate_drawarc.h"
#include "symboleditorstate_drawcircle.h"
#include "symboleditorstate_drawline.h"
#include "symboleditorstate_drawpolygon.h"
#include "symboleditorstate_drawrect.h"
#include "symboleditorstate_drawtext.h"
#include "symboleditorstate_measure.h"
#include "symboleditorstate_select.h"
#include <QtCore>
/*******************************************************************************
* Namespace
******************************************************************************/
namespace librepcb {
namespace editor {
/*******************************************************************************
* Constructors / Destructor
******************************************************************************/
SymbolEditorFsm::SymbolEditorFsm(const Context& context) noexcept
: QObject(nullptr), mCurrentState(State::IDLE), mPreviousState(State::IDLE) {
mStates.insert(State::SELECT, new SymbolEditorState_Select(context));
mStates.insert(State::ADD_PINS, new SymbolEditorState_AddPins(context));
mStates.insert(State::ADD_NAMES, new SymbolEditorState_AddNames(context));
mStates.insert(State::ADD_VALUES, new SymbolEditorState_AddValues(context));
mStates.insert(State::DRAW_LINE, new SymbolEditorState_DrawLine(context));
mStates.insert(State::DRAW_RECT, new SymbolEditorState_DrawRect(context));
mStates.insert(State::DRAW_POLYGON,
new SymbolEditorState_DrawPolygon(context));
mStates.insert(State::DRAW_CIRCLE, new SymbolEditorState_DrawCircle(context));
mStates.insert(State::DRAW_ARC, new SymbolEditorState_DrawArc(context));
mStates.insert(State::DRAW_TEXT, new SymbolEditorState_DrawText(context));
mStates.insert(State::MEASURE, new SymbolEditorState_Measure(context));
foreach (SymbolEditorState* state, mStates) {
connect(state, &SymbolEditorState::statusBarMessageChanged, this,
&SymbolEditorFsm::statusBarMessageChanged);
}
enterNextState(State::SELECT);
}
SymbolEditorFsm::~SymbolEditorFsm() noexcept {
leaveCurrentState();
qDeleteAll(mStates);
mStates.clear();
}
/*******************************************************************************
* Getters
******************************************************************************/
EditorWidgetBase::Tool SymbolEditorFsm::getCurrentTool() const noexcept {
switch (mCurrentState) {
case State::IDLE:
return EditorWidgetBase::Tool::NONE;
case State::SELECT:
return EditorWidgetBase::Tool::SELECT;
case State::ADD_PINS:
return EditorWidgetBase::Tool::ADD_PINS;
case State::ADD_NAMES:
return EditorWidgetBase::Tool::ADD_NAMES;
case State::ADD_VALUES:
return EditorWidgetBase::Tool::ADD_VALUES;
case State::DRAW_LINE:
return EditorWidgetBase::Tool::DRAW_LINE;
case State::DRAW_ARC:
return EditorWidgetBase::Tool::DRAW_ARC;
case State::DRAW_RECT:
return EditorWidgetBase::Tool::DRAW_RECT;
case State::DRAW_POLYGON:
return EditorWidgetBase::Tool::DRAW_POLYGON;
case State::DRAW_CIRCLE:
return EditorWidgetBase::Tool::DRAW_CIRCLE;
case State::DRAW_TEXT:
return EditorWidgetBase::Tool::DRAW_TEXT;
case State::MEASURE:
return EditorWidgetBase::Tool::MEASURE;
default:
Q_ASSERT(false);
return EditorWidgetBase::Tool::NONE;
}
}
/*******************************************************************************
* General Methods
******************************************************************************/
void SymbolEditorFsm::updateAvailableFeatures() noexcept {
QSet<EditorWidgetBase::Feature> features;
if (SymbolEditorState* state = getCurrentState()) {
features |= state->getAvailableFeatures();
}
if (features != mAvailableFeatures) {
mAvailableFeatures = features;
emit availableFeaturesChanged();
}
}
/*******************************************************************************
* Event Handlers
******************************************************************************/
bool SymbolEditorFsm::processKeyPressed(const QKeyEvent& e) noexcept {
if (getCurrentState()) {
return getCurrentState()->processKeyPressed(e);
} else {
return false;
}
}
bool SymbolEditorFsm::processKeyReleased(const QKeyEvent& e) noexcept {
if (getCurrentState()) {
return getCurrentState()->processKeyReleased(e);
} else {
return false;
}
}
bool SymbolEditorFsm::processGraphicsSceneMouseMoved(
QGraphicsSceneMouseEvent& e) noexcept {
if (getCurrentState()) {
return getCurrentState()->processGraphicsSceneMouseMoved(e);
} else {
return false;
}
}
bool SymbolEditorFsm::processGraphicsSceneLeftMouseButtonPressed(
QGraphicsSceneMouseEvent& e) noexcept {
if (getCurrentState()) {
return getCurrentState()->processGraphicsSceneLeftMouseButtonPressed(e);
} else {
return false;
}
}
bool SymbolEditorFsm::processGraphicsSceneLeftMouseButtonReleased(
QGraphicsSceneMouseEvent& e) noexcept {
if (getCurrentState()) {
return getCurrentState()->processGraphicsSceneLeftMouseButtonReleased(e);
} else {
return false;
}
}
bool SymbolEditorFsm::processGraphicsSceneLeftMouseButtonDoubleClicked(
QGraphicsSceneMouseEvent& e) noexcept {
if (getCurrentState()) {
return getCurrentState()->processGraphicsSceneLeftMouseButtonDoubleClicked(
e);
} else {
return false;
}
}
bool SymbolEditorFsm::processGraphicsSceneRightMouseButtonReleased(
QGraphicsSceneMouseEvent& e) noexcept {
if (SymbolEditorState* state = getCurrentState()) {
if (state->processGraphicsSceneRightMouseButtonReleased(e)) {
return true;
} else if (mCurrentState != State::SELECT) {
// If right click is not handled, abort current command.
return processAbortCommand();
} else {
// In select state, switch back to last state.
return switchToPreviousState();
}
} else {
return false;
}
}
bool SymbolEditorFsm::processSelectAll() noexcept {
if (getCurrentState()) {
return getCurrentState()->processSelectAll();
} else {
return false;
}
}
bool SymbolEditorFsm::processCut() noexcept {
if (getCurrentState()) {
return getCurrentState()->processCut();
} else {
return false;
}
}
bool SymbolEditorFsm::processCopy() noexcept {
if (getCurrentState()) {
return getCurrentState()->processCopy();
} else {
return false;
}
}
bool SymbolEditorFsm::processPaste() noexcept {
if (getCurrentState()) {
return getCurrentState()->processPaste();
} else {
return false;
}
}
bool SymbolEditorFsm::processMove(Qt::ArrowType direction) noexcept {
if (getCurrentState()) {
return getCurrentState()->processMove(direction);
} else {
return false;
}
}
bool SymbolEditorFsm::processRotate(const Angle& rotation) noexcept {
if (getCurrentState()) {
return getCurrentState()->processRotate(rotation);
} else {
return false;
}
}
bool SymbolEditorFsm::processMirror(Qt::Orientation orientation) noexcept {
if (getCurrentState()) {
return getCurrentState()->processMirror(orientation);
} else {
return false;
}
}
bool SymbolEditorFsm::processSnapToGrid() noexcept {
if (getCurrentState()) {
return getCurrentState()->processSnapToGrid();
} else {
return false;
}
}
bool SymbolEditorFsm::processRemove() noexcept {
if (getCurrentState()) {
return getCurrentState()->processRemove();
} else {
return false;
}
}
bool SymbolEditorFsm::processEditProperties() noexcept {
if (getCurrentState()) {
return getCurrentState()->processEditProperties();
} else {
return false;
}
}
bool SymbolEditorFsm::processAbortCommand() noexcept {
if (getCurrentState() && (!getCurrentState()->processAbortCommand())) {
return setNextState(State::SELECT);
} else {
return false;
}
}
bool SymbolEditorFsm::processStartSelecting() noexcept {
return setNextState(State::SELECT);
}
bool SymbolEditorFsm::processStartAddingSymbolPins() noexcept {
return setNextState(State::ADD_PINS);
}
bool SymbolEditorFsm::processStartAddingNames() noexcept {
return setNextState(State::ADD_NAMES);
}
bool SymbolEditorFsm::processStartAddingValues() noexcept {
return setNextState(State::ADD_VALUES);
}
bool SymbolEditorFsm::processStartDrawLines() noexcept {
return setNextState(State::DRAW_LINE);
}
bool SymbolEditorFsm::processStartDrawArcs() noexcept {
return setNextState(State::DRAW_ARC);
}
bool SymbolEditorFsm::processStartDrawRects() noexcept {
return setNextState(State::DRAW_RECT);
}
bool SymbolEditorFsm::processStartDrawPolygons() noexcept {
return setNextState(State::DRAW_POLYGON);
}
bool SymbolEditorFsm::processStartDrawCircles() noexcept {
return setNextState(State::DRAW_CIRCLE);
}
bool SymbolEditorFsm::processStartDrawTexts() noexcept {
return setNextState(State::DRAW_TEXT);
}
bool SymbolEditorFsm::processStartDxfImport() noexcept {
setNextState(State::SELECT);
if (SymbolEditorState* state = getCurrentState()) {
if (state->processImportDxf()) {
return true;
}
}
return false;
}
bool SymbolEditorFsm::processStartMeasure() noexcept {
return setNextState(State::MEASURE);
}
/*******************************************************************************
* Private Methods
******************************************************************************/
SymbolEditorState* SymbolEditorFsm::getCurrentState() const noexcept {
return mStates.value(mCurrentState, nullptr);
}
bool SymbolEditorFsm::setNextState(State state) noexcept {
if (state == mCurrentState) {
return true;
}
if (!leaveCurrentState()) {
return false;
}
const bool success = enterNextState(state);
updateAvailableFeatures();
return success;
}
bool SymbolEditorFsm::leaveCurrentState() noexcept {
if (SymbolEditorState* state = getCurrentState()) {
if (!getCurrentState()->exit()) {
return false;
}
disconnect(state, &SymbolEditorState::availableFeaturesChanged, this,
&SymbolEditorFsm::updateAvailableFeatures);
}
if (mCurrentState != State::SELECT) {
// Only memorize states other than SELECT.
mPreviousState = mCurrentState;
}
mCurrentState = State::IDLE;
emit toolChanged(getCurrentTool());
return true;
}
bool SymbolEditorFsm::enterNextState(State state) noexcept {
Q_ASSERT(mCurrentState == State::IDLE);
if (SymbolEditorState* nextState = mStates.value(state, nullptr)) {
if (!nextState->entry()) {
return false;
}
connect(nextState, &SymbolEditorState::availableFeaturesChanged, this,
&SymbolEditorFsm::updateAvailableFeatures);
}
mCurrentState = state;
emit toolChanged(getCurrentTool());
return true;
}
bool SymbolEditorFsm::switchToPreviousState() noexcept {
State nextState = mPreviousState;
if ((nextState == mCurrentState) || (nextState == State::IDLE)) {
nextState = State::SELECT;
}
return setNextState(nextState);
}
/*******************************************************************************
* End of File
******************************************************************************/
} // namespace editor
} // namespace librepcb
d953b88eaThis file is pinned to the selected release. Download the original to open it in your design tool.