diff --git a/web/app/sketcher/components/SketchObjectExplorer.jsx b/web/app/sketcher/components/SketchObjectExplorer.jsx
index 45c2c9a7..fdb74aa4 100644
--- a/web/app/sketcher/components/SketchObjectExplorer.jsx
+++ b/web/app/sketcher/components/SketchObjectExplorer.jsx
@@ -3,30 +3,75 @@ import cx from 'classnames';
import ls from './SketchObjectExplorer.less'
import connect from 'ui/connect';
+import {combine} from 'lstream';
+import mapContext from '../../../../modules/ui/mapContext';
-@connect(streams => streams.sketcherApp.objects.map(objects => ({objects})))
+@connect(streams => combine(streams.sketcherApp.objects, streams.sketcherApp.selection)
+ .map(([objects, selection]) => ({
+ objects,
+ selection
+ })))
+@mapContext(ctx => ({
+ select: (obj, exclusive) => {
+ let viewer = ctx.services.sketcher.inPlaceEditor.viewer;
+ viewer.select([obj], exclusive);
+ viewer.refresh();
+ },
+ deselect: obj => {
+ let viewer = ctx.services.sketcher.inPlaceEditor.viewer;
+ viewer.deselect(obj);
+ viewer.refresh();
+ },
+ setRole: (obj, role) => {
+ let viewer = ctx.services.sketcher.inPlaceEditor.viewer;
+ if (obj.aux) {
+ return;
+ }
+ obj.role = role;
+ viewer.refresh();
+ }
+}))
export class SketchObjectExplorer extends React.Component {
render() {
const {objects} = this.props;
return
- {objects.map(o =>
+ {objects.map(o =>

- {getObjectRole(o)}
-
{o.simpleClassName}
-
{o.id}
-
+ {this.getObjectRole(o)}
+
this.tweakSelection(o, e.shiftKey)} className={cx(ls.objectTag, o.marked&&ls.selected)}>{o.simpleClassName} {o.id}
+
...
)}
}
-}
-function getObjectRole(o) {
- if (o.aux) {
- return
B
- } else if (o.role) {
- return
B
+ tweakSelection(obj, shiftKey) {
+ if (obj.marked) {
+ this.props.deselect(obj);
+ } else {
+ this.props.select(obj, !shiftKey);
+ }
}
+
+ tweakRole(obj) {
+ if (obj.role === 'construction') {
+ this.props.setRole(obj, null);
+ } else if (obj.role === null) {
+ this.props.setRole(obj, 'construction');
+ }
+ this.forceUpdate();
+ }
+
+ getObjectRole(o) {
+ if (o.aux) {
+ return
B
+ } else if (o.role === 'construction') {
+ return
this.tweakRole(o)} title="construction object not used for 3D operations" className={cx(ls.objectRole, ls.construction)}>C
+ } else {
+ return
this.tweakRole(o)} title="sketch object participates in 3D operations" className={cx(ls.objectRole, ls.sketch)}>S
+ }
+ }
+
}
function ObjectIcon({object}) {
diff --git a/web/app/sketcher/components/SketchObjectExplorer.less b/web/app/sketcher/components/SketchObjectExplorer.less
index 650c499f..aea4b917 100644
--- a/web/app/sketcher/components/SketchObjectExplorer.less
+++ b/web/app/sketcher/components/SketchObjectExplorer.less
@@ -1,25 +1,71 @@
+@itemRadius: 5px;
+
+.button {
+ cursor: pointer;
+ &:hover {
+ background-color: #0074D9;
+ }
+ &:active {
+ background-color: #000d7f;
+ }
+}
+
.objectItem {
background-color: rgba(0,0,0, 0.6);
border: 1px solid #000;
border-radius: 5px;
- padding: 3px 5px;
- margin: 2px 5px;
+ margin: 2px @itemRadius;
pointer-events: auto;
display: flex;
- align-items: center;
+ align-items: stretch;
+
@alt-color: #9c9c9c;
.objectIcon {
+ border-radius: @itemRadius 0 0 @itemRadius;
+ padding: 3px 3px;
background-color: @alt-color;
}
.menuButton {
+ border-radius: 0 @itemRadius @itemRadius 0;
background-color: @alt-color;
+ padding: 0 3px;
+ .button;
}
.objectTag {
- display: inline-block;
- padding: 0 2px;
+ display: flex;
+ align-items: center;
+ flex: 1;
+ padding: 0 5px;
+ .button;
+
+ &.selected {
+ background: linear-gradient(#59acff, #0074D9);
+ }
+ }
+
+ .objectRole {
+ display: flex;
+ align-items: center;
+ padding: 0 8px;
+ }
+
+ .objectRole.construction {
+ cursor: pointer;
+ background-color: #7c7c7c;
+ .button;
+ }
+ .objectRole.sketch {
+ cursor: pointer;
+ background-color: #5f5f5f;
+ .button;
+ }
+ .objectRole.aux {
+ cursor: default;
+ background-color: #FDF7E7;
+ color: #1a1a1a;
}
}
diff --git a/web/app/sketcher/io.js b/web/app/sketcher/io.js
index e23e6599..142c4d52 100644
--- a/web/app/sketcher/io.js
+++ b/web/app/sketcher/io.js
@@ -106,8 +106,8 @@ IO.prototype._loadSketch = function(sketch) {
var role = obj['role'];
//support legacy format
- if (!role && layerName === '_construction_') {
- role = 'construction';
+ if (!role) {
+ role = layerName === '_construction_' ? 'construction' : null;
}
if (boundaryProcessing) {
diff --git a/web/app/sketcher/sketcherStreams.js b/web/app/sketcher/sketcherStreams.js
index dca57ecd..c4a78e65 100644
--- a/web/app/sketcher/sketcherStreams.js
+++ b/web/app/sketcher/sketcherStreams.js
@@ -12,6 +12,8 @@ export default function(viewer) {
}).remember([]);
streams.addingRoleMode = state(null);
+ streams.selection = state([]);
+ streams.objectUpdate = stream();
return streams;
};
\ No newline at end of file
diff --git a/web/app/sketcher/viewer2d.js b/web/app/sketcher/viewer2d.js
index 51e64d34..b6d2ba51 100644
--- a/web/app/sketcher/viewer2d.js
+++ b/web/app/sketcher/viewer2d.js
@@ -381,6 +381,7 @@ class Viewer {
if (this.selected.indexOf(obj) == -1) {
this.selected.push(obj);
+ this.streams.selection.next(this.selected);
}
};
@@ -426,6 +427,7 @@ class Viewer {
break;
}
}
+ this.streams.selection.next(this.selected);
};
deselectAll() {
@@ -433,6 +435,7 @@ class Viewer {
this.selected[i].marked = null;
}
while (this.selected.length > 0) this.selected.pop();
+ this.streams.selection.next(this.selected);
};
equalizeLinkedEndpoints() {