Skip to content

Commit

Permalink
I am starting to add a basic table view to Morphic.
Browse files Browse the repository at this point in the history
  • Loading branch information
ronsaldo committed Nov 27, 2023
1 parent bc1f9c1 commit 24ab029
Show file tree
Hide file tree
Showing 18 changed files with 461 additions and 22 deletions.
7 changes: 7 additions & 0 deletions package-sources/Morphic.Core/DataSource.sysmel
@@ -0,0 +1,7 @@
public abstract class DataSource definition: {
public abstract method numberOfElements => Size
:= self subclassResponsibility.

public abstract method elementAtRow: (rowIndex: Size) ::=> AnyValue
:= self subclassResponsibility.
}.
20 changes: 20 additions & 0 deletions package-sources/Morphic.Core/ListViewMorph.sysmel
@@ -0,0 +1,20 @@
public class ListViewMorph superclass: TableViewMorph; definition: {
protected field listDataSource => SimpleListDataSource.

public override method initialize => Void := {
super initialize.
listDataSource := SimpleListDataSource new.
self dataSource: listDataSource.
}.

public method removeAll => Void := {
listDataSource removeAll.
self changed.
}.

public method addItem: item ::=> Size := {
let index := listDataSource addItem: item.
self changed.
index
}.
}.
27 changes: 21 additions & 6 deletions package-sources/Morphic.Core/Morph.sysmel
Expand Up @@ -73,11 +73,14 @@ public class Morph superclass: MorphLayoutElement; definition: {
builder translate: localSceneGraph -- childrenSceneGraph with: self position
}.

public virtual method validSubmorphs => Array
:= submorphs.

public virtual method buildChildrenSceneGraphWith: (builder: FormSGBuilder) ::=> FormSGNode := {
submorphs isEmpty ifTrue: {return: builder null}.
self validSubmorphs isEmpty ifTrue: {return: builder null}.

let nodeSceneGraphList := Array new: submorphs size.
submorphs doWithIndex: {:(Morph)childMorph :(Size)childMorphIndex :: Void |
let nodeSceneGraphList := Array new: self validSubmorphs size.
self validSubmorphs doWithIndex: {:(Morph)childMorph :(Size)childMorphIndex :: Void |
nodeSceneGraphList at: childMorphIndex put: (childMorph buildFullSceneGraphWith: builder)
}.

Expand Down Expand Up @@ -135,6 +138,18 @@ public class Morph superclass: MorphLayoutElement; definition: {
submorphs := #().
}.

public method replaceAllMorphsWith: (newMorphs: Collection) ::=> Void := {
self removeAllMorphs.

let newSubmorphs := Array new: newMorphs size.
newMorphs doWithIndex: {:(Morph)each :(Size)index :: Void |
each owner: self.
newSubmorphs at: index put: each.
}.

submorphs := newSubmorphs.
}.

public method removeMorph: (morph: Morph) ::=> Void := {
self assert: morph owner == self.
submorphs := submorphs copyWithout: morph
Expand All @@ -146,7 +161,7 @@ public class Morph superclass: MorphLayoutElement; definition: {

public virtual method processMouseButtonPressedEvent: (event: MouseButtonPressedEvent) ::=> Void := {
event withLocalTranslation: self position do: {:: Void |
submorphs reverseDo: {:(Morph)each :: Void |
self validSubmorphs reverseDo: {:(Morph)each :: Void |
(each bounds includesPoint: event position) ifTrue: {
each processMouseButtonPressedEvent: event
}
Expand All @@ -164,7 +179,7 @@ public class Morph superclass: MorphLayoutElement; definition: {

public virtual method processMouseButtonReleasedEvent: (event: MouseButtonReleasedEvent) ::=> Void := {
event withLocalTranslation: self position do: {:: Void |
submorphs reverseDo: {:(Morph)each :: Void |
self validSubmorphs reverseDo: {:(Morph)each :: Void |
(each bounds includesPoint: event position) ifTrue: {
each processMouseButtonReleasedEvent: event
}
Expand All @@ -182,7 +197,7 @@ public class Morph superclass: MorphLayoutElement; definition: {

public virtual method processMouseMoveEvent: (event: MouseMoveEvent) ::=> Void := {
event withLocalTranslation: self position do: {:: Void |
submorphs reverseDo: {:(Morph)each :: Void |
self validSubmorphs reverseDo: {:(Morph)each :: Void |
(each bounds includesPoint: event position) ifTrue: {
each processMouseMoveEvent: event
}
Expand Down
6 changes: 3 additions & 3 deletions package-sources/Morphic.Core/MorphBoxLayout.sysmel
Expand Up @@ -6,17 +6,17 @@ public abstract class MorphBoxLayout superclass: MorphLayout; definition: {
elements := OrderedCollection new.
}.

public method add: (target: MorphLayoutElement) proportion: (proportion: UInt32) borderWidth: (borderWidth: Float32) ::=> Void := {
public method add: (target: MorphLayoutElement) proportion: (proportion: Float32) borderWidth: (borderWidth: Float32) ::=> Void := {
elements add: (MorphBoxLayoutElement new
target: target;
proportion: proportion;
borderWidth: borderWidth;
yourself)
}.

public method add: (target: MorphLayoutElement) proportion: (proportion: UInt32) ::=> Void
public method add: (target: MorphLayoutElement) proportion: (proportion: Float32) ::=> Void
:= self add: target proportion: proportion borderWidth: 0f32.

public method add: (element: MorphLayoutElement) ::=> Void
:= self add: element proportion: 0u32.
:= self add: element proportion: 0f32.
}.
4 changes: 2 additions & 2 deletions package-sources/Morphic.Core/MorphBoxLayoutElement.sysmel
@@ -1,13 +1,13 @@
public class MorphBoxLayoutElement superclass: MorphLayoutElement; definition: {
public field target => MorphLayoutElement.
public field proportion => UInt32.
public field proportion => Float32.
public field borderWidth => Float32.

public override method bounds => RectangleF32
:= target bounds expandBy: borderWidth@borderWidth.

public override method bounds: (newBounds: RectangleF32) ::=> Void := {
proportion = 0u32 ifTrue: {
proportion = 0f32 ifTrue: {
target position: newBounds min + (borderWidth@borderWidth)
} ifFalse: {
target bounds: (newBounds insetBy: borderWidth@borderWidth)
Expand Down
8 changes: 4 additions & 4 deletions package-sources/Morphic.Core/MorphHorizontalBoxLayout.sysmel
@@ -1,12 +1,12 @@
public class MorphHorizontalBoxLayout superclass: MorphBoxLayout; definition: {
public override method bounds: (newBounds: RectangleF32) ::=> Void := {
let usedWidth mutable := 0f32.
let totalProportion mutable := 0u32.
let totalProportion mutable := 0f32.

## Compute the used height and the total proportion.
elements do: {:(MorphBoxLayoutElement)element :: Void |
let proportion := element proportion.
proportion = 0u32 ifTrue: {
proportion = 0f32 ifTrue: {
usedWidth := usedWidth + element bounds width
} ifFalse: {
totalProportion := totalProportion + proportion
Expand All @@ -22,9 +22,9 @@ public class MorphHorizontalBoxLayout superclass: MorphBoxLayout; definition: {
let destY := newBounds min y.
elements do: {:(MorphBoxLayoutElement)element :: Void |
let proportion := element proportion.
let elementWidth := proportion = 0u32
let elementWidth := proportion = 0f32
ifTrue: (element bounds width)
ifFalse: (availableWidth * proportion asFloat32 / totalProportion asFloat32).
ifFalse: (availableWidth * proportion / totalProportion).

let elementBounds := destX@destY extent: elementWidth@availableHeight.
element bounds: elementBounds.
Expand Down
8 changes: 4 additions & 4 deletions package-sources/Morphic.Core/MorphVerticalBoxLayout.sysmel
@@ -1,12 +1,12 @@
public class MorphVerticalBoxLayout superclass: MorphBoxLayout; definition: {
public override method bounds: (newBounds: RectangleF32) ::=> Void := {
let usedHeight mutable := 0f32.
let totalProportion mutable := 0u32.
let totalProportion mutable := 0f32.

## Compute the used height and the total proportion.
elements do: {:(MorphBoxLayoutElement)element :: Void |
let proportion := element proportion.
proportion = 0u32 ifTrue: {
proportion = 0f32 ifTrue: {
usedHeight := usedHeight + element bounds height
} ifFalse: {
totalProportion := totalProportion + proportion
Expand All @@ -21,9 +21,9 @@ public class MorphVerticalBoxLayout superclass: MorphBoxLayout; definition: {
let destY mutable := newBounds min y.
elements do: {:(MorphBoxLayoutElement)element :: Void |
let proportion := element proportion.
let elementHeight := proportion = 0u32
let elementHeight := proportion = 0f32
ifTrue: (element bounds height)
ifFalse: (availableHeight * proportion asFloat32 / totalProportion asFloat32).
ifFalse: (availableHeight * proportion / totalProportion).

let elementBounds := destX@destY extent: availableWidth@elementHeight.
element bounds: elementBounds.
Expand Down
26 changes: 26 additions & 0 deletions package-sources/Morphic.Core/SimpleListDataSource.sysmel
@@ -0,0 +1,26 @@
public class SimpleListDataSource superclass: DataSource; definition: {
public field items => OrderedCollection.

public override method initialize => Void := {
super initialize.
items := OrderedCollection new.
}.

public override method numberOfElements => Size
:= items size.

public override method elementAtRow: (rowIndex: Size) ::=> AnyValue
:= rowIndex < items size
ifTrue: (items at: rowIndex)
ifFalse: nil.

public method removeAll => Void := {
items removeAll
}.

public method addItem: item ::=> Size := {
let index := items size.
items add: item.
index
}.
}.
17 changes: 17 additions & 0 deletions package-sources/Morphic.Core/StringTableViewColumn.sysmel
@@ -0,0 +1,17 @@
public class StringTableViewColumn superclass: TableViewColumn; definition: {
let DisplayBlockType := (AnyValue) => String.

public field display => DisplayBlockType.

public override method initialize => Void := {
super initialize.
display := {:element :: String | element asString }.
}.

public override method createCellMorphForElement: element ::=> Morph
:= display(element) asMorph.

public override method updateCellMorph: (morph: Morph) withElement: element ::=> Void := {
(morph downCastTo: StringMorph) contents: display(element)
}.
}.
16 changes: 16 additions & 0 deletions package-sources/Morphic.Core/TableRowSelection.sysmel
@@ -0,0 +1,16 @@
public class TableRowSelection definition: {
public field selectedIndices => Array.

__Meta__ definition: {
public method with: (index: Size) ::=> self
:= self new selectedIndices: (Array with: index); yourself
}.

public override method initialize => Void := {
super initialize.
selectedIndices := #().
}.

public method includesRowIndex: (index: Size) ::=> Boolean
:= selectedIndices includes: index.
}.
14 changes: 14 additions & 0 deletions package-sources/Morphic.Core/TableViewColumn.sysmel
@@ -0,0 +1,14 @@
public abstract class TableViewColumn definition: {
public field name => String.
public field width => Float32.

public virtual method minimalCellExtent ::=> Float32x2
:= 0f32 @ FontFace default height.

public virtual method createCellMorphForElement: element ::=> Morph
:= Morph new.

public virtual method updateCellMorph: (morph: Morph) withElement: element ::=> Void := {
## By default do nothing.
}.
}.
122 changes: 122 additions & 0 deletions package-sources/Morphic.Core/TableViewContentMorph.sysmel
@@ -0,0 +1,122 @@
TableViewContentMorph definition: {
protected field visibleRows => Array.

public override method initialize => Void := {
super initialize.
visibleRows := #().
}.

public method tableViewMorph => TableViewMorph
:= owner downCastTo: TableViewMorph.

public method dataSource => DataSource
:= self tableViewMorph dataSource.

public method columns => OrderedCollection
:= self tableViewMorph columns.

public method rowHeight => Float32
:= self tableViewMorph rowHeight.

public override method defaultColor => Color
:= Color transparent.

public override method validSubmorphs => Array := {
self ensureThatVisibleRowsExists.
super validSubmorphs
}.

public method updateContent => Void := {
self ensureThatVisibleRowsExists.
visibleRows do: {:(TableViewRowMorph)eachRow :: Void |
eachRow updateContent
}
}.

public override method updateLayout => Void := {
let rowHeight := self rowHeight.
let rowExtent := self extent x @ rowHeight.

visibleRows do: {:(TableViewRowMorph)eachRow :: Void |
let rowPosition := 0f32 @ (eachRow rowIndex asFloat32 * rowHeight).
eachRow bounds: (rowPosition extent: rowExtent)
}.
}.

public method computeVisibleRowRangeFrom: (firstVisibleRow: Size ref) to: (lastVisibleRow: Size ref) ::=> Void := {
let visibleBounds := self localBounds.
let rowHeight := self rowHeight.
let dataSource := self dataSource.
let elementCount := dataSource ifNil: 0sz ifNotNil: dataSource numberOfElements.
let maxRowIndex := elementCount > 0sz ifTrue: elementCount - 1sz ifFalse: 0sz.

firstVisibleRow := ((visibleBounds min y / rowHeight) floor max: 0f32) asSize min: maxRowIndex.
lastVisibleRow := ((visibleBounds max y / rowHeight) ceiling max: 0f32) asSize min: maxRowIndex.
}.

public method ensureThatVisibleRowsExists => Void := {
let dataSource := self dataSource.
dataSource isNil || (dataSource numberOfElements = 0sz) ifTrue: {
self removeAllMorphs.
visibleRows := #().
return: void
}.

let firstVisibleRowIndex mutable := 0sz.
let lastVisibleRowIndex mutable := 0sz.
self computeVisibleRowRangeFrom: firstVisibleRowIndex to: lastVisibleRowIndex.

visibleRows isNotEmpty &&
(firstVisibleRowIndex = visibleRows first rowIndex) &&
(lastVisibleRowIndex = visibleRows last rowIndex) ifTrue: {
return: void
}.

let overlappingRows := visibleRows select: {:(TableViewRowMorph)eachRowMorph :: Boolean |
(firstVisibleRowIndex <= eachRowMorph rowIndex) && (eachRowMorph rowIndex <= lastVisibleRowIndex)
}.

let previousEndIndex := overlappingRows isEmpty
ifTrue: (firstVisibleRowIndex)
ifFalse: (overlappingRows first rowIndex).
let nextStartIndex := overlappingRows isEmpty
ifTrue: (firstVisibleRowIndex)
ifFalse: (overlappingRows last rowIndex + 1sz).

let newVisibleRows := OrderedCollection new.

{
let i mutable := firstVisibleRowIndex.
while: (i < previousEndIndex) do: {
let rowMorph := TableViewRowMorph new.
self addMorph: rowMorph.

newVisibleRows add: (rowMorph
rowIndex: i;
createCells;
updateContent;
yourself)
} continueWith: (i := i + 1sz).
}.

newVisibleRows addAll: overlappingRows.

{
let i mutable := nextStartIndex.
while: (i <= lastVisibleRowIndex) do: {
let rowMorph := TableViewRowMorph new.
self addMorph: rowMorph.

newVisibleRows add: (rowMorph
rowIndex: i;
createCells;
updateContent;
yourself)
} continueWith: (i := i + 1sz).
}.

visibleRows := newVisibleRows asArray.
self replaceAllMorphsWith: visibleRows.
self updateLayout.
}.
}.
3 changes: 3 additions & 0 deletions package-sources/Morphic.Core/TableViewHeaderMorph.sysmel
@@ -0,0 +1,3 @@
TableViewHeaderMorph definition: {

}.

0 comments on commit 24ab029

Please sign in to comment.