Skip to content

Commit

Permalink
feat(polygon): only show handles on hover
Browse files Browse the repository at this point in the history
  • Loading branch information
PaulHax committed May 2, 2024
1 parent 253d261 commit 7dc8823
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 17 deletions.
38 changes: 34 additions & 4 deletions src/components/tools/polygon/PolygonSVG2D.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
:stroke-width="strokeWidth"
fill="transparent"
:r="radius"
:visibility="index === 0 ? firstHandleVisibility : handleVisibility"
/>
<polyline
:points="linePoints"
Expand All @@ -24,14 +25,22 @@ import { onVTKEvent } from '@/src/composables/onVTKEvent';
import { ANNOTATION_TOOL_HANDLE_RADIUS } from '@/src/constants';
import { worldToSVG } from '@/src/utils/vtk-helpers';
import type { Vector2, Vector3 } from '@kitware/vtk.js/types';
import { PropType, defineComponent, toRefs, ref, watch, inject } from 'vue';
import {
PropType,
defineComponent,
toRefs,
ref,
watch,
inject,
computed,
} from 'vue';
import { Maybe } from '@/src/types';
import { VtkViewContext } from '@/src/components/vtk/context';
import { useResizeObserver } from '@vueuse/core';
import { vtkFieldRef } from '@/src/core/vtk/vtkFieldRef';
const POINT_RADIUS = ANNOTATION_TOOL_HANDLE_RADIUS;
const FINISHABLE_POINT_RADIUS = POINT_RADIUS + 6;
const FINISHABLE_POINT_RADIUS = POINT_RADIUS;
export default defineComponent({
props: {
Expand All @@ -52,13 +61,32 @@ export default defineComponent({
type: Boolean,
default: false,
},
showHandles: {
type: Boolean,
default: false,
},
},
setup(props) {
const { points, movePoint, placing, finishable } = toRefs(props);
const { points, movePoint, placing, finishable, showHandles } =
toRefs(props);
const view = inject(VtkViewContext);
if (!view) throw new Error('No VtkView');
const finishPossible = computed(() => {
return points.value.length > 0 && placing.value && finishable.value;
});
const handleVisibility = computed(() => {
return showHandles.value ? 'visible' : 'hidden';
});
const firstHandleVisibility = computed(() => {
if (finishPossible.value) {
return 'visible';
}
return handleVisibility.value;
});
type SVGPoint = { point: Vector2; radius: number };
const handlePoints = ref<Array<SVGPoint>>([]);
const linePoints = ref<string>('');
Expand All @@ -74,7 +102,7 @@ export default defineComponent({
});
// Indicate finishable
if (svgPoints.length > 0 && finishable.value && placing.value) {
if (finishPossible.value) {
svgPoints[0].radius = FINISHABLE_POINT_RADIUS;
}
Expand Down Expand Up @@ -117,6 +145,8 @@ export default defineComponent({
devicePixelRatio,
handlePoints,
linePoints,
firstHandleVisibility,
handleVisibility,
};
},
});
Expand Down
27 changes: 25 additions & 2 deletions src/components/tools/polygon/PolygonWidget2D.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,18 @@ import {
watchEffect,
inject,
onUnmounted,
ref,
} from 'vue';
import vtkPlaneManipulator from '@kitware/vtk.js/Widgets/Manipulators/PlaneManipulator';
import { useImage } from '@/src/composables/useCurrentImage';
import { updatePlaneManipulatorFor2DView } from '@/src/utils/manipulators';
import { LPSAxisDir } from '@/src/types/lps';
import { onVTKEvent } from '@/src/composables/onVTKEvent';
import {
useHoverEvent,
useRightClickContextMenu,
useWidgetVisibility,
} from '@/src/composables/annotationTool';
import { getCSSCoordinatesFromEvent } from '@/src/utils/vtk-helpers';
import { usePolygonStore as useStore } from '@/src/store/tools/polygons';
import vtkWidgetFactory, {
vtkPolygonViewWidget as WidgetView,
Expand Down Expand Up @@ -92,7 +93,27 @@ export default defineComponent({
emit('placed');
});
useHoverEvent(emit, widget);
const lastHoverEventData = ref<any>(null);
onVTKEvent(widget, 'onHoverEvent', (eventData: any) => {
lastHoverEventData.value = eventData;
});
const dragging = ref(false);
onVTKEvent(widget, 'onDraggingEvent', (eventData: any) => {
dragging.value = eventData.dragging;
});
const showHandles = computed(() => {
return lastHoverEventData.value?.hovering && !dragging.value;
});
watchEffect(() => {
if (!lastHoverEventData.value) return;
const displayXY = getCSSCoordinatesFromEvent(lastHoverEventData.value);
if (displayXY) {
emit('widgetHover', {
displayXY,
hovering: lastHoverEventData.value?.hovering && !dragging.value,
});
}
});
// --- right click handling --- //
Expand Down Expand Up @@ -134,6 +155,7 @@ export default defineComponent({
slice,
tool,
editState,
showHandles,
};
},
});
Expand All @@ -148,5 +170,6 @@ export default defineComponent({
:move-point="editState.movePoint"
:placing="tool.placing"
:finishable="editState.finishable"
:show-handles="showHandles"
/>
</template>
23 changes: 12 additions & 11 deletions src/vtk/PolygonWidget/behavior.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,13 @@ const DOUBLE_CLICK_SLIP_DISTANCE_MAX_SQUARED =

export default function widgetBehavior(publicAPI: any, model: any) {
model.classHierarchy.push('vtkPolygonWidgetBehavior');
model._isDragging = false;

const setDragging = (isDragging: boolean) => {
model._dragging = isDragging;
publicAPI.invokeDraggingEvent({
dragging: isDragging,
});
};

// overUnselectedHandle is true if mouse is over handle that was created before a mouse move event.
// That happens if creating new handle and immediately dragging.
Expand Down Expand Up @@ -52,6 +58,7 @@ export default function widgetBehavior(publicAPI: any, model: any) {
macro.event(publicAPI, model, 'RightClickEvent');
macro.event(publicAPI, model, 'PlacedEvent');
macro.event(publicAPI, model, 'HoverEvent');
macro.event(publicAPI, model, 'DraggingEvent');

publicAPI.resetInteractions = () => {
model._interactor.cancelAnimation(publicAPI, true);
Expand Down Expand Up @@ -123,7 +130,7 @@ export default function widgetBehavior(publicAPI: any, model: any) {
if (
worldCoords?.length &&
(model.activeState === model.widgetState.getMoveHandle() ||
model._isDragging)
model._dragging)
) {
model.activeState.setOrigin(worldCoords);

Expand Down Expand Up @@ -155,12 +162,6 @@ export default function widgetBehavior(publicAPI: any, model: any) {
publicAPI.handleLeftButtonPress = (event: vtkMouseEvent) => {
const activeWidget = model._widgetManager.getActiveWidget();

// turns off hover while dragging
publicAPI.invokeHoverEvent({
...event,
hovering: false,
});

if (
!model.manipulator ||
ignoreKey(event) ||
Expand Down Expand Up @@ -199,7 +200,7 @@ export default function widgetBehavior(publicAPI: any, model: any) {
}

if (model.activeState?.getActive() && model.pickable && model.dragable) {
model._isDragging = true;
setDragging(true);
model._apiSpecificRenderWindow.setCursor('grabbing');
model._interactor.requestAnimation(publicAPI);
publicAPI.invokeStartInteractionEvent();
Expand Down Expand Up @@ -287,10 +288,10 @@ export default function widgetBehavior(publicAPI: any, model: any) {

freeHanding = false;

if (model._isDragging) {
if (model._dragging) {
model._apiSpecificRenderWindow.setCursor('pointer');
model._interactor.cancelAnimation(publicAPI);
model._isDragging = false;
setDragging(false);
model._widgetManager.enablePicking();
// So a following left click without moving the mouse can immediately grab the handle,
// we don't call model.widgetState.deactivate() here.
Expand Down
1 change: 1 addition & 0 deletions src/vtk/PolygonWidget/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export interface vtkPolygonWidgetState extends vtkAnnotationWidgetState {

export interface vtkPolygonViewWidget extends vtkAnnotationToolWidget {
getWidgetState(): vtkPolygonWidgetState;
onDraggingEvent(callback: (e: any) => void): vtkSubscription;
}

export interface IPolygonWidgetInitialValues
Expand Down

0 comments on commit 7dc8823

Please sign in to comment.