mirror of https://codeberg.org/topola/topola.git
Add master interactor to rule all interactors (WIP, not used yet)
This commit is contained in:
parent
623dc967ca
commit
da7585b135
|
|
@ -85,7 +85,7 @@ impl Viewport {
|
||||||
let _ = interactor.update(
|
let _ = interactor.update(
|
||||||
workspace.autorouter.router().navmesher_board().board(),
|
workspace.autorouter.router().navmesher_board().board(),
|
||||||
workspace.appearance_panel.active,
|
workspace.appearance_panel.active,
|
||||||
InteractiveInput::new(pointer_on_scene, false, false),
|
InteractiveInput::new(pointer_on_scene, false, false, false),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -98,7 +98,7 @@ impl Viewport {
|
||||||
let _ = interactor.update(
|
let _ = interactor.update(
|
||||||
workspace.autorouter.router().navmesher_board().board(),
|
workspace.autorouter.router().navmesher_board().board(),
|
||||||
workspace.appearance_panel.active,
|
workspace.appearance_panel.active,
|
||||||
InteractiveInput::new(pointer_for_scene, true, false),
|
InteractiveInput::new(pointer_for_scene, true, false, false),
|
||||||
);
|
);
|
||||||
|
|
||||||
workspace.selection = interactor.selection().clone();
|
workspace.selection = interactor.selection().clone();
|
||||||
|
|
|
||||||
|
|
@ -1,26 +0,0 @@
|
||||||
// SPDX-FileCopyrightText: 2026 Topola contributors
|
|
||||||
//
|
|
||||||
// SPDX-License-Identifier: MIT OR Apache-2.0
|
|
||||||
|
|
||||||
use crate::{
|
|
||||||
board::Board,
|
|
||||||
primitives::{JointId, PolygonId, SegmentId, ViaId},
|
|
||||||
};
|
|
||||||
|
|
||||||
impl Board {
|
|
||||||
pub fn delete_joint(&mut self, joint_id: JointId) {
|
|
||||||
self.layout.delete_joint(joint_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn delete_segment(&mut self, segment_id: SegmentId) {
|
|
||||||
self.layout.delete_segment(segment_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn delete_via(&mut self, via_id: ViaId) {
|
|
||||||
self.layout.delete_via(via_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn delete_polygon(&mut self, polygon_id: PolygonId) {
|
|
||||||
self.layout.delete_polygon(polygon_id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -15,13 +15,13 @@ use crate::{
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone, Constructor, Debug, Deserialize, Eq, Ord, PartialEq, PartialOrd, Serialize)]
|
#[derive(Clone, Constructor, Debug, Deserialize, Eq, PartialEq, Serialize)]
|
||||||
pub struct DragSelectionOptions {
|
pub struct DragSelectionOptions {
|
||||||
combine: SelectionCombineMode,
|
combine: SelectionCombineMode,
|
||||||
contain: SelectionContainMode,
|
contain: SelectionContainMode,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, Getters, Ord, PartialEq, PartialOrd)]
|
#[derive(Clone, Debug, Eq, Getters, PartialEq)]
|
||||||
pub struct DragSelectionInteractor {
|
pub struct DragSelectionInteractor {
|
||||||
origin: Vector2<i64>,
|
origin: Vector2<i64>,
|
||||||
original_selection: PersistableSelection,
|
original_selection: PersistableSelection,
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,50 @@
|
||||||
|
// SPDX-FileCopyrightText: 2026 Topola contributors
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MIT OR Apache-2.0
|
||||||
|
|
||||||
|
use derive_getters::Getters;
|
||||||
|
use derive_more::Constructor;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
InteractiveInput,
|
||||||
|
board::{
|
||||||
|
Board,
|
||||||
|
interactors::{SelectionCombineMode, SelectionInteractor},
|
||||||
|
selections::PersistableSelection,
|
||||||
|
},
|
||||||
|
layout::LayerId,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Clone, Constructor, Debug, Eq, Getters, PartialEq)]
|
||||||
|
pub struct MasterInteractor {
|
||||||
|
selection: PersistableSelection,
|
||||||
|
selection_interactor: Option<SelectionInteractor>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MasterInteractor {
|
||||||
|
pub fn update(&mut self, board: &mut Board, input: InteractiveInput) {
|
||||||
|
if input.delete {
|
||||||
|
board.delete_net_free_primitives(self.selection.nets.clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.selection_interactor.is_none() {
|
||||||
|
self.selection_interactor = Some(SelectionInteractor::new(
|
||||||
|
input.pointer,
|
||||||
|
self.selection.clone(),
|
||||||
|
SelectionCombineMode::Additive,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(selection_interactor) = self.selection_interactor.as_mut() {
|
||||||
|
if let Some(selection) =
|
||||||
|
selection_interactor.update(board, LayerId::new(0), input.clone())
|
||||||
|
{
|
||||||
|
self.selection = selection;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if input.release || input.cancel {
|
||||||
|
self.selection_interactor = None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -3,31 +3,24 @@
|
||||||
// SPDX-License-Identifier: MIT OR Apache-2.0
|
// SPDX-License-Identifier: MIT OR Apache-2.0
|
||||||
|
|
||||||
mod drag_selection;
|
mod drag_selection;
|
||||||
|
mod master;
|
||||||
mod selection;
|
mod selection;
|
||||||
|
|
||||||
|
use derive_more::Constructor;
|
||||||
pub use drag_selection::{DragSelectionInteractor, DragSelectionOptions};
|
pub use drag_selection::{DragSelectionInteractor, DragSelectionOptions};
|
||||||
pub use selection::SelectionInteractor;
|
pub use selection::SelectionInteractor;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::Vector2;
|
use crate::Vector2;
|
||||||
|
|
||||||
#[derive(Clone, Debug, Deserialize, Eq, Ord, PartialEq, PartialOrd, Serialize)]
|
#[derive(Clone, Constructor, Debug, Deserialize, Eq, Ord, PartialEq, PartialOrd, Serialize)]
|
||||||
pub struct InteractiveInput {
|
pub struct InteractiveInput {
|
||||||
pointer: Vector2<i64>,
|
pointer: Vector2<i64>,
|
||||||
released: bool,
|
release: bool,
|
||||||
|
delete: bool,
|
||||||
cancel: bool,
|
cancel: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InteractiveInput {
|
|
||||||
pub fn new(pointer: Vector2<i64>, released: bool, cancel: bool) -> Self {
|
|
||||||
Self {
|
|
||||||
pointer,
|
|
||||||
released,
|
|
||||||
cancel,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, Deserialize, Eq, Ord, PartialEq, PartialOrd, Serialize)]
|
#[derive(Clone, Debug, Deserialize, Eq, Ord, PartialEq, PartialOrd, Serialize)]
|
||||||
pub enum SelectionCombineMode {
|
pub enum SelectionCombineMode {
|
||||||
Replace,
|
Replace,
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ use crate::{
|
||||||
layout::LayerId,
|
layout::LayerId,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, Getters, Ord, PartialEq, PartialOrd)]
|
#[derive(Clone, Debug, Eq, Getters, PartialEq)]
|
||||||
pub struct SelectionInteractor {
|
pub struct SelectionInteractor {
|
||||||
origin: Vector2<i64>,
|
origin: Vector2<i64>,
|
||||||
original_selection: PersistableSelection,
|
original_selection: PersistableSelection,
|
||||||
|
|
@ -50,7 +50,7 @@ impl SelectionInteractor {
|
||||||
return Some(self.selection.clone());
|
return Some(self.selection.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
if input.released && input.pointer == self.origin {
|
if input.release && input.pointer == self.origin {
|
||||||
let mut selection = self.original_selection.clone();
|
let mut selection = self.original_selection.clone();
|
||||||
|
|
||||||
// Pins have intentional precedence over nets and components.
|
// Pins have intentional precedence over nets and components.
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MIT OR Apache-2.0
|
// SPDX-License-Identifier: MIT OR Apache-2.0
|
||||||
|
|
||||||
mod delete;
|
|
||||||
mod insert;
|
mod insert;
|
||||||
pub mod interactors;
|
pub mod interactors;
|
||||||
mod layer;
|
mod layer;
|
||||||
|
|
|
||||||
|
|
@ -5,15 +5,91 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
board::{Board, selections::ComponentSelection},
|
board::{Board, selections::ComponentSelection},
|
||||||
layout::compounds::ComponentId,
|
layout::compounds::ComponentId,
|
||||||
|
primitives::{JointId, PolygonId, SegmentId, ViaId},
|
||||||
|
selections::NetSelection,
|
||||||
};
|
};
|
||||||
|
|
||||||
impl Board {
|
impl Board {
|
||||||
pub fn resolve_components(&self, selection: ComponentSelection) -> Vec<ComponentId> {
|
pub fn resolve_components(
|
||||||
|
&self,
|
||||||
|
selection: ComponentSelection,
|
||||||
|
) -> impl Iterator<Item = ComponentId> {
|
||||||
selection
|
selection
|
||||||
.0
|
.0
|
||||||
.clone()
|
.clone()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter_map(|selector| self.component_id(&selector.component))
|
.filter_map(|selector| self.component_id(&selector.component))
|
||||||
.collect()
|
}
|
||||||
|
|
||||||
|
pub fn resolve_net_joints(&self, selection: NetSelection) -> impl Iterator<Item = JointId> {
|
||||||
|
let mut resolved_joints = Vec::new();
|
||||||
|
|
||||||
|
for (index, _) in self.layout.joints().container() {
|
||||||
|
let joint_id = JointId::new(index);
|
||||||
|
|
||||||
|
let Some(selector) = self.joint_net_selector(joint_id) else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
|
||||||
|
if selection.0.contains(&selector) {
|
||||||
|
resolved_joints.push(joint_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resolved_joints.into_iter()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn resolve_net_segments(&self, selection: NetSelection) -> impl Iterator<Item = SegmentId> {
|
||||||
|
let mut resolved_segments = Vec::new();
|
||||||
|
|
||||||
|
for (index, _) in self.layout.segments().container() {
|
||||||
|
let segment_id = SegmentId::new(index);
|
||||||
|
|
||||||
|
let Some(selector) = self.segment_net_selector(segment_id) else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
|
||||||
|
if selection.0.contains(&selector) {
|
||||||
|
resolved_segments.push(segment_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resolved_segments.into_iter()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn resolve_net_vias(&self, selection: NetSelection) -> impl Iterator<Item = ViaId> {
|
||||||
|
let mut resolved_vias = Vec::new();
|
||||||
|
|
||||||
|
for (index, _) in self.layout.vias().container() {
|
||||||
|
let via_id = ViaId::new(index);
|
||||||
|
|
||||||
|
let Some(selector) = self.via_net_selector(via_id) else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
|
||||||
|
if selection.0.contains(&selector) {
|
||||||
|
resolved_vias.push(via_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resolved_vias.into_iter()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn resolve_net_polygons(&self, selection: NetSelection) -> impl Iterator<Item = PolygonId> {
|
||||||
|
let mut resolved_polygons = Vec::new();
|
||||||
|
|
||||||
|
for (index, _) in self.layout.polygons().container() {
|
||||||
|
let polygon_id = PolygonId::new(index);
|
||||||
|
|
||||||
|
let Some(selector) = self.polygon_net_selector(polygon_id) else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
|
||||||
|
if selection.0.contains(&selector) {
|
||||||
|
resolved_polygons.push(polygon_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resolved_polygons.into_iter()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
use std::collections::BTreeSet;
|
use std::collections::BTreeSet;
|
||||||
|
|
||||||
use derive_more::Constructor;
|
use derive_more::{Constructor, IntoIterator};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(Clone, Constructor, Debug, Deserialize, Eq, Ord, PartialEq, PartialOrd, Serialize)]
|
#[derive(Clone, Constructor, Debug, Deserialize, Eq, Ord, PartialEq, PartialOrd, Serialize)]
|
||||||
|
|
@ -12,7 +12,9 @@ pub struct ComponentSelector {
|
||||||
pub component: String,
|
pub component: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default, Deserialize, Eq, Ord, PartialEq, PartialOrd, Serialize)]
|
#[derive(
|
||||||
|
Clone, Debug, Default, Deserialize, Eq, IntoIterator, Ord, PartialEq, PartialOrd, Serialize,
|
||||||
|
)]
|
||||||
pub struct ComponentSelection(pub BTreeSet<ComponentSelector>);
|
pub struct ComponentSelection(pub BTreeSet<ComponentSelector>);
|
||||||
|
|
||||||
impl ComponentSelection {
|
impl ComponentSelection {
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
use std::collections::BTreeSet;
|
use std::collections::BTreeSet;
|
||||||
|
|
||||||
|
use derive_more::IntoIterator;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default, Deserialize, Eq, Ord, PartialEq, PartialOrd, Serialize)]
|
#[derive(Clone, Debug, Default, Deserialize, Eq, Ord, PartialEq, PartialOrd, Serialize)]
|
||||||
|
|
@ -17,7 +18,9 @@ impl NetSelector {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default, Deserialize, Eq, Ord, PartialEq, PartialOrd, Serialize)]
|
#[derive(
|
||||||
|
Clone, Debug, Default, Deserialize, Eq, IntoIterator, Ord, PartialEq, PartialOrd, Serialize,
|
||||||
|
)]
|
||||||
pub struct NetSelection(pub BTreeSet<NetSelector>);
|
pub struct NetSelection(pub BTreeSet<NetSelector>);
|
||||||
|
|
||||||
impl NetSelection {
|
impl NetSelection {
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
use std::collections::BTreeSet;
|
use std::collections::BTreeSet;
|
||||||
|
|
||||||
use derive_more::Constructor;
|
use derive_more::{Constructor, IntoIterator};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(
|
#[derive(
|
||||||
|
|
@ -15,7 +15,9 @@ pub struct PinSelector {
|
||||||
pub layer: String,
|
pub layer: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default, Deserialize, Eq, Ord, PartialEq, PartialOrd, Serialize)]
|
#[derive(
|
||||||
|
Clone, Debug, Default, Deserialize, Eq, IntoIterator, Ord, PartialEq, PartialOrd, Serialize,
|
||||||
|
)]
|
||||||
pub struct PinSelection(pub BTreeSet<PinSelector>);
|
pub struct PinSelection(pub BTreeSet<PinSelector>);
|
||||||
|
|
||||||
impl PinSelection {
|
impl PinSelection {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
// SPDX-FileCopyrightText: 2026 Topola contributors
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MIT OR Apache-2.0
|
||||||
|
|
||||||
|
use crate::{Board, selections::NetSelection};
|
||||||
|
|
||||||
|
impl Board {
|
||||||
|
pub fn delete_net_free_primitives(&mut self, selection: NetSelection) {
|
||||||
|
for joint_id in self
|
||||||
|
.resolve_net_joints(selection.clone())
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.clone()
|
||||||
|
{
|
||||||
|
self.layout.delete_joint(joint_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
for segment_id in self
|
||||||
|
.resolve_net_segments(selection.clone())
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.clone()
|
||||||
|
{
|
||||||
|
self.layout.delete_segment(segment_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
for via_id in self
|
||||||
|
.resolve_net_vias(selection.clone())
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.clone()
|
||||||
|
{
|
||||||
|
self.layout.delete_via(via_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
for polygon_id in self
|
||||||
|
.resolve_net_polygons(selection.clone())
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.clone()
|
||||||
|
{
|
||||||
|
self.layout.delete_polygon(polygon_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -2,4 +2,5 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MIT OR Apache-2.0
|
// SPDX-License-Identifier: MIT OR Apache-2.0
|
||||||
|
|
||||||
|
mod delete;
|
||||||
mod move_by;
|
mod move_by;
|
||||||
|
|
|
||||||
|
|
@ -5,12 +5,11 @@
|
||||||
use crate::{Board, Vector2, layout::compounds::ComponentId, selections::ComponentSelection};
|
use crate::{Board, Vector2, layout::compounds::ComponentId, selections::ComponentSelection};
|
||||||
|
|
||||||
impl Board {
|
impl Board {
|
||||||
pub fn move_components_by(
|
pub fn move_components_by(&mut self, selection: ComponentSelection, translation: Vector2<i64>) {
|
||||||
&mut self,
|
self.move_resolved_components_by(
|
||||||
selection: &ComponentSelection,
|
&self.resolve_components(selection).collect::<Vec<_>>(),
|
||||||
translation: Vector2<i64>,
|
translation,
|
||||||
) {
|
);
|
||||||
self.move_resolved_components_by(&self.resolve_components(selection.clone()), translation);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn move_resolved_components_by(
|
pub fn move_resolved_components_by(
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,7 @@ use serde::{Deserialize, Serialize};
|
||||||
use crate::layout::LayerId;
|
use crate::layout::LayerId;
|
||||||
use crate::layout::compounds::{ComponentId, NetId, PinId};
|
use crate::layout::compounds::{ComponentId, NetId, PinId};
|
||||||
use crate::math::Vector2;
|
use crate::math::Vector2;
|
||||||
|
use crate::primitives::{SegmentId, ViaId};
|
||||||
use super::{SegmentId, ViaId};
|
|
||||||
|
|
||||||
#[derive(
|
#[derive(
|
||||||
Clone,
|
Clone,
|
||||||
|
|
|
||||||
|
|
@ -18,5 +18,6 @@ pub use via::*;
|
||||||
pub enum PrimitiveId {
|
pub enum PrimitiveId {
|
||||||
Joint(JointId),
|
Joint(JointId),
|
||||||
Segment(SegmentId),
|
Segment(SegmentId),
|
||||||
|
Via(ViaId),
|
||||||
Polygon(PolygonId),
|
Polygon(PolygonId),
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue