From fc5bc1632dd1e157c51d508f21170c942c3375f2 Mon Sep 17 00:00:00 2001 From: probablycorey Date: Wed, 29 Jan 2014 12:08:34 -0800 Subject: [PATCH] Shrink the nearest pane code --- src/pane-container-view.coffee | 49 ++++++-- src/positionally-aware-pane.coffee | 194 ----------------------------- 2 files changed, 42 insertions(+), 201 deletions(-) delete mode 100644 src/positionally-aware-pane.coffee diff --git a/src/pane-container-view.coffee b/src/pane-container-view.coffee index f7ef29bb6..2f52c8e4f 100644 --- a/src/pane-container-view.coffee +++ b/src/pane-container-view.coffee @@ -2,7 +2,6 @@ Delegator = require 'delegato' {$, View} = require './space-pen-extensions' PaneView = require './pane-view' PaneContainer = require './pane-container' -PositionallyAwarePane = require './positionally-aware-pane' # Private: Manages the list of panes within a {WorkspaceView} module.exports = @@ -101,16 +100,52 @@ class PaneContainerView extends View @model.activatePreviousPane() focusPaneAbove: -> - @positionallyAwarePaneForActivePane().focusPaneAbove() + @nearestPaneInDirection('above')?.focus() focusPaneBelow: -> - @positionallyAwarePaneForActivePane().focusPaneBelow() + @nearestPaneInDirection('below')?.focus() focusPaneOnLeft: -> - @positionallyAwarePaneForActivePane().focusPaneOnLeft() + @nearestPaneInDirection('left')?.focus() focusPaneOnRight: -> - @positionallyAwarePaneForActivePane().focusPaneOnRight() + @nearestPaneInDirection('right')?.focus() - positionallyAwarePaneForActivePane: -> - new PositionallyAwarePane(@getActivePane(), @getPanes()) + nearestPaneInDirection: (direction) -> + pane = @getActivePane() + box = @boundingBoxForPane(pane) + panes = @getPanes() + .filter (otherPane) => + otherBox = @boundingBoxForPane(otherPane) + switch direction + when 'left' then otherBox.right.x <= box.left.x + when 'right' then otherBox.left.x >= box.right.x + when 'above' then otherBox.bottom.y <= box.top.y + when 'below' then otherBox.top.y >= box.bottom.y + .sort (paneA, paneB) => + boxA = @boundingBoxForPane(paneA) + boxB = @boundingBoxForPane(paneB) + switch direction + when 'left' + @distanceBetweenPoints(box.left, boxA.right) - @distanceBetweenPoints(box.left, boxB.right) + when 'right' + @distanceBetweenPoints(box.right, boxA.left) - @distanceBetweenPoints(box.right, boxB.left) + when 'above' + @distanceBetweenPoints(box.top, boxA.bottom) - @distanceBetweenPoints(box.top, boxB.bottom) + when 'below' + @distanceBetweenPoints(box.bottom, boxA.top) - @distanceBetweenPoints(box.bottom, boxB.top) + + panes[0] + + boundingBoxForPane: (pane) -> + boundingBox = pane[0].getBoundingClientRect() + + left: {x: boundingBox.left, y: boundingBox.top} + right: {x: boundingBox.right, y: boundingBox.top} + top: {x: boundingBox.left, y: boundingBox.top} + bottom: {x: boundingBox.left, y: boundingBox.bottom} + + distanceBetweenPoints: (pointA, pointB) -> + x = pointB.x - pointA.x + y = pointB.y - pointA.y + Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)); diff --git a/src/positionally-aware-pane.coffee b/src/positionally-aware-pane.coffee deleted file mode 100644 index 62960b6f5..000000000 --- a/src/positionally-aware-pane.coffee +++ /dev/null @@ -1,194 +0,0 @@ -_ = require 'underscore-plus' - -# Private: Wraps a {Pane} to decorate it with knowledge of its physicial -# location relative to all other {Pane}s. -# -# Intended as a helper for {PaneContainerView}. -module.exports = -class PositionallyAwarePane - - # Creates a {PositionallyAwarePane}. - # - # * pane: - # The {Pane} that needs to gain some positional awareness. - # * allPanes: - # The collection of all {Pane}s. - constructor: (@pane, @allPanes) -> - - focusPaneAbove: -> - @bestChoiceForVerticalNavigation(@panesInAdjacentRowAbove())?.focus() - - focusPaneBelow: -> - @bestChoiceForVerticalNavigation(@panesInAdjacentRowBelow())?.focus() - - focusPaneOnLeft: -> - @bestChoiceForHorizontalNavigation(@panesInAdjacentColumnOnLeft())?.focus() - - focusPaneOnRight: -> - @bestChoiceForHorizontalNavigation(@panesInAdjacentColumnOnRight())?.focus() - - focus: -> - @pane.focus() - - width: -> - @pane.width() - - height: -> - @pane.height() - - xLeft: -> - @pane.offset().left - - xCenter: -> - @xLeft() + @width()/2 - - xRight: -> - @xLeft() + @width() - - yTop: -> - @pane.offset().top - - yCenter: -> - @yTop() + @height()/2 - - yBottom: -> - @yTop() + @height() - - ### Internal ### - - panesInAdjacentRowAbove: -> - allPanesAbove = @otherPanes().filter (pane) => @isBelow(pane) - yBottomValues = _.map allPanesAbove, (pane) -> pane.yBottom() - maxYBottom = _.max yBottomValues - panesVerticallyNearest = allPanesAbove.filter (pane) -> - pane.yBottom() == maxYBottom - - panesInAdjacentRowBelow: -> - allPanesBelow = @otherPanes().filter (pane) => @isAbove(pane) - - yTopValues = _.map allPanesBelow, (pane) -> pane.yTop() - minYTop = _.min yTopValues - panesVerticallyNearest = allPanesBelow.filter (pane) -> - pane.yTop() == minYTop - - panesInAdjacentColumnOnLeft: -> - allPanesOnLeft = @otherPanes().filter (pane) => @isRightOf(pane) - xRightValues = _.map allPanesOnLeft, (pane) -> pane.xRight() - maxXRight = _.max xRightValues - panesHorizontallyNearest = allPanesOnLeft.filter (pane) -> - pane.xRight() == maxXRight - - # Internal - panesInAdjacentColumnOnRight: -> - allPanesOnRight = @otherPanes().filter (pane) => @isLeftOf(pane) - xLeftValues = _.map allPanesOnRight, (pane) -> pane.xLeft() - minXLeft = _.min xLeftValues - panesHorizontallyNearest = allPanesOnRight.filter (pane) -> - pane.xLeft() == minXLeft - - # Determine whether this pane is above the given pane. - # - # * otherPane: - # The {PositionallyAwarePane} to compare to this pane. - # - # Returns true if this pane is above otherPane; otherwise, false. - isAbove: (otherPane) -> - otherPaneYTop = otherPane.yTop() + @overlap() - otherPaneYTop >= @yBottom() - - # Determine whether this pane is below the given pane. - # - # * otherPane: - # The {PositionallyAwarePane} to compare to this pane. - # - # Returns true if this pane is below otherPane; otherwise, false. - isBelow: (otherPane) -> - otherPaneYBottom = otherPane.yBottom() - @overlap() - otherPaneYBottom <= @yTop() - - # Determine whether this pane is to the left of the given pane. - # - # * otherPane: - # The {PositionallyAwarePane} to compare to this pane. - # - # Returns true if this pane is to the left of otherPane; otherwise, false. - isLeftOf: (otherPane) -> - otherPaneXLeft = otherPane.xLeft() + @overlap() - otherPaneXLeft >= @xRight() - - # Determine whether this pane is to the right of the given pane. - # - # * otherPane: - # The {PositionallyAwarePane} to compare to this pane. - # - # Returns true if this pane is to the right of otherPane; otherwise, false. - isRightOf: (otherPane) -> - otherPaneXRight = otherPane.xRight() - @overlap() - otherPaneXRight <= @xLeft() - - # The adjacent column may include several panes. When navigating left or right - # from this pane, find the pane in the adjacent column that is the most - # appropriate destination. - # - # * panes: - # An Array of {PositionallyAwarePane}s in the column adjacent to this pane. - # - # Returns a PositionallyAwarePane. - bestChoiceForHorizontalNavigation: (panes) -> - _.find panes, (pane) => - pane.yTop() <= @yCenter() and @yCenter() <= pane.yBottom() - - # The adjacent row may include several panes. When navigating up or down from - # this pane, find the pane in the adjacent row that is the most appropriate - # destination. - # - # * panes: - # An Array of {PositionallyAwarePane}s in the row adjacent to this pane. - # - # Returns a PositionallyAwarePane. - bestChoiceForVerticalNavigation: (panes) -> - _.find panes, (pane) => - pane.xLeft() <= @xCenter() and @xCenter() <= pane.xRight() - - # In theory, if two panes are side-by-side, then the rightmost x coordinate of - # the pane on the left should be less than or equal to the leftmost x - # coordinate of the pane on the right. For example, assume we have two panes: - # - # ----- - # |1|2| - # ----- - # - # If the rightmost x coordinate of Pane #1 is 400, then the leftmost x - # coordinate of Pane #2 should be at least 400. In practice, this isn't always - # true. Sometimes there seems to be a small "overlap" between the two panes. - # If Pane #1's rightmost x coordinate is 400, then Pane 2's leftmost x - # coordinate might be 399.2 (for example). - # - # A similar issue occurs for the y coordinates. - # - # To cope with this issue, this method provides a rough guess as to the - # amount of overlap between panes. - # - # Returns a Number. - overlap: -> - 2 - - # Returns an Array of {PositionallyAwarePane}s for all of the other panes, - # excluding this pane. - otherPanes: -> - _.map @allPanes, (pane) -> new PositionallyAwarePane(pane, @allPanes) - - coordinates: -> - xLeft: @xLeft() - xCenter: @xCenter() - xRight: @xRight() - yTop: @yTop() - yCenter: @yCenter() - yBottom: @yBottom() - - logDebugInfo: -> - console.log "Coordinates for this pane:" - console.log @coordinates() - - console.log "Coordinates for other panes:" - @otherPanes().forEach (pane) -> console.log pane.coordinates()