mirror of
https://github.com/molstar/molstar.git
synced 2026-06-04 13:30:24 +08:00
Fix Markdown Commands query focus (#1626)
This commit is contained in:
@@ -23,11 +23,11 @@ Generally, the command should be URL encoded, e.g., `a b` => `a%20b` (in JS, `en
|
||||
- `focus-refs=ref1,ref2,...` - On click, focuses nodes with the provided refs
|
||||
- `highlight-refs=ref1,ref2,...` - On mouse over, highlights the provided refs
|
||||
- `query=...&lang=...&action=highlight,focus&focus-radius=...`
|
||||
- `query` is an expression (e.g., `resn HEM` when using PyMol syntax)
|
||||
- (optional) `lang` is one of `mol-script` (default), `pymol`, `vmd`, `jmol`
|
||||
- (optional) `action` is an array of `highlight` (default), `focus` (multiple actions can be specified)
|
||||
- (optional) `focus-radius` is extra distance applied when focusing the selection (default is `3`)
|
||||
- Example: `[HEM](!query%3Dresn%20HEM%26lang%3Dpymol%26action%3Dhighlight%2Cfocus)` highlights or focuses the HEM residue (the command must be URL encoded because it contains spaces and possibly other special characters)
|
||||
- `query` is an expression (e.g., `resn HEM` when using PyMol syntax)
|
||||
- (optional) `lang` is one of `mol-script` (default), `pymol`, `vmd`, `jmol`
|
||||
- (optional) `action` is an array of `highlight` (default), `focus` (multiple actions can be specified)
|
||||
- (optional) `focus-radius` is extra distance applied when focusing the selection (default is `3`)
|
||||
- Example: `[HEM](!query=resn%20HEM%26lang=pymol&action=highlight,focus)` highlights or focuses the HEM residue (the query must be URL encoded because it contains spaces and possibly other special characters)
|
||||
- `play-audio=src`, `toggle-audio[=str]`, `stop-audio`, `pause-audio` - Audio playback support
|
||||
|
||||
## Custom Content
|
||||
@@ -37,11 +37,11 @@ Extends Markdown Image syntax to support expressions of the form `
|
||||
- `color-palette-colors=color1,color2` - Renders a gradient with the provided colors
|
||||
- `color-palette-width=CCS-value` - Specifies the width of the element, defaults to `150px`
|
||||
- `color-palette-height=CCS-value` - Specified the height of the element, defaults to `0.5em`
|
||||
- `color-palette-discrete` - Renders discrete color list instead of interpolating
|
||||
- `color-palette-name=name` - Renders a gradient with the provided named color palette (see `mol-util/color/lists.ts` for supported color schemes)
|
||||
- `color-palette-colors=color1,color2` - Renders a gradient with the provided colors
|
||||
- `color-palette-width=CCS-value` - Specifies the width of the element, defaults to `150px`
|
||||
- `color-palette-height=CCS-value` - Specified the height of the element, defaults to `0.5em`
|
||||
- `color-palette-discrete` - Renders discrete color list instead of interpolating
|
||||
|
||||
|
||||
## Example
|
||||
|
||||
@@ -13,7 +13,7 @@ import { Loci } from '../../../mol-model/loci';
|
||||
import { Structure } from '../../../mol-model/structure';
|
||||
import { PluginContext } from '../../../mol-plugin/context';
|
||||
import { PluginState } from '../../../mol-plugin/state';
|
||||
import { StateObject, StateTransform } from '../../../mol-state';
|
||||
import { StateObjectCell, StateSelection, StateTransform } from '../../../mol-state';
|
||||
import { PluginStateObject } from '../../objects';
|
||||
|
||||
|
||||
@@ -65,7 +65,7 @@ export function getCellBoundingSphere(plugin: PluginContext, cellRef: StateTrans
|
||||
/** Push bounding spheres within cell `cellRef` to `out`. If a cell does not define bounding spheres, collect bounding spheres from subtree. */
|
||||
function collectCellBoundingSpheres(out: Sphere3D[], plugin: PluginContext, cellRef: StateTransform.Ref): Sphere3D[] {
|
||||
const cell = plugin.state.data.cells.get(cellRef);
|
||||
const spheres = getStateObjectBoundingSpheres(cell?.obj);
|
||||
const spheres = getStateObjectBoundingSpheres(plugin, cell);
|
||||
if (spheres) {
|
||||
out.push(...spheres);
|
||||
} else {
|
||||
@@ -76,14 +76,17 @@ function collectCellBoundingSpheres(out: Sphere3D[], plugin: PluginContext, cell
|
||||
}
|
||||
|
||||
/** Return a set of bounding spheres of a plugin state object. Return `undefined` if this plugin state object type does not define bounding spheres. */
|
||||
function getStateObjectBoundingSpheres(obj: StateObject | undefined): Sphere3D[] | undefined {
|
||||
function getStateObjectBoundingSpheres(plugin: PluginContext, cell: StateObjectCell | undefined): Sphere3D[] | undefined {
|
||||
const obj = cell?.obj;
|
||||
if (!obj) return undefined;
|
||||
if (!obj.data) {
|
||||
console.warn('Focus: no data');
|
||||
return undefined;
|
||||
}
|
||||
if (obj.data instanceof Structure) {
|
||||
const sphere = Loci.getBoundingSphere(Structure.Loci(obj.data));
|
||||
const decorated = StateSelection.getDecorated<PluginStateObject.Molecule.Structure>(plugin.state.data, cell.transform.ref);
|
||||
const data = decorated?.obj?.data ?? obj?.data;
|
||||
const sphere = Loci.getBoundingSphere(Structure.Loci(data));
|
||||
return sphere ? [sphere] : [];
|
||||
} else if (PluginStateObject.isRepresentation3D(obj)) {
|
||||
const out: Sphere3D[] = [];
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
import { getCellBoundingSphere } from '../../mol-plugin-state/manager/focus-camera/focus-object';
|
||||
import { PluginStateObject } from '../../mol-plugin-state/objects';
|
||||
import { StateObjectCell } from '../../mol-state';
|
||||
import { StateObjectCell, StateSelection } from '../../mol-state';
|
||||
import { PluginContext } from '../../mol-plugin/context';
|
||||
import { Script } from '../../mol-script/script';
|
||||
import { QueryContext, QueryFn, StructureElement, StructureSelection } from '../../mol-model/structure';
|
||||
@@ -136,7 +136,8 @@ export const BuiltInMarkdownExtension: MarkdownExtension[] = [
|
||||
if (!action.includes('focus')) {
|
||||
return;
|
||||
}
|
||||
const spheres = structures.map(s => {
|
||||
const decorated = structures.map(s => StateSelection.getDecorated<PluginStateObject.Molecule.Structure>(manager.plugin.state.data, s.transform.ref));
|
||||
const spheres = decorated.map(s => {
|
||||
if (!s.obj?.data) return undefined;
|
||||
const selection = query(new QueryContext(s.obj.data));
|
||||
if (StructureSelection.isEmpty(selection)) return;
|
||||
|
||||
@@ -375,6 +375,14 @@ namespace StateSelection {
|
||||
const first = children.first();
|
||||
if (first && state.transforms.get(first).transformer.definition.isDecorator) return tryFindDecorator(state, first, transformer);
|
||||
}
|
||||
|
||||
export function getDecorated<T extends StateObject>(state: State, root: StateTransform.Ref): StateObjectCell<T> {
|
||||
const children = state.tree.children.get(root);
|
||||
if (children.size !== 1) return state.cells.get(root) as any;
|
||||
const first = children.first();
|
||||
if (first && state.transforms.get(first).transformer.definition.isDecorator) return getDecorated(state, first);
|
||||
return state.cells.get(root) as any;
|
||||
}
|
||||
}
|
||||
|
||||
export { StateSelection };
|
||||
Reference in New Issue
Block a user