internal void TimeBoxDelete(TRB_PART part, TRB_STATE state, bool visibleOnly = true)
 {
     ProjectCollection.ForEach(proj =>
     {
         if (proj.Visible || !visibleOnly)
         {
             proj.DeleteTimeBoxes(part, state);
         }
     }
                               );
     ActivityTraceBuilder.Buildv2(this);
 }
 internal void TimeBoxClearContainedEdits(TRB_PART part, TRB_STATE state, bool visibleOnly = true)
 {
     lock (tableLock)
     {
         ProjectCollection.ForEach(proj =>
         {
             if (proj.Visible || !visibleOnly)
             {
                 proj.TimeBoxClearContainedEdits(part, state);
             }
         }
                                   );
         _sortAndSanitize();
         _setTimeExtents();
         _organizeIntoProjects();
         ActivityTraceBuilder.Buildv2(this);
     }
 }
        public void MoveSelectedEdges(TimeBox trbClicked, TRB_PART partMov, DateTime dt, TimeSpan snapSpan,
                                      TRB_ACTION action)
        {
            // rules..
            // don't move other edges ???
            if (action == TRB_ACTION.BEGIN)
            {
                startDT = dt;

                ptrAdjTS_0 = dt - (DateTime)trbClicked.GetDateTime(TRB_PART.START);
                ptrAdjTS_1 = dt - (DateTime)trbClicked.GetDateTime(TRB_PART.END);

                // 1 unset all edges
                UnsetState(TRB_PART.START | TRB_PART.END, TRB_STATE.SELECTED);
                // 2 set edges accordingly
                SetState(partMov, TRB_PART.WHOLE, TRB_STATE.SELECTED);

                // 3. what edge are we moving, start or end?
                movingPart = partMov;

                TimeBox adj;
                spanL = TimeSpan.MinValue;
                spanR = TimeSpan.MaxValue;

                if (movingPart.HasFlag(TRB_PART.START))
                {
                    // left move
                    // 4. Get the minimum distance to the previous end
                    foreach (var proj in EachVisibleProject())
                    {
                        if (!proj.Visible)
                        {
                            continue;
                        }
                        foreach (var trb in proj.TimeBoxCollection)
                        {
                            if (trb.HasState(movingPart, TRB_STATE.SELECTED))
                            {
                                trb.StoreDates();
                                adj = _getAdj(trb, -1);
                                if (adj != null)
                                {
                                    spanL = _max(spanL, adj.EndDate - trb.StartDate);
                                }
                                if (!movingPart.HasFlag(TRB_PART.END))
                                {
                                    spanR = _min(spanR, trb.EndDate - trb.StartDate);
                                }
                            }
                        }
                    }
                }

                if (movingPart.HasFlag(TRB_PART.END))
                {
                    // right move
                    // 5. Get the MAximuim distance to the next start
                    foreach (var proj in EachVisibleProject())
                    {
                        if (!proj.Visible)
                        {
                            continue;
                        }
                        foreach (var trb in proj.TimeBoxCollection)
                        {
                            if (trb.HasState(movingPart, TRB_STATE.SELECTED))
                            {
                                trb.StoreDates();
                                adj = _getAdj(trb, +1);
                                if (adj != null)
                                {
                                    spanR = _min(spanR, adj.StartDate - trb.EndDate);
                                }
                                if (!movingPart.HasFlag(TRB_PART.START))
                                {
                                    spanL = _max(spanL, trb.StartDate - trb.EndDate);
                                }
                            }
                        }
                    }
                }
            }

            bool snapped = false;

            if (snapSpan.TotalMinutes > 0)
            {
                // snap the active edge only
                snapped = _snapToUnselectedEdges(ref dt, snapSpan);
            }

            TimeSpan spanDT = dt - startDT;

            if (spanDT < spanL)
            {
                spanDT = spanL;
            }
            if (spanDT > spanR)
            {
                spanDT = spanR;
            }

            foreach (var proj in EachVisibleProject())
            {
                if (!proj.Visible)
                {
                    continue;
                }
                foreach (var trb in proj.TimeBoxCollection)
                {
                    if (trb.HasState(movingPart, TRB_STATE.SELECTED))
                    {
                        trb.ShiftDateTime(movingPart, spanDT);
                    }
                }
            }

            if (snapped)
            {
                SetState(TRB_PART.END, TRB_PART.END, TRB_STATE.SELECTED, TRB_STATE.SNAPPED);
            }
            else
            {
                UnsetState(TRB_PART.END, TRB_PART.END, TRB_STATE.SELECTED, TRB_STATE.SNAPPED);
            }


            // finally snap the unsnapped to others nearest day
            if (action == TRB_ACTION.FINISH)
            {
                // condition: Selected but not snapped
                TimeBoxProcess(delegate(TimeBox trb)
                {
                    if (trb.HasState(movingPart, TRB_STATE.SELECTED) &&
                        trb.HasState(movingPart, TRB_STATE.SNAPPED | TRB_STATE.NOT))
                    {
                        // snap to whole day
                        var myDT   = (DateTime)trb.GetDateTime(movingPart);
                        var snapDT = FileChangeTable.Round(myDT, new TimeSpan(1, 0, 0, 0));

                        var thisSpan = snapDT - trb.GetStoredDateTime(movingPart);
                        if (thisSpan < spanL)
                        {
                            thisSpan = spanL;
                        }
                        if (thisSpan > spanR)
                        {
                            thisSpan = spanR;
                        }
                        trb.ShiftDateTime(movingPart, (TimeSpan)thisSpan);
                    }
                });

                foreach (var proj in EachVisibleProject())
                {
                    if (!proj.Visible)
                    {
                        continue;
                    }
                    if (proj.HasState(TRB_PART.WHOLE, TRB_STATE.SELECTED))
                    {
                        proj.TimeBoxSort();
                        proj.TimeBoxMerge();
                    }
                }

                ActivityTraceBuilder.Buildv2(this);
                movingPart = TRB_PART.NONE;
            }
        }