341{
342 dc.SetUserScale(1.0, 1.0);
343 dc.SetDeviceOrigin(0, 0);
344
345 dc.SetPen(*wxBLACK_PEN);
346 int xStart = 30;
347 int yStart = m_height - 45;
348 int width = 300;
349 int height = 30;
350
351 struct Stop {
352 double pos;
353 wxColour color;
354 };
355
356 std::vector<Stop> stops = {
357 {0.00, VoltToColour(-1.0, 210)},
358 {0.25, VoltToColour(-0.5, 210)},
359 {0.50, VoltToColour(0.0, 210)},
360 {0.75, VoltToColour(0.5, 210)},
361 {1.00, VoltToColour(1.0, 210)}
362 };
363
364 auto ColorAt = [&](double t) -> wxColour
365 {
366 for (size_t i = 0; i < stops.size() - 1; ++i)
367 {
368 if (t >= stops[i].pos && t <= stops[i + 1].pos)
369 {
370 double localT =
371 (t - stops[i].pos) /
372 (stops[i + 1].pos - stops[i].pos);
373
374 const wxColour& c1 = stops[i].color;
375 const wxColour& c2 = stops[i + 1].color;
376
377 return wxColour(
378 c1.Red() + localT * (c2.Red() - c1.Red()),
379 c1.Green() + localT * (c2.Green() - c1.Green()),
380 c1.Blue() + localT * (c2.Blue() - c1.Blue())
381 );
382 }
383 }
384 return stops.back().color;
385 };
386
387 for (int x = 0; x < width; ++x)
388 {
389 double t = (double)x / width;
390
391 wxColour c = ColorAt(t);
392
393 dc.SetPen(wxPen(c));
394 dc.DrawLine(xStart + x,
395 yStart,
396 xStart + x,
397 yStart + height);
398 }
399
400 dc.SetPen(*wxBLACK_PEN);
401 dc.SetBrush(*wxTRANSPARENT_BRUSH);
402 dc.DrawRectangle(xStart, yStart, width, height);
403 wxPoint2DDouble lines[10];
404 lines[0] = wxPoint2DDouble(30, m_height - 50);
405 lines[1] = wxPoint2DDouble(30, m_height - 40);
406 lines[2] = wxPoint2DDouble(105, m_height - 50);
407 lines[3] = wxPoint2DDouble(105, m_height - 40);
408 lines[4] = wxPoint2DDouble(180, m_height - 50);
409 lines[5] = wxPoint2DDouble(180, m_height - 40);
410 lines[6] = wxPoint2DDouble(255, m_height - 50);
411 lines[7] = wxPoint2DDouble(255, m_height - 40);
412 lines[8] = wxPoint2DDouble(330, m_height - 50);
413 lines[9] = wxPoint2DDouble(330, m_height - 40);
414
415 for (size_t i = 0; i < 10; i += 2) {
416 dc.DrawLine(lines[i].m_x, lines[i].m_y, lines[i + 1].m_x, lines[i + 1].m_y);
417 }
418
419 dc.SetFont(wxFont(10, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL));
420 dc.DrawText(_("Voltage (p.u.)"), 30, m_height - 15);
421 wxString voltageText = "";
422 int textWidth, textHeight;
423 voltageText = wxString::Format("%.3f", m_limits[0]);
424 dc.GetTextExtent(voltageText, &textWidth, &textHeight);
425 dc.DrawText(voltageText, 330 - textWidth / 2, m_height - 65);
426 voltageText = wxString::Format("%.3f", m_limits[0] * 0.75 + m_limits[1] * 0.25);
427 dc.GetTextExtent(voltageText, &textWidth, &textHeight);
428 dc.DrawText(voltageText, 255 - textWidth / 2, m_height - 65);
429 voltageText = wxString::Format("%.3f", m_limits[0] * 0.5 + m_limits[1] * 0.5);
430 dc.GetTextExtent(voltageText, &textWidth, &textHeight);
431 dc.DrawText(voltageText, 180 - textWidth / 2, m_height - 65);
432 voltageText = wxString::Format("%.3f", m_limits[0] * 0.25 + m_limits[1] * 0.75);
433 dc.GetTextExtent(voltageText, &textWidth, &textHeight);
434 dc.DrawText(voltageText, 105 - textWidth / 2, m_height - 65);
435 voltageText = wxString::Format("%.3f", m_limits[1]);
436 dc.GetTextExtent(voltageText, &textWidth, &textHeight);
437 dc.DrawText(voltageText, 30 - textWidth / 2, m_height - 65);
438}