26#include <QGraphicsProxyWidget>
27#include <QGraphicsSceneContextMenuEvent>
31#include <QStyleOptionGraphicsItem>
46#define MAXFONTSIZE 300.0f
69 if (
state->getStateClass())
83 StateItem* parentState = qgraphicsitem_cast<StateItem*>(parentItem());
114 bool showStateClassName =
115 stateClass && (
instanceName != stateClass->getStateName() );
117 const int renderFlags =
static_cast<uint8_t
>(Qt::TextSingleLine) |
118 static_cast<uint8_t
>(Qt::AlignTop) |
119 static_cast<uint8_t
>(Qt::AlignHCenter);
123 float instanceNameWidthRelative = showSubstates ? 0.5f : 0.8f;
126 float instanceNameScaleFactor = textRect.width() * instanceNameWidthRelative /
131 if (showStateClassName)
133 textRect.adjust(0, 10, 0, 0);
137 textRect.adjust(0, 20, 0, 0);
144 (
bounds.height() - painter->fontMetrics().height() * instanceNameScaleFactor) / 2,
150 QStyleOptionGraphicsItem::levelOfDetailFromTransform(painter->worldTransform());
151 QFont f = painter->font();
154 std::min<float>(f.pointSizeF() * instanceNameScaleFactor, (maxFsize).height() / lodT));
156 float textHeightScale = 0.8;
159 if (showSubstates &&
state->getStateClass() &&
160 painter->fontMetrics().height() > 0.5 *
state->getStateClass()->margin.top())
162 float margin =
state->getStateClass()->margin.top();
163 float height = painter->fontMetrics().height();
164 float size = f.pointSizeF();
165 textHeightScale = margin / height;
166 if (showStateClassName)
168 textHeightScale *= 0.45;
172 textHeightScale *= 0.7;
174 f.setPointSizeF(size * textHeightScale);
182 if (showStateClassName && !stateClass->getStateName().isEmpty())
184 QString classNameText =
"[state: " + stateClass->getStateName() +
"]";
185 float instanceNamePointSize = f.pointSizeF();
186 float classNameScaleFactor =
187 textRect.width() * 0.8f / painter->fontMetrics().width(classNameText);
190 textRect.adjust(0, painter->fontMetrics().height() * 1.0, 0, 0);
192 lodT = QStyleOptionGraphicsItem::levelOfDetailFromTransform(painter->worldTransform());
194 float classNamePointSize =
196 std::min<float>(f.pointSizeF() * classNameScaleFactor, (maxFsize).height() / lodT);
197 classNamePointSize = std::min(classNamePointSize,
198 instanceNamePointSize);
199 f.setPointSizeF(classNamePointSize);
202 painter->drawText(textRect, renderFlags, classNameText);
233 StateInstanceItemMap::iterator it =
subStates.find(substate);
246 SLOT(setPosition(QPointF)));
250 SLOT(setBoundingBox(
float)));
252 stateItem->setScale(substate->getScale());
254 stateItem->setPos(substate->getTopLeft());
255 stateItem->
setSize(substate->getClassSize());
267 StateInstanceItemMap::iterator it =
subStates.find(substate);
275 substateItem->setPos(substate->getTopLeft());
276 substateItem->
setSize(substate->getClassSize());
277 substateItem->setScale(substate->getScale());
293 StateInstanceItemMap::iterator it =
subStates.find(substate);
301 QPointer<StateItem> substateItem = it.value();
305 substateItem->prepareGeometryChange();
306 QObject::disconnect(substateItem);
307 delete substateItem.data();
345 TransitionMap::iterator it =
transitions.find(transition);
359 TransitionMap::iterator it =
transitions.find(transition);
367 QObject::disconnect(t);
375 TransitionMap::iterator it =
transitions.find(transition);
381 int highlightDuration = 10000;
402 if (t->sourceState ==
state || t->destinationState ==
state)
411 QPoint mouseScreenPos,
412 QPointF mouseItemPos)
415 transition,
state->getStateClass(), mouseScreenPos, mouseItemPos);
421 TransitionMap::iterator it =
transitions.find(transition);
424 StateInstanceItemMap::iterator itState =
subStates.begin();
426 for (; itState !=
subStates.end(); itState++)
429 QPointF dropPointMapped = item->mapFromParent(dropPoint);
431 if (item->contains(dropPointMapped))
435 QList<QPointF> suppPoint;
436 suppPoint.push_back(dropPoint);
437 state->getStateClass()->updateTransitionDestination(
443 state->getStateClass()->detachTransitionDestination(transition, dropPoint);
474 if (
state->getStateClass())
476 connect(
state->getStateClass().get(),
480 connect(
state->getStateClass().get(),
486 connect(
state->getStateClass().get(),
494 state->getStateClass().get(),
512 if (!
state->getStateClass())
517 const auto& ts =
state->getStateClass()->getTransitions(
true);
519 for (
int i = 0; i < ts.size(); i++)
524 const auto& sl =
state->getStateClass()->getSubstates();
526 for (
auto i = sl.begin(); i != sl.end(); i++)
540 switch (
state->getType())
544 QColor color(52, 152, 219);
547 color = color.lighter(130);
551 color = color.lighter(110);
559 QColor color(26, 188, 156);
562 color = color.lighter(130);
566 color = color.lighter(110);
572 case eDynamicRemoteState:
578 QColor color(241, 196, 15);
579 color = color.lighter(120);
610 if (
state->getStateClass())
612 auto desc =
state->getStateClass()->getDescription();
625 auto curScene = scene();
631 curScene->removeItem(t);
636 s->prepareGeometryChange();
640 curScene->removeItem(s);
649 const QGraphicsItem* parent =
this;
650 while (
dynamic_cast<StateItem*
>(parent->parentItem()))
652 parent = parent->parentItem();
663 return state->adjustPosition(newPos);
681 substate->setMaxShownSubstateLevel(value);
683 for (
auto& item : childItems())
693 for (
auto substate : substates)
695 bool active = (substate->getInstanceName() == substateName);
696 substate->setActiveState(
active);
704 for (
auto substate : substates)
706 substate->setActiveState(
false);
714 StateItem* parent = qgraphicsitem_cast<StateItem*>(parentItem());
718 parent = qgraphicsitem_cast<StateItem*>(parent->parentItem());
726 StateItem* parent = qgraphicsitem_cast<StateItem*>(parentItem());
733 QVector<StateItem*> result;
734 for (QGraphicsItem* item : this->childItems())
739 result.push_back(
state);
745 QVector<TransitionItem*>
748 QVector<TransitionItem*> result;
749 for (QGraphicsItem* item : this->childItems())
754 result.push_back(transition);
786 if (!
state->getStateClass())
797 if (oldSize != newSize)
807 if (oldPos != newPos)
836 scene()->clearSelection();
839 this->setSelected(
true);
847 if (change == ItemSelectedHasChanged && value.toBool() ==
true)
852 else if (change == ItemSelectedHasChanged && value.toBool() ==
false)
857 else if (change == ItemScaleHasChanged)
865 else if (change == ItemSceneChange)
924 qobject_cast<const AbstractStateMimeData*>(event->mimeData());
927 state->getType() == eNormalState)
929 event->setDropAction(Qt::LinkAction);
933 event->setDropAction(Qt::IgnoreAction);
949 if (event->proposedAction() == Qt::IgnoreAction)
955 qobject_cast<const AbstractStateMimeData*>(event->mimeData());
958 (
state->getType() == eNormalState ||
state->getType() == eRemoteState))
961 const QString newStateNameBase =
data->getState()->getStateName();
962 QString newStateName = newStateNameBase;
964 while (
state->getStateClass()->getSubstates().find(newStateName) !=
965 state->getStateClass()->getSubstates().end())
967 newStateName = newStateNameBase +
"_" + QString::number(i);
972 data->getState()->hasDescendant(
state->getStateClass()))
974 QMessageBox::warning(event->source(),
975 "State drag'n'drop error",
976 "State cycle detected - you must not insert a state which is "
977 "also a parent state of the current state");
980 else if (
data->getState()->getType() == eDynamicRemoteState &&
981 !
data->isInSameGroup(
state->getStateClass()))
983 QMessageBox::warning(event->source(),
984 "State drag'n'drop error",
985 "Dynamic Remote States can only be added in the same group.");
988 else if (
data->isInSameGroup(
state->getStateClass()))
990 if (
data->getState()->getType() == eDynamicRemoteState)
992 state->getStateClass()->addDynamicRemoteSubstate(
993 data->getState(), newStateName, event->pos());
997 state->getStateClass()->addSubstate(
998 data->getState(), newStateName, event->pos());
1001 else if (
data->isPublic())
1003 state->getStateClass()->addRemoteSubstate(
1004 data->getState(),
data->getProxyName(), newStateName, event->pos());
1008 QMessageBox::warning(event->source(),
1009 "State drag'n'drop error",
1010 "Only public states can be added as a Remote State.");
1022 event->setDropAction(Qt::LinkAction);
1027 event->setDropAction(Qt::IgnoreAction);
1045 if (!
state->getStateInstance() || !
state->getStateInstance()->getStateClass())
1050 if (
state->getStateInstance()->getStateClass()->getUUID() == sC->getUUID())
1055 return state->hasAncestor(sC);
1061 if (!sC || !
state->getStateClass())
1065 return state->getStateClass()->hasDescendant(sC);
bool isLevelOfDetailLow(QGraphicsSceneEvent *event) const
RoundRectItem(const QRectF &bounds, const QColor &color, QGraphicsItem *parent=0)
void setEditable(bool editable)
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget=0) override
QVariant itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value) override
void setColor(QColor newColor)
void setRimPen(QPen newPen)
void setSize(const QSizeF &newSize)
The AbstractStateMimeData class is used to transport state data from the treeview to the stateview an...
MorphingItem(QGraphicsItem *derivedItem)
virtual LevelOfDetail getLevelOfDetail(QPainter *painter) const
virtual LevelOfDetail getLevelOfDetailByParent(QPainter *painter, MorphingItem *parent) const
void stateItemBoundingBoxChanged(float newSquareBoundingBoxSize)
void transitionMoved(statechartmodel::TransitionCPtr transition, QPointF dropPoint)
void notifyStateChanged(statechartmodel::SignalType signalType)
void itemResized(const QRectF &oldSize, const QRectF &newSize) override
void dragMoveEvent(QGraphicsSceneDragDropEvent *event) override
QPointF adjustPosition(QPointF &newPos) override
QString getInstanceName() const
bool hasDescendant(statechartmodel::StatePtr state) const
void setActiveState(bool active)
QString getFullStatePath() const
void contextMenuEvent(QGraphicsSceneContextMenuEvent *event) override
LevelOfDetail getLevelOfDetail(float levelOfDetail) const override
void notifyTransitionChanged(statechartmodel::TransitionCPtr transition, statechartmodel::SignalType signalType)
void transitionContextMenuRequested(statechartmodel::TransitionCPtr transition, statechartmodel::StatePtr state, QPoint mouseScreenPos, QPointF mouseItemPos)
TransitionMap transitions
bool hasAncestor(statechartmodel::StatePtr state) const
int getMaxShownSubstateLevel() const
void forwardTransitionContextMenuRequested(statechartmodel::TransitionCPtr transition, QPoint mouseScreenPos, QPointF mouseItemPos)
QVector< StateItem * > getSubstateItems() const
statechartmodel::StateInstancePtr getStateInstance() const
QVector< TransitionItem * > getTransitionItems() const
void notifySubstateChanged(statechartmodel::StateInstancePtr substate, statechartmodel::SignalType signalType)
void dragEnterEvent(QGraphicsSceneDragDropEvent *event) override
int maxShownSubstateLevel
void stateItemResized(QSizeF newSize)
void setInstanceName(const QString &value)
void itemBoundingBoxChanged(float oldSize, float size) override
void itemMoved(const QPointF &oldPos, const QPointF &newPos) override
StateItem * getParentStateItem() const
void setup(QGraphicsItem *parent)
void stateItemMoved(QPointF newPosition)
void clearActiveSubstate()
int getInstanceLevel() const
void stateContextMenuRequested(statechartmodel::StateInstancePtr stateInstace, QPoint mouseScreenPos, QPointF mouseItemPos)
statechartmodel::StateInstancePtr state
void dropEvent(QGraphicsSceneDragDropEvent *event) override
void setMaxShownSubstateLevel(int value)
QVariant itemChange(GraphicsItemChange change, const QVariant &value) override
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override
StateItem(statechartmodel::StateInstancePtr state, QGraphicsItem *parent=0)
bool itemResizing(const QRectF &oldSize, QRectF &proposedSize) override
StateInstanceItemMap subStates
void notifyTransitionsChanged(statechartmodel::StateInstancePtr transition, statechartmodel::SignalType signalType)
void setActiveSubstate(const QString &substateName)
void highlightAnimation(int duration=5000)
static QString StateTypeToString(eStateType type)
#define ARMARX_CHECK_EXPRESSION(expression)
This macro evaluates the expression and if it turns out to be false it will throw an ExpressionExcept...
#define ARMARX_INFO
The normal logging level.
#define ARMARX_IMPORTANT
The logging level for always important information, but expected behaviour (in contrast to ARMARX_WAR...
#define ARMARX_DEBUG
The logging level for output that is only interesting while debugging.
#define ARMARX_WARNING
The logging level for unexpected behaviour, but not a serious problem.
std::shared_ptr< State > StatePtr
std::shared_ptr< StateInstance > StateInstancePtr
std::shared_ptr< const Transition > TransitionCPtr
SignalType
The SignalType enum.
This file offers overloads of toIce() and fromIce() functions for STL container types.