Kaynağa Gözat

forgot files

Adam Shaw 7 yıl önce
ebeveyn
işleme
c2e5f32b7b

+ 89 - 0
src/agenda/TimeGridSlicer.ts

@@ -0,0 +1,89 @@
+import DateProfileGenerator, { DateProfile } from '../DateProfileGenerator'
+import { DateRange, intersectRanges } from '../datelib/date-range'
+import DaySeries from '../component/DaySeries'
+import { Seg } from '../component/DateComponent'
+import { DateEnv } from '../datelib/env'
+
+export default class TimeGridSlicer {
+
+  dateProfile: DateProfile
+  daySeries: DaySeries
+  dateRanges: DateRange[]
+  isRtl: boolean
+  colCnt: number
+
+
+  constructor(dateProfile: DateProfile, dateProfileGenerator: DateProfileGenerator, isRtl: boolean, dateEnv: DateEnv) {
+    this.dateProfile = dateProfile
+    this.daySeries = new DaySeries(dateProfile, dateProfileGenerator)
+    this.dateRanges = this.daySeries.dates.map(function(dayDate) {
+      return {
+        start: dateEnv.add(dayDate, dateProfile.minTime),
+        end: dateEnv.add(dayDate, dateProfile.maxTime)
+      }
+    })
+    this.isRtl = isRtl
+    this.colCnt = this.daySeries.dates.length
+  }
+
+
+  // Slices up the given span (unzoned start/end with other misc data) into an array of segments
+  rangeToSegs(range: DateRange): Seg[] {
+
+    range = intersectRanges(range, this.dateProfile.validRange)
+
+    if (range) {
+      let segs = this.sliceRangeByTimes(range)
+      let i
+
+      for (i = 0; i < segs.length; i++) {
+        if (this.isRtl) {
+          segs[i].col = this.daySeries.dates.length - 1 - segs[i].dayIndex
+        } else {
+          segs[i].col = segs[i].dayIndex
+        }
+
+        segs[i].component = this
+      }
+
+      return segs
+    } else {
+      return []
+    }
+  }
+
+
+  sliceRangeByTimes(range) {
+    let { dateRanges } = this
+    let segs = []
+    let segRange
+    let dayIndex
+
+    for (dayIndex = 0; dayIndex < dateRanges.length; dayIndex++) {
+
+      segRange = intersectRanges(range, dateRanges[dayIndex])
+
+      if (segRange) {
+        segs.push({
+          start: segRange.start,
+          end: segRange.end,
+          isStart: segRange.start.valueOf() === range.start.valueOf(),
+          isEnd: segRange.end.valueOf() === range.end.valueOf(),
+          dayIndex: dayIndex
+        })
+      }
+    }
+
+    return segs
+  }
+
+
+  getColDate(col: number) {
+    if (this.isRtl) {
+      col = this.colCnt - 1 - col
+    }
+
+    return this.daySeries.dates[col]
+  }
+
+}

+ 150 - 0
src/basic/DayGridSlicer.ts

@@ -0,0 +1,150 @@
+import { DateRange, intersectRanges } from '../datelib/date-range'
+import DateProfileGenerator, { DateProfile } from '../DateProfileGenerator'
+import { Seg } from '../component/DateComponent'
+import { addDays, DateMarker } from '../datelib/marker'
+import DaySeries from '../component/DaySeries'
+
+
+export default class DayGridSlicer {
+
+  dateProfile: DateProfile
+  daySeries: DaySeries
+  daysPerRow: number
+  isRtl: boolean
+  rowCnt: number
+  colCnt: number
+
+
+  constructor(dateProfile: DateProfile, dateProfileGenerator: DateProfileGenerator, isRtl: boolean, breakOnWeeks: boolean) {
+    let daySeries = new DaySeries(dateProfile, dateProfileGenerator)
+    let { dates } = daySeries
+    let daysPerRow
+    let firstDay
+    let rowCnt
+
+    if (breakOnWeeks) {
+      // count columns until the day-of-week repeats
+      firstDay = dates[0].getUTCDay()
+      for (daysPerRow = 1; daysPerRow < dates.length; daysPerRow++) {
+        if (dates[daysPerRow].getUTCDay() === firstDay) {
+          break
+        }
+      }
+      rowCnt = Math.ceil(dates.length / daysPerRow)
+    } else {
+      rowCnt = 1
+      daysPerRow = dates.length
+    }
+
+    this.dateProfile = dateProfile
+    this.daySeries = daySeries
+    this.daysPerRow = daysPerRow
+    this.isRtl = isRtl
+    this.rowCnt = rowCnt
+    this.colCnt = daysPerRow
+  }
+
+
+  // Slices up the given span (unzoned start/end with other misc data) into an array of segments
+  rangeToSegs(range: DateRange): Seg[] {
+
+    range = intersectRanges(range, this.dateProfile.validRange)
+
+    if (range) {
+      let segs = this.sliceRangeByRow(range)
+
+      for (let i = 0; i < segs.length; i++) {
+        let seg = segs[i]
+        seg.component = this
+
+        if (this.isRtl) {
+          seg.leftCol = this.daysPerRow - 1 - seg.lastRowDayIndex
+          seg.rightCol = this.daysPerRow - 1 - seg.firstRowDayIndex
+        } else {
+          seg.leftCol = seg.firstRowDayIndex
+          seg.rightCol = seg.lastRowDayIndex
+        }
+      }
+
+      return segs
+    } else {
+      return []
+    }
+  }
+
+
+  // Slices up a date range into a segment for every week-row it intersects with
+  // range already normalized to start-of-day
+  sliceRangeByRow(range) {
+    let daysPerRow = this.daysPerRow
+    let rangeFirst = this.daySeries.getDateDayIndex(range.start) // inclusive first index
+    let rangeLast = this.daySeries.getDateDayIndex(addDays(range.end, -1)) // inclusive last index
+    let segs = []
+    let row
+    let rowFirst
+    let rowLast // inclusive day-index range for current row
+    let segFirst
+    let segLast // inclusive day-index range for segment
+
+    for (row = 0; row < this.rowCnt; row++) {
+      rowFirst = row * daysPerRow
+      rowLast = rowFirst + daysPerRow - 1
+
+      // intersect segment's offset range with the row's
+      segFirst = Math.max(rangeFirst, rowFirst)
+      segLast = Math.min(rangeLast, rowLast)
+
+      // deal with in-between indices
+      segFirst = Math.ceil(segFirst) // in-between starts round to next cell
+      segLast = Math.floor(segLast) // in-between ends round to prev cell
+
+      if (segFirst <= segLast) { // was there any intersection with the current row?
+        segs.push({
+          row: row,
+
+          // normalize to start of row
+          firstRowDayIndex: segFirst - rowFirst,
+          lastRowDayIndex: segLast - rowFirst,
+
+          // must be matching integers to be the segment's start/end
+          isStart: segFirst === rangeFirst,
+          isEnd: segLast === rangeLast
+        })
+      }
+    }
+
+    return segs
+  }
+
+
+  // Computes the DateMarker for the given cell
+  getCellDate(row, col): DateMarker {
+    return this.daySeries.dates[this.getCellDayIndex(row, col)]
+  }
+
+
+  // Computes the ambiguously-timed date range for the given cell
+  getCellRange(row, col): DateRange {
+    let start = this.getCellDate(row, col)
+    let end = addDays(start, 1)
+
+    return { start, end }
+  }
+
+
+  // Returns the number of day cells, chronologically, from the first of the grid (0-based)
+  private getCellDayIndex(row, col) {
+    return row * this.daysPerRow + this.getColDayIndex(col)
+  }
+
+
+  // Returns the numner of day cells, chronologically, from the first cell in *any given row*
+  private getColDayIndex(col) {
+    if (this.isRtl) {
+      return this.colCnt - 1 - col
+    } else {
+      return col
+    }
+  }
+
+}

+ 49 - 0
src/component/DaySeries.ts

@@ -0,0 +1,49 @@
+import DateProfileGenerator, { DateProfile } from '../DateProfileGenerator'
+import { DateMarker, addDays, diffDays } from '../datelib/marker'
+
+export default class DaySeries {
+
+  dates: DateMarker[] // whole-day dates for each column. left to right
+  indices: number[] // for each day from start, the offset
+
+  constructor(dateProfile: DateProfile, dateProfileGenerator: DateProfileGenerator) {
+    let date: DateMarker = dateProfile.renderRange.start
+    let end: DateMarker = dateProfile.renderRange.end
+    let indices: number[] = []
+    let dates: DateMarker[] = []
+    let dayIndex = -1
+
+    while (date < end) { // loop each day from start to end
+      if (dateProfileGenerator.isHiddenDay(date)) {
+        indices.push(dayIndex + 0.5) // mark that it's between indices
+      } else {
+        dayIndex++
+        indices.push(dayIndex)
+        dates.push(date)
+      }
+      date = addDays(date, 1)
+    }
+
+    this.dates = dates
+    this.indices = indices
+  }
+
+  // Given a date, returns its chronolocial cell-index from the first cell of the grid.
+  // If the date lies between cells (because of hiddenDays), returns a floating-point value between offsets.
+  // If before the first offset, returns a negative number.
+  // If after the last offset, returns an offset past the last cell offset.
+  // Only works for *start* dates of cells. Will not work for exclusive end dates for cells.
+  getDateDayIndex(date: DateMarker) {
+    let indices = this.indices
+    let dayOffset = Math.floor(diffDays(this.dates[0], date))
+
+    if (dayOffset < 0) {
+      return indices[0] - 1
+    } else if (dayOffset >= indices.length) {
+      return indices[indices.length - 1] + 1
+    } else {
+      return indices[dayOffset]
+    }
+  }
+
+}