229{
230 dc.SetUserScale(1.0, 1.0);
231 dc.SetDeviceOrigin(0, 0);
232
233 dc.SetPen(*wxBLACK_PEN);
234 if (wxSystemSettings::GetAppearance().IsDark())
235 {
236 dc.SetPen(wxPen(wxColour(205, 210, 215)));
237 }
238 int xStart = 30;
239 int yStart = m_height - 45;
240 int width = 300;
241 int height = 30;
242
243 struct Stop {
244 double pos;
245 wxColour color;
246 };
247
248 std::vector<Stop> stops = {
249 {0.00, VoltToColour(-1.0, 210)},
250 {0.25, VoltToColour(-0.5, 210)},
251 {0.50, VoltToColour(0.0, 210)},
252 {0.75, VoltToColour(0.5, 210)},
253 {1.00, VoltToColour(1.0, 210)}
254 };
255
256 auto ColorAt = [&](double t) -> wxColour
257 {
258 for (size_t i = 0; i < stops.size() - 1; ++i)
259 {
260 if (t >= stops[i].pos && t <= stops[i + 1].pos)
261 {
262 double localT =
263 (t - stops[i].pos) /
264 (stops[i + 1].pos - stops[i].pos);
265
266 const wxColour& c1 = stops[i].color;
267 const wxColour& c2 = stops[i + 1].color;
268
269 return wxColour(
270 c1.Red() + localT * (c2.Red() - c1.Red()),
271 c1.Green() + localT * (c2.Green() - c1.Green()),
272 c1.Blue() + localT * (c2.Blue() - c1.Blue())
273 );
274 }
275 }
276 return stops.back().color;
277 };
278
279 for (int x = 0; x < width; ++x)
280 {
281 double t = (double)x / width;
282
283 wxColour c = ColorAt(t);
284
285 dc.SetPen(wxPen(c));
286 dc.DrawLine(xStart + x,
287 yStart,
288 xStart + x,
289 yStart + height);
290 }
291
292 dc.SetPen(*wxBLACK_PEN);
293 if (wxSystemSettings::GetAppearance().IsDark())
294 {
295 dc.SetPen(wxPen(wxColour(205, 210, 215)));
296 }
297 dc.SetBrush(*wxTRANSPARENT_BRUSH);
298 dc.DrawRectangle(xStart, yStart, width, height);
299 wxPoint2DDouble lines[10];
300 lines[0] = wxPoint2DDouble(30, m_height - 50);
301 lines[1] = wxPoint2DDouble(30, m_height - 40);
302 lines[2] = wxPoint2DDouble(105, m_height - 50);
303 lines[3] = wxPoint2DDouble(105, m_height - 40);
304 lines[4] = wxPoint2DDouble(180, m_height - 50);
305 lines[5] = wxPoint2DDouble(180, m_height - 40);
306 lines[6] = wxPoint2DDouble(255, m_height - 50);
307 lines[7] = wxPoint2DDouble(255, m_height - 40);
308 lines[8] = wxPoint2DDouble(330, m_height - 50);
309 lines[9] = wxPoint2DDouble(330, m_height - 40);
310
311 for (size_t i = 0; i < 10; i += 2) {
312 dc.DrawLine(lines[i].m_x, lines[i].m_y, lines[i + 1].m_x, lines[i + 1].m_y);
313 }
314
315 dc.SetFont(wxFont(10, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL));
316 dc.DrawText(_("Voltage (p.u.)"), 30, m_height - 15);
317 wxString voltageText = "";
318 int textWidth, textHeight;
319 voltageText = wxString::Format("%.3f", m_limits[0]);
320 dc.GetTextExtent(voltageText, &textWidth, &textHeight);
321 dc.DrawText(voltageText, 330 - textWidth / 2, m_height - 65);
322 voltageText = wxString::Format("%.3f", m_limits[0] * 0.75 + m_limits[1] * 0.25);
323 dc.GetTextExtent(voltageText, &textWidth, &textHeight);
324 dc.DrawText(voltageText, 255 - textWidth / 2, m_height - 65);
325 voltageText = wxString::Format("%.3f", m_limits[0] * 0.5 + m_limits[1] * 0.5);
326 dc.GetTextExtent(voltageText, &textWidth, &textHeight);
327 dc.DrawText(voltageText, 180 - textWidth / 2, m_height - 65);
328 voltageText = wxString::Format("%.3f", m_limits[0] * 0.25 + m_limits[1] * 0.75);
329 dc.GetTextExtent(voltageText, &textWidth, &textHeight);
330 dc.DrawText(voltageText, 105 - textWidth / 2, m_height - 65);
331 voltageText = wxString::Format("%.3f", m_limits[1]);
332 dc.GetTextExtent(voltageText, &textWidth, &textHeight);
333 dc.DrawText(voltageText, 30 - textWidth / 2, m_height - 65);
334}