Minsky
minskyTCL.h
Go to the documentation of this file.
1 /*
2  @copyright Steve Keen 2013
3  @author Russell Standish
4  This file is part of Minsky.
5 
6  Minsky is free software: you can redistribute it and/or modify it
7  under the terms of the GNU General Public License as published by
8  the Free Software Foundation, either version 3 of the License, or
9  (at your option) any later version.
10 
11  Minsky is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with Minsky. If not, see <http://www.gnu.org/licenses/>.
18 */
19 
20 #ifndef MINSKYTCL_H
21 #define MINSKYTCL_H
22 #include "minsky.h"
23 #include "godleyTableWindow.h"
24 #include "variableInstanceList.h"
25 #include "classdesc_access.h"
26 #include <fstream>
27 #include <memory>
28 
29 namespace ecolab {extern Tk_Window mainWin;}
30 
31 // TCL specific definitions for global minsky object
32 namespace minsky
33 {
34  cmd_data* getCommandData(const string& name);
35 
36  template <class O>
37  int deleteTclObject(ClientData, Tcl_Interp*, int, const char **);
38 
40  ecolab::TCL_obj_t& minskyTCL_obj();
41  void setTCL_objAttributes();
42 
43  struct MinskyTCL: public Minsky
44  {
45  bool rebuildTCLcommands=false;
46 
48  void getValue(const std::string& valueId);
49 
50  std::unique_ptr<std::ostream> eventRecord;
51  void startRecording(const char* file) {
52  eventRecord.reset(new std::ofstream(file));
53  *eventRecord<<"checkRecordingVersion "<<minskyVersion<<endl;
54  }
55  void stopRecording() {
56  eventRecord.reset();
57  }
58 
62  /*static*/ void operationIcon(const char* imageName, const char* opName) const;
63 
64  std::set<string> matchingTableColumns(const std::string& currTable, GodleyAssetClass::AssetClass ac) {
65  auto it=TCL_obj_properties().find(currTable);
66  if (it!=TCL_obj_properties().end())
67  if (auto g=it->second->memberPtrCasted<GodleyIcon>())
68  return Minsky::matchingTableColumns(*g, ac);
69  return std::set<string>();
70  }
71 
73  void registerRef(ItemPtr& item, const std::string& name)
74  {
75  if (item)
76  item->TCL_obj(minskyTCL_obj(),name);
77  else
78  TCL_obj_deregister(name);
79  }
80 
82  {
83  TCL_obj_deregister("minsky.canvas.item");
85  canvas.itemFocus.reset();
86  registerRef(canvas.item,"minsky.canvas.item");
87  registerRef(canvas.itemFocus,"minsky.canvas.itemFocus");
88  return canvas.item.get();
89  }
90 
92  {
93  TCL_obj_deregister("minsky.canvas.item");
95  canvas.item.reset();
96  registerRef(canvas.item,"minsky.canvas.item");
97  registerRef(canvas.itemFocus,"minsky.canvas.itemFocus");
98  return canvas.item.get();
99  }
100 
101  bool getItemAt(float x, float y)
102  {
103  // deregister any old definitions, as item is polymorphic
104  TCL_obj_deregister("minsky.canvas.item");
105  canvas.getItemAt(x,y);
106  registerRef(canvas.item,"minsky.canvas.item");
107  return canvas.item.get();
108  }
109 
110  // call item->retype, and update the canvas.item ptr with the new object
112  {
113  if (canvas.item)
114  if (auto g=canvas.item->group.lock())
115  {
116  // snag a reference to the actual location of this item,
117  // so we can update canvas.item later. Ticket #1135.
118  auto itemItr=find(g->items.begin(), g->items.end(), canvas.item);
119  if (auto v=canvas.item->variableCast())
120  v->retype(type);
121  if (itemItr!=g->items.end())
122  {
123  canvas.item=*itemItr;
124  TCL_obj_deregister("minsky.canvas.item");
125  registerRef(canvas.item,"minsky.canvas.item");
126  }
127  }
128  }
129 
131  {
132  // deregister any old definitions, as item is polymorphic
133  TCL_obj_deregister("minsky.canvas.item");
135  registerRef(canvas.item,"minsky.canvas.item");
136  return canvas.item.get();
137  }
138 
140  {
142  {
143  TCL_obj_deregister("minsky.canvas.item");
144  registerRef(canvas.item,"minsky.canvas.item");
145  return true;
146  }
147  return false;
148  }
149 
150  bool getWireAt(float x, float y)
151  {
152  canvas.getWireAt(x,y);
153  if (canvas.wire)
154  TCL_obj(minskyTCL_obj(),"minsky.canvas.wire",*canvas.wire);
155  else
156  TCL_obj_deregister("minsky.canvas.wire");
157  return canvas.wire.get();
158  }
159 
160  void addVariable(const std::string& name, VariableType::Type type) {
161  canvas.addVariable(name,type);
162  registerRef(canvas.itemFocus,"minsky.canvas.itemFocus");
163  }
166  registerRef(canvas.itemFocus,"minsky.canvas.itemFocus");
167  }
168  void addNote(const std::string& text) {
169  canvas.addNote(text);
170  registerRef(canvas.itemFocus,"minsky.canvas.itemFocus");
171  }
172  void addPlot() {
173  canvas.addPlot();
174  registerRef(canvas.itemFocus,"minsky.canvas.itemFocus");
175  }
176  void addGodley() {
177  canvas.addGodley();
178  registerRef(canvas.itemFocus,"minsky.canvas.itemFocus");
179  }
180  void addGroup() {
181  canvas.addGroup();
182  registerRef(canvas.itemFocus,"minsky.canvas.itemFocus");
183  }
184  void addSwitch() {
185  canvas.addSwitch();
186  registerRef(canvas.itemFocus,"minsky.canvas.itemFocus");
187  }
188  void addIntegral() {
190  registerRef(canvas.item,"minsky.canvas.item");
191  }
192  void addRavel() {
193  canvas.addRavel();
194  registerRef(canvas.item,"minsky.canvas.item");
195  }
196  void addLock() {
197  canvas.addLock();
198  registerRef(canvas.item,"minsky.canvas.item");
199  }
200  void addSheet() {
201  canvas.addSheet();
202  registerRef(canvas.item,"minsky.canvas.item");
203  }
204 
205  void createGroup() {
207  registerRef(canvas.itemFocus,"minsky.canvas.itemFocus");
208  }
209  void convertVarType(const std::string& name, VariableType::Type type) {
210  Minsky::convertVarType(name,type);
211  registerRef(canvas.item,"minsky.canvas.item");
212  }
213 
214  void groupOfItem() {
215  if (canvas.item) {
216  canvas.item=canvas.item->group.lock();
217  registerRef(canvas.item,"minsky.canvas.item");
218  }
219  }
220 
221  void resetItem() {
222  canvas.item.reset();
223  registerRef(canvas.item,"minsky.canvas.item");
224  }
225 
226  bool selectVar(float x, float y) {
227  bool r=canvas.selectVar(x,y);
228  if (r)
229  registerRef(canvas.item,"minsky.canvas.item");
230  return r;
231  }
232 
236  std::string TCLItem() {
237  std::string name="item"+std::to_string(std::size_t(canvas.item.get()));
238  if (canvas.item && !TCL_obj_properties().count(name)) {
239  canvas.item->TCL_obj(minskyTCL_obj(),name);
240  // create a reference to manage object's lifetime
241  Tcl_CreateCommand
242  (ecolab::interp(), (name+".delete").c_str(),
243  (Tcl_CmdProc*)deleteTclObject<Item>,
244  (ClientData)(new ItemPtr(canvas.item)),NULL);
245  }
246  return canvas.item? name: "";
247  }
248 
250  void setColour(std::size_t i, const char* name);
251 
253  bool findObject(const std::string& type)
254  {
255  canvas.item.reset();
256  if (type=="Group" && !canvas.model->groups.empty())
257  canvas.item=canvas.model->groups.front();
258  else
259  model->recursiveDo
260  (&GroupItems::items, [&](const Items&, Items::const_iterator i)
261  {
262  if ((*i)->classType()==type)
263  {
264  canvas.item=*i;
265  return true;
266  }
267  return false;
268  });
269  registerRef(canvas.item,"minsky.canvas.item");
270  return canvas.item.get();
271  }
272 
273  bool findVariable(const std::string& name)
274  {
275  canvas.item.reset();
276  model->recursiveDo
277  (&GroupItems::items, [&](const Items&, Items::const_iterator i)
278  {
279  if (auto v=dynamic_cast<VariableBase*>(i->get()))
280  if (v->name()==name)
281  {
282  canvas.item=*i;
283  return true;
284  }
285  return false;
286  });
287  registerRef(canvas.item,"minsky.canvas.item");
288  return canvas.item.get();
289  }
290 
294  TCL_obj(minskyTCL_obj(),"minsky.canvas.model", *canvas.model);
295  }
299  TCL_obj(minskyTCL_obj(),"minsky.canvas.model", *canvas.model);
300  }
301 
302 
303 
304  std::string openGodley() {
305  if (auto gi=dynamic_pointer_cast<GodleyIcon>(canvas.item))
306  {
307  std::string name="godleyWindow"+to_string(std::size_t(canvas.item.get()));
308  if (TCL_obj_properties().count(name)==0)
309  {
310  TCL_obj(minskyTCL_obj(),name,*gi);
311  }
312  return name;
313  }
314  return "";
315  }
316 
317  std::string listAllInstances() const {
318  if (auto v=canvas.item->variableCast())
319  {
320  std::string name="instanceList"+to_string(std::size_t(canvas.item.get()));
321  if (TCL_obj_properties().count(name)==0)
322  {
323  auto instanceList=new VariableInstanceList(*canvas.model, v->valueId());
324  // pass ownership of object to TCL interpreter
325  Tcl_CreateCommand
326  (ecolab::interp(), (name+".delete").c_str(),
327  (Tcl_CmdProc*)deleteTclObject<VariableInstanceList>,
328  (ClientData)instanceList,NULL);
329  TCL_obj(minskyTCL_obj(),name,*instanceList);
330  }
331  return name;
332  }
333  return "";
334  }
335 
336  void loadVariableFromCSV(const std::string& specVar, const std::string& filename)
337  {
338  auto i=TCL_obj_properties().find(specVar);
339  if (i!=TCL_obj_properties().end())
340  if (auto spec=dynamic_cast<member_entry<DataSpec>*>(i->second.get()))
341  if (auto v=canvas.item->variableCast())
342  {
343  setBusyCursor();
344  v->importFromCSV({filename}, spec->memberptr->toSchema());
345  clearBusyCursor();
346  }
347  }
348 
350  void load(const std::string& filename) {
351  Minsky::load(filename);
352  // load resets the model pointer, etc, so request rebuilding of
353  // TCL commands
354  rebuildTCLcommands=true;
355  }
356 
358  void undo(TCL_args args) {
359  if (args.count) Minsky::undo(args);
360  else Minsky::undo();
361  }
362 
363  string valueId(const string& x) {return minsky::valueId(x);}
364 
365  ecolab::Accessor<std::string> defaultFont{
366  [this]() {return Minsky::defaultFont();},
367  [this](const std::string& x) {return Minsky::defaultFont(x);}
368  };
369 
370  void setBusyCursor() override
371  {tclcmd()<<"setCursor watch\n";}
372  void clearBusyCursor() override
373  {tclcmd()<<"setCursor {}\n";}
374 
375  void message(const std::string& m) override
376  {(tclcmd()<<"if [llength [info command tk_messageBox]] {tk_messageBox -message \"")|m|"\" -type ok}\n";}
377 
378  void runItemDeletedCallback(const Item& item) override
379  {tclcmd()<<item.deleteCallback<<'\n';}
380 
381  MemCheckResult checkMemAllocation(std::size_t bytes) const override {
382  if (ecolab::mainWin && bytes>0.2*physicalMem())
383  {
384  tclcmd cmd;
385  cmd<<"tk_messageBox -message {Allocation will use more than 50% of available memory. Do you want to proceed?} -type yesno\n";
386  return cmd.result=="yes"? proceed: abort;
387  }
388  return OK;
389  }
390 
391  static int numOpArgs(OperationType::Type o);
393 
395  private:
396  std::unique_ptr<char[]> _defaultFont;
397 
398  CmdData getCommandData(const std::string& command) const override {
399  auto t=minsky::getCommandData(command);
400  if (!t) return no_command;
401  if (t->is_const) return is_const;
402  if (t->is_setterGetter) return is_setterGetter;
403  return generic;
404  }
405 
406  };
407 }
408 
409 #include "minskyTCL.cd"
410 #endif
void addGroup()
item or wire obtained by get*At() calls
Definition: canvas.h:201
bool getItemAtFocus()
Definition: minskyTCL.h:130
template int deleteTclObject< Item >(ClientData cd, Tcl_Interp *interp, int argc, const char **argv)
void message(const std::string &m) override
display a message in a popup box on the GUI
Definition: minskyTCL.h:375
WirePtr wire
item or wire obtained by get*At() calls
Definition: canvas.h:176
CLASSDESC_ACCESS(MinskyTCL)
Tk_Window mainWin
Definition: tclmain.cc:66
bool findVariableDefinition()
populates item with the defining variable if there is one. Leave item unchanged if it is not a variab...
Definition: canvas.cc:768
void loadVariableFromCSV(const std::string &specVar, const std::string &filename)
Definition: minskyTCL.h:336
std::unique_ptr< std::ostream > eventRecord
Definition: minskyTCL.h:50
static int numOpArgs(OperationType::Type o)
Definition: minskyTCL.cc:203
CmdData getCommandData(const std::string &command) const override
return meta information on a given command
Definition: minskyTCL.h:398
void startRecording(const char *file)
Definition: minskyTCL.h:51
void openModelInCanvas()
reinitialises canvas to the toplevel group
Definition: minskyTCL.h:297
void addNote(const std::string &text)
item or wire obtained by get*At() calls
Definition: canvas.h:192
MemCheckResult
check whether to proceed or abort, given a request to allocate bytes of memory. Implemented in Minsky...
Definition: minsky.h:463
void addIntegral()
Definition: minskyTCL.h:188
int deleteTclObject(ClientData cd, Tcl_Interp *interp, int argc, const char **argv)
Definition: minskyTCL.cc:75
void addVariable(const std::string &name, VariableType::Type type)
item or wire obtained by get*At() calls
Definition: canvas.h:187
void load(const std::string &filename)
load from a file
Definition: minskyTCL.h:350
std::shared_ptr< Item > ItemPtr
Definition: item.h:57
void openGroupInCanvas(const ItemPtr &item)
reinitialises canvas to the group located in item
Definition: canvas.cc:692
void addPlot()
item or wire obtained by get*At() calls
Definition: canvas.h:196
string valueId(const string &name)
construct a valueId from fully qualified name @ name should not be canonicalised
Definition: valueId.cc:75
Model model
Definition: canvas.h:103
void registerRef(ItemPtr &item, const std::string &name)
register item as a TCL obj under name if it exists, otherwise deregister it
Definition: minskyTCL.h:73
void openGroupInCanvas()
reinitialises canvas to the group located in item
Definition: minskyTCL.h:292
bool getItemAt(float x, float y)
Definition: minskyTCL.h:101
void addSheet()
item or wire obtained by get*At() calls
Definition: canvas.h:205
void setBusyCursor() override
set/clear busy cursor in GUI
Definition: minskyTCL.h:370
void addVariable(const std::string &name, VariableType::Type type)
Definition: minskyTCL.h:160
std::size_t physicalMem() const
returns amount of memory installed on system
Definition: minsky.cc:1713
void operationIcon(const char *imageName, const char *opName) const
fill in a Tk image with the icon for a specific operation
Definition: minskyTCL.cc:189
void addOperation(OperationType::Type op)
Definition: minskyTCL.h:164
bool selectVar(float x, float y)
populates item with a variable if (x,y) is over a variable part
Definition: canvas.cc:755
void addLock()
item or wire obtained by get*At() calls
Definition: canvas.h:204
long undo(int changes=1)
restore model to state changes ago
Definition: minsky.cc:1401
Creation and access to the minskyTCL_obj object, which has code to record whenever Minsky&#39;s state cha...
Definition: constMap.h:22
void setColour(std::size_t i, const char *name)
sets the colour of palette item i to Tk acceptable colour name
Definition: minskyTCL.cc:219
std::vector< ItemPtr > Items
Definition: item.h:366
string valueId(const string &x)
Definition: minskyTCL.h:363
std::string openGodley()
Definition: minskyTCL.h:304
std::unique_ptr< char[]> _defaultFont
Definition: minskyTCL.h:396
Canvas canvas
Definition: minsky.h:256
void groupOfItem()
Definition: minskyTCL.h:214
void convertVarType(const std::string &name, VariableType::Type type)
Definition: minskyTCL.h:209
void addIntegral()
add integral to current canvas item (which must be variable convertible to an integral variable ...
Definition: minsky.cc:1527
void stopRecording()
Definition: minskyTCL.h:55
void createGroup()
Definition: minskyTCL.h:205
bool getItemAt(float x, float y) override
item or wire obtained by get*At() calls
Definition: canvas.h:178
std::string defaultFont()
the default used by Pango
Definition: minsky.cc:1738
bool rebuildTCLcommands
Definition: minskyTCL.h:45
void addOperation(OperationType::Type op)
item or wire obtained by get*At() calls
Definition: canvas.h:182
bool findVariableDefinition()
Definition: minskyTCL.h:139
std::set< string > matchingTableColumns(const std::string &currTable, GodleyAssetClass::AssetClass ac)
Definition: minskyTCL.h:64
void addGodley()
item or wire obtained by get*At() calls
Definition: canvas.h:200
ecolab::TCL_obj_t & minskyTCL_obj()
a TCL_obj_t that provides a hook for detecting model edits
Definition: minskyTCLObj.h:70
bool getWireAt(float x, float y) override
item or wire obtained by get*At() calls
Definition: canvas.cc:432
bool itemFromItemFocus()
Definition: minskyTCL.h:81
static const std::string minskyVersion
return the AEGIS assigned version number
Definition: minsky.h:337
void addSwitch()
item or wire obtained by get*At() calls
Definition: canvas.h:202
void load(const std::string &filename)
load from a file
Definition: minsky.cc:1048
bool selectVar(float x, float y)
Definition: minskyTCL.h:226
void retypeItem(VariableType::Type type)
Definition: minskyTCL.h:111
std::string TCLItem()
create a TCL controlled object that is a reference to item
Definition: minskyTCL.h:236
void clearBusyCursor() override
Definition: minskyTCL.h:372
ItemPtr itemFocus
item selected by clicking
Definition: canvas.h:106
bool findVariable(const std::string &name)
Definition: minskyTCL.h:273
void getValue(const std::string &valueId)
generate a TCL_obj referring to variableValues[valueId]
Definition: minskyTCL.cc:141
void addNote(const std::string &text)
Definition: minskyTCL.h:168
std::set< string > matchingTableColumns(const GodleyIcon &currTable, GodleyAssetClass::AssetClass ac)
Definition: minsky.cc:567
double t
time
Definition: rungeKutta.h:57
cmd_data * getCommandData(const string &name)
Definition: minskyTCL.cc:62
void convertVarType(const std::string &name, VariableType::Type type)
Converts variable(s) named by name into a variable of type type.
Definition: minsky.cc:1457
MemCheckResult checkMemAllocation(std::size_t bytes) const override
Definition: minskyTCL.h:381
GroupPtr model
Definition: minsky.h:255
void setTCL_objAttributes()
Definition: minskyTCL.cc:104
void groupSelection()
create a group from items found in the current selection
Definition: canvas.cc:439
string to_string(CONST84 char *x)
Definition: minskyTCLObj.h:33
bool getWireAt(float x, float y)
Definition: minskyTCL.h:150
void runItemDeletedCallback(const Item &item) override
run callback attached to item
Definition: minskyTCL.h:378
void undo(TCL_args args)
restore model to state changes ago
Definition: minskyTCL.h:358
std::string listAllInstances() const
Definition: minskyTCL.h:317
bool findObject(const std::string &type)
find first object of given type
Definition: minskyTCL.h:253
void addRavel()
item or wire obtained by get*At() calls
Definition: canvas.h:203
OperationType::Group classifyOp(OperationType::Type o) const
Definition: minskyTCL.h:392
static Group classify(Type t)
bool itemFocusFromItem()
Definition: minskyTCL.h:91
std::string deleteCallback
Definition: item.h:177
ItemPtr item
item or wire obtained by get*At() calls
Definition: canvas.h:175