/// <summary> /// Creates a new TimelineBlockingEvent. /// </summary> /// <param name="parentEvent">The parent TimelineEvent this event is blocking for</param> /// <param name="interimTime">Interim time (offset) between parent event and this blocking event</param> /// <param name="bufferTimeBefore">Additional buffer time before event</param> /// <param name="bufferTimeAfter">Additional buffer time after event</param> public TimelineBlockingEvent(TimelineEvent parentEvent, double interimTime, double bufferTimeBefore, double bufferTimeAfter) : base(parentEvent.eventTime + interimTime - bufferTimeBefore, parentEvent.eventLength + bufferTimeBefore + bufferTimeAfter, Color.DarkGray, delegate() {}, delegate() {}) { this.parentEvent = parentEvent; this.interimTime = interimTime; this.bufferTimeBefore = bufferTimeBefore; this.bufferTimeAfter = bufferTimeAfter; parentEvent.EventTimesChanged += new EventTimesChangedEventHandler(parentEvent_EventTimesChanged); }
/// <summary> /// Erstellt ein neues SelectionChangedEventArgs /// </summary> /// <param name="te">ausgewähltes TimelineEntry</param> /// <param name="ev">ausgewähltes TimelineEvent</param> /// <param name="dragAction">Art des Drag and Drop-Vorganges</param> public EventChangedEventArgs(TimelineEntry te, TimelineEvent ev, DragNDrop dragAction) { this.m_selectedEntry = te; this.m_handeledEvent = ev; this.m_dragAction = dragAction; }
/// <summary> /// Eventhandler beim Drücken der Maustaste /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void TimelineControl_MouseDown(object sender, MouseEventArgs e) { // wurde der Zeitschieber angeklickt? if ((e.Button == MouseButtons.Left) && (Math.Abs(e.X - GetHorizontalClientPositionAtCurrentTime()) < 2)) { // Drag'n'Drop Modus setzen howToDrag = DragNDrop.MOVE_TIMELINE_BAR; } // wurde ein Plus-/Minussysmbol einer Gruppe angeklickt? else if (e.X < rowHeight && GetGroupAtClientPosition(e.Location, true) != null) { TimelineGroup tg = GetGroupAtClientPosition(e.Location, true); tg.collapsed = !tg.collapsed; } // wurde vielleicht was anderes wichtiges angeklickt? else { TimelineEntry newEntry = GetTimelineEntryAtControlPosition(e.Location); TimelineGroup newGroup = GetGroupAtClientPosition(e.Location, false); if (newEntry != m_selectedEntry || newGroup != m_selectedGroup) { m_selectedGroup = newGroup; m_selectedEntry = newEntry; OnSelectionChanged(); } // wurde ein TimelineEntry angeklickt? if (m_selectedEntry != null) { // gucken, ob es sich bei te um ein TrafficLight handelt TrafficLight tl = m_selectedEntry as TrafficLight; if (tl != null) { switch (e.Button) { case MouseButtons.Left: #region TimelineEvent hinzufügen if ((Control.ModifierKeys & Keys.Control) == Keys.Control) { double time = GetTimeAtControlPosition(e.Location, true); // Event hinzufügen, welches die Ampel umschaltet TimelineEvent eventToAdd = new TimelineEvent(time, Math.Min(1, (m_selectedEntry.GetTimeOfNextEvent(time) - time) / 2), Color.Green, tl.SwitchToGreen, tl.SwitchToRed); m_selectedEntry.AddEvent(eventToAdd, true, false); howToDrag = DragNDrop.MOVE_EVENT_END; eventToDrag = eventToAdd; this.Cursor = Cursors.SizeWE; Invalidate(); } #endregion #region TimelineEntry selektieren else { // Drag'n'Drop für Events initialisieren TimelineEvent theEvent = GetTimelineEventAtControlPosition(e.Location, true); if (theEvent != null) { if (Math.Abs(GetClientPositionForTimelineEvent(theEvent).X - e.Location.X) < 3) { howToDrag = DragNDrop.MOVE_EVENT_START; eventToDrag = theEvent; } else if (Math.Abs(GetClientPositionForTimelineEvent(theEvent).X + theEvent.eventLength * zoom - e.Location.X) < 3) { howToDrag = DragNDrop.MOVE_EVENT_END; eventToDrag = theEvent; } else { mouseDownPosition = e.Location; eventToDragOffset = GetClientPositionForTimelineEvent(theEvent).X - e.Location.X; howToDrag = DragNDrop.MOVE_EVENT; eventToDrag = theEvent; } } } #endregion break; case MouseButtons.Right: #region TimelineEvent entfernen if ((Control.ModifierKeys & Keys.Control) == Keys.Control) { double time = GetTimeAtControlPosition(e.Location, false); TimelineEvent eventToRemove = tl.GetEventAtTime(time); tl.RemoveEvent(eventToRemove); } #endregion break; } } } Invalidate(); } }
/// <summary> /// gibt die Koordinaten der linken oberen Ecke des TimelineEvents te zurück /// </summary> /// <param name="te">TimelineEvent, dessen Position berechnet werden soll</param> /// <returns>Koordinaten der linken oberen Ecke des Balkens, der te repräsentiert oder, (0,0), falls te nicht in m_entries.events</returns> public Point GetClientPositionForTimelineEvent(TimelineEvent te) { int y = 0; foreach (TimelineGroup tg in steuerung.groups) { y += totalRowHeight; if (! tg.collapsed) { foreach (TimelineEntry foo in tg.entries) { if (foo.events.Contains(te)) { return new Point(totalRowHeight + (int)Math.Round(m_zoom * te.eventTime), y); } y += totalRowHeight; } } } return new Point(0, 0); }
void parentEvent_EventTimesChanged(object sender, TimelineEvent.EventTimesChangedEventArgs e) { adjustEventTimesToParentEvent(); }
void events_EventTimesChanged(object sender, TimelineEvent.EventTimesChangedEventArgs e) { AdjustSurroundingEvents(e._changedEvent); }
/// <summary> /// Gibt den LinkedListNode zurück, der e enthält /// </summary> /// <param name="e">Event nach dem zu suchen ist</param> /// <returns>den erstbesten LinkedListNode mit Value == e oder null, falls kein solcher existiert</returns> private LinkedListNode<TimelineEvent> GetListNode(TimelineEvent e) { LinkedListNode<TimelineEvent> lln = events.First; while (lln != null) { if (lln.Value == e) { return lln; } lln = lln.Next; } return null; }
/// <summary> /// bewegt den Beginn des TimelineEvents eventToMove aber nur so weit, dass es sich mit keinen anderen Events überschneidet, aus dem Entry herausragt oder kleiner als 1 wird /// </summary> /// <param name="eventToMove">Event welches bewegt werden soll</param> /// <param name="time">Zeit an die das Event bewegt werden soll</param> public void MoveEventStart(TimelineEvent eventToMove, double time) { LinkedListNode<TimelineEvent> lln = GetListNode(eventToMove); if (lln != null) { double min = (lln.Previous != null) ? lln.Previous.Value.eventTime + lln.Previous.Value.eventLength : 0; double max = eventToMove.eventTime + eventToMove.eventLength - 1; if (time < min) { eventToMove.eventTime = min; eventToMove.eventLength = max + 1 - eventToMove.eventTime; } else if (time > max) { eventToMove.eventTime = max; eventToMove.eventLength = 1; } else { eventToMove.eventTime = time; eventToMove.eventLength = max + 1 - eventToMove.eventTime; } } OnEntryChanged(new EntryChangedEventArgs(this)); }
/// <summary> /// entfernt das TimelineEvent von diesem TimelineEntry /// </summary> /// <param name="eventToRemove">zu entfernendes TimelineEvent</param> public void RemoveEvent(TimelineEvent eventToRemove) { if (_events.Remove(eventToRemove)) eventToRemove.EventTimesChanged -= events_EventTimesChanged; OnEntryChanged(new EntryChangedEventArgs(this)); }
/// <summary> /// bewegt TimelineEvent eventToMove als ganzes aber nur so weit, dass es sich mit keinen anderen Events überschneidet oder aus dem Entry herausragt /// </summary> /// <param name="eventToMove">Event welches bewegt werden soll</param> /// <param name="time">Zeit an die das Event bewegt werden soll</param> public void MoveEvent(TimelineEvent eventToMove, double time) { LinkedListNode<TimelineEvent> lln = GetListNode(eventToMove); if (lln != null) { double min = (lln.Previous != null) ? lln.Previous.Value.eventTime + lln.Previous.Value.eventLength : 0; double max = (lln.Next != null) ? lln.Next.Value.eventTime - eventToMove.eventLength : this.maxTime - eventToMove.eventLength; if (time < min) eventToMove.eventTime = min; else if (time > max) eventToMove.eventTime = max; else eventToMove.eventTime = time; } OnEntryChanged(new EntryChangedEventArgs(this)); }
/// <summary> /// bewegt das Ende des TimelineEvents eventToMove aber nur so weit, dass es sich mit keinen anderen Events überschneidet, aus dem Entry herausragt oder kleiner als 1 wird /// </summary> /// <param name="eventToMove">Event welches bewegt werden soll</param> /// <param name="time">Zeit an die das Event bewegt werden soll</param> public void MoveEventEnd(TimelineEvent eventToMove, double time) { LinkedListNode<TimelineEvent> lln = GetListNode(eventToMove); if (lln != null) { double min = eventToMove.eventTime + 1; double max = (lln.Next != null) ? lln.Next.Value.eventTime : this.maxTime; if (time < min) { eventToMove.eventLength = min - eventToMove.eventTime; } else if (time > max) { eventToMove.eventLength = max - eventToMove.eventTime; } else { eventToMove.eventLength = time - eventToMove.eventTime; } } OnEntryChanged(new EntryChangedEventArgs(this)); }
/// <summary> /// To be called when the times of <paramref name="changedEvent"/> have changed: /// Readjusts start/ending times of all surrounding events. Deleted surrounding events, if necessary! /// </summary> /// <param name="changedEvent">TimelineEvent of this entry that has changed its time parameters.</param> public void AdjustSurroundingEvents(TimelineEvent changedEvent) { double startTime = changedEvent.eventTime; double endTime = changedEvent.eventEndTime; LinkedListNode<TimelineEvent> lln = GetListNode(changedEvent); if (lln != null) { // adjust previous events: LinkedListNode<TimelineEvent> pLln = lln.Previous; while (pLln != null) { TimelineEvent e = pLln.Value; // if the previous event starts after changedEvent, delete it if (e.eventTime >= startTime) { LinkedListNode<TimelineEvent> toRemove = pLln; pLln = pLln.Previous; _events.Remove(toRemove); } // else if the previous event ends after changedEvent, shorten it and we're done here else if (e.eventEndTime > startTime) { e.eventEndTime = startTime; break; } // else we're done here else { break; } } // adjust following events LinkedListNode<TimelineEvent> nLln = lln.Next; while (nLln != null) { TimelineEvent e = nLln.Value; // if the following event ends before changedEvent ends, delete it if (e.eventEndTime <= endTime) { LinkedListNode<TimelineEvent> toRemove = nLln; nLln = nLln.Next; _events.Remove(toRemove); } // else if the following event starts before changedEvent ends, shorten it and we're done here else if (e.eventTime < endTime) { e.eventLength -= endTime - e.eventTime; e.eventTime = endTime; break; } // else we're done here else { break; } } } else { throw new Exception("TimelineEvent not found. Must be from this TimelineEntry!"); } OnEntryChanged(new EntryChangedEventArgs(this)); }
/// <summary> /// fügt dem TimelineEntry ein fertiges TimelineEvent an der richtigen Stelle hinzu /// </summary> /// <param name="eventToAdd">TimelineEvent welches eingefügt werden soll</param> /// <param name="addBlockingEntries">Flag whether to add TimelineBlockingEvents to all other signals in this signal group which have interim times with each other.</param> /// <param name="adjustSurroundingEvents">Flag whether to adjust the times of the surrounding events to not overlap the created event. Will delete completely overlapped events.</param> public void AddEvent(TimelineEvent eventToAdd, bool addBlockingEntries, bool adjustSurroundingEvents) { if (events.Count != 0) { LinkedListNode<TimelineEvent> ln = events.First; while (ln != null && ln.Value.eventTime + ln.Value.eventLength < eventToAdd.eventTime) { ln = ln.Next; } if (ln == null) { events.AddLast(eventToAdd); } else { if (eventToAdd.eventTime + eventToAdd.eventLength > ln.Value.eventTime) { if (adjustSurroundingEvents) { events.AddBefore(ln, eventToAdd); AdjustSurroundingEvents(eventToAdd); } else { Exception e = new Exception("TimelineEvents überlappen sich"); throw e; } } else { events.AddBefore(ln, eventToAdd); } } } else { events.AddFirst(eventToAdd); } // add blocking entries if (addBlockingEntries) { List<Pair<TimelineEntry, double>> interimTimes = parentGroup.GetInterimTimes(this); if (interimTimes != null) { foreach (Pair<TimelineEntry, double> p in interimTimes) { double startTime = eventToAdd.eventTime + (Math.Floor(p.Right * 2) / 2); TimelineEvent blockingEvent = new TimelineBlockingEvent(eventToAdd, p.Right, 1, 2); p.Left.AddEvent(blockingEvent, false, true); } } } eventToAdd.EventTimesChanged += new TimelineEvent.EventTimesChangedEventHandler(events_EventTimesChanged); OnEntryChanged(new EntryChangedEventArgs(this)); }
/// <summary> /// Creates new EventTimesChangedEventArgs /// </summary> public EventTimesChangedEventArgs(TimelineEvent te) { _changedEvent = te; }
/// <summary> /// To be called when the times of <paramref name="changedEvent"/> have changed: /// Readjusts start/ending times of all surrounding events. Deleted surrounding events, if necessary! /// </summary> /// <param name="changedEvent">TimelineEvent of this entry that has changed its time parameters.</param> public void AdjustSurroundingEvents(TimelineEvent changedEvent) { double startTime = changedEvent.eventTime; double endTime = changedEvent.eventEndTime; LinkedListNode <TimelineEvent> lln = GetListNode(changedEvent); if (lln != null) { // adjust previous events: LinkedListNode <TimelineEvent> pLln = lln.Previous; while (pLln != null) { TimelineEvent e = pLln.Value; // if the previous event starts after changedEvent, delete it if (e.eventTime >= startTime) { LinkedListNode <TimelineEvent> toRemove = pLln; pLln = pLln.Previous; _events.Remove(toRemove); } // else if the previous event ends after changedEvent, shorten it and we're done here else if (e.eventEndTime > startTime) { e.eventEndTime = startTime; break; } // else we're done here else { break; } } // adjust following events LinkedListNode <TimelineEvent> nLln = lln.Next; while (nLln != null) { TimelineEvent e = nLln.Value; // if the following event ends before changedEvent ends, delete it if (e.eventEndTime <= endTime) { LinkedListNode <TimelineEvent> toRemove = nLln; nLln = nLln.Next; _events.Remove(toRemove); } // else if the following event starts before changedEvent ends, shorten it and we're done here else if (e.eventTime < endTime) { e.eventLength -= endTime - e.eventTime; e.eventTime = endTime; break; } // else we're done here else { break; } } } else { throw new Exception("TimelineEvent not found. Must be from this TimelineEntry!"); } OnEntryChanged(new EntryChangedEventArgs(this)); }