[squeak-dev] The Trunk: Morphic-mt.1582.mcz

Chris Muller asqueaker at gmail.com
Thu Oct 24 23:36:31 UTC 2019


Very nice, looking forward to trying it out.

Thanks!

On Wed, Oct 23, 2019 at 8:31 AM <commits at source.squeak.org> wrote:

> Marcel Taeumel uploaded a new version of Morphic to project The Trunk:
> http://source.squeak.org/trunk/Morphic-mt.1582.mcz
>
> ==================== Summary ====================
>
> Name: Morphic-mt.1582
> Author: mt
> Time: 23 October 2019, 3:31:24.67861 pm
> UUID: 82af72b9-4198-4bd2-8e7e-e8733d9018c7
> Ancestors: Morphic-mt.1581
>
> Adds things for column-specific list filtering:
>
> - backgroundColor for LazyListMorph
> - optional filter-term indication for LazyListMorph
> - column highlights for multi-column lists
> - Character tab to cycle between columns
>
> Note that I opted to not use the [space] key for column toggling because
> (a) we have to widget-focus cycling via [tab] at the moment and (b) the
> space character might be a valuable filter term.
>
> =============== Diff against Morphic-mt.1581 ===============
>
> Item was changed:
>   Morph subclass: #LazyListMorph
> +       instanceVariableNames: 'listItems listIcons listFilterOffsets font
> selectedRow selectedRows preSelectedRow listSource maxWidth columnIndex
> iconExtent backgroundColor showFilter'
> -       instanceVariableNames: 'listItems listIcons listFilterOffsets font
> selectedRow selectedRows preSelectedRow listSource maxWidth columnIndex
> iconExtent'
>         classVariableNames: ''
>         poolDictionaries: ''
>         category: 'Morphic-Widgets'!
>
>   !LazyListMorph commentStamp: 'mt 10/13/2019 19:44' prior: 0!
>   The morph that displays the list in a PluggableListMorph.  It is "lazy"
> because it will only request the list items that it actually needs to
> display.
>
>   I will cache the maximum width of my items in maxWidth to avoid this
> potentially expensive and frequent computation.
>
>   The following layout properties are supported:
>   - #cellPositioning: #leftCenter [default], #center, #rightCenter
>   - #cellInset: [default: 3 at 0 corner: 3 at 0]!
>
> Item was added:
> + ----- Method: LazyListMorph>>backgroundColor (in category 'accessing')
> -----
> + backgroundColor
> +       "Since #color is this morph's default text color, this extra
> property is used for the actual background color. Supports nil."
> +
> +       ^ backgroundColor!
>
> Item was added:
> + ----- Method: LazyListMorph>>backgroundColor: (in category 'accessing')
> -----
> + backgroundColor: aColor
> +
> +       backgroundColor = aColor ifTrue: [^ self].
> +       backgroundColor := aColor.
> +
> +       self changed.
> +       "Invalidate owner because we want to fill the vertical axis in the
> viewport entirely."
> +       self owner ifNotNil: [:o | o changed].!
>
> Item was changed:
>   ----- Method: LazyListMorph>>displayFilterOn:for:in:font: (in category
> 'drawing') -----
>   displayFilterOn: canvas for: row in: drawBounds font: font
>         "Draw filter matches if any."
>
>         | fillStyle fillHeight |
> +       self showFilter ifFalse: [^ self].
> -       listSource filterableList ifFalse: [^ self].
>
>         fillHeight := font height.
>         fillStyle := self filterColor isColor
>                 ifTrue: [SolidFillStyle color: self filterColor]
>                 ifFalse: [self filterColor].
>         fillStyle isGradientFill ifTrue: [
>                 fillStyle origin: drawBounds topLeft.
>                 fillStyle direction: 0@ fillHeight].
>
>         (self filterOffsets: row) do: [:offset |
>                 | highlightRectangle |
>                 highlightRectangle := ((drawBounds left + offset first
> first) @ drawBounds top
>                         corner: (drawBounds left + offset first last) @
> (drawBounds top + fillHeight)).
>                 canvas
>                         frameAndFillRoundRect: (highlightRectangle
> outsetBy: 1 at 0)
>                         radius: (3 * RealEstateAgent scaleFactor) truncated
>                         fillStyle: fillStyle
>                         borderWidth: (1 * RealEstateAgent scaleFactor)
> truncated
>                         borderColor: fillStyle asColor twiceDarker.
>                 canvas
>                         drawString: offset second
>                         in: highlightRectangle
>                         font: font
>                         color: self filterTextColor].!
>
> Item was changed:
>   ----- Method: LazyListMorph>>drawOn: (in category 'drawing') -----
>   drawOn: aCanvas
>
>         | topRow bottomRow |
> +       self backgroundColor ifNotNil: [:color |
> +               aCanvas fillRectangle: (self topLeft corner: self right @
> ((self owner ifNil: [self]) bottom)) color: color].
> +
>         self getListSize = 0 ifTrue: [ ^self ].
>
>         self drawPreSelectionOn: aCanvas.
>
>         topRow := self topVisibleRowForCanvas: aCanvas.
>         bottomRow := self bottomVisibleRowForCanvas: aCanvas.
>
>         "Draw multi-selection."
>         self listSource hasMultiSelection ifTrue: [
>                 topRow to: bottomRow do: [ :row |
>                         (self listSource itemSelectedAmongMultiple: row)
> ifTrue: [
>                                 self drawBackgroundForMulti: row on:
> aCanvas ] ] ].
>         self drawSelectionOn: aCanvas.
>
>         "Draw hovered row if preference enabled."
>         PluggableListMorph highlightHoveredRow ifTrue: [
>                 self listSource hoverRow > 0 ifTrue: [
>                         self highlightHoverRow: listSource hoverRow on:
> aCanvas ] ].
>
>         "Draw all visible rows."
>         topRow to: bottomRow do: [ :row |
>                 self display: (self item: row) atRow: row on: aCanvas ].
>
>         "Finally, highlight drop row for drag/drop operations.."
>         self listSource potentialDropRow > 0 ifTrue: [
>                 self highlightPotentialDropRow: self listSource
> potentialDropRow on: aCanvas ].!
>
> Item was added:
> + ----- Method: LazyListMorph>>showFilter (in category 'accessing') -----
> + showFilter
> +
> +       ^ (showFilter ~~ false and: [listSource filterableList])!
>
> Item was added:
> + ----- Method: LazyListMorph>>showFilter: (in category 'accessing') -----
> + showFilter: aBoolean
> +
> +       showFilter = aBoolean ifTrue: [^ self].
> +       showFilter := aBoolean.
> +       self changed.!
>
> Item was added:
> + ----- Method: PluggableMultiColumnListMorph>>filterColumnColor (in
> category 'filtering') -----
> + filterColumnColor
> +
> +       ^ (Color gray: 0.85) alpha: 0.4!
>
> Item was added:
> + ----- Method: PluggableMultiColumnListMorph>>filterColumnIndex (in
> category 'filtering') -----
> + filterColumnIndex
> +       "Which column to apply the filter to?"
> +
> +       | i |
> +       i := 0.
> +       self listMorphs
> +               detect: [:m | i := i + 1. m backgroundColor notNil]
> +               ifNone: [i := 0].
> +       ^ i!
>
> Item was added:
> + ----- Method:
> PluggableMultiColumnListMorph>>filterList:columnIndex:matching: (in
> category 'filtering') -----
> + filterList: columns columnIndex: index matching: aPattern
> +       "A matching row has a match in at least one column."
> +
> +       | frontMatching substringMatching rowCount columnCount tmp |
> +       aPattern ifEmpty: [^ columns].
> +       columns ifEmpty: [^ columns].
> +
> +       rowCount := columns first size.
> +       rowCount = 0 ifTrue: [^ columns].
> +       columnCount := columns size.
> +
> +       frontMatching := Array new: columnCount.
> +       1 to: columnCount do: [:c | frontMatching at: c put:
> OrderedCollection new].
> +       substringMatching := Array new: columnCount.
> +       1 to: columnCount do: [:c | substringMatching at: c put:
> OrderedCollection new].
> +
> +       modelToView := Dictionary new.
> +       viewToModel := Dictionary new.
> +       tmp := OrderedCollection new.
> +
> +       1 to: rowCount do: [:rowIndex |
> +               | match foundPos |
> +               match := false.
> +               foundPos := self
> +                                               filterListItem: ((columns
> at: index) at: rowIndex)
> +                                               matching: aPattern.
> +               foundPos = 1
> +                       ifTrue: [
> +                               1 to: columnCount do: [:colIndex |
> +                                       (frontMatching at: colIndex) add:
> ((columns at: colIndex) at: rowIndex)].
> +                               modelToView at: rowIndex put:
> frontMatching first size.
> +                               viewToModel at: frontMatching first size
> put: rowIndex]
> +                       ifFalse: [foundPos > 1 ifTrue: [
> +                               1 to: columnCount do: [:colIndex |
> +                                       (substringMatching at: colIndex)
> add: ((columns at: colIndex) at: rowIndex)].
> +                               tmp add: rowIndex; add: substringMatching
> first size]]
> +       ].
> +
> +       tmp pairsDo: [:modelIndex :viewIndex |
> +               modelToView at: modelIndex put: viewIndex + frontMatching
> first size.
> +               viewToModel at: viewIndex + frontMatching first size put:
> modelIndex].
> +
> +       ^ (1 to: columnCount) collect: [:colIndex |
> +               (frontMatching at: colIndex), (substringMatching at:
> colIndex)]
> +
> +
> +
> +
> +
> +
> +
> +
> +
> +
> +
> +
> +
> + !
>
> Item was changed:
>   ----- Method: PluggableMultiColumnListMorph>>filterList:matching: (in
> category 'filtering') -----
>   filterList: columns matching: aPattern
>         "A matching row has a match in at least one column."
>
>         | frontMatching substringMatching rowCount columnCount tmp |
>         aPattern ifEmpty: [^ columns].
>         columns ifEmpty: [^ columns].
>
> +       "Enable column-specific filtering."
> +       self filterColumnIndex in: [:index |
> +               index > 0 ifTrue: [^ self filterList: columns columnIndex:
> index matching: aPattern]].
> +
>         rowCount := columns first size.
>         rowCount = 0 ifTrue: [^ columns].
>         columnCount := columns size.
>
>         frontMatching := Array new: columnCount.
>         1 to: columnCount do: [:c | frontMatching at: c put:
> OrderedCollection new].
>         substringMatching := Array new: columnCount.
>         1 to: columnCount do: [:c | substringMatching at: c put:
> OrderedCollection new].
>
>         modelToView := Dictionary new.
>         viewToModel := Dictionary new.
>         tmp := OrderedCollection new.
>
>         1 to: rowCount do: [:rowIndex |
>                 | match foundPos |
>                 match := false.
>                 foundPos := 0.
>                 1 to: columnCount do: [:colIndex |
>                         match := match or: [(foundPos := (self
>
> filterListItem: ((columns at: colIndex) at: rowIndex)
>
> matching: aPattern)+colIndex) > colIndex]].
>                 match & (foundPos = 2) "means front match in first column"
>                         ifTrue: [
>                                 1 to: columnCount do: [:colIndex |
>                                         (frontMatching at: colIndex) add:
> ((columns at: colIndex) at: rowIndex)].
>                                 modelToView at: rowIndex put:
> frontMatching first size.
>                                 viewToModel at: frontMatching first size
> put: rowIndex]
>                         ifFalse: [match ifTrue: [
>                                 1 to: columnCount do: [:colIndex |
>                                         (substringMatching at: colIndex)
> add: ((columns at: colIndex) at: rowIndex)].
>                                 tmp add: rowIndex; add: substringMatching
> first size]]
>         ].
>
>         tmp pairsDo: [:modelIndex :viewIndex |
>                 modelToView at: modelIndex put: viewIndex + frontMatching
> first size.
>                 viewToModel at: viewIndex + frontMatching first size put:
> modelIndex].
>
>         ^ (1 to: columnCount) collect: [:colIndex |
>                 (frontMatching at: colIndex), (substringMatching at:
> colIndex)]
>
>
>
>
>
>
>
>
>
>
>
>
>
>   !
>
> Item was added:
> + ----- Method: PluggableMultiColumnListMorph>>highlightNextColumn (in
> category 'filtering') -----
> + highlightNextColumn
> +
> +       | i currentColumn nextColumn |
> +       i := self filterColumnIndex.
> +       i = 0 ifTrue: [self listMorphs do: [:m | m showFilter: false]].
> +
> +       currentColumn := self listMorphs at: (i max: 1).
> +       nextColumn := self listMorphs at: i \\ self listMorphs size + 1.
> +
> +       currentColumn
> +               showFilter: false;
> +               backgroundColor: nil.
> +
> +       nextColumn
> +               showFilter: true;
> +               backgroundColor: self filterColumnColor.!
>
> Item was added:
> + ----- Method: PluggableMultiColumnListMorph>>highlightNoColumn (in
> category 'filtering') -----
> + highlightNoColumn
> +
> +       self listMorphs do: [:m |
> +               m showFilter: true; backgroundColor: nil].!
>
> Item was added:
> + ----- Method: PluggableMultiColumnListMorph>>removeFilter (in category
> 'filtering') -----
> + removeFilter
> +
> +       self highlightNoColumn.
> +       super removeFilter.
> + !
>
> Item was added:
> + ----- Method: PluggableMultiColumnListMorph>>specialKeyPressed: (in
> category 'filtering') -----
> + specialKeyPressed: asciiValue
> +       "Use the [Tab] key to filter specific columns."
> +
> +       ^ asciiValue = Character tab asciiValue
> +               ifTrue: [self highlightNextColumn]
> +               ifFalse: [super specialKeyPressed: asciiValue].!
>
> Item was changed:
>   ----- Method: PluggableMultiColumnListMorph>>updateColumns (in category
> 'updating') -----
>   updateColumns
>         "The number of columns must match the number of list morphs."
>
>         | columnsChanged |
>         columnsChanged := self columnCount ~= listMorphs size.
>
>         [self columnCount < listMorphs size]
>                 whileTrue: [
>                         listMorphs removeLast delete].
>
>         [self columnCount > listMorphs size]
>                 whileTrue: [
>                         listMorphs addLast: self createListMorph.
>                         self scroller addMorphBack: listMorphs last].
>
>         listMorphs doWithIndex: [:listMorph :columnIndex |
>                 listMorph
>                         columnIndex: columnIndex;
> +                       color: self textColor;
>                         cellPositioning: (self cellPositioningAtColumn:
> columnIndex);
>                         cellInset: (self cellInsetAtColumn: columnIndex);
>                         hResizing: (self hResizingAtColumn: columnIndex);
>                         spaceFillWeight: (self spaceFillWeightAtColumn:
> columnIndex)].
>
>         columnsChanged ifTrue: [self setListParameters].!
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20191024/fff5b12f/attachment.html>


More information about the Squeak-dev mailing list