<commit_before>CLASS({
  package: 'foam.ui',
  name: 'SlidePanel',
  extendsModel: 'View',

  requires: [
    'GestureTarget'
  ],
  imports: [
    'clearTimeout',
    'document',
    'gestureManager',
    'setTimeout'
  ],

  constants: {
    CLOSED: {
      name: 'CLOSED',
      layout: function() {
        return [ this.parentWidth - this.stripWidth, this.minPanelWidth, this.stripWidth ];
      },
      onResize: function() {
        if ( this.parentWidth > this.minWidth + this.minPanelWidth )
          this.nextState = this.EXPANDED;
      },
      toggle: function() { this.open(); },
      open: function() { this.nextState = this.OPEN; },
      shadow: true
    },
    EXPANDED: {
      name: 'EXPANDED',
      layout: function() {
        var extraWidth = this.parentWidth - this.minWidth - this.minPanelWidth;
        var panelWidth = this.minPanelWidth + extraWidth * this.panelRatio;
        return [ this.parentWidth - panelWidth, panelWidth, panelWidth ];
      },
      onResize: function() {
        if ( this.parentWidth < this.minWidth + this.minPanelWidth )
          this.nextState = this.CLOSED;
      }
    },
    OPEN: {
      name: 'OPEN',
      layout: function() {
        return [ this.parentWidth - this.stripWidth, this.minPanelWidth, this.panelWidth ];
      },
      onResize: function() {
        if ( this.parentWidth > this.minWidth + this.minPanelWidth )
          this.nextState = this.OPEN_EXPANDED;
      },
      close: function() { this.nextState = this.CLOSED; },
      toggle: function() { this.close(); },
      shadow: true
    },
    OPEN_EXPANDED: {
      name: 'OPEN_EXPANDED',
      layout: function() { return this.EXPANDED.layout.call(this); },
      onResize: function() {
        if ( this.parentWidth < this.minWidth + this.minPanelWidth )
          this.nextState = this.OPEN;
      }
    }
  },

  help: 'A controller that shows a main view with a small strip of the ' +
      'secondary view visible at the right edge. This "panel" can be dragged ' +
      'by a finger or mouse pointer to any position from its small strip to ' +
      'fully exposed. If the containing view is wide enough, both panels ' +
      'will always be visible.',

  properties: [
    {
      name: 'state'
    },
    {
      name: 'nextState',
      postSet: function(oldState, newState) {
//        if ( oldState === newState ) return;
        this.state = newState;

        var layout = this.state.layout.call(this);
        console.log(oldState.name + '  ->  ' + newState.name, layout);
        this.mainWidth  = layout[0];
        this.panelWidth = layout[1]+2;
        this.panelX     = this.parentWidth-layout[2];

        // Movement.animate(500, function() { this.progress = 1.0; }.bind(this))();
      }
    },
    {
      name: 'progress',
      defaultValue: 0,
      postSet: function(_, p) {
console.log('progress: ', p);
        var layout = this.interpolate(this.state, this.nextState);
        this.mainWidth = layout[0];
        this.panelWidth = layout[1];
        this.panelX = this.parentWidth-layout[2];
        if ( p >= 1.0 ) this.state = this.nextState;
      }
    },

    { model_: 'ViewFactoryProperty', name: 'mainView' },
    { model_: 'ViewFactoryProperty', name: 'panelView' },
    {
      model_: 'IntProperty',
      name: 'minWidth',<commit_msg>Added animation.<commit_after>CLASS({
  package: 'foam.ui',
  name: 'SlidePanel',
  extendsModel: 'View',

  requires: [
    'GestureTarget'
  ],
  imports: [
    'clearTimeout',
    'document',
    'gestureManager',
    'setTimeout'
  ],

  constants: {
    CLOSED: {
      name: 'CLOSED',
      layout: function() {
        return [ this.parentWidth - this.stripWidth, this.minPanelWidth, this.stripWidth ];
      },
      onResize: function() {
        if ( this.parentWidth > this.minWidth + this.minPanelWidth )
          this.nextState = this.EXPANDED;
      },
      toggle: function() { this.open(); },
      open: function() { this.nextState = this.OPEN; },
      shadow: true
    },
    EXPANDED: {
      name: 'EXPANDED',
      layout: function() {
        var extraWidth = this.parentWidth - this.minWidth - this.minPanelWidth;
        var panelWidth = this.minPanelWidth + extraWidth * this.panelRatio;
        return [ this.parentWidth - panelWidth, panelWidth, panelWidth ];
      },
      onResize: function() {
        if ( this.parentWidth < this.minWidth + this.minPanelWidth )
          this.nextState = this.CLOSED;
      }
    },
    OPEN: {
      name: 'OPEN',
      layout: function() {
        return [ this.parentWidth - this.stripWidth, this.minPanelWidth, this.panelWidth ];
      },
      onResize: function() {
        if ( this.parentWidth > this.minWidth + this.minPanelWidth )
          this.nextState = this.OPEN_EXPANDED;
      },
      close: function() { this.nextState = this.CLOSED; },
      toggle: function() { this.close(); },
      shadow: true
    },
    OPEN_EXPANDED: {
      name: 'OPEN_EXPANDED',
      layout: function() { return this.EXPANDED.layout.call(this); },
      onResize: function() {
        if ( this.parentWidth < this.minWidth + this.minPanelWidth )
          this.nextState = this.OPEN;
      }
    }
  },

  help: 'A controller that shows a main view with a small strip of the ' +
      'secondary view visible at the right edge. This "panel" can be dragged ' +
      'by a finger or mouse pointer to any position from its small strip to ' +
      'fully exposed. If the containing view is wide enough, both panels ' +
      'will always be visible.',

  properties: [
    {
      name: 'state'
    },
    {
      name: 'nextState',
      postSet: function(oldState, newState) {
//        if ( oldState === newState ) return;
        this.state = newState;

        this.desiredLayout = this.state.layout.call(this);
      }
    },
    {
      name: 'currentLayout',
      postSet: function(_, layout) {
        this.mainWidth  = layout[0];
        this.panelWidth = layout[1]+2;
        this.panelX     = this.parentWidth-layout[2];
      }
    },
    {
      name: 'desiredLayout',
      postSet: function(_, layout) {
        var startLayout = this.currentLayout;
        var start = Date.now();
        var end   = start + 200;
        var animate = function() {
          var now = Date.now();
          var p = (now-start) / (end-start);
          if ( p < 1 ) {
            this.currentLayout = [
              startLayout[0] * ( 1 - p ) + layout[0] * p,
              startLayout[1] * ( 1 - p ) + layout[1] * p,
              startLayout[2] * ( 1 - p ) + layout[2] * p
            ];
            this.X.requestAnimationFrame(animate);
          } else {
            this.currentLayout = layout;
          }
        }.bind(this);
        animate();
      }
    },
    { model_: 'ViewFactoryProperty', name: 'mainView' },
    { model_: 'ViewFactoryProperty', name: 'panelView' },
    {
      model_: 'IntProperty',
      name: 'minWidth',
{'fraction_non_alphanumeric': 0.13380484988452657, 'fraction_numerical': 0.004618937644341801, 'mean_word_length': 2.1141573033707863, 'pattern_counts': {'":': 0, '<': 8, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1971753', 'n_tokens_mistral': 2138, 'n_tokens_neox': 2118, 'n_words': 490}