Skip to content
Snippets Groups Projects
Select Git revision
  • 4624b6f969685736d1e9762985d438f12e671f15
  • mui5-annotation-on-video-stable default
  • get_setter_canvasSizeInformations
  • fix-error-div-into-p
  • annotation-on-video-v2
  • detached
  • annotation-on-video-r17
  • mui5
  • mui5-react-18
  • jacob-test
  • annotation-on-video protected
  • master
  • test-antoinev1
  • 20-fetch-thumbnail-on-annotation
  • add-research-field
  • Save
  • add-plugin
  • 14-wip-no-seek-to
  • 14-bug-on-video-time-control
  • 9_wip_videotests
  • _upgrade_material_ui
  • latest-tetras-16
  • v3.3.0
  • v3.2.0
  • v3.1.1
  • v3.1.0
  • v3.0.0
  • v3.0.0-rc.7
  • v3.0.0-rc.6
  • v3.0.0-rc.5
  • v3.0.0-rc.4
  • v3.0.0-rc.3
  • v3.0.0-rc.2
  • v3.0.0-rc.1
  • v3.0.0-beta.10
  • v3.0.0-beta.9
  • v3.0.0-beta.8
  • v3.0.0-beta.7
  • v3.0.0-beta.6
  • v3.0.0-beta.5
  • v3.0.0-beta.3
41 results

CollectionDialog.js

Blame
  • ThumbnailNavigation.js 6.72 KiB
    import React, { Component } from 'react';
    import PropTypes from 'prop-types';
    import Paper from '@material-ui/core/Paper';
    import AutoSizer from 'react-virtualized-auto-sizer';
    import { VariableSizeList as List } from 'react-window';
    import classNames from 'classnames';
    import CanvasWorld from '../lib/CanvasWorld';
    import ThumbnailCanvasGrouping from '../containers/ThumbnailCanvasGrouping';
    import ns from '../config/css-ns';
    
    /**
     */
    export class ThumbnailNavigation extends Component {
      /**
       */
      constructor(props) {
        super(props);
    
        this.scrollbarSize = 15;
        this.spacing = 8; // 2 * (2px margin + 2px border + 2px padding + 2px padding)
        this.calculateScaledSize = this.calculateScaledSize.bind(this);
        this.itemCount = this.itemCount.bind(this);
        this.handleKeyUp = this.handleKeyUp.bind(this);
        this.nextCanvas = this.nextCanvas.bind(this);
        this.previousCanvas = this.previousCanvas.bind(this);
        this.gridRef = React.createRef();
      }
    
      /**
       * If the view has changed and the thumbnailNavigation is open, recompute all
       * of the grids
       */
      componentDidUpdate(prevProps) {
        const { canvasIndex, position, view } = this.props;
        if (prevProps.view !== view && position !== 'off') {
          this.gridRef.current.resetAfterIndex(0);
        }
        if (prevProps.canvasIndex !== canvasIndex) {
          let index = canvasIndex;
          if (view === 'book') index = Math.ceil(index / 2);
          this.gridRef.current.scrollToItem(index, 'center');
        }
      }
    
      /**
       * When on right, row height
       * When on bottom, column width
       */
      calculateScaledSize(index) {
        const { thumbnailNavigation, canvasGroupings, position } = this.props;
        const canvases = canvasGroupings.groupings()[index];
        const world = new CanvasWorld(canvases);
        const bounds = world.worldBounds();
        switch (position) {
          case 'far-right': {
            const calc = Math.floor(
              this.calculatingWidth(canvases.length) * bounds[3] / bounds[2],
            );
            if (!Number.isInteger(calc)) return thumbnailNavigation.width + this.spacing;
            return calc + this.spacing;
          }
          // Default case bottom
          default: {
            if (bounds[3] === 0) return thumbnailNavigation.width + this.spacing;
            const calc = Math.ceil(
              (thumbnailNavigation.height - this.scrollbarSize - this.spacing - 4)
               * bounds[2] / bounds[3],
            );
            return calc;
          }
        }
      }
    
      /** */
      calculatingWidth(canvasesLength) {
        const { thumbnailNavigation } = this.props;
        if (canvasesLength === 1) {
          return thumbnailNavigation.width;
        }
        return thumbnailNavigation.width * 2;
      }
    
      /** */
      rightWidth() {
        const { view, thumbnailNavigation } = this.props;
        switch (view) {
          case 'book':
            return (thumbnailNavigation.width * 2);
          default:
            return thumbnailNavigation.width;
        }
      }
    
      /** */
      style() {
        const { position, thumbnailNavigation } = this.props;
        switch (position) {
          case 'far-right':
            return {
              height: '100%',
              minHeight: 0,
              width: `${this.rightWidth() + this.scrollbarSize + this.spacing}px`,
            };
          // Default case bottom
          default:
            return {
              height: `${thumbnailNavigation.height}px`,
              width: '100%',
            };
        }
      }
    
      /** */
      areaHeight(height) {
        const { position, thumbnailNavigation } = this.props;
        switch (position) {
          case 'far-right':
            return height;
          // Default case bottom
          default:
            return thumbnailNavigation.height;
        }
      }
    
      /** */
      itemCount() {
        const { canvasGroupings } = this.props;
        return canvasGroupings.groupings().length;
      }
    
      /** */
      handleKeyUp(e) {
        const { position } = this.props;
        let nextKey = 'ArrowRight';
        let previousKey = 'ArrowLeft';
        if (position === 'far-right') {
          nextKey = 'ArrowDown';
          previousKey = 'ArrowUp';
        }
        switch (e.key) {
          case nextKey:
            this.nextCanvas();
            break;
          case previousKey:
            this.previousCanvas();
            break;
          default:
            break;
        }
      }
    
      /**
       */
      nextCanvas() {
        const { hasNextCanvas, setNextCanvas } = this.props;
        if (hasNextCanvas) {
          setNextCanvas();
        }
      }
    
      /**
       */
      previousCanvas() {
        const { hasPreviousCanvas, setPreviousCanvas } = this.props;
        if (hasPreviousCanvas) {
          setPreviousCanvas();
        }
      }
    
      /**
       * Renders things
       */
      render() {
        const {
          t,
          canvasGroupings,
          classes,
          position,
          thumbnailNavigation,
          viewingDirection,
          windowId,
        } = this.props;
        if (position === 'off') {
          return <></>;
        }
        const htmlDir = viewingDirection === 'right-to-left' ? 'rtl' : 'ltr';
        const itemData = {
          canvasGroupings,
          height: thumbnailNavigation.height - this.spacing - this.scrollbarSize,
          position,
          windowId,
        };
        return (
          <Paper
            className={classNames(
              ns('thumb-navigation'),
              classes.thumbNavigation,
            )}
            aria-label={t('thumbnailNavigation')}
            square
            elevation={0}
            style={this.style()}
            tabIndex={0}
            onKeyUp={this.handleKeyUp}
            role="grid"
          >
            <div role="row" style={{ height: '100%', width: '100%' }}>
              <AutoSizer
                defaultHeight={100}
                defaultWidth={400}
              >
                {({ height, width }) => (
                  <List
                    direction={htmlDir}
                    height={this.areaHeight(height)}
                    itemCount={this.itemCount()}
                    itemSize={this.calculateScaledSize}
                    width={width}
                    layout={(position === 'far-bottom') ? 'horizontal' : 'vertical'}
                    itemData={itemData}
                    ref={this.gridRef}
                  >
                    {ThumbnailCanvasGrouping}
                  </List>
                )}
              </AutoSizer>
            </div>
          </Paper>
        );
      }
    }
    
    ThumbnailNavigation.propTypes = {
      canvasGroupings: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types
      canvasIndex: PropTypes.number.isRequired,
      classes: PropTypes.objectOf(PropTypes.string).isRequired,
      hasNextCanvas: PropTypes.bool,
      hasPreviousCanvas: PropTypes.bool,
      position: PropTypes.string.isRequired,
      setNextCanvas: PropTypes.func,
      setPreviousCanvas: PropTypes.func,
      t: PropTypes.func.isRequired,
      thumbnailNavigation: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types
      view: PropTypes.string,
      viewingDirection: PropTypes.string,
      windowId: PropTypes.string.isRequired,
    };
    
    ThumbnailNavigation.defaultProps = {
      hasNextCanvas: false,
      hasPreviousCanvas: false,
      setNextCanvas: () => {},
      setPreviousCanvas: () => {},
      view: undefined,
      viewingDirection: '',
    };