/// <summary>
        /// Gets collection of selected elements in necessary Gantt item.
        /// </summary>
        /// <param name="selectedType">TYpe of elements which can be added to selection.</param>
        /// <param name="ganttItem">Parent gantt item.</param>
        /// <param name="firstSelectedElement">First element in global selection.</param>
        /// <param name="lastSelectedElement">Last element in global selection.</param>
        /// <returns>Collection of selected elements.</returns>
        private ICollection <IGanttItemElement> _GetSelectedElementsByGanttItem(Type selectedType, IGanttItem ganttItem,
                                                                                IGanttItemElement firstSelectedElement, IGanttItemElement lastSelectedElement)
        {
            Collection <IGanttItemElement> selectedElements = new Collection <IGanttItemElement>();

            int startIndex = 0;
            int endIndex   = ganttItem.GanttItemElements.Count;

            if (ganttItem.GanttItemElements.Contains(firstSelectedElement))
            {
                startIndex = ganttItem.GanttItemElements.IndexOf(firstSelectedElement);
            }
            if (ganttItem.GanttItemElements.Contains(lastSelectedElement))
            {
                endIndex = ganttItem.GanttItemElements.IndexOf(lastSelectedElement) + 1;
            }

            for (int i = startIndex; i < endIndex; i++)
            {
                if (ganttItem.GanttItemElements[i].Tag.GetType() == selectedType)
                {
                    selectedElements.Add(ganttItem.GanttItemElements[i]);
                }
            }

            return(selectedElements);
        }
Пример #2
0
        /// <summary>
        /// Called when one of the elements raised time range event.
        /// </summary>
        /// <param name="sender">Event source.</param>
        /// <param name="e">Event arguments.</param>
        private void _ElementTimeRangeChanged(object sender, EventArgs e)
        {
            IGanttItemElement changedElement = sender as IGanttItemElement;

            Debug.Assert(changedElement != null);

            bool needToRaiseEvent = false;

            // Check whether new end time is later then saved value:
            if (changedElement.EndTime > EndTime)
            {
                _endTime         = changedElement.EndTime;
                needToRaiseEvent = true;
            }

            // Check whether new start time is earlier then saved value:
            if (changedElement.StartTime < StartTime)
            {
                _startTime       = changedElement.StartTime;
                needToRaiseEvent = true;
            }

            // Raise event if necessary.
            if (needToRaiseEvent && TimeRangeChanged != null)
            {
                TimeRangeChanged(this, EventArgs.Empty);
            }
        }
        /// <summary>
        /// Selection logic if "Shift" button was pressed in selection.
        /// </summary>
        /// <param name="pressedElement">Last clicked element.</param>
        /// <returns>New selection collection. If selection shouldn't be changed - returns null.</returns>
        private ICollection <IGanttItemElement> _SelectItemsByShift(IGanttItemElement clickedElement)
        {
            Debug.Assert(_selectedElements.Count > 0); // Collection should contain at least one element. Otherwise we use _SelectItem method.

            // If user clicked to element in other GanttItem - do nothing.
            if (_selectedElements.First().Value.ParentGanttItem != clickedElement.ParentGanttItem)
            {
                return(null);
            }

            // Else - need to select range between first selected item and clicked item.

            // If just clicked element has the same tag as current GanttItem -
            // elemet is already in selection (was added earlier by custom logic in _SelectItem() method). And we should do nothing.
            if (_selectedElements.First().Key.ParentGanttItem.Tag == clickedElement.Tag)
            {
                return(null);
            }

            // Check that clicked item is the same type as items in collection.
            Type selectedItemsType = _selectedElements.First().Value.Tag.GetType();

            // If new element Tag type is nos same as Tag type of already selected elements - do nothing.
            if (clickedElement.Tag.GetType() != selectedItemsType)
            {
                return(null);
            }

            // Rename vars to make code more clear.
            IGanttItemElement firstSelectedElement = _selectedElements.First().Key;
            IGanttItemElement lastSelectedElement  = clickedElement;

            IGanttItem parentItem = lastSelectedElement.ParentGanttItem;

            // Defines whether selection bounds are in revert order.
            bool doSelectionBoundsHaveInvalidOrder = (parentItem.GanttItemElements.IndexOf(lastSelectedElement) < parentItem.GanttItemElements.IndexOf(firstSelectedElement));

            // If index of last selected item parent is smaller than first selected item parent - interchange items.
            if (doSelectionBoundsHaveInvalidOrder)
            {
                IGanttItemElement buffer = firstSelectedElement;
                firstSelectedElement = lastSelectedElement;
                lastSelectedElement  = buffer;
            }

            // Collection of all element which should be selected now.
            ICollection <IGanttItemElement> newSelectedElements = new Collection <IGanttItemElement>();

            // Select elements from selection range.
            newSelectedElements = _GetSelectedElementsByGanttItem(selectedItemsType, parentItem,
                                                                  firstSelectedElement, lastSelectedElement);

            return(newSelectedElements);
        }
        /// <summary>
        /// Selection logic if "Ctrl" button was pressed in selection.
        /// </summary>
        /// <param name="clickedElement">Last clicked element.</param>
        /// <returns>Collection of new selected elements. Null if selection shouldn't be changed.</returns>
        private ICollection <IGanttItemElement> _SelectItemsByCtrl(IGanttItemElement clickedElement)
        {
            Debug.Assert(_selectedElements.Count > 0); // Collection should contain at least one element. Otherwise we use _SelectItem method.

            Collection <IGanttItemElement> oldSelectedElements = new Collection <IGanttItemElement>(_selectedElements.Values.ToList <IGanttItemElement>());

            // Check that clicked item is the same type as items in collection.
            Type selectedItemsType = _selectedElements.First().Key.Tag.GetType();

            // If new element Tag type is nos same as Tag type of already selected elements - do nothing.
            if (clickedElement.Tag.GetType() != selectedItemsType)
            {
                return(null);
            }

            Collection <IGanttItemElement> selectedElements = new Collection <IGanttItemElement>();

            // Add clicked element to collection.
            selectedElements.Add(clickedElement);

            // If clicked element has same Tag as parent Gantt Item - select all elements with this tag.
            if (clickedElement.Tag == clickedElement.ParentGanttItem.Tag)
            {
                selectedElements = _GetSelectedElementsWithGanttItemTag(clickedElement.ParentGanttItem);
            }

            // If clicked element is not contains in selected collection - add it (select).
            if (!oldSelectedElements.Contains(clickedElement))
            {
                foreach (IGanttItemElement element in selectedElements)
                {
                    oldSelectedElements.Add(element);
                }
            }

            // Otherwise - remove elements (deselect).
            else
            {
                foreach (IGanttItemElement element in selectedElements)
                {
                    if (oldSelectedElements.Contains(element))
                    {
                        oldSelectedElements.Remove(element);
                    }
                }
            }

            return(oldSelectedElements);
        }
        /// <summary>
        /// Redraws element when it necessary.
        /// </summary>
        /// <param name="sender">Element to redraw.</param>
        /// <param name="e">Event args.</param>
        private void _ElementRedrawRequired(object sender, EventArgs e)
        {
            IGanttItemElement element = sender as IGanttItemElement;

            Debug.Assert(element != null);

            GanttItemElementDrawingVisual visual = null;

            if (_mapElementToVisual.TryGetValue(element, out visual))
            {
                visual.RedrawRequired = true;
            }

            InvalidateVisual();
        }
Пример #6
0
        /// <summary>
        /// Finds first element in collection by tag.
        /// </summary>
        /// <param name="tag">Necessary tag.</param>
        /// <returns>Result element.</returns>
        public IGanttItemElement FindFirstElementByTag(object tag)
        {
            IGanttItemElement foundElement = null;

            // Add all elements with necessary tag into result collection.
            foreach (IGanttItemElement element in _ganttItemElements)
            {
                if (element.Tag.Equals(tag))
                {
                    foundElement = element;
                    break;
                }
            }

            return(foundElement);
        }
        /// <summary>
        /// Handler updates selection if necessary.
        /// </summary>
        /// <param name="sender">Container.</param>
        /// <param name="e">Mouse event args.</param>
        private void _PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            if (_needToReleaseSelection)
            {
                // Get clicked element.
                IGanttItemElement ganttItemElement = this.HitTest(Mouse.GetPosition(this)) as IGanttItemElement;

                if (ganttItemElement == null)
                {
                    return;
                }

                _Select(ganttItemElement);
            }
            _needToReleaseSelection       = false;
            _mustStartDraggingOnMouseMove = false;
        }
        /// <summary>
        /// Calculates drawing area for necessary visual children.
        /// </summary>
        /// <param name="element">Element for which bounds should be calculated.</param>
        /// <returns>New drawing area in relative coordinates.</returns>
        private Rect _GetChildDrawingArea(IGanttItemElement element, GanttItemElementDrawingContext context)
        {
            Debug.Assert(element != null);
            Debug.Assert(element.ParentGanttItem != null);

            // Define Y position of element.
            double yPos = _ganttItems.IndexOf(element.ParentGanttItem) * _rowHeight;

            // Copy start and end time from element to context.
            context.StartTime = element.StartTime;
            context.EndTime   = element.EndTime;

            // If elemnts start time or end time is out of
            if (element.StartTime < _startTime)
            {
                context.StartTime = _startTime;
            }
            if (element.EndTime > _endTime)
            {
                context.EndTime = _endTime;
            }

            // Define element duration in time units.
            TimeSpan elementDuration = context.EndTime - context.StartTime;

            // Define element shift from left container border. We are always make a gap with width = 1 for correctly show elements styles.
            double xPos = Math.Max(1, (context.StartTime - _startTime).Ticks * _pixelsPerTick);

            // Define element duration in pixels.
            double elementWidth = Math.Max(0, Math.Abs(elementDuration.Ticks) * _pixelsPerTick);

            if (elementWidth == 0)
            {
                elementWidth = DEFAULT_ELEMENT_WIDTH;
            }

            // Define element height - it's the same for all elements and equals row height.
            double elementHeight = _rowHeight;

            return(new Rect(xPos, yPos, elementWidth, elementHeight));
        }
        /// <summary>
        /// Selects gantt elements depending on keyboard state.
        /// </summary>
        /// <param name="ganttItemElement">Element to select.</param>
        private void _Select(IGanttItemElement ganttItemElement)
        {
            Debug.Assert(ganttItemElement != null);

            ICollection <IGanttItemElement> newSelection = null;

            // If no modifier keys was pressed on keyboard or selection is empty - use single selection logic.
            if (_selectedElements.Count == 0 || Keyboard.Modifiers == ModifierKeys.None)
            {
                newSelection = _SelectItem(ganttItemElement);
            }
            else if (Keyboard.Modifiers == ModifierKeys.Shift) // If "Shift" key was pressed.
            {
                newSelection = _SelectItemsByShift(ganttItemElement);
            }
            else if (Keyboard.Modifiers == ModifierKeys.Control) // if "Ctrl" key was pressed.
            {
                newSelection = _SelectItemsByCtrl(ganttItemElement);
            }

            // If new selected collection is null - selection should not be changed.
            if (newSelection == null)
            {
                return;
            }

            // Set "RedrawRequired" status to true in necessary elements.
            _UpdateRedrawRequiredStatusWhenSelectionChanged(newSelection);

            // Update collection of selected items
            _selectedElements.Clear();

            foreach (IGanttItemElement element in newSelection)
            {
                _selectedElements.Add(element, element);
            }

            InvalidateVisual();
            _OnSelectionChanged();
        }
        /// <summary>
        /// Handler changes selection by mouse click.
        /// </summary>
        /// <param name="sender">Container.</param>
        /// <param name="e">Mouse event args.</param>
        private void _MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            Debug.Assert(_selectedElements != null);

            // Get clicked element.
            IGanttItemElement ganttItemElement = this.HitTest(Mouse.GetPosition(this)) as IGanttItemElement;

            if (ganttItemElement == null)
            {
                return;
            }

            _mustStartDraggingOnMouseMove = true;

            if (_selectedElements.ContainsKey(ganttItemElement))
            {
                _needToReleaseSelection = true;
                return;
            }

            _Select(ganttItemElement);
        }
        /// <summary>
        /// Method removes all visuals from child collection if visual is bound with gantt item. Also removes objects from selection.
        /// </summary>
        /// <param name="ganttItem">Gantt item.</param>
        private void _RemoveVisualsForGanttItem(IGanttItem ganttItem)
        {
            Collection <IGanttItemElement> itemsToRemove = new Collection <IGanttItemElement>();

            foreach (GanttItemElementDrawingVisual visual in _children) //(int i = 0; i < VisualChildrenCount; i++)
            {
                IGanttItemElement element = ((GanttItemElementDrawingVisual)visual).GanttItemElement;

                if (element.ParentGanttItem.Equals(ganttItem))
                {
                    itemsToRemove.Add(element);
                }
            }

            // Remove necessary elements from collection.
            foreach (IGanttItemElement element in itemsToRemove)
            {
                element.RedrawRequired -= _ElementRedrawRequired;
                _children.Remove(_mapElementToVisual[element]);
                _mapElementToVisual.Remove(element);
                _selectedElements.Remove(element);
            }
        }
        /// <summary>
        /// Adds item into collection of selected items.
        /// </summary>
        /// <param name="pressedElement"></param>
        /// <returns>Collection of selected elements.</returns>
        private ICollection <IGanttItemElement> _SelectItem(IGanttItemElement ganttItemElement)
        {
            List <IGanttItemElement> newSelection = new List <IGanttItemElement>();

            // If selected element has the same Tag as parent Gantt Item - select all elements with this tag.
            if (ganttItemElement.Tag == ganttItemElement.ParentGanttItem.Tag)
            {
                ICollection <IGanttItemElement> selectedElements = _GetSelectedElementsWithGanttItemTag(ganttItemElement.ParentGanttItem);

                if (selectedElements.Count == 0)
                {
                    return(null);
                }

                newSelection.AddRange(selectedElements);
            }
            else
            {
                newSelection.Add(ganttItemElement);
            }

            return(newSelection);
        }
Пример #13
0
 public GanttItemElementDrawingVisual(IGanttItemElement element)
 {
     GanttItemElement = element;
     RedrawRequired   = true;
 }
 public GanttItemElementDrawingVisual(IGanttItemElement element)
 {
     GanttItemElement = element;
     RedrawRequired = true;
 }
        /// <summary>
        /// Selection logic if "Shift" button was pressed in selection.
        /// </summary>
        /// <param name="pressedElement">Last clicked element.</param>
        /// <returns>New selection collection. If selection shouldn't be changed - returns null.</returns>
        private ICollection<IGanttItemElement> _SelectItemsByShift(IGanttItemElement clickedElement)
        {
            Debug.Assert(_selectedElements.Count > 0); // Collection should contain at least one element. Otherwise we use _SelectItem method.

            // If user clicked to element in other GanttItem - do nothing.
            if (_selectedElements.First().Value.ParentGanttItem != clickedElement.ParentGanttItem)
                return null;

            // Else - need to select range between first selected item and clicked item.

            // If just clicked element has the same tag as current GanttItem -
            // elemet is already in selection (was added earlier by custom logic in _SelectItem() method). And we should do nothing.
            if (_selectedElements.First().Key.ParentGanttItem.Tag == clickedElement.Tag)
                return null;

            // Check that clicked item is the same type as items in collection.
            Type selectedItemsType = _selectedElements.First().Value.Tag.GetType();

            // If new element Tag type is nos same as Tag type of already selected elements - do nothing.
            if (clickedElement.Tag.GetType() != selectedItemsType)
                return null;

            // Rename vars to make code more clear.
            IGanttItemElement firstSelectedElement = _selectedElements.First().Key;
            IGanttItemElement lastSelectedElement = clickedElement;

            IGanttItem parentItem = lastSelectedElement.ParentGanttItem;

            // Defines whether selection bounds are in revert order.
            bool doSelectionBoundsHaveInvalidOrder = (parentItem.GanttItemElements.IndexOf(lastSelectedElement) < parentItem.GanttItemElements.IndexOf(firstSelectedElement));

            // If index of last selected item parent is smaller than first selected item parent - interchange items.
            if (doSelectionBoundsHaveInvalidOrder)
            {
                IGanttItemElement buffer = firstSelectedElement;
                firstSelectedElement = lastSelectedElement;
                lastSelectedElement = buffer;
            }

            // Collection of all element which should be selected now.
            ICollection<IGanttItemElement> newSelectedElements = new Collection<IGanttItemElement>();

            // Select elements from selection range.
            newSelectedElements = _GetSelectedElementsByGanttItem(selectedItemsType, parentItem,
                firstSelectedElement, lastSelectedElement);

            return newSelectedElements;
        }
        /// <summary>
        /// Selection logic if "Ctrl" button was pressed in selection.
        /// </summary>
        /// <param name="clickedElement">Last clicked element.</param>
        /// <returns>Collection of new selected elements. Null if selection shouldn't be changed.</returns>
        private ICollection<IGanttItemElement> _SelectItemsByCtrl(IGanttItemElement clickedElement)
        {
            Debug.Assert(_selectedElements.Count > 0); // Collection should contain at least one element. Otherwise we use _SelectItem method.

            Collection<IGanttItemElement> oldSelectedElements = new Collection<IGanttItemElement>(_selectedElements.Values.ToList<IGanttItemElement>());

            // Check that clicked item is the same type as items in collection.
            Type selectedItemsType = _selectedElements.First().Key.Tag.GetType();

            // If new element Tag type is nos same as Tag type of already selected elements - do nothing.
            if (clickedElement.Tag.GetType() != selectedItemsType)
                return null;

            Collection<IGanttItemElement> selectedElements = new Collection<IGanttItemElement>();

            // Add clicked element to collection.
            selectedElements.Add(clickedElement);

            // If clicked element has same Tag as parent Gantt Item - select all elements with this tag.
            if (clickedElement.Tag == clickedElement.ParentGanttItem.Tag)
                selectedElements = _GetSelectedElementsWithGanttItemTag(clickedElement.ParentGanttItem);

            // If clicked element is not contains in selected collection - add it (select).
            if (!oldSelectedElements.Contains(clickedElement))
            {
                foreach (IGanttItemElement element in selectedElements)
                    oldSelectedElements.Add(element);
            }

            // Otherwise - remove elements (deselect).
            else
            {
                foreach (IGanttItemElement element in selectedElements)
                    if (oldSelectedElements.Contains(element))
                        oldSelectedElements.Remove(element);
            }

            return oldSelectedElements;
        }
        /// <summary>
        /// Adds item into collection of selected items.
        /// </summary>
        /// <param name="pressedElement"></param>
        /// <returns>Collection of selected elements.</returns>
        private ICollection<IGanttItemElement> _SelectItem(IGanttItemElement ganttItemElement)
        {
            List<IGanttItemElement> newSelection = new List<IGanttItemElement>();

            // If selected element has the same Tag as parent Gantt Item - select all elements with this tag.
            if (ganttItemElement.Tag == ganttItemElement.ParentGanttItem.Tag)
            {
                ICollection<IGanttItemElement> selectedElements = _GetSelectedElementsWithGanttItemTag(ganttItemElement.ParentGanttItem);

                if (selectedElements.Count == 0)
                    return null;

                newSelection.AddRange(selectedElements);
            }
            else
                newSelection.Add(ganttItemElement);

            return newSelection;
        }
        /// <summary>
        /// Selects gantt elements depending on keyboard state.
        /// </summary>
        /// <param name="ganttItemElement">Element to select.</param>
        private void _Select(IGanttItemElement ganttItemElement)
        {
            Debug.Assert(ganttItemElement != null);

            ICollection<IGanttItemElement> newSelection = null;

            // If no modifier keys was pressed on keyboard or selection is empty - use single selection logic.
            if (_selectedElements.Count == 0 || Keyboard.Modifiers == ModifierKeys.None)
            {
                newSelection = _SelectItem(ganttItemElement);
            }
            else if (Keyboard.Modifiers == ModifierKeys.Shift) // If "Shift" key was pressed.
            {
                newSelection = _SelectItemsByShift(ganttItemElement);
            }
            else if (Keyboard.Modifiers == ModifierKeys.Control) // if "Ctrl" key was pressed.
            {
                newSelection = _SelectItemsByCtrl(ganttItemElement);
            }

            // If new selected collection is null - selection should not be changed.
            if (newSelection == null)
                return;

            // Set "RedrawRequired" status to true in necessary elements.
            _UpdateRedrawRequiredStatusWhenSelectionChanged(newSelection);

            // Update collection of selected items
            _selectedElements.Clear();

            foreach (IGanttItemElement element in newSelection)
                _selectedElements.Add(element, element);

            InvalidateVisual();
            _OnSelectionChanged();
        }
        /// <summary>
        /// Gets collection of selected elements in necessary Gantt item.
        /// </summary>
        /// <param name="selectedType">TYpe of elements which can be added to selection.</param>
        /// <param name="ganttItem">Parent gantt item.</param>
        /// <param name="firstSelectedElement">First element in global selection.</param>
        /// <param name="lastSelectedElement">Last element in global selection.</param>
        /// <returns>Collection of selected elements.</returns>
        private ICollection<IGanttItemElement> _GetSelectedElementsByGanttItem(Type selectedType, IGanttItem ganttItem,
            IGanttItemElement firstSelectedElement, IGanttItemElement lastSelectedElement)
        {
            Collection<IGanttItemElement> selectedElements = new Collection<IGanttItemElement>();

            int startIndex = 0;
            int endIndex = ganttItem.GanttItemElements.Count;

            if (ganttItem.GanttItemElements.Contains(firstSelectedElement))
                startIndex = ganttItem.GanttItemElements.IndexOf(firstSelectedElement);
            if (ganttItem.GanttItemElements.Contains(lastSelectedElement))
                endIndex = ganttItem.GanttItemElements.IndexOf(lastSelectedElement) + 1;

            for (int i = startIndex; i < endIndex; i++)
            {
                if (ganttItem.GanttItemElements[i].Tag.GetType() == selectedType)
                    selectedElements.Add(ganttItem.GanttItemElements[i]);
            }

            return selectedElements;
        }
        /// <summary>
        /// Calculates drawing area for necessary visual children.
        /// </summary>
        /// <param name="element">Element for which bounds should be calculated.</param>
        /// <returns>New drawing area in relative coordinates.</returns>
        private Rect _GetChildDrawingArea(IGanttItemElement element, GanttItemElementDrawingContext context)
        {
            Debug.Assert(element != null);
            Debug.Assert(element.ParentGanttItem != null);

            // Define Y position of element.
            double yPos = _ganttItems.IndexOf(element.ParentGanttItem) * _rowHeight;

            // Copy start and end time from element to context.
            context.StartTime = element.StartTime;
            context.EndTime = element.EndTime;

            // If elemnts start time or end time is out of
            if (element.StartTime < _startTime)
                context.StartTime = _startTime;
            if (element.EndTime > _endTime)
                context.EndTime = _endTime;

            // Define element duration in time units.
            TimeSpan elementDuration = context.EndTime - context.StartTime;

            // Define element shift from left container border. We are always make a gap with width = 1 for correctly show elements styles.
            double xPos = Math.Max(1, (context.StartTime - _startTime).Ticks * _pixelsPerTick);

            // Define element duration in pixels.
            double elementWidth = Math.Max(0, Math.Abs(elementDuration.Ticks) * _pixelsPerTick);

            if (elementWidth == 0)
                elementWidth = DEFAULT_ELEMENT_WIDTH;

            // Define element height - it's the same for all elements and equals row height.
            double elementHeight = _rowHeight;

            return new Rect(xPos, yPos, elementWidth, elementHeight);
        }
 /// <summary>
 /// Retruns bounds of element.
 /// </summary>
 /// <param name="element">IGanttItemElement.</param>
 /// <returns>Element bounds.</returns>
 public Rect GetElementBounds(IGanttItemElement element)
 {
     return _GetChildDrawingArea(element, new GanttItemElementDrawingContext());
 }
 /// <summary>
 /// Retruns bounds of element.
 /// </summary>
 /// <param name="element">IGanttItemElement.</param>
 /// <returns>Element bounds.</returns>
 public Rect GetElementBounds(IGanttItemElement element)
 {
     return(_GetChildDrawingArea(element, new GanttItemElementDrawingContext()));
 }