private void ProfileEventsViewer_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
        {
            if (m_Data == null || ClientSize.Width == 0 || ClientSize.Height == 0)
            {
                return;
            }

            if (m_OffScreenBitmap == null)
            {
                UpdateOffscreenSurface();
            }

            Int64 width            = ClientSize.Width;
            Time  timeStepPerPixel = TimeStepPerPixel();

            DrawEventContext drawContext = new DrawEventContext();

            drawContext.Graphics           = m_OffScreenGraphics;
            drawContext.m_TimeStepPerPixel = timeStepPerPixel;

            drawContext.Graphics.Clear(Color.LightGray);
            drawContext.m_Y = (Int32)m_YOffset;

            int contextIndex = 0;

            // draw the thing
            foreach (ProfileEventData.ProfileContext context in m_Data.Contexts.Values)
            {
                if (context.Heads.Count == 0)
                {
                    continue;
                }

                Brush titleBrush;

                // Print context name
                if ((contextIndex & 1) == 0)
                {
                    titleBrush = titleBrush1;
                }
                else
                {
                    titleBrush = titleBrush2;
                }

                drawContext.Graphics.FillRectangle(titleBrush, 0, drawContext.m_Y, width, ((context.MaxLevel + 1) * EventHeight) + TitleHeight);
                drawContext.Graphics.DrawString(context.Name, contextTitleFont, fontBrush, 0, drawContext.m_Y);

                drawContext.m_Y += TitleHeight;
                drawContext.overDraw.Reset();

                foreach (ProfileEventData.ProfileContext.Event profileEvent in context.Heads)
                {
                    DrawEvent(profileEvent, ref drawContext);
                }

                drawContext.m_Y += ((context.MaxLevel + 1) * EventHeight);
                contextIndex++;

                if (m_CurrentMarker != null)
                {
                    DrawEvent(m_CurrentMarker, ref drawContext);
                }
            }

            // draw the selection range
            Int64 rangeX  = ConvertTimeToX(m_RangeStart);
            Int64 rangeXE = ConvertTimeToX(m_RangeEnd);

            if (rangeXE == rangeX)
            {
                rangeXE++;
            }
            Int64 rangeWidth = rangeXE - rangeX;

            // check if the range is visilbe
            if ((rangeX < ClientSize.Width) &&
                (rangeXE > 0) && rangeWidth != 0)
            {
                // display the selection range extent
                drawContext.Graphics.FillRectangle(rangeBrush, rangeX, 0, rangeWidth, ClientSize.Height);

                // display range length
                drawContext.Graphics.DrawString(TimeToString((UInt64)(m_RangeEnd - m_RangeStart)), barFont, fontBrush, rangeX, ClientSize.Height - EventHeight);
            }


            e.Graphics.DrawImage(m_OffScreenBitmap, 0, 0);
        }
        private void DrawEvent(ProfileEventData.ProfileContext.Event profileEvent, ref DrawEventContext drawContext)
        {
            Pen   activeRectPen = rectPen;
            float rectOffset    = 0;

            if (profileEvent == m_eventSelection)
            {
                activeRectPen = rectPenSelected;
                rectOffset    = 1.5f;
            }

            if (profileEvent.Inside(m_TimeStart, m_TimeEnd))
            {
                Int64 screenXEnd = (Int64)((profileEvent.Time + profileEvent.Length - m_TimeStart) / drawContext.m_TimeStepPerPixel);
                if (!drawContext.overDraw.ShouldDraw(screenXEnd))
                {
                    return;
                }

                // compute screen X size
                Int64 screenX      = (Int64)((profileEvent.Time - m_TimeStart) / drawContext.m_TimeStepPerPixel);
                Int64 screenLength = (Int64)((profileEvent.Length) / drawContext.m_TimeStepPerPixel);
                Int64 screenXE     = screenX + screenLength;
                bool  nulSized     = (screenLength == 0);


                // draw a rectangle
                rectBrush.Color = m_Data.GetProfileColor(profileEvent.ProfileID);
                screenX         = Math.Max(-20, screenX);
                screenXE        = Math.Min(ClientSize.Width + 20, screenXE);
                if (screenXE == screenX)
                {
                    screenXE++;
                }
                screenLength = screenXE - screenX;

                int offsetY = 0;
                if (profileEvent.EventType == ProfileEventViewer.ProfileEventData.ProfileContext.Event.EventStart)
                {
                    drawContext.Graphics.FillRectangle(rectBrush, screenX, drawContext.m_Y, screenLength, EventHeight);
                    drawContext.Graphics.DrawRectangle(activeRectPen, screenX + rectOffset, drawContext.m_Y + rectOffset, screenLength - (rectOffset * 2), EventHeight - (rectOffset * 2));
                }
                else
                {
                    //drawContext.Graphics.FillRectangle(rectBrush, screenX, drawContext.m_Y, screenLength, MarkerHeight);
                    offsetY = -2 * EventHeight;

                    rectBrush.Color = Color.Red;
                    drawContext.Graphics.FillRectangle(rectBrush, screenX, drawContext.m_Y + offsetY, screenLength, EventHeight);
                    drawContext.Graphics.DrawRectangle(activeRectPen, screenX + rectOffset, drawContext.m_Y + offsetY + rectOffset, screenLength - (rectOffset * 2), EventHeight - (rectOffset * 2));
                }


                // set the clip region and display the profile name (if there's any chance it could fit)
                if ((screenLength > 20) || (profileEvent == m_eventSelection))
                {
                    Region oldClipRegion = drawContext.Graphics.Clip;
                    drawContext.Graphics.SetClip(new Rectangle((int)screenX + 1, drawContext.m_Y + offsetY, (int)screenLength - 1, EventHeight));

                    string profileName = String.Format("{0}{1}", (screenX < 0) ? "<< " : "", m_Data.GetProfileName(profileEvent.ProfileID));
                    string profileTime = String.Format("{0}{1}", (screenX < 0) ? "<< " : "", TimeToString((UInt64)profileEvent.Length));
                    drawContext.Graphics.DrawString(profileName, barFont, fontBrush, Math.Max(screenX + 1, 0), drawContext.m_Y - 0 + offsetY);
                    drawContext.Graphics.DrawString(profileTime, barFont, fontBrush, Math.Max(screenX + 1, 0), drawContext.m_Y + 10 + offsetY);

                    drawContext.Graphics.Clip = oldClipRegion;
                }

                // must draw the childs (if we were not too small)
                if (profileEvent.Child != null && screenLength > 1)
                {
                    drawContext.Graphics.FillRectangle(selfBrush, screenX, drawContext.m_Y + EventHeight, screenLength, EventHeight);

                    drawContext.m_Y += EventHeight;
                    Int64 keepColumn = drawContext.overDraw.Reset();

                    ProfileEventData.ProfileContext.Event child = profileEvent.Child;

                    while (child != null)
                    {
                        DrawEvent(child, ref drawContext);
                        child = child.Sibling;
                    }

                    drawContext.overDraw.Reset(keepColumn);

                    drawContext.m_Y -= EventHeight;
                }
            }
        }