Beispiel #1
0
        /// <summary>
        /// Update tooltip when mouse moves over picture
        /// </summary>
        private void HistoryPictureOnMouseMove(object sender, MouseEventArgs e)
        {
            var p = Cursor.Position;
            var x = p.X;
            var y = p.Y + 20;

            if (_lastPosition.X == x && _lastPosition.Y == y && _lastScrollPositionY == e.Y)
            {
                return;
            }
            if (e.X < GraphStartPixel)
            {
                return;
            }
            if (_indexToDaynumber == null || _indexToDaynumber.Length == 0)
            {
                return;
            }

            _lastPosition = new Point(x, y);

            // var absoluteY = y - historyPicture.Location.Y - Location.Y;
            var dayIndex = (e.Y - GraphSpacing / 2) / (GraphHeight + GraphSpacing);

            if (dayIndex < 0)
            {
                dayIndex = 0;
            }
            if (dayIndex >= _indexToDaynumber.Length)
            {
                dayIndex = _indexToDaynumber.Length - 1;
            }
            var dayNumber = _indexToDaynumber[dayIndex];

            var second = (((uint)e.X - GraphStartPixel) * _graphSeconds / _graphWidth) + _graphFirstSecond;

            var graphPixel = e.X - GraphStartPixel;
            var slot       = DaySlots.GetValueOrDefault(dayNumber).FirstOrDefault(d => d.EndX >= graphPixel);

            if (slot == null || slot.StartX > graphPixel)
            {
                _tipLabel.Text = $"{SecondToTime(second)} (no activity)";
            }
            else
            {
                _tipLabel.Text = $"{SecondToTime(second)} {slot.Describe(_showSharedHistory)}";
            }

            _tipLabel.Location   = _lastPosition;
            _lastScrollPositionY = e.Y;

            if (!_tipLabel.Visible)
            {
                _tipLabel.ShowFloating();
            }
        }
        private DaySlots SplitDayInSlots(DayOfWeekInfo dayOfWeekInfo)
        {
            try
            {
                ThrowExceptionIsNotValidDataDay(dayOfWeekInfo);


                var availableSlots = new List <IntervalSlot>();

                var workStartAt = GetDateTimeFrom(dayOfWeekInfo, dayOfWeekInfo.WorkPeriod.StartHour, 0);
                var workEndsAt  = GetDateTimeFrom(dayOfWeekInfo, dayOfWeekInfo.WorkPeriod.EndHour, 0);

                var lunchStartAt = GetDateTimeFrom(dayOfWeekInfo, dayOfWeekInfo.WorkPeriod.LunchStartHour, 0);
                var lunchEndsAt  = GetDateTimeFrom(dayOfWeekInfo, dayOfWeekInfo.WorkPeriod.LunchEndHour, 0);

                while (workStartAt != workEndsAt)
                {
                    int minutes = +_weekData.SlotDurationMinutes;

                    var slotToAdd = GetDateTimeFrom(dayOfWeekInfo, workStartAt.Hour, workStartAt.Minute);

                    if (IsAvailableSlot(dayOfWeekInfo, slotToAdd, lunchStartAt, lunchEndsAt))
                    {
                        availableSlots.Add(new IntervalSlot(slotToAdd, _weekData.SlotDurationMinutes));
                    }

                    workStartAt = workStartAt.AddMinutes(minutes);
                }

                return(new DaySlots(dayOfWeekInfo.CurrentDate, availableSlots));
            }
            catch (Exception err)
            {
                _loggerProvider.Log(err);
                return(DaySlots.CreateDayWithNoAvailability(dayOfWeekInfo.CurrentDate));
            }
        }
        private static IEnumerable <FreeSlot> GetDayFreeSlots(DateTime startOfDay, int slotDurationMinutes, DaySlots day)
        {
            if (day?.WorkPeriod == null)
            {
                return(null);
            }

            var freeSlots = new List <FreeSlot>();

            var slotStart = new DateTime(startOfDay.Year, startOfDay.Month, startOfDay.Day, day.WorkPeriod.StartHour, 0, 0);
            var dayEnd    = new DateTime(startOfDay.Year, startOfDay.Month, startOfDay.Day, day.WorkPeriod.EndHour, 0, 0);
            var slotEnd   = slotStart.AddMinutes(slotDurationMinutes);

            while (slotEnd <= dayEnd)
            {
                if (!day.IsInLunchPeriod(slotStart, slotEnd) && !day.IsSlotBusy(slotStart, slotEnd))
                {
                    freeSlots.Add(new FreeSlot
                    {
                        StartTime = slotStart,
                        EndTime   = slotEnd,
                    });
                }

                slotStart = slotStart.AddMinutes(slotDurationMinutes);
                slotEnd   = slotStart.AddMinutes(slotDurationMinutes);
            }

            return(freeSlots);
        }
        private void DrawHistory(Bitmap target, Dictionary <string, MonthActivities> history)
        {
            // Figure out when first activity started and when last activity ended (for the whole month)
            var firstTime = history.MinOrDefault(c => c.Value.Days.MinOrDefault(d => d.Value.First().StartSecond));
            var lastTime  = history.MaxOrDefault(c => c.Value.Days.MaxOrDefault(d => d.Value.Last().EndSecond));

            // Create list of programs used, the most used first
            var programs = history.SelectMany(c => c.Value.Days.Values.SelectMany(x => x.Where(a => a.WasActive)
                                                                                  .Select(a => new
            {
                Id      = c.Value.ApplicationNames[a.ApplicationNameIndex],
                Seconds = a.EndSecond - a.StartSecond
            })))
                           .GroupBy(z => z.Id).ToDictionary(x => x.Key, a => a.Sum(s => s.Seconds))
                           .OrderByDescending(x => x.Value);

            // Assign unique colors to the most used programs
            var brushLookup = programs.Zip(_programBrushes, (program, color) => new { program, color })
                              .ToDictionary(x => x.program.Key, x => x.color);
            var idleBrush = new SolidBrush(Color.Gray);

            _graphFirstSecond = firstTime;

            var graphicsObj = Graphics.FromImage(_historyGraph);
            var pen         = new Pen(Color.Olive, 1);

            _graphWidth   = (uint)(target.Width - 80);
            _graphSeconds = lastTime - firstTime;
            if (_graphSeconds == 0)
            {
                _graphSeconds = 1;
            }
            var daylineHeight = 2;

            // Draw hour lines
            var greypen   = new Pen(Color.LightGray, 1);
            var firstHour = (int)Math.Ceiling(firstTime / 3600.0);
            var lastHour  = (int)Math.Floor(lastTime / 3600.0);

            for (int x = firstHour; x <= lastHour; x++)
            {
                var xpixel = (((x * 3600) - firstTime) * _graphWidth) / _graphSeconds + GraphStartPixel;
                graphicsObj.DrawLine(greypen, xpixel, 10, xpixel, target.Height);
            }

            // Draw each day
            DaySlots.Clear();
            int currentY = GraphSpacing;

            foreach (var dayNumber in _indexToDaynumber)
            {
                DaySlots.Add(dayNumber, new List <ScreenSlot>());
                var dayHistory = history.Where(x => x.Value.Days.ContainsKey(dayNumber))
                                 .ToDictionary(x => x.Key, x => x.Value.Days[dayNumber]);

                // At what pixel is this day's first and last activities?
                var todaysFirstSecond = dayHistory.Min(x => x.Value.FirstActiveSecond);
                var todaysLastSecond  = dayHistory.Max(x => x.Value.LastActiveSecond);

                var startpixel = (todaysFirstSecond - firstTime) * _graphWidth / _graphSeconds;
                var endPixel   = (todaysLastSecond - firstTime) * _graphWidth / _graphSeconds;

                // Draw a small line representing the whole day
                var graphbox = new Rectangle((int)startpixel + GraphStartPixel,
                                             currentY + GraphHeight / 2 - daylineHeight / 2, (int)(endPixel - startpixel) + 1, daylineHeight);
                graphicsObj.DrawRectangle(pen, graphbox);

                var startz = dayHistory.SelectMany(x => x.Value)
                             .GroupBy(a => (a.StartSecond - firstTime) * _graphWidth / _graphSeconds)
                             .ToDictionary(x => x.Key, x => x.ToList());
                var endz = dayHistory.SelectMany(x => x.Value)
                           .GroupBy(a => (a.EndSecond - firstTime) * _graphWidth / _graphSeconds)
                           .ToDictionary(x => x.Key, x => x.ToList());
                var allPixels = startz.Keys.Concat(endz.Keys).Distinct()
                                .OrderBy(x => x).ToList();

                var activeActivities = new HashSet <ActivitySpan>();
                for (var index = 0; index < allPixels.Count - 1; index++)
                {
                    startpixel = allPixels[index];
                    endPixel   = allPixels[index + 1] - 0;
                    // Add new activities
                    if (startz.ContainsKey(startpixel))
                    {
                        activeActivities.AddRange(startz[startpixel]);
                    }
                    // Remove ending activities
                    if (endz.ContainsKey(startpixel))
                    {
                        foreach (var endedSpan in endz[startpixel])
                        {
                            activeActivities.Remove(endedSpan);
                        }
                    }

                    var span = new ScreenSlot(startpixel, endPixel, currentY, activeActivities);
                    DaySlots[dayNumber].Add(span);

                    // Select brush
                    Brush thisBrush;
                    if (!span.WasActive)
                    {
                        thisBrush = idleBrush;
                    }
                    else if (activeActivities.Count(x => x.WasActive) == 1)
                    {
                        thisBrush = ActivityBrush(activeActivities.Single(x => x.WasActive), brushLookup);
                    }
                    else
                    {
                        var colorList = activeActivities.Select(a => ActivityBrush(a, brushLookup).Color)
                                        .Distinct().OrderBy(x => x.Name).ToList();
                        var key = string.Join("|", colorList.Select(x => x.Name));
                        if (_textureBrushes.ContainsKey(key))
                        {
                            thisBrush = _textureBrushes[key];
                        }
                        else
                        {
                            var scale = 3;
                            var img   = new Bitmap(1, colorList.Count * scale);
                            var ix    = 0;
                            foreach (var color in colorList)
                            {
                                for (int i = 0; i < scale; i++)
                                {
                                    img.SetPixel(0, ix++, color);
                                }
                            }
                            thisBrush            = new TextureBrush(img);
                            _textureBrushes[key] = thisBrush;
                        }
                    }

                    // Draw
                    graphicsObj.FillRectangle(thisBrush, span.DrawBox);
                }

                currentY += GraphSpacing + GraphHeight;
            }
            graphicsObj.Dispose();
        }