%%--------------------------------------------------------------------- %% This is added as a test because it was giving a false positive %% (function move/4 will nevr be called) due to the strange use of %% self-recursive fun construction in placex/3. %% %% The analysis was getting confused that the foldl call will never %% terminate (due to a wrong hard-coded type for foldl) and inferred %% that the remaining calls in the body of placex/3 will not be %% reached. Fixed 11 March 2005. %%--------------------------------------------------------------------- -module(appmon_place). -export([place/2]). place(DG, Root) -> case appmon_dg:get(data, DG, Root) of false -> [0]; _Other -> placey(DG, Root, 1), placex(DG, Root, []) end. placey(DG, V, Y) -> appmon_dg:set(y, DG, V, Y), Y1 = Y+1, lists:foreach(fun(C) -> placey(DG, C, Y1) end, appmon_dg:get(out, DG, V)). placex(DG, V, LastX) -> Ch = appmon_dg:get(out, DG, V), ChLX = lists:foldl(fun(C, Accu) -> placex(DG, C, Accu) end, tll(LastX), Ch), Width = appmon_dg:get(w, DG, V), MyX = calc_mid(DG, Width, Ch), DeltaX = calc_delta(MyX, hdd(LastX)+20), appmon_dg:set(x, DG, V, MyX), move(DG, V, [MyX+Width | ChLX], DeltaX). move(_DG, _L, LastX, 0) -> LastX; move(DG, V, LastX, DeltaX) -> move2(DG, V, LastX, DeltaX). move2(DG, V, LastX, DeltaX) -> NewX = appmon_dg:get(x, DG, V)+DeltaX, appmon_dg:set(x, DG, V, NewX), ChLX = lists:foldl(fun(C, LX) -> move2(DG, C, LX, DeltaX) end, tll(LastX), appmon_dg:get(out, DG, V)), [max(NewX+appmon_dg:get(w, DG, V), hdd(LastX)) | ChLX]. max(A, B) when A>B -> A; max(_, B) -> B. calc_mid(_DG, _Width, []) -> 0; calc_mid(DG, Width, ChList) -> LeftMostX = appmon_dg:get(x, DG, hd(ChList)), Z2 = lists:last(ChList), RightMostX = appmon_dg:get(x, DG, Z2)+appmon_dg:get(w, DG, Z2), trunc((LeftMostX+RightMostX)/2)-trunc(Width/2). calc_delta(Mid, Right) -> if Right>Mid -> Right-Mid; true -> 0 end. %% Special head and tail %% Handles empty list in a non-standard way tll([]) -> []; tll([_|T]) -> T. hdd([]) -> 0; hdd([H|_]) -> H.