Skip to content

Commit 83b461b

Browse files
committed
Add Export command to UI
1 parent 70c140a commit 83b461b

File tree

1 file changed

+130
-93
lines changed

1 file changed

+130
-93
lines changed

src/plugins.ts

Lines changed: 130 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
1-
import {
2-
ICollaborativeDrive,
3-
SharedDocumentFactory
4-
} from '@jupyter/collaborative-drive';
1+
// plugins.ts
2+
import { ICollaborativeDrive } from '@jupyter/collaborative-drive';
53
import {
64
IAnnotationModel,
75
IJCadWorkerRegistry,
@@ -17,8 +15,12 @@ import {
1715
import {
1816
IThemeManager,
1917
showErrorMessage,
18+
InputDialog,
19+
showDialog,
2020
WidgetTracker
2121
} from '@jupyterlab/apputils';
22+
import { IMainMenu } from '@jupyterlab/mainmenu';
23+
import { PathExt } from '@jupyterlab/coreutils';
2224
import { LabIcon } from '@jupyterlab/ui-components';
2325

2426
import { JupyterCadWidgetFactory } from '@jupytercad/jupytercad-core';
@@ -32,109 +34,144 @@ import { JupyterCadFCModelFactory } from './modelfactory';
3234
import freecadIconSvg from '../style/freecad.svg';
3335

3436
const freecadIcon = new LabIcon({
35-
name: 'jupytercad:stp',
37+
name: 'jupytercad:freecad',
3638
svgstr: freecadIconSvg
3739
});
3840

3941
const FACTORY = 'Jupytercad Freecad Factory';
40-
41-
class JupyterCadFCstdDoc extends JupyterCadDoc {
42-
toJcadEndpoint = 'jupytercad_freecad/export-jcad';
43-
toFcstdEndpoint = 'jupytercad_freecad/export-fcstd';
44-
}
45-
46-
const activate = async (
47-
app: JupyterFrontEnd,
48-
tracker: WidgetTracker<IJupyterCadWidget>,
49-
themeManager: IThemeManager,
50-
annotationModel: IAnnotationModel,
51-
drive: ICollaborativeDrive,
52-
workerRegistry: IJCadWorkerRegistry,
53-
externalCommandRegistry: IJCadExternalCommandRegistry
54-
): Promise<void> => {
55-
const fcCheck = await requestAPI<{ installed: boolean }>(
56-
'jupytercad_freecad/backend-check',
57-
{
58-
method: 'POST',
59-
body: JSON.stringify({
60-
backend: 'FreeCAD'
61-
})
62-
}
63-
);
64-
const { installed } = fcCheck;
65-
const backendCheck = () => {
66-
if (!installed) {
67-
showErrorMessage(
68-
'FreeCAD is not installed',
69-
'FreeCAD is required to open FCStd files'
70-
);
71-
}
72-
return installed;
73-
};
74-
const widgetFactory = new JupyterCadWidgetFactory({
75-
name: FACTORY,
76-
modelName: 'jupytercad-fcmodel',
77-
fileTypes: ['FCStd'],
78-
defaultFor: ['FCStd'],
79-
tracker,
80-
commands: app.commands,
81-
workerRegistry,
82-
externalCommandRegistry,
83-
backendCheck
84-
});
85-
86-
// Registering the widget factory
87-
app.docRegistry.addWidgetFactory(widgetFactory);
88-
89-
// Creating and registering the model factory for our custom DocumentModel
90-
const modelFactory = new JupyterCadFCModelFactory({ annotationModel });
91-
app.docRegistry.addModelFactory(modelFactory);
92-
// register the filetype
93-
app.docRegistry.addFileType({
94-
name: 'FCStd',
95-
displayName: 'FCStd',
96-
mimeTypes: ['application/octet-stream'],
97-
extensions: ['.FCStd', 'fcstd'],
98-
fileFormat: 'base64',
99-
contentType: 'FCStd',
100-
icon: freecadIcon
101-
});
102-
103-
const FCStdSharedModelFactory: SharedDocumentFactory = () => {
104-
return new JupyterCadFCstdDoc();
105-
};
106-
drive.sharedModelFactory.registerDocumentFactory(
107-
'FCStd',
108-
FCStdSharedModelFactory
109-
);
110-
111-
widgetFactory.widgetCreated.connect((sender, widget) => {
112-
widget.title.icon = freecadIcon;
113-
// Notify the instance tracker if restore data needs to update.
114-
widget.context.pathChanged.connect(() => {
115-
tracker.save(widget);
116-
});
117-
themeManager.themeChanged.connect((_, changes) =>
118-
widget.context.model.themeChanged.emit(changes)
119-
);
120-
121-
tracker.add(widget);
122-
app.shell.activateById('jupytercad::leftControlPanel');
123-
app.shell.activateById('jupytercad::rightControlPanel');
124-
});
125-
console.log('jupytercad:fcplugin is activated!');
126-
};
42+
const EXPORT_FCSTD_CMD = 'jupytercad:export-fcstd';
12743

12844
export const fcplugin: JupyterFrontEndPlugin<void> = {
12945
id: 'jupytercad:fcplugin',
13046
requires: [
13147
IJupyterCadDocTracker,
48+
IMainMenu,
13249
IThemeManager,
13350
IAnnotationToken,
13451
ICollaborativeDrive,
13552
IJCadWorkerRegistryToken,
13653
IJCadExternalCommandRegistryToken
13754
],
13855
autoStart: true,
139-
activate
56+
activate: async (
57+
app: JupyterFrontEnd,
58+
tracker: WidgetTracker<IJupyterCadWidget>,
59+
mainMenu: IMainMenu,
60+
themeManager: IThemeManager,
61+
annotationModel: IAnnotationModel,
62+
drive: ICollaborativeDrive,
63+
workerRegistry: IJCadWorkerRegistry,
64+
externalCommandRegistry: IJCadExternalCommandRegistry
65+
) => {
66+
const { installed } = await requestAPI<{ installed: boolean }>(
67+
'jupytercad_freecad/backend-check',
68+
{
69+
method: 'POST',
70+
body: JSON.stringify({ backend: 'FreeCAD' })
71+
}
72+
);
73+
const backendCheck = () => {
74+
if (!installed) {
75+
showErrorMessage(
76+
'FreeCAD is not installed',
77+
'FreeCAD is required to open or export FCStd files'
78+
);
79+
}
80+
return installed;
81+
};
82+
83+
const widgetFactory = new JupyterCadWidgetFactory({
84+
name: FACTORY,
85+
modelName: 'jupytercad-fcmodel',
86+
fileTypes: ['FCStd'],
87+
defaultFor: ['FCStd'],
88+
tracker,
89+
commands: app.commands,
90+
workerRegistry,
91+
externalCommandRegistry,
92+
backendCheck
93+
});
94+
app.docRegistry.addWidgetFactory(widgetFactory);
95+
96+
const modelFactory = new JupyterCadFCModelFactory({ annotationModel });
97+
app.docRegistry.addModelFactory(modelFactory);
98+
99+
app.docRegistry.addFileType({
100+
name: 'FCStd',
101+
displayName: 'FCStd',
102+
mimeTypes: ['application/octet-stream'],
103+
extensions: ['.FCStd', '.fcstd'],
104+
fileFormat: 'base64',
105+
contentType: 'FCStd',
106+
icon: freecadIcon
107+
});
108+
109+
drive.sharedModelFactory.registerDocumentFactory(
110+
'FCStd',
111+
(): JupyterCadDoc => new JupyterCadDoc()
112+
);
113+
114+
widgetFactory.widgetCreated.connect((_, widget) => {
115+
widget.title.icon = freecadIcon;
116+
widget.context.pathChanged.connect(() => tracker.save(widget));
117+
themeManager.themeChanged.connect((_, changes) =>
118+
widget.context.model.themeChanged.emit(changes)
119+
);
120+
app.shell.activateById('jupytercad::leftControlPanel');
121+
app.shell.activateById('jupytercad::rightControlPanel');
122+
tracker.add(widget);
123+
});
124+
125+
console.log('jupytercad:fcplugin is activated!');
126+
127+
app.commands.addCommand(EXPORT_FCSTD_CMD, {
128+
label: 'Export to .FCStd',
129+
iconClass: 'fa fa-file-export',
130+
isEnabled: () => {
131+
const w = tracker.currentWidget;
132+
return !!w && w.context.path.toLowerCase().endsWith('.jcad');
133+
},
134+
execute: async () => {
135+
const w = tracker.currentWidget;
136+
if (!w) {
137+
return;
138+
}
139+
const defaultName = PathExt.basename(w.context.path).replace(
140+
/\.[^.]+$/,
141+
'.FCStd'
142+
);
143+
const result = await InputDialog.getText({
144+
title: 'Export to .FCStd',
145+
placeholder: 'Output file name',
146+
text: defaultName
147+
});
148+
if (!result.value) {
149+
return;
150+
}
151+
try {
152+
const resp = await requestAPI<{ path?: string; done?: boolean }>(
153+
'jupytercad_freecad/export-fcstd',
154+
{
155+
method: 'POST',
156+
body: JSON.stringify({
157+
path: w.context.path,
158+
newName: result.value
159+
})
160+
}
161+
);
162+
const outPath = resp.path ?? result.value;
163+
await showDialog({
164+
title: 'Export successful',
165+
body: `Wrote file to: ${outPath}`
166+
});
167+
} catch (e: any) {
168+
showErrorMessage('Export Error', e.message || String(e));
169+
}
170+
}
171+
});
172+
173+
mainMenu.fileMenu.addGroup([{ command: EXPORT_FCSTD_CMD }], /* rank */ 100);
174+
}
140175
};
176+
177+
export default [fcplugin];

0 commit comments

Comments
 (0)