From 6e7cf4d219fac55271f74a8cc9b9f0c3a8a70cf7 Mon Sep 17 00:00:00 2001 From: Russell Standish Date: Fri, 29 May 2026 14:20:10 +1000 Subject: [PATCH 1/4] feat: move display Godley table variable values as an attribute of GodleyIcon rather than system preference. For feature #194. --- .../src/app/managers/CommandsManager.ts | 3 +-- .../src/app/managers/ContextMenuManager.ts | 14 +++++++++++- .../src/app/managers/GodleyMenuManager.ts | 10 ++------- .../src/app/managers/StoreManager.ts | 4 ++-- .../preferences/preferences.component.html | 11 ---------- .../preferences/preferences.component.ts | 1 - gui-js/libs/shared/src/lib/backend/minsky.ts | 4 ++-- model/godleyIcon.h | 7 +++++- model/godleyTableWindow.cc | 4 ++-- model/godleyTableWindow.h | 3 +++ model/minsky.cc | 22 +++++++++---------- model/minsky.h | 3 +-- schema/schema3.cc | 2 ++ schema/schema3.h | 5 +++-- 14 files changed, 48 insertions(+), 45 deletions(-) diff --git a/gui-js/apps/minsky-electron/src/app/managers/CommandsManager.ts b/gui-js/apps/minsky-electron/src/app/managers/CommandsManager.ts index fb2044549..ca541008d 100644 --- a/gui-js/apps/minsky-electron/src/app/managers/CommandsManager.ts +++ b/gui-js/apps/minsky-electron/src/app/managers/CommandsManager.ts @@ -1235,12 +1235,11 @@ export class CommandsManager { static async applyPreferences() { const { enableMultipleEquityColumns, - godleyTableShowValues, godleyTableOutputStyle, font, numBackups, } = StoreManager.store.get('preferences'); - minsky.setGodleyDisplayValue(godleyTableShowValues,godleyTableOutputStyle); + minsky.displayStyle(godleyTableOutputStyle); minsky.multipleEquities(enableMultipleEquityColumns); minsky.defaultFont(font); minsky.numBackups(numBackups); diff --git a/gui-js/apps/minsky-electron/src/app/managers/ContextMenuManager.ts b/gui-js/apps/minsky-electron/src/app/managers/ContextMenuManager.ts index 1444cc0df..db9478907 100644 --- a/gui-js/apps/minsky-electron/src/app/managers/ContextMenuManager.ts +++ b/gui-js/apps/minsky-electron/src/app/managers/ContextMenuManager.ts @@ -682,7 +682,19 @@ export class ContextMenuManager { label: 'Display variables', type: 'checkbox', checked: displayVariableChecked, - click: () => godley.toggleVariableDisplay() + click: async () => { + await godley.toggleVariableDisplay(); + await minsky.canvas.requestRedraw(); + } + }), + new MenuItem({ + label: 'Display values', + type: 'checkbox', + checked: await godley.displayValues(), + click: async () => { + await godley.toggleDisplayValues(); + await minsky.canvas.requestRedraw(); + }, }), new MenuItem({ label: 'Copy flow variables', diff --git a/gui-js/apps/minsky-electron/src/app/managers/GodleyMenuManager.ts b/gui-js/apps/minsky-electron/src/app/managers/GodleyMenuManager.ts index 732d6b944..c837ce598 100644 --- a/gui-js/apps/minsky-electron/src/app/managers/GodleyMenuManager.ts +++ b/gui-js/apps/minsky-electron/src/app/managers/GodleyMenuManager.ts @@ -58,7 +58,6 @@ export class GodleyMenuManager { const preferences = StoreManager.store.get('preferences'); let { enableMultipleEquityColumns, - godleyTableShowValues, godleyTableOutputStyle, } = preferences; @@ -66,19 +65,14 @@ export class GodleyMenuManager { enableMultipleEquityColumns = value as boolean; minsky.multipleEquities(enableMultipleEquityColumns); GodleyMenuManager.refresh(window); - } else { - if (property === 'godleyTableOutputStyle') { + } else if (property === 'godleyTableOutputStyle') { godleyTableOutputStyle = value as GodleyTableOutputStyles; - } else if (property === 'godleyTableShowValues') { - godleyTableShowValues = value as boolean; - } - minsky.setGodleyDisplayValue(godleyTableShowValues, godleyTableOutputStyle); + minsky.displayStyle(godleyTableOutputStyle); } StoreManager.store.set({ preferences: { ...preferences, - godleyTableShowValues: godleyTableShowValues, godleyTableOutputStyle: godleyTableOutputStyle, enableMultipleEquityColumns: enableMultipleEquityColumns, }, diff --git a/gui-js/apps/minsky-electron/src/app/managers/StoreManager.ts b/gui-js/apps/minsky-electron/src/app/managers/StoreManager.ts index ddcc18df3..f682ba05a 100644 --- a/gui-js/apps/minsky-electron/src/app/managers/StoreManager.ts +++ b/gui-js/apps/minsky-electron/src/app/managers/StoreManager.ts @@ -3,7 +3,7 @@ import Store from 'electron-store'; import {homedir} from 'node:os'; interface MinskyPreferences { - godleyTableShowValues: boolean; +// godleyTableShowValues: boolean; godleyTableOutputStyle: string; enableMultipleEquityColumns: boolean; numberOfRecentFilesToDisplay: number; @@ -31,7 +31,7 @@ class StoreManager { defaultModelDirectory: homedir(), defaultDataDirectory: homedir(), preferences: { - godleyTableShowValues: false, + // godleyTableShowValues: false, godleyTableOutputStyle: 'sign', enableMultipleEquityColumns: false, numberOfRecentFilesToDisplay: 10, diff --git a/gui-js/libs/menu/src/lib/options/preferences/preferences.component.html b/gui-js/libs/menu/src/lib/options/preferences/preferences.component.html index 0474daaee..42d75235e 100644 --- a/gui-js/libs/menu/src/lib/options/preferences/preferences.component.html +++ b/gui-js/libs/menu/src/lib/options/preferences/preferences.component.html @@ -3,17 +3,6 @@
-
- - -
-
diff --git a/gui-js/libs/menu/src/lib/options/preferences/preferences.component.ts b/gui-js/libs/menu/src/lib/options/preferences/preferences.component.ts index 73eb1fbf7..a47038ab9 100644 --- a/gui-js/libs/menu/src/lib/options/preferences/preferences.component.ts +++ b/gui-js/libs/menu/src/lib/options/preferences/preferences.component.ts @@ -22,7 +22,6 @@ export class PreferencesComponent implements OnInit { constructor(private electronService: ElectronService) { this.form = new FormGroup({ - godleyTableShowValues: new FormControl(null), godleyTableOutputStyle: new FormControl(null), enableMultipleEquityColumns: new FormControl(null), numberOfRecentFilesToDisplay: new FormControl(null), diff --git a/gui-js/libs/shared/src/lib/backend/minsky.ts b/gui-js/libs/shared/src/lib/backend/minsky.ts index 3eb3d7e06..3eece4cde 100644 --- a/gui-js/libs/shared/src/lib/backend/minsky.ts +++ b/gui-js/libs/shared/src/lib/backend/minsky.ts @@ -743,6 +743,7 @@ export class GodleyIcon extends Item { async currency(...args: string[]): Promise {return this.$callMethod('currency',...args);} async deleteRow(a1: number): Promise {return this.$callMethod('deleteRow',a1);} async destroyFrame(): Promise {return this.$callMethod('destroyFrame');} + async displayValues(...args: boolean[]): Promise {return this.$callMethod('displayValues',...args);} async draw(a1: ICairoShim): Promise {return this.$callMethod('draw',a1);} async editorMode(): Promise {return this.$callMethod('editorMode');} async flowSignature(a1: number): Promise {return this.$callMethod('flowSignature',a1);} @@ -771,6 +772,7 @@ export class GodleyIcon extends Item { async toEditorX(a1: number): Promise {return this.$callMethod('toEditorX',a1);} async toEditorY(a1: number): Promise {return this.$callMethod('toEditorY',a1);} async toggleButtons(): Promise {return this.$callMethod('toggleButtons');} + async toggleDisplayValues(): Promise {return this.$callMethod('toggleDisplayValues');} async toggleEditorMode(): Promise {return this.$callMethod('toggleEditorMode');} async toggleVariableDisplay(): Promise {return this.$callMethod('toggleVariableDisplay');} async update(): Promise {return this.$callMethod('update');} @@ -1368,7 +1370,6 @@ export class Minsky extends CppClass { async dimensionalAnalysis(): Promise {return this.$callMethod('dimensionalAnalysis');} async displayErrorItem(a1: Item): Promise {return this.$callMethod('displayErrorItem',a1);} async displayStyle(...args: string[]): Promise {return this.$callMethod('displayStyle',...args);} - async displayValues(...args: boolean[]): Promise {return this.$callMethod('displayValues',...args);} async doPushHistory(...args: boolean[]): Promise {return this.$callMethod('doPushHistory',...args);} async ecolabVersion(): Promise {return this.$callMethod('ecolabVersion');} async edited(): Promise {return this.$callMethod('edited');} @@ -1454,7 +1455,6 @@ export class Minsky extends CppClass { async setAutoSaveFile(a1: string): Promise {return this.$callMethod('setAutoSaveFile',a1);} async setBusyCursor(): Promise {return this.$callMethod('setBusyCursor');} async setDefinition(a1: string,a2: string): Promise {return this.$callMethod('setDefinition',a1,a2);} - async setGodleyDisplayValue(a1: boolean,a2: string): Promise {return this.$callMethod('setGodleyDisplayValue',a1,a2);} async setGodleyIconResource(a1: string): Promise {return this.$callMethod('setGodleyIconResource',a1);} async setGroupIconResource(a1: string): Promise {return this.$callMethod('setGroupIconResource',a1);} async setLockIconResource(a1: string,a2: string): Promise {return this.$callMethod('setLockIconResource',a1,a2);} diff --git a/model/godleyIcon.h b/model/godleyIcon.h index dc8d7c761..69e52604a 100644 --- a/model/godleyIcon.h +++ b/model/godleyIcon.h @@ -82,8 +82,13 @@ namespace minsky GodleyTableEditor editor{*this}; /// for rendering the popup window GodleyTableWindow popup{*this}; - void adjustPopupWidgets() {popup.adjustWidgets();} + + /// whether to display values in this table + bool displayValues=false; + void toggleDisplayValues() {displayValues=!displayValues;} + void adjustPopupWidgets() {popup.adjustWidgets();} + /// scale icon until it's height or width matches \a h or \a w depending on which is minimum void scaleIcon(float w, float h); diff --git a/model/godleyTableWindow.cc b/model/godleyTableWindow.cc index 84274bd72..f726ede34 100644 --- a/model/godleyTableWindow.cc +++ b/model/godleyTableWindow.cc @@ -233,7 +233,7 @@ namespace minsky { string value; FlowCoef fc(text); - if (cminsky().displayValues && col!=0) // Do not add value "= 0.0" to first column. For tickets 1064/1274 + if (m_godleyIcon.displayValues && col!=0) // Do not add value "= 0.0" to first column. For tickets 1064/1274 try { auto vv=cminsky().variableValues @@ -280,7 +280,7 @@ namespace minsky } else //Display values of parameters used as initial conditions in Godley tables. for ticket 1126. - if (m_godleyIcon.table.initialConditionRow(row) && cminsky().displayValues) text=defang(text+=value); + if (m_godleyIcon.table.initialConditionRow(row) && m_godleyIcon.displayValues) text=defang(text+=value); else text=defang(text); } pango.setMarkup(text); diff --git a/model/godleyTableWindow.h b/model/godleyTableWindow.h index caf0367de..388dcf960 100644 --- a/model/godleyTableWindow.h +++ b/model/godleyTableWindow.h @@ -94,6 +94,9 @@ namespace minsky /// minimum column width (for eg empty columns) static constexpr double minColumnWidth=4*ButtonWidget::buttonSpacing; + // note explicit getter/setter here rather than public member to + // avoid an infinite recursion when running RESTProcess on this + // object GodleyIcon& godleyIcon() {return m_godleyIcon;} const GodleyIcon& godleyIcon() const {return m_godleyIcon;} diff --git a/model/minsky.cc b/model/minsky.cc index 76afc2e3b..9e2edd1b6 100644 --- a/model/minsky.cc +++ b/model/minsky.cc @@ -1597,17 +1597,17 @@ namespace minsky }); } - void Minsky::setGodleyDisplayValue(bool displayValues, GodleyTable::DisplayStyle displayStyle) - { - this->displayValues=displayValues; - this->displayStyle=displayStyle; - canvas.requestRedraw(); - model->recursiveDo(&GroupItems::items, [](Items&,Items::iterator i) { - if (auto g=dynamic_cast(i->get())) - g->popup.requestRedraw(); - return false; - }); - } +// void Minsky::setGodleyDisplayValue(bool displayValues, GodleyTable::DisplayStyle displayStyle) +// { +// this->displayValues=displayValues; +// this->displayStyle=displayStyle; +// canvas.requestRedraw(); +// model->recursiveDo(&GroupItems::items, [](Items&,Items::iterator i) { +// if (auto g=dynamic_cast(i->get())) +// g->popup.requestRedraw(); +// return false; +// }); +// } void Minsky::importVensim(const string& filename) { diff --git a/model/minsky.h b/model/minsky.h index af2bb0f01..36d88a835 100644 --- a/model/minsky.h +++ b/model/minsky.h @@ -424,11 +424,10 @@ namespace minsky void srand(int seed) {::srand(seed);} // godley table display values preferences - bool displayValues=false; GodleyTable::DisplayStyle displayStyle=GodleyTable::sign; /// set display value mode on all godley table editor modes - void setGodleyDisplayValue(bool displayValues, GodleyTable::DisplayStyle displayStyle); + //void setGodleyDisplayValue(bool displayValues, GodleyTable::DisplayStyle displayStyle); /// import a Vensim file void importVensim(const std::string&); diff --git a/schema/schema3.cc b/schema/schema3.cc index f3dc0660d..669d85129 100644 --- a/schema/schema3.cc +++ b/schema/schema3.cc @@ -577,6 +577,8 @@ namespace schema3 SchemaHelper::setVariableDisplay(*x1, *y.variableDisplay); if (y.buttonDisplay && *y.buttonDisplay!=x1->buttonDisplay()) x1->toggleButtons(); + if (y.displayValues && *y.displayValues!=x1->displayValues) + x1->toggleDisplayValues(); if (y.currency) x1->currency=*y.currency; } if (auto* x1=dynamic_cast(&x)) diff --git a/schema/schema3.h b/schema/schema3.h index be988b6e3..dcfd2eaaa 100644 --- a/schema/schema3.h +++ b/schema/schema3.h @@ -125,7 +125,7 @@ namespace schema3 // Godley Icon specific fields Optional>> data; Optional> assetClasses; - Optional editorMode, buttonDisplay, variableDisplay; + Optional editorMode, buttonDisplay, variableDisplay, displayValues; Optional currency; // sheet specific fields Optional showSlice; // slicing rows @@ -160,7 +160,8 @@ namespace schema3 ItemBase(id,static_cast(g),ports), data(g.table.getData()), assetClasses(g.table.assetClass()), editorMode(g.editorMode()), buttonDisplay(g.buttonDisplay()), - variableDisplay(g.variableDisplay()), currency(g.currency) + variableDisplay(g.variableDisplay()), displayValues(g.displayValues), + currency(g.currency) {name=g.table.title;} Item(int id, const minsky::PlotWidget& p, const std::vector& ports): ItemBase(id,static_cast(p),ports), From 552b98587c47b0f360aaa36dbe80a18db0b6dd64 Mon Sep 17 00:00:00 2001 From: Russell Standish Date: Fri, 29 May 2026 14:28:35 +1000 Subject: [PATCH 2/4] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- .../apps/minsky-electron/src/app/managers/ContextMenuManager.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gui-js/apps/minsky-electron/src/app/managers/ContextMenuManager.ts b/gui-js/apps/minsky-electron/src/app/managers/ContextMenuManager.ts index db9478907..8750ed666 100644 --- a/gui-js/apps/minsky-electron/src/app/managers/ContextMenuManager.ts +++ b/gui-js/apps/minsky-electron/src/app/managers/ContextMenuManager.ts @@ -690,7 +690,7 @@ export class ContextMenuManager { new MenuItem({ label: 'Display values', type: 'checkbox', - checked: await godley.displayValues(), + checked: await godley.displayValues(), click: async () => { await godley.toggleDisplayValues(); await minsky.canvas.requestRedraw(); From bcb078902cfb82ab85ce64e89aaef6643563db60 Mon Sep 17 00:00:00 2001 From: Russell Standish Date: Fri, 29 May 2026 15:03:27 +1000 Subject: [PATCH 3/4] chore: remove useless unit test --- test/testMinsky.cc | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/test/testMinsky.cc b/test/testMinsky.cc index d8b0430a8..5e8aa0551 100644 --- a/test/testMinsky.cc +++ b/test/testMinsky.cc @@ -1628,21 +1628,6 @@ TEST(TensorOps, evalOpEvaluate) EXPECT_TRUE(variableValues[":unitVar"]->units.str().empty()); } - // Test setGodleyDisplayValue - TEST_F(MinskySuite, setGodleyDisplayValue) - { - auto g1 = new GodleyIcon; - model->addItem(g1); - - setGodleyDisplayValue(true, GodleyTable::DRCR); - EXPECT_TRUE(displayValues); - EXPECT_EQ(GodleyTable::DRCR, displayStyle); - - setGodleyDisplayValue(false, GodleyTable::sign); - EXPECT_FALSE(displayValues); - EXPECT_EQ(GodleyTable::sign, displayStyle); - } - // Test save and load TEST_F(MinskySuite, saveAndLoad) { From cbbd7b72100ea3315934ed81d6d7d169f53bfd12 Mon Sep 17 00:00:00 2001 From: Russell Standish Date: Fri, 29 May 2026 15:30:09 +1000 Subject: [PATCH 4/4] bigfix: Fix failing regression test --- .../minsky-electron/src/app/managers/StoreManager.ts | 2 -- model/minsky.cc | 12 ------------ model/minsky.h | 3 --- test/00/godleyTableWindow.sh | 4 ++-- 4 files changed, 2 insertions(+), 19 deletions(-) diff --git a/gui-js/apps/minsky-electron/src/app/managers/StoreManager.ts b/gui-js/apps/minsky-electron/src/app/managers/StoreManager.ts index f682ba05a..f3aa3baec 100644 --- a/gui-js/apps/minsky-electron/src/app/managers/StoreManager.ts +++ b/gui-js/apps/minsky-electron/src/app/managers/StoreManager.ts @@ -3,7 +3,6 @@ import Store from 'electron-store'; import {homedir} from 'node:os'; interface MinskyPreferences { -// godleyTableShowValues: boolean; godleyTableOutputStyle: string; enableMultipleEquityColumns: boolean; numberOfRecentFilesToDisplay: number; @@ -31,7 +30,6 @@ class StoreManager { defaultModelDirectory: homedir(), defaultDataDirectory: homedir(), preferences: { - // godleyTableShowValues: false, godleyTableOutputStyle: 'sign', enableMultipleEquityColumns: false, numberOfRecentFilesToDisplay: 10, diff --git a/model/minsky.cc b/model/minsky.cc index 9e2edd1b6..c101c7ee2 100644 --- a/model/minsky.cc +++ b/model/minsky.cc @@ -1597,18 +1597,6 @@ namespace minsky }); } -// void Minsky::setGodleyDisplayValue(bool displayValues, GodleyTable::DisplayStyle displayStyle) -// { -// this->displayValues=displayValues; -// this->displayStyle=displayStyle; -// canvas.requestRedraw(); -// model->recursiveDo(&GroupItems::items, [](Items&,Items::iterator i) { -// if (auto g=dynamic_cast(i->get())) -// g->popup.requestRedraw(); -// return false; -// }); -// } - void Minsky::importVensim(const string& filename) { ifstream f(filename); diff --git a/model/minsky.h b/model/minsky.h index 36d88a835..e1c3cd97a 100644 --- a/model/minsky.h +++ b/model/minsky.h @@ -426,9 +426,6 @@ namespace minsky // godley table display values preferences GodleyTable::DisplayStyle displayStyle=GodleyTable::sign; - /// set display value mode on all godley table editor modes - //void setGodleyDisplayValue(bool displayValues, GodleyTable::DisplayStyle displayStyle); - /// import a Vensim file void importVensim(const std::string&); diff --git a/test/00/godleyTableWindow.sh b/test/00/godleyTableWindow.sh index caf70f922..f47f644a0 100755 --- a/test/00/godleyTableWindow.sh +++ b/test/00/godleyTableWindow.sh @@ -10,8 +10,8 @@ minsky.defaultFont('Sans') minsky.load('$here/examples/1Free.mky') minsky.multipleEquities(True) minsky.displayStyle('sign') -minsky.displayValues(True) item=findObject('GodleyIcon') +item.displayValues(True) gw=item.popup gw.enableButtons() gw.renderToSVG('1FreeBase.svg') @@ -34,7 +34,7 @@ gw.renderToSVG('1FreeSelectedCol.svg') minsky.load('$here/examples/LoanableFunds.mky') item=findObject('GodleyIcon') minsky.displayStyle('DRCR') -minsky.displayValues(0) +item.displayValues(False) item.popup.enableButtons() item.popup.renderToSVG('LoanableFundsBase.svg') EOF