From cbc823aba10fd9efa8317b7e9e8b744b6fbb6be0 Mon Sep 17 00:00:00 2001 From: Craig Everett Date: Wed, 16 Apr 2025 16:03:09 +0900 Subject: [PATCH] args (#10) More complete types. Reviewed-on: https://git.qpq.swiss/QPQ-AG/GajuDesk/pulls/10 Co-authored-by: Craig Everett Co-committed-by: Craig Everett --- src/gd_con.erl | 16 ++- src/gd_gui.erl | 4 +- src/gd_v_devman.erl | 273 ++++++++++++++++++++++++++++++-------------- zomp.meta | 6 +- 4 files changed, 205 insertions(+), 94 deletions(-) diff --git a/src/gd_con.erl b/src/gd_con.erl index 57ade09..6366d3f 100644 --- a/src/gd_con.erl +++ b/src/gd_con.erl @@ -486,11 +486,15 @@ code_change(_, State, _) -> {ok, State}. -terminate(normal, _) -> - zx:stop(); -terminate(Reason, State) -> - ok = log(info, "Reason: ~tp, State: ~tp", [Reason, State]), - zx:stop(). +terminate(Reason, _) -> + ok = log(info, "Reason: ~p,", [Reason]), + case whereis(gmc_con) of + undefined -> + zx:stop(); + PID -> + ok = log(info, "gd_con found at: ~p", [PID]), + application:stop(gajumine) + end. @@ -882,7 +886,7 @@ do_recover_key(Mnemonic, State) -> do_recover_key2(Seed, State = #s{wallet = Current, wallets = Wallets, pass = Pass}) -> #wallet{name = WalletName, keys = Keys, poas = POAs} = Current, - Recovered = #key{id = ID, name = AccName} = hz_key_master:make_key("", Seed), + Recovered = #key{id = ID, name = AccName} = hz_key_master:make_key(Seed), case lists:keymember(ID, #key.id, Keys) of false -> NewKeys = [Recovered | Keys], diff --git a/src/gd_gui.erl b/src/gd_gui.erl index 10d1261..c267d36 100644 --- a/src/gd_gui.erl +++ b/src/gd_gui.erl @@ -32,7 +32,7 @@ {wx = none :: none | wx:wx_object(), frame = none :: none | wx:wx_object(), sizer = none :: none | wx:wx_object(), - lang = en :: en | jp, + lang = en_US :: en_US | ja_JP, j = none :: none | fun(), prefs = #{} :: #{atom() := term()}, accounts = [] :: [gajudesk:poa()], @@ -84,7 +84,7 @@ start_link(Accounts) -> init(Prefs) -> ok = log(info, "GUI starting..."), - Lang = maps:get(lang, Prefs, en_us), + Lang = maps:get(lang, Prefs, en_US), Trans = gd_jt:read_translations(?MODULE), J = gd_jt:j(Lang, Trans), diff --git a/src/gd_v_devman.erl b/src/gd_v_devman.erl index def3093..da81c73 100644 --- a/src/gd_v_devman.erl +++ b/src/gd_v_devman.erl @@ -429,12 +429,11 @@ call_params([{L, C} | T], A) -> clicked4(State, #c{id = ConID, build = #{aci := ACI}, funs = {_, Funs}}, {Name, Type}, - {PK, Nonce, TTL, GasP, Gas, Amount}) -> + {PK, Nonce, TTL, GasP, Gas, Amt}) -> AACI = hz:prepare_aaci(ACI), - #f{args = ArgFields} = lists:keyfind(Name, #f.name, Funs), + #f{args = ArgFields} = maps:get(Name, Funs), Args = lists:map(fun get_arg/1, ArgFields), - FunName = binary_to_list(Name), - case hz:contract_call(PK, Nonce, Gas, GasP, Amount, TTL, AACI, ConID, FunName, Args) of + case hz:contract_call(PK, Nonce, Gas, GasP, Amt, TTL, AACI, ConID, Name, Args) of {ok, UnsignedTX} -> case Type of call -> do_call(State, ConID, PK, UnsignedTX); @@ -599,33 +598,39 @@ deploy2(State, Source) -> case compile(Source) of % Options = sophia_options(), % case so_compiler:from_string(Source, Options) of +% TODO: Make hz accept either the aaci or the aci, preferring the aaci if present {ok, Build} -> - deploy3(State, Build); + ACI = maps:get(aci, Build), + RawAACI = {aaci, ContractName, Funs, NS} = hz:prepare_aaci(ACI), + {InitSpec, Callable} = maps:take("init", Funs), + AACI = setelement(3, RawAACI, Callable), + Complete = maps:put(aaci, AACI, Build), + ok = tell(info, "Deploying Contract: ~p", [ContractName]), + deploy3(State, InitSpec, Complete, NS); Other -> ok = tell(info, "Compilation Failed!~n~tp", [Other]), State end. -deploy3(State, Build) -> +deploy3(State, InitSpec, Build, NS) -> case gd_con:list_keys() of {ok, 0, []} -> handle_troubling(State, "No keys exist in the current wallet."); {ok, Selected, Keys} -> - deploy4(State, Build, Selected, Keys); + deploy4(State, InitSpec, Build, NS, Selected, Keys); error -> handle_troubling(State, "No wallet is selected!") end. -deploy4(State = #s{frame = Frame, j = J}, Build = #{aci := ACI}, Selected, Keys) -> - {#{functions := Funs}, _} = find_main(ACI), - #{arguments := As} = lom:find(name, <<"init">>, Funs), +deploy4(State = #s{frame = Frame, j = J}, InitSpec, Build, NS, Selected, Keys) -> + InitArgs = element(1, InitSpec), Dialog = wxDialog:new(Frame, ?wxID_ANY, J("Deploy Contract")), Sizer = wxBoxSizer:new(?wxVERTICAL), ScrollWin = wxScrolledWindow:new(Dialog), ScrollSz = wxBoxSizer:new(?wxVERTICAL), ok = wxScrolledWindow:setSizerAndFit(ScrollWin, ScrollSz), ok = wxScrolledWindow:setScrollRate(ScrollWin, 5, 5), - FunName = unicode:characters_to_list(["init/", integer_to_list(length(As))]), + FunName = unicode:characters_to_list(["init/", integer_to_list(length(InitArgs))]), FunSz = wxStaticBoxSizer:new(?wxVERTICAL, ScrollWin, [{label, FunName}]), KeySz = wxStaticBoxSizer:new(?wxVERTICAL, ScrollWin, [{label, J("Signature Key")}]), KeyPicker = wxChoice:new(ScrollWin, ?wxID_ANY, [{choices, Keys}]), @@ -640,24 +645,7 @@ deploy4(State = #s{frame = Frame, j = J}, Build = #{aci := ACI}, Selected, Keys) GridSz = wxFlexGridSizer:new(2, 4, 4), ok = wxFlexGridSizer:setFlexibleDirection(GridSz, ?wxHORIZONTAL), ok = wxFlexGridSizer:addGrowableCol(GridSz, 1), - MakeArgField = - fun(#{name := AN, type := T}) -> - Type = - case T of - <<"address">> -> address; - <<"int">> -> integer; - <<"bool">> -> boolean; - L when is_list(L) -> list; % FIXME -% I when is_binary(I) -> iface % FIXME - I when is_binary(I) -> address % FIXME - end, - ANT = wxStaticText:new(ScrollWin, ?wxID_ANY, AN), - TCT = wxTextCtrl:new(ScrollWin, ?wxID_ANY), - _ = wxFlexGridSizer:add(GridSz, ANT, zxw:flags(base)), - _ = wxFlexGridSizer:add(GridSz, TCT, zxw:flags(wide)), - {ANT, TCT, Type} - end, - ArgFields = lists:map(MakeArgField, As), + ArgFields = make_arg_fields(ScrollWin, GridSz, InitArgs, NS, J), _ = wxStaticBoxSizer:add(FunSz, GridSz, zxw:flags(wide)), _ = wxStaticBoxSizer:add(ScrollSz, FunSz, [{proportion, 1}, {flag, ?wxEXPAND}]), _ = wxStaticBoxSizer:add(ScrollSz, KeySz, [{proportion, 0}, {flag, ?wxEXPAND}]), @@ -673,7 +661,7 @@ deploy4(State = #s{frame = Frame, j = J}, Build = #{aci := ACI}, Selected, Keys) ?wxID_OK -> ID = wxChoice:getString(KeyPicker, wxChoice:getSelection(KeyPicker)), PK = unicode:characters_to_binary(ID), - InitArgs = lists:map(fun get_arg/1, ArgFields), + IArgs = lists:map(fun get_arg/1, ArgFields), Controls = [{"TTL", TTL_Tx}, {"Gas Price", GasP_Tx}, @@ -683,7 +671,7 @@ deploy4(State = #s{frame = Frame, j = J}, Build = #{aci := ACI}, Selected, Keys) {ok, [TTL, GasP, Gas, Amount]} -> {ok, Nonce} = hz:next_nonce(PK), DeployParams = {PK, Nonce, TTL, GasP, Gas, Amount}, - {ok, DeployParams, InitArgs}; + {ok, DeployParams, IArgs}; E -> E end; @@ -849,9 +837,9 @@ open_hash3(State, Address, Source) -> % TODO: Compile on load and verify the deployed hash for validity. Options = sophia_options(), case so_compiler:from_string(Source, Options) of - {ok, Build = #{aci := ACI}} -> - {Defs = #{functions := Funs}, ConIfaces} = find_main(ACI), - Callable = lom:delete(name, <<"init">>, Funs), + {ok, Build = #{aaci := AACI}} -> + {Defs = #{functions := Funs}, ConIfaces} = find_main(AACI), + Callable = maps:remove("init", Funs), FunDefs = {maps:put(functions, Callable, Defs), ConIfaces}, ok = tell(info, "Compilation Succeeded!~n~tp~n~n~tp", [Build, FunDefs]), add_code_page(State, {hash, Address}, Source); @@ -1118,12 +1106,16 @@ load3(State = #s{tabs = TopBook, cons = {Consbook, Pages}, buttons = Buttons, j _ = wxSizer:add(PageSz, ConsSz, [{proportion, 1}, {flag, ?wxEXPAND}]), {Out, IFaces, Build, NewButtons} = case compile(Source) of - {ok, B = #{aci := ACI}} -> - {#{functions := Fs}, _} = find_main(ACI), - Callable = lom:delete(name, <<"init">>, Fs), - {NB, IFs} = fun_interfaces(ScrollWin, FunSz, Buttons, Callable, J), - O = io_lib:format("Compilation Succeeded!~n~tp~n~nDone!~n", [B]), - {O, IFs, B, NB}; + {ok, Output} -> + ACI = maps:get(aci, Output), + AACI = {aaci, ContractName, Funs, NS} = hz:prepare_aaci(ACI), + Complete = maps:put(aaci, AACI, Output), + ok = tell(info, "Loading Contract: ~p", [ContractName]), + Callable = maps:remove("init", Funs), + tell(info, "Callable: ~p", [Callable]), + {NB, IFs} = fun_interfaces(ScrollWin, FunSz, Buttons, Callable, NS, J), + O = io_lib:format("Compilation Succeeded!~n~tp~n~nDone!~n", [Complete]), + {O, IFs, Complete, NB}; Other -> O = io_lib:format("Compilation Failed!~n~tp~n", [Other]), {O, [], none, Buttons} @@ -1141,9 +1133,18 @@ load3(State = #s{tabs = TopBook, cons = {Consbook, Pages}, buttons = Buttons, j State#s{cons = {Consbook, NewPages}, buttons = NewButtons}. -get_arg({_, TextCtrl, _}) -> +get_arg({list, AFs, _}) -> + lists:map(fun get_arg/1, AFs); +get_arg({record, AFs}) -> + get_record(AFs); +get_arg({tuple, AFs}) -> + list_to_tuple(lists:map(fun get_arg/1, AFs)); +get_arg({_, TextCtrl}) -> wxTextCtrl:getValue(TextCtrl). +get_record([{L, A} | T]) -> + [{L, get_arg(A)} | get_record(T)]. + find_main(ACI) -> find_main(ACI, none, []). @@ -1159,60 +1160,166 @@ find_main([C | T], M, Is) -> find_main([], M, Is) -> {M, Is}. -fun_interfaces(ScrollWin, FunSz, Buttons, Funs, J) -> +fun_interfaces(ScrollWin, FunSz, Buttons, Funs, NS, J) -> MakeIface = - fun(#{name := N, arguments := As}) -> - FunName = unicode:characters_to_list([N, "/", integer_to_list(length(As))]), + fun(Name, {Args, _}) -> + tell(info, "Fun: ~p, Args: ~p", [Name, Args]), + FunName = unicode:characters_to_list([Name, "/", integer_to_list(length(Args))]), FN = wxStaticBoxSizer:new(?wxVERTICAL, ScrollWin, [{label, FunName}]), GridSz = wxFlexGridSizer:new(2, 4, 4), ok = wxFlexGridSizer:setFlexibleDirection(GridSz, ?wxHORIZONTAL), ok = wxFlexGridSizer:addGrowableCol(GridSz, 1), - MakeArgField = - fun(#{name := AN, type := T}) -> - Type = - case T of - <<"address">> -> address; - <<"int">> -> integer; - <<"bool">> -> boolean; - L when is_list(L) -> list; % FIXME -% I when is_binary(I) -> iface % FIXME - I when is_binary(I) -> address % FIXME - end, - ANT = wxStaticText:new(ScrollWin, ?wxID_ANY, AN), - TCT = wxTextCtrl:new(ScrollWin, ?wxID_ANY), - _ = wxFlexGridSizer:add(GridSz, ANT, zxw:flags(base)), - _ = wxFlexGridSizer:add(GridSz, TCT, zxw:flags(wide)), - {ANT, TCT, Type} - end, - ArgFields = lists:map(MakeArgField, As), + ArgFields = make_arg_fields(ScrollWin, GridSz, Args, NS, J), ButtSz = wxBoxSizer:new(?wxHORIZONTAL), - {CallButton, DryRunButton} = - case N =:= <<"init">> of - false -> - CallBn = wxButton:new(ScrollWin, ?wxID_ANY, [{label, J("Call")}]), - DryRBn = wxButton:new(ScrollWin, ?wxID_ANY, [{label, J("Dry Run")}]), - _ = wxBoxSizer:add(ButtSz, CallBn, zxw:flags(wide)), - _ = wxBoxSizer:add(ButtSz, DryRBn, zxw:flags(wide)), - {#w{name = {N, call}, id = wxButton:getId(CallBn), wx = CallBn}, - #w{name = {N, dryr}, id = wxButton:getId(DryRBn), wx = DryRBn}}; - true -> - Deploy = wxButton:new(ScrollWin, ?wxID_ANY, [{label, J("Deploy")}]), - _ = wxBoxSizer:add(ButtSz, Deploy, zxw:flags(wide)), - {#w{name = {N, call}, id = wxButton:getId(Deploy), wx = Deploy}, - none} - end, + CallBn = wxButton:new(ScrollWin, ?wxID_ANY, [{label, J("Call")}]), + DryRBn = wxButton:new(ScrollWin, ?wxID_ANY, [{label, J("Dry Run")}]), + _ = wxBoxSizer:add(ButtSz, CallBn, zxw:flags(wide)), + _ = wxBoxSizer:add(ButtSz, DryRBn, zxw:flags(wide)), + CallButton = #w{name = {Name, call}, id = wxButton:getId(CallBn), wx = CallBn}, + DryRButton = #w{name = {Name, dryr}, id = wxButton:getId(DryRBn), wx = DryRBn}, _ = wxStaticBoxSizer:add(FN, GridSz, zxw:flags(wide)), _ = wxStaticBoxSizer:add(FN, ButtSz, zxw:flags(base)), _ = wxSizer:add(FunSz, FN, zxw:flags(base)), - #f{name = N, call = CallButton, dryrun = DryRunButton, args = ArgFields} + #f{name = Name, call = CallButton, dryrun = DryRButton, args = ArgFields} end, - IFaces = lists:map(MakeIface, Funs), - NewButtons = lists:foldl(fun map_iface_buttons/2, Buttons, IFaces), + IFaces = maps:map(MakeIface, Funs), + tell(info, "IFaces: ~p", [IFaces]), + NewButtons = maps:fold(fun map_iface_buttons/3, Buttons, IFaces), {NewButtons, IFaces}. -map_iface_buttons(#f{call = C = #w{id = CID}, dryrun = D = #w{id = DID}}, A) -> - maps:put(DID, D, maps:put(CID, C, A)); -map_iface_buttons(#f{call = C = #w{id = CID}, dryrun = none}, A) -> +% FIXME: This can be simplified and needs to provide better widgets for types. +% "variant" types should be wxChoice +% Booleans should either be wxChoice or check boxes +% The sizer expansion direction for vertical elements is stupid +make_arg_fields(ScrollWin, GridSz, Args, NS, J) -> + MakeArgField = + fun + ({AN, {T, already_normalized, T}}) -> +% tell(info, "~p Arg: ~p, Type: ~p", [?LINE, AN, T]), + ANT = wxStaticText:new(ScrollWin, ?wxID_ANY, AN), + TCT = wxTextCtrl:new(ScrollWin, ?wxID_ANY), + _ = wxFlexGridSizer:add(GridSz, ANT, fill()), + _ = wxFlexGridSizer:add(GridSz, TCT, fill()), + {T, TCT}; + ({T, already_normalized, T}) -> +% tell(info, "~p Type: ~p", [?LINE, T]), + ANT = wxStaticText:new(ScrollWin, ?wxID_ANY, atom_to_list(T)), + TCT = wxTextCtrl:new(ScrollWin, ?wxID_ANY), + _ = wxFlexGridSizer:add(GridSz, ANT, fill()), + _ = wxFlexGridSizer:add(GridSz, TCT, fill()), + {T, TCT}; + ({AN, {_TypeName, T, T}}) -> +% tell(info, "~p Arg: ~p, ~p: ~p", [?LINE, AN, TypeName, T]), + ANT = wxStaticText:new(ScrollWin, ?wxID_ANY, AN), + TCT = wxTextCtrl:new(ScrollWin, ?wxID_ANY), + _ = wxFlexGridSizer:add(GridSz, ANT, fill()), + _ = wxFlexGridSizer:add(GridSz, TCT, fill()), + {T, TCT}; + ({AN, {_TypeName, already_normalized, {record, InnerArgs}}}) -> +% tell(info, "~p Arg: ~p, ~p: ~p", [?LINE, AN, TypeName, InnerArgs]), + ANT = wxStaticText:new(ScrollWin, ?wxID_ANY, AN), + InnerSz = wxFlexGridSizer:new(2, 4, 4), + ok = wxFlexGridSizer:setFlexibleDirection(InnerSz, ?wxHORIZONTAL), + ok = wxFlexGridSizer:addGrowableCol(InnerSz, 1), + AFs = make_arg_fields(ScrollWin, InnerSz, InnerArgs, NS, J), + _ = wxFlexGridSizer:add(GridSz, ANT, fill()), + _ = wxFlexGridSizer:add(GridSz, InnerSz, fill()), + {record, AFs}; + ({AN, {_TypeName, already_normalized, {tuple, InnerArgs}}}) -> +% tell(info, "~p Arg: ~p, ~p: ~p", [?LINE, AN, TypeName, InnerArgs]), + ANT = wxStaticText:new(ScrollWin, ?wxID_ANY, AN), + InnerSz = wxFlexGridSizer:new(2, 4, 4), + ok = wxFlexGridSizer:setFlexibleDirection(InnerSz, ?wxHORIZONTAL), + ok = wxFlexGridSizer:addGrowableCol(InnerSz, 1), + AFs = make_arg_fields(ScrollWin, InnerSz, InnerArgs, NS, J), + _ = wxFlexGridSizer:add(GridSz, ANT, fill()), + _ = wxFlexGridSizer:add(GridSz, InnerSz, fill()), + {tuple, AFs}; + ({AN, {_TypeName, already_normalized, {list, InnerArgs}}}) -> +% tell(info, "~p Arg: ~p, ~p: ~p", [?LINE, AN, TypeName, InnerArgs]), + ANT = wxStaticText:new(ScrollWin, ?wxID_ANY, AN), + ArgSz = wxBoxSizer:new(?wxVERTICAL), + InnerSz = wxFlexGridSizer:new(2, 4, 4), + ok = wxFlexGridSizer:setFlexibleDirection(InnerSz, ?wxHORIZONTAL), + ok = wxFlexGridSizer:addGrowableCol(InnerSz, 1), + AFs = make_arg_fields(ScrollWin, InnerSz, InnerArgs, NS, J), + B = wxButton:new(ScrollWin, ?wxID_ANY, [{label, J("Add")}]), + AB = #w{name = {AN, add}, id = wxButton:getId(B), wx = B}, + _ = wxBoxSizer:add(ArgSz, InnerSz, fill()), + _ = wxBoxSizer:add(ArgSz, B, fill()), + _ = wxFlexGridSizer:add(GridSz, ANT, fill()), + _ = wxFlexGridSizer:add(GridSz, ArgSz, fill()), + {list, AFs, AB}; + ({AN, {_TypeName, already_normalized, T}}) -> +% tell(info, "~p Arg: ~p, ~p: ~p", [?LINE, AN, TypeName, T]), + ANT = wxStaticText:new(ScrollWin, ?wxID_ANY, AN), + InnerSz = wxFlexGridSizer:new(2, 4, 4), + ok = wxFlexGridSizer:setFlexibleDirection(InnerSz, ?wxHORIZONTAL), + ok = wxFlexGridSizer:addGrowableCol(InnerSz, 1), + AFs = make_arg_fields(ScrollWin, InnerSz, T, NS, J), + _ = wxFlexGridSizer:add(GridSz, ANT, fill()), + _ = wxFlexGridSizer:add(GridSz, InnerSz, fill()), + {tuple, AFs}; + ({AN, {{tuple, _}, already_normalized, {tuple, InnerArgs}}}) -> +% tell(info, "~p Arg: ~p, Tuple: ~p", [?LINE, AN, InnerArgs]), + ANT = wxStaticText:new(ScrollWin, ?wxID_ANY, AN), + InnerSz = wxFlexGridSizer:new(2, 4, 4), + ok = wxFlexGridSizer:setFlexibleDirection(InnerSz, ?wxHORIZONTAL), + ok = wxFlexGridSizer:addGrowableCol(InnerSz, 1), + AFs = make_arg_fields(ScrollWin, InnerSz, InnerArgs, NS, J), + _ = wxFlexGridSizer:add(GridSz, ANT, fill()), + _ = wxFlexGridSizer:add(GridSz, InnerSz, fill()), + {tuple, AFs}; + ({AN, {{list, _}, already_normalized, {list, InnerArgs}}}) -> +% tell(info, "~p Arg: ~p, List: ~p", [?LINE, AN, InnerArgs]), + ANT = wxStaticText:new(ScrollWin, ?wxID_ANY, AN), + ArgSz = wxBoxSizer:new(?wxHORIZONTAL), + InnerSz = wxFlexGridSizer:new(2, 4, 4), + ok = wxFlexGridSizer:setFlexibleDirection(InnerSz, ?wxHORIZONTAL), + ok = wxFlexGridSizer:addGrowableCol(InnerSz, 1), + AFs = make_arg_fields(ScrollWin, InnerSz, InnerArgs, NS, J), + B = wxButton:new(ScrollWin, ?wxID_ANY, [{label, J("Add")}]), + AB = #w{name = {AN, add}, id = wxButton:getId(B), wx = B}, + _ = wxBoxSizer:add(ArgSz, InnerSz, fill()), + _ = wxBoxSizer:add(ArgSz, B, fill()), + _ = wxFlexGridSizer:add(GridSz, ANT, fill()), + _ = wxFlexGridSizer:add(GridSz, ArgSz, fill()), + {list, AFs, AB}; + ({{tuple, _}, already_normalized, {tuple, InnerArgs}}) -> +% tell(info, "~p Tuple: ~p", [?LINE, InnerArgs]), + ANT = wxStaticText:new(ScrollWin, ?wxID_ANY, "tuple"), + InnerSz = wxFlexGridSizer:new(2, 4, 4), + ok = wxFlexGridSizer:setFlexibleDirection(InnerSz, ?wxHORIZONTAL), + ok = wxFlexGridSizer:addGrowableCol(InnerSz, 1), + AFs = make_arg_fields(ScrollWin, InnerSz, InnerArgs, NS, J), + _ = wxFlexGridSizer:add(GridSz, ANT, fill()), + _ = wxFlexGridSizer:add(GridSz, InnerSz, fill()), + {tuple, AFs}; + ({{list, _}, already_normalized, {list, InnerArgs}}) -> +% tell(info, "~p List: ~p", [?LINE, InnerArgs]), + ANT = wxStaticText:new(ScrollWin, ?wxID_ANY, "list"), + ArgSz = wxBoxSizer:new(?wxHORIZONTAL), + InnerSz = wxFlexGridSizer:new(2, 4, 4), + ok = wxFlexGridSizer:setFlexibleDirection(InnerSz, ?wxHORIZONTAL), + ok = wxFlexGridSizer:addGrowableCol(InnerSz, 1), + AFs = make_arg_fields(ScrollWin, InnerSz, InnerArgs, NS, J), + B = wxButton:new(ScrollWin, ?wxID_ANY, [{label, J("Add")}]), + AB = #w{name = {list, add}, id = wxButton:getId(B), wx = B}, + _ = wxBoxSizer:add(ArgSz, InnerSz, [{proportion, 1}, {flag, ?wxEXPAND}]), + _ = wxBoxSizer:add(ArgSz, B, fill()), + _ = wxFlexGridSizer:add(GridSz, ANT, fill()), + _ = wxFlexGridSizer:add(GridSz, ArgSz, fill()), + {list, AFs, AB} + end, + lists:map(MakeArgField, Args). + +fill() -> + [{proportion, 0}, {flag, ?wxEXPAND}]. + + +map_iface_buttons(_, #f{call = C = #w{id = CID}, dryrun = D = #w{id = DID}}, A) -> + maps:merge(#{CID => C, DID => D}, A); +map_iface_buttons(_, #f{call = C = #w{id = CID}, dryrun = none}, A) -> maps:put(CID, C, A). diff --git a/zomp.meta b/zomp.meta index c253603..332101f 100644 --- a/zomp.meta +++ b/zomp.meta @@ -2,16 +2,16 @@ {type,gui}. {modules,[]}. {prefix,"gd"}. -{author,"Craig Everett"}. {desc,"A desktop client for the Gajumaru network of blockchain networks"}. +{author,"Craig Everett"}. {package_id,{"otpr","gajudesk",{0,5,4}}}. -{deps,[{"otpr","hakuzaru",{0,6,0}}, +{deps,[{"otpr","base58",{0,1,1}}, + {"otpr","hakuzaru",{0,6,0}}, {"otpr","gmserialization",{0,1,3}}, {"otpr","sophia",{9,0,0}}, {"otpr","gmbytecode",{3,4,1}}, {"otpr","lom",{1,0,0}}, {"otpr","zj",{1,1,0}}, - {"otpr","erl_base58",{0,1,0}}, {"otpr","eblake2",{1,0,0}}, {"otpr","ec_utils",{1,0,0}}, {"otpr","zxwidgets",{1,0,1}}]}.