Minsky
godleyTableWindow.h
Go to the documentation of this file.
1 /*
2  @copyright Steve Keen 2018
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 
24 #ifndef GODLEYTABLEWINDOW_H
25 #define GODLEYTABLEWINDOW_H
26 #include "assetClass.h"
27 #include "godleyTable.h"
28 #include "renderNativeWindow.h"
29 #include <accessor.h>
30 #include <memory>
31 #include <vector>
32 
33 namespace minsky
34 {
36  {
37  enum RowCol {row, col};
39  };
40 
41  class GodleyIcon;
42 
44  template <minsky::ButtonWidgetEnums::RowCol rowCol>
46  {
48  protected:
50  int m_mouseOver=-1;
51  public:
52  static constexpr double buttonSpacing=15;
53 
55  unsigned idx=0;
56 
57  void draw(cairo_t*);
59  void drawButton(cairo_t*, const std::string& label,
60  double r, double g, double b, int idx);
62  void invoke(double x);
65  void hover(double x) {m_mouseOver=button(x);}
67  int button(double x) const {return x/buttonSpacing;}
68  int mouseOver() const {return m_mouseOver;}
69 
72  };
73 
74  class GodleyTableEditor;
75 
76  // This class is intended to be owned by a Godley Icon
78  {
79 
82  bool button1=false;
83  void m_enableButtons() {
86  }
87  public:
88  static constexpr double columnButtonsOffset=12;
91  double topTableOffset=30;
92  static constexpr double pulldownHot=12;
93  static constexpr double minColumnWidth=4*ButtonWidget<col>::buttonSpacing;
95 
97  const GodleyIcon& godleyIcon() const {return m_godleyIcon;}
98 
99  bool drawButtons=true;
102 
108  int srcRow=-1, srcCol=-1;
109  bool selectedCellInTable() const;
110  int hoverRow=-1, hoverCol=-1;
112  std::vector<double> colLeftMargin;
114  double rowHeight=0;
117  unsigned insertIdx=0, selectIdx=0;
118  double zoomFactor=1;
119 
122 
123  void draw(cairo_t* cairo);
124 
125  double width() const {return colLeftMargin.empty()? 0: colLeftMargin.back();}
126  double height() const;
127 
129  void mouseDown(double x, double y);
130  void mouseUp(double x, double y);
132  void mouseMoveB1(double x, double y);
133  void mouseMove(double x, double y);
134  void keyPress(int keySym, const std::string& utf8);
135 
138  ClickType clickTypeZoomed(double x, double y) const {return clickType(x/zoomFactor, y/zoomFactor);}
139 
140 
142  void addStockVar(double x);
143  void addStockVarByCol(int c);
144  void importStockVar(const std::string& name, double x);
145  void importStockVarByCol(const std::string& name, int c);
146  void deleteStockVar(double x);
147  void deleteStockVarByCol(int c);
148  void addFlow(double y);
149  void addFlowByRow(int r);
150  void deleteFlow(double y);
151  void deleteFlowByRow(int r);
152 
153  int colXZoomed(double x) const {return colX(x/zoomFactor);}
154  int rowYZoomed(double y) const {return rowY(y/zoomFactor);}
155 
156  // warn user when a stock variable column is going to be moved to a different asset class on pressing a column button widget. For ticket 1072.
157  std::string moveAssetClass(double x, double y);
158  // warn user when a stock variable column is going to be swapped with a column from a different asset class on mouse click and drag. For ticket 1072.
159  std::string swapAssetClass(double x, double y);
160 
161  void highlightColumn(cairo_t* cairo,unsigned col);
162  void highlightRow(cairo_t* cairo,unsigned row);
163  void highlightCell(cairo_t* cairo,unsigned row, unsigned col);
164 
165  // support cut/copy/paste operations
166  void delSelection();
167  void cut();
168  void copy();
169  void paste();
170 
171  int textIdx(double x) const;
172 
173  std::size_t maxHistory{100};
174  std::size_t historyPtr=0;
175  // push state onto history if different
176  void pushHistory();
178  void undo(int changes);
179 
181  void adjustWidgets();
182 
184  void update();
185 
188  void navigateRight();
189  void navigateLeft();
190  void navigateUp();
191  void navigateDown();
193 
194  ClickType clickType(double x, double y) const;
196  std::set<string> matchingTableColumns(double x);
197  std::set<string> matchingTableColumnsByCol(int c);
198 
199  protected:
200  std::vector<ButtonWidget<row>> rowWidgets;
201  std::vector<ButtonWidget<col>> colWidgets;
203  int colX(double x) const;
205  int rowY(double y) const;
206  int motionRow=-1, motionCol=-1;
207  // Perform deep comparison of Godley tables in history to avoid spurious noAssetClass columns from arising during undo. For ticket 1118.
208  std::deque<GodleyTable> history;
209  void checkCell00();
210  void handleBackspace();
212  void handleDelete();
213  virtual void requestRedrawCanvas() {} // request redraw of canvas if a canvas
214  };
215 
217  {
219  protected:
220  bool redraw(int, int, int width, int height) override {
221  if (surface.get()) {
222  draw(surface->cairo());
223  return true;
224  }
225  return false;
226  }
227  public:
230  void requestRedraw() {if (surface.get()) surface->requestRedraw();}
231  void requestRedrawCanvas() override {requestRedraw();}
232 
233  void mouseDown(float x, float y) override {GodleyTableEditor::mouseDown(x,y);}
234  void mouseUp(float x, float y) override {GodleyTableEditor::mouseUp(x,y);}
235  void mouseMove(float x, float y) override {GodleyTableEditor::mouseMove(x,y);}
236  void zoom(double, double, double z) override {GodleyTableEditor::zoomFactor*=z; requestRedraw();}
237  double zoomFactor() const override {return GodleyTableEditor::zoomFactor;}
238  bool keyPress(const EventInterface::KeyPressArgs& args) override
239  {GodleyTableEditor::keyPress(args.keySym,args.utf8); return true;}
240  bool hasScrollBars() const override {return true;}
241  };
242 
243 }
244 
245 #include "godleyTableWindow.cd"
246 #endif
double leftTableOffset
offset of the table within the window
int rowY(double y) const
row at y in unzoomed coordinates
ClickType clickType(double x, double y) const
static constexpr double pulldownHot
space for ▼ in stackVar cells minimum column width (for eg empty columns)
void update()
update canvas godleyIcon, and any related godley icons. Can throw
supports +/-/←/→/↓/↑ widget
void importStockVarByCol(const std::string &name, int c)
ButtonWidget(GodleyIcon &godleyIcon, unsigned idx=0)
void navigateDown()
move selected cell right, left, up or down, moving to next line and wrapping if at end of row or col ...
void adjustWidgets()
ensure button widgets are synced with current table data
bool drawButtons
whether to draw row/column buttons
bool hasScrollBars() const override
return whether this window has scrollbars (needed for MacOSX).
std::set< string > matchingTableColumnsByCol(int c)
void mouseMove(double x, double y)
std::deque< GodleyTable > history
void invoke(double x)
invoke action associated with button at x
void draw(cairo_t *cairo)
static constexpr double minColumnWidth
void mouseMoveB1(double x, double y)
mouse motion with button 1 pressed
double zoomFactor
zoom the display
void addStockVar(double x)
add/delete rows/columns at x,y
void highlightCell(cairo_t *cairo, unsigned row, unsigned col)
unsigned idx
row or column this widget is located in
void mouseUp(float x, float y) override
int button(double x) const
convert x coordinate into a button
int srcRow
src cell in the event of a move
std::set< string > matchingTableColumns(double x)
return list of matching table columns for column at x
double rowHeight
computed height of each row
void hover(int button)
indicate which button mouse is hovering over. x<0 means not hovering
int colXZoomed(double x) const
void undo(int changes)
restore to state changes ago
std::vector< ButtonWidget< row > > rowWidgets
void highlightColumn(cairo_t *cairo, unsigned col)
std::size_t maxHistory
maximum no. of history states to save
void mouseDown(float x, float y) override
Creation and access to the minskyTCL_obj object, which has code to record whenever Minsky&#39;s state cha...
Definition: constMap.h:22
std::vector< double > colLeftMargin
computed positions of the table columns
void importStockVar(const std::string &name, double x)
CLASSDESC_ACCESS(ButtonWidget)
void zoom(double, double, double z) override
void requestRedrawCanvas() override
int colX(double x) const
column at x in unzoomed coordinates
static constexpr double buttonSpacing
void checkCell00()
check if cell (0,0) is selected, and deselect if so handle delete or backspace. Cell assumed selected...
bool button1
mouse button pressed
void navigateUp()
move selected cell right, left, up or down, moving to next line and wrapping if at end of row or col ...
void drawButton(cairo_t *, const std::string &label, double r, double g, double b, int idx)
draw button idx, with label label and colour r, b, g
GodleyIcon & m_godleyIcon
Godley icon that owns this.
CLASSDESC_ACCESS(GodleyTableEditor)
bool redraw(int, int, int width, int height) override
virtual void requestRedrawCanvas()
int rowYZoomed(double y) const
void mouseMove(float x, float y) override
void keyPress(int keySym, const std::string &utf8)
void mouseUp(double x, double y)
CLASSDESC_ACCESS(GodleyTableWindow)
bool keyPress(const EventInterface::KeyPressArgs &args) override
handle key press over current itemFocus,
int selectedRow
which cell is active, none initially
void highlightRow(cairo_t *cairo, unsigned row)
unsigned scrollRowStart
starting row/col number of the scrolling region
ClickType clickTypeZoomed(double x, double y) const
returns the clickType in zoomed coordinates
void navigateLeft()
move selected cell right, left, up or down, moving to next line and wrapping if at end of row or col ...
int motionCol
current cell under mouse motion
double zoomFactor() const override
void navigateRight()
move selected cell right, left, up or down, moving to next line and wrapping if at end of row or col ...
std::string swapAssetClass(double x, double y)
unsigned insertIdx
location of insertion pointer in selected cell, as well as other end of selection (if mouse-swiped) ...
std::vector< ButtonWidget< col > > colWidgets
const GodleyIcon & godleyIcon() const
int textIdx(double x) const
std::string moveAssetClass(double x, double y)
static constexpr double columnButtonsOffset
void mouseDown(double x, double y)
event handling