Skip to content

Commit

Permalink
Delete Object Keyboard Shortcut (#388)
Browse files Browse the repository at this point in the history
* #46 Define function to `handleRemoveObject`

* #46 Bring `handleRemoveObject` in commands

* `Ctrl` + `X` keybinding to remove object

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Add handling if no object is selected

* `[Delete]` Keybinding & Enable it on ObjectTree too

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
  • Loading branch information
arjxn-py and pre-commit-ci[bot] authored Jul 30, 2024
1 parent 0e44856 commit fb39912
Show file tree
Hide file tree
Showing 4 changed files with 119 additions and 41 deletions.
47 changes: 47 additions & 0 deletions packages/base/src/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
ISelection,
Parts
} from '@jupytercad/schema';
import { CommandRegistry } from '@lumino/commands';
import { JupyterFrontEnd } from '@jupyterlab/application';
import { showErrorMessage, WidgetTracker } from '@jupyterlab/apputils';
import { ITranslator } from '@jupyterlab/translation';
Expand All @@ -33,9 +34,11 @@ import {
chamferIcon,
filletIcon
} from './tools';
import keybindings from './keybindings.json';
import { JupyterCadPanel, JupyterCadWidget } from './widget';
import { DocumentRegistry } from '@jupyterlab/docregistry';
import { PathExt } from '@jupyterlab/coreutils';
import { handleRemoveObject } from './panelview';

export function newName(type: string, model: IJupyterCadModel): string {
const sharedModel = model.sharedModel;
Expand Down Expand Up @@ -638,6 +641,22 @@ const EXPORT_FORM = {
}
};

function loadKeybindings(commands: CommandRegistry, keybindings: any[]) {
keybindings.forEach(binding => {
commands.addKeyBinding({
command: binding.command,
keys: binding.keys,
selector: binding.selector
});
});
}

function getSelectedObjectId(widget: JupyterCadWidget): string {
const selected =
widget.context.model.sharedModel.awareness.getLocalState()?.selected;
return selected ? Object.keys(selected.value)[0] : '';
}

/**
* Add the FreeCAD commands to the application's command registry.
*/
Expand Down Expand Up @@ -714,6 +733,31 @@ export function addCommands(
}
});

commands.addCommand(CommandIDs.removeObject, {
label: trans.__('Remove Object'),
isEnabled: () => {
const current = tracker.currentWidget;
return current ? current.context.model.sharedModel.editable : false;
},
execute: () => {
const current = tracker.currentWidget;
if (!current) {
return;
}

const objectId = getSelectedObjectId(current);
if (!objectId) {
console.warn('No object is selected.');
return;
}
const sharedModel = current.context.model.sharedModel;

handleRemoveObject(objectId, sharedModel, () =>
sharedModel.awareness.setLocalStateField('selected', {})
);
}
});

commands.addCommand(CommandIDs.newBox, {
label: trans.__('New Box'),
isEnabled: () => {
Expand Down Expand Up @@ -953,6 +997,7 @@ export function addCommands(
await dialog.launch();
}
});
loadKeybindings(commands, keybindings);
}

/**
Expand All @@ -964,6 +1009,8 @@ export namespace CommandIDs {

export const newSketch = 'jupytercad:sketch';

export const removeObject = 'jupytercad:removeObject';

export const newBox = 'jupytercad:newBox';
export const newCylinder = 'jupytercad:newCylinder';
export const newSphere = 'jupytercad:newSphere';
Expand Down
12 changes: 12 additions & 0 deletions packages/base/src/keybindings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[
{
"command": "jupytercad:removeObject",
"keys": ["Delete"],
"selector": ".jp-jupytercad-panel"
},
{
"command": "jupytercad:removeObject",
"keys": ["Delete"],
"selector": ".jpcad-treeview-wrapper"
}
]
94 changes: 54 additions & 40 deletions packages/base/src/panelview/objecttree.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,47 @@ interface IProps {
cpModel: IControlPanelModel;
}

export const handleRemoveObject = (
objectId: string,
sharedModel: any,
syncSelected: () => void
): void => {
if (!sharedModel) {
return;
}

const dependants = sharedModel.getDependants(objectId);

let body: React.JSX.Element;
if (dependants.length) {
body = (
<div>
{'Removing this object will also result in removing:'}
<ul>
{dependants.map(dependant => (
<li key={dependant}>{dependant}</li>
))}
</ul>
</div>
);
} else {
body = <div>Are you sure?</div>;
}

showDialog({
title: `Removing ${objectId}`,
body,
buttons: [Dialog.okButton(), Dialog.cancelButton()]
}).then(({ button: { accept } }) => {
if (accept) {
const toRemove = dependants.concat([objectId]);
sharedModel.removeObjects(toRemove);
}
});

syncSelected();
};

class ObjectTreeReact extends React.Component<IProps, IStates> {
constructor(props: IProps) {
super(props);
Expand Down Expand Up @@ -265,6 +306,17 @@ class ObjectTreeReact extends React.Component<IProps, IStates> {
this.setState(old => ({ ...old, options: sender.options }));
};

private _handleRemoveObject = (objectId: string): void => {
const sharedModel = this.props.cpModel.jcadModel?.sharedModel;
if (!sharedModel) {
return;
}

handleRemoveObject(objectId, sharedModel, () => {
this.props.cpModel.jcadModel?.syncSelected({});
});
};

render(): React.ReactNode {
const { selectedNodes, openNodes, options } = this.state;
const data = this.stateToTree();
Expand All @@ -278,7 +330,7 @@ class ObjectTreeReact extends React.Component<IProps, IStates> {
}

return (
<div className="jpcad-treeview-wrapper">
<div className="jpcad-treeview-wrapper" tabIndex={0}>
<ReactTree
multiSelect={true}
nodes={data}
Expand Down Expand Up @@ -394,45 +446,7 @@ class ObjectTreeReact extends React.Component<IProps, IStates> {
className={'jp-ToolbarButtonComponent'}
onClick={() => {
const objectId = opts.node.parentId as string;
const sharedModel =
this.props.cpModel.jcadModel?.sharedModel;
if (!sharedModel) {
return;
}

const dependants =
sharedModel.getDependants(objectId);

let body: React.JSX.Element;
if (dependants.length) {
body = (
<div>
{
'Removing this object will also result in removing:'
}
<ul>
{dependants.map(dependant => (
<li>{dependant}</li>
))}
</ul>
</div>
);
} else {
body = <div>Are you sure?</div>;
}

showDialog({
title: `Removing ${objectId}`,
body,
buttons: [Dialog.okButton(), Dialog.cancelButton()]
}).then(({ button: { accept } }) => {
if (accept) {
const toRemove = dependants.concat([objectId]);
sharedModel.removeObjects(toRemove);
}
});

this.props.cpModel.jcadModel?.syncSelected({});
this._handleRemoveObject(objectId);
}}
icon={closeIcon}
/>
Expand Down
7 changes: 6 additions & 1 deletion packages/base/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,10 @@
"outDir": "lib",
"rootDir": "src"
},
"include": ["src/**/*", "src/schema/*.json", "src/_interface/*.json"]
"include": [
"src/**/*",
"src/schema/*.json",
"src/_interface/*.json",
"src/*.json"
]
}

0 comments on commit fb39912

Please sign in to comment.