Bug 1406287 - Part 3: Correspond for changing size of sidebar. r?gl draft
authorDaisuke Akatsuka <dakatsuka@mozilla.com>
Wed, 25 Oct 2017 14:12:53 +0900
changeset 685936 1a4e0e53c99828848b4c2ff0da327c4704589797
parent 685935 73cca812d6827eede4535869ea8b294164b21f28
child 685937 402e2ae803c2cbdf2961224a7eda4a9a445ebbbd
push id86037
push userbmo:dakatsuka@mozilla.com
push dateWed, 25 Oct 2017 05:43:28 +0000
reviewersgl
bugs1406287
milestone58.0a1
Bug 1406287 - Part 3: Correspond for changing size of sidebar. r?gl MozReview-Commit-ID: 9ndHImmpM9c
devtools/client/inspector/animation/actions/index.js
devtools/client/inspector/animation/actions/moz.build
devtools/client/inspector/animation/actions/sidebar.js
devtools/client/inspector/animation/animation.js
devtools/client/inspector/animation/components/AnimationTimeTickList.js
devtools/client/inspector/animation/reducers/moz.build
devtools/client/inspector/animation/reducers/sidebar.js
devtools/client/inspector/inspector.js
devtools/client/inspector/reducers.js
devtools/client/shared/components/splitter/SplitBox.js
--- a/devtools/client/inspector/animation/actions/index.js
+++ b/devtools/client/inspector/animation/actions/index.js
@@ -6,9 +6,11 @@
 
 const { createEnum } = require("devtools/client/shared/enum");
 
 createEnum([
   // Update the list of animation.
   "UPDATE_ANIMATIONS",
   // Update state of the picker enabled.
   "UPDATE_ELEMENT_PICKER_ENABLED",
+  // Update sidebar size.
+  "UPDATE_SIDEBAR_SIZE"
 ], module.exports);
--- a/devtools/client/inspector/animation/actions/moz.build
+++ b/devtools/client/inspector/animation/actions/moz.build
@@ -1,9 +1,10 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 DevToolsModules(
     'animations.js',
     'element-picker.js',
-    'index.js'
+    'index.js',
+    'sidebar.js'
 )
new file mode 100644
--- /dev/null
+++ b/devtools/client/inspector/animation/actions/sidebar.js
@@ -0,0 +1,19 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+const { UPDATE_SIDEBAR_SIZE } = require("./index");
+
+module.exports = {
+  /**
+   * Update the sidebar size.
+   */
+  updateSidebarSize(size) {
+    return {
+      type: UPDATE_SIDEBAR_SIZE,
+      size,
+    };
+  }
+};
--- a/devtools/client/inspector/animation/animation.js
+++ b/devtools/client/inspector/animation/animation.js
@@ -6,24 +6,26 @@
 
 const { AnimationsFront } = require("devtools/shared/fronts/animation");
 const { createElement, createFactory } = require("devtools/client/shared/vendor/react");
 const { Provider } = require("devtools/client/shared/vendor/react-redux");
 
 const App = createFactory(require("./components/App"));
 const { isAllTimingEffectEqual } = require("./utils/utils");
 const { updateAnimations } = require("./actions/animations");
+const { updateSidebarSize } = require("./actions/sidebar");
 const { updateElementPickerEnabled } = require("./actions/element-picker");
 
 class AnimationInspector {
   constructor(inspector) {
     this.inspector = inspector;
 
     this.toggleElementPicker = this.toggleElementPicker.bind(this);
     this.update = this.update.bind(this);
+    this.onSidebarResized = this.onSidebarResized.bind(this);
     this.onElementPickerStarted = this.onElementPickerStarted.bind(this);
     this.onElementPickerStopped = this.onElementPickerStopped.bind(this);
 
     this.init();
   }
 
   init() {
     const target = this.inspector.target;
@@ -40,23 +42,25 @@ class AnimationInspector {
           toggleElementPicker: this.toggleElementPicker
         }
       )
     );
     this.provider = provider;
 
     this.inspector.selection.on("new-node-front", this.update);
     this.inspector.sidebar.on("newanimationinspector-selected", this.update);
+    this.inspector.toolbox.on("inspector-sidebar-resized", this.onSidebarResized);
     this.inspector.toolbox.on("picker-started", this.onElementPickerStarted);
     this.inspector.toolbox.on("picker-stopped", this.onElementPickerStopped);
   }
 
   destroy() {
     this.inspector.selection.off("new-node-front", this.update);
     this.inspector.sidebar.off("newanimationinspector-selected", this.update);
+    this.inspector.toolbox.off("inspector-sidebar-resized", this.onSidebarResized);
     this.inspector.toolbox.off("picker-started", this.onElementPickerStarted);
     this.inspector.toolbox.off("picker-stopped", this.onElementPickerStopped);
 
     this.inspector = null;
   }
 
   async update() {
     if (!this.inspector || !this.isPanelVisible()) {
@@ -92,11 +96,15 @@ class AnimationInspector {
 
   onElementPickerStarted() {
     this.inspector.store.dispatch(updateElementPickerEnabled(true));
   }
 
   onElementPickerStopped() {
     this.inspector.store.dispatch(updateElementPickerEnabled(false));
   }
+
+  onSidebarResized(type, size) {
+    this.inspector.store.dispatch(updateSidebarSize(size));
+  }
 }
 
 module.exports = AnimationInspector;
--- a/devtools/client/inspector/animation/components/AnimationTimeTickList.js
+++ b/devtools/client/inspector/animation/components/AnimationTimeTickList.js
@@ -1,47 +1,67 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
 const { createFactory, DOM: dom, PropTypes, PureComponent } =
   require("devtools/client/shared/vendor/react");
+const { connect } = require("devtools/client/shared/vendor/react-redux");
 const ReactDOM = require("devtools/client/shared/vendor/react-dom");
 
 const AnimationTimeTickItem = createFactory(require("./AnimationTimeTickItem"));
 const { findOptimalTimeInterval } = require("../utils/utils");
 
 // The minimum spacing between 2 time graduation headers in the timeline (px).
 const TIME_GRADUATION_MIN_SPACING = 40;
 
 class AnimationTimeTickList extends PureComponent {
   static get displayName() {
     return "AnimationTimeTickList";
   }
 
   static get propTypes() {
     return {
       timescale: PropTypes.object.isRequired,
+      sidebarWidth: PropTypes.number.isRequired,
     };
   }
 
   constructor() {
     super();
 
     this.state = {
       tickList: []
     };
   }
 
   componentDidMount() {
     this.updateTickList();
   }
 
+  componentWillReceiveProps(nextProps) {
+    this.updateTickList();
+  }
+
+  shouldComponentUpdate(nextProps, nextState) {
+    if (this.state.tickList.length !== nextState.tickList.length) {
+      return true;
+    }
+    for (let i = 0; i < this.state.tickList.length; i++) {
+      const currentTickItem = this.state.tickList[i];
+      const nextTickItem = nextState.tickList[i];
+      if (currentTickItem.text !== nextTickItem.text) {
+        return true;
+      }
+    }
+    return false;
+  }
+
   createTickList() {
     const { timescale } = this.props;
 
     const tickListEl = ReactDOM.findDOMNode(this);
     if (!tickListEl) {
       // Not mounted yet.
       return [];
     }
@@ -74,9 +94,15 @@ class AnimationTimeTickList extends Pure
       },
       tickList.map(tickItem => {
         return AnimationTimeTickItem(tickItem);
       })
     );
   }
 }
 
-module.exports = AnimationTimeTickList;
+const mapStateToProps = state => {
+  return {
+    sidebarWidth: state.animationSidebar.width
+  };
+};
+
+module.exports = connect(mapStateToProps)(AnimationTimeTickList);
--- a/devtools/client/inspector/animation/reducers/moz.build
+++ b/devtools/client/inspector/animation/reducers/moz.build
@@ -1,8 +1,9 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 DevToolsModules(
     'animations.js',
     'element-picker.js',
+    'sidebar.js',
 )
new file mode 100644
--- /dev/null
+++ b/devtools/client/inspector/animation/reducers/sidebar.js
@@ -0,0 +1,23 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+const { UPDATE_SIDEBAR_SIZE } = require("../actions/index");
+
+const INITIAL_SIZE = {
+  width: 0,
+  height: 0
+};
+
+const reducers = {
+  [UPDATE_SIDEBAR_SIZE](_, { size }) {
+    return size;
+  }
+};
+
+module.exports = function (size = INITIAL_SIZE, action) {
+  const reducer = reducers[action.type];
+  return reducer ? reducer(size, action) : size;
+};
--- a/devtools/client/inspector/inspector.js
+++ b/devtools/client/inspector/inspector.js
@@ -121,16 +121,17 @@ function Inspector(toolbox) {
   this.onDetached = this.onDetached.bind(this);
   this.onMarkupLoaded = this.onMarkupLoaded.bind(this);
   this.onNewSelection = this.onNewSelection.bind(this);
   this.onNewRoot = this.onNewRoot.bind(this);
   this.onPanelWindowResize = this.onPanelWindowResize.bind(this);
   this.onShowBoxModelHighlighterForNode =
     this.onShowBoxModelHighlighterForNode.bind(this);
   this.onSidebarHidden = this.onSidebarHidden.bind(this);
+  this.onSidebarResized = this.onSidebarResized.bind(this);
   this.onSidebarSelect = this.onSidebarSelect.bind(this);
   this.onSidebarShown = this.onSidebarShown.bind(this);
 
   this._target.on("will-navigate", this._onBeforeNavigate);
   this._detectingActorFeatures = this._detectActorFeatures();
 }
 
 Inspector.prototype = {
@@ -498,16 +499,17 @@ Inspector.prototype = {
       endPanelControl: true,
       startPanel: this.InspectorTabPanel({
         id: "inspector-main-content"
       }),
       endPanel: this.InspectorTabPanel({
         id: "inspector-sidebar-container"
       }),
       vert: this.useLandscapeMode(),
+      onControlledPanelResized: this.onSidebarResized,
     });
 
     this._splitter = this.ReactDOM.render(splitter,
       this.panelDoc.getElementById("inspector-splitter-box"));
 
     this.panelWin.addEventListener("resize", this.onPanelWindowResize, true);
   },
 
@@ -568,16 +570,20 @@ Inspector.prototype = {
 
     // Then forces the panel creation by calling getPanel
     // (This allows lazy loading the panels only once we select them)
     this.getPanel(toolId);
 
     this.toolbox.emit("inspector-sidebar-select", toolId);
   },
 
+  onSidebarResized: function (width, height) {
+    this.toolbox.emit("inspector-sidebar-resized", { width, height });
+  },
+
   /**
    * Lazily get and create panel instances displayed in the sidebar
    */
   getPanel: function (id) {
     if (this._panels.has(id)) {
       return this._panels.get(id);
     }
     let panel;
--- a/devtools/client/inspector/reducers.js
+++ b/devtools/client/inspector/reducers.js
@@ -5,14 +5,16 @@
 "use strict";
 
 // This file exposes the Redux reducers of the box model, grid and grid highlighter
 // settings.
 
 exports.animations = require("devtools/client/inspector/animation/reducers/animations");
 exports.animationElementPicker =
   require("devtools/client/inspector/animation/reducers/element-picker");
+exports.animationSidebar =
+  require("devtools/client/inspector/animation/reducers/sidebar");
 exports.boxModel = require("devtools/client/inspector/boxmodel/reducers/box-model");
 exports.extensionsSidebar = require("devtools/client/inspector/extensions/reducers/sidebar");
 exports.fontOptions = require("devtools/client/inspector/fonts/reducers/font-options");
 exports.fonts = require("devtools/client/inspector/fonts/reducers/fonts");
 exports.grids = require("devtools/client/inspector/grids/reducers/grids");
 exports.highlighterSettings = require("devtools/client/inspector/grids/reducers/highlighter-settings");
--- a/devtools/client/shared/components/splitter/SplitBox.js
+++ b/devtools/client/shared/components/splitter/SplitBox.js
@@ -36,16 +36,18 @@ const SplitBox = React.createClass({
     // True if the right/bottom panel should be controlled.
     endPanelControl: PropTypes.bool,
     // Size of the splitter handle bar.
     splitterSize: PropTypes.string,
     // True if the splitter bar is vertical (default is vertical).
     vert: PropTypes.bool,
     // Style object.
     style: PropTypes.object,
+    // Call when controlled panel was resized.
+    onControlledPanelResized: PropTypes.func,
   },
 
   getDefaultProps() {
     return {
       splitterSize: 5,
       vert: true,
       endPanelControl: false
     };
@@ -79,16 +81,23 @@ const SplitBox = React.createClass({
       nextProps.startPanel != this.props.startPanel ||
       nextProps.endPanel != this.props.endPanel ||
       nextProps.endPanelControl != this.props.endPanelControl ||
       nextProps.minSize != this.props.minSize ||
       nextProps.maxSize != this.props.maxSize ||
       nextProps.splitterSize != this.props.splitterSize;
   },
 
+  componentDidUpdate(prevProps, prevState) {
+    if (this.props.onControlledPanelResized && (prevState.width !== this.state.width ||
+                                                prevState.height !== this.state.height)) {
+      this.props.onControlledPanelResized(this.state.width, this.state.height);
+    }
+  },
+
   // Dragging Events
 
   /**
    * Set 'resizing' cursor on entire document during splitter dragging.
    * This avoids cursor-flickering that happens when the mouse leaves
    * the splitter bar area (happens frequently).
    */
   onStartMove() {