Explorar o código

Add DragAndDropManager (#968)

* Add PluginContext.customDragAndDropHandlers

* refactor to manager
David Sehnal hai 1 ano
pai
achega
975cceed77

+ 1 - 0
CHANGELOG.md

@@ -11,6 +11,7 @@ Note that since we don't clearly distinguish between a public and private interf
 - Improve `distinctColors` function
     - Add `sort` and `sampleCountFactor` parameters
     - Fix clustering issues
+- Add `DragAndDropManager`
 - Add `options` support for default bond labels
 
 ## [v3.41.0] - 2023-10-15

+ 8 - 0
src/examples/basic-wrapper/index.ts

@@ -46,6 +46,14 @@ class BasicWrapper {
         this.plugin.representation.structure.themes.colorThemeRegistry.add(CustomColorThemeProvider);
         this.plugin.managers.lociLabels.addProvider(StripedResidues.labelProvider!);
         this.plugin.customModelProperties.register(StripedResidues.propertyProvider, true);
+
+        this.plugin.managers.dragAndDrop.addHandler('custom-wrapper', (files) => {
+            if (files.some(f => f.name.toLowerCase().endsWith('.testext'))) {
+                console.log('.testext File dropped');
+                return true;
+            }
+            return false;
+        });
     }
 
     async load({ url, format = 'mmcif', isBinary = false, assemblyId = '' }: LoadParams) {

+ 58 - 0
src/mol-plugin-state/manager/drag-and-drop.ts

@@ -0,0 +1,58 @@
+/**
+ * Copyright (c) 2023 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * @author David Sehnal <david.sehnal@gmail.com>
+ */
+
+
+import { OpenFiles } from '../actions/file';
+import { Asset } from '../../mol-util/assets';
+import { PluginCommands } from '../../mol-plugin/commands';
+import { PluginContext } from '../../mol-plugin/context';
+
+export type PluginDragAndDropHandler = (files: File[], plugin: PluginContext) => Promise<boolean> | boolean
+
+export class DragAndDropManager {
+    private handlers: [name: string, handler: PluginDragAndDropHandler][] = [];
+
+    addHandler(name: string, handler: PluginDragAndDropHandler) {
+        const index = this.handlers.findIndex(h => h[0] === name);
+        if (index < 0) this.handlers.push([name, handler]);
+        else this.handlers[index][1] = handler;
+    }
+
+    removeHandler(name: string) {
+        const index = this.handlers.findIndex(h => h[0] === name);
+        if (index >= 0) this.handlers.splice(index, 1);
+    }
+
+    async handle(files: File[]) {
+        for (let i = this.handlers.length - 1; i >= 0; i--) {
+            const handler = this.handlers[i][1];
+            const handled = await handler(files, this.plugin);
+            if (handled) return;
+        }
+
+        defaultDragAndDropHandler(this.plugin, files);
+    }
+
+    constructor(public plugin: PluginContext) {
+    }
+}
+
+function defaultDragAndDropHandler(plugin: PluginContext, files: File[]) {
+    const sessions = files.filter(f => {
+        const fn = f.name.toLowerCase();
+        return fn.endsWith('.molx') || fn.endsWith('.molj');
+    });
+
+    if (sessions.length > 0) {
+        PluginCommands.State.Snapshots.OpenFile(plugin, { file: sessions[0] });
+    } else {
+        plugin.runTask(plugin.state.data.applyAction(OpenFiles, {
+            files: files.map(f => Asset.File(f)),
+            format: { name: 'auto', params: {} },
+            visuals: true
+        }));
+    }
+}

+ 1 - 14
src/mol-plugin-ui/plugin.tsx

@@ -211,20 +211,7 @@ function dropFiles(ev: React.DragEvent<HTMLDivElement>, plugin: PluginUIContext,
         }
     }
 
-    const sessions = files.filter(f => {
-        const fn = f.name.toLowerCase();
-        return fn.endsWith('.molx') || fn.endsWith('.molj');
-    });
-
-    if (sessions.length > 0) {
-        PluginCommands.State.Snapshots.OpenFile(plugin, { file: sessions[0] });
-    } else {
-        plugin.runTask(plugin.state.data.applyAction(OpenFiles, {
-            files: files.map(f => Asset.File(f)),
-            format: { name: 'auto', params: {} },
-            visuals: true
-        }));
-    }
+    plugin.managers.dragAndDrop.handle(files);
 }
 
 function DragOverlay({ plugin, showDragOverlay }: { plugin: PluginUIContext, showDragOverlay: BehaviorSubject<boolean> }) {

+ 3 - 1
src/mol-plugin/context.ts

@@ -61,6 +61,7 @@ import { PluginToastManager } from './util/toast';
 import { ViewportScreenshotHelper } from './util/viewport-screenshot';
 import { PLUGIN_VERSION, PLUGIN_VERSION_DATE } from './version';
 import { setSaccharideCompIdMapType } from '../mol-model/structure/structure/carbohydrates/constants';
+import { DragAndDropManager } from '../mol-plugin-state/manager/drag-and-drop';
 
 export type PluginInitializedState =
     | { kind: 'no' }
@@ -186,7 +187,8 @@ export class PluginContext {
         lociLabels: void 0 as any as LociLabelManager,
         toast: new PluginToastManager(this),
         asset: new AssetManager(),
-        task: new TaskManager()
+        task: new TaskManager(),
+        dragAndDrop: new DragAndDropManager(this),
     } as const;
 
     readonly events = {