Skip to content

Commit

Permalink
Synced from the Blueshift Repository
Browse files Browse the repository at this point in the history
  • Loading branch information
Blueshift Staff committed Oct 3, 2024
1 parent 8138221 commit 187e4db
Show file tree
Hide file tree
Showing 16 changed files with 122 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { ColumnOperationFactory } from './column-operations/_column-operation.fa
import { GridOperationFactory } from './grid-operations/_grid-operation.factory'
import { RowOperationFactory } from './row-operations/_row-operation.factory'
import { GridSelectionController } from './selection/grid-selection.controller'
import { MatIconRegistry } from '@angular/material/icon'

export const DATA_GRIDS_FOCUSED_TREE: string[] = []

Expand All @@ -41,13 +42,17 @@ export class GridControllerService {

private _subs : Set<Subscription> = new Set()

public iconClass = this.iconRegistry.getDefaultFontSetClass().filter((fontSetClass) => fontSetClass.includes('material') || fontSetClass.includes('symbols'))[0]
?? this.iconRegistry.getDefaultFontSetClass()[0];

constructor(
private readonly events : GridEventsService,
public readonly prefs : LocalPreferencesService,
public readonly localize: LocalizationService,
public readonly datePipe: DatePipe,
public readonly dialogs : MatDialog,
public readonly uploads : GridFileUploadService,
private readonly iconRegistry: MatIconRegistry,
icons: IconsService,
) {

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { fromEvent, merge, Subject } from 'rxjs'
import { fromEvent, merge, Observable, Subject } from 'rxjs'
import { distinctUntilChanged, map, takeUntil } from 'rxjs/operators'

import {
Expand All @@ -19,25 +19,24 @@ export class MultiRowSelectionStrategy implements IGridSelectionStrategy {
constructor(public readonly controller: ISelectionController) { }

public attach(el: HTMLElement): void {
this._keyboardHandling()
this.controller.addSubscription(fromEvent(window.document.documentElement, 'mouseup').subscribe(_ => this._mouseReleased.next(true)))
this.controller.addSubscription(fromEvent<MouseEvent>(el, 'mousedown').subscribe(e => this._startSelection(e)))
this._keyboardHandling()
}

private _startSelection(e: MouseEvent): void {
// button 0 = Left Mouse Button
if (e.button !== 0 || !HasParentOfClass('cell', e.target as HTMLElement)) return
this._gridEvents.CellSelectionStartedEvent.emit(true)

let state = this.controller.CreateSelectionStateFromMouseEvent.run({
ctrlKey: !e.shiftKey && typeof this.controller.state?.previousSelection !== 'undefined',
shiftKey: e.shiftKey,
target: e.target
})

if (!HasParentOfClass('cell', e.target as HTMLElement)) return
let state = this.controller.CreateSelectionStateFromMouseEvent.run(e)
if (!state) return

e.preventDefault() // stops native html element dragging
const lastSelection = this.controller.latestSelection()
// button 2 = Right Mouse Button
if (e.button === 2 && lastSelection?.includes(state.startCellPos) === true) return

this._gridEvents.CellSelectionStartedEvent.emit(true)

// button 0 = Left Mouse Button
if (e.button === 0) e.preventDefault() // stops native html element dragging

this.controller.state = state

Expand All @@ -49,7 +48,9 @@ export class MultiRowSelectionStrategy implements IGridSelectionStrategy {
this.controller.CalculateNextSelection.run()

const focusChanged = this.controller.EmitFocusedCell.run()
if (focusChanged) state.previousSelection = state.currentSelection.clone()
if (focusChanged) {
state.previousSelection = state.currentSelection.clone()
}

this._continueSelection()
}
Expand All @@ -59,12 +60,20 @@ export class MultiRowSelectionStrategy implements IGridSelectionStrategy {
const state = this.controller.state
if (!state) throw new Error('Selection state is undefined')

this._gridEvents.RowMouseEnteredEvent.on()
.pipe(removeNullish(), takeUntil(merge(this._windowFocusChanged, this._mouseReleased)))
.subscribe(rowComponent => {
const event: Observable<IGridCellCoordinates> = state.isRowSelection ?
this._gridEvents.RowMouseEnteredEvent.onWithInitialValue().pipe(removeNullish(), map(row => row.lastCellPosition)) :
this._gridEvents.CellMouseEnteredEvent.onWithInitialValue().pipe(removeNullish(), map(cell => new GridCellCoordinates( cell.rowComponent.rowKey, cell.column.columnKey )))

event
.pipe(takeUntil(merge(this._windowFocusChanged, this._mouseReleased)))
.subscribe(endCellPos => {
const nextSelection = (state.hasShiftKey && state.previousSelection ? state.previousSelection : state.initialSelection).clone()
this.controller.CalculateNextSelection.run(nextSelection, state.startCellPos, rowComponent.lastCellPosition)
const columns = this.controller.gridController.dataSource.columns
const lastColumnKey = columns[columns.length - 1].columnKey
const firstColumnKey = columns[0].columnKey
this.controller.CalculateNextSelection.run(nextSelection, new GridCellCoordinates(state.startCellPos.rowKey, firstColumnKey), new GridCellCoordinates(endCellPos.rowKey, lastColumnKey))
this._emitSelection(nextSelection)
this.controller.EmitNextSelectionSlice.run()
})
.add(() => {
const finalSelection = this.controller.GetFinalSelection.run()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ export class StandardSelectionStrategy implements IGridSelectionStrategy {
constructor(public readonly controller: ISelectionController) { }

public attach(el: HTMLElement): void {

this.controller.addSubscription(fromEvent(window.document.documentElement, 'mouseup').subscribe(_ => this._mouseReleased.next(true)))
this.controller.addSubscription(fromEvent<MouseEvent>(el, 'mousedown').subscribe(e => this._startSelection(e)))
this._keyboardHandling()
Expand Down
1 change: 1 addition & 0 deletions projects/ngx-grid-core/src/lib/events/row/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ export * from "./row-status-changed.event"
export * from "./rows-committed.event"
export * from "./rows-inserted.event"
export * from "./rows-reverted.event"
export * from "./row-double-clicked.event"
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { IGridRowComponent } from '../../typings/interfaces'
import { BaseGridEventAbstract } from '../base-grid-event.abstract'
import { GridEventsService } from '../grid-events.service'

export class RowDoubleClickedEvent extends BaseGridEventAbstract<IGridRowComponent> {
public readonly eventName = 'RowDoubleClickedEvent'
constructor(eventService: GridEventsService) { super(eventService) }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export interface IIconCellValue {
key: string
size: number
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { BehaviorSubject } from 'rxjs'

import { GridControllerService } from '../../../controller/grid-controller.service'
import { GridOverlayService } from '../../../services/grid-overlay-service.service'
import { ECellMode } from '../../../typings/enums/cell-mode.enum'
import { IGridCellComponent } from '../../../typings/interfaces'
import { BaseCellType } from './abstractions/base-cell-type.abstract'
import { IIconCellValue } from '../../../typings/interfaces/icon-cell-value.interface'

export class IconCellType extends BaseCellType {

public mode = new BehaviorSubject<ECellMode>(ECellMode.Readonly)

private _displayNode?: HTMLElement

constructor(
gridController: GridControllerService,
overlayService: GridOverlayService,
parentCell : IGridCellComponent
) { super(overlayService, parentCell, gridController) }

public get displayNode() { return this._displayNode ?? this._generateDisplayNode() }
public get editableNode() { return this.displayNode }

public override receiveValue(value: IIconCellValue | null = this.value): void {
super.receiveValue(value)
if (!this._displayNode) return;
else
{
this._displayNode.innerText = value?.key ?? ''
this._displayNode.style.fontSize = value?.size + 'px'
}
if (!value) this._displayNode.style.display = 'none'
else this._displayNode.style.display = ''
}

private _generateDisplayNode(): HTMLElement {
const node = document.createElement('span')
node.classList.add(this.gridController.iconClass)
this._displayNode = node
this.receiveValue()
return this._displayNode
}

public override measureWidth(): number {
return this.value?.size ?? 0
}

}
4 changes: 3 additions & 1 deletion projects/ngx-grid-core/src/lib/ui/cell/cell-types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { NumberCellType as Number } from './number.cell-type'
import { RichTextCellType as RichText } from './rich-text.cell-type'
import { TextCellType as Text } from './text.cell-type'
import { ButtonCellType as Button } from './button.cell-type'
import { IconCellType as Icon } from './icon.cell-type'

/* eslint-disable @typescript-eslint/naming-convention */
const CELL_TYPES = {
Expand All @@ -24,7 +25,8 @@ const CELL_TYPES = {
DropdownMultiSelect,
File,
Color,
Button
Button,
Icon
}

export default CELL_TYPES
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,5 @@ export const CELL_MULTI_EDITORS: {[key in TCellTypeName]: Array<new (cellValue:
File : [ editors.ClearValues ],
Color : [ editors.ClearValues ],
Button : [],
Icon : [],
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,5 @@ export const CELL_VALUE_PARSERS: {[key in TCellTypeName]: ICellValueParser} = {
DateRange : new ValueParser([parsers.Array]),
NumberRange : new ValueParser([parsers.Array]),
Button : new ValueParser([parsers.Button]),
Icon : new ValueParser([parsers.Icon]),
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { IGridValueParsingResult } from '../../../../../typings/interfaces'
import { BaseParser } from './base-parser.abstract'
import { IParsingTest } from './parsing-test.interface'

export class IconParser extends BaseParser implements IParsingTest {
constructor (public readonly initialValue: any) { super() }

public run(): IGridValueParsingResult<any[]> {
const val = this.initialValue
// IIconCellValue
if (typeof val === 'object' && val !== null && !Array.isArray(val) && 'key' in val && 'size' in val && typeof val.size === 'number') {
return this.passed(val)
}
return this.failed()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { NumberParser as Number } from './number.parser'
import { StringParser as String } from './string.parser'
import { AnyParser as Any } from './any.parser'
import { ButtonParser as Button } from './button.parser'
import { IconParser as Icon } from './icon.parser'

export {
Array,
Expand All @@ -19,5 +20,6 @@ export {
File,
Color,
Any,
Button
Button,
Icon
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, Inje
import { FormControl } from '@angular/forms'
import { debounceTime, distinctUntilChanged, filter, map, pairwise, startWith } from 'rxjs/operators'

import { DataGridConfigs } from '../../../data-grid-configs.class'
import { GridDataSource } from '../../../grid-data-source'
import { GRID_OVERLAY_DATA } from '../../../services/grid-overlay-service.service'
import { EForeignKeyDropdownState } from '../../../typings/enums'
Expand All @@ -27,8 +26,6 @@ export class MultiSelectForeignKeyDropdownOverlayComponent extends BaseOverlayCo
public values: TPrimaryKey[] = []
public searchCtrl = new FormControl()

public gridConfig = new DataGridConfigs().withRowMultiSelect().withConfigs({ scrollToPreselected: false })

public loadingState = this.gridController.gridEvents
.ForeignKeyDropdownStateChangedEvent
.on()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, In
import { Subject } from 'rxjs'
import { debounceTime, repeat, takeUntil } from 'rxjs/operators'

import { DataGridConfigs } from '../../../data-grid-configs.class'
import { GridDataSource } from '../../../grid-data-source'
import { GRID_OVERLAY_DATA } from '../../../services/grid-overlay-service.service'
import { IGridDataSource, IGridOverlayData, IGridRecordSelectedEvent } from '../../../typings/interfaces'
Expand All @@ -22,8 +21,6 @@ export class MultiSelectGridSelectedListComponent extends BaseOverlayComponent i
public dataSource?: IGridDataSource
public values : TPrimaryKey[] = []
public dataSetName = ''

public gridConfig = new DataGridConfigs().withRowMultiSelect()

private _valueUpdated = new Subject<void>()
private _updateDataNext = new Subject<any>()
Expand Down
3 changes: 3 additions & 0 deletions projects/ngx-grid-core/src/lib/ui/row/row.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,9 @@ export class RowComponent extends AutoUnsubscribe implements OnInit, OnChanges,

@HostListener('mouseenter')
public mouseEntered = () => this.events.factory.RowMouseEnteredEvent.emit(this)

@HostListener('dblclick')
public dblClick = () => this.events.factory.RowDoubleClickedEvent.emit(this)

public indexOf = (columnKey: string) => { return this.columns.findIndex(c => c.columnKey === columnKey) }
public cellColumnKey = (i: number) => this.columns[i]
Expand Down
1 change: 1 addition & 0 deletions projects/ngx-grid-core/src/public-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,4 @@ export * from './lib/services/grid-multi-cell-edit.service'
export * from './lib/controller/transform-pipeline/transformer.abstract'
export * from './lib/controller/transform-pipeline/transform-pipeline.abstract'
export * from './lib/controller/transform-pipeline/generic-transformer'
export * from './lib/controller/selection/strategies'

0 comments on commit 187e4db

Please sign in to comment.