mirror of
https://github.com/pulsar-edit/pulsar.git
synced 2024-09-21 07:58:04 +03:00
Shrink the nearest pane code
This commit is contained in:
parent
8772e45a39
commit
fc5bc1632d
@ -2,7 +2,6 @@ Delegator = require 'delegato'
|
|||||||
{$, View} = require './space-pen-extensions'
|
{$, View} = require './space-pen-extensions'
|
||||||
PaneView = require './pane-view'
|
PaneView = require './pane-view'
|
||||||
PaneContainer = require './pane-container'
|
PaneContainer = require './pane-container'
|
||||||
PositionallyAwarePane = require './positionally-aware-pane'
|
|
||||||
|
|
||||||
# Private: Manages the list of panes within a {WorkspaceView}
|
# Private: Manages the list of panes within a {WorkspaceView}
|
||||||
module.exports =
|
module.exports =
|
||||||
@ -101,16 +100,52 @@ class PaneContainerView extends View
|
|||||||
@model.activatePreviousPane()
|
@model.activatePreviousPane()
|
||||||
|
|
||||||
focusPaneAbove: ->
|
focusPaneAbove: ->
|
||||||
@positionallyAwarePaneForActivePane().focusPaneAbove()
|
@nearestPaneInDirection('above')?.focus()
|
||||||
|
|
||||||
focusPaneBelow: ->
|
focusPaneBelow: ->
|
||||||
@positionallyAwarePaneForActivePane().focusPaneBelow()
|
@nearestPaneInDirection('below')?.focus()
|
||||||
|
|
||||||
focusPaneOnLeft: ->
|
focusPaneOnLeft: ->
|
||||||
@positionallyAwarePaneForActivePane().focusPaneOnLeft()
|
@nearestPaneInDirection('left')?.focus()
|
||||||
|
|
||||||
focusPaneOnRight: ->
|
focusPaneOnRight: ->
|
||||||
@positionallyAwarePaneForActivePane().focusPaneOnRight()
|
@nearestPaneInDirection('right')?.focus()
|
||||||
|
|
||||||
positionallyAwarePaneForActivePane: ->
|
nearestPaneInDirection: (direction) ->
|
||||||
new PositionallyAwarePane(@getActivePane(), @getPanes())
|
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));
|
||||||
|
@ -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()
|
|
Loading…
Reference in New Issue
Block a user