// Calculates tab's elements, based on its width and height. // Generates a GraphicsPath, which is used for painting the tab, etc. bool Reshape(int dx, int dy) { dx--; if (width == dx && height == dy) return false; width = dx; height = dy; GraphicsPath shape; // define tab's body int c = int((float)height * 0.6f + 0.5f); // size of bounding square for the arc shape.AddArc(0, 0, c, c, 180.0f, 90.0f); shape.AddArc(width - c, 0, c, c, 270.0f, 90.0f); shape.AddLine(width, height, 0, height); shape.CloseFigure(); shape.SetMarker(); // define "x"'s circle c = height > 17 ? 14 : int((float)height * 0.78f + 0.5f); // size of bounding square for the circle Point p(width - c - 3, (height - c) / 2); // circle's position shape.AddEllipse(p.X, p.Y, c, c); shape.SetMarker(); // define "x" int o = int((float)c * 0.286f + 0.5f); // "x"'s offset shape.AddLine(p.X+o, p.Y+o, p.X+c-o, p.Y+c-o); shape.StartFigure(); shape.AddLine(p.X+c-o, p.Y+o, p.X+o, p.Y+c-o); shape.SetMarker(); delete data; data = new PathData(); shape.GetPathData(data); return true; }
// Calculates tab's elements, based on its width and height. // Generates a GraphicsPath, which is used for painting the tab, etc. bool Reshape(int dx, int dy) { dx--; if (width == dx && height == dy) return false; width = dx; height = dy; GraphicsPath shape; // define tab's body shape.AddRectangle(Rect(0, 0, width, height)); shape.SetMarker(); // define "x"'s circle int c = int((float)height * 0.78f + 0.5f); // size of bounding square for the circle int maxC = DpiScaleX(hwnd, 17); if (height > maxC) { c = DpiScaleX(hwnd, 17); } Point p(width - c - DpiScaleX(hwnd, 3), (height - c) / 2); // circle's position shape.AddEllipse(p.X, p.Y, c, c); shape.SetMarker(); // define "x" int o = int((float)c * 0.286f + 0.5f); // "x"'s offset shape.AddLine(p.X + o, p.Y + o, p.X + c - o, p.Y + c - o); shape.StartFigure(); shape.AddLine(p.X + c - o, p.Y + o, p.X + o, p.Y + c - o); shape.SetMarker(); delete data; data = new PathData(); shape.GetPathData(data); return true; }
/* ** Draws the meter on the double buffer ** */ bool MeterSegmentedLine::Draw(Gfx::Canvas& canvas) { int maxSize = m_DataWidth; if (!Meter::Draw(canvas) || maxSize <= 0) return false; Gdiplus::Graphics& graphics = canvas.BeginGdiplusContext(); double maxValue = 0.0; int counter = 0; // Find the maximum value if (m_Autoscale) { double newValue = 0; counter = 0; for (auto i = m_AllValues.cbegin(); i != m_AllValues.cend(); ++i) { double scale = m_ScaleValues[counter]; for (auto j = (*i).cbegin(); j != (*i).cend(); ++j) { double val = (*j) * scale; newValue = max(newValue, val); } ++counter; } // Scale the value up to nearest power of 2 if (newValue > DBL_MAX / 2.0) { maxValue = DBL_MAX; } else { maxValue = 2.0; while (maxValue < newValue) { maxValue *= 2.0; } } } else { for (auto i = m_Measures.cbegin(); i != m_Measures.cend(); ++i) { double val = (*i)->GetMaxValue(); maxValue = max(maxValue, val); } if (maxValue == 0.0) { maxValue = 1.0; } } Gdiplus::Rect meterRect = GetMeterRectPadding(); // Draw all the lines const REAL H = meterRect.Height - 1.0f; counter = 0; auto pointsBuffer = m_Points.cbegin(); for (auto i = m_AllValues.cbegin(); i != m_AllValues.cend(); ++i) { // Draw a line REAL Y, oldY; const double scale = m_ScaleValues[counter] * H / maxValue; int pos = m_CurrentPos; auto calcY = [&](REAL& _y, REAL stepSize, int currPos) //TODO: move this lambda elsewhere { _y = 0; switch (m_CurveFitMethod) { //first value case 0: _y = (REAL)((*i)[currPos]); break; //maximum value case 1: for (int ind = 0; ind < stepSize; ind++) _y = max(_y, (REAL)((*i)[(currPos + ind) % m_DataWidth])); break; //arithmetic mean case 2: for (int ind = 0; ind < stepSize; ind++) _y += (REAL)((*i)[(currPos + ind) % m_DataWidth]); _y /= stepSize; break; default: _y = (REAL)((*i)[currPos]); } _y *= scale; _y = min(_y, H); _y = max(_y, 0.0f); _y = meterRect.Y + (H - _y); }; // Cache all lines GraphicsPath path; int segmentInd = 0, step, divider; //compute y values step = m_SegmentDividers[m_SegmentDividers.size() - 1]; divider = m_Segments.size() > 0 ? m_W - m_Segments[m_Segments.size() - 1] : m_W; for (int j = 0; j < m_W; ++j) { calcY(Y, step, pos - pos % step); (*pointsBuffer)[j] = Y; if (segmentInd < m_Segments.size() && j >= divider) { segmentInd++; step = m_SegmentDividers[m_SegmentDividers.size() - segmentInd - 1]; divider = segmentInd != m_Segments.size() ? m_W - m_Segments[m_Segments.size() - segmentInd - 1] : m_W; } pos += step; pos %= m_DataWidth; } //draw y values segmentInd = 0; divider = m_Segments.size() > 0 ? m_W - m_Segments[m_Segments.size() - segmentInd - 1] : m_W; if (!m_GraphStartLeft) { for (int j = 1; j < m_W; ++j) { if (segmentInd < m_Segments.size() && j >= divider) { segmentInd++; path.SetMarker(); path.StartFigure(); divider = segmentInd != m_Segments.size() ? m_W - m_Segments[m_Segments.size() - segmentInd - 1] : m_W; } path.AddLine((REAL)(meterRect.X + j - 1), (*pointsBuffer)[j - 1], (REAL)(meterRect.X + j), (*pointsBuffer)[j]); } } else { for (int j = 1; j < m_W; ++j) { if (segmentInd < m_Segments.size() && j >= divider) { segmentInd++; path.SetMarker(); path.StartFigure(); divider = segmentInd != m_Segments.size() ? m_W - m_Segments[m_Segments.size() - segmentInd - 1] : m_W; } path.AddLine((REAL)(meterRect.X + meterRect.Width - j), (*pointsBuffer)[j - 1], (REAL)(meterRect.X + meterRect.Width - j - 1), (*pointsBuffer)[j]); } } // Draw cached lines GraphicsPathIterator pathIter(&path); GraphicsPath subPath; for (auto color = m_Colors[counter].rbegin(); color != m_Colors[counter].rend(); ++color) { pathIter.NextMarker(&subPath); Pen pen(*color, (REAL)m_LineWidth); pen.SetLineJoin(LineJoinRound); graphics.DrawPath(&pen, &subPath); } ++counter; ++pointsBuffer; } canvas.EndGdiplusContext(); return true; }