19#include "../../forms/IOControlForm.h"
20#include <wx/dcscreen.h>
26 Node* node =
new Node(m_position, Node::NodeType::NODE_IN, m_borderSize);
27 m_nodeList.push_back(node);
29 if (ioFlags & IN_TERMINAL_VOLTAGE)
30 SetValue(IN_TERMINAL_VOLTAGE);
31 else if (ioFlags & IN_VELOCITY)
32 SetValue(IN_VELOCITY);
33 node->StartMove(m_position);
36IOControl::~IOControl()
39 if (m_gcText)
delete m_gcText;
40 for (
auto& node : m_nodeList) if (node) delete node;
128 std::vector<wxPoint2DDouble> pts;
129 if (m_angle == 0.0) {
130 pts.push_back(m_rect.GetLeftTop() + wxPoint2DDouble(m_borderSize, m_borderSize));
131 pts.push_back(m_rect.GetRightTop() + wxPoint2DDouble(-m_borderSize - 10, m_borderSize));
132 pts.push_back(m_position + wxPoint2DDouble(m_width / 2 - m_borderSize, 0));
133 pts.push_back(m_rect.GetRightBottom() + wxPoint2DDouble(-m_borderSize - 10, -m_borderSize));
134 pts.push_back(m_rect.GetLeftBottom() + wxPoint2DDouble(m_borderSize, -m_borderSize));
136 else if (m_angle == 90.0) {
137 pts.push_back(m_rect.GetLeftTop() + wxPoint2DDouble(m_borderSize, m_borderSize));
138 pts.push_back(m_rect.GetRightTop() + wxPoint2DDouble(-m_borderSize, m_borderSize));
139 pts.push_back(m_rect.GetRightBottom() + wxPoint2DDouble(-m_borderSize, -m_borderSize - 10));
140 pts.push_back(m_position + wxPoint2DDouble(0, m_height / 2 - m_borderSize));
141 pts.push_back(m_rect.GetLeftBottom() + wxPoint2DDouble(m_borderSize, -m_borderSize - 10));
143 else if (m_angle == 180.0) {
144 pts.push_back(m_rect.GetLeftTop() + wxPoint2DDouble(m_borderSize + 10, m_borderSize));
145 pts.push_back(m_rect.GetRightTop() + wxPoint2DDouble(-m_borderSize, m_borderSize));
146 pts.push_back(m_rect.GetRightBottom() + wxPoint2DDouble(-m_borderSize, -m_borderSize));
147 pts.push_back(m_rect.GetLeftBottom() + wxPoint2DDouble(m_borderSize + 10, -m_borderSize));
148 pts.push_back(m_position + wxPoint2DDouble(-m_width / 2 + m_borderSize, 0));
150 else if (m_angle == 270.0) {
151 pts.push_back(m_position + wxPoint2DDouble(0, -m_height / 2 + m_borderSize));
152 pts.push_back(m_rect.GetRightTop() + wxPoint2DDouble(-m_borderSize, m_borderSize + 10));
153 pts.push_back(m_rect.GetRightBottom() + wxPoint2DDouble(-m_borderSize, -m_borderSize));
154 pts.push_back(m_rect.GetLeftBottom() + wxPoint2DDouble(m_borderSize, -m_borderSize));
155 pts.push_back(m_rect.GetLeftTop() + wxPoint2DDouble(m_borderSize, m_borderSize + 10));
157 pts.emplace_back(pts[0]);
160 gc->SetPen(*wxTRANSPARENT_PEN);
161 gc->SetBrush(wxBrush(m_selectionColour));
162 double borderSize = (m_borderSize * 2.0 + 1.0) / scale;
163 std::vector<wxPoint2DDouble> selPts = pts;
164 if (m_angle == 0.0) {
165 selPts[0] += wxPoint2DDouble(-borderSize / 2, -borderSize / 2);
166 selPts[1] += wxPoint2DDouble(borderSize / 2, -borderSize / 2);
167 selPts[2] += wxPoint2DDouble(1.5 * borderSize / 2, 0);
168 selPts[3] += wxPoint2DDouble(borderSize / 2, borderSize / 2);
169 selPts[4] += wxPoint2DDouble(-borderSize / 2, borderSize / 2);
171 else if (m_angle == 90.0) {
172 selPts[0] += wxPoint2DDouble(-borderSize / 2, -borderSize / 2);
173 selPts[1] += wxPoint2DDouble(borderSize / 2, -borderSize / 2);
174 selPts[2] += wxPoint2DDouble(borderSize / 2, borderSize / 2);
175 selPts[3] += wxPoint2DDouble(0, 1.5 * borderSize / 2);
176 selPts[4] += wxPoint2DDouble(-borderSize / 2, borderSize / 2);
178 else if (m_angle == 180.0) {
179 selPts[0] += wxPoint2DDouble(-borderSize / 2, -borderSize / 2);
180 selPts[1] += wxPoint2DDouble(borderSize / 2, -borderSize / 2);
181 selPts[2] += wxPoint2DDouble(borderSize / 2, borderSize / 2);
182 selPts[3] += wxPoint2DDouble(-borderSize / 2, borderSize / 2);
183 selPts[4] += wxPoint2DDouble(-1.5 * borderSize / 2, 0);
185 else if (m_angle == 270.0) {
186 selPts[0] += wxPoint2DDouble(0, -1.5 * borderSize / 2);
187 selPts[1] += wxPoint2DDouble(borderSize / 2, -borderSize / 2);
188 selPts[2] += wxPoint2DDouble(borderSize / 2, borderSize / 2);
189 selPts[3] += wxPoint2DDouble(-borderSize / 2, borderSize / 2);
190 selPts[4] += wxPoint2DDouble(-borderSize / 2, -borderSize / 2);
192 gc->DrawLines(5, &selPts[0]);
194 gc->SetPen(wxPen(wxColour(0, 0, 0, 255), 1));
195 gc->SetBrush(wxBrush(wxColour(255, 255, 255, 255)));
196 gc->DrawLines(6, &pts[0]);
199 if (m_angle == 0.0) {
200 m_gcText->
Draw(m_position + wxPoint2DDouble(-5.0 - m_gcText->GetWidth() / 2, -m_gcText->GetHeight() / 2), gc);
202 else if (m_angle == 90.0) {
203 m_gcText->
Draw(m_position + wxPoint2DDouble(-m_gcText->GetWidth() / 2, -5.0 - m_gcText->GetHeight() / 2), gc);
205 else if (m_angle == 180.0) {
206 m_gcText->
Draw(m_position + wxPoint2DDouble(5.0 - m_gcText->GetWidth() / 2, -m_gcText->GetHeight() / 2), gc);
208 else if (m_angle == 270.0) {
209 m_gcText->
Draw(m_position + wxPoint2DDouble(-m_gcText->GetWidth() / 2, 5.0 - m_gcText->GetHeight() / 2), gc);
212 gc->SetPen(*wxTRANSPARENT_PEN);
213 gc->SetBrush(wxBrush(wxColour(0, 0, 0, 255)));
220 if (form.ShowModal() == wxID_OK) {
232 if (m_angle >= 360.0)
234 else if (m_angle < 0)
239 for (
auto it = m_nodeList.begin(), itEnd = m_nodeList.end(); it != itEnd; ++it) {
241 node->Rotate(clockwise);
245wxString IOControl::GenerateText()
247 wxString omega = wxString::FromUTF8(
"\xCF\x89");
248 wxString subZero = wxString::FromUTF8(
"\xE2\x82\x92");
249 wxString capDelta = wxString::FromUTF8(
"\xCE\x94");
252 case IN_TERMINAL_VOLTAGE: {
253 m_ioNodeType = Node::NodeType::NODE_OUT;
257 m_ioNodeType = Node::NodeType::NODE_OUT;
260 case IN_ACTIVE_POWER: {
261 m_ioNodeType = Node::NodeType::NODE_OUT;
264 case IN_REACTIVE_POWER: {
265 m_ioNodeType = Node::NodeType::NODE_OUT;
268 case OUT_FIELD_VOLTAGE: {
269 m_ioNodeType = Node::NodeType::NODE_IN;
272 case OUT_MEC_POWER: {
273 m_ioNodeType = Node::NodeType::NODE_IN;
276 case IN_INITIAL_TERMINAL_VOLTAGE: {
277 m_ioNodeType = Node::NodeType::NODE_OUT;
278 return _(
"Vt") + subZero;
280 case IN_INITIAL_MEC_POWER: {
281 m_ioNodeType = Node::NodeType::NODE_OUT;
282 return _(
"Pm") + subZero;
284 case IN_INITIAL_VELOCITY: {
285 m_ioNodeType = Node::NodeType::NODE_OUT;
286 return omega + subZero;
288 case IN_DELTA_VELOCITY: {
289 m_ioNodeType = Node::NodeType::NODE_OUT;
290 return capDelta + omega;
292 case IN_DELTA_ACTIVE_POWER: {
293 m_ioNodeType = Node::NodeType::NODE_OUT;
294 return capDelta + _(
"P");
300void IOControl::SetValue(IOFlags value)
303 wxString text = GenerateText();
308 m_gcText =
new GCText(text);
310 m_width = m_gcText->GetWidth() + 10 + 2 * m_borderSize;
311 m_height = m_gcText->GetHeight() + 10 + 2 * m_borderSize;
318void IOControl::UpdatePoints()
320 if (m_nodeList.size() != 0) {
321 Node* node = m_nodeList[0];
322 if (node->GetNodeType() != m_ioNodeType) {
327 node->SetNodeType(m_ioNodeType);
328 if (m_angle == 0.0) {
329 if (m_ioNodeType == Node::NodeType::NODE_IN)
330 node->SetPosition(m_position + wxPoint2DDouble(-m_width / 2, 0));
332 node->SetPosition(m_position + wxPoint2DDouble(m_width / 2 - 2, 0));
334 else if (m_angle == 90.0) {
335 if (m_ioNodeType == Node::NodeType::NODE_IN)
336 node->SetPosition(m_position + wxPoint2DDouble(0, -m_height / 2));
338 node->SetPosition(m_position + wxPoint2DDouble(0, m_height / 2 - 2));
340 else if (m_angle == 180.0) {
341 if (m_ioNodeType == Node::NodeType::NODE_IN)
342 node->SetPosition(m_position + wxPoint2DDouble(m_width / 2, 0));
344 node->SetPosition(m_position + wxPoint2DDouble(2 - m_width / 2, 0));
346 else if (m_angle == 270.0) {
347 if (m_ioNodeType == Node::NodeType::NODE_IN)
348 node->SetPosition(m_position + wxPoint2DDouble(0, m_height / 2));
350 node->SetPosition(m_position + wxPoint2DDouble(0, 2 - m_height / 2));
359 copy->m_gcText = m_gcText->
GetCopy();
370rapidxml::xml_node<>* IOControl::SaveElement(rapidxml::xml_document<>& doc, rapidxml::xml_node<>* elementListNode)
372 auto elementNode = XMLParser::AppendNode(doc, elementListNode,
"IO");
373 XMLParser::SetNodeAttribute(doc, elementNode,
"ID", m_elementID);
375 SaveCADProperties(doc, elementNode);
376 SaveControlNodes(doc, elementNode);
379 auto name = XMLParser::AppendNode(doc, elementNode,
"Name");
380 XMLParser::SetNodeValue(doc, name, m_name);
381 auto value = XMLParser::AppendNode(doc, elementNode,
"Value");
382 XMLParser::SetNodeValue(doc, value, m_value);
383 auto ioFlags = XMLParser::AppendNode(doc, elementNode,
"IOFlags");
384 XMLParser::SetNodeValue(doc, ioFlags, m_ioFlags);
389bool IOControl::OpenElement(rapidxml::xml_node<>* elementNode)
391 if (!OpenCADProperties(elementNode))
return false;
392 if (!OpenControlNodes(elementNode))
return false;
395 IOControl::IOFlags value =
static_cast<IOControl::IOFlags
>(XMLParser::GetNodeValueInt(elementNode,
"Value"));
397 auto name = elementNode->first_node(
"Name");
398 if (name) m_name = name->value();
403bool IOControl::Initialize()
407 if(m_value == IOControl::IN_TEST) {
408 m_output = m_testValue;
Base class of all elements of the program. This class is responsible for manage graphical and his dat...
void SetPosition(const wxPoint2DDouble position)
Set the element position and update the rectangle.
Class to draw text on Graphics Context using wxWidgets.
virtual GCText * GetCopy()
Get a deep text copy.
virtual void Draw(wxPoint2DDouble position, wxGraphicsContext *gc, double angle=0.0, wxColour colour= *wxBLACK) const
Draw the text in wxGraphicsContext.
virtual void SetText(wxString text)
Set correctly a new text string.
Provides the communication with the power element.
virtual bool UpdateText()
Update the OpenGL text in the element (if present).
virtual void Rotate(bool clockwise=true)
Rotate the element.
virtual Element * GetCopy()
Get a the element copy.
virtual bool ShowForm(wxWindow *parent, Element *element)
Show element data form.
virtual void DrawDC(wxPoint2DDouble translation, double scale, wxGraphicsContext *gc) const
Draw the element using GDI+.
Node of a control element. This class manages the user interaction with the connection and control el...