/// <summary>Возвращает информацию по ячейке</summary> void GetCell(Point pos, out MFWorker worker, out DateTime?t) { worker = null; t = null; if (rectGrid == Rect.Empty) { return; } var workers = MFPlannerManager.GetWorkers(IsShowEndWorkWokers); var index = 0; for (; index < workers.Count; index++) { var rectTmp = new Rect(0, rectGrid.Y + rowHeight * index, rectGrid.Right, rowHeight); if (rectTmp.Contains(pos)) { worker = workers[index]; } } var d = TimeStart; var cellWidth = rectGrid.Width / (TimeEnd - TimeStart).TotalDays; index = 0; while (d < TimeEnd) { var rectTmp = new Rect(rectGrid.X + index * cellWidth, rectGrid.Top - rowMonthAndDay, cellWidth, rectGrid.Height + rowMonthAndDay); if (rectTmp.Contains(pos)) { t = d; return; } d = d.AddDays(1); index++; } }
// Изменились работники void MFPlannerManager_WorkersChanged(object sender, EventArgs e) { listWorkers.ItemsSource = null; listWorkers.ItemsSource = MFPlannerManager.GetWorkers(true); }
// Размеры protected override Size MeasureOverride(Size constraint) { var workers = MFPlannerManager.GetWorkers(IsShowEndWorkWokers); return(new Size(constraint.Width, workers.Count * rowHeight + rowMonthAndDay * 3)); }
void Rendraw(DrawingContext dc) { if (double.IsNaN(ActualWidth) || double.IsNaN(ActualHeight)) { return; } var t0 = DateTime.Now; FormattedText txt = null; int index = 0; var posMouse = Mouse.GetPosition(this); rectGrid = new Rect(0, (rowMonthAndDay * 2 + 3), ActualWidth, ActualHeight - (rowMonthAndDay * 2 + 3)); Rect rectTmp = Rect.Empty; // фон dc.DrawRectangle(Brushes.White, penGrid, new Rect(0, 0, ActualWidth, ActualHeight)); #region рисуем шкалу человеков var workers = MFPlannerManager.GetWorkers(IsShowEndWorkWokers); double colWorkerWidth = 100; for (index = 0; index < workers.Count; index++) { var name = string.Format("{0} {1} [{2}]", workers[index].SecondName, workers[index].Name, workers[index].Post); // Если уволенный if (workers[index].EndWorkTime.HasValue) { dc.DrawRectangle(brushEndWork, null, new Rect(0, rectGrid.Y + rowHeight * index, rectGrid.Right, rowHeight)); name += string.Format("\n(уволен)"); } txt = new FormattedText(name, CultureInfo.CurrentCulture, FlowDirection.LeftToRight, typeface, 14, Brushes.Black); if (colWorkerWidth < txt.Width + 10) { colWorkerWidth = txt.Width + 10; } var nameHeight = txt.Height + 2; // фамиля + имя dc.DrawText(txt, new Point(5, rectGrid.Y + rowHeight * index + (rowHeight - nameHeight) / 2)); //name = string.Format("пост: {0}", workers[index].Post); //txt = new FormattedText(name, CultureInfo.CurrentCulture, FlowDirection.LeftToRight, typeface, 11, Brushes.Gray); //dc.DrawText(txt, new Point((colWorkerWidth - txt.Width) / 2, rectGrid.Y + rowHeight * index + (rowHeight - nameHeight) / 2 + nameHeight)); dc.DrawLine(penGrid, new Point(0, rectGrid.Y + rowHeight * index), new Point(rectGrid.Right, rectGrid.Y + rowHeight * index)); // Выделение для мыши rectTmp = new Rect(0, rectGrid.Y + rowHeight * index, rectGrid.Right, rowHeight); if (rectTmp.Contains(posMouse)) { dc.DrawRectangle(brushSelection, null, rectTmp); } } dc.DrawLine(penGrid, new Point(0, rectGrid.Y + rowHeight * (index)), new Point(rectGrid.Right, rectGrid.Y + rowHeight * (index))); #endregion // максимальное имя rectGrid.X = colWorkerWidth; rectGrid.Width -= colWorkerWidth; rectGrid.Height = 50 * workers.Count; var cellWidth = rectGrid.Width / (TimeEnd - TimeStart).TotalDays; #region исуем шкалу дат DateTime?datePrev = null; var d = TimeStart; var now = DateTime.Now.Date; index = 0; while (d < TimeEnd) { // если у нас выходные if (d.DayOfWeek == DayOfWeek.Saturday || d.DayOfWeek == DayOfWeek.Sunday) { rectTmp = new Rect(rectGrid.X + index * cellWidth, rectGrid.Top - rowMonthAndDay, cellWidth, rectGrid.Height + rowMonthAndDay); dc.DrawRectangle(brushSaturdaySunday, null, rectTmp); } // текущий день if (d.Date == now) { rectTmp = new Rect(rectGrid.X + index * cellWidth, rectGrid.Top - rowMonthAndDay, cellWidth, rectGrid.Height + rowMonthAndDay); dc.DrawRectangle(brushNow, null, rectTmp); } // месяц изменился полная линия if (!datePrev.HasValue || (datePrev.Value.Month != d.Month)) { txt = new FormattedText(d.ToString("MMMM"), CultureInfo.CurrentCulture, FlowDirection.LeftToRight, typeface, 15, Brushes.Black); dc.DrawText(txt, new Point(rectGrid.X + index * cellWidth + 5, 2)); dc.DrawLine(penGrid, new Point(rectGrid.X + index * cellWidth, 0), new Point(rectGrid.X + index * cellWidth, rectGrid.Bottom)); } else // обычная линия { dc.DrawLine(penGrid, new Point(rectGrid.X + index * cellWidth, rectGrid.Y - rowMonthAndDay), new Point(rectGrid.X + index * cellWidth, rectGrid.Bottom)); } // рисуем день txt = new FormattedText(d.ToString("dd"), CultureInfo.CurrentCulture, FlowDirection.LeftToRight, typeface, 11, Brushes.Black); if (cellWidth >= txt.Width) { dc.DrawText(txt, new Point(rectGrid.X + index * cellWidth + (cellWidth - txt.Width) / 2, rowMonthAndDay + 6)); } // Выделение для мыши rectTmp = new Rect(rectGrid.X + index * cellWidth, rectGrid.Top - rowMonthAndDay, cellWidth, rectGrid.Height + rowMonthAndDay); if (rectTmp.Contains(posMouse)) { dc.DrawRectangle(brushSelection, null, rectTmp); // отрисовываем дату шкалы txt = new FormattedText(d.ToString("dd MMMM yyyy"), CultureInfo.CurrentCulture, FlowDirection.LeftToRight, typeface, 15, Brushes.Black); rectTmp = new Rect(rectGrid.X + index * cellWidth, rectGrid.Bottom, txt.Width + 10, rowMonthAndDay); dc.DrawRectangle(brushSelection, null, rectTmp); dc.DrawText(txt, new Point(rectTmp.Left + 5, rectTmp.Top)); } datePrev = d; d = d.AddDays(1); index++; } // Горизонтальная линия // дата dc.DrawLine(penGrid, new Point(rectGrid.Left, rowMonthAndDay + 3), new Point(rectGrid.Right, rowMonthAndDay + 3)); //dc.DrawLine(penGrid, new Point(0, rowMonthAndDay * 2 + 3), new Point(rect.Right, rowMonthAndDay * 2 + 3)); #endregion // Добавляем проекты if (isDirty) { var dictionary = new Dictionary <int, List <ActionTemp> >(); List <MFPlannerAction> actions = MFPlannerManager.GetActions(); foreach (MFPlannerAction action in actions) { if (!dictionary.ContainsKey(action.WorkerId)) { dictionary[action.WorkerId] = new List <ActionTemp>(); } //if ((a.TimeBegin.Date >= TimeStart && a.TimeBegin.Date <= TimeEnd) // || (a.TimeEnd.Date >= TimeStart && a.TimeEnd.Date <= TimeEnd)) { for (int indexWorker = 0; indexWorker < workers.Count; indexWorker++) { if (workers[indexWorker].Id == action.WorkerId) { double sIndex = (int)(action.TimeBegin.Date - TimeStart).TotalDays, eIndex = (int)(action.TimeEnd.Date - TimeStart).TotalDays; double x = Math.Max(rectGrid.X, rectGrid.X + sIndex * cellWidth), w = (eIndex - Math.Max(0, sIndex) + 1) * cellWidth; if (w > 0 && x < rectGrid.Right) { rectTmp = new Rect(x, rectGrid.Y + rowHeight * indexWorker, w, rowHeight); rectTmp.Inflate(0, -1); } else { rectTmp = Rect.Empty; } dictionary[action.WorkerId].Add(new ActionTemp { Action = action, Rect = rectTmp }); } } } } // выравниваем foreach (var kv in dictionary) { foreach (var a in kv.Value) { var intersectItems = kv.Value.Where(x => x != a && x.Rect.IntersectsWith(a.Rect) && x.Rect != Rect.Empty); rectTmp = a.Rect; double y = rectTmp.Y, count = intersectItems.Count(); if (count > 0) { rectTmp.Height = rectTmp.Height / (count + 1); rectTmp.Y = y; y += rectTmp.Height + 0.5; a.Rect = rectTmp; } foreach (var item in intersectItems) { rectTmp = item.Rect; rectTmp.Height = rectTmp.Height / (count + 1); rectTmp.Y = y; item.Rect = rectTmp; y += rectTmp.Height + 0.5; } } } foreach (var v in dictionary) { // Анализируем положения foreach (var a in v.Value) { MFPlannerProjectControl cProject = null; if (!controlsCache.ContainsKey(a.Action.Id)) { cProject = new MFPlannerProjectControl { Tag = a.Action, Width = a.Rect.Width, Height = a.Rect.Height }; cProject.InitContextMenu(); controlsCache[a.Action.Id] = cProject; Children.Add(cProject); } else { cProject = controlsCache[a.Action.Id]; } // видимость //cProject.Visibility = rectGrid.IntersectsWith(a.Rect) ? Visibility.Visible : Visibility.Collapsed; if (a.Rect == Rect.Empty) { cProject.Visibility = Visibility.Collapsed; continue; } cProject.Visibility = Visibility.Visible; var h = a.Rect.Height; //// уменьшаем //var count = v.Value.Count(x => x != a && x.Rect.IntersectsWith(a.Rect)); //if (count >= 1) //{ // h = h / (count + 1); //} cProject.Width = a.Rect.Width; cProject.Height = h; Canvas.SetLeft(cProject, a.Rect.Left); Canvas.SetTop(cProject, a.Rect.Top); cProject.InvalidateVisual(); } } isDirty = false; } //var res = (DateTime.Now - t0).TotalMilliseconds; //txt = new FormattedText(res.ToString(), CultureInfo.CurrentCulture, FlowDirection.LeftToRight, typeface, 15, Brushes.Black); //dc.DrawText(txt, new Point(0, 0)); }