NumeRe v1.1.4
NumeRe: Framework für Numerische Rechnungen
variableviewer.cpp
Go to the documentation of this file.
1/*****************************************************************************
2 NumeRe: Framework fuer Numerische Rechnungen
3 Copyright (C) 2019 Erik Haenel et al.
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17******************************************************************************/
18
19#include "variableviewer.hpp"
20#include "../../kernel/core/ui/language.hpp"
21#include "../../kernel/core/utils/stringtools.hpp"
22#include "../../common/datastructures.h"
23#include "../../common/Options.h"
24#include "../NumeReWindow.h"
25#include <wx/menu.h>
26#include <wx/dialog.h>
27#include <wx/clipbrd.h>
28
29#define DIMCOLUMN 1
30#define CLASSCOLUMN 2
31#define VALUECOLUMN 3
32#define SIZECOLUMN 4
33
34extern Language _guilang;
35using namespace wxcode;
36
37struct VarData : public wxTreeItemData
38{
39 std::string sInternalName;
40
41 VarData(const std::string name) : sInternalName(name) {}
42};
43
44
45
46
47BEGIN_EVENT_TABLE(VariableViewer, wxcode::wxTreeListCtrl)
48 EVT_TREE_ITEM_RIGHT_CLICK(-1, VariableViewer::OnRightClick)
49 EVT_TREE_ITEM_ACTIVATED(-1, VariableViewer::OnDoubleClick)
52
53
54
63VariableViewer::VariableViewer(wxWindow* parent, NumeReWindow* mainWin, int fieldsize, bool debugMode) : wxTreeListCtrl(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTR_TWIST_BUTTONS | wxTR_FULL_ROW_HIGHLIGHT | wxTR_ROW_LINES | wxTR_NO_LINES | wxTR_HIDE_ROOT)
64{
65 selectedID = wxTreeItemId();
66
67 nDataFieldSize = fieldsize;
68 mainWindow = mainWin;
69
70 // Create the default columns
71 AddColumn(_guilang.get("GUI_VARVIEWER_NAME"), 150);
72 AddColumn(_guilang.get("GUI_VARVIEWER_DIM"), 80, wxALIGN_RIGHT);
73 AddColumn(_guilang.get("GUI_VARVIEWER_CLASS"), 55);
74 AddColumn(_guilang.get("GUI_VARVIEWER_VALUE"), fieldsize - (!debugMode)*50);
75
76 if (!debugMode)
77 AddColumn(_guilang.get("GUI_VARVIEWER_SIZE"), 120);
78
79 // Create root node
80 AddRoot("ROOT");
81
82 // Create variable class nodes
83 numRoot = AppendItem(GetRootItem(), _guilang.get("GUI_VARVIEWER_VARS"));
84 stringRoot = AppendItem(GetRootItem(), _guilang.get("GUI_VARVIEWER_STRINGS"));
85 clusterRoot = AppendItem(GetRootItem(), _guilang.get("GUI_VARVIEWER_CLUSTERS"));
86 tableRoot = AppendItem(GetRootItem(), _guilang.get("GUI_VARVIEWER_TABLES"));
87 SetItemText(tableRoot, VALUECOLUMN, " {min, ..., max}");
88 SetItemText(clusterRoot, VALUECOLUMN, " {first, ..., last}");
89
90 // Make the variable class nodes bold
91 SetItemBold(numRoot, true);
92 SetItemBold(stringRoot, true);
93 SetItemBold(tableRoot, true);
94 SetItemBold(clusterRoot, true);
95
96 for (size_t i = 0; i < 6; i++)
97 {
98 bExpandedState[i] = true;
99 }
100
101 setDebuggerMode(debugMode);
102}
103
104
114bool VariableViewer::checkPresence(const std::string& sVar)
115{
116 for (size_t i = 0; i < vLastVarSet.size(); i++)
117 {
118 if (vLastVarSet[i] == sVar)
119 return true;
120 }
121
122 return false;
123}
124
125
135bool VariableViewer::checkSpecialVals(const std::string& sVar)
136{
137 if (sVar.substr(0, sVar.find('\t')) == "data()")
138 return true;
139 else if (sVar.substr(0, sVar.find('\t')) == "table()")
140 return true;
141 else if (sVar.substr(0, sVar.find('\t')) == "string()")
142 return true;
143 else if (sVar.substr(0, sVar.find('\t')) == "x")
144 return true;
145 else if (sVar.substr(0, sVar.find('\t')) == "y")
146 return true;
147 else if (sVar.substr(0, sVar.find('\t')) == "z")
148 return true;
149 else if (sVar.substr(0, sVar.find('\t')) == "t")
150 return true;
151 else if (sVar.substr(0, sVar.find('\t')) == "nrows" || sVar.substr(0, sVar.find('\t')) == "nlines")
152 return true;
153 else if (sVar.substr(0, sVar.find('\t')) == "ncols")
154 return true;
155 else if (sVar.substr(0, sVar.find('\t')) == "nlen")
156 return true;
157 else if (sVar.substr(0, sVar.find('\t')) == "ans" || sVar.substr(0, sVar.find('\t')) == "ans{}")
158 return true;
159
160 return false;
161}
162
163
175wxTreeItemId VariableViewer::AppendVariable(wxTreeItemId rootNode, std::string sVar)
176{
177 wxString tooltip;
178
179 wxTreeItemId currentItem = AppendItem(rootNode, sVar.substr(0, sVar.find('\t')));
180 tooltip = sVar.substr(0, sVar.find('\t'));
181 sVar.erase(0, sVar.find('\t')+1);
182
183 SetItemText(currentItem, DIMCOLUMN, sVar.substr(0, sVar.find('\t')) + " ");
184 sVar.erase(0, sVar.find('\t')+1);
185
186 SetItemText(currentItem, CLASSCOLUMN, " " + sVar.substr(0, sVar.find('\t')));
187 sVar.erase(0, sVar.find('\t')+1);
188
189 SetItemText(currentItem, VALUECOLUMN, " " + sVar.substr(0, sVar.find('\t')));
190
191 // Create the tooltip and set it
192 size_t pos = sVar.find('\t');
193
194 if (pos < 2e3)
195 tooltip += " = " + sVar.substr(0, pos);
196 else
197 tooltip += " = " + sVar.substr(0, 1000) + "[...]" + sVar.substr(pos-1000, pos);
198
199 SetItemToolTip(currentItem, tooltip);
200
201 // Write values to the size column
202 if (!debuggerMode)
203 {
204 SetItemText(currentItem, SIZECOLUMN, " " + sVar.substr(sVar.rfind('\t')+1));
205 sVar.erase(sVar.rfind('\t'));
206 }
207
208 // Set the internal variable's name as a
209 // VarData object
210 // NOTE: STRING::RFIND is necessary to avoid issues with
211 // tabulator characters in the VALUECOLUMN
212 SetItemData(currentItem, new VarData(sVar.substr(sVar.rfind('\t')+1)));
213
214 return currentItem;
215}
216
217
226{
227 if (HasChildren(numRoot))
228 bExpandedState[0] = IsExpanded(numRoot);
229
230 if (HasChildren(stringRoot))
231 bExpandedState[1] = IsExpanded(stringRoot);
232
233 if (HasChildren(tableRoot))
234 bExpandedState[2] = IsExpanded(tableRoot);
235
236 if (HasChildren(clusterRoot))
237 bExpandedState[3] = IsExpanded(clusterRoot);
238
239 DeleteChildren(numRoot);
240 DeleteChildren(stringRoot);
241 DeleteChildren(tableRoot);
242 DeleteChildren(clusterRoot);
243
244 if (argumentRoot.IsOk())
245 {
246 if (HasChildren(argumentRoot))
247 bExpandedState[4] = IsExpanded(argumentRoot);
248
249 DeleteChildren(argumentRoot);
250 }
251
252 if (globalRoot.IsOk())
253 {
254 if (HasChildren(globalRoot))
255 bExpandedState[5] = IsExpanded(globalRoot);
256
257 DeleteChildren(globalRoot);
258 }
259}
260
261
271void VariableViewer::HandleDebugActions(const std::vector<std::string>& vVarList)
272{
273 if (!debuggerMode)
274 return;
275
276 vLastVarSet = vVarList;
277}
278
279
288wxString VariableViewer::GetInternalName(wxTreeItemId id)
289{
290 return static_cast<VarData*>(GetItemData(id))->sInternalName;
291}
292
293
304void VariableViewer::OnMenuEvent(wxCommandEvent& event)
305{
306 switch (event.GetId())
307 {
308 case ID_VARVIEWER_NEW:
309 OnNewTable();
310 break;
313 break;
316 break;
318 OnRemoveTable(GetItemText(selectedID));
319 break;
321 OnRenameTable(GetItemText(selectedID));
322 break;
324 OnSaveTable(GetItemText(selectedID));
325 break;
327 OnSaveasTable(GetItemText(selectedID));
328 break;
330 OnCopyValue(GetItemText(selectedID) + " =" + GetItemText(selectedID, VALUECOLUMN));
331 }
332}
333
334
344{
345 wxTextEntryDialog textEntry(this, _guilang.get("GUI_VARVIEWER_NEWTABLE_QUESTION"), _guilang.get("GUI_VARVIEWER_NEWTABLE"), "table()");
346
347 if (textEntry.ShowModal() != wxID_OK)
348 return;
349
350 wxString tables = textEntry.GetValue();
351
352 // Ensure that the user entered the necessary parentheses
353 if (tables.find(',') != std::string::npos)
354 {
355 wxString tablesTemp;
356
357 // Examine each table name
358 while (tables.length())
359 {
360 if (tablesTemp.length())
361 tablesTemp += ", ";
362
363 // Get the next table name
364 tablesTemp += tables.substr(0, tables.find(','));
365
366 // Add the needed parentheses directly at the end of
367 // the table name string
368 if (tablesTemp.substr(tablesTemp.find_last_not_of(' ')-1, 2) != "()")
369 tablesTemp.insert(tablesTemp.find_last_not_of(' ')+1, "()");
370
371 // Cut off the current table name
372 if (tables.find(',') != std::string::npos)
373 tables.erase(0, tables.find(',')+1);
374 else
375 break;
376 }
377
378 tables = tablesTemp;
379 }
380 else if (tables.find("()") == std::string::npos)
381 {
382 // Add the needed parentheses directly at the end of
383 // the table name string
384 tables.insert(tables.find_last_not_of(' ')+1, "()");
385 }
386
387 mainWindow->pass_command("new " + tables + " -free");
388}
389
390
400void VariableViewer::OnShowTable(const wxString& table, const wxString& tableDisplayName)
401{
402 mainWindow->showTable(table, tableDisplayName);
403}
404
405
414void VariableViewer::OnEditTable(const wxString& table)
415{
416 mainWindow->pass_command("edit " + table);
417}
418
419
429void VariableViewer::OnRenameTable(const wxString& table)
430{
431 wxTextEntryDialog textEntry(this, _guilang.get("GUI_VARVIEWER_NEWNAME_QUESTION"), _guilang.get("GUI_VARVIEWER_NEWNAME"), table);
432
433 if (textEntry.ShowModal() != wxID_OK)
434 return;
435
436 mainWindow->pass_command("rename " + table + ", " + textEntry.GetValue());
437}
438
439
448void VariableViewer::OnRemoveTable(const wxString& table)
449{
450 mainWindow->pass_command("remove " + table);
451}
452
453
462void VariableViewer::OnSaveTable(const wxString& table)
463{
464 mainWindow->pass_command("save " + table);
465}
466
467
478void VariableViewer::OnSaveasTable(const wxString& table)
479{
480 wxTextEntryDialog textEntry(this, _guilang.get("GUI_VARVIEWER_SAVENAME_QUESTION"), _guilang.get("GUI_VARVIEWER_SAVENAME"), table.substr(0, table.find('(')));
481
482 if (textEntry.ShowModal() != wxID_OK)
483 return;
484
485 mainWindow->pass_command("save " + table + " -file=\"" + textEntry.GetValue() + "\"");
486}
487
488
497void VariableViewer::OnCopyValue(const wxString& value)
498{
499 if (wxTheClipboard->Open())
500 {
501 wxTheClipboard->SetData(new wxTextDataObject(value));
502 wxTheClipboard->Close();
503 }
504}
505
506
515{
516 if (HasChildren(numRoot) && bExpandedState[0])
517 Expand(numRoot);
518
519 if (HasChildren(stringRoot) && bExpandedState[1])
520 Expand(stringRoot);
521
522 if (HasChildren(tableRoot) && bExpandedState[2])
523 Expand(tableRoot);
524
525 if (HasChildren(clusterRoot) && bExpandedState[3])
526 Expand(clusterRoot);
527
528 if (argumentRoot.IsOk() && HasChildren(argumentRoot) && bExpandedState[4])
529 Expand(argumentRoot);
530
531 if (globalRoot.IsOk() && HasChildren(globalRoot) && bExpandedState[5])
532 Expand(globalRoot);
533}
534
535
546void VariableViewer::OnRightClick(wxTreeEvent& event)
547{
548 if (!event.GetItem().IsOk() || GetItemParent(event.GetItem()) == GetRootItem())
549 return;
550
551 // Get the name of the table and determine, whether
552 // the table may be modified
553 bool isTable = GetItemParent(event.GetItem()) == tableRoot || GetItemText(event.GetItem()).find("()") != std::string::npos;
554 wxString itemLabel = GetItemText(event.GetItem());
555 bool bMayBeModified = itemLabel != "string()" && itemLabel != "table()";
556
557 // Create the menu
558 wxMenu popUpmenu;
559
560 if (isTable && !debuggerMode)
561 {
562 // Append commons
563 popUpmenu.Append(ID_VARVIEWER_NEW, _guilang.get("GUI_VARVIEWER_MENU_NEWTABLE"));
564 popUpmenu.AppendSeparator();
565 popUpmenu.Append(ID_VARVIEWER_SHOW, _guilang.get("GUI_VARVIEWER_MENU_SHOWVALUE"));
566 popUpmenu.Append(ID_VARVIEWER_EDIT, _guilang.get("GUI_VARVIEWER_MENU_EDITVALUE"));
567 popUpmenu.Append(ID_VARVIEWER_RENAME, _guilang.get("GUI_VARVIEWER_MENU_RENAME"));
568 popUpmenu.Append(ID_VARVIEWER_REMOVE, _guilang.get("GUI_VARVIEWER_MENU_REMOVE"));
569
570 // Add stuff, for non-string tables
571 if (itemLabel != "string()")
572 {
573 popUpmenu.AppendSeparator();
574 popUpmenu.Append(ID_VARVIEWER_SAVE, _guilang.get("GUI_VARVIEWER_MENU_SAVE"));
575 popUpmenu.Append(ID_VARVIEWER_SAVEAS, _guilang.get("GUI_VARVIEWER_MENU_SAVEAS"));
576 }
577
578 // Disable menu items for tables, which
579 // cannot be modified
580 if (!bMayBeModified)
581 {
582 popUpmenu.Enable(ID_VARVIEWER_RENAME, false);
583 popUpmenu.Enable(ID_VARVIEWER_REMOVE, false);
584 }
585 }
586 else if (!isTable)
587 popUpmenu.Append(ID_VARVIEWER_COPYVALUE, _guilang.get("GUI_VARVIEWER_MENU_COPYVALUE"));
588
589
590 // Store the selected item for the menu event handler
591 selectedID = event.GetItem();
592
593 // Display the menu
594 if (!isTable || !debuggerMode)
595 PopupMenu(&popUpmenu, event.GetPoint());
596}
597
598
607void VariableViewer::OnDoubleClick(wxTreeEvent& event)
608{
609 if (GetItemParent(event.GetItem()) != tableRoot && GetItemParent(event.GetItem()) != clusterRoot)
610 {
611 // In the debugger mode it's possible that the arguments
612 // or the globals contain table variables, which should
613 // also be viewable
614 if (debuggerMode && (GetItemParent(event.GetItem()) == argumentRoot || GetItemParent(event.GetItem()) == globalRoot))
615 {
616 if (GetItemText(event.GetItem()).find("()") != std::string::npos || GetItemText(event.GetItem()).find("{}") != std::string::npos)
617 OnShowTable(GetInternalName(event.GetItem()), GetItemText(event.GetItem()));
618 else if (GetInternalName(event.GetItem()).find("{}") != std::string::npos) // Fix for macros and templates
619 OnShowTable(GetInternalName(event.GetItem()), GetItemText(event.GetItem()) + "@CST{}");
620 else if (GetInternalName(event.GetItem()).find("()") != std::string::npos) // Fix for macros and templates
621 OnShowTable(GetInternalName(event.GetItem()), GetItemText(event.GetItem()) + "@TAB()");
622 }
623
624 return;
625 }
626
627 OnShowTable(GetInternalName(event.GetItem()), GetItemText(event.GetItem()));
628}
629
630
641{
642 debuggerMode = mode;
643
644 if (mode)
645 {
646 SetColumnWidth(CLASSCOLUMN, 75);
647
648 // Create or remove the procedure argument
649 // root item
651 {
652 argumentRoot = AppendItem(GetRootItem(), _guilang.get("GUI_VARVIEWER_ARGUMENTS"));
653 SetItemBold(argumentRoot, true);
654 }
656 {
657 Delete(argumentRoot);
658 argumentRoot.Unset();
659 }
660
661 // Create or remove the global variable
662 // root item
664 {
665 globalRoot = AppendItem(GetRootItem(), _guilang.get("GUI_VARVIEWER_GLOBALS"));
666 SetItemBold(globalRoot, true);
667 }
669 {
670 Delete(globalRoot);
671 globalRoot.Unset();
672 }
673 }
674}
675
676
692void VariableViewer::UpdateVariables(const std::vector<std::string>& vVarList, size_t nNumerics, size_t nStrings, size_t nTables, size_t nClusters, size_t nArguments, size_t nGlobals)
693{
694 // Clear the tree first
695 ClearTree();
696
697 // Show the numbers of variables in the current group
698 SetItemText(numRoot, DIMCOLUMN, "[" + toString(nNumerics) + "] ");
699 SetItemText(stringRoot, DIMCOLUMN, "[" + toString(nStrings) + "] ");
700 SetItemText(tableRoot, DIMCOLUMN, "[" + toString(nTables) + "] ");
701 SetItemText(clusterRoot, DIMCOLUMN, "[" + toString(nClusters) + "] ");
702
703 if (argumentRoot.IsOk())
704 {
705 SetItemText(argumentRoot, DIMCOLUMN, "[" + toString(nArguments) + "] ");
706 }
707
708 if (globalRoot.IsOk())
709 {
710 SetItemText(globalRoot, DIMCOLUMN, "[" + toString(nGlobals) + "] ");
711 }
712
713 wxTreeItemId currentItem;
714
715 // Go through the list of all passed variables
716 for (size_t i = 0; i < vVarList.size(); i++)
717 {
718 if (i < nNumerics)
719 {
720 // Append a variable to the numerics list
721 currentItem = AppendVariable(numRoot, vVarList[i]);
722 }
723 else if (i < nStrings+nNumerics)
724 {
725 // Append a variable to the string list
726 currentItem = AppendVariable(stringRoot, vVarList[i]);
727 }
728 else if (i < nStrings+nNumerics+nTables)
729 {
730 // Append a variable to the tables list
731 currentItem = AppendVariable(tableRoot, vVarList[i]);
732 }
733 else if (i < nStrings+nNumerics+nTables+nClusters)
734 {
735 // Append a variable to the tables list
736 currentItem = AppendVariable(clusterRoot, vVarList[i]);
737 }
738 else if (argumentRoot.IsOk() && i < nStrings+nNumerics+nTables+nClusters+nArguments)
739 {
740 // Append a variable to the tables list
741 currentItem = AppendVariable(argumentRoot, vVarList[i]);
742 }
743 else if (globalRoot.IsOk() && i < nStrings+nNumerics+nTables+nClusters+nArguments+nGlobals)
744 {
745 // Append a variable to the tables list
746 currentItem = AppendVariable(globalRoot, vVarList[i]);
747 }
748
749 // Perform all necessary highlighting options
750 if (debuggerMode && !checkPresence(vVarList[i]))
751 SetItemTextColour(currentItem, *wxRED);
752 if (!debuggerMode && checkSpecialVals(vVarList[i]))
753 {
754 SetItemTextColour(currentItem, wxColour(0, 0, 192));
755 }
756 }
757
758 // Expand the tree
759 ExpandAll();
760
761 // Handle debug mode specific tasks
762 HandleDebugActions(vVarList);
763}
764
This class handles the internal language system and returns the language strings of the selected lang...
Definition: language.hpp:38
std::string get(const std::string &sMessage, const std::vector< std::string > &vTokens) const
This member function returns the language string for the passed language identifier and replaces all ...
Definition: language.cpp:292
This class is the actual NumeRe main frame. The application's logic is implemented here.
Definition: NumeReWindow.h:177
void showTable(const wxString &tableName, const wxString &tableDisplayName)
This member function is a wrapper for an event handler of the variable viewer to display the contents...
Options * getOptions()
Definition: NumeReWindow.h:245
void pass_command(const wxString &command, bool isEvent=false)
This member function is a wrapper for the corresponding terminal function to pass a command to the ke...
bool GetShowGlobalVariables() const
Definition: Options.h:265
bool GetShowProcedureArguments() const
Definition: Options.h:263
void OnSaveTable(const wxString &table)
This member function saves the selected table.
void setDebuggerMode(bool mode=true)
This member function creates or removes unneeded tree root items and handles the debugger mode.
void OnEditTable(const wxString &table)
This member function displays the selected table for editing.
wxTreeItemId tableRoot
void OnRightClick(wxTreeEvent &event)
This member function creates the pop-up menu in the var viewer case (it does nothing in debugger mode...
void UpdateVariables(const std::vector< std::string > &vVarList, size_t nNumerics, size_t nStrings, size_t nTables, size_t nClusters, size_t nArguments=0, size_t nGlobals=0)
This member function is used to update the variable list, which is displayed by this control.
void OnRemoveTable(const wxString &table)
This member function removes the selected table.
wxTreeItemId clusterRoot
NumeReWindow * mainWindow
wxTreeItemId numRoot
void OnRenameTable(const wxString &table)
This member function displays a text entry dialog to choose a new name for the selected table.
void ExpandAll()
This member function expands all nodes, which contain child nodes.
wxTreeItemId stringRoot
bool bExpandedState[6]
wxString GetInternalName(wxTreeItemId id)
Returns the internal variable name of the selected variable.
void ClearTree()
A simple helper function to clean the tree.
void OnSaveasTable(const wxString &table)
This member function displays a text entry dialog to choose the file name for the selected table,...
bool checkSpecialVals(const std::string &sVar)
This member functions checks for special variable names, to highlight them (not used in debug mode).
bool checkPresence(const std::string &sVar)
This member function checks, whether a variable was already part of the previous variable set (only u...
void OnCopyValue(const wxString &value)
Copies the selected text to the clip board.
wxTreeItemId AppendVariable(wxTreeItemId rootNode, std::string sVar)
This member function splits the passed variable at tabulator characters and adds its contents to the ...
wxTreeItemId argumentRoot
void OnNewTable()
This member function displays a text entry dialog to enter the new table names and sends the correspo...
void OnDoubleClick(wxTreeEvent &event)
This event handler displays the selected table.
wxTreeItemId selectedID
std::vector< std::string > vLastVarSet
void HandleDebugActions(const std::vector< std::string > &vVarList)
This member function handles every task, which is specific to the debug mode after a variable update.
wxTreeItemId globalRoot
void OnMenuEvent(wxCommandEvent &event)
This member function handles the menu events created from the popup menu and redirects the control to...
void OnShowTable(const wxString &table, const wxString &tableDisplayName)
This member function displays the selected table.
@ ID_VARVIEWER_REMOVE
@ ID_VARVIEWER_SAVEAS
@ ID_VARVIEWER_NEW
@ ID_VARVIEWER_SAVE
@ ID_VARVIEWER_SHOW
@ ID_VARVIEWER_RENAME
@ ID_VARVIEWER_EDIT
@ ID_VARVIEWER_COPYVALUE
char name[32]
Definition: resampler.cpp:371
std::string sInternalName
VarData(const std::string name)
std::string toString(int)
Converts an integer to a string without the Settings bloat.
END_EVENT_TABLE()
#define DIMCOLUMN
Language _guilang
#define CLASSCOLUMN
#define SIZECOLUMN
#define VALUECOLUMN