Explorar el Código

get grid/views onboard with removing footprint concept

Adam Shaw hace 7 años
padre
commit
3b34a4bae2

+ 25 - 27
src/View.ts

@@ -8,12 +8,12 @@ import DateProfileGenerator from './DateProfileGenerator'
 import InteractiveDateComponent from './component/InteractiveDateComponent'
 import GlobalEmitter from './common/GlobalEmitter'
 import UnzonedRange from './models/UnzonedRange'
-import EventInstance from './models/event/EventInstance'
 import { DateMarker, addDays, addMs, diffWholeDays } from './datelib/marker'
 import { createDuration } from './datelib/duration'
 import { createFormatter } from './datelib/formatting'
-import { EventStore } from './reducers/event-store'
-import { sliceEventRanges } from './reducers/event-rendering'
+import { EventStore, EventInstance } from './reducers/event-store'
+import { EventRenderRange } from './reducers/event-rendering'
+import { Selection } from './reducers/selection'
 
 
 /* An abstract class from which other views inherit from
@@ -388,8 +388,18 @@ export default abstract class View extends InteractiveDateComponent {
 
 
   renderEventStore(eventStore: EventStore) {
-    let activeUnzonedRange = this.get('dateProfile').activeUnzonedRange
-    let eventRanges = sliceEventRanges(eventStore.instances, eventStore, activeUnzonedRange)
+    let eventRanges: EventRenderRange[] = []
+
+    for (let instanceId in eventStore.instances) {
+      let eventInstance = eventStore.instances[instanceId]
+
+      eventRanges.push({
+        eventDef: eventStore.defs[eventInstance.defId],
+        eventInstance,
+        range: eventInstance.range
+      })
+    }
+
     this.renderEventRanges(eventRanges)
   }
 
@@ -730,41 +740,29 @@ export default abstract class View extends InteractiveDateComponent {
 
   // Selects a date span on the view. `start` and `end` are both Moments.
   // `ev` is the native mouse event that begin the interaction.
-  select(footprint, ev?) {
+  select(selection: Selection, ev?) {
     this.unselect(ev)
-    this.renderSelectionFootprint(footprint)
-    this.reportSelection(footprint, ev)
-  }
-
-
-  renderSelectionFootprint(footprint) {
-    if (this['renderSelection']) { // legacy method in custom view classes
-      this['renderSelection'](
-        footprint.toLegacy(this.calendar)
-      )
-    } else {
-      super.renderSelectionFootprint(footprint)
-    }
+    this.renderSelection(selection)
+    this.reportSelection(selection, ev)
   }
 
 
   // Called when a new selection is made. Updates internal state and triggers handlers.
-  reportSelection(footprint, ev?) {
+  reportSelection(selection: Selection, ev?) {
     this.isSelected = true
-    this.triggerSelect(footprint, ev)
+    this.triggerSelect(selection, ev)
   }
 
 
   // Triggers handlers to 'select'
-  triggerSelect(footprint, ev?) {
+  triggerSelect(selection: Selection, ev?) {
     const dateEnv = this.calendar.dateEnv
-    let dateProfile = this.calendar.footprintToDateProfile(footprint) // abuse of "Event"DateProfile?
 
     this.publiclyTrigger('select', [
       {
-        start: dateEnv.toDate(dateProfile.unzonedRange.start),
-        end: dateEnv.toDate(dateProfile.unzonedRange.end),
-        isAllDay: dateProfile.isAllDay,
+        start: dateEnv.toDate(selection.range.start),
+        end: dateEnv.toDate(selection.range.end),
+        isAllDay: selection.isAllDay,
         jsEvent: ev,
         view: this
       }
@@ -1047,7 +1045,7 @@ View.watch('displayingBusinessHours', [ 'displayingDates', 'businessHourGenerato
 View.watch('displayingEvents', [ 'displayingDates', 'eventStore' ], function(deps) {
   this.requestEventStoreRender(deps.eventStore)
 }, function() {
-  this.requestEventStoreUnrender()
+  this.requestEventsUnrender()
 })
 
 

+ 24 - 43
src/agenda/AgendaView.ts

@@ -13,8 +13,8 @@ import TimeGrid from './TimeGrid'
 import DayGrid from '../basic/DayGrid'
 import { createDuration } from '../datelib/duration'
 import { createFormatter } from '../datelib/formatting'
-import { EventStore } from '../reducers/event-store'
-import { sliceEventRanges } from '../reducers/event-rendering'
+import { EventRenderRange } from '../reducers/event-rendering'
+import { Selection } from '../reducers/selection'
 
 const AGENDA_ALL_DAY_EVENT_LIMIT = 5
 const WEEK_HEADER_FORMAT = createFormatter({ week: 'short' })
@@ -305,31 +305,13 @@ export default class AgendaView extends View {
   /* Event Rendering
   ------------------------------------------------------------------------------------------------------------------*/
 
+  renderEventRanges(eventRanges: EventRenderRange[]) {
+    let groups = groupEventRangesByAllDay(eventRanges)
 
-  renderEventStore(eventStore: EventStore) {
-    let activeUnzonedRange = this.get('dateProfile').activeUnzonedRange
-    let { instances, defs } = eventStore
-    let allDayInstances = {}
-    let timedInstances = {}
-
-    for (let instanceId in instances) {
-      let instance = instances[instanceId]
-
-      if (defs[instance.defId].isAllDay) {
-        allDayInstances[instanceId] = instance
-      } else {
-        timedInstances[instanceId] = instance
-      }
-    }
-
-    this.timeGrid.renderEventRanges(
-      sliceEventRanges(timedInstances, eventStore, activeUnzonedRange)
-    )
+    this.timeGrid.renderEventRanges(groups.timed)
 
     if (this.dayGrid) {
-      this.dayGrid.renderEventRanges(
-        sliceEventRanges(allDayInstances, eventStore, activeUnzonedRange)
-      )
+      this.dayGrid.renderEventRanges(groups.allDay)
     }
   }
 
@@ -339,27 +321,27 @@ export default class AgendaView extends View {
 
 
   // A returned value of `true` signals that a mock "helper" event has been rendered.
-  renderDrag(eventFootprints, seg, isTouch) {
-    let groups = groupEventFootprintsByAllDay(eventFootprints)
+  renderDrag(eventRanges: EventRenderRange[], origSeg, isTouch) {
+    let groups = groupEventRangesByAllDay(eventRanges)
     let renderedHelper = false
 
-    renderedHelper = this.timeGrid.renderDrag(groups.timed, seg, isTouch)
+    renderedHelper = this.timeGrid.renderDrag(groups.timed, origSeg, isTouch)
 
     if (this.dayGrid) {
-      renderedHelper = this.dayGrid.renderDrag(groups.allDay, seg, isTouch) || renderedHelper
+      renderedHelper = this.dayGrid.renderDrag(groups.allDay, origSeg, isTouch) || renderedHelper
     }
 
     return renderedHelper
   }
 
 
-  renderEventResize(eventFootprints, seg, isTouch) {
-    let groups = groupEventFootprintsByAllDay(eventFootprints)
+  renderEventResize(eventRanges: EventRenderRange[], origSeg, isTouch) {
+    let groups = groupEventRangesByAllDay(eventRanges)
 
-    this.timeGrid.renderEventResize(groups.timed, seg, isTouch)
+    this.timeGrid.renderEventResize(groups.timed, origSeg, isTouch)
 
     if (this.dayGrid) {
-      this.dayGrid.renderEventResize(groups.allDay, seg, isTouch)
+      this.dayGrid.renderEventResize(groups.allDay, origSeg, isTouch)
     }
   }
 
@@ -369,11 +351,11 @@ export default class AgendaView extends View {
 
 
   // Renders a visual indication of a selection
-  renderSelectionFootprint(componentFootprint) {
-    if (!componentFootprint.isAllDay) {
-      this.timeGrid.renderSelectionFootprint(componentFootprint)
+  renderSelection(selection: Selection) {
+    if (!selection.isAllDay) {
+      this.timeGrid.renderSelection(selection)
     } else if (this.dayGrid) {
-      this.dayGrid.renderSelectionFootprint(componentFootprint)
+      this.dayGrid.renderSelection(selection)
     }
   }
 
@@ -457,18 +439,17 @@ agendaDayGridMethods = {
 }
 
 
-function groupEventFootprintsByAllDay(eventFootprints) {
+function groupEventRangesByAllDay(eventRanges: EventRenderRange[]) {
   let allDay = []
   let timed = []
-  let i
 
-  for (i = 0; i < eventFootprints.length; i++) {
-    if (eventFootprints[i].componentFootprint.isAllDay) {
-      allDay.push(eventFootprints[i])
+  for (let eventRange of eventRanges) {
+    if (eventRange.eventDef.isAllDay) {
+      allDay.push(eventRange)
     } else {
-      timed.push(eventFootprints[i])
+      timed.push(eventRange)
     }
   }
 
-  return { allDay: allDay, timed: timed }
+  return { allDay, timed }
 }

+ 22 - 21
src/agenda/TimeGrid.ts

@@ -13,6 +13,9 @@ import TimeGridFillRenderer from './TimeGridFillRenderer'
 import { Duration, createDuration, addDurations, wholeDivideDurations, asRoughMs } from '../datelib/duration'
 import { startOfDay, DateMarker, addMs } from '../datelib/marker'
 import { DateFormatter, createFormatter, formatIsoTimeString } from '../datelib/formatting'
+import { Seg } from '../reducers/seg'
+import { EventRenderRange } from '../reducers/event-rendering'
+import { Selection } from '../reducers/selection'
 
 /* A component that renders one or more columns of vertical time slots
 ----------------------------------------------------------------------------------------------------------------------*/
@@ -83,8 +86,8 @@ export default class TimeGrid extends InteractiveDateComponent {
 
 
   // Slices up the given span (unzoned start/end with other misc data) into an array of segments
-  componentFootprintToSegs(componentFootprint) {
-    let segs = this.sliceRangeByTimes(componentFootprint.unzonedRange)
+  rangeToSegs(range: UnzonedRange): Seg[] {
+    let segs = this.sliceRangeByTimes(range)
     let i
 
     for (i = 0; i < segs.length; i++) {
@@ -435,11 +438,8 @@ export default class TimeGrid extends InteractiveDateComponent {
 
     // seg system might be overkill, but it handles scenario where line needs to be rendered
     //  more than once because of columns with the same date (resources columns for example)
-    let segs = this.componentFootprintToSegs(
-      new ComponentFootprint(
-        new UnzonedRange(date, addMs(date, 1)), // protect against null range
-        false // all-day
-      )
+    let segs = this.rangeToSegs(
+      new UnzonedRange(date, addMs(date, 1)), // protect against null range
     )
     let top = this.computeDateTop(date)
     let nodes = []
@@ -664,22 +664,19 @@ export default class TimeGrid extends InteractiveDateComponent {
 
   // Renders a visual indication of an event being dragged over the specified date(s).
   // A returned value of `true` signals that a mock "helper" event has been rendered.
-  renderDrag(eventFootprints, seg, isTouch) {
-    let i
+  renderDrag(eventRanges: EventRenderRange[], origSeg, isTouch) {
+    let segs = this.eventRangesToSegs(eventRanges)
 
-    if (seg) { // if there is event information for this drag, render a helper event
+    if (origSeg) { // if there is event information for this drag, render a helper event
 
-      if (eventFootprints.length) {
-        this.helperRenderer.renderEventDraggingFootprints(eventFootprints, seg, isTouch)
+      if (eventRanges.length) {
+        this.helperRenderer.renderEventDraggingSegs(segs, origSeg, isTouch)
 
         // signal that a helper has been rendered
         return true
       }
     } else { // otherwise, just render a highlight
-
-      for (i = 0; i < eventFootprints.length; i++) {
-        this.renderHighlight(eventFootprints[i].componentFootprint)
-      }
+      this.renderHighlightSegs(segs)
     }
   }
 
@@ -696,8 +693,10 @@ export default class TimeGrid extends InteractiveDateComponent {
 
 
   // Renders a visual indication of an event being resized
-  renderEventResize(eventFootprints, seg, isTouch) {
-    this.helperRenderer.renderEventResizingFootprints(eventFootprints, seg, isTouch)
+  renderEventResize(eventRanges: EventRenderRange[], origSeg, isTouch) {
+    let segs = this.eventRangesToSegs(eventRanges)
+
+    this.helperRenderer.renderEventResizingSegs(segs, origSeg, isTouch)
   }
 
 
@@ -712,11 +711,13 @@ export default class TimeGrid extends InteractiveDateComponent {
 
 
   // Renders a visual indication of a selection. Overrides the default, which was to simply render a highlight.
-  renderSelectionFootprint(componentFootprint) {
+  renderSelection(selection: Selection) {
+    let segs = this.selectionToSegs(selection)
+
     if (this.opt('selectHelper')) { // this setting signals that a mock helper event should be rendered
-      this.helperRenderer.renderComponentFootprint(componentFootprint)
+      this.helperRenderer.renderEventSegs(segs)
     } else {
-      this.renderHighlight(componentFootprint)
+      this.renderHighlightSegs(segs)
     }
   }
 

+ 21 - 27
src/basic/DayGrid.ts

@@ -14,7 +14,6 @@ import CoordCache from '../common/CoordCache'
 import Popover from '../common/Popover'
 import UnzonedRange from '../models/UnzonedRange'
 import ComponentFootprint from '../models/ComponentFootprint'
-import EventFootprint from '../models/event/EventFootprint'
 import BusinessHourRenderer from '../component/renderers/BusinessHourRenderer'
 import StandardInteractionsMixin from '../component/interactions/StandardInteractionsMixin'
 import InteractiveDateComponent from '../component/InteractiveDateComponent'
@@ -24,6 +23,8 @@ import DayGridHelperRenderer from './DayGridHelperRenderer'
 import DayGridFillRenderer from './DayGridFillRenderer'
 import { addDays } from '../datelib/marker'
 import { createFormatter } from '../datelib/formatting'
+import { Seg } from '../reducers/seg'
+import { EventRenderRange } from '../reducers/event-rendering'
 
 const DAY_NUM_FORMAT = createFormatter({ day: 'numeric' })
 const WEEK_NUM_FORMAT = createFormatter({ week: 'numeric' })
@@ -78,8 +79,8 @@ export default class DayGrid extends InteractiveDateComponent {
 
 
   // Slices up the given span (unzoned start/end with other misc data) into an array of segments
-  componentFootprintToSegs(componentFootprint) {
-    let segs = this.sliceRangeByRow(componentFootprint.unzonedRange)
+  rangeToSegs(range: UnzonedRange): Seg[] {
+    let segs = this.sliceRangeByRow(range)
 
     for (let i = 0; i < segs.length; i++) {
       let seg = segs[i]
@@ -358,9 +359,9 @@ export default class DayGrid extends InteractiveDateComponent {
 
 
   // Unrenders all events currently rendered on the grid
-  executeEventUnrender() {
+  unrenderEvents() {
     this.removeSegPopover() // removes the "more.." events popover
-    super.executeEventUnrender()
+    super.unrenderEvents()
   }
 
 
@@ -377,16 +378,14 @@ export default class DayGrid extends InteractiveDateComponent {
 
   // Renders a visual indication of an event or external element being dragged.
   // `eventLocation` has zoned start and end (optional)
-  renderDrag(eventFootprints, seg, isTouch) {
-    let i
+  renderDrag(eventRanges: EventRenderRange[], origSeg, isTouch) {
+    let segs = this.eventRangesToSegs(eventRanges)
 
-    for (i = 0; i < eventFootprints.length; i++) {
-      this.renderHighlight(eventFootprints[i].componentFootprint)
-    }
+    this.renderHighlightSegs(segs)
 
     // render drags from OTHER components as helpers
-    if (eventFootprints.length && seg && seg.component !== this) {
-      this.helperRenderer.renderEventDraggingFootprints(eventFootprints, seg, isTouch)
+    if (eventRanges.length && origSeg && origSeg.component !== this) {
+      this.helperRenderer.renderEventDraggingSegs(segs, origSeg, isTouch)
 
       return true // signal helpers rendered
     }
@@ -405,14 +404,12 @@ export default class DayGrid extends InteractiveDateComponent {
 
 
   // Renders a visual indication of an event being resized
-  renderEventResize(eventFootprints, seg, isTouch) {
-    let i
+  renderEventResize(eventRanges: EventRenderRange[], origSeg, isTouch) {
+    let segs = this.eventRangesToSegs(eventRanges)
 
-    for (i = 0; i < eventFootprints.length; i++) {
-      this.renderHighlight(eventFootprints[i].componentFootprint)
-    }
+    this.renderHighlightSegs(segs)
 
-    this.helperRenderer.renderEventResizingFootprints(eventFootprints, seg, isTouch)
+    this.helperRenderer.renderEventResizingSegs(segs, origSeg, isTouch)
   }
 
 
@@ -751,19 +748,16 @@ export default class DayGrid extends InteractiveDateComponent {
 
     for (i = 0; i < segs.length; i++) {
       seg = segs[i]
-      slicedRange = seg.footprint.componentFootprint.unzonedRange.intersect(dayRange)
+      slicedRange = seg.eventRange.intersect(dayRange)
 
       if (slicedRange) {
         newSegs.push(
           assignTo({}, seg, {
-            footprint: new EventFootprint(
-              new ComponentFootprint(
-                slicedRange,
-                seg.footprint.componentFootprint.isAllDay
-              ),
-              seg.footprint.eventDef,
-              seg.footprint.eventInstance
-            ),
+            eventRange: {
+              eventDef: seg.eventRange.eventDef,
+              eventInstance: seg.eventRange.eventInstance,
+              range: slicedRange
+            },
             isStart: seg.isStart && slicedRange.isStart,
             isEnd: seg.isEnd && slicedRange.isEnd
           })

+ 63 - 126
src/component/DateComponent.ts

@@ -2,12 +2,14 @@ import { attrsToStr, htmlEscape } from '../util/html'
 import Component from './Component'
 import Calendar from '../Calendar'
 import View from '../View'
-import { eventRangeToEventFootprint } from '../models/event/util'
-import EventFootprint from '../models/event/EventFootprint'
 import { DateProfile } from '../DateProfileGenerator'
 import { DateMarker, DAY_IDS, addDays, startOfDay, diffDays, diffWholeDays } from '../datelib/marker'
 import { Duration, createDuration, asRoughMs } from '../datelib/duration'
-import { EventRenderRange } from '../reducers/event-rendering'
+import { EventRenderRange, sliceEventRanges } from '../reducers/event-rendering'
+import { Selection } from '../reducers/selection'
+import UnzonedRange from '../models/UnzonedRange'
+import { Seg } from '../reducers/seg'
+import { EventDef, EventInstance, parseDef, createInstance } from '../reducers/event-store'
 
 
 export default abstract class DateComponent extends Component {
@@ -202,6 +204,26 @@ export default abstract class DateComponent extends Component {
   }
 
 
+  getBusinessHourSegs() { // recursive
+    let segs = this.getOwnBusinessHourSegs()
+
+    this.iterChildren(function(child) {
+      segs.push.apply(segs, child.getBusinessHourSegs())
+    })
+
+    return segs
+  }
+
+
+  getOwnBusinessHourSegs() {
+    if (this.businessHourRenderer) {
+      return this.businessHourRenderer.getSegs()
+    }
+
+    return []
+  }
+
+
   // Event Displaying
   // -----------------------------------------------------------------------------------------------------------------
 
@@ -210,11 +232,13 @@ export default abstract class DateComponent extends Component {
 
     if (this.eventRenderer) {
       this.eventRenderer.rangeUpdated() // poorly named now
-      this.eventRenderer.renderRanges(eventRanges)
-    } else if (this['renderEvents']) { // legacy
-      // TODO
-      // this['renderEvents'](convertEventsPayloadToLegacyArray(eventsPayload, this._getCalendar()))
+      this.eventRenderer.renderSegs(
+        this.eventRangesToSegs(eventRanges)
+      )
     }
+    // else if (this['renderEvents']) { // legacy
+    //   this['renderEvents'](convertEventsPayloadToLegacyArray(eventsPayload, this._getCalendar()))
+    // }
 
     this.callChildren('renderEventRanges', arguments)
   }
@@ -231,26 +255,6 @@ export default abstract class DateComponent extends Component {
   }
 
 
-  getBusinessHourSegs() { // recursive
-    let segs = this.getOwnBusinessHourSegs()
-
-    this.iterChildren(function(child) {
-      segs.push.apply(segs, child.getBusinessHourSegs())
-    })
-
-    return segs
-  }
-
-
-  getOwnBusinessHourSegs() {
-    if (this.businessHourRenderer) {
-      return this.businessHourRenderer.getSegs()
-    }
-
-    return []
-  }
-
-
   getEventSegs() { // recursive
     let segs = this.getOwnEventSegs()
 
@@ -288,14 +292,10 @@ export default abstract class DateComponent extends Component {
     // an optimization, because getEventLegacy is expensive
     if (this.hasPublicHandlers('eventAfterRender')) {
       segs.forEach((seg) => {
-        let legacy
-
         if (seg.el) { // necessary?
-          legacy = seg.footprint.getEventLegacy(this._getCalendar())
-
           this.publiclyTrigger('eventAfterRender', [
             {
-              event: legacy,
+              event: seg.eventRange, // what to do here?
               el: seg.el,
               view: this
             }
@@ -319,11 +319,9 @@ export default abstract class DateComponent extends Component {
         let legacy
 
         if (seg.el) { // necessary?
-          legacy = seg.footprint.getEventLegacy(this._getCalendar())
-
           this.publiclyTrigger('eventDestroy', [
             {
-              event: legacy,
+              event: seg.eventRange, // what to do here?
               el: seg.el,
               view: this
             }
@@ -344,7 +342,7 @@ export default abstract class DateComponent extends Component {
 
     this.getEventSegs().forEach(function(seg) {
       if (
-        seg.footprint.eventDef.id === eventDefId &&
+        seg.eventRange.eventDef.id === eventDefId &&
         seg.el // necessary?
       ) {
         seg.el.style.visibility = ''
@@ -361,7 +359,7 @@ export default abstract class DateComponent extends Component {
 
     this.getEventSegs().forEach(function(seg) {
       if (
-        seg.footprint.eventDef.id === eventDefId &&
+        seg.eventRange.eventDef.id === eventDefId &&
         seg.el // necessary?
       ) {
         seg.el.style.visibility = 'hidden'
@@ -379,11 +377,11 @@ export default abstract class DateComponent extends Component {
   // Renders a visual indication of a event or external-element drag over the given drop zone.
   // If an external-element, seg will be `null`.
   // Must return elements used for any mock events.
-  renderDrag(eventFootprints, seg?, isTouch = false) {
+  renderDrag(eventRanges: EventRenderRange[], origSeg?, isTouch = false) {
     let renderedHelper = false
 
     this.iterChildren(function(child) {
-      if (child.renderDrag(eventFootprints, seg, isTouch)) {
+      if (child.renderDrag(eventRanges, origSeg, isTouch)) {
         renderedHelper = true
       }
     })
@@ -423,7 +421,7 @@ export default abstract class DateComponent extends Component {
 
 
   // Renders a visual indication of an event being resized.
-  renderEventResize(eventFootprints, seg, isTouch) {
+  renderEventResize(eventRanges: EventRenderRange[], seg, isTouch) {
     this.callChildren('renderEventResize', arguments)
   }
 
@@ -440,10 +438,10 @@ export default abstract class DateComponent extends Component {
 
   // Renders a visual indication of the selection
   // TODO: rename to `renderSelection` after legacy is gone
-  renderSelectionFootprint(componentFootprint) {
-    this.renderHighlight(componentFootprint)
+  renderSelection(selection: Selection) {
+    this.renderHighlightSegs(this.selectionToSegs(selection))
 
-    this.callChildren('renderSelectionFootprint', arguments)
+    this.callChildren('renderSelection', arguments)
   }
 
 
@@ -460,11 +458,11 @@ export default abstract class DateComponent extends Component {
 
 
   // Renders an emphasis on the given date range. Given a span (unzoned start/end and other misc data)
-  renderHighlight(componentFootprint) {
+  renderHighlightSegs(segs) {
     if (this.fillRenderer) {
-      this.fillRenderer.renderFootprint(
+      this.fillRenderer.renderSegs(
         'highlight',
-        componentFootprint,
+        segs,
         {
           getClasses() {
             return [ 'fc-highlight' ]
@@ -472,8 +470,6 @@ export default abstract class DateComponent extends Component {
         }
       )
     }
-
-    this.callChildren('renderHighlight', arguments)
   }
 
 
@@ -482,8 +478,6 @@ export default abstract class DateComponent extends Component {
     if (this.fillRenderer) {
       this.fillRenderer.unrender('highlight')
     }
-
-    this.callChildren('unrenderHighlight', arguments)
   }
 
 
@@ -565,78 +559,35 @@ export default abstract class DateComponent extends Component {
   }
 
 
-  /* Converting eventRange -> eventFootprint
+  /* Converting selection/eventRanges -> segs
   ------------------------------------------------------------------------------------------------------------------*/
 
 
-  eventRangesToEventFootprints(eventRanges) {
-    let eventFootprints = []
-    let i
-
-    for (i = 0; i < eventRanges.length; i++) {
-      eventFootprints.push.apply( // append
-        eventFootprints,
-        this.eventRangeToEventFootprints(eventRanges[i])
-      )
-    }
-
-    return eventFootprints
+  selectionToSegs(selection: Selection): Seg[] {
+    return this.rangeToSegs(selection.range, selection.isAllDay)
   }
 
 
-  eventRangeToEventFootprints(eventRange): EventFootprint[] {
-    return [ eventRangeToEventFootprint(eventRange) ]
-  }
+  eventRangesToSegs(eventRanges: EventRenderRange[]): Seg[] {
+    let activeUnzonedRange = this.dateProfile.activeUnzonedRange
+    let eventRenderRanges = sliceEventRanges(eventRanges, activeUnzonedRange)
+    let allSegs: Seg[] = []
 
+    for (let eventRenderRange of eventRenderRanges) {
+      let segs = this.rangeToSegs(eventRenderRange.range, eventRenderRange.eventDef.isAllDay)
 
-  /* Converting componentFootprint/eventFootprint -> segs
-  ------------------------------------------------------------------------------------------------------------------*/
-
-
-  eventFootprintsToSegs(eventFootprints) {
-    let segs = []
-    let i
-
-    for (i = 0; i < eventFootprints.length; i++) {
-      segs.push.apply(segs,
-        this.eventFootprintToSegs(eventFootprints[i])
-      )
-    }
-
-    return segs
-  }
-
-
-  // Given an event's span (unzoned start/end and other misc data), and the event itself,
-  // slices into segments and attaches event-derived properties to them.
-  // eventSpan - { start, end, isStart, isEnd, otherthings... }
-  eventFootprintToSegs(eventFootprint) {
-    let unzonedRange = eventFootprint.componentFootprint.unzonedRange
-    let segs
-    let i
-    let seg
-
-    segs = this.componentFootprintToSegs(eventFootprint.componentFootprint)
-
-    for (i = 0; i < segs.length; i++) {
-      seg = segs[i]
-
-      if (!unzonedRange.isStart) {
-        seg.isStart = false
+      for (let seg of segs) {
+        seg.eventRange = eventRenderRange
+        allSegs.push(seg)
       }
-      if (!unzonedRange.isEnd) {
-        seg.isEnd = false
-      }
-
-      seg.footprint = eventFootprint
-      // TODO: rename to seg.eventFootprint
     }
 
-    return segs
+    return allSegs
   }
 
 
-  componentFootprintToSegs(componentFootprint) {
+  // must implement if want to use many of the rendering utils
+  rangeToSegs(range: UnzonedRange, isAllDay: boolean): Seg[] {
     return []
   }
 
@@ -823,23 +774,9 @@ export default abstract class DateComponent extends Component {
 }
 
 
-// legacy
-
-function convertEventsPayloadToLegacyArray(eventsPayload, calendar) {
-  let eventDefId
-  let eventInstances
-  let legacyEvents = []
-  let i
-
-  for (eventDefId in eventsPayload) {
-    eventInstances = eventsPayload[eventDefId].eventInstances
-
-    for (i = 0; i < eventInstances.length; i++) {
-      legacyEvents.push(
-        eventInstances[i].toLegacy(calendar)
-      )
-    }
-  }
+export function fabricateEventRange(range: UnzonedRange, isAllDay: boolean): EventRenderRange {
+  let eventDef: EventDef = parseDef(null, {}, isAllDay, true)
+  let eventInstance: EventInstance = createInstance(eventDef.defId, range)
 
-  return legacyEvents
+  return { eventDef, eventInstance, range }
 }

+ 6 - 6
src/list/ListView.ts

@@ -100,7 +100,7 @@ export default class ListView extends View {
 
 
   // slices by day
-  componentFootprintToSegs(footprint) {
+  rangeToSegs(range: UnzonedRange, isAllDay: boolean) {
     const dateEnv = this.calendar.dateEnv
     let dayRanges = this.dayRanges
     let dayIndex
@@ -109,7 +109,7 @@ export default class ListView extends View {
     let segs = []
 
     for (dayIndex = 0; dayIndex < dayRanges.length; dayIndex++) {
-      segRange = footprint.unzonedRange.intersect(dayRanges[dayIndex])
+      segRange = range.intersect(dayRanges[dayIndex])
 
       if (segRange) {
         seg = {
@@ -122,18 +122,18 @@ export default class ListView extends View {
 
         segs.push(seg)
 
-        // detect when footprint won't go fully into the next day,
+        // detect when range won't go fully into the next day,
         // and mutate the latest seg to the be the end.
         if (
-          !seg.isEnd && !footprint.isAllDay &&
+          !seg.isEnd && !isAllDay &&
           dayIndex + 1 < dayRanges.length &&
-          footprint.unzonedRange.end <
+          range.end <
             dateEnv.add(
               dayRanges[dayIndex + 1].start,
               this.nextDayThreshold
             )
         ) {
-          seg.end = footprint.unzonedRange.end
+          seg.end = range.end
           seg.isEnd = true
           break
         }

+ 40 - 68
src/reducers/event-rendering.ts

@@ -1,5 +1,5 @@
 import UnzonedRange from '../models/UnzonedRange'
-import { EventInstanceHash, EventStore, EventDef, EventInstance } from './event-store'
+import { EventDef, EventInstance } from './event-store'
 
 export interface EventRenderRange {
   eventDef: EventDef
@@ -7,88 +7,60 @@ export interface EventRenderRange {
   range: UnzonedRange
 }
 
-export function sliceEventRanges(instances: EventInstanceHash, store: EventStore, sliceRange: UnzonedRange): EventRenderRange[] {
-  let groupedInverseBg = {}
-  let ungroupedInverseBg: EventInstance[] = []
-  let normal: EventInstance[] = []
-  let segs: EventRenderRange[] = []
 
-  for (let instanceId in instances) {
-    let instance = instances[instanceId]
-    let def = store.defs[instance.defId]
-    let groupId = def.groupId
+export function sliceEventRanges(origRanges: EventRenderRange[], windowRange: UnzonedRange): EventRenderRange[] {
+  let renderRanges: EventRenderRange[] = []
+  let inverseBgGroups: { [groupId: string]: EventRenderRange[] } = {}
+
+  for (let origRange of origRanges) {
+    let { eventDef, eventInstance } = origRange
+
+    if (eventDef.rendering === 'inverse-background') {
+      let groupId = eventDef.groupId
 
-    if (def.rendering === 'inverse-background') {
       if (groupId) {
-        (groupedInverseBg[groupId] || (groupedInverseBg[groupId] = []))
-          .push(instance)
+        (inverseBgGroups[groupId] || (inverseBgGroups[groupId] = []))
+          .push(origRange)
+
       } else {
-        ungroupedInverseBg.push(instance)
+        let invertedRanges = UnzonedRange.invertRanges([ eventInstance.range ], windowRange)
+
+        for (let invertedRange of invertedRanges) {
+          renderRanges.push({
+            eventDef,
+            eventInstance,
+            range: invertedRange
+          })
+        }
       }
     } else {
-      normal.push(instance)
-    }
-  }
-
-  for (let groupId in groupedInverseBg) {
-    let inverseBgInstances = groupedInverseBg[groupId]
-    let ranges = inverseBgInstances.map(getInstanceRange)
-    let invertedRanges = UnzonedRange.invertRanges(ranges, sliceRange)
-
-    for (let range of invertedRanges) {
-      segs.push({
-        eventDef: store.defs[inverseBgInstances[0].defId],
-        eventInstance: inverseBgInstances[0],
-        range
-      })
-    }
-  }
-
-  for (let instance of ungroupedInverseBg) {
-    let invertedRanges = UnzonedRange.invertRanges([ instance.range ], sliceRange)
-
-    for (let range of invertedRanges) {
-      segs.push({
-        eventDef: store.defs[instance.defId],
-        eventInstance: instance,
-        range
+      renderRanges.push({
+        eventDef,
+        eventInstance,
+        range: eventInstance.range.intersect(windowRange)
       })
     }
   }
 
-  for (let instance of normal) {
-    let slicedRange = instance.range.intersect(sliceRange)
-
-    if (slicedRange) {
-      segs.push({
-        eventDef: store.defs[instance.defId],
-        eventInstance: instance,
-        range: slicedRange
+  for (let groupId in inverseBgGroups) {
+    let inverseBgGroup = inverseBgGroups[groupId]
+    let { eventDef, eventInstance } = inverseBgGroup[0]
+    let origRanges = inverseBgGroup.map(getRange)
+    let invertedRanges = UnzonedRange.invertRanges(origRanges, windowRange)
+
+    for (let invertedRange of invertedRanges) {
+      renderRanges.push({
+        eventDef,
+        eventInstance,
+        range: invertedRange
       })
     }
   }
 
-  return segs
-}
-
-function getInstanceRange(eventInstance: EventInstance) {
-  return eventInstance.range
+  return renderRanges
 }
 
-export function furtherSliceEventSegments(segs: EventRenderRange[], sliceRange: UnzonedRange): EventRenderRange[] {
-  let newSegs: EventRenderRange[] = []
-
-  for (let seg of segs) {
-    let newRange = seg.range.intersect(sliceRange)
-
-    if (newRange) {
-      newSegs.push({
-        eventDef: seg.eventDef,
-        eventInstance: seg.eventInstance,
-        range: newRange
-      })
-    }
-  }
 
-  return newSegs
+function getRange(eventRange: EventRenderRange) {
+  return eventRange.range
 }

+ 43 - 0
src/reducers/selection.ts

@@ -0,0 +1,43 @@
+import UnzonedRange from '../models/UnzonedRange'
+import { DateInput, DateEnv } from '../datelib/env'
+import { refineProps } from '../reducers/utils'
+
+export interface SelectionInput {
+  start: DateInput
+  end: DateInput
+  isAllDay?: boolean
+  [otherProp: string]: any
+}
+
+export interface Selection {
+  range: UnzonedRange
+  isAllDay: boolean
+  [otherProp: string]: any
+}
+
+const STANDARD_PROPS = {
+  start: null, // dont auto-refine
+  end: null, // dont auto-refine
+  isAllDay: Boolean
+}
+
+export function parseSelection(raw: SelectionInput, dateEnv: DateEnv): Selection {
+  let otherProps = {} as any
+  let standardProps = refineProps(raw, STANDARD_PROPS, otherProps)
+  let startMeta = standardProps.start ? dateEnv.createMarkerMeta(standardProps.start) : null
+  let endMeta = standardProps.end ? dateEnv.createMarkerMeta(standardProps.end) : null
+  let isAllDay = standardProps.isAllDay
+
+  if (startMeta && endMeta) {
+
+    if (isAllDay == null) {
+      isAllDay = startMeta.isTimeUnspecified && endMeta.isTimeUnspecified
+    }
+
+    // use this leftover object as the selection object
+    otherProps.range = new UnzonedRange(startMeta.marker, endMeta.marker)
+    otherProps.isAllDay = isAllDay
+
+    return otherProps
+  }
+}