diff --git a/CHANGELOG.md b/CHANGELOG.md index 13eced13ac23a0834e0ea19c5f3e6dd52f86be8b..235642fa915b3a74fe6ccd501b7d7559eeebfc6f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,8 +7,11 @@ Note that since we don't clearly distinguish between a public and private interf ## [Unreleased] - Add ``bumpiness`` (per-object and per-group), ``bumpFrequency`` & ``bumpAmplitude`` (per-object) render parameters (#299) -- Change ``label`` representation defaults: Use text border instead of rectangle background. +- Change ``label`` representation defaults: Use text border instead of rectangle background - Add outline color option to renderer +- Fix false positives in Model.isFromPdbArchive +- Add drag and drop support for loading any file, including multiple at once + - If there are session files (.molx or .molj) among the dropped files, only the first session will be loaded ## [v3.0.0-dev.3] - 2021-12-4 diff --git a/src/mol-plugin-ui/plugin.tsx b/src/mol-plugin-ui/plugin.tsx index bcef3bc4456426c83a0505ef2c29aa2f71637952..f8835c46b3ee3bd36543db00f98fa6151787e66b 100644 --- a/src/mol-plugin-ui/plugin.tsx +++ b/src/mol-plugin-ui/plugin.tsx @@ -18,6 +18,8 @@ import { Toasts } from './toast'; import { Viewport, ViewportControls } from './viewport'; import { PluginCommands } from '../mol-plugin/commands'; import { PluginUIContext } from './context'; +import { OpenFiles } from '../mol-plugin-state/actions/file'; +import { Asset } from '../mol-util/assets'; export class Plugin extends React.Component<{ plugin: PluginUIContext }, {}> { region(kind: 'left' | 'right' | 'bottom' | 'main', element: JSX.Element) { @@ -102,22 +104,34 @@ class Layout extends PluginUIComponent { onDrop = (ev: React.DragEvent<HTMLDivElement>) => { ev.preventDefault(); - let file: File | undefined | null; + const files: File[] = []; if (ev.dataTransfer.items) { // Use DataTransferItemList interface to access the file(s) for (let i = 0; i < ev.dataTransfer.items.length; i++) { if (ev.dataTransfer.items[i].kind !== 'file') continue; - file = ev.dataTransfer.items[i].getAsFile(); - break; + const file = ev.dataTransfer.items[i].getAsFile(); + if (file) files.push(file); } } else { - file = ev.dataTransfer.files[0]; + for (let i = 0; i < ev.dataTransfer.files.length; i++) { + const file = ev.dataTransfer.files[0]; + if (file) files.push(file); + } } - if (!file) return; - const fn = file?.name.toLowerCase() || ''; - if (fn.endsWith('molx') || fn.endsWith('molj')) { - PluginCommands.State.Snapshots.OpenFile(this.plugin, { 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(this.plugin, { file: sessions[0] }); + } else { + this.plugin.runTask(this.plugin.state.data.applyAction(OpenFiles, { + files: files.map(f => Asset.File(f)), + format: { name: 'auto', params: {} }, + visuals: true + })); } }