Minsky: 3.17.0
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 <memory>
30 #include <vector>
31 
32 namespace minsky
33 {
35  {
36  enum RowCol {row, col};
38  };
39 
40  class GodleyIcon;
41 
43  template <minsky::ButtonWidgetEnums::RowCol rowCol>
45  {
47  protected:
49  int m_mouseOver=-1;
50  public:
51  static constexpr double buttonSpacing=15;
52 
54  unsigned idx=0;
55 
56  void draw(cairo_t*);
58  void drawButton(cairo_t*, const std::string& label,
59  double r, double g, double b, int idx);
61  void invoke(double x);
64  void hover(double x) {m_mouseOver=button(x);}
66  int button(double x) const {return x/buttonSpacing;}
67  int mouseOver() const {return m_mouseOver;}
68 
71  };
72 
73  class GodleyTableEditor;
74 
75  // This class is intended to be owned by a Godley Icon
77  {
78 
81  bool button1=false;
82  void m_enableButtons() {
85  }
86  public:
87  static constexpr double columnButtonsOffset=12;
90  double topTableOffset=30;
91  static constexpr double pulldownHot=12;
92  static constexpr double minColumnWidth=4*ButtonWidget<col>::buttonSpacing;
94 
96  const GodleyIcon& godleyIcon() const {return m_godleyIcon;}
97 
98  bool drawButtons=true;
101 
107  int srcRow=-1, srcCol=-1;
108  bool selectedCellInTable() const;
109  int hoverRow=-1, hoverCol=-1;
111  std::vector<double> colLeftMargin;
113  double rowHeight=0;
116  unsigned insertIdx=0, selectIdx=0;
117  double zoomFactor=1;
118 
121 
122  void draw(cairo_t* cairo);
123 
124  double width() const {return colLeftMargin.empty()? 0: colLeftMargin.back();}
125  double height() const;
126 
128  void mouseDown(double x, double y);
129  void mouseUp(double x, double y);
131  void mouseMoveB1(double x, double y);
132  void mouseMove(double x, double y);
133  void keyPress(int keySym, const std::string& utf8);
134 
137  ClickType clickTypeZoomed(double x, double y) const {return clickType(x/zoomFactor, y/zoomFactor);}
138 
139 
141  void addStockVar(double x);
142  void addStockVarByCol(int c);
143  void importStockVar(const std::string& name, double x);
144  void importStockVarByCol(const std::string& name, int c);
145  void deleteStockVar(double x);
146  void deleteStockVarByCol(int c);
147  void addFlow(double y);
148  void addFlowByRow(int r);
149  void deleteFlow(double y);
150  void deleteFlowByRow(int r);
151 
152  int colXZoomed(double x) const {return colX(x/zoomFactor);}
153  int rowYZoomed(double y) const {return rowY(y/zoomFactor);}
154 
155  // 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.
156  std::string moveAssetClass(double x, double y);
157  // 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.
158  std::string swapAssetClass(double x, double y);
159 
160  void highlightColumn(cairo_t* cairo,unsigned col);
161  void highlightRow(cairo_t* cairo,unsigned row);
162  void highlightCell(cairo_t* cairo,unsigned row, unsigned col);
163 
164  // support cut/copy/paste operations
165  void delSelection();
166  void cut();
167  void copy();
168  void paste();
169 
170  int textIdx(double x) const;
171 
172  std::size_t maxHistory{100};
173  std::size_t historyPtr=0;
174  // push state onto history if different
175  void pushHistory();
177  void undo(int changes);
178 
180  void adjustWidgets();
181 
183  void update();
184 
187  void navigateRight();
188  void navigateLeft();
189  void navigateUp();
190  void navigateDown();
192 
193  ClickType clickType(double x, double y) const;
195  std::set<string> matchingTableColumns(double x);
196  std::set<string> matchingTableColumnsByCol(int c);
197 
198  protected:
199  std::vector<ButtonWidget<row>> rowWidgets;
200  std::vector<ButtonWidget<col>> colWidgets;
202  int colX(double x) const;
204  int rowY(double y) const;
205  int motionRow=-1, motionCol=-1;
206  // Perform deep comparison of Godley tables in history to avoid spurious noAssetClass columns from arising during undo. For ticket 1118.
207  std::deque<GodleyTable> history;
208  void checkCell00();
209  void handleBackspace();
211  void handleDelete();
212  virtual void requestRedrawCanvas() {} // request redraw of canvas if a canvas
213  };
214 
216  {
218  protected:
219  bool redraw(int, int, int width, int height) override {
220  if (surface.get()) {
221  draw(surface->cairo());
222  return true;
223  }
224  return false;
225  }
226  public:
229  void requestRedraw() {if (surface.get()) surface->requestRedraw();}
230  void requestRedrawCanvas() override {requestRedraw();}
231 
232  void mouseDown(float x, float y) override {GodleyTableEditor::mouseDown(x,y);}
233  void mouseUp(float x, float y) override {GodleyTableEditor::mouseUp(x,y);}
234  void mouseMove(float x, float y) override {GodleyTableEditor::mouseMove(x,y);}
235  void zoom(double, double, double z) override {GodleyTableEditor::zoomFactor*=z; requestRedraw();}
236  double zoomFactor() const override {return GodleyTableEditor::zoomFactor;}
237  bool keyPress(const EventInterface::KeyPressArgs& args) override
238  {GodleyTableEditor::keyPress(args.keySym,args.utf8); return true;}
239  bool hasScrollBars() const override {return true;}
240  };
241 
242 }
243 
244 #include "godleyTableWindow.cd"
245 #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
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