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;
46 std::vector<wxPoint2DDouble> pts;
48 pts.push_back(m_rect.GetLeftTop() + wxPoint2DDouble(m_borderSize, m_borderSize));
49 pts.push_back(m_rect.GetRightTop() + wxPoint2DDouble(-m_borderSize - 10, m_borderSize));
50 pts.push_back(m_position + wxPoint2DDouble(m_width / 2 - m_borderSize, 0));
51 pts.push_back(m_rect.GetRightBottom() + wxPoint2DDouble(-m_borderSize - 10, -m_borderSize));
52 pts.push_back(m_rect.GetLeftBottom() + wxPoint2DDouble(m_borderSize, -m_borderSize));
54 else if (m_angle == 90.0) {
55 pts.push_back(m_rect.GetLeftTop() + wxPoint2DDouble(m_borderSize, m_borderSize));
56 pts.push_back(m_rect.GetRightTop() + wxPoint2DDouble(-m_borderSize, m_borderSize));
57 pts.push_back(m_rect.GetRightBottom() + wxPoint2DDouble(-m_borderSize, -m_borderSize - 10));
58 pts.push_back(m_position + wxPoint2DDouble(0, m_height / 2 - m_borderSize));
59 pts.push_back(m_rect.GetLeftBottom() + wxPoint2DDouble(m_borderSize, -m_borderSize - 10));
61 else if (m_angle == 180.0) {
62 pts.push_back(m_rect.GetLeftTop() + wxPoint2DDouble(m_borderSize + 10, m_borderSize));
63 pts.push_back(m_rect.GetRightTop() + wxPoint2DDouble(-m_borderSize, m_borderSize));
64 pts.push_back(m_rect.GetRightBottom() + wxPoint2DDouble(-m_borderSize, -m_borderSize));
65 pts.push_back(m_rect.GetLeftBottom() + wxPoint2DDouble(m_borderSize + 10, -m_borderSize));
66 pts.push_back(m_position + wxPoint2DDouble(-m_width / 2 + m_borderSize, 0));
68 else if (m_angle == 270.0) {
69 pts.push_back(m_position + wxPoint2DDouble(0, -m_height / 2 + m_borderSize));
70 pts.push_back(m_rect.GetRightTop() + wxPoint2DDouble(-m_borderSize, m_borderSize + 10));
71 pts.push_back(m_rect.GetRightBottom() + wxPoint2DDouble(-m_borderSize, -m_borderSize));
72 pts.push_back(m_rect.GetLeftBottom() + wxPoint2DDouble(m_borderSize, -m_borderSize));
73 pts.push_back(m_rect.GetLeftTop() + wxPoint2DDouble(m_borderSize, m_borderSize + 10));
75 pts.emplace_back(pts[0]);
78 gc->SetPen(*wxTRANSPARENT_PEN);
79 gc->SetBrush(wxBrush(guiColour->selection));
80 double borderSize = (m_borderSize * 2.0 + 1.0) / scale;
81 std::vector<wxPoint2DDouble> selPts = pts;
83 selPts[0] += wxPoint2DDouble(-borderSize / 2, -borderSize / 2);
84 selPts[1] += wxPoint2DDouble(borderSize / 2, -borderSize / 2);
85 selPts[2] += wxPoint2DDouble(1.5 * borderSize / 2, 0);
86 selPts[3] += wxPoint2DDouble(borderSize / 2, borderSize / 2);
87 selPts[4] += wxPoint2DDouble(-borderSize / 2, borderSize / 2);
89 else if (m_angle == 90.0) {
90 selPts[0] += wxPoint2DDouble(-borderSize / 2, -borderSize / 2);
91 selPts[1] += wxPoint2DDouble(borderSize / 2, -borderSize / 2);
92 selPts[2] += wxPoint2DDouble(borderSize / 2, borderSize / 2);
93 selPts[3] += wxPoint2DDouble(0, 1.5 * borderSize / 2);
94 selPts[4] += wxPoint2DDouble(-borderSize / 2, borderSize / 2);
96 else if (m_angle == 180.0) {
97 selPts[0] += wxPoint2DDouble(-borderSize / 2, -borderSize / 2);
98 selPts[1] += wxPoint2DDouble(borderSize / 2, -borderSize / 2);
99 selPts[2] += wxPoint2DDouble(borderSize / 2, borderSize / 2);
100 selPts[3] += wxPoint2DDouble(-borderSize / 2, borderSize / 2);
101 selPts[4] += wxPoint2DDouble(-1.5 * borderSize / 2, 0);
103 else if (m_angle == 270.0) {
104 selPts[0] += wxPoint2DDouble(0, -1.5 * borderSize / 2);
105 selPts[1] += wxPoint2DDouble(borderSize / 2, -borderSize / 2);
106 selPts[2] += wxPoint2DDouble(borderSize / 2, borderSize / 2);
107 selPts[3] += wxPoint2DDouble(-borderSize / 2, borderSize / 2);
108 selPts[4] += wxPoint2DDouble(-borderSize / 2, -borderSize / 2);
110 gc->DrawLines(5, &selPts[0]);
112 gc->SetPen(wxPen(guiColour->enabled, 1));
113 gc->SetBrush(guiColour->background);
114 gc->DrawLines(6, &pts[0]);
117 if (m_angle == 0.0) {
118 m_gcText->
Draw(m_position + wxPoint2DDouble(-5.0 - m_gcText->GetWidth() / 2, -m_gcText->GetHeight() / 2), gc, 0, guiColour->text);
120 else if (m_angle == 90.0) {
121 m_gcText->
Draw(m_position + wxPoint2DDouble(-m_gcText->GetWidth() / 2, -5.0 - m_gcText->GetHeight() / 2), gc, 0, guiColour->text);
123 else if (m_angle == 180.0) {
124 m_gcText->
Draw(m_position + wxPoint2DDouble(5.0 - m_gcText->GetWidth() / 2, -m_gcText->GetHeight() / 2), gc, 0, guiColour->text);
126 else if (m_angle == 270.0) {
127 m_gcText->
Draw(m_position + wxPoint2DDouble(-m_gcText->GetWidth() / 2, 5.0 - m_gcText->GetHeight() / 2), gc, 0, guiColour->text);
130 gc->SetPen(*wxTRANSPARENT_PEN);
131 gc->SetBrush(guiColour->enabled);
138 if (form.ShowModal() == wxID_OK) {
150 if (m_angle >= 360.0)
152 else if (m_angle < 0)
157 for (
auto it = m_nodeList.begin(), itEnd = m_nodeList.end(); it != itEnd; ++it) {
159 node->Rotate(clockwise);
163void IOControl::SetFont(wxFont& font)
165 m_gcText->SetFont(font);
169wxString IOControl::GenerateText()
171 wxString omega = wxString::FromUTF8(
"\xCF\x89");
172 wxString subZero = wxString::FromUTF8(
"\xE2\x82\x92");
173 wxString capDelta = wxString::FromUTF8(
"\xCE\x94");
176 case IN_TERMINAL_VOLTAGE: {
177 m_ioNodeType = Node::NodeType::NODE_OUT;
181 m_ioNodeType = Node::NodeType::NODE_OUT;
184 case IN_ACTIVE_POWER: {
185 m_ioNodeType = Node::NodeType::NODE_OUT;
188 case IN_REACTIVE_POWER: {
189 m_ioNodeType = Node::NodeType::NODE_OUT;
192 case OUT_FIELD_VOLTAGE: {
193 m_ioNodeType = Node::NodeType::NODE_IN;
196 case OUT_MEC_POWER: {
197 m_ioNodeType = Node::NodeType::NODE_IN;
200 case IN_INITIAL_TERMINAL_VOLTAGE: {
201 m_ioNodeType = Node::NodeType::NODE_OUT;
202 return _(
"Vt") + subZero;
204 case IN_INITIAL_MEC_POWER: {
205 m_ioNodeType = Node::NodeType::NODE_OUT;
206 return _(
"Pm") + subZero;
208 case IN_INITIAL_VELOCITY: {
209 m_ioNodeType = Node::NodeType::NODE_OUT;
210 return omega + subZero;
212 case IN_DELTA_VELOCITY: {
213 m_ioNodeType = Node::NodeType::NODE_OUT;
214 return capDelta + omega;
216 case IN_DELTA_ACTIVE_POWER: {
217 m_ioNodeType = Node::NodeType::NODE_OUT;
218 return capDelta + _(
"P");
221 m_ioNodeType = Node::NodeType::NODE_OUT;
228void IOControl::SetValue(IOFlags value)
231 wxString text = GenerateText();
236 m_gcText =
new GCText(text);
238 m_width = m_gcText->GetWidth() + 10 + 2 * m_borderSize;
239 m_height = m_gcText->GetHeight() + 10 + 2 * m_borderSize;
246void IOControl::UpdatePoints()
248 if (m_nodeList.size() != 0) {
249 Node* node = m_nodeList[0];
250 if (node->GetNodeType() != m_ioNodeType) {
255 node->SetNodeType(m_ioNodeType);
256 if (m_angle == 0.0) {
257 if (m_ioNodeType == Node::NodeType::NODE_IN)
258 node->SetPosition(m_position + wxPoint2DDouble(-m_width / 2, 0));
260 node->SetPosition(m_position + wxPoint2DDouble(m_width / 2 - 2, 0));
262 else if (m_angle == 90.0) {
263 if (m_ioNodeType == Node::NodeType::NODE_IN)
264 node->SetPosition(m_position + wxPoint2DDouble(0, -m_height / 2));
266 node->SetPosition(m_position + wxPoint2DDouble(0, m_height / 2 - 2));
268 else if (m_angle == 180.0) {
269 if (m_ioNodeType == Node::NodeType::NODE_IN)
270 node->SetPosition(m_position + wxPoint2DDouble(m_width / 2, 0));
272 node->SetPosition(m_position + wxPoint2DDouble(2 - m_width / 2, 0));
274 else if (m_angle == 270.0) {
275 if (m_ioNodeType == Node::NodeType::NODE_IN)
276 node->SetPosition(m_position + wxPoint2DDouble(0, m_height / 2));
278 node->SetPosition(m_position + wxPoint2DDouble(0, 2 - m_height / 2));
286 copy->m_gcText = m_gcText ? m_gcText->
GetCopy() :
nullptr;
297rapidxml::xml_node<>* IOControl::SaveElement(rapidxml::xml_document<>& doc, rapidxml::xml_node<>* elementListNode)
299 auto elementNode = XMLParser::AppendNode(doc, elementListNode,
"IO");
300 XMLParser::SetNodeAttribute(doc, elementNode,
"ID", m_elementID);
302 SaveCADProperties(doc, elementNode);
303 SaveControlNodes(doc, elementNode);
306 auto name = XMLParser::AppendNode(doc, elementNode,
"Name");
307 XMLParser::SetNodeValue(doc, name, m_name);
308 auto value = XMLParser::AppendNode(doc, elementNode,
"Value");
309 XMLParser::SetNodeValue(doc, value, m_value);
310 auto ioFlags = XMLParser::AppendNode(doc, elementNode,
"IOFlags");
311 XMLParser::SetNodeValue(doc, ioFlags, m_ioFlags);
316bool IOControl::OpenElement(rapidxml::xml_node<>* elementNode)
318 if (!OpenCADProperties(elementNode))
return false;
319 if (!OpenControlNodes(elementNode))
return false;
322 IOControl::IOFlags value =
static_cast<IOControl::IOFlags
>(XMLParser::GetNodeValueInt(elementNode,
"Value"));
324 auto name = elementNode->first_node(
"Name");
325 if (name) m_name = name->value();
330bool IOControl::Initialize()
334 if(m_value == IOControl::IN_TEST) {
335 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 bool ShowForm(wxWindow *parent, Element *element, wxWindow *workspace=nullptr)
Show element data form.
virtual Element * GetCopy()
Get a the element copy.
virtual void DrawDC(GUIColour *guiColour, 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...