Merge pull request #1378 from atom/cj-flexbox-panes

This replaces custom pane resizing with flexbox
This commit is contained in:
Corey Johnson
2014-01-08 16:36:41 -08:00
9 changed files with 68 additions and 138 deletions

View File

@@ -124,19 +124,19 @@ describe "PaneContainer", ->
describe "serialization", ->
it "can be serialized and deserialized, and correctly adjusts dimensions of deserialized panes after attach", ->
newContainer = atom.deserializers.deserialize(container.serialize())
expect(newContainer.find('.row > :contains(1)')).toExist()
expect(newContainer.find('.row > .column > :contains(2)')).toExist()
expect(newContainer.find('.row > .column > :contains(3)')).toExist()
expect(newContainer.find('.pane-row > :contains(1)')).toExist()
expect(newContainer.find('.pane-row > .pane-column > :contains(2)')).toExist()
expect(newContainer.find('.pane-row > .pane-column > :contains(3)')).toExist()
newContainer.height(200).width(300).attachToDom()
expect(newContainer.find('.row > :contains(1)').width()).toBe 150
expect(newContainer.find('.row > .column > :contains(2)').height()).toBe 100
expect(newContainer.find('.pane-row > :contains(1)').width()).toBe 150
expect(newContainer.find('.pane-row > .pane-column > :contains(2)').height()).toBe 100
xit "removes empty panes on deserialization", ->
# only deserialize pane 1's view successfully
TestView.deserialize = ({name}) -> new TestView(name) if name is '1'
newContainer = atom.deserializers.deserialize(container.serialize())
expect(newContainer.find('.row, .column')).not.toExist()
expect(newContainer.find('.pane-row, .pane-column')).not.toExist()
expect(newContainer.find('> :contains(1)')).toExist()
describe "pane-container:active-pane-item-changed", ->

View File

@@ -4,7 +4,7 @@ Pane = require '../src/pane'
path = require 'path'
temp = require 'temp'
describe "Pane", ->
fdescribe "Pane", ->
[container, view1, view2, editor1, editor2, pane] = []
class TestView extends View
@@ -545,23 +545,23 @@ describe "Pane", ->
it "builds a row if needed, then appends a new pane after itself", ->
# creates the new pane with a copy of the active item if none are given
pane2 = pane1.splitRight(pane1.copyActiveItem())
expect(container.find('.row .pane').toArray()).toEqual [pane1[0], pane2[0]]
expect(container.find('.pane-row .pane').toArray()).toEqual [pane1[0], pane2[0]]
expect(pane2.items).toEqual [editor1]
expect(pane2.activeItem).not.toBe editor1 # it's a copy
pane3 = pane2.splitRight(view3, view4)
expect(pane3.getItems()).toEqual [view3, view4]
expect(container.find('.row .pane').toArray()).toEqual [pane[0], pane2[0], pane3[0]]
expect(container.find('.pane-row .pane').toArray()).toEqual [pane[0], pane2[0], pane3[0]]
it "builds a row if needed, then appends a new pane after itself ", ->
# creates the new pane with a copy of the active item if none are given
pane2 = pane1.splitRight()
expect(container.find('.row .pane').toArray()).toEqual [pane1[0], pane2[0]]
expect(container.find('.pane-row .pane').toArray()).toEqual [pane1[0], pane2[0]]
expect(pane2.items).toEqual []
expect(pane2.activeItem).toBeUndefined()
pane3 = pane2.splitRight()
expect(container.find('.row .pane').toArray()).toEqual [pane1[0], pane2[0], pane3[0]]
expect(container.find('.pane-row .pane').toArray()).toEqual [pane1[0], pane2[0], pane3[0]]
expect(pane3.items).toEqual []
expect(pane3.activeItem).toBeUndefined()
@@ -569,37 +569,37 @@ describe "Pane", ->
it "builds a row if needed, then appends a new pane before itself", ->
# creates the new pane with a copy of the active item if none are given
pane2 = pane.splitLeft(pane1.copyActiveItem())
expect(container.find('.row .pane').toArray()).toEqual [pane2[0], pane[0]]
expect(container.find('.pane-row .pane').toArray()).toEqual [pane2[0], pane[0]]
expect(pane2.items).toEqual [editor1]
expect(pane2.activeItem).not.toBe editor1 # it's a copy
pane3 = pane2.splitLeft(view3, view4)
expect(pane3.getItems()).toEqual [view3, view4]
expect(container.find('.row .pane').toArray()).toEqual [pane3[0], pane2[0], pane[0]]
expect(container.find('.pane-row .pane').toArray()).toEqual [pane3[0], pane2[0], pane[0]]
describe "splitDown(items...)", ->
it "builds a column if needed, then appends a new pane after itself", ->
# creates the new pane with a copy of the active item if none are given
pane2 = pane.splitDown(pane1.copyActiveItem())
expect(container.find('.column .pane').toArray()).toEqual [pane[0], pane2[0]]
expect(container.find('.pane-column .pane').toArray()).toEqual [pane[0], pane2[0]]
expect(pane2.items).toEqual [editor1]
expect(pane2.activeItem).not.toBe editor1 # it's a copy
pane3 = pane2.splitDown(view3, view4)
expect(pane3.getItems()).toEqual [view3, view4]
expect(container.find('.column .pane').toArray()).toEqual [pane[0], pane2[0], pane3[0]]
expect(container.find('.pane-column .pane').toArray()).toEqual [pane[0], pane2[0], pane3[0]]
describe "splitUp(items...)", ->
it "builds a column if needed, then appends a new pane before itself", ->
# creates the new pane with a copy of the active item if none are given
pane2 = pane.splitUp(pane1.copyActiveItem())
expect(container.find('.column .pane').toArray()).toEqual [pane2[0], pane[0]]
expect(container.find('.pane-column .pane').toArray()).toEqual [pane2[0], pane[0]]
expect(pane2.items).toEqual [editor1]
expect(pane2.activeItem).not.toBe editor1 # it's a copy
pane3 = pane2.splitUp(view3, view4)
expect(pane3.getItems()).toEqual [view3, view4]
expect(container.find('.column .pane').toArray()).toEqual [pane3[0], pane2[0], pane[0]]
expect(container.find('.pane-column .pane').toArray()).toEqual [pane3[0], pane2[0], pane[0]]
it "lays out nested panes by equally dividing their containing row / column", ->
container.width(520).height(240).attachToDom()

View File

@@ -18,7 +18,6 @@ class PaneAxis extends View
addChild: (child, index=@children().length) ->
@insertAt(index, child)
@getContainer()?.adjustPaneDimensions()
removeChild: (child) ->
parent = @parent().view()
@@ -47,7 +46,6 @@ class PaneAxis extends View
else
primitiveRemove(child)
container.adjustPaneDimensions()
Pane = require './pane'
container.trigger 'pane:removed', [child] if child instanceof Pane
@@ -68,9 +66,3 @@ class PaneAxis extends View
insertChildAfter: (child, newChild) ->
newChild.insertAfter(child)
horizontalChildUnits: ->
$(child).view().horizontalGridUnits() for child in @children()
verticalChildUnits: ->
$(child).view().verticalGridUnits() for child in @children()

View File

@@ -7,28 +7,7 @@ module.exports =
class PaneColumn extends PaneAxis
@content: ->
@div class: 'column'
@div class: 'pane-column'
className: ->
"PaneColumn"
adjustDimensions: ->
totalUnits = @verticalGridUnits()
unitsSoFar = 0
for child in @children()
child = $(child).view()
childUnits = child.verticalGridUnits()
child.css
width: '100%'
height: "#{childUnits / totalUnits * 100}%"
top: "#{unitsSoFar / totalUnits * 100}%"
left: 0
child.adjustDimensions()
unitsSoFar += childUnits
horizontalGridUnits: ->
Math.max(@horizontalChildUnits()...)
verticalGridUnits: ->
_.sum(@verticalChildUnits())

View File

@@ -127,14 +127,6 @@ class PaneContainer extends View
return pane if view?
null
adjustPaneDimensions: ->
if root = @getRoot()
root.css(width: '100%', height: '100%', top: 0, left: 0)
root.adjustDimensions()
removeEmptyPanes: ->
for pane in @getPanes() when pane.getItems().length == 0
pane.remove()
afterAttach: ->
@adjustPaneDimensions()

View File

@@ -7,28 +7,7 @@ PaneAxis = require './pane-axis'
module.exports =
class PaneRow extends PaneAxis
@content: ->
@div class: 'row'
@div class: 'pane-row'
className: ->
"PaneRow"
adjustDimensions: ->
totalUnits = @horizontalGridUnits()
unitsSoFar = 0
for child in @children()
child = $(child).view()
childUnits = child.horizontalGridUnits()
child.css
width: "#{childUnits / totalUnits * 100}%"
height: '100%'
top: 0
left: "#{unitsSoFar / totalUnits * 100}%"
child.adjustDimensions()
unitsSoFar += childUnits
horizontalGridUnits: ->
_.sum(@horizontalChildUnits())
verticalGridUnits: ->
Math.max(@verticalChildUnits()...)

View File

@@ -21,7 +21,8 @@ class Pane extends View
@content: (wrappedView) ->
@div class: 'pane', tabindex: -1, =>
@div class: 'item-views', outlet: 'itemViews'
@div class: 'flexbox-repaint-hack', =>
@div class: 'item-views', outlet: 'itemViews'
@delegatesProperties 'items', 'activeItem', toProperty: 'model'
@delegatesMethods 'getItems', 'showNextItem', 'showPreviousItem', 'getActiveItemIndex',
@@ -202,15 +203,6 @@ class Pane extends View
viewForActiveItem: ->
@viewForItem(@activeItem)
# Private:
adjustDimensions: -> # do nothing
# Private:
horizontalGridUnits: -> 1
# Private:
verticalGridUnits: -> 1
# Public: Creates a new pane above with a copy of the currently focused item.
splitUp: (items...) ->
@split(items, 'column', 'before')
@@ -248,7 +240,6 @@ class Pane extends View
switch side
when 'before' then parent.insertChildBefore(this, newPane)
when 'after' then parent.insertChildAfter(this, newPane)
@getContainer().adjustPaneDimensions()
newPane.makeActive()
newPane.focus()
newPane

View File

@@ -3,8 +3,51 @@
// Pane-items are things that go inside a pane. Like the UI-Demo, the
// settings-view, the archive-view, the image-view. Etc. Basically a non-
// editor resource with a tab.
.pane-item {
overflow: auto;
color: @text-color;
background-color: @pane-item-background-color;
.panes {
display: -webkit-flex;
-webkit-flex: 1;
.pane-column {
display: -webkit-flex;
-webkit-flex: 1;
-webkit-flex-direction: column;
}
.pane-row {
display: -webkit-flex;
-webkit-flex: 1;
-webkit-flex-direction: row;
}
.pane {
position: relative;
-webkit-flex: 1;
.flexbox-repaint-hack {
display: -webkit-flex;
-webkit-flex-flow: column;
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
}
.pane-item {
color: @text-color;
background-color: @pane-item-background-color;
}
.item-views {
-webkit-flex: 1;
display: -webkit-flex;
min-height: 0;
}
.item-views > * {
-webkit-flex: 1;
min-width: 0;
}
}
}

View File

@@ -39,49 +39,3 @@ h6 {
-webkit-flex-flow: column;
}
}
.panes {
position: relative;
-webkit-flex: 1;
.column {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
overflow-y: hidden;
}
.row {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
overflow-x: hidden;
margin: 0;
}
.pane {
position: absolute;
display: -webkit-flex;
-webkit-flex-flow: column;
top: 0;
bottom: 0;
left: 0;
right: 0;
box-sizing: border-box;
}
.pane .item-views {
-webkit-flex: 1;
display: -webkit-flex;
min-height: 0;
}
.pane .item-views > * {
-webkit-flex: 1;
min-width: 0;
}
}