|
|
|
@@ -690,6 +690,7 @@ LogicEditorWidget::LogicEditorWidget( |
|
|
|
void LogicEditorWidget::setLogicId(const std::string &logic_id) |
|
|
|
{ |
|
|
|
const bool logic_changed = logic_id_ != logic_id; |
|
|
|
clearGesture(); |
|
|
|
logic_id_ = logic_id; |
|
|
|
if (logic_changed) |
|
|
|
{ |
|
|
|
@@ -792,6 +793,7 @@ void LogicEditorWidget::setLogicId(const std::string &logic_id) |
|
|
|
|
|
|
|
void LogicEditorWidget::setEditingEnabled(bool enabled) |
|
|
|
{ |
|
|
|
clearGesture(); |
|
|
|
editing_enabled_ = enabled; |
|
|
|
if (!enabled) |
|
|
|
{ |
|
|
|
@@ -806,6 +808,7 @@ void LogicEditorWidget::setEditingEnabled(bool enabled) |
|
|
|
|
|
|
|
void LogicEditorWidget::setMouseWireMode(MouseWireMode mode) |
|
|
|
{ |
|
|
|
clearGesture(); |
|
|
|
mouse_wire_mode_ = editing_enabled_ ? mode : MouseWireMode::Select; |
|
|
|
selection_pressed_ = false; |
|
|
|
selection_dragging_ = false; |
|
|
|
@@ -1707,14 +1710,21 @@ void LogicEditorWidget::beginGesture(const Hit &hit) |
|
|
|
gesture_active_ = true; |
|
|
|
gesture_origin_ = hit; |
|
|
|
gesture_current_ = hit; |
|
|
|
gesture_scene_position_valid_ = false; |
|
|
|
viewport()->update(); |
|
|
|
} |
|
|
|
|
|
|
|
void LogicEditorWidget::updateGesture(const Hit &hit) |
|
|
|
void LogicEditorWidget::updateGesture( |
|
|
|
const Hit &hit, const QPointF &scene_position) |
|
|
|
{ |
|
|
|
if (gesture_active_ && !hit.rungId.empty()) |
|
|
|
if (!gesture_active_) |
|
|
|
{ |
|
|
|
gesture_current_ = hit; |
|
|
|
return; |
|
|
|
} |
|
|
|
gesture_current_ = hit; |
|
|
|
gesture_scene_position_ = scene_position; |
|
|
|
gesture_scene_position_valid_ = true; |
|
|
|
viewport()->update(); |
|
|
|
} |
|
|
|
|
|
|
|
void LogicEditorWidget::finishGesture(const Hit &hit) |
|
|
|
@@ -1723,57 +1733,62 @@ void LogicEditorWidget::finishGesture(const Hit &hit) |
|
|
|
{ |
|
|
|
return; |
|
|
|
} |
|
|
|
const Hit origin = gesture_origin_; |
|
|
|
gesture_active_ = false; |
|
|
|
if (gesture_origin_.rungId.empty() || hit.rungId.empty()) |
|
|
|
gesture_origin_ = {}; |
|
|
|
gesture_current_ = {}; |
|
|
|
gesture_scene_position_valid_ = false; |
|
|
|
viewport()->update(); |
|
|
|
if (origin.rungId.empty() || hit.rungId.empty()) |
|
|
|
{ |
|
|
|
return; |
|
|
|
} |
|
|
|
LogicEditorResult result; |
|
|
|
const bool connected = mouse_wire_mode_ == MouseWireMode::Draw; |
|
|
|
if ((gesture_origin_.vertical || gesture_origin_.boundary) |
|
|
|
if ((origin.vertical || origin.boundary) |
|
|
|
&& (hit.vertical || hit.boundary)) |
|
|
|
{ |
|
|
|
if (!connected && gesture_origin_.vertical |
|
|
|
&& gesture_origin_.objectId == hit.objectId) |
|
|
|
if (!connected && origin.vertical |
|
|
|
&& origin.objectId == hit.objectId) |
|
|
|
{ |
|
|
|
result = editor_service_.removeVerticalConnections( |
|
|
|
logic_id_, {gesture_origin_.objectId}); |
|
|
|
logic_id_, {origin.objectId}); |
|
|
|
} |
|
|
|
else if (gesture_origin_.column != hit.column) |
|
|
|
else if (origin.column != hit.column) |
|
|
|
{ |
|
|
|
result = {false, LogicEditorError::InvalidOperation, |
|
|
|
"竖线拖动必须保持在同一列边界", {}}; |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
std::string first_rung = gesture_origin_.rungId; |
|
|
|
std::string first_rung = origin.rungId; |
|
|
|
std::string last_rung = hit.rungId; |
|
|
|
if (last_rung.empty() && !gesture_origin_.lowerRungId.empty()) |
|
|
|
if (last_rung.empty() && !origin.lowerRungId.empty()) |
|
|
|
{ |
|
|
|
last_rung = gesture_origin_.lowerRungId; |
|
|
|
last_rung = origin.lowerRungId; |
|
|
|
} |
|
|
|
result = editor_service_.setVerticalConnectionRange( |
|
|
|
logic_id_, first_rung, last_rung, |
|
|
|
gesture_origin_.column, connected); |
|
|
|
origin.column, connected); |
|
|
|
} |
|
|
|
} |
|
|
|
else if (gesture_origin_.vertical || hit.vertical) |
|
|
|
else if (origin.vertical || hit.vertical) |
|
|
|
{ |
|
|
|
result = {false, LogicEditorError::InvalidOperation, |
|
|
|
"请从网格边界开始竖向拖动", {}}; |
|
|
|
} |
|
|
|
else if (gesture_origin_.column == hit.column |
|
|
|
&& gesture_origin_.rungId != hit.rungId) |
|
|
|
else if (origin.column == hit.column |
|
|
|
&& origin.rungId != hit.rungId) |
|
|
|
{ |
|
|
|
result = editor_service_.setVerticalConnectionRange( |
|
|
|
logic_id_, gesture_origin_.rungId, hit.rungId, |
|
|
|
gesture_origin_.column, connected); |
|
|
|
logic_id_, origin.rungId, hit.rungId, |
|
|
|
origin.column, connected); |
|
|
|
} |
|
|
|
else if (gesture_origin_.rungId == hit.rungId) |
|
|
|
else if (origin.rungId == hit.rungId) |
|
|
|
{ |
|
|
|
result = editor_service_.setHorizontalWireRange( |
|
|
|
logic_id_, gesture_origin_.rungId, |
|
|
|
gesture_origin_.column, hit.column, connected); |
|
|
|
logic_id_, origin.rungId, |
|
|
|
origin.column, hit.column, connected); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
@@ -1795,6 +1810,134 @@ void LogicEditorWidget::finishGesture(const Hit &hit) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
void LogicEditorWidget::clearGesture() |
|
|
|
{ |
|
|
|
if (!gesture_active_ && !gesture_scene_position_valid_) |
|
|
|
{ |
|
|
|
return; |
|
|
|
} |
|
|
|
gesture_active_ = false; |
|
|
|
gesture_origin_ = {}; |
|
|
|
gesture_current_ = {}; |
|
|
|
gesture_scene_position_ = {}; |
|
|
|
gesture_scene_position_valid_ = false; |
|
|
|
viewport()->update(); |
|
|
|
} |
|
|
|
|
|
|
|
void LogicEditorWidget::drawGesturePreview(QPainter *painter) const |
|
|
|
{ |
|
|
|
if (!gesture_active_ || painter == nullptr |
|
|
|
|| gesture_origin_.rungId.empty()) |
|
|
|
{ |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
enum class PreviewKind { Invalid, Horizontal, Vertical }; |
|
|
|
PreviewKind kind = PreviewKind::Invalid; |
|
|
|
bool valid = false; |
|
|
|
const Hit &origin = gesture_origin_; |
|
|
|
const Hit ¤t = gesture_current_; |
|
|
|
const bool connected = mouse_wire_mode_ == MouseWireMode::Draw; |
|
|
|
|
|
|
|
if (!current.rungId.empty()) |
|
|
|
{ |
|
|
|
if ((origin.vertical || origin.boundary) |
|
|
|
&& (current.vertical || current.boundary)) |
|
|
|
{ |
|
|
|
kind = PreviewKind::Vertical; |
|
|
|
valid = origin.column == current.column |
|
|
|
&& (origin.rungId != current.rungId |
|
|
|
|| (!connected && origin.vertical |
|
|
|
&& origin.objectId == current.objectId)); |
|
|
|
} |
|
|
|
else if (origin.vertical || current.vertical) |
|
|
|
{ |
|
|
|
kind = PreviewKind::Invalid; |
|
|
|
} |
|
|
|
else if (origin.column == current.column |
|
|
|
&& origin.rungId != current.rungId) |
|
|
|
{ |
|
|
|
kind = PreviewKind::Vertical; |
|
|
|
valid = origin.column >= 0 |
|
|
|
&& origin.column <= ProjectLimits::kMaximumConditionColumns; |
|
|
|
} |
|
|
|
else if (origin.rungId == current.rungId) |
|
|
|
{ |
|
|
|
kind = PreviewKind::Horizontal; |
|
|
|
valid = origin.column >= 0 && current.column >= 0 |
|
|
|
&& origin.column < ProjectLimits::kMaximumConditionColumns |
|
|
|
&& current.column < ProjectLimits::kMaximumConditionColumns; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
QColor preview_color = valid |
|
|
|
? connected ? QColor(QStringLiteral("#277da1")) |
|
|
|
: QColor(QStringLiteral("#c56a1a")) |
|
|
|
: kFaultColor; |
|
|
|
preview_color.setAlpha(220); |
|
|
|
QPen preview_pen(preview_color, valid ? 2.8 : 2.4, Qt::DashLine); |
|
|
|
preview_pen.setCosmetic(true); |
|
|
|
preview_pen.setCapStyle(Qt::SquareCap); |
|
|
|
painter->save(); |
|
|
|
painter->setRenderHint(QPainter::Antialiasing, true); |
|
|
|
painter->setPen(preview_pen); |
|
|
|
painter->setBrush(Qt::NoBrush); |
|
|
|
|
|
|
|
if (valid && kind == PreviewKind::Horizontal) |
|
|
|
{ |
|
|
|
const RowLayout *layout = layoutForRung(origin.rungId); |
|
|
|
if (layout != nullptr) |
|
|
|
{ |
|
|
|
const int first = std::min(origin.column, current.column); |
|
|
|
const int last = std::max(origin.column, current.column); |
|
|
|
for (int column = first; column <= last; ++column) |
|
|
|
{ |
|
|
|
const LadderCell *cell = editor_service_.findCell( |
|
|
|
logic_id_, origin.rungId, column); |
|
|
|
if (cell == nullptr || cell->kind == LadderCellKind::Node |
|
|
|
|| (mouse_wire_mode_ == MouseWireMode::Erase |
|
|
|
&& cell->kind != LadderCellKind::Wire)) |
|
|
|
{ |
|
|
|
continue; |
|
|
|
} |
|
|
|
const qreal left = kLeftBus |
|
|
|
+ static_cast<qreal>(column) * kCellWidth; |
|
|
|
painter->drawLine( |
|
|
|
QPointF(left, layout->centerY), |
|
|
|
QPointF(left + kCellWidth, layout->centerY)); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
else if (valid && kind == PreviewKind::Vertical) |
|
|
|
{ |
|
|
|
const RowLayout *first = layoutForRung(origin.rungId); |
|
|
|
const RowLayout *last = layoutForRung(current.rungId); |
|
|
|
if (first != nullptr && last != nullptr) |
|
|
|
{ |
|
|
|
const qreal x = kLeftBus |
|
|
|
+ static_cast<qreal>(origin.column) * kCellWidth; |
|
|
|
painter->drawLine( |
|
|
|
QPointF(x, first->centerY), |
|
|
|
QPointF(x, last->centerY)); |
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
const RowLayout *layout = layoutForRung(origin.rungId); |
|
|
|
if (layout != nullptr && gesture_scene_position_valid_) |
|
|
|
{ |
|
|
|
const qreal origin_x = kLeftBus |
|
|
|
+ (origin.vertical || origin.boundary |
|
|
|
? static_cast<qreal>(origin.column) * kCellWidth |
|
|
|
: (static_cast<qreal>(origin.column) + 0.5) * kCellWidth); |
|
|
|
painter->drawLine( |
|
|
|
QPointF(origin_x, layout->centerY), |
|
|
|
gesture_scene_position_); |
|
|
|
} |
|
|
|
} |
|
|
|
painter->restore(); |
|
|
|
} |
|
|
|
|
|
|
|
void LogicEditorWidget::showCommandEditor(const Hit &hit) |
|
|
|
{ |
|
|
|
if (!editing_enabled_ || hit.rungId.empty() |
|
|
|
@@ -2199,7 +2342,8 @@ void LogicEditorWidget::mouseMoveEvent(QMouseEvent *event) |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
updateGesture(hitAt(mapToScene(event->pos()))); |
|
|
|
const QPointF scene_position = mapToScene(event->pos()); |
|
|
|
updateGesture(hitAt(scene_position), scene_position); |
|
|
|
} |
|
|
|
event->accept(); |
|
|
|
} |
|
|
|
@@ -2242,6 +2386,13 @@ void LogicEditorWidget::mouseDoubleClickEvent(QMouseEvent *event) |
|
|
|
event->accept(); |
|
|
|
} |
|
|
|
|
|
|
|
void LogicEditorWidget::drawForeground( |
|
|
|
QPainter *painter, const QRectF &rect) |
|
|
|
{ |
|
|
|
QGraphicsView::drawForeground(painter, rect); |
|
|
|
drawGesturePreview(painter); |
|
|
|
} |
|
|
|
|
|
|
|
void LogicEditorWidget::resizeEvent(QResizeEvent *event) |
|
|
|
{ |
|
|
|
QGraphicsView::resizeEvent(event); |
|
|
|
|